@juspay/neurolink 12.55.2 → 12.56.0

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.
@@ -9745,18 +9745,18 @@
9745
9745
  {"objectID":"aaa9ef50d62dd989356ea2bb28e77e07f8bb8cbe1fcff8fb4c84600bee0c8474","title":"Architecture Decision Records — Provider Onboarding Redesign","url":"/docs/provider-integration/adr/README#architecture-decision-records-provider-onboarding-redesign","content":"Short, dated records of the load-bearing decisions behind the provider\nonboarding redesign (Plans 04–10, August 2026). Read these before arguing to\nchange the shape of ProviderDescriptor, the catalog, or the CI gate — the\ntradeoffs were already litigated once.\n\n| ADR | Decision | Status |\n| ---- | ------------------------------------------------------------------------------ | -------------------- |\n| 0001 | ProviderDescriptor is the single source of truth for provider identity | Accepted |\n| 0002 | OpenAI-wire-compatible providers default to a data-catalog row, not a subclass | Accepted and shipped |\n| 0003 | Mocked-fetch contract tests are the CI gate; live-API suites are not | Accepted and shipped |","hierarchy":{"lvl0":"Provider Integration","lvl1":"Architecture Decision Records — Provider Onboarding Redesign","lvl2":"Architecture Decision Records — Provider Onboarding Redesign","lvl3":""}},
9746
9746
  {"objectID":"1be076b3fd50fdb68b087798ec78c74d20575d4a39e3c54f8ee8e1cde744fa6a","title":"Catalog authoring and admission","url":"/docs/provider-integration/catalog-admission","content":"Catalog authoring and admission\n\nCatalog source completeness, PR provenance, installed-package behavior and\ncurrent vendor availability are separate results. The default\npnpm run verify:provider-onboarding remains an offline source check; it does\nnot certify the PR URL or refresh a dated roster/live record.\n\nCatalog model defaults for context and output must be positive safe\nintegers supported by source evidence. Unknown ceilings remain unresolved.\nThis authoring constraint does not alter caller maxTokens: 0 semantics or\noptional per-model overrides. A scaffold intentionally contains invalid zero\nceilings and TODO evidence until the author supplies real values.\n\nInspect an unfinished scaffold:\n\nThis reports incomplete_draft and its validation problems. Successful draft\ninspection is not admission; every admission result has zero provider-count,\npackage, publication, roster and live credit.\n\nAfter filling the source fields, use the exact PENDING_PR marker while no PR\nexists. A guessed URL or arbitrary string is not provenance:\n\nWithout a provider/file selector, draft/source stages inspect the whole\ncatalog. They stay offline. A canonical PR URL is only syntax at this stage;\nthe output explicitly leaves provenance unverified. Existing dated evidence\nis retained without relabeling or requiring a breaking record migration.\nPaired (--catalog-stage source) and equals (--catalog-stage=source) options\ncan be mixed; the same forms apply to provider, file and source-head selectors.\n\nWhen a real introduction PR exists, put its actual URL in addedInPR,\nregenerate and commit the source, then inspect the immutable PR head:\n\nThe explicitly selected provenance stage uses authenticated, read-only gh api\nqueries. It requires the actual repository/PR identity, an added-file association\nfor this provider, the exact local source/PR head and equal provider-file blob.\nUncommitted source, a stale/unrelated head, guessed/nonexistent PR or unrelated\nexisting PR fails. GitHub API access failures fail closed. Association proof\ndoes not certify reviewer approval or current candidate CI.\n\nAfter merge:\n\nThis reports historical_catalog_file_introduction_verified: actual added-file\nassociation, merged state, merge ancestry in the selected local head and all\nfive required checks completed SUCCESS at the introduction PR head. It does\nnot certify current product identity or content continuity after later edits,\ndeletion or replacement. Historical file introduction remains provable even if\na later product reuses that path; the current source bytes are not silently\nequated with the old introduced blob. Current integration/product acceptance\nneeds its separate evidence. The newest run of each required check must pass;\nmissing, skipped, neutral or pending runs fail.\n\nroster, live, package and release are deliberately not admission-command\nstages. Docs-only records cannot become authenticated roster or live receipts.\nThose claims require their separately authorized current account/model/route\nexecution or installed-consumer evidence. This command makes no vendor calls\nand never changes an account, PR, branch, catalog record or remote thread.","hierarchy":{"lvl0":"Provider Integration","lvl1":"Catalog authoring and admission","lvl2":"","lvl3":""}},
9747
9747
  {"objectID":"9af9cab8b3cff18ad3bf19995bd3b8e9e1264fa6f64d7659b6f7222e18d7ea34","title":"Catalog authoring and admission","url":"/docs/provider-integration/catalog-admission#catalog-authoring-and-admission","content":"Catalog source completeness, PR provenance, installed-package behavior and\ncurrent vendor availability are separate results. The default\npnpm run verify:provider-onboarding remains an offline source check; it does\nnot certify the PR URL or refresh a dated roster/live record.\n\nCatalog model defaults for context and output must be positive safe\nintegers supported by source evidence. Unknown ceilings remain unresolved.\nThis authoring constraint does not alter caller maxTokens: 0 semantics or\noptional per-model overrides. A scaffold intentionally contains invalid zero\nceilings and TODO evidence until the author supplies real values.\n\nInspect an unfinished scaffold:\n\nThis reports incomplete_draft and its validation problems. Successful draft\ninspection is not admission; every admission result has zero provider-count,\npackage, publication, roster and live credit.\n\nAfter filling the source fields, use the exact PENDING_PR marker while no PR\nexists. A guessed URL or arbitrary string is not provenance:\n\nWithout a provider/file selector, draft/source stages inspect the whole\ncatalog. They stay offline. A canonical PR URL is only syntax at this stage;\nthe output explicitly leaves provenance unverified. Existing dated evidence\nis retained without relabeling or requiring a breaking record migration.\nPaired (--catalog-stage source) and equals (--catalog-stage=source) options\ncan be mixed; the same forms apply to provider, file and source-head selectors.\n\nWhen a real introduction PR exists, put its actual URL in addedInPR,\nregenerate and commit the source, then inspect the immutable PR head:\n\nThe explicitly selected provenance stage uses authenticated, read-only gh api\nqueries. It requires the actual repository/PR identity, an added-file association\nfor this provider, the exact local source/PR head and equal provider-file blob.\nUncommitted source, a stale/unrelated head, guessed/nonexistent PR or unrelated\nexisting PR fails. GitHub API access failures fail closed.","hierarchy":{"lvl0":"Provider Integration","lvl1":"Catalog authoring and admission","lvl2":"Catalog authoring and admission","lvl3":""}},
9748
- {"objectID":"91f87bcd98e1883a00b720044811501a2f90818bf3c3eff22c5d71b2a5e7d80b","title":"Provider Manifests","url":"/docs/provider-integration/manifests/README","content":"Provider Manifests\n\nThis convention originally applied to every provider onboarded via Tier 2,\n3, or 4: one JSON file here, named <provider>.json where <provider> is\nthe exact AIProviderName enum value (e.g. cerebras.json for\nAIProviderName.CEREBRAS = \"cerebras\").\n\nTier 2 (JSON catalog) providers no longer use a manifest here\n\nAs of the provider-JSON-catalog refactor, Tier 2 providers are declared\nentirely in src/lib/providers/catalog/<id>.json, validated by the zod\nschema in src/lib/providers/catalog/schema.ts. That file's evidence\nobject — rosterVerified, addedInPR, and optionally authProbe,\nbillingProbe, liveMatrix — carries the same onboarding evidence a\nmanifest used to hold, so a separate manifest file would just duplicate\nit. tools/verify-provider-onboarding.ts reflects this: for any provider\nwith a matching src/lib/providers/catalog/<id>.json file, the gate\nchecks that the JSON file exists, parses via the real zod schema, and\n(via that same successful parse, since both fields are non-optional in\nthe schema) carries evidence.rosterVerified and evidence.addedInPR.\n\ncerebras.json and sambanova.json — the two manifests that used to\nlive in this directory — were removed for this reason: both providers\nare now JSON-catalog entries, and their onboarding evidence lives in\nsrc/lib/providers/catalog/cerebras.json and\nsrc/lib/providers/catalog/sambanova.json respectively.\n\nlaya.json was removed the same way when Laya moved from a hand-written class onto a decide catalog file: src/lib/providers/catalog/laya.json carries its evidence block, and the gate checks it with parseCatalogEntry, which accepts chat and decide files alike and also requires the file's id to match its name.\n\nTier 3/4 (hand-written) providers still use a manifest here\n\nA provider onboarded outside the JSON catalog — a custom adapter (Tier 3)\nor fully custom integration (Tier 4) — has no catalog JSON file, so\ntools/verify-provider-onboarding.ts falls back to its original\nfour-check flow for it, including a manifest at\ndocs/provider-integration/manifests/<name>.json. The shape below still\napplies to those providers.\n\nThe block is annotated JSONC for documentation purposes only — the\n// comments and trailing comma explain each field but are not valid\nJSON. A real <provider>.json manifest file must be strict JSON: no\ncomments, no trailing commas.\n\nHow it's checked\n\npnpm run verify:provider-onboarding (tools/verify-provider-onboarding.ts)\nfails a PR that introduces a new AIProviderName member without matching\nonboarding evidence: a valid catalog JSON entry for Tier 2 providers (see\nabove), or a structurally valid manifest here for Tier 3/4 providers. A\nmanifest is structurally valid when it is a JSON object whose provider\nmatches the file name and which carries provider, tier, addedInPR,\naddedDate, filesTouched (an array of strings), mockedContractSection\nand manualTestStatus, plus tier4Justification when tier is 4. The gate\ndoes not retroactively require either for providers that predate the gate\n— see that tool's LEGACY_PROVIDERS list.","hierarchy":{"lvl0":"Provider Integration","lvl1":"Provider Manifests","lvl2":"","lvl3":""}},
9748
+ {"objectID":"91f87bcd98e1883a00b720044811501a2f90818bf3c3eff22c5d71b2a5e7d80b","title":"Provider Manifests","url":"/docs/provider-integration/manifests/README","content":"Provider Manifests\n\nThis convention originally applied to every provider onboarded via Tier 2,\n3, or 4: one JSON file here, named <provider>.json where <provider> is\nthe exact AIProviderName enum value (e.g. cerebras.json for\nAIProviderName.CEREBRAS = \"cerebras\").\n\nTier 2 (JSON catalog) providers no longer use a manifest here\n\nAs of the provider-JSON-catalog refactor, Tier 2 providers are declared\nentirely in src/lib/providers/catalog/<id>.json, validated by the zod\nschema in src/lib/providers/catalog/schema.ts. That file's evidence\nobject — rosterVerified, addedInPR, and optionally authProbe,\nbillingProbe, liveMatrix — carries the same onboarding evidence a\nmanifest used to hold, so a separate manifest file would just duplicate\nit. tools/verify-provider-onboarding.ts reflects this: for any provider\nwith a matching src/lib/providers/catalog/<id>.json file, the gate\nchecks that the JSON file exists, parses via the real zod schema, and\n(via that same successful parse, since both fields are non-optional in\nthe schema) carries evidence.rosterVerified and evidence.addedInPR.\n\ncerebras.json and sambanova.json — the two manifests that used to\nlive in this directory — were removed for this reason: both providers\nare now JSON-catalog entries, and their onboarding evidence lives in\nsrc/lib/providers/catalog/cerebras.json and\nsrc/lib/providers/catalog/sambanova.json respectively.\n\nlaya.json was removed the same way when Laya moved from a hand-written class onto a decide catalog file: src/lib/providers/catalog/laya.json carries its evidence block, and the gate checks it with parseCatalogEntry, which accepts chat and decide files alike and also requires the file's id to match its name.\n\nxor.json was removed the same way when XOR moved onto src/lib/providers/catalog/xor.json.\n\nTier 3/4 (hand-written) providers still use a manifest here\n\nA provider onboarded outside the JSON catalog — a custom adapter (Tier 3)\nor fully custom integration (Tier 4) — has no catalog JSON file, so\ntools/verify-provider-onboarding.ts falls back to its original\nfour-check flow for it, including a manifest at\ndocs/provider-integration/manifests/<name>.json. The shape below still\napplies to those providers.\n\nThe block is annotated JSONC for documentation purposes only — the\n// comments and trailing comma explain each field but are not valid\nJSON. A real <provider>.json manifest file must be strict JSON: no\ncomments, no trailing commas.\n\nHow it's checked\n\npnpm run verify:provider-onboarding (tools/verify-provider-onboarding.ts)\nfails a PR that introduces a new AIProviderName member without matching\nonboarding evidence: a valid catalog JSON entry for Tier 2 providers (see\nabove), or a structurally valid manifest here for Tier 3/4 providers. A\nmanifest is structurally valid when it is a JSON object whose provider\nmatches the file name and which carries provider, tier, addedInPR,\naddedDate, filesTouched (an array of strings), mockedContractSection\nand manualTestStatus, plus tier4Justification when tier is 4. The gate\ndoes not retroactively require either for providers that predate the gate\n— see that tool's LEGACY_PROVIDERS list.","hierarchy":{"lvl0":"Provider Integration","lvl1":"Provider Manifests","lvl2":"","lvl3":""}},
9749
9749
  {"objectID":"f50e43e805f49ece132b5ced9027edcbcb232799cd12a67be9b04ccceb764437","title":"Provider Manifests","url":"/docs/provider-integration/manifests/README#provider-manifests","content":"This convention originally applied to every provider onboarded via Tier 2,\n3, or 4: one JSON file here, named <provider>.json where <provider> is\nthe exact AIProviderName enum value (e.g. cerebras.json for\nAIProviderName.CEREBRAS = \"cerebras\").","hierarchy":{"lvl0":"Provider Integration","lvl1":"Provider Manifests","lvl2":"Provider Manifests","lvl3":""}},
9750
- {"objectID":"a68c16599df99491c1e91d0857d3b92f4bd78a3caa88b6279381ff1ca665926f","title":"Tier 2 (JSON catalog) providers no longer use a manifest here","url":"/docs/provider-integration/manifests/README#tier-2-json-catalog-providers-no-longer-use-a-manifest-here","content":"As of the provider-JSON-catalog refactor, Tier 2 providers are declared\nentirely in src/lib/providers/catalog/<id>.json, validated by the zod\nschema in src/lib/providers/catalog/schema.ts. That file's evidence\nobject — rosterVerified, addedInPR, and optionally authProbe,\nbillingProbe, liveMatrix — carries the same onboarding evidence a\nmanifest used to hold, so a separate manifest file would just duplicate\nit. tools/verify-provider-onboarding.ts reflects this: for any provider\nwith a matching src/lib/providers/catalog/<id>.json file, the gate\nchecks that the JSON file exists, parses via the real zod schema, and\n(via that same successful parse, since both fields are non-optional in\nthe schema) carries evidence.rosterVerified and evidence.addedInPR.\n\ncerebras.json and sambanova.json — the two manifests that used to\nlive in this directory — were removed for this reason: both providers\nare now JSON-catalog entries, and their onboarding evidence lives in\nsrc/lib/providers/catalog/cerebras.json and\nsrc/lib/providers/catalog/sambanova.json respectively.\n\nlaya.json was removed the same way when Laya moved from a hand-written class onto a decide catalog file: src/lib/providers/catalog/laya.json carries its evidence block, and the gate checks it with parseCatalogEntry, which accepts chat and decide files alike and also requires the file's id to match its name.","hierarchy":{"lvl0":"Provider Integration","lvl1":"Provider Manifests","lvl2":"Tier 2 (JSON catalog) providers no longer use a manifest here","lvl3":""}},
9750
+ {"objectID":"a68c16599df99491c1e91d0857d3b92f4bd78a3caa88b6279381ff1ca665926f","title":"Tier 2 (JSON catalog) providers no longer use a manifest here","url":"/docs/provider-integration/manifests/README#tier-2-json-catalog-providers-no-longer-use-a-manifest-here","content":"As of the provider-JSON-catalog refactor, Tier 2 providers are declared\nentirely in src/lib/providers/catalog/<id>.json, validated by the zod\nschema in src/lib/providers/catalog/schema.ts. That file's evidence\nobject — rosterVerified, addedInPR, and optionally authProbe,\nbillingProbe, liveMatrix — carries the same onboarding evidence a\nmanifest used to hold, so a separate manifest file would just duplicate\nit. tools/verify-provider-onboarding.ts reflects this: for any provider\nwith a matching src/lib/providers/catalog/<id>.json file, the gate\nchecks that the JSON file exists, parses via the real zod schema, and\n(via that same successful parse, since both fields are non-optional in\nthe schema) carries evidence.rosterVerified and evidence.addedInPR.\n\ncerebras.json and sambanova.json — the two manifests that used to\nlive in this directory — were removed for this reason: both providers\nare now JSON-catalog entries, and their onboarding evidence lives in\nsrc/lib/providers/catalog/cerebras.json and\nsrc/lib/providers/catalog/sambanova.json respectively.\n\nlaya.json was removed the same way when Laya moved from a hand-written class onto a decide catalog file: src/lib/providers/catalog/laya.json carries its evidence block, and the gate checks it with parseCatalogEntry, which accepts chat and decide files alike and also requires the file's id to match its name.\n\nxor.json was removed the same way when XOR moved onto src/lib/providers/catalog/xor.json.","hierarchy":{"lvl0":"Provider Integration","lvl1":"Provider Manifests","lvl2":"Tier 2 (JSON catalog) providers no longer use a manifest here","lvl3":""}},
9751
9751
  {"objectID":"00fb88ca42034f14d0a87eea1d06b38350fc2cb9b5bed8bb3f544f10b3cd99ab","title":"Tier 3/4 (hand-written) providers still use a manifest here","url":"/docs/provider-integration/manifests/README#tier-34-hand-written-providers-still-use-a-manifest-here","content":"A provider onboarded outside the JSON catalog — a custom adapter (Tier 3)\nor fully custom integration (Tier 4) — has no catalog JSON file, so\ntools/verify-provider-onboarding.ts falls back to its original\nfour-check flow for it, including a manifest at\ndocs/provider-integration/manifests/<name>.json. The shape below still\napplies to those providers.\n\nThe block is annotated JSONC for documentation purposes only — the\n// comments and trailing comma explain each field but are not valid\nJSON. A real <provider>.json manifest file must be strict JSON: no\ncomments, no trailing commas.","hierarchy":{"lvl0":"Provider Integration","lvl1":"Provider Manifests","lvl2":"Tier 3/4 (hand-written) providers still use a manifest here","lvl3":""}},
9752
9752
  {"objectID":"4384ec258a233739ea35584f79662d5111be0b8defd38f75a6ab8068bf3a7e30","title":"How it's checked","url":"/docs/provider-integration/manifests/README#how-its-checked","content":"pnpm run verify:provider-onboarding (tools/verify-provider-onboarding.ts)\nfails a PR that introduces a new AIProviderName member without matching\nonboarding evidence: a valid catalog JSON entry for Tier 2 providers (see\nabove), or a structurally valid manifest here for Tier 3/4 providers. A\nmanifest is structurally valid when it is a JSON object whose provider\nmatches the file name and which carries provider, tier, addedInPR,\naddedDate, filesTouched (an array of strings), mockedContractSection\nand manualTestStatus, plus tier4Justification when tier is 4. The gate\ndoes not retroactively require either for providers that predate the gate\n— see that tool's LEGACY_PROVIDERS list.","hierarchy":{"lvl0":"Provider Integration","lvl1":"Provider Manifests","lvl2":"How it's checked","lvl3":""}},
9753
- {"objectID":"c533e90a3190ff6ad955d7e0c25b0b6370956144cb2b59f1c07b4ffdb1b1e452","title":"Provider Descriptor Migration Ledger","url":"/docs/provider-integration/migration-ledger","content":"Provider Descriptor Migration Ledger\n\nInventory taken at origin/release @ 2cefa3ae4115f817f75a415b6bc70fc3ecaed2d3. TypeSafe was added afterwards (#1761) and is included below; the 25-entry count matched origin/release @ f536fd091.\n\nmistral, huggingface, deepseek and laya have since migrated to the JSON catalog and been removed from HAND_DESCRIPTORS (#1781; laya in the PR that added src/lib/providers/catalog/laya.json) — see Migrated below — and xor, perplexity-decider and cloudflare-clef (decision-only, like TypeSafe) were added as hand descriptors afterwards. Net effect: 25 minus the 3 migrated plus 3 (xor, perplexity-decider, cloudflare-clef) leaves 25 entries currently in HAND_DESCRIPTORS (src/lib/factories/providerDescriptors.ts). The category counts below (Shared adapter needed / Must remain class / Must remain core class) cover exactly those 25; the 4 migrated providers are recorded separately as done and no longer count toward \"what remains.\"\n\nThis ledger records, per provider, why it is (or isn't) a JSON-catalog migration candidate, so \"add a provider\" work doesn't re-litigate the same analysis per PR.\n\nEvery verdict allows one thing regardless of class: the static descriptor metadata (name, aliases, default model, credential env var names, setup URL) can always move into a class-backed JSON record. \"Must remain class\" means the execution — the inference loop (generate/stream/decide, per the provider's inferenceKinds), auth, media pipelines — cannot be reduced to declarative catalog data; it does not mean the provider is exempt from descriptor consolidation.\n\nMigrated (4)\n\nThe first three ran the same class-removal path this ledger recommended below: resolve the JSON/descriptor data conflicts, then delete the hand descriptor and hand-written subclass so the provider is fully catalog-derived.\n\n| Provider | Note |\n| ------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| mistral | Moved onto catalog/mistral.json. defaultModel now derives from the new optional models.registryDefaultModel field when present (only Mistral sets it), and the setupUrl/key-format/timeout/priority conflicts this ledger flagged were resolved in the JSON rather than carried forward. |\n| huggingface | Moved onto catalog/huggingface.json, which gained wire.apiKeyFallbackEnvVars (HF_TOKEN alongside HUGGINGFACE_API_KEY) and capabilities.tools: \"model-dependent\" — the two schema gaps this ledger flagged below before the extension landed. |\n| deepseek | Moved onto catalog/deepseek.json, using the new quirks.responseFormatDowngrade: \"json-schema-to-json-object\" field (DeepSeek 400s on json_schema) instead of an executable hook — the named-quirk approach this ledger recommended. It also sets quirks.replayReasoningContent: true. |\n| laya | Moved onto catalog/laya.json, the first decide entry. Its wire (endpoint, the auto model rule, routing.model, the request-id header, error rules and body shapes) is declarative data that ConfiguredDecisionProvider reads; the LayaProvider class was deleted. It keeps a model manifest, built from the entry, so neurolink models still lists it. |\n\nShared adapter needed (9)\n\nThree adapter families, not nine one-off migrations:\n\nLocal-runtime adapter (ollama, lm-studio, llamacpp) — one OpenAI-compatible local-runtime adapter with optional auth, model discovery/probe, actionable transport errors, timeout policy, optional embeddings. Vendor-specific pull/diagnostic guidance becomes adapter data.\n\nEmbedding-only adapter (voyage, jina, cohere) — one embedding-only provider adapter parameterized by path, request shape, batch size, response-extraction/index policy, unsupported-surface messages. jina extends it with an optional rerank operation profile (don't force reranking into the boolean capability shape). cohere composes this with a generic OpenAI chat adapter (it has both /compatibility/v1 chat and native /v2/embed); preserve its batch limit and body-field quirks in the embedding profile.\n\nImage-generation adapter (stability, ideogram, recraft) — one image-generation adapter family: explici","hierarchy":{"lvl0":"Provider Integration","lvl1":"Provider Descriptor Migration Ledger","lvl2":"","lvl3":""}},
9754
- {"objectID":"b5d36740e9c9cb41c6ccb01db0a9fb1f9c0ac8ac59f1084b9a92332dd79c3e4d","title":"Provider Descriptor Migration Ledger","url":"/docs/provider-integration/migration-ledger#provider-descriptor-migration-ledger","content":"Inventory taken at origin/release @ 2cefa3ae4115f817f75a415b6bc70fc3ecaed2d3. TypeSafe was added afterwards (#1761) and is included below; the 25-entry count matched origin/release @ f536fd091.\n\nmistral, huggingface, deepseek and laya have since migrated to the JSON catalog and been removed from HAND_DESCRIPTORS (#1781; laya in the PR that added src/lib/providers/catalog/laya.json) — see Migrated below — and xor, perplexity-decider and cloudflare-clef (decision-only, like TypeSafe) were added as hand descriptors afterwards. Net effect: 25 minus the 3 migrated plus 3 (xor, perplexity-decider, cloudflare-clef) leaves 25 entries currently in HAND_DESCRIPTORS (src/lib/factories/providerDescriptors.ts). The category counts below (Shared adapter needed / Must remain class / Must remain core class) cover exactly those 25; the 4 migrated providers are recorded separately as done and no longer count toward \"what remains.\"\n\nThis ledger records, per provider, why it is (or isn't) a JSON-catalog migration candidate, so \"add a provider\" work doesn't re-litigate the same analysis per PR.\n\nEvery verdict allows one thing regardless of class: the static descriptor metadata (name, aliases, default model, credential env var names, setup URL) can always move into a class-backed JSON record. \"Must remain class\" means the execution — the inference loop (generate/stream/decide, per the provider's inferenceKinds), auth, media pipelines — cannot be reduced to declarative catalog data; it does not mean the provider is exempt from descriptor consolidation.","hierarchy":{"lvl0":"Provider Integration","lvl1":"Provider Descriptor Migration Ledger","lvl2":"Provider Descriptor Migration Ledger","lvl3":""}},
9755
- {"objectID":"ff6dac10527e9e03a2da5e5a12274cdcd3d49262fbb4fe837cd96d400049ca6f","title":"Migrated (4)","url":"/docs/provider-integration/migration-ledger#migrated-4","content":"The first three ran the same class-removal path this ledger recommended below: resolve the JSON/descriptor data conflicts, then delete the hand descriptor and hand-written subclass so the provider is fully catalog-derived.\n\n| Provider | Note |\n| ------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| mistral | Moved onto catalog/mistral.json. defaultModel now derives from the new optional models.registryDefaultModel field when present (only Mistral sets it), and the setupUrl/key-format/timeout/priority conflicts this ledger flagged were resolved in the JSON rather than carried forward. |\n| huggingface | Moved onto catalog/huggingface.json, which gained wire.apiKeyFallbackEnvVars (HF_TOKEN alongside HUGGINGFACE_API_KEY) and capabilities.tools: \"model-dependent\" — the two schema gaps this ledger flagged below before the extension landed. |\n| deepseek | Moved onto catalog/deepseek.json, using the new quirks.responseFormatDowngrade: \"json-schema-to-json-object\" field (DeepSeek 400s on json_schema) instead of an executable hook — the named-quirk approach this ledger recommended. It also sets quirks.replayReasoningContent: true.","hierarchy":{"lvl0":"Provider Integration","lvl1":"Provider Descriptor Migration Ledger","lvl2":"Migrated (4)","lvl3":""}},
9753
+ {"objectID":"c533e90a3190ff6ad955d7e0c25b0b6370956144cb2b59f1c07b4ffdb1b1e452","title":"Provider Descriptor Migration Ledger","url":"/docs/provider-integration/migration-ledger","content":"Provider Descriptor Migration Ledger\n\nInventory taken at origin/release @ 2cefa3ae4115f817f75a415b6bc70fc3ecaed2d3. TypeSafe was added afterwards (#1761) and is included below; the 25-entry count matched origin/release @ f536fd091.\n\nmistral, huggingface, deepseek, laya and xor have since migrated to the JSON catalog and been removed from HAND_DESCRIPTORS (#1781; laya in the PR that added src/lib/providers/catalog/laya.json; xor in the PR that added src/lib/providers/catalog/xor.json) — see Migrated below — and perplexity-decider and cloudflare-clef (decision-only, like TypeSafe) were added as hand descriptors afterwards. Net effect: the 25-entry baseline minus the 3 baseline entries that migrated (mistral, huggingface, deepseek), plus the 2 added afterwards that stay hand-written (perplexity-decider, cloudflare-clef), leaves 24 entries currently in HAND_DESCRIPTORS (src/lib/factories/providerDescriptors.ts). laya and xor are not part of the 25: they were added to HAND_DESCRIPTORS after the baseline and then migrated, so they cancel out and neither is subtracted from it. The category counts below (Shared adapter needed / Must remain class / Must remain core class) cover exactly those 24; the 5 migrated providers are recorded separately as done and no longer count toward \"what remains.\"\n\nThis ledger records, per provider, why it is (or isn't) a JSON-catalog migration candidate, so \"add a provider\" work doesn't re-litigate the same analysis per PR.\n\nEvery verdict allows one thing regardless of class: the static descriptor metadata (name, aliases, default model, credential env var names, setup URL) can always move into a class-backed JSON record. \"Must remain class\" means the execution — the inference loop (generate/stream/decide, per the provider's inferenceKinds), auth, media pipelines — cannot be reduced to declarative catalog data; it does not mean the provider is exempt from descriptor consolidation.\n\nMigrated (5)\n\nThe first three ran the same class-removal path this ledger recommended below: resolve the JSON/descriptor data conflicts, then delete the hand descriptor and hand-written subclass so the provider is fully catalog-derived.\n\n| Provider | Note |\n| ------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| mistral | Moved onto catalog/mistral.json. defaultModel now derives from the new optional models.registryDefaultModel field when present (only Mistral sets it), and the setupUrl/key-format/timeout/priority conflicts this ledger flagged were resolved in the JSON rather than carried forward. |\n| huggingface | Moved onto catalog/huggingface.json, which gained wire.apiKeyFallbackEnvVars (HF_TOKEN alongside HUGGINGFACE_API_KEY) and capabilities.tools: \"model-dependent\" — the two schema gaps this ledger flagged below before the extension landed. |\n| deepseek | Moved onto catalog/deepseek.json, using the new quirks.responseFormatDowngrade: \"json-schema-to-json-object\" field (DeepSeek 400s on json_schema) instead of an executable hook — the named-quirk approach this ledger recommended. It also sets quirks.replayReasoningContent: true. ","hierarchy":{"lvl0":"Provider Integration","lvl1":"Provider Descriptor Migration Ledger","lvl2":"","lvl3":""}},
9754
+ {"objectID":"b5d36740e9c9cb41c6ccb01db0a9fb1f9c0ac8ac59f1084b9a92332dd79c3e4d","title":"Provider Descriptor Migration Ledger","url":"/docs/provider-integration/migration-ledger#provider-descriptor-migration-ledger","content":"Inventory taken at origin/release @ 2cefa3ae4115f817f75a415b6bc70fc3ecaed2d3. TypeSafe was added afterwards (#1761) and is included below; the 25-entry count matched origin/release @ f536fd091.\n\nmistral, huggingface, deepseek, laya and xor have since migrated to the JSON catalog and been removed from HAND_DESCRIPTORS (#1781; laya in the PR that added src/lib/providers/catalog/laya.json; xor in the PR that added src/lib/providers/catalog/xor.json) — see Migrated below — and perplexity-decider and cloudflare-clef (decision-only, like TypeSafe) were added as hand descriptors afterwards. Net effect: the 25-entry baseline minus the 3 baseline entries that migrated (mistral, huggingface, deepseek), plus the 2 added afterwards that stay hand-written (perplexity-decider, cloudflare-clef), leaves 24 entries currently in HAND_DESCRIPTORS (src/lib/factories/providerDescriptors.ts). laya and xor are not part of the 25: they were added to HAND_DESCRIPTORS after the baseline and then migrated, so they cancel out and neither is subtracted from it. The category counts below (Shared adapter needed / Must remain class / Must remain core class) cover exactly those 24; the 5 migrated providers are recorded separately as done and no longer count toward \"what remains.\"\n\nThis ledger records, per provider, why it is (or isn't) a JSON-catalog migration candidate, so \"add a provider\" work doesn't re-litigate the same analysis per PR.\n\nEvery verdict allows one thing regardless of class: the static descriptor metadata (name, aliases, default model, credential env var names, setup URL) can always move into a class-backed JSON record. \"Must remain class\" means the execution — the inference loop (generate/stream/decide, per the provider's inferenceKinds), auth, media pipelines — cannot be reduced to declarative catalog data; it does not mean the provider is exempt from descriptor consolidation.","hierarchy":{"lvl0":"Provider Integration","lvl1":"Provider Descriptor Migration Ledger","lvl2":"Provider Descriptor Migration Ledger","lvl3":""}},
9755
+ {"objectID":"f783c2b48d5ba6ff25f421bd7b7de07206120c1877e0fd8848cb270d393bd6b7","title":"Migrated (5)","url":"/docs/provider-integration/migration-ledger#migrated-5","content":"The first three ran the same class-removal path this ledger recommended below: resolve the JSON/descriptor data conflicts, then delete the hand descriptor and hand-written subclass so the provider is fully catalog-derived.\n\n| Provider | Note |\n| ------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| mistral | Moved onto catalog/mistral.json. defaultModel now derives from the new optional models.registryDefaultModel field when present (only Mistral sets it), and the setupUrl/key-format/timeout/priority conflicts this ledger flagged were resolved in the JSON rather than carried forward.","hierarchy":{"lvl0":"Provider Integration","lvl1":"Provider Descriptor Migration Ledger","lvl2":"Migrated (5)","lvl3":""}},
9756
9756
  {"objectID":"cbc4193e5e9ffb4c77dd167fe137bc62cfbab5adbe808e814a374670bef12175","title":"Shared adapter needed (9)","url":"/docs/provider-integration/migration-ledger#shared-adapter-needed-9","content":"Three adapter families, not nine one-off migrations:\n\nLocal-runtime adapter (ollama, lm-studio, llamacpp) — one OpenAI-compatible local-runtime adapter with optional auth, model discovery/probe, actionable transport errors, timeout policy, optional embeddings. Vendor-specific pull/diagnostic guidance becomes adapter data.\n\nEmbedding-only adapter (voyage, jina, cohere) — one embedding-only provider adapter parameterized by path, request shape, batch size, response-extraction/index policy, unsupported-surface messages. jina extends it with an optional rerank operation profile (don't force reranking into the boolean capability shape). cohere composes this with a generic OpenAI chat adapter (it has both /compatibility/v1 chat and native /v2/embed); preserve its batch limit and body-field quirks in the embedding profile.\n\nImage-generation adapter (stability, ideogram, recraft) — one image-generation adapter family: explicit multipart vs JSON request profile, base64-vs-URL response profile, custom auth-header support, model-path mapping as data. SSRF and bounded-read policy remain shared mandatory behavior, not per-vendor opt-outs.","hierarchy":{"lvl0":"Provider Integration","lvl1":"Provider Descriptor Migration Ledger","lvl2":"Shared adapter needed (9)","lvl3":""}},
9757
- {"objectID":"68866693ac3b73ea496e4c12c1b7d8fe2de069553e5d38707095387d8f39faba","title":"Must remain class (15)","url":"/docs/provider-integration/migration-ledger#must-remain-class-15","content":"| Provider | Why |\n| -------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |\n| bedrock | AWS SigV4/Converse protocol, custom loop, not OpenAI-compatible. Tier 4. |\n| openai | Chat portion is catalog-shaped, but embeddings, image generation, and OpenAI-specific telemetry/errors are executable behavior. |\n| vertex | Two native protocols (Google GenAI + Anthropic-on-Vertex) and multiple modality pipelines behind one provider identity.","hierarchy":{"lvl0":"Provider Integration","lvl1":"Provider Descriptor Migration Ledger","lvl2":"Must remain class (15)","lvl3":""}},
9757
+ {"objectID":"da986710e206bdfe9e761b9941c084a698a400e499994510b53989e7685fd3a6","title":"Must remain class (14)","url":"/docs/provider-integration/migration-ledger#must-remain-class-14","content":"| Provider | Why |\n| -------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |\n| bedrock | AWS SigV4/Converse protocol, custom loop, not OpenAI-compatible. Tier 4. |\n| openai | Chat portion is catalog-shaped, but embeddings, image generation, and OpenAI-specific telemetry/errors are executable behavior. |\n| vertex | Two native protocols (Google GenAI + Anthropic-on-Vertex) and multiple modality pipelines behind one provider identity.","hierarchy":{"lvl0":"Provider Integration","lvl1":"Provider Descriptor Migration Ledger","lvl2":"Must remain class (14)","lvl3":""}},
9758
9758
  {"objectID":"a4f69e09308f075830f2efa7c1b0126236c5ec0fc12bfe08be21764a627e47a5","title":"Must remain core class (1)","url":"/docs/provider-integration/migration-ledger#must-remain-core-class-1","content":"| Provider | Why |\n| ------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| openai-compatible | This is the generic protocol surface itself, not a direct vendor. It should consume shared descriptor/config primitives but must never become a fixed-vendor JSON row — collapsing it into the catalog would conflate \"the adapter\" with \"an entry in the adapter's catalog.\" |","hierarchy":{"lvl0":"Provider Integration","lvl1":"Provider Descriptor Migration Ledger","lvl2":"Must remain core class (1)","lvl3":""}},
9759
- {"objectID":"235850085d9102413140920b9d5e5e2ff6113d007c865f5d78012af80fbf1843","title":"Suggested execution order","url":"/docs/provider-integration/migration-ledger#suggested-execution-order","content":"The former steps 1–2 below (mistral; huggingface, deepseek) are complete, and laya has moved too — see Migrated above. What remains:\nThree shared adapters (local-runtime, embedding-only, image-generation) — each unlocks 3 providers at once; build once, migrate three.\ngoogle-ai descriptor-only JSON metadata — proof of concept for moving static descriptor data out of a \"must remain class\" provider without touching its execution.\nDirect-vendor \"must remain class\" providers (bedrock, openai, vertex, anthropic, azure, sagemaker, nvidia-nim) get descriptor-only JSON metadata migrations, execution untouched — lower priority, cosmetic consolidation only.\nAggregators (litellm, openrouter), the core adapter (openai-compatible), and the decision-only providers (typesafe, xor, perplexity-decider, cloudflare-clef) are excluded from the first-class-count migration priority entirely — the first three add no direct-vendor coverage however they're implemented, and typesafe/xor/perplexity-decider/cloudflare-clef are decide-only providers with no generate/stream surface to migrate at all.","hierarchy":{"lvl0":"Provider Integration","lvl1":"Provider Descriptor Migration Ledger","lvl2":"Suggested execution order","lvl3":""}},
9759
+ {"objectID":"235850085d9102413140920b9d5e5e2ff6113d007c865f5d78012af80fbf1843","title":"Suggested execution order","url":"/docs/provider-integration/migration-ledger#suggested-execution-order","content":"The former steps 1–2 below (mistral; huggingface, deepseek) are complete, and laya and xor have moved too — see Migrated above. What remains:\nThree shared adapters (local-runtime, embedding-only, image-generation) — each unlocks 3 providers at once; build once, migrate three.\ngoogle-ai descriptor-only JSON metadata — proof of concept for moving static descriptor data out of a \"must remain class\" provider without touching its execution.\nDirect-vendor \"must remain class\" providers (bedrock, openai, vertex, anthropic, azure, sagemaker, nvidia-nim) get descriptor-only JSON metadata migrations, execution untouched — lower priority, cosmetic consolidation only.\nAggregators (litellm, openrouter), the core adapter (openai-compatible), and the decision-only providers (typesafe, perplexity-decider, cloudflare-clef) are excluded from the first-class-count migration priority entirely — the first three add no direct-vendor coverage however they're implemented, and typesafe/perplexity-decider/cloudflare-clef are decide-only providers with no generate/stream surface to migrate at all.","hierarchy":{"lvl0":"Provider Integration","lvl1":"Provider Descriptor Migration Ledger","lvl2":"Suggested execution order","lvl3":""}},
9760
9760
  {"objectID":"6122b2e83358a45c64da87c1ca80a2d579cdfb087a6d9dc58b1e02805296b14a","title":"OpenAI-Compatible Provider Catalog","url":"/docs/provider-integration/openai-compat-catalog","content":"OpenAI-Compatible Provider Catalog\n\nEvery OpenAI-compatible provider in the catalog (80 as of 2026-09-29; the\ndirectory is the list) is registered from one JSON file each, under\nsrc/lib/providers/catalog/<id>.json, and served by one generic class,\nConfiguredOpenAICompatProvider\n(src/lib/providers/configuredOpenAICompat.ts). Adding another provider to\nthis family means adding one JSON file — no subclass, no registry edit, no\nhand-written enum member, no test edit.\n\nThe JSON is the source of truth\n\nOPENAI_COMPAT_CATALOG still exists and keeps its name and element type,\nbut it is now built by the loader (src/lib/providers/catalog/loader.ts)\nfrom the JSON files rather than hand-written. Two consumers read the JSON:\nCodegen (pnpm run codegen:catalog) writes the compile-time\n artifacts into marked regions — the AIProviderName member, the\n <Name>Models enum, the NeurolinkCredentials key — plus the generated\n index. Pre-commit and CI fail on stale output.\nThe loader builds the runtime entry; the descriptor, config options,\n context windows, pricing, vision map and model-choice tables all derive\n from it, as do the provider test suites' rows and counts.\n\nEach file is validated by a zod schema (src/lib/providers/catalog/schema.ts)\nwith a mirrored provider-catalog.schema.json for editor squiggles.\nProbe evidence (roster/auth/billing dates, live-matrix result, PR URL)\nlives in the file's evidence block — the old\ndocs/provider-integration/manifests/<id>.json files were folded into it.\n\nField-by-field reference and the escape hatches:\ntiers/tier-2-catalog-entry.md. Design rationale and the approved rulings:\ndocs/superpowers/plans/2026-08-28-provider-json-catalog-spec.md.\n\nWhen a provider belongs in the catalog\n\nA provider belongs in the JSON catalog if it needs only:\na credential (API key, optionally an extra field like Cloudflare's account id)\na base URL (static default + optional env override, or computed from an\n extra credential field)\na default/fallback model\nerror-message classification (auth / rate-limit / invalid-model / generic)\na named, closed catalog quirk. DeepSeek is the worked example: it 400s on\n json_schema structured-output requests, so deepseek.json sets\n quirks.responseFormatDowngrade: \"json-schema-to-json-object\" and the\n generic ConfiguredOpenAICompatProvider downgrades to json_object before\n sending — no subclass. It also sets quirks.replayReasoningContent: true:\n DeepSeek documents that each assistant turn's reasoning_content must go\n back on later requests once tools are in play, so the shared message\n converter and the streaming tool loop send it — for this quirk only, since\n strict OpenAI-compatible backends reject the unknown field.\na wire-proven capability such as\n capabilities.structuredOutputWithTools. The generic provider suppresses\n response_format when tools are attached by default; an explicit true\n keeps it on the same generate() or stream() request. Set this only after\n a combined tools-plus-schema request returned successfully. Separate tool\n and structured-output probes are not evidence for the combined capability.\n A stale opt-in is still protected by the runtime conflict retry, which drops\n structured output and retries rather than losing the turn.\n\nThe currently opted-in providers are Baseten, DeepSeek, Fireworks AI, GMI\nCloud, Inception Labs, io.net Intelligence, Novita AI, Together AI, Upstage and\nxAI. API Route remains opted out because its evidence verifies the features\nseparately, not together in one request. Mistral remains opted out because its\ncombined probes returned 429 twice, not a successful capability response.\n\nWhen a provider needs a dedicated subclass instead\n\nAzure OpenAI is deliberately not in the catalog because it overrides real\nrequest-shaping behavior that no named catalog quirk expresses:\nAzure OpenAI (src/lib/providers/azureOpenai.ts) overrides four hooks:\n getChatCompletionsURL (deployment-name URL routing across two Azure\n endpoint schemes), getAuthHeaders (Azure's api-key header instead of\n Authorization: Bearer), adjustRequestBody (renames max_tokens to\n max_completion_tokens for o-series/gpt-5+ deployments), and\n suppressResponseFormatWithTools (Azure supports both at once).\n\nIf a future provider needs any hook beyond the 3 mandatory ones\n(getProviderName, getDefaultModel, formatProviderError) or the 2\npurely-declarative optional ones (getFallbackModelName,\ngetFallbackModels) and that hook is not already a named catalog quirk, it\nneeds either a new closed quirk (the DeepSeek route) or a dedicated subclass\n(the Azure OpenAI route).\n\nError-message fidelity\n\nEach entry's errorRules is a direct, order-preserving translation of its\noriginal subclass's formatProviderError if/else ladder into rule data\n(status code and/or case-insensitive pattern), classified via\nclassifyProviderError()\n(src/lib/utils/errorClassifier.ts). Every bespoke message string is\npreserved verbatim — including xAI's \"top up your account\" quota URL and\nGroq's d","hierarchy":{"lvl0":"Provider Integration","lvl1":"OpenAI-Compatible Provider Catalog","lvl2":"","lvl3":""}},
9761
9761
  {"objectID":"9a91a5b4a32a9f1e89c6a28f762c3594c4a39d96d32cc9e6e1fa0f5cb3f609e4","title":"OpenAI-Compatible Provider Catalog","url":"/docs/provider-integration/openai-compat-catalog#openai-compatible-provider-catalog","content":"Every OpenAI-compatible provider in the catalog (80 as of 2026-09-29; the\ndirectory is the list) is registered from one JSON file each, under\nsrc/lib/providers/catalog/<id>.json, and served by one generic class,\nConfiguredOpenAICompatProvider\n(src/lib/providers/configuredOpenAICompat.ts). Adding another provider to\nthis family means adding one JSON file — no subclass, no registry edit, no\nhand-written enum member, no test edit.","hierarchy":{"lvl0":"Provider Integration","lvl1":"OpenAI-Compatible Provider Catalog","lvl2":"OpenAI-Compatible Provider Catalog","lvl3":""}},
9762
9762
  {"objectID":"16e60ee66171009a6638b5110cc8693f90c1a2cfde796c6932c3512d7f7421fb","title":"The JSON is the source of truth","url":"/docs/provider-integration/openai-compat-catalog#the-json-is-the-source-of-truth","content":"OPENAI_COMPAT_CATALOG still exists and keeps its name and element type,\nbut it is now built by the loader (src/lib/providers/catalog/loader.ts)\nfrom the JSON files rather than hand-written. Two consumers read the JSON:\nCodegen (pnpm run codegen:catalog) writes the compile-time\n artifacts into marked regions — the AIProviderName member, the\n <Name>Models enum, the NeurolinkCredentials key — plus the generated\n index. Pre-commit and CI fail on stale output.\nThe loader builds the runtime entry; the descriptor, config options,\n context windows, pricing, vision map and model-choice tables all derive\n from it, as do the provider test suites' rows and counts.\n\nEach file is validated by a zod schema (src/lib/providers/catalog/schema.ts)\nwith a mirrored provider-catalog.schema.json for editor squiggles.\nProbe evidence (roster/auth/billing dates, live-matrix result, PR URL)\nlives in the file's evidence block — the old\ndocs/provider-integration/manifests/<id>.json files were folded into it.\n\nField-by-field reference and the escape hatches:\ntiers/tier-2-catalog-entry.md. Design rationale and the approved rulings:\ndocs/superpowers/plans/2026-08-28-provider-json-catalog-spec.md.","hierarchy":{"lvl0":"Provider Integration","lvl1":"OpenAI-Compatible Provider Catalog","lvl2":"The JSON is the source of truth","lvl3":""}},
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@juspay/neurolink",
3
- "version": "12.55.2",
3
+ "version": "12.56.0",
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": {
@@ -491,7 +491,7 @@
491
491
  "eventsource-parser": "^3.0.8",
492
492
  "fast-xml-parser": "^5.7.0",
493
493
  "google-auth-library": "^10.6.1",
494
- "hono": "^4.13.5",
494
+ "hono": "4.13.13",
495
495
  "iconv-lite": "0.7.2",
496
496
  "inquirer": "^13.3.0",
497
497
  "jose": "^6.1.3",
@@ -592,6 +592,7 @@
592
592
  "@sveltejs/vite-plugin-svelte": "^7.0.0",
593
593
  "@types/cors": "^2.8.19",
594
594
  "@types/diff": "^8.0.0",
595
+ "@types/emscripten": "^1.41.6",
595
596
  "@types/express": "^5.0.6",
596
597
  "@types/fluent-ffmpeg": "^2.1.28",
597
598
  "@types/js-yaml": "^4.0.9",
@@ -709,7 +710,8 @@
709
710
  ],
710
711
  "overrides": {
711
712
  "esbuild@<=0.24.2": ">=0.25.0",
712
- "cookie@<0.7.0": ">=0.7.0",
713
+ "cookie@<0.7.0": "^0.7.2",
714
+ "@types/dom-webcodecs@<0.1.19": "^0.1.19",
713
715
  "@eslint/plugin-kit@<0.3.4": ">=0.3.4",
714
716
  "tmp@<0.2.6": ">=0.2.6",
715
717
  "axios@<1.13.5": ">=1.13.5",
@@ -760,6 +762,7 @@
760
762
  "@xmldom/xmldom": "0.9.12"
761
763
  },
762
764
  "patchedDependencies": {
765
+ "hono@4.13.13": "patches/hono@4.13.13.patch",
763
766
  "mammoth@1.12.0": "patches/mammoth@1.12.0.patch"
764
767
  }
765
768
  },
@@ -1,12 +0,0 @@
1
- import type { ProviderModelManifest } from "../../types/index.js";
2
- /**
3
- * XOR — the `decide` inference type, not text generation.
4
- *
5
- * `contextWindow` is the deployment's maximum prefill, shared by the state,
6
- * the questions and any images or video. `vision` describes `generate()`
7
- * input, which XOR does not serve; its image input is `DecisionRequest.images`.
8
- *
9
- * `maxOutputTokens` is required by the manifest type but has no honest value
10
- * for a model that emits no text, so a small non-zero figure is used.
11
- */
12
- export declare const xorManifest: ProviderModelManifest;
@@ -1,30 +0,0 @@
1
- /**
2
- * XOR — the `decide` inference type, not text generation.
3
- *
4
- * `contextWindow` is the deployment's maximum prefill, shared by the state,
5
- * the questions and any images or video. `vision` describes `generate()`
6
- * input, which XOR does not serve; its image input is `DecisionRequest.images`.
7
- *
8
- * `maxOutputTokens` is required by the manifest type but has no honest value
9
- * for a model that emits no text, so a small non-zero figure is used.
10
- */
11
- export const xorManifest = {
12
- defaultContextWindow: 250_000,
13
- models: {
14
- _default: {
15
- aliases: [],
16
- contextWindow: 250_000,
17
- maxOutputTokens: 256,
18
- vision: false,
19
- functionCalling: false,
20
- },
21
- "xor-1.1": {
22
- aliases: [],
23
- displayName: "XOR 1.1",
24
- contextWindow: 250_000,
25
- maxOutputTokens: 256,
26
- vision: false,
27
- functionCalling: false,
28
- },
29
- },
30
- };
@@ -1,48 +0,0 @@
1
- import type { DecisionError, DecisionPreparedMedia, DecisionState, NeurolinkCredentials } from "../types/index.js";
2
- import { SystemOneDecisionProvider } from "./systemOneDecision.js";
3
- /**
4
- * XOR Provider — the `decide` inference type only.
5
- *
6
- * XOR is Juspay's open-weights "System One" decision model, post-trained from
7
- * Qwen3.6-35B-A3B: the same typed `noul` / `choice` / `score` questions as
8
- * TypeSafe's Jev, on the same wire, in one batched pass. Unlike Jev and Laya it
9
- * also reads images and one video. The request loop, retries, auth circuit
10
- * breaker and answer parsing are shared with every decision provider in
11
- * {@link SystemOneDecisionProvider}.
12
- *
13
- * @see https://huggingface.co/juspay/xor
14
- */
15
- export declare class XorProvider extends SystemOneDecisionProvider {
16
- private readonly apiKey;
17
- private readonly baseURL;
18
- constructor(modelName?: string, sdk?: unknown, _region?: string, credentials?: NeurolinkCredentials["xor"]);
19
- protected getDefaultModel(): string;
20
- protected vendorLabel(): string;
21
- protected vendorDisplayName(): string;
22
- protected decisionApiKey(): string;
23
- protected missingKeyMessage(): string;
24
- protected missingConfigMessage(): string | undefined;
25
- protected decisionEndpoint(): string;
26
- protected decisionHeaders(): Record<string, string>;
27
- /**
28
- * `model` is always sent. A LiteLLM proxy checks team access against the
29
- * body's `model`, and refuses a request that names none. `images` is
30
- * omitted rather than sent empty, which the server rejects.
31
- */
32
- protected buildDecisionBody(state: DecisionState, questions: Record<string, Record<string, unknown>>, model: string, media?: DecisionPreparedMedia): Record<string, unknown>;
33
- /**
34
- * A 403 is deliberately NOT `authentication`: on a LiteLLM proxy it means the
35
- * team's allow-list lacks the model, which an admin can fix at any time, and
36
- * `authentication` would trip the per-instance breaker and keep XOR disabled
37
- * until restart even after access is granted. A 402 (a budget) is the same
38
- * kind of fixable gap. `DecisionErrorKind` has no billing kind, so both map
39
- * to `invalid_request`.
40
- */
41
- protected parseDecisionError(status: number, payload: unknown, requestId: string | undefined): DecisionError;
42
- /**
43
- * XOR's server sets `x-request-id` and `x-typesafe-request-id` to one value.
44
- * A proxy in front may replace or drop them, so its own call id is the last
45
- * resort.
46
- */
47
- protected readRequestId(headers: Headers): string | undefined;
48
- }
@@ -1,192 +0,0 @@
1
- import { XorModels } from "../constants/enums.js";
2
- import { logger } from "../utils/logger.js";
3
- import { redactUrlForError } from "../utils/logSanitize.js";
4
- import { getProviderModel } from "../utils/providerConfig.js";
5
- import { describeValidationErrors, isRecord, redactCredentials, SystemOneDecisionProvider, } from "./systemOneDecision.js";
6
- const XOR_ROUTE = "/v1/systemone";
7
- /**
8
- * XOR_BASE_URL is the origin of a deployment, but a `LITELLM_BASE_URL`-style
9
- * value ends in `/v1`, which the route already carries. Both spellings reduce
10
- * to the same base.
11
- */
12
- function normalizeBaseURL(raw) {
13
- return raw.replace(/\/+$/, "").replace(/\/v1$/i, "");
14
- }
15
- /** What a 500 says when the prefill was too long for the model to read. */
16
- const CONTEXT_LENGTH_MESSAGE = /(context|prefill|prompt).{0,40}(length|limit|too long|exceed)|(too long|exceeds?).{0,40}(context|tokens)/i;
17
- /**
18
- * A base URL that cannot work is refused up front, and its text is never
19
- * repeated: `fetch` rejects a URL with userinfo and echoes it in the error, the
20
- * route is appended after a query string or fragment, and any of them can hold a
21
- * credential.
22
- */
23
- function baseURLProblem(baseURL) {
24
- const fix = "Set XOR_BASE_URL or pass credentials.xor.baseURL to the origin, and give the key through XOR_API_KEY or credentials.xor.apiKey.";
25
- try {
26
- const url = new URL(baseURL);
27
- // `new URL()` accepts any scheme, so a host:port with no scheme parses as
28
- // one (`xor.internal:8080` has the scheme `xor.internal:`) and would reach
29
- // `fetch` as a network error instead of this message.
30
- if (url.protocol !== "https:" && url.protocol !== "http:") {
31
- return `The XOR base URL must start with https:// or http://. ${fix}`;
32
- }
33
- return url.username || url.password || url.search || url.hash
34
- ? `The XOR base URL must not carry credentials, a query string or a fragment. ${fix}`
35
- : undefined;
36
- }
37
- catch {
38
- return `The XOR base URL is not a valid absolute URL. ${fix}`;
39
- }
40
- }
41
- function xorErrorKind(status, message) {
42
- if (status === 401) {
43
- return "authentication";
44
- }
45
- if (status === 413) {
46
- return "max_tokens_exceeded";
47
- }
48
- if (status === 429) {
49
- return "rate_limit";
50
- }
51
- if (status === 503) {
52
- return "overloaded";
53
- }
54
- if (status >= 500) {
55
- return CONTEXT_LENGTH_MESSAGE.test(message)
56
- ? "max_tokens_exceeded"
57
- : "server";
58
- }
59
- return "invalid_request";
60
- }
61
- /**
62
- * Two envelopes reach the client. A LiteLLM proxy answers its own rejections
63
- * (a bad key, a team without the model, a budget) as
64
- * `{"error":{"message","type","code"}}`; XOR's own server answers as
65
- * `{"error":"<string>"}` — a shape that neither TypeSafe's nor Laya's parser
66
- * recognises, since both require `body.error` to be an object. FastAPI's
67
- * `{"detail":…}` is read too, in case something in front speaks it.
68
- */
69
- function readXorErrorMessage(body) {
70
- if (!isRecord(body)) {
71
- return undefined;
72
- }
73
- const { error, detail } = body;
74
- if (isRecord(error) &&
75
- typeof error.message === "string" &&
76
- error.message.length > 0) {
77
- return error.message;
78
- }
79
- if (typeof error === "string" && error.length > 0) {
80
- return error;
81
- }
82
- if (Array.isArray(detail)) {
83
- return `Request failed validation — ${describeValidationErrors(detail)}`;
84
- }
85
- return typeof detail === "string" && detail.length > 0 ? detail : undefined;
86
- }
87
- /**
88
- * XOR Provider — the `decide` inference type only.
89
- *
90
- * XOR is Juspay's open-weights "System One" decision model, post-trained from
91
- * Qwen3.6-35B-A3B: the same typed `noul` / `choice` / `score` questions as
92
- * TypeSafe's Jev, on the same wire, in one batched pass. Unlike Jev and Laya it
93
- * also reads images and one video. The request loop, retries, auth circuit
94
- * breaker and answer parsing are shared with every decision provider in
95
- * {@link SystemOneDecisionProvider}.
96
- *
97
- * @see https://huggingface.co/juspay/xor
98
- */
99
- export class XorProvider extends SystemOneDecisionProvider {
100
- apiKey;
101
- baseURL;
102
- constructor(modelName, sdk, _region, credentials) {
103
- super(modelName, "xor", sdk);
104
- this.apiKey =
105
- credentials?.apiKey?.trim() || (process.env.XOR_API_KEY?.trim() ?? "");
106
- // No built-in endpoint: XOR is reached at a deployment or through a proxy
107
- // route to one, so the base URL comes only from config. `||`, not `??`, so
108
- // a blank one counts as unset.
109
- this.baseURL = normalizeBaseURL(credentials?.baseURL?.trim() || process.env.XOR_BASE_URL?.trim() || "");
110
- // A base URL with `user:pass@` or a `?token=` is refused when a request is
111
- // made, but it is redacted here as well so a misconfigured value cannot leak
112
- // through this line either.
113
- logger.debug("XOR Provider initialized (decide only)", {
114
- modelName: this.modelName,
115
- baseURL: this.baseURL ? redactUrlForError(this.baseURL) : "(not set)",
116
- });
117
- }
118
- getDefaultModel() {
119
- return getProviderModel("XOR_MODEL", XorModels.XOR_1_1);
120
- }
121
- vendorLabel() {
122
- return "XOR";
123
- }
124
- vendorDisplayName() {
125
- return "XOR";
126
- }
127
- decisionApiKey() {
128
- return this.apiKey;
129
- }
130
- missingKeyMessage() {
131
- return "XOR requires an API key. Set XOR_API_KEY or pass credentials.xor.apiKey.";
132
- }
133
- missingConfigMessage() {
134
- return this.baseURL
135
- ? baseURLProblem(this.baseURL)
136
- : "XOR requires a base URL. Set XOR_BASE_URL or pass credentials.xor.baseURL.";
137
- }
138
- decisionEndpoint() {
139
- return `${this.baseURL}${XOR_ROUTE}`;
140
- }
141
- decisionHeaders() {
142
- return {
143
- Authorization: `Bearer ${this.apiKey}`,
144
- "Content-Type": "application/json",
145
- };
146
- }
147
- /**
148
- * `model` is always sent. A LiteLLM proxy checks team access against the
149
- * body's `model`, and refuses a request that names none. `images` is
150
- * omitted rather than sent empty, which the server rejects.
151
- */
152
- buildDecisionBody(state, questions, model, media) {
153
- return {
154
- model,
155
- state,
156
- questions,
157
- ...(media && media.images.length > 0 ? { images: media.images } : {}),
158
- ...(media?.video ? { video: media.video } : {}),
159
- };
160
- }
161
- /**
162
- * A 403 is deliberately NOT `authentication`: on a LiteLLM proxy it means the
163
- * team's allow-list lacks the model, which an admin can fix at any time, and
164
- * `authentication` would trip the per-instance breaker and keep XOR disabled
165
- * until restart even after access is granted. A 402 (a budget) is the same
166
- * kind of fixable gap. `DecisionErrorKind` has no billing kind, so both map
167
- * to `invalid_request`.
168
- */
169
- parseDecisionError(status, payload, requestId) {
170
- const fallback = `XOR request failed with HTTP ${status}`;
171
- const message = redactCredentials(readXorErrorMessage(payload) ?? fallback, this.apiKey) || fallback;
172
- const kind = xorErrorKind(status, message);
173
- return {
174
- kind,
175
- message,
176
- status,
177
- requestId,
178
- retryable: kind === "rate_limit" || kind === "overloaded" || kind === "server",
179
- };
180
- }
181
- /**
182
- * XOR's server sets `x-request-id` and `x-typesafe-request-id` to one value.
183
- * A proxy in front may replace or drop them, so its own call id is the last
184
- * resort.
185
- */
186
- readRequestId(headers) {
187
- return (headers.get("x-request-id") ??
188
- headers.get("x-typesafe-request-id") ??
189
- headers.get("x-litellm-call-id") ??
190
- undefined);
191
- }
192
- }