@juspay/neurolink 12.49.5 → 12.49.7

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.
@@ -2631,9 +2631,9 @@
2631
2631
  {"objectID":"b0a5b78dc4cfcabcd52b58ea94936ee81e97b59b5907f058ccba74881a7aeacd","title":"Context-window filtering","url":"/docs/features/classifier-router-catalog#context-window-filtering","content":"Nothing in routing read maxContextTokens before this. Two independent checks\nnow do:\nrankCatalogue() filters candidates whose contextWindow is below the\n request's estimated input tokens, applied only when it would leave something\n behind (an empty result falls back to the unfiltered pool rather than\n routing nowhere).\nThe classifier's own pick is separately vetoed. Even when jev picks a\n model directly, fitsRequest() checks whether that specific model's window\n can hold the request. If it can't, the pick is dropped regardless of\n confidence — this is a hard provider error, not a degraded answer, because\n an oversized request against a real model puts that model into ModelPool's\n permanent (10-year) cooldown. A wrong guess here is not \"less accurate,\" it\n is unrecoverable for the life of the process.","hierarchy":{"lvl0":"Features","lvl1":"The model catalogue","lvl2":"Context-window filtering","lvl3":""}},
2632
2632
  {"objectID":"e34966644db91aef39b46ef5c2f2fa259e9c828895197c9b2260a07c6e640bce","title":"What this is bad at","url":"/docs/features/classifier-router-catalog#what-this-is-bad-at","content":"Registry quality is coarse, and the catalogue path never shows its own\n work. Auto-enriched quality is a 3-bucket scale (high/medium/low)\n before buildModelCatalog() turns it into 1/2/3; two \"high\" models\n cannot be separated on capability alone. Worse for this page's topic: because\n the catalogue always populates cost/quality, its rendered line never\n shows the registry's own price, speed bucket, or \"strong at …\" scores — only\n the terse capability N / relative cost N form. Declare tiers/quality\n on a hand-declared pool member for finer control over the number itself; there\n is no way to get the richer rendering for a catalogue-sourced model.\nA catalogue candidate's \"relative cost\" is real pricing wearing a relative\n label. buildModelCatalog() seeds it from inputCostPer1K + outputCostPer1K\n — a small decimal like 0.00074 — not a small integer a host would typically\n pick for a hand-declared cost. The number is still correct and still never\n rendered as currency, but it does not compare cleanly against a hand-declared\n member's cost: 1 in the same pool, since one is a real price and the other\n is an arbitrary scale.\nUnknown-to-the-registry models rank on relative numbers, not real prices.\n A model the registry doesn't know (self-hosted, brand-new) keeps whatever\n cost/quality the host declared, compared only against other declared\n values on the same relative scale — never rendered as a dollar figure it\n isn't.\nA wide catalogue is still one choice question, and the cap is hard, not\n smart, when it does bind. Every model adds tokens to that single question;\n maxModels is the safeguard, and a model past it would simply never be\n offered rather than offered with lower priority. Today this is theoretical —\n the registry is 64 models against a default cap of 120, so nothing is\n dropped — but the mechanism has no ranking behavior for the day a registry\n does exceed it.\nPermissive reachability means occasional dead candidates.","hierarchy":{"lvl0":"Features","lvl1":"The model catalogue","lvl2":"What this is bad at","lvl3":""}},
2633
2633
  {"objectID":"2d7354001109ce1051977450cf365d1f2a8e13b345ad206ee23b1f5466228454","title":"See also","url":"/docs/features/classifier-router-catalog#see-also","content":"Classifier Router\nModel routing with a decision model\nThe decide inference type","hierarchy":{"lvl0":"Features","lvl1":"The model catalogue","lvl2":"See also","lvl3":""}},
2634
- {"objectID":"57703ab4e28ce3ad7f4c83d5d3e43f1b1d5541cbb2ac1d6f10f7a057046f0e1b","title":"Model routing with a decision model","url":"/docs/features/classifier-router-jev-strategy","content":"Model routing with a decision model\n\nThe classifier router has a jev strategy: one\ndecision-model round trip answers difficulty,\nrequired capabilities, risk and the model pick simultaneously, with a\ncalibrated confidence on each. This page is the strategy's own mechanics —\nclassifier-router.md covers the router as a whole.\n\nThe degradation contract. With no decision provider configured,\nresolveStrategy() resolves auto to heuristic, exactly as it always did.\nclassifyJev() itself never throws: any failure, timeout, or malformed answer\nfalls back to classifyHeuristic(). Configuring a decision provider (for example TYPESAFE_API_KEY or\nAI_GATEWAY_API_KEY) upgrades routing; it cannot make routing worse than before\nthe key existed. The same holds for PERPLEXITY_API_KEY, which is also the\nPerplexity text provider's key, and for CLOUDFLARE_API_KEY with\nCLOUDFLARE_ACCOUNT_ID, which are also the Cloudflare Workers AI text provider's\ntoken and account id. \"Configured\" counts the environment, the instance\ncredentials, and the request's own per-call credentials — a host that holds\nno decision key but passes a tenant's credentials: { laya } on a generate()\ncall routes that call with jev, and the decision goes to the tenant's account.\n\nWhat goes into the state\n\nclassifyJev() sends the request truncated to 8000 characters, plus four\nsignals the caller already has on hand:\n\nAlongside it, one batch asks: difficulty (a choice over the five tiers),\nneeds_vision / needs_tools / needs_reasoning (boolean), risky\n(boolean), context (a score — see\nper-request context budget), and, only when the\npool has more than one member, model (a choice over the pool, rendered by\nthe catalogue). All of this rides in\none request. On TypeSafe that takes ~400ms, because latency is flat in question\ncount; on Perplexity each further question adds about 65 ms, up to 128 (see\nits guide); on\nCloudflare Clef a small request took 0.3 to 1.0 s on 2026-10-03 (see\nits guide). See\nthe batching rule.\n\nThe Cloudflare Clef endpoint ignores state text past about 2,048 tokens, and\nNeuroLink refuses a state it estimates at more than 1,500 tokens with\nmax_tokens_exceeded. A long request is therefore refused there, and the\nheuristic classifier's tier stands, as it does on any failure.\n\nThe difficulty rubric\n\nFive tiers, ordered easiest to hardest, worded about the shape of the work —\nthe model is never told a provider or model name:\n\n| Tier | Criterion |\n| ---------- | ----------------------------------------------------------------------------------------------------------------------------------------------------- |\n| trivial | Mechanical and local: rename a symbol, fix a typo, add an import, run one named command, or answer something already stated. |\n| simple | A small localised change or a direct factual answer. One file, one obvious approach. |\n| moderate | Ordinary engineering: implement a well-specified change across a few files, write tests, fix a clearly described bug, review a small diff. |\n| hard | Deep reasoning: architecture and design, debugging a failure whose cause is unknown, security analysis, concurrency, cross-system refactors. |\n| expert | Frontier-level work: ambiguous requirements, novel design with no established pattern, or analysis where a wrong answer is costly and hard to detect. |\n\nAsymmetric confidence bars, and why they differ\n\nA verdict harder than the neutral tier (moderate) spends more if wrong; a\nverdict easier than neutral spends less if wrong. Those are not the same\nmistake:\nRouting a simple task to an expensive model wastes money. Cheap to be wrong\n about, so the bar to route up is low: minUpgradeConfidence defaults to\n 0.3.\nRouting a hard task to a weak model produces a wrong answer. Expensive to be\n wrong about, so the bar to route down is high: minDowngradeConfidence\n defaults to 0.6.\n\nBelow the applicable bar, the difficulty verdict is discarded and the heuristic\nclassifier's tier stands instead — not a downgraded jev answer, the ordinary\nzero-cost fallback.\n\nOne case skips both bars: a risky reading above 0.7 forces the tier to at\nleast hard, unconditionally. Risk can only ever raise the tier, never lower\none, and it is not itself gated by confidence.\n\nAsk about the act, not the subject\n\nThe risk question is not \"does this touch production, money, or credentials\":\n\nCarrying out this request would itself change production, move real money,\nexpose credentials, or alter data that cannot be restored. Writing or testing\ncode that deals with such things, without running it against the real system,\ndoes not count.\n\nThe naive phrasing was tried first and scored high on ordinary code that merely\nconcerns those things — \"add a refund endpoint that calls Stripe\" — which\n","hierarchy":{"lvl0":"Features","lvl1":"Model routing with a decision model","lvl2":"","lvl3":""}},
2634
+ {"objectID":"57703ab4e28ce3ad7f4c83d5d3e43f1b1d5541cbb2ac1d6f10f7a057046f0e1b","title":"Model routing with a decision model","url":"/docs/features/classifier-router-jev-strategy","content":"Model routing with a decision model\n\nThe classifier router has a jev strategy: one\ndecision-model round trip answers difficulty,\nrequired capabilities, risk and the model pick simultaneously, with a\ncalibrated confidence on each. This page is the strategy's own mechanics —\nclassifier-router.md covers the router as a whole.\n\nThe degradation contract. With no decision provider configured,\nresolveStrategy() resolves auto to heuristic, exactly as it always did.\nclassifyJev() itself never throws: any failure, timeout, or malformed answer\nfalls back to classifyHeuristic(). Configuring a decision provider (for example TYPESAFE_API_KEY or\nAI_GATEWAY_API_KEY) upgrades routing; it cannot make routing worse than before\nthe key existed. The same holds for PERPLEXITY_API_KEY, which is also the\nPerplexity text provider's key, and for CLOUDFLARE_API_KEY with\nCLOUDFLARE_ACCOUNT_ID, which are also the Cloudflare Workers AI text provider's\ntoken and account id. \"Configured\" counts the environment, the instance\ncredentials, and the request's own per-call credentials — a host that holds\nno decision key but passes a tenant's credentials: { laya } on a generate()\ncall routes that call with jev, and the decision goes to the tenant's account.\n\nWhat goes into the state\n\nclassifyJev() sends the request truncated to 8000 characters, plus four\nsignals the caller already has on hand:\n\nAlongside it, one batch asks: difficulty (a choice over the five tiers),\nneeds_vision / needs_tools / needs_reasoning (boolean), risky\n(boolean), context (a score — see\nper-request context budget), and, only when the\npool has more than one member, model (a choice over the pool, rendered by\nthe catalogue). All of this rides in\none request. On TypeSafe that takes ~400ms, because latency is flat in question\ncount; on Perplexity each further question adds about 65 ms, up to 128 (see\nits guide); on\nCloudflare Clef a small request took 0.3 to 1.0 s on 2026-10-03 (see\nits guide). See\nthe batching rule.\n\nNeuroLink refuses a state it estimates at more than 16,000 tokens (about 60,000\ncharacters of prose) with max_tokens_exceeded, to keep Clef inside what it was\nseen to read in full and inside a timeout a fail-open consumer can afford. A\nlonger request is refused there, and the heuristic classifier's tier stands, as it\ndoes on any failure.\n\nThe difficulty rubric\n\nFive tiers, ordered easiest to hardest, worded about the shape of the work —\nthe model is never told a provider or model name:\n\n| Tier | Criterion |\n| ---------- | ----------------------------------------------------------------------------------------------------------------------------------------------------- |\n| trivial | Mechanical and local: rename a symbol, fix a typo, add an import, run one named command, or answer something already stated. |\n| simple | A small localised change or a direct factual answer. One file, one obvious approach. |\n| moderate | Ordinary engineering: implement a well-specified change across a few files, write tests, fix a clearly described bug, review a small diff. |\n| hard | Deep reasoning: architecture and design, debugging a failure whose cause is unknown, security analysis, concurrency, cross-system refactors. |\n| expert | Frontier-level work: ambiguous requirements, novel design with no established pattern, or analysis where a wrong answer is costly and hard to detect. |\n\nAsymmetric confidence bars, and why they differ\n\nA verdict harder than the neutral tier (moderate) spends more if wrong; a\nverdict easier than neutral spends less if wrong. Those are not the same\nmistake:\nRouting a simple task to an expensive model wastes money. Cheap to be wrong\n about, so the bar to route up is low: minUpgradeConfidence defaults to\n 0.3.\nRouting a hard task to a weak model produces a wrong answer. Expensive to be\n wrong about, so the bar to route down is high: minDowngradeConfidence\n defaults to 0.6.\n\nBelow the applicable bar, the difficulty verdict is discarded and the heuristic\nclassifier's tier stands instead — not a downgraded jev answer, the ordinary\nzero-cost fallback.\n\nOne case skips both bars: a risky reading above 0.7 forces the tier to at\nleast hard, unconditionally. Risk can only ever raise the tier, never lower\none, and it is not itself gated by confidence.\n\nAsk about the act, not the subject\n\nThe risk question is not \"does this touch production, money, or credentials\":\n\nCarrying out this request would itself change production, move real money,\nexpose credentials, or alter data that cannot be restored. Writing or testing\ncode that deals with such things, without running it against the real system,\ndoes not count.\n\nThe naive phrasing was tried first and scored high on ordinary code that merely\nconcerns those t","hierarchy":{"lvl0":"Features","lvl1":"Model routing with a decision model","lvl2":"","lvl3":""}},
2635
2635
  {"objectID":"bd360e5abf4e93403d1fb23a27c946fed1b86d8d8863a98519338332ca726639","title":"Model routing with a decision model","url":"/docs/features/classifier-router-jev-strategy#model-routing-with-a-decision-model","content":"The classifier router has a jev strategy: one\ndecision-model round trip answers difficulty,\nrequired capabilities, risk and the model pick simultaneously, with a\ncalibrated confidence on each. This page is the strategy's own mechanics —\nclassifier-router.md covers the router as a whole.\n\nThe degradation contract. With no decision provider configured,\nresolveStrategy() resolves auto to heuristic, exactly as it always did.\nclassifyJev() itself never throws: any failure, timeout, or malformed answer\nfalls back to classifyHeuristic(). Configuring a decision provider (for example TYPESAFE_API_KEY or\nAI_GATEWAY_API_KEY) upgrades routing; it cannot make routing worse than before\nthe key existed. The same holds for PERPLEXITY_API_KEY, which is also the\nPerplexity text provider's key, and for CLOUDFLARE_API_KEY with\nCLOUDFLARE_ACCOUNT_ID, which are also the Cloudflare Workers AI text provider's\ntoken and account id. \"Configured\" counts the environment, the instance\ncredentials, and the request's own per-call credentials — a host that holds\nno decision key but passes a tenant's credentials: { laya } on a generate()\ncall routes that call with jev, and the decision goes to the tenant's account.","hierarchy":{"lvl0":"Features","lvl1":"Model routing with a decision model","lvl2":"Model routing with a decision model","lvl3":""}},
2636
- {"objectID":"a6b27c365174a477eafb6835b9ab5990c7434acd58cb21534f8419ea21c63dd5","title":"What goes into the state","url":"/docs/features/classifier-router-jev-strategy#what-goes-into-the-state","content":"classifyJev() sends the request truncated to 8000 characters, plus four\nsignals the caller already has on hand:\n\nAlongside it, one batch asks: difficulty (a choice over the five tiers),\nneeds_vision / needs_tools / needs_reasoning (boolean), risky\n(boolean), context (a score — see\nper-request context budget), and, only when the\npool has more than one member, model (a choice over the pool, rendered by\nthe catalogue). All of this rides in\none request. On TypeSafe that takes ~400ms, because latency is flat in question\ncount; on Perplexity each further question adds about 65 ms, up to 128 (see\nits guide); on\nCloudflare Clef a small request took 0.3 to 1.0 s on 2026-10-03 (see\nits guide). See\nthe batching rule.\n\nThe Cloudflare Clef endpoint ignores state text past about 2,048 tokens, and\nNeuroLink refuses a state it estimates at more than 1,500 tokens with\nmax_tokens_exceeded. A long request is therefore refused there, and the\nheuristic classifier's tier stands, as it does on any failure.","hierarchy":{"lvl0":"Features","lvl1":"Model routing with a decision model","lvl2":"What goes into the state","lvl3":""}},
2636
+ {"objectID":"a6b27c365174a477eafb6835b9ab5990c7434acd58cb21534f8419ea21c63dd5","title":"What goes into the state","url":"/docs/features/classifier-router-jev-strategy#what-goes-into-the-state","content":"classifyJev() sends the request truncated to 8000 characters, plus four\nsignals the caller already has on hand:\n\nAlongside it, one batch asks: difficulty (a choice over the five tiers),\nneeds_vision / needs_tools / needs_reasoning (boolean), risky\n(boolean), context (a score — see\nper-request context budget), and, only when the\npool has more than one member, model (a choice over the pool, rendered by\nthe catalogue). All of this rides in\none request. On TypeSafe that takes ~400ms, because latency is flat in question\ncount; on Perplexity each further question adds about 65 ms, up to 128 (see\nits guide); on\nCloudflare Clef a small request took 0.3 to 1.0 s on 2026-10-03 (see\nits guide). See\nthe batching rule.\n\nNeuroLink refuses a state it estimates at more than 16,000 tokens (about 60,000\ncharacters of prose) with max_tokens_exceeded, to keep Clef inside what it was\nseen to read in full and inside a timeout a fail-open consumer can afford. A\nlonger request is refused there, and the heuristic classifier's tier stands, as it\ndoes on any failure.","hierarchy":{"lvl0":"Features","lvl1":"Model routing with a decision model","lvl2":"What goes into the state","lvl3":""}},
2637
2637
  {"objectID":"ed3d90e1e698e522c2fb4cbd27b81d89a769c3d860bbbb85d004ef5cf1d1090d","title":"The difficulty rubric","url":"/docs/features/classifier-router-jev-strategy#the-difficulty-rubric","content":"Five tiers, ordered easiest to hardest, worded about the shape of the work —\nthe model is never told a provider or model name:\n\n| Tier | Criterion |\n| ---------- | ----------------------------------------------------------------------------------------------------------------------------------------------------- |\n| trivial | Mechanical and local: rename a symbol, fix a typo, add an import, run one named command, or answer something already stated. |\n| simple | A small localised change or a direct factual answer. One file, one obvious approach. |\n| moderate | Ordinary engineering: implement a well-specified change across a few files, write tests, fix a clearly described bug, review a small diff. |\n| hard | Deep reasoning: architecture and design, debugging a failure whose cause is unknown, security analysis, concurrency, cross-system refactors. |\n| expert | Frontier-level work: ambiguous requirements, novel design with no established pattern, or analysis where a wrong answer is costly and hard to detect. |","hierarchy":{"lvl0":"Features","lvl1":"Model routing with a decision model","lvl2":"The difficulty rubric","lvl3":""}},
2638
2638
  {"objectID":"2bcf89adce5486bff7cc01f6916f9bf26080de8996ec2277df6e15eb3eb264e3","title":"Asymmetric confidence bars, and why they differ","url":"/docs/features/classifier-router-jev-strategy#asymmetric-confidence-bars-and-why-they-differ","content":"A verdict harder than the neutral tier (moderate) spends more if wrong; a\nverdict easier than neutral spends less if wrong. Those are not the same\nmistake:\nRouting a simple task to an expensive model wastes money. Cheap to be wrong\n about, so the bar to route up is low: minUpgradeConfidence defaults to\n 0.3.\nRouting a hard task to a weak model produces a wrong answer. Expensive to be\n wrong about, so the bar to route down is high: minDowngradeConfidence\n defaults to 0.6.\n\nBelow the applicable bar, the difficulty verdict is discarded and the heuristic\nclassifier's tier stands instead — not a downgraded jev answer, the ordinary\nzero-cost fallback.\n\nOne case skips both bars: a risky reading above 0.7 forces the tier to at\nleast hard, unconditionally. Risk can only ever raise the tier, never lower\none, and it is not itself gated by confidence.","hierarchy":{"lvl0":"Features","lvl1":"Model routing with a decision model","lvl2":"Asymmetric confidence bars, and why they differ","lvl3":""}},
2639
2639
  {"objectID":"516e7c128214404728015c7b49bc089992935102cb4baebbcdc3d8170078873c","title":"Ask about the act, not the subject","url":"/docs/features/classifier-router-jev-strategy#ask-about-the-act-not-the-subject","content":"The risk question is not \"does this touch production, money, or credentials\":\n\nCarrying out this request would itself change production, move real money,\nexpose credentials, or alter data that cannot be restored. Writing or testing\ncode that deals with such things, without running it against the real system,\ndoes not count.\n\nThe naive phrasing was tried first and scored high on ordinary code that merely\nconcerns those things — \"add a refund endpoint that calls Stripe\" — which\nwould have escalated every such request to the most expensive tier. The second\nsentence is what separates writing the code from running it against something\nreal.","hierarchy":{"lvl0":"Features","lvl1":"Model routing with a decision model","lvl2":"Ask about the act, not the subject","lvl3":""}},
@@ -3249,7 +3249,7 @@
3249
3249
  {"objectID":"a18da32e2f63d235059c36cf45cff486c8f1dc0c4d4e55ee5f239dd89ede5d21","title":"BudgetCheckResult","url":"/docs/features/context-compaction#budgetcheckresult","content":"Returned by checkContextBudget().","hierarchy":{"lvl0":"Features","lvl1":"Context Compaction","lvl2":"BudgetCheckResult","lvl3":""}},
3250
3250
  {"objectID":"1a2b7ee1dace651a8300809eec11e00b29da084cbfe5b040e4760d58ea0b5879","title":"BudgetCheckParams","url":"/docs/features/context-compaction#budgetcheckparams","content":"Parameters for checkContextBudget().\n\nSource: src/lib/context/budgetChecker.ts:18-54","hierarchy":{"lvl0":"Features","lvl1":"Context Compaction","lvl2":"BudgetCheckParams","lvl3":""}},
3251
3251
  {"objectID":"4bad23fd2858cc71b5af8506276229485c7d0a9636cfddae5c5d9df400bc28b8","title":"The 5-Stage Pipeline","url":"/docs/features/context-compaction#the-5-stage-pipeline","content":"The ContextCompactor runs stages sequentially. Each stage only runs if the\nprevious stage didn't bring tokens below the target budget.\n\n| # | Stage | CompactionStage | Needs a decision model |\n| --- | ------------------------- | ----------------- | -------------------------------------- |\n| 0 | Relevance drop | relevance | yes — skipped entirely without one |\n| 1 | Tool output pruning | prune | no |\n| 2 | File read deduplication | deduplicate | no |\n| 3 | LLM summarization | summarize | no (its gate uses one) |\n| 4 | Sliding window truncation | truncate | no |\n\nresult.stagesUsed reports the ones that actually ran, in order.","hierarchy":{"lvl0":"Features","lvl1":"Context Compaction","lvl2":"The 5-Stage Pipeline","lvl3":""}},
3252
- {"objectID":"918fce938e3acd086621a86be0faaaecccf78059d8a0ef53b2dbc4fcd87347a1","title":"Stage 0: Relevance drop","url":"/docs/features/context-compaction#stage-0-relevance-drop","content":"File: src/lib/context/contextDecision.ts\n\nEverything below Stage 0 is chronological: the pipeline's only notion of\n\"droppable\" is \"old\". Stage 0 is the one stage that asks what a message is\nfor — one boolean per message (\"is this needed to answer the current\nrequest?\") in a single batch. On TypeSafe that costs the same for 200 messages\nas for one because decision latency is flat in question count; on Perplexity each\nfurther question adds about 65 ms and a request takes at most 128 (see\nits guide); on\nCloudflare Clef a request takes at most 64 questions, which tryDecide() splits\ninto batches of 64 (see its guide).\nThe Clef endpoint also ignores state text past about 2,048 tokens, and NeuroLink\nrefuses a state it estimates at more than 1,500 tokens, so a longer set of\neligible messages gets a refusal and the stage is skipped, as on any failure.\n\nIt is strictly additive. With no decision provider configured the stage\ndoes not run, stagesUsed omits relevance, and the pipeline behaves exactly\nas the four-stage one always did. It is also bounded by maxDropRatio and\nwalks oldest-first, so when the cap binds it spares the newest candidates —\nthe same recency assumption every other stage makes.","hierarchy":{"lvl0":"Features","lvl1":"Context Compaction","lvl2":"Stage 0: Relevance drop","lvl3":""}},
3252
+ {"objectID":"918fce938e3acd086621a86be0faaaecccf78059d8a0ef53b2dbc4fcd87347a1","title":"Stage 0: Relevance drop","url":"/docs/features/context-compaction#stage-0-relevance-drop","content":"File: src/lib/context/contextDecision.ts\n\nEverything below Stage 0 is chronological: the pipeline's only notion of\n\"droppable\" is \"old\". Stage 0 is the one stage that asks what a message is\nfor — one boolean per message (\"is this needed to answer the current\nrequest?\") in a single batch. On TypeSafe that costs the same for 200 messages\nas for one because decision latency is flat in question count; on Perplexity each\nfurther question adds about 65 ms and a request takes at most 128 (see\nits guide); on\nCloudflare Clef a request takes at most 64 questions, which tryDecide() splits\ninto batches of 64 (see its guide).\nNeuroLink also refuses a state it estimates at more than 16,000 tokens (about\n60,000 characters of prose), so a longer set of eligible messages gets a refusal\nand the stage is skipped, as on any failure.\n\nIt is strictly additive. With no decision provider configured the stage\ndoes not run, stagesUsed omits relevance, and the pipeline behaves exactly\nas the four-stage one always did. It is also bounded by maxDropRatio and\nwalks oldest-first, so when the cap binds it spares the newest candidates —\nthe same recency assumption every other stage makes.","hierarchy":{"lvl0":"Features","lvl1":"Context Compaction","lvl2":"Stage 0: Relevance drop","lvl3":""}},
3253
3253
  {"objectID":"c1fa9b4e362150149aa7889fbd1374625457cdc5cba6f57fb15d82ef305fc492","title":"The summary gate","url":"/docs/features/context-compaction#the-summary-gate","content":"Stage 3 used to accept any non-empty string as a summary. When a decision\nmodel is configured, the generated summary is now checked first (\"does this\npreserve every decision and open question?\") and a rejected summary leaves the\nmessages untouched so a later stage can try instead. The rejection is recorded\non the span as compaction.stage3.summaryRejected, because a gate that\nsilently discarded work would be indistinguishable from one that never ran.\n\nRejection is deliberately rare: the gate exists to catch a summary that lost a\ndecision, not to second-guess wording.","hierarchy":{"lvl0":"Features","lvl1":"Context Compaction","lvl2":"The summary gate","lvl3":""}},
3254
3254
  {"objectID":"2a518830a84553879be50318dfc47b77a34bf2c61cb5bc21a443ad5a5fcba95b","title":"Stage 1: Tool Output Pruning","url":"/docs/features/context-compaction#stage-1-tool-output-pruning","content":"File: src/lib/context/stages/toolOutputPruner.ts\n\nWalks messages backwards, protecting the most recent tool outputs, and replaces older tool results with \"[Tool result cleared]\".\n\nPruneConfig:\n\n| Field | Type | Default | Description |\n| ---------------- | ---------- | ----------- | ----------------------------------------------------------- |\n| protectTokens | number | 40,000 | Token budget of recent tool outputs to protect from pruning |\n| minimumSavings | number | 20,000 | Minimum tokens that must be saved for pruning to be applied |\n| protectedTools | string[] | [\"skill\"] | Tool names that are never pruned |\n| provider | string | — | Provider name for token estimation multiplier |\n\nPruneResult:","hierarchy":{"lvl0":"Features","lvl1":"Context Compaction","lvl2":"Stage 1: Tool Output Pruning","lvl3":""}},
3255
3255
  {"objectID":"7c30f222482767920767c8a3dee1c3955d4b615a31c54b58851b467e409a9e64","title":"Stage 2: File Read Deduplication","url":"/docs/features/context-compaction#stage-2-file-read-deduplication","content":"File: src/lib/context/stages/fileReadDeduplicator.ts\n\nDetects multiple reads of the same file path. Keeps only the latest read, replaces earlier reads with \"[File <path> - refer to latest read below]\".\n\nDeduplicationResult:\n\nFile read detection uses the regex pattern: /(?:read|reading|read_file|readFile|Read file|cat)\\s+['\"]?([^\\s'\"\\n]+)/i\n\nA 30% savings threshold (DEDUP_THRESHOLD = 0.3) must be met for deduplication to be applied.","hierarchy":{"lvl0":"Features","lvl1":"Context Compaction","lvl2":"Stage 2: File Read Deduplication","lvl3":""}},
@@ -3368,17 +3368,17 @@
3368
3368
  {"objectID":"71509585343bb3860ff000ad67405f6ed19fbc26f8eb973ac1fe58088af460b4","title":"Laya, at a Laya server or a LiteLLM proxy route","url":"/docs/features/decide-inference-type#laya-at-a-laya-server-or-a-litellm-proxy-route","content":"Laya has no built-in endpoint. The base URL and key can equally come from the\nconfig passed to the SDK, new NeuroLink({ credentials: { laya: { baseURL, apiKey } } }),\nor per call; config set there counts when NeuroLink picks the default decision\nprovider, exactly as the environment does.\n\nWhen a TypeSafe key (TYPESAFE_API_KEY or AI_GATEWAY_API_KEY) is configured\nalongside Laya, TypeSafe is the default; Laya runs where a caller names it\n(provider: \"laya\") or when neither TypeSafe key is set. Laya counts as\nconfigured only with both its key and its base URL. See the\nLaya provider guide.","hierarchy":{"lvl0":"Features","lvl1":"The `decide` inference type","lvl2":"Laya, at a Laya server or a LiteLLM proxy route","lvl3":""}},
3369
3369
  {"objectID":"19994573e52cd09183db8050eadaea8ece3e291ef40c3009a5c44dfa959bf99c","title":"XOR, at a deployment or a LiteLLM proxy route","url":"/docs/features/decide-inference-type#xor-at-a-deployment-or-a-litellm-proxy-route","content":"XOR, Juspay's open-weights decision model, has no built-in endpoint either.\nNeuroLink calls <base URL>/v1/systemone, and a trailing /v1 on the base URL\nis accepted. The base URL and key can equally come from the config passed to the\nSDK, new NeuroLink({ credentials: { xor: { baseURL, apiKey } } }), or per\ncall; config set there counts when NeuroLink picks the default decision\nprovider, exactly as the environment does. On a LiteLLM proxy the key's team\nmust allow xor-1.1, otherwise the proxy answers 403 team_model_access_denied.\n\nBuilt-in features use the first configured decision provider in the order\nTypeSafe, Laya, XOR, Perplexity, Cloudflare Clef. XOR counts as configured only with both its key\nand its base URL, and runs where a caller names it (provider: \"xor\") or when\nneither TypeSafe nor Laya is configured. It reads images and video; see\nImages and video and the\nXOR provider guide.","hierarchy":{"lvl0":"Features","lvl1":"The `decide` inference type","lvl2":"XOR, at a deployment or a LiteLLM proxy route","lvl3":""}},
3370
3370
  {"objectID":"dc8b9e9a2c66b1d2a60305a09a44263ceca755d40f04b6771e0a7c05a5237a64","title":"Perplexity, at its hosted endpoint","url":"/docs/features/decide-inference-type#perplexity-at-its-hosted-endpoint","content":"Perplexity's pplx-decider-v1-27b is a hosted API at a public endpoint, so a key\nalone configures it and there is no base URL to set. NeuroLink calls\n<base URL>/v1/decisions; a trailing /v1 on an override is accepted. The key\ncan equally come from the config passed to the SDK,\nnew NeuroLink({ credentials: { perplexityDecider: { apiKey } } }), or per call;\nconfig set there counts when a decide() call picks the default decision\nprovider, exactly as the environment does. The classifier router's auto gate is\nread differently: it looks at the constructor's credentials and the environment\nonly, so a credentials.perplexityDecider passed on one call does not influence\nit. The provider id is perplexity-decider: the perplexity provider is the\nSonar text provider, which serves generate() and stream() and not decide().\n\nPERPLEXITY_API_KEY is shared with that text provider. A host that set it\nonly to use Sonar has therefore also configured decide, and built-in features\nwill use Perplexity whenever none of TypeSafe, Laya or XOR is configured.\nPerplexity comes after XOR in descriptor order, so it never displaces one that\nis. Context compaction's relevance stage and summary gate need no opt-in of their\nown, so earlier conversation text starts going to Perplexity the first time a\nconversation outgrows its budget; model routing, tool routing and RAG planning do\nnothing unless enabled. To keep the shared key from activating decisions, pass\nthe text provider's key as credentials.perplexity instead of through the\nenvironment, and keep it out of .env too, because the SDK and the CLI load that\nfile into the environment, or configure one of TypeSafe, Laya and XOR, which then\nreceives those texts instead. The Perplexity provider guide lists\nwhat each consumer sends\nand the\nexact switches.\nIt reads images but no video; see Images and video.","hierarchy":{"lvl0":"Features","lvl1":"The `decide` inference type","lvl2":"Perplexity, at its hosted endpoint","lvl3":""}},
3371
- {"objectID":"86d184ec9e501d4e94e973c833eaee71bb40744e683334ad36c497c3f625387f","title":"Cloudflare Clef, on Workers AI","url":"/docs/features/decide-inference-type#cloudflare-clef-on-workers-ai","content":"Cloudflare's clef and clef-flash are hosted on Workers AI at a public\nendpoint, so there is no base URL to set. The account id is part of the route, so\nClef counts as configured only with both the token and the account id. They can\nequally come from the config passed to the SDK,\nnew NeuroLink({ credentials: { cloudflareClef: { apiKey, accountId } } })\n(baseURL is optional), or per call; config set there counts when a decide()\ncall picks the default decision provider, exactly as the environment does. The\nclassifier router's auto gate is read differently: it looks at the\nconstructor's credentials and the environment only, so a\ncredentials.cloudflareClef passed on one call does not influence it. The\nprovider id is cloudflare-clef: the cloudflare provider is the Workers AI text\nprovider, which serves generate() and stream() and not decide(), and\ncredentials.cloudflare does not configure decide.\n\nThe Workers AI endpoint ignores state text past about 2,048 tokens.\nCloudflare documents a 64K window; text past the observed boundary is ignored\nwithout an error (hosted service or model: unknown). NeuroLink refuses a state it estimates at more than 1,500\ntokens with max_tokens_exceeded, which every built-in consumer treats as \"carry\non as before\"; see Limits and gotchas. Clef suits short\ndecisions.\n\nCLOUDFLARE_API_KEY and CLOUDFLARE_ACCOUNT_ID are shared with that text\nprovider. A host that set them only to use Workers AI text has therefore also\nconfigured decide, and built-in features will use Clef whenever none of\nTypeSafe, Laya, XOR or Perplexity is configured. Clef comes last in the order, so\nit never displaces one that is. No switch turns it off while the two variables\nare set. The Clef provider guide explains\nwhen NeuroLink uses it\nand\nhow the two providers share the token.\nIt reads images but no video; see Images and video.\n\nThe degradation contract.","hierarchy":{"lvl0":"Features","lvl1":"The `decide` inference type","lvl2":"Cloudflare Clef, on Workers AI","lvl3":""}},
3371
+ {"objectID":"86d184ec9e501d4e94e973c833eaee71bb40744e683334ad36c497c3f625387f","title":"Cloudflare Clef, on Workers AI","url":"/docs/features/decide-inference-type#cloudflare-clef-on-workers-ai","content":"Cloudflare's clef and clef-flash are hosted on Workers AI at a public\nendpoint, so there is no base URL to set. The account id is part of the route, so\nClef counts as configured only with both the token and the account id. They can\nequally come from the config passed to the SDK,\nnew NeuroLink({ credentials: { cloudflareClef: { apiKey, accountId } } })\n(baseURL is optional), or per call; config set there counts when a decide()\ncall picks the default decision provider, exactly as the environment does. The\nclassifier router's auto gate is read differently: it looks at the\nconstructor's credentials and the environment only, so a\ncredentials.cloudflareClef passed on one call does not influence it. The\nprovider id is cloudflare-clef: the cloudflare provider is the Workers AI text\nprovider, which serves generate() and stream() and not decide(), and\ncredentials.cloudflare does not configure decide.\n\nThe Workers AI endpoint's state window changed during October 2026.\nCloudflare documents a 64K window; until 2026-10-04 text past about 2,048 tokens\nwas ignored without an error, and on 2026-10-07 states of at least 190,153 tokens\n(clef-flash) and 52,154 (clef) were read in full (hosted service or model:\nunknown). NeuroLink refuses a state it estimates at more than 16,000 tokens with\nmax_tokens_exceeded, which every built-in consumer treats as \"carry on as\nbefore\"; see Limits and gotchas. Latency grows with the\nstate, about 0.2 s per 1,000 tokens on large ones, so NeuroLink's default timeout\nadds 250 ms per 1,000 estimated tokens.\n\nCLOUDFLARE_API_KEY and CLOUDFLARE_ACCOUNT_ID are shared with that text\nprovider. A host that set them only to use Workers AI text has therefore also\nconfigured decide, and built-in features will use Clef whenever none of\nTypeSafe, Laya, XOR or Perplexity is configured. Clef comes last in the order, so\nit never displaces one that is. No switch turns it off while the two variables\nare set.","hierarchy":{"lvl0":"Features","lvl1":"The `decide` inference type","lvl2":"Cloudflare Clef, on Workers AI","lvl3":""}},
3372
3372
  {"objectID":"7990ffc08aca0afbeae4310cfdcd3758daf52da4d9edd1da90a82b683f4d7d41","title":"Two transports","url":"/docs/features/decide-inference-type#two-transports","content":"The same model is reachable two ways. Which one runs is decided once, in the\nconstructor:\n\n| | Direct | Vercel AI Gateway |\n| ------------------- | ------------------ | --------------------------------------------- |\n| Key | TYPESAFE_API_KEY | AI_GATEWAY_API_KEY |\n| Endpoint | api.typesafe.ai | ai-gateway.vercel.sh/v4/ai/evaluation-model |\n| Model named in | request body | ai-model-id header |\n| Question vocabulary | noul | boolean |\n| confidence | on each answer | on providerMetadata, not on the answer |\n| Billed by | TypeSafe | Vercel |\n\nHolding both keys keeps the direct transport, so the confidence figures a\nhost already sees do not shift underneath it when a second key appears. Both\ntransports report the vendor's calibrated confidence — the gateway simply puts\nit somewhere else, under providerMetadata.typesafe.confidence.<questionId>,\nleaving the answer objects without one. Set TYPESAFE_TRANSPORT=gateway (or\ncredentials.typesafe.transport) to override.\n\n⚠️ Read that field, not the distribution peak. It is tempting to take\nmax(probabilities) when an answer carries no confidence, and on a\nnear-certain answer the two agree. On an uncertain one they do not, and not by a\nlittle: a measured four-way choice returned probabilities\n{alpha 0.16, beta 0.28, gamma 0.33, delta 0.23} — a peak of 0.33 against a\nreported confidence of 0.10. That gap straddles the default\nminUpgradeConfidence of 0.3, so the derived number clears a bar the real one\nfails and a near-random pick gets acted on as a confident one. The peak stays as\nthe fallback when neither source reports a confidence, and it is genuinely a\ndifferent quantity: an even distribution over N options lands near 1/N, not 0.","hierarchy":{"lvl0":"Features","lvl1":"The `decide` inference type","lvl2":"Two transports","lvl3":""}},
3373
3373
  {"objectID":"e5df7db87d4cb31c67fcce769cf5a3573764cb358ed9ee4b41f7ce86cb3954b7","title":"Using it","url":"/docs/features/decide-inference-type#using-it","content":"readDecisionBoolean / readDecisionChoice / readDecisionScore validate at\nruntime and return undefined for a missing id or a mismatched type, so no\ncall site needs a type assertion.\n\nUse decide() instead of tryDecide() when you want the failure to surface;\nit throws a ProviderError whose cause carries a typed kind\n(authentication, rate_limit, max_tokens_exceeded, …).\n\nMore questions than a provider takes. A provider that caps the questions in\none request (Laya and Cloudflare Clef take 64) refuses a longer map from decide() with\nmax_tokens_exceeded. tryDecide(), which every built-in consumer calls,\nsplits the map at the cap instead, keeps the questions in the order given, runs\nup to four batches at a time and joins the answers into one result: usage is\nsummed, the latency is the slowest batch's, and requestId lists the batches'\nids. A batch that fails costs only its own questions, which then have no answer\n(the read* helpers return undefined for them, and every built-in consumer\ncarries on without that decision); tryDecide() returns null only when every\nbatch failed. The state and any media are sent with each batch, so a split\nrequest costs the state's tokens once for each batch. A provider with no cap\n(TypeSafe, XOR) always gets one request.","hierarchy":{"lvl0":"Features","lvl1":"The `decide` inference type","lvl2":"Using it","lvl3":""}},
3374
3374
  {"objectID":"7232a490e9e72e01dbe1a12de9470a38ed66ef91aa076b8c8cc745770eb03545","title":"From the CLI","url":"/docs/features/decide-inference-type#from-the-cli","content":"The same primitive is available as neurolink decide [state], which calls\ndecide() (not tryDecide()) and prints one line per answer:\n\nTo ask about an image or a video, add --image <path> (repeatable) or\n--video <path>. XOR reads both, Perplexity and Cloudflare Clef read images only,\nand TypeSafe and Laya read neither:\n\nSee the CLI command reference for the full flag\nlist, including --state-file, --questions-file, --image, --video and\n--format json.","hierarchy":{"lvl0":"Features","lvl1":"The `decide` inference type","lvl2":"From the CLI","lvl3":""}},
3375
3375
  {"objectID":"3b801c727cb399feb7390c3ad67aba9ea5f77581096bb852b7aafb87b70998aa","title":"A choice answer is also a ranking","url":"/docs/features/decide-inference-type#a-choice-answer-is-also-a-ranking","content":"readDecisionChoice returns ranked — every option sorted by probability,\nhighest first. One choice question over N options therefore ranks all N in a\nsingle request. This is the basis for picking from a large catalogue.","hierarchy":{"lvl0":"Features","lvl1":"The `decide` inference type","lvl2":"A choice answer is also a ranking","lvl3":""}},
3376
3376
  {"objectID":"e67682840a5ce9650dba2a1d437b0dfbba456cae60fa3f607127e209bf1ec3e7","title":"Images and video","url":"/docs/features/decide-inference-type#images-and-video","content":"A decision provider whose descriptor declares media limits reads images, and\npossibly one video, alongside state. XOR does, and so do Perplexity and\nCloudflare Clef, which declare images only and no video; TypeSafe and Laya do\nnot. Two optional fields on the request carry them, for decide() and\ntryDecide() alike:\nimages — up to 8 images, the limit XOR and Perplexity each declare; Cloudflare\n Clef takes up to 4.\nvideo — one video, for a provider that declares video (XOR).\n\nEach image and the video takes the same three input forms:\na Buffer;\na local file path;\na data:image/…;base64, or data:video/…;base64, URL.\n\nNeuroLink identifies a Buffer or a file from its bytes, not its extension — PNG,\nJPEG, WebP and GIF images, and MP4, MOV and WebM video —\nand sends it as a data: URL. A data: URL you pass yourself must hold base64\nimage or video content. Clef normalizes image/jpg to image/jpeg; other data URLs are sent as given. Perplexity and Cloudflare Clef read\nPNG, JPEG and WebP only, and refuse a GIF before any request.\n\nWhat is refused. Everything NeuroLink can check is refused before any\nrequest, as a non-retryable invalid_request:\nan http(s) URL — media is not fetched for you, so pass a Buffer, a file path\n or a data: URL;\na string that is not a file path or a data: URL, such as bare base64 or a\n URL with another scheme;\na missing file, a directory, or an empty Buffer or file;\nsomething that is not an image or a video;\nmore than 8 images, or more than 4 for Cloudflare Clef;\na request body over the provider's limit: 8 MB for XOR, 32 MiB for Perplexity,\n 256,000 bytes for Cloudflare Clef. The limit applies to the encoded body, so\n the base64 form counts, and a photo usually has to be resized to well under\n 190 KB before Clef will take it.","hierarchy":{"lvl0":"Features","lvl1":"The `decide` inference type","lvl2":"Images and video","lvl3":""}},
3377
3377
  {"objectID":"a6077cedd1ca3e03b757da9a2ef8c185a56d2f1032dd5ed43fe28bd71454836c","title":"The one rule: batch, never fan out","url":"/docs/features/decide-inference-type#the-one-rule-batch-never-fan-out","content":"This inverts the instinct you have from LLMs.\n\nOn TypeSafe, question count barely affects latency (measured against its live\nAPI):\n\n| questions | round trip | input tokens |\n| --------- | ---------- | ------------ |\n| 1 | 393 ms | 310 |\n| 10 | 390 ms | 481 |\n| 100 | 423 ms | 2 281 |\n| 400 | 465 ms | 8 581 |\n\nThese are TypeSafe's figures. perplexity-decider differs: about 0.3 to 1.1 s\nfor one question, about 65 ms for each further question (a request takes at\nmost 128), and an input time that grows faster than linearly with size: 3.9 s\nat 65,000 tokens, 10 s at 146,000 and 22.9 s at 251,000. See\nits latency section.\ncloudflare-clef takes 0.3 to 1.0 s for a small request and 1.1 to 1.3 s for\n64 questions (measured 2026-10-03). A 64-question request with the same\nquestions and a shorter state took 1.5 s on clef-flash and 2.3 s on clef on 2026-10-04; see\nits latency section.\n\nOn TypeSafe, 400 questions cost ~70 ms more than one. Concurrent requests, by\ncontrast, queue: ten parallel calls take ~1.4 s wall with nine landing together\nat the end, while the server's own upstream time stays flat at 64–169 ms.\n\nSo on TypeSafe, 400 things in one request take ~465 ms; the same 400 as separate\nrequests take roughly a minute. Add every question you might need to the call\nyou are already making — speculative questions are nearly free on TypeSafe (on\nPerplexity each costs about 65 ms, up to 128 in a request; Cloudflare Clef takes\nup to 64), and a second round trip is not.","hierarchy":{"lvl0":"Features","lvl1":"The `decide` inference type","lvl2":"The one rule: batch, never fan out","lvl3":""}},
3378
- {"objectID":"0c1ce0b91d624674d6b4cc3b1f67fad986bcdfd379812b89e121784a94408ec3","title":"Model routing","url":"/docs/features/decide-inference-type#model-routing","content":"The classifier router gains a jev\nstrategy, and its default becomes auto — resolving to jev when a decision\nprovider is configured and heuristic when not.\n\nOne request asks for the difficulty tier, whether the task needs\nvision/tools/reasoning, whether carrying it out is risky, and which pool\nmember to use — all at once, in ~400 ms on TypeSafe's Jev.\n\n| | heuristic | llm | jev |\n| ---------------------- | ------------- | ------------------------------- | --------------------------------------------------- |\n| Added latency | 0 ms | ~1–8 s | ~400 ms on TypeSafe |\n| Cost per decision | none | a full LLM call | ~$0.00002 on TypeSafe |\n| Confidence | keyword score | self-reported (defaults to 0.7) | as the provider reports it (calibrated on TypeSafe) |\n| Picks a model directly | no | yes | yes |\n\nThe jev column is TypeSafe's figures; the\nPerplexity guide gives its\nlatency and the confidence it reports. The\nCloudflare Clef guide gives its\nlatency; because Clef reads only about 2,048 tokens of state, a long prompt is\nrefused there and routing falls back to the heuristic, as it does on any failure.\n\nThresholds are asymmetric, because the two mistakes do not cost the same:\nminUpgradeConfidence defaults to 0.3 (spending more on a wrong guess costs\nmoney) and minDowngradeConfidence to 0.6 (spending less on a wrong guess\nproduces a wrong answer).\n\nThe key upgrades routing; it does not switch routing on. The classifier\nrouter is still opt-in (classifierRouter.enabled) and still needs a pool,\nbecause NeuroLink cannot invent the set of models you are willing to route\nbetween.","hierarchy":{"lvl0":"Features","lvl1":"The `decide` inference type","lvl2":"Model routing","lvl3":""}},
3378
+ {"objectID":"0c1ce0b91d624674d6b4cc3b1f67fad986bcdfd379812b89e121784a94408ec3","title":"Model routing","url":"/docs/features/decide-inference-type#model-routing","content":"The classifier router gains a jev\nstrategy, and its default becomes auto — resolving to jev when a decision\nprovider is configured and heuristic when not.\n\nOne request asks for the difficulty tier, whether the task needs\nvision/tools/reasoning, whether carrying it out is risky, and which pool\nmember to use — all at once, in ~400 ms on TypeSafe's Jev.\n\n| | heuristic | llm | jev |\n| ---------------------- | ------------- | ------------------------------- | --------------------------------------------------- |\n| Added latency | 0 ms | ~1–8 s | ~400 ms on TypeSafe |\n| Cost per decision | none | a full LLM call | ~$0.00002 on TypeSafe |\n| Confidence | keyword score | self-reported (defaults to 0.7) | as the provider reports it (calibrated on TypeSafe) |\n| Picks a model directly | no | yes | yes |\n\nThe jev column is TypeSafe's figures; the\nPerplexity guide gives its\nlatency and the confidence it reports. The\nCloudflare Clef guide gives its\nlatency; a prompt NeuroLink estimates over 16,000 tokens is refused there and\nrouting falls back to the heuristic, as it does on any failure.\n\nThresholds are asymmetric, because the two mistakes do not cost the same:\nminUpgradeConfidence defaults to 0.3 (spending more on a wrong guess costs\nmoney) and minDowngradeConfidence to 0.6 (spending less on a wrong guess\nproduces a wrong answer).\n\nThe key upgrades routing; it does not switch routing on. The classifier\nrouter is still opt-in (classifierRouter.enabled) and still needs a pool,\nbecause NeuroLink cannot invent the set of models you are willing to route\nbetween. What the key changes is which classifier runs inside a router you\nalready enabled.","hierarchy":{"lvl0":"Features","lvl1":"The `decide` inference type","lvl2":"Model routing","lvl3":""}},
3379
3379
  {"objectID":"40f783ceca290c039cce7f0199ab5758d7a0719b0a91c335c1c6e490a72b1412","title":"The model catalogue","url":"/docs/features/decide-inference-type#the-model-catalogue","content":"Enabling classifierRouter.catalog widens the routable pool beyond what you\ndeclared by hand: candidates are built from the 64-model registry (7\nproviders — see the model catalogue\nfor which), intersected with the credentials this host actually holds, and\nranked by a deterministic formula whenever no decision provider is available\nto choose among them.\n\n| | Without catalog | With catalog.enabled |\n| -------------- | ------------------------ | ------------------------------------- |\n| Candidate pool | only the declared pool | declared pool plus registry matches |\n| Fallback pick | first pool member | tierScore()-ranked, tier-aware |\n| Cap | none needed | maxModels, default 120 |\n\nSee the model catalogue for how\ncandidates are filtered, rendered, and ranked.","hierarchy":{"lvl0":"Features","lvl1":"The `decide` inference type","lvl2":"The model catalogue","lvl3":""}},
3380
3380
  {"objectID":"1362463e9ab1e8a456cb34a4e5ac2ec8493f18ddc2a8d277282de858c0420131","title":"Per-request context budget","url":"/docs/features/decide-inference-type#per-request-context-budget","content":"A per-request compactionThreshold option lowers the point at which history\ngets compacted, below the 0.8-of-window default. The jev strategy can fill\nit in automatically from a four-level scope rubric (current-message through\neverything) — and the mapping is a one-directional invariant: it can only\never lower the 0.8 default, never raise it, because over-filling a window is\nan unrecoverable provider error.\n\nSee per-request context budget for the\nrubric, the invariant, and how the threshold scales the compaction target.","hierarchy":{"lvl0":"Features","lvl1":"The `decide` inference type","lvl2":"Per-request context budget","lvl3":""}},
3381
- {"objectID":"ac97e63916f0ffdf1d9befada357186f236753d40ea1f0e97bcab715e54fa7cd","title":"Relevance-driven compaction","url":"/docs/features/decide-inference-type#relevance-driven-compaction","content":"Before the existing positional compaction stages run, an optional Stage 0\nasks, per eligible message, whether the current request still needs it — at\n~400 ms for the whole batch regardless of message count (on TypeSafe;\nperplexity-decider differs, taking about 0.3 to 1.1 s for one question and about\n65 ms for each further one, plus an input time that grows faster than linearly\nwith size; cloudflare-clef took 0.3 to 1.0 s for a small request on 2026-10-03, and its\nendpoint ignores state text past about 2,048 tokens).\nOnly plain user/assistant text is eligible, the most recent messages are never\ntouched, and a message is dropped only on a confident \"no.\"\n\n| | Positional stages (1–4) | Stage 0 (relevance) |\n| ----------------- | ---------------------------------- | ------------------------------------------------------------ |\n| Basis for keeping | position (recency) | relevance to the current request |\n| Drop granularity | whole messages / summarized ranges | whole messages |\n| Runs when | always, once over budget | decision provider configured, request known, and over budget |\n\nSee relevance-driven compaction for\nthe eligibility rules, the drop cap, and the separate summary-quality gate on\nStage 3.","hierarchy":{"lvl0":"Features","lvl1":"The `decide` inference type","lvl2":"Relevance-driven compaction","lvl3":""}},
3381
+ {"objectID":"ac97e63916f0ffdf1d9befada357186f236753d40ea1f0e97bcab715e54fa7cd","title":"Relevance-driven compaction","url":"/docs/features/decide-inference-type#relevance-driven-compaction","content":"Before the existing positional compaction stages run, an optional Stage 0\nasks, per eligible message, whether the current request still needs it — at\n~400 ms for the whole batch regardless of message count (on TypeSafe;\nperplexity-decider differs, taking about 0.3 to 1.1 s for one question and about\n65 ms for each further one, plus an input time that grows faster than linearly\nwith size; cloudflare-clef took 0.3 to 1.0 s for a small request on 2026-10-03, and its\nendpoint refuses nothing below 16,000 estimated state tokens, but a state that large takes seconds).\nOnly plain user/assistant text is eligible, the most recent messages are never\ntouched, and a message is dropped only on a confident \"no.\"\n\n| | Positional stages (1–4) | Stage 0 (relevance) |\n| ----------------- | ---------------------------------- | ------------------------------------------------------------ |\n| Basis for keeping | position (recency) | relevance to the current request |\n| Drop granularity | whole messages / summarized ranges | whole messages |\n| Runs when | always, once over budget | decision provider configured, request known, and over budget |\n\nSee relevance-driven compaction for\nthe eligibility rules, the drop cap, and the separate summary-quality gate on\nStage 3.","hierarchy":{"lvl0":"Features","lvl1":"The `decide` inference type","lvl2":"Relevance-driven compaction","lvl3":""}},
3382
3382
  {"objectID":"451d199b91f25696bed61dedb5ebc0465143dbf3bc350ca8a3943e622f9aedf8","title":"Tool / MCP routing","url":"/docs/features/decide-inference-type#tool-mcp-routing","content":"The shipped tool router asks a generative model for {servers: string[]} on\na 15-second budget — a shape that cannot express uncertainty. A decision\nmodel instead asks one yes/no question per server, answered with a probability,\nand a server is excluded only on a confident \"no\" (minDropConfidence default\n0.6), because dropping a needed server breaks the turn while keeping an unneeded\none only costs a few tokens.\n\nA measured wording change moved unrelated servers from a mean probability of\n0.31 (dropping 12 of 39 unneeded servers) to a mean of 0.03 (dropping 37 of\n39, with zero wrong drops) — seen in\ntool / MCP routing by decision model,\nwhich also covers the exact question shape and its size guards.","hierarchy":{"lvl0":"Features","lvl1":"The `decide` inference type","lvl2":"Tool / MCP routing","lvl3":""}},
3383
3383
  {"objectID":"b35e1ab2390a7b132037c293ecaf436f9ff9498591ccdd47b58ee0a6a95e7616","title":"RAG retrieval planning","url":"/docs/features/decide-inference-type#rag-retrieval-planning","content":"RAGPipelineConfig.decide lets each RAG query get its own topK/hybrid/\ngraph/rerank plan instead of one fixed configuration for every query. An\nexplicit per-call QueryOptions field always wins over the plan, and a\ncapability the pipeline wasn't configured with can never be switched on by\nit.\n\nSee per-query RAG retrieval planning\nfor the breadth rubric and why its confidence bar is deliberately lower than\ntool routing's or compaction's.","hierarchy":{"lvl0":"Features","lvl1":"The `decide` inference type","lvl2":"RAG retrieval planning","lvl3":""}},
3384
3384
  {"objectID":"e399806055971566454170aeec7214ec9b5948c8e3a35731a9c64b4ee2be7c21","title":"One funnel for all five sites","url":"/docs/features/decide-inference-type#one-funnel-for-all-five-sites","content":"Every one of those calls is stamped with a site — routing, toolRouting,\ncontextRelevance, summaryGate or ragPlan (the DecisionSite union) — and\ngoes through one private path on NeuroLink, which is also where a bound\ntryDecide() lands. For the four sites that run inside a NeuroLink request —\nrouting, toolRouting, contextRelevance and summaryGate — that path\nforwards the outer generate() / stream() call's per-call credentials,\nabortSignal and requestId (the top-level option, else\ncontext.requestId) to the decision, so a request that carries\ncredentials: { laya: {...} } routes and compacts against that account\nrather than the instance's; for routing the per-call credentials also count\ntowards the auto strategy's activation, so a host that holds no decision key\nitself still routes a request that carries one. ragPlan runs inside a\nhost-wired RAGPipeline, outside any NeuroLink request, so it receives only\nwhat the host puts on the options it hands tryDecide (see \"Host-wired\nconsumers\" below). The path also adds decision.site and\ndecision.host_question_count to the model.decision span; emits\ndecision:before / decision:after on the instance emitter; and runs the\ndecisionHooks described next. Without hooks or listeners, the decision\npayload — state and questions — is unchanged; per-call credentials are still\nforwarded, so the full request on the wire (account, base URL) can differ from\nthe instance's.","hierarchy":{"lvl0":"Features","lvl1":"The `decide` inference type","lvl2":"One funnel for all five sites","lvl3":""}},
@@ -4146,13 +4146,13 @@
4146
4146
  {"objectID":"1d8625a67cba7bc640e454fe15f76d86e2be4fbe79e9496fc085e5a6df496086","title":"Future Enhancements","url":"/docs/features/pdf-support#future-enhancements","content":"Planned features for PDF support:\nOCR Integration: Extract text from scanned PDFs\nPage Selection: Analyze specific pages only\nPDF Generation: Create PDFs from AI responses\nForm Filling: Extract and populate PDF forms","hierarchy":{"lvl0":"Features","lvl1":"PDF File Support","lvl2":"Future Enhancements","lvl3":""}},
4147
4147
  {"objectID":"20bb5119cb74199a04bebd17c621d8c6a0438c0833f12103b9f3914c5f026ceb","title":"Feedback and Support","url":"/docs/features/pdf-support#feedback-and-support","content":"Found a bug or have a feature request? Please:\nCheck existing issues on GitHub\nCreate a new issue with:\nProvider used\nPDF file details (size, pages)\nError message or unexpected behavior\nSample code (if possible)","hierarchy":{"lvl0":"Features","lvl1":"PDF File Support","lvl2":"Feedback and Support","lvl3":""}},
4148
4148
  {"objectID":"7c47c75b9023d438078ad3ed696c167cb9b5beaa369fad844635f7f32cce74a5","title":"Version 9.2.0 (Current)","url":"/docs/features/pdf-support#version-920-current","content":"✅ Initial PDF support for Vertex AI, Anthropic, Bedrock, AI Studio\n✅ Auto-detection via --file flag\n✅ Multiple PDF processing\n✅ Size and page limit validation\n✅ Comprehensive error messages\n✅ CLI and SDK integration\n✅ Streaming support\n✅ Mixed multimodal inputs (PDF + CSV + images)\n\nNext: Multimodal Chat Guide | CSV Support","hierarchy":{"lvl0":"Features","lvl1":"PDF File Support","lvl2":"Version 9.2.0 (Current)","lvl3":""}},
4149
- {"objectID":"2a46dad649fcc5c7b389d9db519211899183703302b4127f0a4a2285018e1362","title":"Per-Request Credentials","url":"/docs/features/per-request-credentials","content":"Per-Request Credentials\n\nStatus: Stable | Availability: SDK only\n\nOverview\n\nNeuroLink allows provider credentials to be supplied at two levels below the environment-variable default: on the NeuroLink constructor (instance level) and on individual generate() / stream() calls (per-call level). Credentials are resolved in the following order of precedence:\n\nThis enables multi-tenant architectures where different users or tenants supply their own provider API keys (bring-your-own-key, BYOK), without requiring separate NeuroLink instances per user or touching the process environment.\n\nTypical use cases:\nMulti-tenant SaaS — each API request carries the calling user's provider key; no shared key leakage between tenants\nBYOK products — end users paste their OpenAI / Anthropic keys in settings; you forward them to NeuroLink per call\nTesting and CI — inject credentials programmatically without setting environment variables\nProvider switching — override only the active provider's credentials while leaving others to fall through to env vars\n\nQuick Start\n\nInstance-Level vs Per-Call\n\nInstance-Level Credentials\n\nSet credentials in the NeuroLink constructor. These apply as the default for every generate() and stream() call made on that instance. Useful when serving a single tenant or when you have a known key for the duration of the instance lifecycle.\n\nPer-Call Credentials\n\nSet credentials directly on generate() or stream(). These override the instance-level credentials for that single call only. Only the providers you explicitly set are overridden — others continue falling through to instance credentials and then environment variables.\n\nPrecedence Rules\n\n| Level | Scope | Set on |\n| ----------- | --------------------- | ----------------------------------------------------------------------------------- |\n| Per-call | Single request only | generate({ credentials }), stream({ credentials }) or decide({ credentials }) |\n| Instance | All calls on instance | new NeuroLink({ credentials }) |\n| Environment | Process-wide fallback | OPENAI_API_KEY, ANTHROPIC_API_KEY, … |\n\nUnset providers at any level fall through to the next. You never need to repeat a credential at the per-call level if the instance default is correct.\n\nProvider Credential Reference\n\nAll fields are optional — omit any field you want to fall through to a lower-precedence level.\n\n| Provider | Key | Fields |\n| -------------------- | ------------------- | ---------------------------------------------------------------------------------------------------- |\n| OpenAI | openai | apiKey, baseURL |\n| Anthropic | anthropic | apiKey, oauthToken, baseURL |\n| Google AI Studio | googleAiStudio | apiKey, baseURL |\n| Google Vertex AI | vertex | projectId, location, apiKey (Express Mode), serviceAccountKey, clientEmail, privateKey |\n| Amazon Bedrock | bedrock | accessKeyId, secretAccessKey, sessionToken, region |\n| Amazon SageMaker | sagemaker | accessKeyId, secretAccessKey, sessionToken, region, endpoint |\n| Azure OpenAI | azure | apiKey, resourceName, deploymentName, apiVersion |\n| Mistral | mistral | apiKey |\n| Hugging Face | huggingFace | apiKey, baseURL |\n| OpenRouter | openrouter | apiKey, baseURL |\n| LiteLLM | litellm | apiKey, baseURL |\n| OpenAI-Compatible | openaiCompatible | apiKey, baseURL |\n| Cerebras | cerebras | apiKey, baseURL |\n| SambaNova | sambanova | apiKey, baseURL |\n| Ollama | ollama | baseURL ","hierarchy":{"lvl0":"Features","lvl1":"Per-Request Credentials","lvl2":"","lvl3":""}},
4149
+ {"objectID":"2a46dad649fcc5c7b389d9db519211899183703302b4127f0a4a2285018e1362","title":"Per-Request Credentials","url":"/docs/features/per-request-credentials","content":"Per-Request Credentials\n\nStatus: Stable | Availability: SDK only\n\nOverview\n\nNeuroLink allows provider credentials to be supplied at two levels below the environment-variable default: on the NeuroLink constructor (instance level) and on individual generate() / stream() calls (per-call level). Credentials are resolved in the following order of precedence:\n\nThis enables multi-tenant architectures where different users or tenants supply their own provider API keys (bring-your-own-key, BYOK), without requiring separate NeuroLink instances per user or touching the process environment.\n\nTypical use cases:\nMulti-tenant SaaS — each API request carries the calling user's provider key; no shared key leakage between tenants\nBYOK products — end users paste their OpenAI / Anthropic keys in settings; you forward them to NeuroLink per call\nTesting and CI — inject credentials programmatically without setting environment variables\nProvider switching — override only the active provider's credentials while leaving others to fall through to env vars\n\nQuick Start\n\nInstance-Level vs Per-Call\n\nInstance-Level Credentials\n\nSet credentials in the NeuroLink constructor. These apply as the default for every generate() and stream() call made on that instance. Useful when serving a single tenant or when you have a known key for the duration of the instance lifecycle.\n\nPer-Call Credentials\n\nSet credentials directly on generate() or stream(). These override the instance-level credentials for that single call only. Only the providers you explicitly set are overridden — others continue falling through to instance credentials and then environment variables.\n\nPrecedence Rules\n\n| Level | Scope | Set on |\n| ----------- | --------------------- | ----------------------------------------------------------------------------------- |\n| Per-call | Single request only | generate({ credentials }), stream({ credentials }) or decide({ credentials }) |\n| Instance | All calls on instance | new NeuroLink({ credentials }) |\n| Environment | Process-wide fallback | OPENAI_API_KEY, ANTHROPIC_API_KEY, … |\n\nUnset providers at any level fall through to the next. You never need to repeat a credential at the per-call level if the instance default is correct.\n\nProvider Credential Reference\n\nAll fields are optional — omit any field you want to fall through to a lower-precedence level.\n\n| Provider | Key | Fields |\n| -------------------- | ------------------- | ------------------------------------------------------------------------------------------------------------- |\n| OpenAI | openai | apiKey, baseURL |\n| Anthropic | anthropic | apiKey, oauthToken, baseURL |\n| Google AI Studio | googleAiStudio | apiKey, baseURL |\n| Google Vertex AI | vertex | projectId, location, apiKey (Express Mode), serviceAccountKey, clientEmail, privateKey, baseURL |\n| Amazon Bedrock | bedrock | accessKeyId, secretAccessKey, sessionToken, region |\n| Amazon SageMaker | sagemaker | accessKeyId, secretAccessKey, sessionToken, region, endpoint |\n| Azure OpenAI | azure | apiKey, resourceName, deploymentName, apiVersion |\n| Mistral | mistral | apiKey |\n| Hugging Face | huggingFace | apiKey, baseURL |\n| OpenRouter | openrouter | apiKey, baseURL |\n| LiteLLM | litellm | apiKey, baseURL |\n| OpenAI-Compatible | openaiCompatible | apiKey, baseURL |\n| Cerebras | cerebras | apiKey, baseURL |\n| SambaNova | sambanova | apiKey, baseURL ","hierarchy":{"lvl0":"Features","lvl1":"Per-Request Credentials","lvl2":"","lvl3":""}},
4150
4150
  {"objectID":"12291afcfaaf4af65b01b07e93a9eac08280ff7c61394f6051a86c1b152a7b4a","title":"Per-Request Credentials","url":"/docs/features/per-request-credentials#per-request-credentials","content":"Status: Stable | Availability: SDK only","hierarchy":{"lvl0":"Features","lvl1":"Per-Request Credentials","lvl2":"Per-Request Credentials","lvl3":""}},
4151
4151
  {"objectID":"6c6756b0806344240b3c86d6b0063587db50f2c4ccf936a32e87d4377b77014c","title":"Overview","url":"/docs/features/per-request-credentials#overview","content":"NeuroLink allows provider credentials to be supplied at two levels below the environment-variable default: on the NeuroLink constructor (instance level) and on individual generate() / stream() calls (per-call level). Credentials are resolved in the following order of precedence:\n\nThis enables multi-tenant architectures where different users or tenants supply their own provider API keys (bring-your-own-key, BYOK), without requiring separate NeuroLink instances per user or touching the process environment.\n\nTypical use cases:\nMulti-tenant SaaS — each API request carries the calling user's provider key; no shared key leakage between tenants\nBYOK products — end users paste their OpenAI / Anthropic keys in settings; you forward them to NeuroLink per call\nTesting and CI — inject credentials programmatically without setting environment variables\nProvider switching — override only the active provider's credentials while leaving others to fall through to env vars","hierarchy":{"lvl0":"Features","lvl1":"Per-Request Credentials","lvl2":"Overview","lvl3":""}},
4152
4152
  {"objectID":"d4e86918319aa78b4e4461dbf29a60ebe90935e74fc70617f59bf524ba3e1eae","title":"Instance-Level Credentials","url":"/docs/features/per-request-credentials#instance-level-credentials","content":"Set credentials in the NeuroLink constructor. These apply as the default for every generate() and stream() call made on that instance. Useful when serving a single tenant or when you have a known key for the duration of the instance lifecycle.","hierarchy":{"lvl0":"Features","lvl1":"Per-Request Credentials","lvl2":"Instance-Level Credentials","lvl3":""}},
4153
4153
  {"objectID":"250b1dd11e018f5f252b27ce408e3dade21eff1cf26eed4aaf81126fad6ab691","title":"Per-Call Credentials","url":"/docs/features/per-request-credentials#per-call-credentials","content":"Set credentials directly on generate() or stream(). These override the instance-level credentials for that single call only. Only the providers you explicitly set are overridden — others continue falling through to instance credentials and then environment variables.","hierarchy":{"lvl0":"Features","lvl1":"Per-Request Credentials","lvl2":"Per-Call Credentials","lvl3":""}},
4154
4154
  {"objectID":"4166cbaf6e6263ac98e24d7ede9950b44aade18e787b57e71138d2fc2deaaa07","title":"Precedence Rules","url":"/docs/features/per-request-credentials#precedence-rules","content":"| Level | Scope | Set on |\n| ----------- | --------------------- | ----------------------------------------------------------------------------------- |\n| Per-call | Single request only | generate({ credentials }), stream({ credentials }) or decide({ credentials }) |\n| Instance | All calls on instance | new NeuroLink({ credentials }) |\n| Environment | Process-wide fallback | OPENAI_API_KEY, ANTHROPIC_API_KEY, … |\n\nUnset providers at any level fall through to the next. You never need to repeat a credential at the per-call level if the instance default is correct.","hierarchy":{"lvl0":"Features","lvl1":"Per-Request Credentials","lvl2":"Precedence Rules","lvl3":""}},
4155
- {"objectID":"b739fcf7819dd6f055ebe3bcdb161ff839067dc172235f9d0072f9cf79d7bcd3","title":"Provider Credential Reference","url":"/docs/features/per-request-credentials#provider-credential-reference","content":"All fields are optional — omit any field you want to fall through to a lower-precedence level.\n\n| Provider | Key | Fields |\n| -------------------- | ------------------- | ---------------------------------------------------------------------------------------------------- |\n| OpenAI | openai | apiKey, baseURL |\n| Anthropic | anthropic | apiKey, oauthToken, baseURL |\n| Google AI Studio | googleAiStudio | apiKey, baseURL |\n| Google Vertex AI | vertex | projectId, location, apiKey (Express Mode), serviceAccountKey, clientEmail, privateKey |\n| Amazon Bedrock | bedrock | accessKeyId, secretAccessKey, sessionToken, region |\n| Amazon SageMaker | sagemaker | accessKeyId, secretAccessKey, sessionToken, region, endpoint |\n| Azure OpenAI | azure | apiKey, resourceName, deploymentName, apiVersion |\n| Mistral | mistral | apiKey |\n| Hugging Face | huggingFace | apiKey, baseURL |\n| OpenRouter | openrouter | apiKey, baseURL |\n| LiteLLM | litellm | apiKey, baseURL |\n| OpenAI-Compatible | openaiCompatible","hierarchy":{"lvl0":"Features","lvl1":"Per-Request Credentials","lvl2":"Provider Credential Reference","lvl3":""}},
4155
+ {"objectID":"b739fcf7819dd6f055ebe3bcdb161ff839067dc172235f9d0072f9cf79d7bcd3","title":"Provider Credential Reference","url":"/docs/features/per-request-credentials#provider-credential-reference","content":"All fields are optional — omit any field you want to fall through to a lower-precedence level.\n\n| Provider | Key | Fields |\n| -------------------- | ------------------- | ------------------------------------------------------------------------------------------------------------- |\n| OpenAI | openai | apiKey, baseURL |\n| Anthropic | anthropic | apiKey, oauthToken, baseURL |\n| Google AI Studio | googleAiStudio | apiKey, baseURL |\n| Google Vertex AI | vertex | projectId, location, apiKey (Express Mode), serviceAccountKey, clientEmail, privateKey, baseURL |\n| Amazon Bedrock | bedrock | accessKeyId, secretAccessKey, sessionToken, region |\n| Amazon SageMaker | sagemaker | accessKeyId, secretAccessKey, sessionToken, region, endpoint |\n| Azure OpenAI | azure | apiKey, resourceName, deploymentName, apiVersion |\n| Mistral | mistral | apiKey |\n| Hugging Face | huggingFace | apiKey, baseURL |\n| OpenRouter | openrouter | apiKey, baseURL |\n| LiteLLM | litellm | apiKey, baseURL","hierarchy":{"lvl0":"Features","lvl1":"Per-Request Credentials","lvl2":"Provider Credential Reference","lvl3":""}},
4156
4156
  {"objectID":"575e2e50c5fd00e53fce66deee556264f3df8962e2188ac446e6e7d4ad29b2ed","title":"OpenAI","url":"/docs/features/per-request-credentials#openai","content":"Custom base URL for OpenAI-compatible proxies:","hierarchy":{"lvl0":"Features","lvl1":"Per-Request Credentials","lvl2":"OpenAI","lvl3":""}},
4157
4157
  {"objectID":"499e7c1d012d337ad54e06db35770d5b3471afb0f9e3f471564642e8ba7e5c6b","title":"Anthropic","url":"/docs/features/per-request-credentials#anthropic","content":"OAuth token (Anthropic Claude subscription):\n\nA gateway or proxy in front of Anthropic (baseURL wins over ANTHROPIC_BASE_URL, with or without a trailing /v1; a gateway that does its own auth accepts any apiKey):","hierarchy":{"lvl0":"Features","lvl1":"Per-Request Credentials","lvl2":"Anthropic","lvl3":""}},
4158
4158
  {"objectID":"3f5ea871d2750f36fca227c33f109de53f5d0bc4c184ea956d0b8c3736babe29","title":"Vertex AI — Express Mode","url":"/docs/features/per-request-credentials#vertex-ai-express-mode","content":"Express Mode uses a simple API key instead of service-account credentials, making it suitable for per-request BYOK flows:\n\nFull service-account credentials (server-side only — keep private keys out of client code):","hierarchy":{"lvl0":"Features","lvl1":"Per-Request Credentials","lvl2":"Vertex AI — Express Mode","lvl3":""}},
@@ -4522,9 +4522,9 @@
4522
4522
  {"objectID":"5594cc075cbacf6979c75d68f20b45ccff0513a1e4c7087d756491900cbb1c4d","title":"Model Detection Utilities","url":"/docs/features/thinking-configuration#model-detection-utilities","content":"NeuroLink provides utilities to check thinking support:","hierarchy":{"lvl0":"Features","lvl1":"Extended Thinking Configuration","lvl2":"Model Detection Utilities","lvl3":""}},
4523
4523
  {"objectID":"559dd274be4e9bdfeabf680692f3830f92a5c13caefc42acfb819d9635f2dad7","title":"Important Notes","url":"/docs/features/thinking-configuration#important-notes","content":"Provider compatibility: Thinking configuration is provider-specific. Gemini uses thinkingLevel, Claude uses budgetTokens\nToken consumption: Extended thinking uses additional tokens beyond the response\nLatency impact: Higher thinking levels increase response time\nNot all models support thinking: Check supportsThinkingConfig() before enabling\nStreaming support: Thinking configuration works with both generate() and stream()","hierarchy":{"lvl0":"Features","lvl1":"Extended Thinking Configuration","lvl2":"Important Notes","lvl3":""}},
4524
4524
  {"objectID":"4bd3d62cf46ca16e0b9a52768c51ca4bced1f07f6c32f9a141c0cbfc599bcefb","title":"See Also","url":"/docs/features/thinking-configuration#see-also","content":"API Reference\nProvider Configuration\nStreaming","hierarchy":{"lvl0":"Features","lvl1":"Extended Thinking Configuration","lvl2":"See Also","lvl3":""}},
4525
- {"objectID":"ffa6f024a99609da8db45d9a02bc76178d7fac894f00af93b830f9b356e86f3c","title":"Tool / MCP routing by decision model","url":"/docs/features/tool-routing-decision-model","content":"Tool / MCP routing by decision model\n\nThe shipped tool router asks a generative model for {servers: string[]} on\na 15-second budget. That shape cannot express uncertainty — a server is in\nthe list or it is not, and the only recourse for a model that is unsure is to\ninclude it. A decision model instead\nasks one calibrated yes/no question per server, in a single round trip of\nabout 400ms and $0.00002 on TypeSafe (on Perplexity each further question adds\nabout 65 ms, up to 128 in a request; see\nits guide; on\nCloudflare Clef a request takes up to 64 questions, and tryDecide() splits a\nlarger set into batches of 64; see\nits guide), and each\nanswer comes back with a real probability rather than a name that either did or\ndidn't make a list.\n\nThe degradation contract. selectServersByDecision() is used only when a\ndecision provider is configured; hosts never wire decideFn by hand — it is\nbound automatically wherever tool routing resolves, using the same\ntryDecide() that returns null on any failure or absent configuration. No\ndecision provider, a failed call, fewer than two candidate servers, or an\nanswer set that would drop nothing — any of these fall straight through to\nthe existing generative router, unchanged.\n\nOne question per server\n\nEach routable server gets its own boolean question, built from its\ndescription (or, absent one, its tool names):\n\nA server is excluded only on a confident false — minDropConfidence\ndefaults to 0.6. undefined (unanswered, malformed, or too close to a\ncoin flip) and a confident true both keep the server. This is the same\nasymmetry as the classifier's upgrade/downgrade bars: keeping an unneeded\nserver costs a few hundred tokens of tool definitions; dropping a needed one\nbreaks the turn outright, because the model can never call a tool it was\nnever shown and has no way to ask for it back.\n\nTwo size guards bound the request: at most 200 servers are asked about\nin one batch (MAX_SERVERS), and the query text sent as state is capped at\n10,000 characters. Servers past the cap are never asked about and are\ntherefore always kept — a server that was not offered to the model must\nnever be silently dropped by its own absence from the question set.\n\nThe Cloudflare Clef endpoint ignores state text past about 2,048 tokens, and\nNeuroLink refuses a state it estimates at more than 1,500 tokens with\nmax_tokens_exceeded. A query long enough to be estimated above that is refused,\nand routing falls through to the generative router, as it does on any failure.\n\nThe wording that made this work: a measured A/B result\n\nThe first phrasing tried was the obvious one: \"answering this request will\nrequire calling at least one tool from this server,\" with false meaning\n\"this server is unrelated, OR the request needs no tool at all.\" Measured\nagainst a 10-request × 5-server labelled set, it separated correctly but\nweakly — unrelated servers averaged p = 0.31 and reached as high as\n0.80, so at the 0.6 drop bar only 12 of 39 unneeded servers were\nactually dropped.\n\nThree changes fixed it: naming the server explicitly, asking in the present\ntense about what carrying out the request involves rather than what\n\"will require,\" and splitting the bundled false criterion (which was\nreally two separate claims joined by \"or\") into one single claim. That\nmoved unrelated servers to a mean of p = 0.03 with a maximum of 0.35\n— 37 of 39 dropped at the same 0.6 bar, still with zero wrong drops.\n\nThe lesson generalises past this one question: a decision model reads\nliterally, and an \"or\" in a criterion is two questions wearing one coat. Each\nhalf of a compound criterion pulls the answer toward the middle whenever\nonly one half is true, which is exactly the muddy, hard-to-gate signal the\nfirst version produced.\n\nWhat this is bad at\nIt reasons about servers, not individual tools. The unit of decision is\n a whole MCP server; a server with twenty tools where the request needs one\n is kept or dropped as a unit, not tool-by-tool.\nThe description quality bounds the question quality. A server with no\n declared description falls back to a comma-joined list of its own tool\n names, which carries much less signal than a well-written one-line\n description — the wording fix above only helps once the server's own text\n is legible to a literal reader.\nA close call still resolves to \"keep.\" There is no partial exclusion;\n anything from a coin flip up to just under 0.6 confidence is treated\n identically to a confident true.\nIt shares the base model's general limits — literal reading, no\n arithmetic, accuracy sensitive to a noisy or oversized state — all\n described in\n what decide is bad at.\nThe query is untrusted input sent as state, and this module does not\n sanitize it. The blast radius is deliberately bounded instead: server ids\n are never read back off the wire (answers are matched by position, not by\n name), so the worst a crafted query can do is keep more already-registered\n servers than necessary — it cannot register a server that ","hierarchy":{"lvl0":"Features","lvl1":"Tool / MCP routing by decision model","lvl2":"","lvl3":""}},
4525
+ {"objectID":"ffa6f024a99609da8db45d9a02bc76178d7fac894f00af93b830f9b356e86f3c","title":"Tool / MCP routing by decision model","url":"/docs/features/tool-routing-decision-model","content":"Tool / MCP routing by decision model\n\nThe shipped tool router asks a generative model for {servers: string[]} on\na 15-second budget. That shape cannot express uncertainty — a server is in\nthe list or it is not, and the only recourse for a model that is unsure is to\ninclude it. A decision model instead\nasks one calibrated yes/no question per server, in a single round trip of\nabout 400ms and $0.00002 on TypeSafe (on Perplexity each further question adds\nabout 65 ms, up to 128 in a request; see\nits guide; on\nCloudflare Clef a request takes up to 64 questions, and tryDecide() splits a\nlarger set into batches of 64; see\nits guide), and each\nanswer comes back with a real probability rather than a name that either did or\ndidn't make a list.\n\nThe degradation contract. selectServersByDecision() is used only when a\ndecision provider is configured; hosts never wire decideFn by hand — it is\nbound automatically wherever tool routing resolves, using the same\ntryDecide() that returns null on any failure or absent configuration. No\ndecision provider, a failed call, fewer than two candidate servers, or an\nanswer set that would drop nothing — any of these fall straight through to\nthe existing generative router, unchanged.\n\nOne question per server\n\nEach routable server gets its own boolean question, built from its\ndescription (or, absent one, its tool names):\n\nA server is excluded only on a confident false — minDropConfidence\ndefaults to 0.6. undefined (unanswered, malformed, or too close to a\ncoin flip) and a confident true both keep the server. This is the same\nasymmetry as the classifier's upgrade/downgrade bars: keeping an unneeded\nserver costs a few hundred tokens of tool definitions; dropping a needed one\nbreaks the turn outright, because the model can never call a tool it was\nnever shown and has no way to ask for it back.\n\nTwo size guards bound the request: at most 200 servers are asked about\nin one batch (MAX_SERVERS), and the query text sent as state is capped at\n10,000 characters. Servers past the cap are never asked about and are\ntherefore always kept — a server that was not offered to the model must\nnever be silently dropped by its own absence from the question set.\n\nNeuroLink refuses a state it estimates at more than 16,000 tokens with\nmax_tokens_exceeded. A query long enough to be estimated above that is refused,\nand routing falls through to the generative router, as it does on any failure.\n\nThe wording that made this work: a measured A/B result\n\nThe first phrasing tried was the obvious one: \"answering this request will\nrequire calling at least one tool from this server,\" with false meaning\n\"this server is unrelated, OR the request needs no tool at all.\" Measured\nagainst a 10-request × 5-server labelled set, it separated correctly but\nweakly — unrelated servers averaged p = 0.31 and reached as high as\n0.80, so at the 0.6 drop bar only 12 of 39 unneeded servers were\nactually dropped.\n\nThree changes fixed it: naming the server explicitly, asking in the present\ntense about what carrying out the request involves rather than what\n\"will require,\" and splitting the bundled false criterion (which was\nreally two separate claims joined by \"or\") into one single claim. That\nmoved unrelated servers to a mean of p = 0.03 with a maximum of 0.35\n— 37 of 39 dropped at the same 0.6 bar, still with zero wrong drops.\n\nThe lesson generalises past this one question: a decision model reads\nliterally, and an \"or\" in a criterion is two questions wearing one coat. Each\nhalf of a compound criterion pulls the answer toward the middle whenever\nonly one half is true, which is exactly the muddy, hard-to-gate signal the\nfirst version produced.\n\nWhat this is bad at\nIt reasons about servers, not individual tools. The unit of decision is\n a whole MCP server; a server with twenty tools where the request needs one\n is kept or dropped as a unit, not tool-by-tool.\nThe description quality bounds the question quality. A server with no\n declared description falls back to a comma-joined list of its own tool\n names, which carries much less signal than a well-written one-line\n description — the wording fix above only helps once the server's own text\n is legible to a literal reader.\nA close call still resolves to \"keep.\" There is no partial exclusion;\n anything from a coin flip up to just under 0.6 confidence is treated\n identically to a confident true.\nIt shares the base model's general limits — literal reading, no\n arithmetic, accuracy sensitive to a noisy or oversized state — all\n described in\n what decide is bad at.\nThe query is untrusted input sent as state, and this module does not\n sanitize it. The blast radius is deliberately bounded instead: server ids\n are never read back off the wire (answers are matched by position, not by\n name), so the worst a crafted query can do is keep more already-registered\n servers than necessary — it cannot register a server that wasn't already\n configured.\n\nSee also\nThe decide inference type\nModel routi","hierarchy":{"lvl0":"Features","lvl1":"Tool / MCP routing by decision model","lvl2":"","lvl3":""}},
4526
4526
  {"objectID":"4b84d2a2ea7a8b34624599647a02792ace2fc30650e5bb5d3da1ea68e46fdad8","title":"Tool / MCP routing by decision model","url":"/docs/features/tool-routing-decision-model#tool-mcp-routing-by-decision-model","content":"The shipped tool router asks a generative model for {servers: string[]} on\na 15-second budget. That shape cannot express uncertainty — a server is in\nthe list or it is not, and the only recourse for a model that is unsure is to\ninclude it. A decision model instead\nasks one calibrated yes/no question per server, in a single round trip of\nabout 400ms and $0.00002 on TypeSafe (on Perplexity each further question adds\nabout 65 ms, up to 128 in a request; see\nits guide; on\nCloudflare Clef a request takes up to 64 questions, and tryDecide() splits a\nlarger set into batches of 64; see\nits guide), and each\nanswer comes back with a real probability rather than a name that either did or\ndidn't make a list.\n\nThe degradation contract. selectServersByDecision() is used only when a\ndecision provider is configured; hosts never wire decideFn by hand — it is\nbound automatically wherever tool routing resolves, using the same\ntryDecide() that returns null on any failure or absent configuration. No\ndecision provider, a failed call, fewer than two candidate servers, or an\nanswer set that would drop nothing — any of these fall straight through to\nthe existing generative router, unchanged.","hierarchy":{"lvl0":"Features","lvl1":"Tool / MCP routing by decision model","lvl2":"Tool / MCP routing by decision model","lvl3":""}},
4527
- {"objectID":"0b9203bc3ddca1d61b578f4bea25de508f6a241da96f270ca4742163bd99884a","title":"One question per server","url":"/docs/features/tool-routing-decision-model#one-question-per-server","content":"Each routable server gets its own boolean question, built from its\ndescription (or, absent one, its tool names):\n\nA server is excluded only on a confident false — minDropConfidence\ndefaults to 0.6. undefined (unanswered, malformed, or too close to a\ncoin flip) and a confident true both keep the server. This is the same\nasymmetry as the classifier's upgrade/downgrade bars: keeping an unneeded\nserver costs a few hundred tokens of tool definitions; dropping a needed one\nbreaks the turn outright, because the model can never call a tool it was\nnever shown and has no way to ask for it back.\n\nTwo size guards bound the request: at most 200 servers are asked about\nin one batch (MAX_SERVERS), and the query text sent as state is capped at\n10,000 characters. Servers past the cap are never asked about and are\ntherefore always kept — a server that was not offered to the model must\nnever be silently dropped by its own absence from the question set.\n\nThe Cloudflare Clef endpoint ignores state text past about 2,048 tokens, and\nNeuroLink refuses a state it estimates at more than 1,500 tokens with\nmax_tokens_exceeded. A query long enough to be estimated above that is refused,\nand routing falls through to the generative router, as it does on any failure.","hierarchy":{"lvl0":"Features","lvl1":"Tool / MCP routing by decision model","lvl2":"One question per server","lvl3":""}},
4527
+ {"objectID":"0b9203bc3ddca1d61b578f4bea25de508f6a241da96f270ca4742163bd99884a","title":"One question per server","url":"/docs/features/tool-routing-decision-model#one-question-per-server","content":"Each routable server gets its own boolean question, built from its\ndescription (or, absent one, its tool names):\n\nA server is excluded only on a confident false — minDropConfidence\ndefaults to 0.6. undefined (unanswered, malformed, or too close to a\ncoin flip) and a confident true both keep the server. This is the same\nasymmetry as the classifier's upgrade/downgrade bars: keeping an unneeded\nserver costs a few hundred tokens of tool definitions; dropping a needed one\nbreaks the turn outright, because the model can never call a tool it was\nnever shown and has no way to ask for it back.\n\nTwo size guards bound the request: at most 200 servers are asked about\nin one batch (MAX_SERVERS), and the query text sent as state is capped at\n10,000 characters. Servers past the cap are never asked about and are\ntherefore always kept — a server that was not offered to the model must\nnever be silently dropped by its own absence from the question set.\n\nNeuroLink refuses a state it estimates at more than 16,000 tokens with\nmax_tokens_exceeded. A query long enough to be estimated above that is refused,\nand routing falls through to the generative router, as it does on any failure.","hierarchy":{"lvl0":"Features","lvl1":"Tool / MCP routing by decision model","lvl2":"One question per server","lvl3":""}},
4528
4528
  {"objectID":"19352c9bf82d208bbd76e4303e3e35ac7d4f7497562a4f1ee006d8cf1fae5f6b","title":"The wording that made this work: a measured A/B result","url":"/docs/features/tool-routing-decision-model#the-wording-that-made-this-work-a-measured-ab-result","content":"The first phrasing tried was the obvious one: \"answering this request will\nrequire calling at least one tool from this server,\" with false meaning\n\"this server is unrelated, OR the request needs no tool at all.\" Measured\nagainst a 10-request × 5-server labelled set, it separated correctly but\nweakly — unrelated servers averaged p = 0.31 and reached as high as\n0.80, so at the 0.6 drop bar only 12 of 39 unneeded servers were\nactually dropped.\n\nThree changes fixed it: naming the server explicitly, asking in the present\ntense about what carrying out the request involves rather than what\n\"will require,\" and splitting the bundled false criterion (which was\nreally two separate claims joined by \"or\") into one single claim. That\nmoved unrelated servers to a mean of p = 0.03 with a maximum of 0.35\n— 37 of 39 dropped at the same 0.6 bar, still with zero wrong drops.\n\nThe lesson generalises past this one question: a decision model reads\nliterally, and an \"or\" in a criterion is two questions wearing one coat. Each\nhalf of a compound criterion pulls the answer toward the middle whenever\nonly one half is true, which is exactly the muddy, hard-to-gate signal the\nfirst version produced.","hierarchy":{"lvl0":"Features","lvl1":"Tool / MCP routing by decision model","lvl2":"The wording that made this work: a measured A/B result","lvl3":""}},
4529
4529
  {"objectID":"9c9af1c1ff58051674501cb10c371fdcf50758c935a2dfa168df9719969bb7af","title":"What this is bad at","url":"/docs/features/tool-routing-decision-model#what-this-is-bad-at","content":"It reasons about servers, not individual tools. The unit of decision is\n a whole MCP server; a server with twenty tools where the request needs one\n is kept or dropped as a unit, not tool-by-tool.\nThe description quality bounds the question quality. A server with no\n declared description falls back to a comma-joined list of its own tool\n names, which carries much less signal than a well-written one-line\n description — the wording fix above only helps once the server's own text\n is legible to a literal reader.\nA close call still resolves to \"keep.\" There is no partial exclusion;\n anything from a coin flip up to just under 0.6 confidence is treated\n identically to a confident true.\nIt shares the base model's general limits — literal reading, no\n arithmetic, accuracy sensitive to a noisy or oversized state — all\n described in\n what decide is bad at.\nThe query is untrusted input sent as state, and this module does not\n sanitize it. The blast radius is deliberately bounded instead: server ids\n are never read back off the wire (answers are matched by position, not by\n name), so the worst a crafted query can do is keep more already-registered\n servers than necessary — it cannot register a server that wasn't already\n configured.","hierarchy":{"lvl0":"Features","lvl1":"Tool / MCP routing by decision model","lvl2":"What this is bad at","lvl3":""}},
4530
4530
  {"objectID":"b55a36dccb54a184ce24fa850942a8f5455cbe7f4391a23fc94f326aebeae19e","title":"See also","url":"/docs/features/tool-routing-decision-model#see-also","content":"The decide inference type\nModel routing with a decision model\nRelevance-driven compaction","hierarchy":{"lvl0":"Features","lvl1":"Tool / MCP routing by decision model","lvl2":"See also","lvl3":""}},
@@ -5658,23 +5658,23 @@
5658
5658
  {"objectID":"5862cb134695d7821bb2656e8d0c7c1ffee1ff3f295c36858f60fa939ba2facd","title":"Verification status","url":"/docs/getting-started/providers/chutes#verification-status","content":"Tier-2 onboarding normally requires a live-key capability sweep\n(docs/provider-integration/tiers/tier-2-catalog-entry.md,\n\"Live verification\"), gated by pnpm run verify:provider-onboarding. This\nentry was added under a credential-free onboarding pass instead: no\nChutes API key was ever created or used, and no authenticated or POST\nrequest was sent to any Chutes endpoint. Everything below is either a public\ndocument or a single unauthenticated GET.\n\n| Probe | Result |\n| ------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |\n| Roster | Unauthenticated GET https://llm.chutes.ai/v1/models, HTTP 200, 14 models, re-run 2026-09-28. /v1/models is itself documented by Chutes as a \"public catalog (no key required).\" |\n| Wire shape | Chutes' own homepage Python sample posts to https://llm.chutes.ai/v1/chat/completions with model + messages + Authorization: Bearer $CHUTES_API_KEY + stream: true — never executed here, only read. |\n| Tools / structured output | Confirmed from docs only: the \"Function Calling, Agents, and Tool Use\" guide shows OpenAI-shaped tools/tool_choice/tool_call_id, and the same guide shows a separate response_format: {\"type\": \"json_object\"} JSON-mode example.","hierarchy":{"lvl0":"Getting Started","lvl1":"Chutes Provider Guide","lvl2":"Verification status","lvl3":""}},
5659
5659
  {"objectID":"34c0be7e44128ded319ab20090fe5bfecd98725996a4350660f6dad0932a5601","title":"Troubleshooting","url":"/docs/getting-started/providers/chutes#troubleshooting","content":"| Symptom | Cause | Fix |\n| ---------------------------------------------------------- | ------------------------------------------------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| Requests hit an anonymous rate limit (HTTP 429) | No token, or an invalid token, was sent | Set CHUTES_API_KEY, and send it as Authorization: Bearer <key> — X-API-Key is documented as unsupported for inference calls |\n| Model not found | The roster changed since 2026-09-28 | Pick a current id from the unauthenticated GET /v1/models roster |\n| Structured output silently dropped when tools are used | structuredOutputWithTools is false — no combined probe was possible | This is intentional pending a live-key check, not a bug; NeuroLink's runtime conflict retry drops structured output and retries rather than losing the turn |\n| Unsure whether a specific model supports tools / JSON mode | capabilities.tools is \"model-dependent\" — two roster ids ship no supported_features at all | Check the model's entry in GET /v1/models, or consult the Models table above |","hierarchy":{"lvl0":"Getting Started","lvl1":"Chutes Provider Guide","lvl2":"Troubleshooting","lvl3":""}},
5660
5660
  {"objectID":"f743dd0fbfd3517546cecc2240a8513ad5a47938ceae45eec2ad4fe45aa06d9f","title":"See also","url":"/docs/getting-started/providers/chutes#see-also","content":"Provider setup overview\nAll providers\nTier-2 onboarding — how this provider's JSON becomes a working integration, and what live verification still needs to happen\nProvider feature compatibility","hierarchy":{"lvl0":"Getting Started","lvl1":"Chutes Provider Guide","lvl2":"See also","lvl3":""}},
5661
- {"objectID":"1fb3d0f4a1510905b14436d78a4928a8e825b3dbdb324b6cb7c9a340e088d0f6","title":"Cloudflare Clef Provider Guide","url":"/docs/getting-started/providers/cloudflare-clef","content":"Cloudflare Clef Provider Guide\n\nA provider of decide — the same typed boolean / choice / score\nanswers as TypeSafe's Jev, Laya, XOR and\nPerplexity, from Cloudflare's Clef models on Workers\nAI, and it also reads images. It emits no text at all.\n\nThis is not the Cloudflare Workers AI text provider\n(cloudflare, which runs chat models). The two are separate providers that\nread the same CLOUDFLARE_API_KEY and CLOUDFLARE_ACCOUNT_ID; see\nOne token, two providers.\n\nRead Limits before you rely on it. Workers AI reads only about\nthe first 2,048 tokens of the state, far less than the 64K context Cloudflare\ndocuments, and ignores text past that point without an error (hosted service\nor model: unknown). NeuroLink refuses a state it\nestimates as longer than that rather than let a decision be made on text the\nmodel never saw.\n\nOverview\n\nClef is a decision model: it reads a state and a set of typed questions and\nreturns a probability for every allowed answer, with no free-form text and no\nreasoning tokens to wait for. Cloudflare publishes two sizes, clef (27B) and\nclef-flash (9B), and says it is releasing their weights under the Apache 2.0\nlicense. Both answered in about a second from a developer machine. Cloudflare's\npages call them available, and do not say whether they are generally available\nor in beta.\n\nKey Facts\n\n| | |\n| ----------------------- | ----------------------------------------------------------------------------------------------------------------------------------- |\n| Provider id | cloudflare-clef |\n| Models | clef (27B, the default) and clef-flash (9B). @cf/cloudflare/clef and @cf/cloudflare/clef-flash are accepted too |\n| Question types | boolean (sent as noul), choice (2 to 255 options), score (2 to 10 levels) |\n| Questions per request | 64 |\n| Images | up to 4 per request: PNG, JPEG or WebP. No video |\n| State | Workers AI reads about the first 2,048 tokens; NeuroLink refuses a state it estimates at more than 1,500 |\n| Request size | 256,000 bytes in NeuroLink, base64 image data included |\n| Endpoint | https://api.cloudflare.com/client/v4/accounts/<account id>/ai/run/@cf/cloudflare/<model> |\n| Credentials | an API token with Workers AI permission, and the account id |\n| Price | $0.24 per million input tokens for clef, $0.09 for clef-flash; no output price is listed (Cloudflare's Workers AI pricing page) |\n| Measured latency | 2026-10-03: 0.3 to 1.0 s for a small request; 64 questions: 1.1 s (clef-flash), 1.3 s (clef); 2026-10-04: 1.5 s / 2.3 s |\n| Default decide provider | last, after TypeSafe, Laya, XOR and Perplexity |\n| Verified live | 2026-10-03 and 2026-10-04, with a real account (see Limits) |\n\nQuick Start\nGet a token and your account id\n\nCreate an API token with the Workers AI: Read + Write permission at\ndash.cloudflare.com/profile/api-tokens, and copy your account id from\nthe dashboard URL or the \"Account ID\" panel.\nConfigure\n\nOr pass them in code, which wins over the environment:\n\nBoth the token and the account id are needed: the account id is part of the\nroute, so a token alone does not count as configured.\nUse it\n\nThe figures in the comments are what a live call to clef returned for this\nexample on 2026-10-03, rounded; clef-flash answered the same example with\n0.96, 0.82 and 0.50, 2.72. Pick the faster model for one call with\nmodel: \"clef-flash\".\n\nFrom the CLI\n\nImages\n\nPass up to four images beside the state, as a Buffer, a file path or a\ndata:image/…;base64, URL; an http(s) URL is refused. PNG, JPEG and WebP are\nread; image/jpg is accepted as a JPEG alias and sent as image/jpeg. Other formats are refused before they are sent.\nThey travel in their own images array, not inside the state. Cloudflare\n places them before the state.\nThe Workers AI API accepts no video. Its model page says it does, but the API refuses\n a video and has no field for one, so NeuroLink refuses a video too.\nPixels: Cloudflare documents 16 megapixels an image. 16.00 megapixe","hierarchy":{"lvl0":"Getting Started","lvl1":"Cloudflare Clef Provider Guide","lvl2":"","lvl3":""}},
5662
- {"objectID":"eebb9363ccd61130d0be9464df57f02fd61d00b6ff81821dd3162c030c0bc0db","title":"Cloudflare Clef Provider Guide","url":"/docs/getting-started/providers/cloudflare-clef#cloudflare-clef-provider-guide","content":"A provider of decide — the same typed boolean / choice / score\nanswers as TypeSafe's Jev, Laya, XOR and\nPerplexity, from Cloudflare's Clef models on Workers\nAI, and it also reads images. It emits no text at all.\n\nThis is not the Cloudflare Workers AI text provider\n(cloudflare, which runs chat models). The two are separate providers that\nread the same CLOUDFLARE_API_KEY and CLOUDFLARE_ACCOUNT_ID; see\nOne token, two providers.\n\nRead Limits before you rely on it. Workers AI reads only about\nthe first 2,048 tokens of the state, far less than the 64K context Cloudflare\ndocuments, and ignores text past that point without an error (hosted service\nor model: unknown). NeuroLink refuses a state it\nestimates as longer than that rather than let a decision be made on text the\nmodel never saw.","hierarchy":{"lvl0":"Getting Started","lvl1":"Cloudflare Clef Provider Guide","lvl2":"Cloudflare Clef Provider Guide","lvl3":""}},
5661
+ {"objectID":"1fb3d0f4a1510905b14436d78a4928a8e825b3dbdb324b6cb7c9a340e088d0f6","title":"Cloudflare Clef Provider Guide","url":"/docs/getting-started/providers/cloudflare-clef","content":"Cloudflare Clef Provider Guide\n\nA provider of decide — the same typed boolean / choice / score\nanswers as TypeSafe's Jev, Laya, XOR and\nPerplexity, from Cloudflare's Clef models on Workers\nAI, and it also reads images. It emits no text at all.\n\nThis is not the Cloudflare Workers AI text provider\n(cloudflare, which runs chat models). The two are separate providers that\nread the same CLOUDFLARE_API_KEY and CLOUDFLARE_ACCOUNT_ID; see\nOne token, two providers.\n\nRead Limits before you rely on it. Workers AI's state window\nchanged in October 2026 (hosted service or model: unknown). Until 2026-10-04 it\nread only about the first 2,048 tokens of the state, far less than the 64K\ncontext Cloudflare documents, and ignored the rest without an error; on\n2026-10-07 it read states of at least 190,153 tokens (clef-flash) and 52,154\n(clef). NeuroLink refuses a state it estimates at more than 16,000 tokens,\ninside what was read in full, and a longer wait than a fail-open feature can\nafford.\n\nOverview\n\nClef is a decision model: it reads a state and a set of typed questions and\nreturns a probability for every allowed answer, with no free-form text and no\nreasoning tokens to wait for. Cloudflare publishes two sizes, clef (27B) and\nclef-flash (9B), and says it is releasing their weights under the Apache 2.0\nlicense. Both answered in about a second from a developer machine. Cloudflare's\npages call them available, and do not say whether they are generally available\nor in beta.\n\nKey Facts\n\n| | |\n| ----------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| Provider id | cloudflare-clef |\n| Models | clef (27B, the default) and clef-flash (9B). @cf/cloudflare/clef and @cf/cloudflare/clef-flash are accepted too |\n| Question types | boolean (sent as noul), choice (2 to 255 options), score (2 to 10 levels) |\n| Questions per request | 64 |\n| Images | up to 4 per request: PNG, JPEG or WebP. No video |\n| State | read in full up to at least 190,153 tokens (clef-flash) and 52,154 (clef) on 2026-10-07; about 2,048 until 2026-10-04. NeuroLink refuses a state it estimates at more than 16,000 |\n| Request size | 256,000 bytes in NeuroLink, base64 image data included |\n| Endpoint | https://api.cloudflare.com/client/v4/accounts/<account id>/ai/run/@cf/cloudflare/<model> |\n| Credentials | an API token with Workers AI permission, and the account id |\n| Price | $0.24 per million input tokens for clef, $0.09 for clef-flash; no output price is listed (Cloudflare's Workers AI pricing page) |\n| Measured latency | 2026-10-03: 0.3 to 1.0 s for a small request; 64 questions: 1.1 s (clef-flash), 1.3 s (clef); 2026-10-04: 1.5 s / 2.3 s |\n| Default decide provider | last, after TypeSafe, Laya, XOR and Perplexity |\n| Verified live | 2026-10-03 and 2026-10-04, with a real account (see Limits) |\n\nQuick Start\nGet a token and your account id\n\nCreate an API token with the Workers AI: Read + Write permission at\ndash.cloudflare.com/profile/api-tokens, and copy your account id from\nthe dashboard URL or the \"Account ID\" panel.\nConfigure\n\nOr pass them in code, which wins over the environment:\n\nBoth the token and the account id are needed: the account id is part of the\nro","hierarchy":{"lvl0":"Getting Started","lvl1":"Cloudflare Clef Provider Guide","lvl2":"","lvl3":""}},
5662
+ {"objectID":"eebb9363ccd61130d0be9464df57f02fd61d00b6ff81821dd3162c030c0bc0db","title":"Cloudflare Clef Provider Guide","url":"/docs/getting-started/providers/cloudflare-clef#cloudflare-clef-provider-guide","content":"A provider of decide — the same typed boolean / choice / score\nanswers as TypeSafe's Jev, Laya, XOR and\nPerplexity, from Cloudflare's Clef models on Workers\nAI, and it also reads images. It emits no text at all.\n\nThis is not the Cloudflare Workers AI text provider\n(cloudflare, which runs chat models). The two are separate providers that\nread the same CLOUDFLARE_API_KEY and CLOUDFLARE_ACCOUNT_ID; see\nOne token, two providers.\n\nRead Limits before you rely on it. Workers AI's state window\nchanged in October 2026 (hosted service or model: unknown). Until 2026-10-04 it\nread only about the first 2,048 tokens of the state, far less than the 64K\ncontext Cloudflare documents, and ignored the rest without an error; on\n2026-10-07 it read states of at least 190,153 tokens (clef-flash) and 52,154\n(clef). NeuroLink refuses a state it estimates at more than 16,000 tokens,\ninside what was read in full, and a longer wait than a fail-open feature can\nafford.","hierarchy":{"lvl0":"Getting Started","lvl1":"Cloudflare Clef Provider Guide","lvl2":"Cloudflare Clef Provider Guide","lvl3":""}},
5663
5663
  {"objectID":"d3aa34515e7690cc133be051b57b7fda1e8fdd225ef0dd7a162d91ee2ffa91d8","title":"Overview","url":"/docs/getting-started/providers/cloudflare-clef#overview","content":"Clef is a decision model: it reads a state and a set of typed questions and\nreturns a probability for every allowed answer, with no free-form text and no\nreasoning tokens to wait for. Cloudflare publishes two sizes, clef (27B) and\nclef-flash (9B), and says it is releasing their weights under the Apache 2.0\nlicense. Both answered in about a second from a developer machine. Cloudflare's\npages call them available, and do not say whether they are generally available\nor in beta.","hierarchy":{"lvl0":"Getting Started","lvl1":"Cloudflare Clef Provider Guide","lvl2":"Overview","lvl3":""}},
5664
- {"objectID":"babb1678dd2f0f63c1db8cf3e5216f3ac6b22a00331fe49058519957948ca5fb","title":"Key Facts","url":"/docs/getting-started/providers/cloudflare-clef#key-facts","content":"| | |\n| ----------------------- | ----------------------------------------------------------------------------------------------------------------------------------- |\n| Provider id | cloudflare-clef |\n| Models | clef (27B, the default) and clef-flash (9B). @cf/cloudflare/clef and @cf/cloudflare/clef-flash are accepted too |\n| Question types | boolean (sent as noul), choice (2 to 255 options), score (2 to 10 levels) |\n| Questions per request | 64 |\n| Images | up to 4 per request: PNG, JPEG or WebP.","hierarchy":{"lvl0":"Getting Started","lvl1":"Cloudflare Clef Provider Guide","lvl2":"Key Facts","lvl3":""}},
5664
+ {"objectID":"babb1678dd2f0f63c1db8cf3e5216f3ac6b22a00331fe49058519957948ca5fb","title":"Key Facts","url":"/docs/getting-started/providers/cloudflare-clef#key-facts","content":"| | |\n| ----------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| Provider id | cloudflare-clef |\n| Models | clef (27B, the default) and clef-flash (9B). @cf/cloudflare/clef and @cf/cloudflare/clef-flash are accepted too |\n| Question types | boolean (sent as noul), choice (2 to 255 options), score (2 to 10 levels) |\n| Questions per request | 64 |\n| Images | up to 4 per request: PNG, JPEG or WebP. No video |\n| State | read in full up to at least 190,153 tokens (clef-flash) and 52,154 (clef) on 2026-10-07; about 2,048 until 2026-10-04.","hierarchy":{"lvl0":"Getting Started","lvl1":"Cloudflare Clef Provider Guide","lvl2":"Key Facts","lvl3":""}},
5665
5665
  {"objectID":"5f8fca781ea20214c667a17eb2e49fc41c5a9187b58b202f67758f2bfc581c4e","title":"1. Get a token and your account id","url":"/docs/getting-started/providers/cloudflare-clef#1-get-a-token-and-your-account-id","content":"Create an API token with the Workers AI: Read + Write permission at\ndash.cloudflare.com/profile/api-tokens, and copy your account id from\nthe dashboard URL or the \"Account ID\" panel.","hierarchy":{"lvl0":"Getting Started","lvl1":"Cloudflare Clef Provider Guide","lvl2":"1. Get a token and your account id","lvl3":""}},
5666
5666
  {"objectID":"592a6f5702dc95c7cba68e1233dc74e8d60465eb77496a4313b4a096757237b3","title":"2. Configure","url":"/docs/getting-started/providers/cloudflare-clef#2-configure","content":"`bash","hierarchy":{"lvl0":"Getting Started","lvl1":"Cloudflare Clef Provider Guide","lvl2":"2. Configure","lvl3":""}},
5667
5667
  {"objectID":"de4ffe6ae22db4a0719caae8e38b4a0a8a438224c94701a762c9e1f4cc209393","title":"Optional","url":"/docs/getting-started/providers/cloudflare-clef#optional","content":"typescript\n\nconst neurolink = new NeuroLink({\n credentials: {\n cloudflareClef: { apiKey: \"…\", accountId: \"…\" }, // baseURL is optional\n },\n});\n`\n\nBoth the token and the account id are needed: the account id is part of the\nroute, so a token alone does not count as configured.","hierarchy":{"lvl0":"Getting Started","lvl1":"Cloudflare Clef Provider Guide","lvl2":"Optional","lvl3":""}},
5668
5668
  {"objectID":"0b26521b87bd72415fe58482c8628d4c3d04a49575ca2e89a55f29cf65834ccc","title":"3. Use it","url":"/docs/getting-started/providers/cloudflare-clef#3-use-it","content":"The figures in the comments are what a live call to clef returned for this\nexample on 2026-10-03, rounded; clef-flash answered the same example with\n0.96, 0.82 and 0.50, 2.72. Pick the faster model for one call with\nmodel: \"clef-flash\".","hierarchy":{"lvl0":"Getting Started","lvl1":"Cloudflare Clef Provider Guide","lvl2":"3. Use it","lvl3":""}},
5669
5669
  {"objectID":"251d84b27d167ed1d24cad4c91fb45246bf057457ea226ad977f4e581af03d28","title":"Images","url":"/docs/getting-started/providers/cloudflare-clef#images","content":"Pass up to four images beside the state, as a Buffer, a file path or a\ndata:image/…;base64, URL; an http(s) URL is refused. PNG, JPEG and WebP are\nread; image/jpg is accepted as a JPEG alias and sent as image/jpeg. Other formats are refused before they are sent.\nThey travel in their own images array, not inside the state. Cloudflare\n places them before the state.\nThe Workers AI API accepts no video. Its model page says it does, but the API refuses\n a video and has no field for one, so NeuroLink refuses a video too.\nPixels: Cloudflare documents 16 megapixels an image. 16.00 megapixels were\n accepted (4096 × 3900 at 15.97 MP, 8000 × 2000 and 16000 × 1000 at 16.00 MP);\n 16.38 megapixels (4096 × 4000) were refused with a 422. The limit is on the\n pixel count, not on either side.\nCost: an image costs at most about 1,000 input tokens however large it is.\n A test request with one 512 × 512 image counted 389 input tokens in all, one\n with a 1,024 × 1,024 image counted 1,157, and larger images up to the pixel\n limit counted between 1,125 and 1,157.\nHow many: exactly four tiny PNG/JPEG/WebP images succeeded on both models\n on 2026-10-04; a fifth was refused with a 422. Four is also NeuroLink's limit.\nNeuroLink's size limit is 256,000 bytes for the encoded request body,\n including base64 image data. A 195 KB PNG encodes to about 260,000 characters\n and is refused locally. Resize or compress a photo to well under 190 KB first.\n The 2026-10-03 API probe accepted a 195 KB PNG and refused a 202 KB one.\n That boundary has since moved: on 2026-10-05 both models accepted PNG\n requests with encoded bodies up to 492,485 bytes and refused 532,505 bytes\n (clef-flash) and 532,499 (clef) (see below), so the 195/202 KB figures are historical and NeuroLink's cap is\n the stricter limit.","hierarchy":{"lvl0":"Getting Started","lvl1":"Cloudflare Clef Provider Guide","lvl2":"Images","lvl3":""}},
5670
- {"objectID":"f98057fa646a175aee28fef3b525786c83a66b8ac8489feec28fd872866cf4ab","title":"When NeuroLink uses it","url":"/docs/getting-started/providers/cloudflare-clef#when-neurolink-uses-it","content":"Built-in features that call decide() pick the first decision provider that is\nconfigured, in this order: TypeSafe, Laya, XOR, Perplexity, then Clef. A host\nwith none of the first four, but with CLOUDFLARE_API_KEY and\nCLOUDFLARE_ACCOUNT_ID set for the Workers AI text provider, therefore has Clef\nas its default decision provider. Naming provider: \"cloudflare-clef\" reaches it\nwhatever else is configured.\n\nBecause of the state window below, a built-in feature whose state is longer than\nabout 1,500 estimated tokens gets a refusal from Clef, which each of them treats\nas \"carry on as before\". Clef suits short decisions: routing a request, a\nguardrail on one action, classifying one message or one picture.","hierarchy":{"lvl0":"Getting Started","lvl1":"Cloudflare Clef Provider Guide","lvl2":"When NeuroLink uses it","lvl3":""}},
5670
+ {"objectID":"f98057fa646a175aee28fef3b525786c83a66b8ac8489feec28fd872866cf4ab","title":"When NeuroLink uses it","url":"/docs/getting-started/providers/cloudflare-clef#when-neurolink-uses-it","content":"Built-in features that call decide() pick the first decision provider that is\nconfigured, in this order: TypeSafe, Laya, XOR, Perplexity, then Clef. A host\nwith none of the first four, but with CLOUDFLARE_API_KEY and\nCLOUDFLARE_ACCOUNT_ID set for the Workers AI text provider, therefore has Clef\nas its default decision provider. Naming provider: \"cloudflare-clef\" reaches it\nwhatever else is configured.\n\nBecause of the state limit below, a built-in feature whose state is longer than\nabout 16,000 estimated tokens (about 60,000 characters of prose) gets a refusal\nfrom Clef, which each of them treats as \"carry on as before\". Clef suits short decisions: routing a request, a\nguardrail on one action, classifying one message or one picture.","hierarchy":{"lvl0":"Getting Started","lvl1":"Cloudflare Clef Provider Guide","lvl2":"When NeuroLink uses it","lvl3":""}},
5671
5671
  {"objectID":"69f3db3e89a8fd474930cba6df7b01125fa2d9dd41aaadf8d8838423632ace30","title":"What is sent to Cloudflare","url":"/docs/getting-started/providers/cloudflare-clef#what-is-sent-to-cloudflare","content":"boolean is the SDK's name for the wire's noul. model is sent although the\npath already names it: Cloudflare's schema marks it required, and a body whose\nmodel differs from the path is refused. A request with no model was accepted\nlive and answered by clef-flash, so sending it matters only for following the\nschema. Cloudflare wraps every answer in its own\nenvelope, and NeuroLink reads the answers out of it:\n\nThe request id is the cf-ai-req-id response header; where that is absent (a\nrejected token never reaches the model) it is the edge's cf-ray.","hierarchy":{"lvl0":"Getting Started","lvl1":"Cloudflare Clef Provider Guide","lvl2":"What is sent to Cloudflare","lvl3":""}},
5672
5672
  {"objectID":"37eb6d126d3af6ca22085fbf94025a8f23da15691c8f6070b946f5aaa27e2f10","title":"One token, two providers","url":"/docs/getting-started/providers/cloudflare-clef#one-token-two-providers","content":"cloudflare-clef and cloudflare read the same two variables, but each has its\nown credentials slice, so the two cannot be mixed up:\n\n| | cloudflare (text) | cloudflare-clef (decide) |\n| --------------- | --------------------------- | ---------------------------- |\n| Token | CLOUDFLARE_API_KEY | CLOUDFLARE_API_KEY |\n| Account id | CLOUDFLARE_ACCOUNT_ID | CLOUDFLARE_ACCOUNT_ID |\n| SDK credentials | credentials.cloudflare | credentials.cloudflareClef |\n| Serves | generate() and stream() | decide() only |\n\ncredentials.cloudflare does not configure decide. Setting the two\nvariables for the text provider also lets decide() use Clef when no other\ndecision provider is configured, and no switch turns that off while the two\nvariables are set in the environment. A host that wants the Workers AI text\nprovider without Clef can give the text provider its token and account id only\nthrough credentials.cloudflare, and leave the environment variables unset.","hierarchy":{"lvl0":"Getting Started","lvl1":"Cloudflare Clef Provider Guide","lvl2":"One token, two providers","lvl3":""}},
5673
- {"objectID":"fee62c91a128411e33fcad60cf048405bd86ff0f4015189d992b70d34fe1b86f","title":"Measured on a real account, October 2026","url":"/docs/getting-started/providers/cloudflare-clef#measured-on-a-real-account-october-2026","content":"The Workers AI endpoint ignores text past about 2,048 tokens, far below\nCloudflare's documented 64K context (hosted service or model: unknown). Request-size refusals also changed between two measurement dates.\nThe original measurements were on 2026-10-03; the bounded follow-up campaign\nused 133 probe calls on 2026-10-04, with one request at a time.\n\nWhich model: on both clef-flash and clef, the follow-up still read the\nfact at the 2026-10-03 clef-flash lower bound for logs, number lists, digit\narrays and compact JSON, and did not read it 2.5% to 3.1% further on. English prose and\nrandom CJK had already matched on both models. It also checked the question\ncount, pixel and four/five-image boundaries on both models, the id, option,\nscore-level and PNG/JPEG/WebP boundaries on clef, and the image/jpg case on\nboth models. Natural-script\nprose was measured on clef; a reworked many-key object probe matched on both.\nTypeScript, minified JSON and synthetic Devanagari/emoji cuts remain 9B-only\nmeasurements. Historical latency, billing and burst figures retain their dates.","hierarchy":{"lvl0":"Getting Started","lvl1":"Cloudflare Clef Provider Guide","lvl2":"Measured on a real account, October 2026","lvl3":""}},
5673
+ {"objectID":"fee62c91a128411e33fcad60cf048405bd86ff0f4015189d992b70d34fe1b86f","title":"Measured on a real account, October 2026","url":"/docs/getting-started/providers/cloudflare-clef#measured-on-a-real-account-october-2026","content":"The Workers AI endpoint ignored text past about 2,048 tokens until 2026-10-04,\nfar below Cloudflare's documented 64K context, and read far more on 2026-10-07\n(hosted service or model: unknown). Request-size refusals also changed between two measurement dates.\nThe original measurements were on 2026-10-03; the bounded follow-up campaign\nused 133 probe calls on 2026-10-04, with one request at a time.\n\nWhich model: on both clef-flash and clef, the follow-up still read the\nfact at the 2026-10-03 clef-flash lower bound for logs, number lists, digit\narrays and compact JSON, and did not read it 2.5% to 3.1% further on. English prose and\nrandom CJK had already matched on both models. It also checked the question\ncount, pixel and four/five-image boundaries on both models, the id, option,\nscore-level and PNG/JPEG/WebP boundaries on clef, and the image/jpg case on\nboth models. Natural-script\nprose was measured on clef; a reworked many-key object probe matched on both.\nTypeScript, minified JSON and synthetic Devanagari/emoji cuts remain 9B-only\nmeasurements. Historical latency, billing and burst figures retain their dates.","hierarchy":{"lvl0":"Getting Started","lvl1":"Cloudflare Clef Provider Guide","lvl2":"Measured on a real account, October 2026","lvl3":""}},
5674
5674
  {"objectID":"26bf07373276f11bf9e656e74cd4a5cbdeeed0e8b4bfa1c057f362b55a3ad959","title":"The state window changed on 2026-10-07","url":"/docs/getting-started/providers/cloudflare-clef#the-state-window-changed-on-2026-10-07","content":"The window described above no longer applies. On 2026-10-07 the Workers AI\nendpoint read the whole state. This section records what was measured; the\nnumbers above stay as the record of 2026-10-03 and 2026-10-04.\n\nMeasured with one request at a time between 07:24 and 08:12 UTC, with a fact\nplaced at the end of the state (the part a cut would drop) and the question \"what\ncolour does the text say the vault code is?\". A fact counts as read when the\nanswer's probability for its colour is at least 0.8.\n\n| State | Model | Characters | Input tokens billed | Fact read (probability) | Time |\n| --------------------------------- | ------------ | ---------- | ------------------- | ----------------------- | ------ |\n| Prose, fact at 55,000 | clef-flash | 60,032 | 10,555 | yes (0.980) | 0.8 s |\n| Prose, fact at 55,000 | clef | 60,032 | 10,555 | yes (0.996) | 2.0 s |\n| Prose, no fact (control) | clef-flash | 60,000 | 10,547 | no (0.297) | 1.1 s |\n| Prose, no fact (control) | clef | 60,000 | 10,547 | no (0.170) | 2.0 s |\n| Prose, fact at 200,000 | clef-flash | 240,032 | 41,755 | yes (0.978) | 3.0 s |\n| Prose, fact at the end | clef-flash | 300,031 | 52,154 | yes (0.984) | 4.9 s |\n| Prose, fact at the end | clef | 300,031 | 52,154 | yes (0.996) | 11.8 s |\n| Prose, fact at the end | clef-flash | 500,031 | 86,819 | yes (0.985) | 19.2 s |\n| JSON array of digits, fact at end | clef-flash | 115,031 | 115,153 | yes (0.986) | 11.3 s |\n| JSON array of digits, fact at end | clef-flash | 158,031 | 158,153 | yes (0.987) | 30.9 s |\n| JSON array of digits, fact at end |","hierarchy":{"lvl0":"Getting Started","lvl1":"Cloudflare Clef Provider Guide","lvl2":"The state window changed on 2026-10-07","lvl3":""}},
5675
- {"objectID":"39c1f7ffec3b0df62b067ce9d778c3752d09cb8fdecce80b4e64028655048470","title":"What NeuroLink refuses before any request","url":"/docs/getting-started/providers/cloudflare-clef#what-neurolink-refuses-before-any-request","content":"| Refused | Limit | Error kind |\n| --------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------ | ------------------------------------- |\n| A state estimated over 1,500 tokens | digits 1 token each, punctuation 0.75, emoji 3, other non-ASCII text 1.5, letters about 4 characters a token | max_tokens_exceeded |\n| More than 64 questions in one decide() | 64 | max_tokens_exceeded |\n| A request body over 256,000 bytes | 256,000 | invalid_request |\n| More than 4 images, a video, or a format other than PNG, JPEG or WebP | | invalid_request |\n| A model name that is not a plain name, such as clef/../x | | invalid_request |\n| A missing token or account id, or a base URL that cannot work | | authentication or invalid_request |\n\nNeuroLink.tryDecide(), which every built-in feature calls, splits a question\nmap at 64 and runs up to four batches at once, so only a direct decide() meets\nthe 64-question refusal.\n\nWhy 1,500 and not 2,048.","hierarchy":{"lvl0":"Getting Started","lvl1":"Cloudflare Clef Provider Guide","lvl2":"What NeuroLink refuses before any request","lvl3":""}},
5675
+ {"objectID":"39c1f7ffec3b0df62b067ce9d778c3752d09cb8fdecce80b4e64028655048470","title":"What NeuroLink refuses before any request","url":"/docs/getting-started/providers/cloudflare-clef#what-neurolink-refuses-before-any-request","content":"| Refused | Limit | Error kind |\n| --------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------ | ------------------------------------- |\n| A state estimated over 16,000 tokens | digits 1 token each, punctuation 0.75, emoji 3, other non-ASCII text 1.5, letters about 4 characters a token | max_tokens_exceeded |\n| More than 64 questions in one decide() | 64 | max_tokens_exceeded |\n| A request body over 256,000 bytes | 256,000 | invalid_request |\n| More than 4 images, a video, or a format other than PNG, JPEG or WebP | | invalid_request |\n| A model name that is not a plain name, such as clef/../x | | invalid_request |\n| A missing token or account id, or a base URL that cannot work | | authentication or invalid_request |\n\nNeuroLink.tryDecide(), which every built-in feature calls, splits a question\nmap at 64 and runs up to four batches at once, so only a direct decide() meets\nthe 64-question refusal.\n\nWhy 16,000.","hierarchy":{"lvl0":"Getting Started","lvl1":"Cloudflare Clef Provider Guide","lvl2":"What NeuroLink refuses before any request","lvl3":""}},
5676
5676
  {"objectID":"bb0d1df2801529da652fbd15360879d9b2ccce53dfdf4d825a7a00f4e19d8d15","title":"What is not verified","url":"/docs/getting-started/providers/cloudflare-clef#what-is-not-verified","content":"The status Cloudflare returns for a token without Workers AI permission. No\n such token was available. A 403 is treated as an ordinary invalid_request,\n not authentication, so that if it does mean a missing permission, fixing it\n in the dashboard works at once, without restarting the process.\nAny 5xx other than one 529. Cloudflare answered a single server error, HTTP 529\n with code 5012 (\"Clef inference failed\"), to a 190,153-token state on clef on\n 2026-10-07; the retry and classification of 500, 502, 503 and 504 rest on\n ordinary HTTP conventions.\nWhat a Workers Paid account that has run out of credit gets. Only the Free plan's\n daily allocation running out was seen (HTTP 429, code 4006, 2026-10-05); it is\n not retried. Cloudflare documents a reset at 00:00 UTC, but this account was\n still refused at 02:38 and 04:12 UTC on 2026-10-06 and answered again at\n 07:24 UTC on 2026-10-07, so when the allowance returns here is not verified.\nThe 27B TypeScript, minified-JSON and synthetic Devanagari/emoji cuts; see the\n model coverage above.\nThe rate limit. Only a burst of 60 was tried.\nWhether Cloudflare's service is generally available or in beta.\nWhether the state window (about 2,048 tokens until 2026-10-04, none found by\n 2026-10-07) and the changing request-size limit belong to the hosted service or\n to the model itself. The open weights on Hugging Face\n were not run.\nWhether either limit changes again. The live decide suite carries three canary\n cases that fail with an instruction to re-measure: 19.10 and 19.10b send a\n prose state and a digit array just under NeuroLink's own limit, with a fact at\n the very end, to both models, and fail if the service stops reading below that\n limit; 19.11 checks both sides of the text-only request ceiling on clef-flash.\n None of them notices a service that reads more than the limit allows.","hierarchy":{"lvl0":"Getting Started","lvl1":"Cloudflare Clef Provider Guide","lvl2":"What is not verified","lvl3":""}},
5677
- {"objectID":"4214184c06ad6cee88e38838f55c38c5a554a78434494b5d765a1c120eb0e339","title":"Latency and the timeout","url":"/docs/getting-started/providers/cloudflare-clef#latency-and-the-timeout","content":"On 2026-10-03, a small request answered in 0.3 to 1.0 s from a developer\nmachine; 64 questions took 1.1 s on clef-flash and 1.3 s on clef; the\nslowest of 60 requests sent at once took 2.2 s. On 2026-10-04, a\n64-question request with the same questions and a shorter state took 1.5 s on clef-flash and 2.3 s on clef. The default timeout is 5 s. Pass timeoutMs to change it for\none call.","hierarchy":{"lvl0":"Getting Started","lvl1":"Cloudflare Clef Provider Guide","lvl2":"Latency and the timeout","lvl3":""}},
5677
+ {"objectID":"4214184c06ad6cee88e38838f55c38c5a554a78434494b5d765a1c120eb0e339","title":"Latency and the timeout","url":"/docs/getting-started/providers/cloudflare-clef#latency-and-the-timeout","content":"On 2026-10-03, a small request answered in 0.3 to 1.0 s from a developer\nmachine; 64 questions took 1.1 s on clef-flash and 1.3 s on clef; the\nslowest of 60 requests sent at once took 2.2 s. On 2026-10-04, a\n64-question request with the same questions and a shorter state took 1.5 s on clef-flash and 2.3 s on clef. The default timeout is 5 s plus 250 ms for each full 1,000 estimated state tokens\n(5 s for a short state, 9 s at the 16,000-token limit); on 2026-10-07 large states took about 0.2 s per\n1,000 input tokens (1.7 to 1.9 s for 20,954 tokens on clef-flash; 11.8 s for 52,154 on clef). Pass\ntimeoutMs to change it for one call.","hierarchy":{"lvl0":"Getting Started","lvl1":"Cloudflare Clef Provider Guide","lvl2":"Latency and the timeout","lvl3":""}},
5678
5678
  {"objectID":"c2d0b99e3c2760e14d8be1f81ba92c025ad96523cdeaa34dd002a748ae9658de","title":"Errors","url":"/docs/getting-started/providers/cloudflare-clef#errors","content":"Cloudflare answers with its own envelope, { \"success\": false, \"errors\": [{ \"code\",\n\"message\" }] }, and a refusal from the model nests a second envelope, with a\ntrailing request id, inside message. NeuroLink flattens both to one line and\ntakes the request id out of the text.\n\n| Status | Code | Seen for | Kind | Retried |\n| ------ | ----- | ----------------------------------------------------------------------------------------- | ----------------------------------- | ------------------------------ |\n| 401 | 10000 | a token Cloudflare does not know | authentication | no; trips the breaker |\n| 403 | | never seen; a token without Workers AI permission may draw it | invalid_request | no; does not trip the breaker |\n| 400 | 5006 | no questions; an unknown question type | invalid_request | no |\n| 400 | 7000 | a model path that does not exist (\"No route for that URI\") | invalid_request | no |\n| 400 | 6003 | a body that is not JSON | invalid_request | no |\n| 422 | 5012 | a validation failure: 65 questions, a fifth image, an unknown field, an empty instruction | invalid_request | no |\n| 413 | 5021 | a request past the estimate above | max_tokens_exceeded | no |\n| 429 | 3040 | \"Capacity temporarily exceeded\"; no Retry-After","hierarchy":{"lvl0":"Getting Started","lvl1":"Cloudflare Clef Provider Guide","lvl2":"Errors","lvl3":""}},
5679
5679
  {"objectID":"ce05a3d9d2ab15b8867c8e721fbfa0f8e1248520e2413765fa7d70bd835e3f85","title":"Troubleshooting","url":"/docs/getting-started/providers/cloudflare-clef#troubleshooting","content":"\"requires the account id\" — set CLOUDFLARE_ACCOUNT_ID or\n credentials.cloudflareClef.accountId.\n\"The state is ~N tokens; Cloudflare's … model reads at most 1500\" — shorten\n the state, or send only the part the question is about. Cloudflare would have\n cut the rest without telling you.\n\"No route for that URI\" — the model name or the base URL is wrong. Clef is\n served as clef and clef-flash, and the base URL must end in /client/v4.\nA 429 \"Capacity temporarily exceeded\" — retried for you; if it keeps\n happening, send fewer requests at once.\nA 429 \"you have used up your daily free allocation of 10,000 neurons\" — the\n Free plan's allowance for the day is gone. It is not retried, because nothing\n changes until the allowance returns (Cloudflare documents a reset at 00:00 UTC; on\n this account it came back later, see \"What is not verified\"); upgrade to Workers Paid or wait.\n Built-in features that use Clef as their default fall back as on any failure.\nAn image is refused as \"The request is N bytes; Cloudflare accepts at most\n 256000\" — Cloudflare counts the base64 text of the image, so NeuroLink\n refuses it locally under the retained conservative cap. Resize or compress it\n to well under 190 KB; a 195 KB PNG, which Cloudflare accepted, is about 260,000\n characters in base64 and is refused here.\ndecide() uses Clef although you never chose it — you have the Workers AI\n token and account id set and no other decision provider; see\n When NeuroLink uses it.","hierarchy":{"lvl0":"Getting Started","lvl1":"Cloudflare Clef Provider Guide","lvl2":"Troubleshooting","lvl3":""}},
5680
5680
  {"objectID":"64d2af754e23d6f77f9ba5991174048f9dc4e8434d0f9a633527785feff8158e","title":"See also","url":"/docs/getting-started/providers/cloudflare-clef#see-also","content":"The decide inference type\nTypeSafe (Jev) Provider Guide\nLaya Provider Guide\nXOR Provider Guide\nPerplexity Decisions Provider Guide\nCloudflare Workers AI text provider\nClef on Workers AI\nIntroducing Clef: our open-source decision models, and new RL fine-tuning platform (Cloudflare Blog)","hierarchy":{"lvl0":"Getting Started","lvl1":"Cloudflare Clef Provider Guide","lvl2":"See also","lvl3":""}},
@@ -6240,7 +6240,7 @@
6240
6240
  {"objectID":"43b838d60f2794ce46361196d6fc8a708b3a301398dd55f2c8015d567aa21c2c","title":"[Laya](/docs/getting-started/providers/laya)","url":"/docs/getting-started/providers#layadocsgetting-startedproviderslaya","content":"Open-weights decision provider — the same typed boolean/choice/score answers as Jev, from Convai Innovations' Apache-2.0 checkpoints, at a Laya server or LiteLLM proxy route you configure\n🧭 Serves decide only; built-in features use it when its key and base URL are set and neither TYPESAFE_API_KEY nor AI_GATEWAY_API_KEY is\n📏 Refuses more than ~768 tokens of state (320 on english) before any network call, since its encoders read only 1,024 (512)\n🔌 No built-in endpoint: LAYA_BASE_URL (or credentials.laya.baseURL) names a Laya server or a LiteLLM pass-through route to one\n🔑 LAYA_API_KEY is the key that endpoint accepts; on LiteLLM, the route must be in the key's Allowed Routes\n\nSetup Guide →","hierarchy":{"lvl0":"Getting Started","lvl1":"AI Provider Guides","lvl2":"[Laya](/docs/getting-started/providers/laya)","lvl3":""}},
6241
6241
  {"objectID":"613cbeca5e8fa0bbe765b8db9ec4ed2ff76a913dd45b8dab5e2de06a6e5f19ff","title":"[XOR](/docs/getting-started/providers/xor)","url":"/docs/getting-started/providers#xordocsgetting-startedprovidersxor","content":"Open-weights decision provider — the same typed boolean/choice/score answers as Jev, from xor-1.1, Juspay's Apache-2.0 model, at a deployment or LiteLLM proxy route you configure\n🧭 Serves decide only; built-in features use it when its key and base URL are set and no TypeSafe key, no AI_GATEWAY_API_KEY and no Laya key and base URL is\n🖼️ Takes up to 8 images or one video with a decision, as a Buffer, a local file path or a data: URL; TypeSafe and Laya refuse media before any request, and Perplexity refuses a video\n📏 Refuses more than about 200,000 estimated tokens of state before any network call\n🔌 No built-in endpoint: XOR_BASE_URL (or credentials.xor.baseURL) is the origin of a deployment or of a LiteLLM route to one; requests go to <base URL>/v1/systemone\n🔑 XOR_API_KEY is the key that endpoint accepts; on LiteLLM, the key's team must allow xor-1.1\n📦 Weights and setup: huggingface.co/juspay/xor\n\nSetup Guide →","hierarchy":{"lvl0":"Getting Started","lvl1":"AI Provider Guides","lvl2":"[XOR](/docs/getting-started/providers/xor)","lvl3":""}},
6242
6242
  {"objectID":"6ab8cdd8152a0d7c9844d54b6d4eaccc905b60e79f4b28508d78d52c3cfe9470","title":"[Perplexity Decisions](/docs/getting-started/providers/perplexity-decider)","url":"/docs/getting-started/providers#perplexity-decisionsdocsgetting-startedprovidersperplexity-decider","content":"Hosted decision provider — the same typed boolean/choice/score answers as Jev, from Perplexity's pplx-decider-v1-27b, at https://api.perplexity.ai\n🧭 Serves decide only (provider id perplexity-decider, not the Sonar text provider perplexity); built-in features use it when it is configured and no TypeSafe key, no AI_GATEWAY_API_KEY, no Laya key and base URL and no XOR key and base URL is\n🔑 PERPLEXITY_API_KEY alone configures it, and it is the same key the Perplexity text provider reads, so a key set for Sonar also lets built-in features use it when none of TypeSafe, Laya or XOR is configured; the guide lists what each consumer then sends\n🖼️ Takes up to 8 PNG, JPEG or WebP images with a decision; no video\n💰 $0.04 per million input tokens (image tokens included), output free, as Perplexity documents it\n📏 Refuses more than about 100,000 estimated tokens of state (NeuroLink's own window; the server's ceiling is 262,144 input tokens), or more than 128 questions in a decide() call (tryDecide() splits them), before any network call. The 128-question cap, the server's token ceiling and the latency were measured on a real account in October 2026\n🔌 Hosted endpoint, so no base URL is needed; PERPLEXITY_DECIDER_BASE_URL (or credentials.perplexityDecider.baseURL) can name another origin\n\nSetup Guide →","hierarchy":{"lvl0":"Getting Started","lvl1":"AI Provider Guides","lvl2":"[Perplexity Decisions](/docs/getting-started/providers/perplexity-decider)","lvl3":""}},
6243
- {"objectID":"94b24c75db64d3f04ba04b2ee0f04ec13bc0509de0aea1fa1b3e5516dea73ea9","title":"[Cloudflare Clef](/docs/getting-started/providers/cloudflare-clef)","url":"/docs/getting-started/providers#cloudflare-clefdocsgetting-startedproviderscloudflare-clef","content":"Hosted decision provider on Workers AI — the same typed boolean/choice/score answers as Jev, from Cloudflare's clef (27B) and clef-flash (9B), at https://api.cloudflare.com/client/v4\n🧭 Serves decide only (provider id cloudflare-clef, not the Workers AI text provider cloudflare); built-in features use it only when it is configured and none of TypeSafe, Laya, XOR or Perplexity is — it comes last\n🔑 CLOUDFLARE_API_KEY (Workers AI permission) and CLOUDFLARE_ACCOUNT_ID configure it, and they are the same two variables the Cloudflare text provider reads, so a pair set for that provider also lets built-in features use it when no other decision provider is configured\n🖼️ Takes up to 4 PNG, JPEG or WebP images with a decision; no video\n💰 $0.24 per million input tokens for clef, $0.09 for clef-flash; no output price is listed on Cloudflare's pricing page\n📏 The endpoint ignores state text past about 2,048 tokens (hosted service or model: unknown), far less than the 64K Cloudflare documents, and says nothing when it does; NeuroLink refuses more than about 1,500 estimated tokens (digits count a token each, punctuation 0.75, emoji 3), more than 64 questions in a decide() call (tryDecide() splits them) and a request over 256,000 bytes, base64 image data included, before any network call. The state cut and the request ceiling were measured on a real account in October 2026, with the follow-up text cuts and API limits checked on both models; see the guide for the tested shapes and dates\n🔌 Hosted endpoint, so no base URL is needed; CLOUDFLARE_CLEF_BASE_URL (or credentials.cloudflareClef.baseURL) can name another base\n\nSetup Guide →","hierarchy":{"lvl0":"Getting Started","lvl1":"AI Provider Guides","lvl2":"[Cloudflare Clef](/docs/getting-started/providers/cloudflare-clef)","lvl3":""}},
6243
+ {"objectID":"94b24c75db64d3f04ba04b2ee0f04ec13bc0509de0aea1fa1b3e5516dea73ea9","title":"[Cloudflare Clef](/docs/getting-started/providers/cloudflare-clef)","url":"/docs/getting-started/providers#cloudflare-clefdocsgetting-startedproviderscloudflare-clef","content":"Hosted decision provider on Workers AI — the same typed boolean/choice/score answers as Jev, from Cloudflare's clef (27B) and clef-flash (9B), at https://api.cloudflare.com/client/v4\n🧭 Serves decide only (provider id cloudflare-clef, not the Workers AI text provider cloudflare); built-in features use it only when it is configured and none of TypeSafe, Laya, XOR or Perplexity is — it comes last\n🔑 CLOUDFLARE_API_KEY (Workers AI permission) and CLOUDFLARE_ACCOUNT_ID configure it, and they are the same two variables the Cloudflare text provider reads, so a pair set for that provider also lets built-in features use it when no other decision provider is configured\n🖼️ Takes up to 4 PNG, JPEG or WebP images with a decision; no video\n💰 $0.24 per million input tokens for clef, $0.09 for clef-flash; no output price is listed on Cloudflare's pricing page\n📏 The state window changed in October 2026 (hosted service or model: unknown): until 2026-10-04 the endpoint ignored text past about 2,048 tokens without an error, and on 2026-10-07 it read states of at least 190,153 tokens (clef-flash) and 52,154 (clef); NeuroLink refuses more than 16,000 estimated tokens (digits count a token each, punctuation 0.75, emoji 3), more than 64 questions in a decide() call (tryDecide() splits them) and a request over 256,000 bytes, base64 image data included, before any network call. The state cut and the request ceiling were measured on a real account in October 2026, with the follow-up text cuts and API limits checked on both models; see the guide for the tested shapes and dates\n🔌 Hosted endpoint, so no base URL is needed; CLOUDFLARE_CLEF_BASE_URL (or credentials.cloudflareClef.baseURL) can name another base\n\nSetup Guide →","hierarchy":{"lvl0":"Getting Started","lvl1":"AI Provider Guides","lvl2":"[Cloudflare Clef](/docs/getting-started/providers/cloudflare-clef)","lvl3":""}},
6244
6244
  {"objectID":"c98403894a115164f29a019817b7f39c93b59623a9854b4575ad06bc5f597320","title":"🧩 Additional Catalog Providers","url":"/docs/getting-started/providers#-additional-catalog-providers","content":"Every provider below is a Tier-2 catalog entry. Provider-specific\nbehavioural quirks may apply, so check the provider's catalog file. The whole\nintegration is one JSON file under src/lib/providers/catalog/. Each page is\ngenerated from that file, which is also what the CI onboarding gate reads.","hierarchy":{"lvl0":"Getting Started","lvl1":"AI Provider Guides","lvl2":"🧩 Additional Catalog Providers","lvl3":""}},
6245
6245
  {"objectID":"026138da0a559269ecd9f0b2ceb72d9039096e72e064142afb7bfb74a5cb7455","title":"[API Route](/docs/getting-started/providers/api-route)","url":"/docs/getting-started/providers#api-routedocsgetting-startedprovidersapi-route","content":"Claude Sonnet 4.6\n🤖 8 models; default claude-sonnet-4-6 (1M context)\n🛠️ Native tool calling + structured output together\n💳 Free tier available\n✅ Roster verified 2026-09-17 (authenticated GET /v1/models)\n🔑 API key from api-route.com\n🔄 Aliases: apiroute\n\nSetup Guide →","hierarchy":{"lvl0":"Getting Started","lvl1":"AI Provider Guides","lvl2":"[API Route](/docs/getting-started/providers/api-route)","lvl3":""}},
6246
6246
  {"objectID":"85aa65949d959db077347ecf93a4c40ade9ebab4300d4d52c62c702f6929053b","title":"[Baseten](/docs/getting-started/providers/baseten)","url":"/docs/getting-started/providers#basetendocsgetting-startedprovidersbaseten","content":"GLM 5.3 Flash\n🤖 16 models; default zai-org/GLM-5.3-Flash (1M context)\n🛠️ Native tool calling + structured output together\n💳 Free tier available\n✅ Roster verified 2026-09-03 (authenticated GET /v1/models)\n🔑 API key from app.baseten.co\n\nSetup Guide →","hierarchy":{"lvl0":"Getting Started","lvl1":"AI Provider Guides","lvl2":"[Baseten](/docs/getting-started/providers/baseten)","lvl3":""}},
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@juspay/neurolink",
3
- "version": "12.49.5",
3
+ "version": "12.49.7",
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": {