@juspay/neurolink 12.47.8 → 12.47.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +2 -2
- package/dist/browser/neurolink.min.js +377 -377
- package/dist/providers/openAI/client.js +12 -27
- package/dist/proxy/proxyFetch.d.ts +12 -0
- package/dist/proxy/proxyFetch.js +33 -10
- package/dist/utils/safeFetch.d.ts +6 -0
- package/dist/utils/safeFetch.js +54 -22
- package/dist/utils/ssrfGuard.d.ts +16 -0
- package/dist/utils/ssrfGuard.js +55 -0
- package/docs-site/static/search-index.json +9 -9
- package/package.json +1 -1
|
@@ -4642,7 +4642,7 @@
|
|
|
4642
4642
|
{"objectID":"caf02eee26aa7729661ed647c22f28f178d24a17df1db96a91bd1eab695f9c5c","title":"VideoOutputOptions","url":"/docs/features/video-generation#videooutputoptions","content":"Options for video output configuration:","hierarchy":{"lvl0":"Features","lvl1":"Video Generation with Veo 3.1","lvl2":"VideoOutputOptions","lvl3":""}},
|
|
4643
4643
|
{"objectID":"fce4213cacd85364d286746562ea069e475294cfebba4d64d0af73d2c424d975","title":"VideoGenerationResult","url":"/docs/features/video-generation#videogenerationresult","content":"Result type for generated video:","hierarchy":{"lvl0":"Features","lvl1":"Video Generation with Veo 3.1","lvl2":"VideoGenerationResult","lvl3":""}},
|
|
4644
4644
|
{"objectID":"cefe6d3bbf734ed3f4ac6c12a9a5b7978cf97b83290ddb0ccb10c3f9d4015540","title":"Extended GenerateResult","url":"/docs/features/video-generation#extended-generateresult","content":"The generate() function returns an extended result when video mode is enabled:","hierarchy":{"lvl0":"Features","lvl1":"Video Generation with Veo 3.1","lvl2":"Extended GenerateResult","lvl3":""}},
|
|
4645
|
-
{"objectID":"dda02ada49679c68c3b7f9f0a943c4be35dad2271bd6b0c327a1b5f45633939c","title":"Configuration Options","url":"/docs/features/video-generation#configuration-options","content":"| Option | Type | Default | Required | Description |\n| -------------------------- | ------------------- | ---------------- | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| input.images[0] | Buffer \\| string | - | Yes | Image buffer, file path, or URL |\n| input.text | string | - | Yes | Text description of desired video |\n| output.video.provider | VideoProviderName | \"vertex\" | No | Video handler: vertex (default), kling, runway, replicate. See Routing Across Providers.
|
|
4645
|
+
{"objectID":"dda02ada49679c68c3b7f9f0a943c4be35dad2271bd6b0c327a1b5f45633939c","title":"Configuration Options","url":"/docs/features/video-generation#configuration-options","content":"| Option | Type | Default | Required | Description |\n| -------------------------- | ------------------- | ---------------- | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| input.images[0] | Buffer \\| string | - | Yes | Image buffer, file path, or URL |\n| input.text | string | - | Yes | Text description of desired video |\n| output.video.provider | VideoProviderName | \"vertex\" | No | Video handler: vertex (default), kling, runway, replicate. See Routing Across Providers.","hierarchy":{"lvl0":"Features","lvl1":"Video Generation with Veo 3.1","lvl2":"Configuration Options","lvl3":""}},
|
|
4646
4646
|
{"objectID":"413c75fb15e0809a8de1076feb1f1791b978918974ba4c37caf06442d6af06b3","title":"1. Prompt Engineering","url":"/docs/features/video-generation#1-prompt-engineering","content":"Prompt Template Examples:\n\n| Use Case | Template |\n| ---------------- | ---------------------------------------------------------------------------------- |\n| Product Rotation | \"Elegant 360-degree rotation of [product] with [lighting style] lighting\" |\n| Hero Shot | \"Cinematic zoom from [distance] to [detail] with [motion style] camera movement\" |\n| Lifestyle | \"Natural scene with [subject] in [environment], subtle ambient movement\" |\n| Social Media | \"Quick dynamic reveal of [product] with energetic transitions\" |","hierarchy":{"lvl0":"Features","lvl1":"Video Generation with Veo 3.1","lvl2":"1. Prompt Engineering","lvl3":""}},
|
|
4647
4647
|
{"objectID":"b2caf49c96c701c855f0836f814b17eac08f6458c181b68498078d10d86430f5","title":"4. Quality vs. Cost Tradeoffs","url":"/docs/features/video-generation#4-quality-vs-cost-tradeoffs","content":"| Setting | Quality | Cost | Use Case |\n| --------- | ------- | ------- | ------------------------ |\n| 720p, 4s | Good | Low | Quick previews, drafts |\n| 720p, 8s | Good | Medium | Social media content |\n| 1080p, 6s | High | High | Marketing materials |\n| 1080p, 8s | Highest | Highest | Professional productions |","hierarchy":{"lvl0":"Features","lvl1":"Video Generation with Veo 3.1","lvl2":"4. Quality vs. Cost Tradeoffs","lvl3":""}},
|
|
4648
4648
|
{"objectID":"5ea53d45139063ed91c05ba353a19b7a0719e1fcc1b496633fcd2d6893e05bf2","title":"Validation Rules","url":"/docs/features/video-generation#validation-rules","content":"| Parameter | Validation | Error Type | Example Message |\n| -------------------------- | ------------------------------- | -------------- | -------------------------------------------------- |\n| input.images[0] | Must be valid image file/buffer | NeuroLinkError | Invalid image format. Supported: JPEG, PNG, WebP |\n| input.images[0] | Max 10MB | NeuroLinkError | Image size exceeds 10MB limit |\n| input.text | 1-500 characters | NeuroLinkError | Prompt must be between 1 and 500 characters |\n| output.video.resolution | 720p or 1080p | NeuroLinkError | Invalid resolution. Use '720p' or '1080p' |\n| output.video.length | 4, 6, or 8 | NeuroLinkError | Invalid length. Use 4, 6, or 8 seconds |\n| output.video.aspectRatio | 9:16 or 16:9 | NeuroLinkError | Invalid aspect ratio. Use '9:16' or '16:9' |","hierarchy":{"lvl0":"Features","lvl1":"Video Generation with Veo 3.1","lvl2":"Validation Rules","lvl3":""}},
|
|
@@ -5670,7 +5670,7 @@
|
|
|
5670
5670
|
{"objectID":"8772f256e59f69594bfa7c3d3f4e24e19b712cbb2646b9d04008868b7a1833f3","title":"CLI","url":"/docs/getting-started/providers/dashscope#cli","content":"npx @juspay/neurolink generate \"Hello\" --provider dashscope\ntypescript\nawait neurolink.generate({\n input: { text: \"Hello\" },\n provider: \"dashscope\",\n credentials: { dashscope: { apiKey: process.env.DASHSCOPEAPIKEY } },\n});\n`","hierarchy":{"lvl0":"Getting Started","lvl1":"Alibaba Cloud Model Studio (DashScope) Provider Guide","lvl2":"CLI","lvl3":""}},
|
|
5671
5671
|
{"objectID":"4d3ec8b035c5aab1c8bf8263e769d84773f64dff75cf094fbeea9afefdafc888","title":"Base URL","url":"/docs/getting-started/providers/dashscope#base-url","content":"The catalog uses https://dashscope-intl.aliyuncs.com/compatible-mode/v1. The\nvendor's regions page\nlists dashscope-intl.aliyuncs.com as the Singapore DashScope domain, labelled\n\"existing domain\", and says the China (Beijing) and Singapore regions each\nsupport one service deployment scope, Chinese mainland and International\nrespectively. The\nOpenAI-compatible Chat page\nsays \"The existing domain remains fully functional.\"\n\nThe regions page also documents a workspace-dedicated domain,\nhttps://{WorkspaceId}.ap-southeast-1.maas.aliyuncs.com/compatible-mode/v1,\nlabelled \"(recommended)\" in its endpoint comparison. To use it, set\nDASHSCOPE_BASE_URL to that URL with your workspace id. The same page states:\n\"The DashScope domain (dashscope.aliyuncs.com) will no longer support new\nfeatures after September 30, 2026.\"","hierarchy":{"lvl0":"Getting Started","lvl1":"Alibaba Cloud Model Studio (DashScope) Provider Guide","lvl2":"Base URL","lvl3":""}},
|
|
5672
5672
|
{"objectID":"3807695c9f2813a8f67a551bddf289d5980d5dbea2a42fbb6079c24e0b05ee3c","title":"Models","url":"/docs/getting-started/providers/dashscope#models","content":"| Model | Context | Vision | $/M in · out | Notes |\n| ------------------- | ------- | ---------------- | ------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |\n| qwen3.8-max ⭐ | 1M | yes | $2 / $6 | NeuroLink default. The model in the vendor's OpenAI-compatible examples; the text-generation page says \"For the strongest reasoning, choose qwen3.8-max.\" Thinking mode, Function Calling, Built-in tools and Structured output Supported. |\n| qwen3.8-flash | 1M | yes | $0.15 / $0.47 | Fallback. Thinking mode, Function Calling, Built-in tools and Structured output Supported. |\n| qwen3.7-plus | 1M | yes | — | Fallback. The text-generation page says \"We recommend qwen3.7-plus for balanced performance and cost, with full tool calling and a 1M-token context window for large codebases.\" |\n| qwen3.8-max-0902 | 1M | yes | $2 / $6 | Fallback. Thinking mode, Function Calling, Built-in tools and Structured output Supported. |\n| qwen3.7-flash | 1M | yes | — | Fallback. Thinking mode, Function Calling, Built-in tools and Structured output Supported.","hierarchy":{"lvl0":"Getting Started","lvl1":"Alibaba Cloud Model Studio (DashScope) Provider Guide","lvl2":"Models","lvl3":""}},
|
|
5673
|
-
{"objectID":"78c324b99cf27436784db89a263aec3110ca7db427f752870d96ecd3c479ae84","title":"Verification status","url":"/docs/getting-started/providers/dashscope#verification-status","content":"Tier-2 onboarding requires evidence before a provider is accepted, and\npnpm run verify:provider-onboarding gates it in CI. This is what the catalog\ncurrently records for Alibaba Cloud Model Studio (DashScope) —\ndocs-verified only, not live-verified:\n\n| Probe | Result |\n| ------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| Roster | unauthenticated GET /compatible-mode/v1/models, HTTP 401 without a key, 2026-09-29. Model ids are taken from the vendor's text-generation and Models pages (retrieved 2026-09-29); the roster is not verified |\n| Auth-failure shape | the same GET returned a JSON body with error.message \"You didn't provide an API key.
|
|
5673
|
+
{"objectID":"78c324b99cf27436784db89a263aec3110ca7db427f752870d96ecd3c479ae84","title":"Verification status","url":"/docs/getting-started/providers/dashscope#verification-status","content":"Tier-2 onboarding requires evidence before a provider is accepted, and\npnpm run verify:provider-onboarding gates it in CI. This is what the catalog\ncurrently records for Alibaba Cloud Model Studio (DashScope) —\ndocs-verified only, not live-verified:\n\n| Probe | Result |\n| ------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| Roster | unauthenticated GET /compatible-mode/v1/models, HTTP 401 without a key, 2026-09-29. Model ids are taken from the vendor's text-generation and Models pages (retrieved 2026-09-29); the roster is not verified |\n| Auth-failure shape | the same GET returned a JSON body with error.message \"You didn't provide an API key.","hierarchy":{"lvl0":"Getting Started","lvl1":"Alibaba Cloud Model Studio (DashScope) Provider Guide","lvl2":"Verification status","lvl3":""}},
|
|
5674
5674
|
{"objectID":"a2c7aa04c54b187cd6b44bece5430acb5c311feca6195d44bcdf6c0749444354","title":"Troubleshooting","url":"/docs/getting-started/providers/dashscope#troubleshooting","content":"The rows below restate what the vendor's\nerror-code page\ngives for the named error.\n\n| Symptom | Cause the vendor lists | Fix the vendor lists |\n| --------------------------------------- | --------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------ |\n| HTTP 401 invalid_api_key | Among the causes: the API key and the base URL belong to different regions | Use an API key from the Singapore region page together with the Singapore base URL |\n| HTTP 403 AllocationQuota.FreeTierOnly | \"Cause 2\": the free quota exhaustion stop was enabled and requests were made after the free quota ran out | Disable the free quota exhaustion stop switch to continue on a paid basis |\n| HTTP 400 Arrearage | The Alibaba Cloud account associated with the API key has an overdue payment | Check Expenses and Costs on the vendor's billing console and recharge |\n| HTTP 404 model_not_found | The model does not exist, or Model Studio has not been activated | Compare the model value with the Models page; activate model services in the Model Marketplace |\n| HTTP 429 Throttling | API calls triggered rate limiting | \"Reduce call frequency or retry later.\" |","hierarchy":{"lvl0":"Getting Started","lvl1":"Alibaba Cloud Model Studio (DashScope) Provider Guide","lvl2":"Troubleshooting","lvl3":""}},
|
|
5675
5675
|
{"objectID":"7f7161d64efdcc9bf9835b94d1ff319fbeddc6e3868d6df2b5ae50bb9943dd32","title":"See also","url":"/docs/getting-started/providers/dashscope#see-also","content":"Provider setup overview\nAll providers\nTier-2 onboarding — how this provider's JSON becomes a working integration\nProvider feature compatibility","hierarchy":{"lvl0":"Getting Started","lvl1":"Alibaba Cloud Model Studio (DashScope) Provider Guide","lvl2":"See also","lvl3":""}},
|
|
5676
5676
|
{"objectID":"b2be5208100a44ce994ffae3b90fca7b5cf973105450c48eb805966668653ee4","title":"Deepgram Provider Guide","url":"/docs/getting-started/providers/deepgram","content":"Deepgram Provider Guide\n\nFast, accurate speech-to-text with streaming, speaker diarization, and smart formatting\n\nSTT-only in NeuroLink — Deepgram is registered as the STT provider id\ndeepgram. Deepgram's TTS product is not wired in NeuroLink today; for\nTTS use openai-tts, elevenlabs, azure-tts, or google-ai.\n\nOverview\n\nDeepgram is a speech recognition provider optimised for speed and accuracy in production environments. NeuroLink wraps Deepgram's Listen API, giving you access to the Nova-2 and Nova-3 model families through the standard generate() call. Deepgram's strengths include real-time streaming transcription over WebSocket, speaker diarization for multi-speaker audio, and smart formatting that cleans up dates, currency, and numbers automatically.\n\nKey Facts\n\n| Property | Value |\n| ---------------------- | --------------------------------------------- |\n| Provider ID | deepgram |\n| API endpoint | https://api.deepgram.com/v1/listen |\n| Streaming endpoint | wss://api.deepgram.com/v1/listen |\n| Default model | nova-2 |\n| Formats | mp3, wav, ogg, opus |\n| Max audio | 2 hours (7,200 seconds) per request |\n| Languages | 40+ languages and dialects |\n| Streaming | Yes (WebSocket-based real-time transcription) |\n\nQuick Start\nGet an API Key\n\nSign up at https://console.deepgram.com and create an API key under Settings → API Keys.\nConfigure Environment\n\nAdd to your .env file:\nInstall NeuroLink\nTranscribe Your First Audio File\n\nSupported Models\n\n| Model ID | Description | Best For |\n| ------------------ | -------------------------------------------------- | --------------------------------------- |\n| nova-2 (default) | Fastest, lowest Word Error Rate in the Nova family | General transcription, production use |\n| nova-2-general | General-purpose variant, same as nova-2 | Broad use cases |\n| nova-2-meeting | Optimised for multi-speaker meeting audio | Video conferences, recordings |\n| nova-2-phonecall | Tuned for telephone audio quality | Call centre, PSTN audio |\n| nova-2-voicemail | Handles background noise and compressed audio | Voicemail transcription |\n| nova-2-finance | Finance-domain vocabulary boost | Earnings calls, financial content |\n| nova-2-medical | Medical terminology | Clinical notes, consultations |\n| nova-3 | Next-generation model with improved accuracy | Demanding accuracy requirements |\n| nova | Previous generation Nova | Legacy compatibility |\n| enhanced | High accuracy, slower processing | Archival, quality-critical paths |\n| base | Fastest, lower accuracy | Draft transcriptions, cost optimisation |\n\nSDK Usage\n\nBasic Transcription\n\nChoosing a Model\n\nSmart Formatting\n\nSmart formatting cleans up numbers, currency, dates, and other structured data automatically:\n\nSpeaker Diarization\n\nIdentify who spoke when in multi-speaker audio:\n\nUtterance Segmentation\n\nSplit audio into utterance-level segments with speaker and timing information:\n\nWord-Level Timestamps\n\nCustom Vocabulary / Keyword Boosting\n\nImprove recognition of domain-specific terms:\n\nContent Redaction\n\nAutomatically redact sensitive data from transcripts:\n\nReal-Time Streaming Transcription\n\nUse the DeepgramSTT handler directly for WebSocket-based streaming:\n\nPer-Call Credential Override\n\nCLI Usage\n\nBasic Transcription\n\nLanguage Selection\n\nSmart Formatting\n\nSpeaker Diarization\n\nSupported Languages\n\nDeepgram supports 40+ languages and regional dialects. Key languages available with diarization and punctuation:\n\n| Code | Language |\n| ------- | ------------ |\n| en | English |\n| en-US | English (US) |\n| en-GB | English (UK) |\n| es | Spanish |\n| fr | French |\n| de | German |\n| it | Italian |\n| pt | Portuguese |\n| nl | Dutch |\n| ja | Japanese |\n| ko | Korean |\n| zh | Chinese |\n| hi | Hindi |\n| ru | Russian |\n\nFor the full language list, see the Deepgram language support docs.\n\nConfiguration Reference\n\n| Environment Variable | Required | Default | Description |\n| -------------------- | -------- | -------- | ------------------------------ |\n| DEEPGRAM_API_KEY | Yes | — | Deepgram API key |\n| DEEPGRAM_MODEL | No | nova-2 | Default transcription model |\n| DEEPGRAM_LANGUAGE | No | en-US | Default transcription language |\n\n","hierarchy":{"lvl0":"Getting Started","lvl1":"Deepgram Provider Guide","lvl2":"","lvl3":""}},
|
|
@@ -5808,7 +5808,7 @@
|
|
|
5808
5808
|
{"objectID":"ba58bfebf84dce1e3ebc6f75220da9323b2422bf93673f27f2f3f22e7ca4586f","title":"CLI","url":"/docs/getting-started/providers/featherless-ai#cli","content":"npx @juspay/neurolink generate \"Hello\" --provider featherless-ai\ntypescript\nawait neurolink.generate({\n input: { text: \"Hello\" },\n provider: \"featherless-ai\",\n credentials: {\n \"featherless-ai\": { apiKey: process.env.FEATHERLESSAIAPI_KEY },\n },\n});\n`","hierarchy":{"lvl0":"Getting Started","lvl1":"Featherless AI Provider Guide","lvl2":"CLI","lvl3":""}},
|
|
5809
5809
|
{"objectID":"aac706f0b9e4ef68cab16a551eb94bf66fe5a93cad84c2c8cb003d09fb75e42a","title":"Models","url":"/docs/getting-started/providers/featherless-ai#models","content":"Featherless's live roster is enormous — 22,060 models as of 2026-09-28,\nspanning mainline instruction-tuned checkpoints alongside a very large number\nof community roleplay, uncensored and \"abliterated\" (safety-refusal-removed)\nfine-tunes; Featherless's own site markets these as first-class catalog\nfilters (\"LLMs for Roleplay\", \"Uncensored Models\", \"Abliterated Models\"). This\ncatalog entry lists 12 models — a bounded, verifiable slice, not the whole\nroster — chosen to include the default, its closest official counterpart, and\na representative spread of the architectures Featherless serves (Llama-3.3-70B\nfamily, QRWKV, RWKV5).\n\n| Model | Context | Vision | $/M in · out | Notes |\n| ---------------------------------------------- | ------- | ------ | ------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| unsloth/Llama-3.3-70B-Instruct ⭐ | 32K | no | $2.60 / $3.00 | Recommended — an ungated community re-upload of Meta's Llama 3.3 70B Instruct. Chosen as default because the official meta-llama id is gated (see below). Roster reports tool_use: true. |\n| meta-llama/Llama-3.3-70B-Instruct | 32K | no | $0.65 / $0.75 | Meta's official weights. Hugging-Face-gated on Featherless (HTTP 403 until unlocked in the account UI) — kept as a fallback, not the default. |\n| Sao10K/L3.3-70B-Euryale-v2.3 | 32K | no | $0.65 / $0.75 | Roleplay/long-form-writing Llama-3.3-70B fine-tune. Not gated; roster-listed only.","hierarchy":{"lvl0":"Getting Started","lvl1":"Featherless AI Provider Guide","lvl2":"Models","lvl3":""}},
|
|
5810
5810
|
{"objectID":"3c01830b2f0ad1b3e24cc8906bbf820cbf9bce36f4fc799eaaf404db60ac1a4d","title":"Verification status","url":"/docs/getting-started/providers/featherless-ai#verification-status","content":"Tier-2 onboarding requires evidence before a provider is accepted, and\npnpm run verify:provider-onboarding gates it in CI. This entry was built\nentirely credential-free — no signup, no API key, no POST request to\nFeatherless was made — so it records what a public, unauthenticated pass can\nprove and nothing more:\n\n| Probe | Result |\n| --------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| Roster | unauthenticated GET /v1/models, HTTP 200, 22,060 models, 2026-09-28 |\n| Billing | unauthenticated GET https://featherless.ai/pricing, HTTP 200, 2026-09-28 — no free tier found anywhere on the page; plans start at $25/mo |\n| Auth rejection | not probed — would require a POST request, which credential-free onboarding does not permit","hierarchy":{"lvl0":"Getting Started","lvl1":"Featherless AI Provider Guide","lvl2":"Verification status","lvl3":""}},
|
|
5811
|
-
{"objectID":"9313497b2b07b4c2105ddaf14337e3352bdc192c493a5dd7d023b19c4145127f","title":"Troubleshooting","url":"/docs/getting-started/providers/featherless-ai#troubleshooting","content":"| Symptom | Cause | Fix |\n| ------------------------------------------- | --------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| Invalid Featherless API key | FEATHERLESS_AI_API_KEY unset or wrong | Check the key in your Featherless account at https://featherless.ai/register |\n| HTTP 403, \"model is gated\" | The requested model (e.g.","hierarchy":{"lvl0":"Getting Started","lvl1":"Featherless AI Provider Guide","lvl2":"Troubleshooting","lvl3":""}},
|
|
5811
|
+
{"objectID":"9313497b2b07b4c2105ddaf14337e3352bdc192c493a5dd7d023b19c4145127f","title":"Troubleshooting","url":"/docs/getting-started/providers/featherless-ai#troubleshooting","content":"| Symptom | Cause | Fix |\n| ------------------------------------------- | --------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| Invalid Featherless API key | FEATHERLESS_AI_API_KEY unset or wrong | Check the key in your Featherless account at https://featherless.ai/register |\n| HTTP 403, \"model is gated\" | The requested model (e.g. meta-llama/Llama-3.3-70B-Instruct) is Hugging-Face-gated on Featherless | Open the model's page on featherless.ai while signed in and click \"Unlock Model\" to accept its license, or use the ungated unsloth/Llama-3.3-70B-Instruct default instead |\n| Model not found | The roster changed since 2026-09-28, or the id was mistyped | Pick a current id from the unauthenticated GET /v1/models roster or https://featherless.ai/models |\n| HTTP 400, \"This Model is Cold\" | Featherless documents cold/loading/warm model states; a cold model needs to load | Retry — warm-up can take from a few minutes up to an hour for very large models, per Featherless's error-codes page |\n| HTTP 503, \"Service Temporarily Unavailable\" | Featherless","hierarchy":{"lvl0":"Getting Started","lvl1":"Featherless AI Provider Guide","lvl2":"Troubleshooting","lvl3":""}},
|
|
5812
5812
|
{"objectID":"971ab825ba3dee7648e70b4787f4ded05ea1075e91f5a450ea2fbc643a9bc869","title":"See also","url":"/docs/getting-started/providers/featherless-ai#see-also","content":"Provider setup overview\nAll providers\nTier-2 onboarding — how this provider's JSON becomes a working integration\nProvider feature compatibility","hierarchy":{"lvl0":"Getting Started","lvl1":"Featherless AI Provider Guide","lvl2":"See also","lvl3":""}},
|
|
5813
5813
|
{"objectID":"b1184b197b42e32c5be5fb34fb171453c9691187c6fd632ea6ee2ffc096329ad","title":"Fireworks AI Provider Guide","url":"/docs/getting-started/providers/fireworks","content":"Fireworks AI Provider Guide\n\nOpen-model inference tuned for low-latency production workloads\n\nOverview\n\nFireworks AI hosts Kimi, GPT-OSS, Qwen, GLM and\nother open models with aggressive throughput optimizations.\nNeuroLink talks to the OpenAI-compatible endpoint at api.fireworks.ai.\n\nKey Facts\nProtocol: OpenAI-compatible (/inference/v1/chat/completions)\nDefault base URL: https://api.fireworks.ai/inference/v1\nDefault model: accounts/fireworks/models/kimi-k3 (vision-capable)\nStreaming: Yes\nTool calling: Yes (model-dependent)\n\nQuick Start\nGet an API Key\n\nhttps://fireworks.ai/account/api-keys\nConfigure Environment\nGenerate\n\nSupported Models (sample)\n\n| Model ID | Vision | Notes |\n| ---------------------------------------- | ------ | ----------------------------------- |\n| accounts/fireworks/models/kimi-k3 | Yes | Default — newest Moonshot flagship |\n| accounts/fireworks/models/gpt-oss-120b | No | Text fallback (fallbackModelName) |\n| accounts/fireworks/models/qwen3p8-max | Yes | Qwen flagship |\n| accounts/fireworks/models/glm-5p3 | No | Rejects image inputs |\n\nFireworks lists models on /models that are not deployed for serverless\nuse, so the catalog only keeps ids that answered a real chat call.\nkimi-k2p6, the default until September 2026, now returns 404\nnot deployed and is retired.\n\nBrowse: https://fireworks.ai/models\n\nCLI Usage\n\nProvider Aliases\n\n| Alias | Example |\n| ----------- | ---------------------- |\n| fireworks | --provider fireworks |\n\nConfiguration Reference\n\n| Environment Variable | Required | Default |\n| -------------------- | -------- | --------------------------------------- |\n| FIREWORKS_API_KEY | Yes | — |\n| FIREWORKS_MODEL | No | accounts/fireworks/models/kimi-k3 |\n| FIREWORKS_BASE_URL | No | https://api.fireworks.ai/inference/v1 |\n\nTroubleshooting\nModel not found, inaccessible, and/or not deployed — your account\n has not deployed the requested model. Check\n https://fireworks.ai/models and either\n deploy it or pick a serverless one.\n\nSee Also\nTogether AI Provider\nGroq Provider","hierarchy":{"lvl0":"Getting Started","lvl1":"Fireworks AI Provider Guide","lvl2":"","lvl3":""}},
|
|
5814
5814
|
{"objectID":"05cd5f1dffdb316d6e5f1b3ff86da591b78de22e32dc78ccf67aa1f40d59597d","title":"Fireworks AI Provider Guide","url":"/docs/getting-started/providers/fireworks#fireworks-ai-provider-guide","content":"Open-model inference tuned for low-latency production workloads","hierarchy":{"lvl0":"Getting Started","lvl1":"Fireworks AI Provider Guide","lvl2":"Fireworks AI Provider Guide","lvl3":""}},
|
|
@@ -6898,7 +6898,7 @@
|
|
|
6898
6898
|
{"objectID":"88e47ec55c1f3481092432425a6fabfeda109649e1722eff1cc531f760df674c","title":"CLI","url":"/docs/getting-started/providers/pareto-inference#cli","content":"npx @juspay/neurolink generate \"Hello\" --provider pareto-inference\ntypescript\nawait neurolink.generate({\n input: { text: \"Hello\" },\n provider: \"pareto-inference\",\n credentials: {\n \"pareto-inference\": { apiKey: process.env.PARETOINFERENCEAPI_KEY },\n },\n});\n`","hierarchy":{"lvl0":"Getting Started","lvl1":"Pareto Inference Provider Guide","lvl2":"CLI","lvl3":""}},
|
|
6899
6899
|
{"objectID":"79c93948b6d461182578b28b94eb9fa1edbf0815941cdb6090462ac57a92a6ab","title":"Models","url":"/docs/getting-started/providers/pareto-inference#models","content":"| Model | Context | Vision | $/M in · out · cached | Notes |\n| ----------------------- | --------------- | ------ | ----------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |\n| z-ai/glm-5.3-flash ⭐ | not published\\ | no | $0.09 / $0.30 (cached $0.018) | Only model Pareto serves. Max output documented as 1–131,072 tokens (default 131,072). \\Pareto publishes no context window; the catalog falls back to 131,072, the documented output ceiling, which is not a vendor context length. |\n\n\\ Pareto's own docs state it does not* disclose GLM 5.3 Flash's serving\ndetails (\"We do not disclose the technical details of our GLM 5.3 Flash\nserving system\"), and no context-window number appears on any public page.\nmodels.defaultContextWindow (131,072) is therefore a catalog fallback — the\ndocumented output ceiling, not a vendor context length — flagged in the\ncatalog entry's description. Correct it once Pareto publishes a real figure or\nan authenticated probe reveals one.\n\nFallback order: none — z-ai/glm-5.3-flash is the only model Pareto\nserves, so it is both the default and its own (schema-exempt) single-entry\nfallback list.","hierarchy":{"lvl0":"Getting Started","lvl1":"Pareto Inference Provider Guide","lvl2":"Models","lvl3":""}},
|
|
6900
6900
|
{"objectID":"106d04b8baec018f872ce608c3b0dd33f8b3d43ada85072831a2e9ab9c64c46b","title":"Verification status","url":"/docs/getting-started/providers/pareto-inference#verification-status","content":"Tier-2 onboarding requires evidence before a provider is accepted, and\npnpm run verify:provider-onboarding gates it in CI. This is what the\ncatalog records for Pareto Inference — and, just as importantly, what it\ndoes not yet record:\n\n| Probe | Result |\n| --------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| Roster | unauthenticated GET /v1/models, HTTP 200, 1 model (z-ai/glm-5.3-flash), 2026-09-28. No API key was used or required for this call. |\n| Auth rejection | Not probed. Would require a POST with an invalid key, which this credential-free onboarding pass does not send. Pareto's docs describe 401 as \"the chat API key is missing, invalid, or no longer active,\" with no example error body. |\n| Live capability sweep | Not run. evidence.liveMatrix is null.","hierarchy":{"lvl0":"Getting Started","lvl1":"Pareto Inference Provider Guide","lvl2":"Verification status","lvl3":""}},
|
|
6901
|
-
{"objectID":"b844edaf09c93fb3089bbf0a71254c5039dedf111e2b59563321484496862aa4","title":"Troubleshooting","url":"/docs/getting-started/providers/pareto-inference#troubleshooting","content":"| Symptom | Cause | Fix |\n| --------------------------------------- | -------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------- |\n| Invalid Pareto Inference API key | PARETO_INFERENCE_API_KEY unset, wrong, or expired | Pareto documents 401 as \"the chat API key is missing, invalid, or no longer active\" — check or replace the key in the dashboard |\n| 429 with credit_exhausted | Prepaid balance is empty | Buy more prepaid credits |\n| 429 with credit_insufficient | Held credits (reserved for max_tokens) are below what's needed | Lower max_tokens, or buy more credits |\n| 429 with model_capacity | The model itself is at capacity — not an account-level limit | Honor the Retry-After header and retry |\n| 502 mid-stream | The model request failed after the stream started | Retry the request; check whether a tool call already ran before retrying |\n| 503 | Temporary Pareto-side failure (e.g.","hierarchy":{"lvl0":"Getting Started","lvl1":"Pareto Inference Provider Guide","lvl2":"Troubleshooting","lvl3":""}},
|
|
6901
|
+
{"objectID":"b844edaf09c93fb3089bbf0a71254c5039dedf111e2b59563321484496862aa4","title":"Troubleshooting","url":"/docs/getting-started/providers/pareto-inference#troubleshooting","content":"| Symptom | Cause | Fix |\n| --------------------------------------- | -------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------- |\n| Invalid Pareto Inference API key | PARETO_INFERENCE_API_KEY unset, wrong, or expired | Pareto documents 401 as \"the chat API key is missing, invalid, or no longer active\" — check or replace the key in the dashboard |\n| 429 with credit_exhausted | Prepaid balance is empty | Buy more prepaid credits |\n| 429 with credit_insufficient | Held credits (reserved for max_tokens) are below what's needed | Lower max_tokens, or buy more credits |\n| 429 with model_capacity | The model itself is at capacity — not an account-level limit | Honor the Retry-After header and retry |\n| 502 mid-stream | The model request failed after the stream started | Retry the request; check whether a tool call already ran before retrying |\n| 503 | Temporary Pareto-side failure (e.g. maintenance, GPU outage) | Wait and retry; Retry-After gives the delay in seconds","hierarchy":{"lvl0":"Getting Started","lvl1":"Pareto Inference Provider Guide","lvl2":"Troubleshooting","lvl3":""}},
|
|
6902
6902
|
{"objectID":"57b8457eff592f229d3c0f0fb7c73148341ecffd72bb29c15d73f1471b1fd886","title":"See also","url":"/docs/getting-started/providers/pareto-inference#see-also","content":"Provider setup overview\nAll providers\nTier-2 onboarding — how this provider's JSON becomes a working integration\nProvider feature compatibility","hierarchy":{"lvl0":"Getting Started","lvl1":"Pareto Inference Provider Guide","lvl2":"See also","lvl3":""}},
|
|
6903
6903
|
{"objectID":"daf00919862e4bbed4b3fc1082bea17843a987e5e3970cefed2c95537b22cceb","title":"Perplexity Decisions Provider Guide","url":"/docs/getting-started/providers/perplexity-decider","content":"Perplexity Decisions Provider Guide\n\nA provider of decide — the same typed boolean / choice / score\nanswers as TypeSafe's Jev, Laya, XOR and\nCloudflare Clef, from Perplexity's hosted Decisions API,\nand it also reads images. It emits no text at all.\n\nThis is not the Perplexity text provider (perplexity, the\nSonar models), which serves generate() and stream(). The two share one API\nkey, which has a consequence worth reading before you set it. See\nWhat is sent to Perplexity and\nOne key, two providers.\n\nOverview\n\npplx-decider-v1-27b is Perplexity's decision model. You send one state\nplus named, typed questions, and optionally images. The model answers every\nquestion in a single batched pass and returns a typed answer for each, with a\nprobability instead of a sentence. NeuroLink calls Perplexity's public endpoint,\nso a key alone configures it: there is no base URL to set.\n\nKey Facts\n\n| | |\n| ------------------------ | ----------------------------------------------------------------------------------------------------------------- |\n| Provider id | perplexity-decider (no aliases) — distinct from perplexity, the Sonar text provider |\n| Inference type | decide only |\n| Model | pplx-decider-v1-27b; the API answers 400 to a missing or unknown model. PERPLEXITY_DECIDER_MODEL sets it |\n| Key | PERPLEXITY_API_KEY, shared with the Perplexity text provider, or credentials.perplexityDecider.apiKey |\n| Endpoint | https://api.perplexity.ai/v1/decisions; PERPLEXITY_DECIDER_BASE_URL can name another origin |\n| Media | images (PNG, JPEG or WebP), up to 8 per request; no video |\n| Questions per request | up to 128 |\n| Server input ceiling | under 262,144 tokens (state, questions and images); more is refused with an explicit 400, never cut off silently |\n| Images and that ceiling | billed as input tokens, and counted toward the ceiling at one token per 32 × 32 tile (measured) |\n| NeuroLink's state window | 100,000 estimated tokens: a deliberate local limit, not the server's |\n| Cost | $0.04 per million input tokens (image tokens included); output tokens are free. Perplexity's documented price |\n| Default timeout | 10 seconds plus 100 ms for each question (10.1 s for one, 22.8 s for 128); timeoutMs or --timeout replaces it |\n| Precedence | used automatically when TypeSafe, Laya and XOR are not configured |\n\nEach limit, token rate and latency in this guide is either measured on a real\naccount in October 2026 or taken from Perplexity's documentation, and says\nwhich where it appears. Measured: the 128-question and 8-image caps, the\n262,144-token input ceiling for the state, the questions and the images (nothing\nis cut off silently), characters per token for each kind of text, latency by\ninput size and by question count, what an image costs, which image sizes stall\n(the 2,048-tile rule, checked at its edge: see Images), and how the\nAPI answers a burst of requests. Documented and not tested: the 32 MiB request\nbody, the price, and the option and level counts. Perplexity documents a limit of\n10 requests per second for the account's tier (every organization, on every\nplan, with a token limit on large bursts), and a burst test on the one account\ntested saw the request limit act.\n\nQuick Start\nGet a key\n\nCreate one in the Perplexity console. Any\nPerplexity API key works.\nConfigure\n\nSet the key in the environment:\n\nor in the config passed to the SDK, exactly as for any other provider. Values\npassed per call override the constructor's, which override the environment:\n\ncredentials.perplexityDecider is its own slice. A key passed as\ncredentials.perplexity belongs to the text provider and does not configure\nthis one. PERPLEXITY_BASE_URL, which moves the text provider, is not read here;\nthe override for this provider is PERPLEXITY_DECIDER_BASE_URL, and a trailing\n/v1 on it is accepted.\nUse it\n\nNeuroLink's boolean question is sent to the API as its noul type, and the\nanswer is read back as a boolean. A boolean answer carries a probability and\nno confidence of its own; a choice or score answer carries the confidence the\nAPI reports, which Perplexity describes as the model's own certainty estimate,\nnot the top probability. Perplexity's API reference and quickstart do not call\nthat confidence calibrated, and NeuroLink did not measure whether i","hierarchy":{"lvl0":"Getting Started","lvl1":"Perplexity Decisions Provider Guide","lvl2":"","lvl3":""}},
|
|
6904
6904
|
{"objectID":"cd579839c9ecb7a84dee24ccd591e76f90eb1f05b384a35488c7603f72178d38","title":"Perplexity Decisions Provider Guide","url":"/docs/getting-started/providers/perplexity-decider#perplexity-decisions-provider-guide","content":"A provider of decide — the same typed boolean / choice / score\nanswers as TypeSafe's Jev, Laya, XOR and\nCloudflare Clef, from Perplexity's hosted Decisions API,\nand it also reads images. It emits no text at all.\n\nThis is not the Perplexity text provider (perplexity, the\nSonar models), which serves generate() and stream(). The two share one API\nkey, which has a consequence worth reading before you set it. See\nWhat is sent to Perplexity and\nOne key, two providers.","hierarchy":{"lvl0":"Getting Started","lvl1":"Perplexity Decisions Provider Guide","lvl2":"Perplexity Decisions Provider Guide","lvl3":""}},
|
|
@@ -9623,7 +9623,7 @@
|
|
|
9623
9623
|
{"objectID":"dc84c011b75c26bc86d2fd6505afaaf435a12b7e811b3cd60b7c2cb3d3fad164","title":"Provider Integration Documentation","url":"/docs/provider-integration/README#provider-integration-documentation","content":"Implementation guides for extending NeuroLink with new providers, new modalities, and new capability surfaces.","hierarchy":{"lvl0":"Provider Integration","lvl1":"Provider Integration Documentation","lvl2":"Provider Integration Documentation","lvl3":""}},
|
|
9624
9624
|
{"objectID":"267930c7646bc9e09d60707cd02e7abeb38bdedcc93ef101cb52b30851f112b8","title":"Two reading paths","url":"/docs/provider-integration/README#two-reading-paths","content":"This folder contains two kinds of document:\nImplementation journals (00-14) — the historical record of specific shipped features (DeepSeek/NIM/LM Studio/llama.cpp providers, voice/speech integration). Useful as concrete worked examples and when you want to know exactly what was done in a particular release.\nHow-to guides (15-22 + CHECKLIST) — the canonical, generalized playbook for adding a new provider or modality of any kind. Use these when implementing something new.\n\nIf you're adding code today, start with CHECKLIST.md (decision tree → matching guide).","hierarchy":{"lvl0":"Provider Integration","lvl1":"Provider Integration Documentation","lvl2":"Two reading paths","lvl3":""}},
|
|
9625
9625
|
{"objectID":"6b36e4dba30a94517db6fa06e2b8ed176997629de663baaabfe724cdaf211801","title":"Quick decision tree","url":"/docs/provider-integration/README#quick-decision-tree","content":"For a fast pre-flight checklist you can paste into your PR description, see CHECKLIST.md.","hierarchy":{"lvl0":"Provider Integration","lvl1":"Provider Integration Documentation","lvl2":"Quick decision tree","lvl3":""}},
|
|
9626
|
-
{"objectID":"786e31ae7d38d079ef26dcbc1e320013456a228b7ab8438b3586749562ac5cfa","title":"How-to guides (the playbook)","url":"/docs/provider-integration/README#how-to-guides-the-playbook","content":"| Doc | Scope | When to read |\n| ---------------------------------------------------------------------- | -------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------- |\n| 15-adding-llm-provider.md | Superseded — legacy redirect only | New chat/text-generation providers: start at tiers/README.md instead |\n| 16-adding-tts-provider.md | New text-to-speech handler | Adding Fish Audio, Cartesia, Murf, PlayHT, Sarvam TTS |\n| 17-adding-stt-provider.md | New speech-to-text handler | Adding AssemblyAI, Gladia, Rev.ai, Speechmatics |\n| 18-adding-realtime-provider.md | New bidirectional voice handler | Adding Hume EVI, Resemble.ai realtime, custom WebSocket protocols |\n| 19-adding-video-provider.md | New video-generation provider (incl.","hierarchy":{"lvl0":"Provider Integration","lvl1":"Provider Integration Documentation","lvl2":"How-to guides (the playbook)","lvl3":""}},
|
|
9626
|
+
{"objectID":"786e31ae7d38d079ef26dcbc1e320013456a228b7ab8438b3586749562ac5cfa","title":"How-to guides (the playbook)","url":"/docs/provider-integration/README#how-to-guides-the-playbook","content":"| Doc | Scope | When to read |\n| ---------------------------------------------------------------------- | -------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------- |\n| 15-adding-llm-provider.md | Superseded — legacy redirect only | New chat/text-generation providers: start at tiers/README.md instead |\n| 16-adding-tts-provider.md | New text-to-speech handler | Adding Fish Audio, Cartesia, Murf, PlayHT, Sarvam TTS |\n| 17-adding-stt-provider.md | New speech-to-text handler | Adding AssemblyAI, Gladia, Rev.ai, Speechmatics |\n| 18-adding-realtime-provider.md | New bidirectional voice handler | Adding Hume EVI, Resemble.ai realtime, custom WebSocket protocols |\n| 19-adding-video-provider.md | New video-generation provider (incl. one-time refactor) | Adding Kling, Runway, Pika, Luma, Wan-Alpha (via Replicate) |\n| 20-adding-image-gen-provider.md | New image-gen provider or model | Adding Stability, FLUX direct, Ideogram, Recraft, or new models on existing providers |\n| 21-adding-new-modality.md | A brand-new modality category | Adding Avatar (D-ID, HeyGen), Music (Beatoven, Lyria, ElevenLabs Music), 3D, SFX,","hierarchy":{"lvl0":"Provider Integration","lvl1":"Provider Integration Documentation","lvl2":"How-to guides (the playbook)","lvl3":""}},
|
|
9627
9627
|
{"objectID":"377fa1c12e2231bf4515500254aec64339e7a152e3666f0360dfb0658c12c608","title":"Implementation journals (the worked examples)","url":"/docs/provider-integration/README#implementation-journals-the-worked-examples","content":"These document specific shipped features and serve as concrete references for the patterns generalized in 15-22.\n\n| Doc | Topic | Commit |\n| ---------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------- | ---------- |\n| 00-architecture.md | Common provider patterns, with the OpenAI-compatible base documented as one transport family | — |\n| 01-shared-changes.md | Master diff list for everything outside src/lib/providers/<name>.ts (worked example for the four cloud-OpenAI-compat providers) | c829f4de |\n| 02-deepseek.md | DeepSeek native transport, structured output and model-specific limits | Current |\n| 03-nvidia-nim.md | NVIDIA NIM native extra fields and one-shot request repair | Current |\n| 04-lm-studio.md | LM Studio native local-server integration and model discovery | Current |\n| 05-llamacpp.md | llama.cpp native local-server integration and tool limitations | Current |\n| 06-testing.md | Test additions and validation strategy for the four cloud providers | c829f4de |\n| 07-implementation-order.md | Ordered task list,","hierarchy":{"lvl0":"Provider Integration","lvl1":"Provider Integration Documentation","lvl2":"Implementation journals (the worked examples)","lvl3":""}},
|
|
9628
9628
|
{"objectID":"ca7d0e03eb7d31debf6b6552e129e6b5aa0d29e979a664d2ae8fedbd590aa0d5","title":"Critical rules (quick reference)","url":"/docs/provider-integration/README#critical-rules-quick-reference","content":"These rules are baked into the codebase and enforced by ESLint. Violating any of them blocks CI.\n\n| # | Rule | Enforced by |\n| --- | -------------------------------------------------- | ------------------------------------------------------------- |\n| 1 | Dynamic imports inside the registry only | (convention; failure surfaces as circular-dep error at build) |\n| 2 | Types in canonical src/lib/types/ location | neurolink/no-local-type-alias |\n| 5 | Backward compatibility — public API additive only | (convention; reviewer-enforced) |\n| 6 | formatProviderError must return, never throw | (convention; loud at runtime) |\n| 7 | Use type, never interface | neurolink/no-interface |\n| 8 | No \"Types\" suffix in type filenames | neurolink/no-types-suffix-filename |\n| 9 | Globally unique exported type names (use prefixes) | neurolink/unique-type-names |\n| 10 | Types barrel uses export * only | neurolink/types-barrel-exports-only |\n| 11 | No local types/ directories | neurolink/no-local-types-folder |\n| 12 | No type re-exports from non-type files | neurolink/no-type-export-outside-types |\n| 13 | Internal types imported from barrel only | neurolink/barrel-type-imports |\n\nFull text and rationale lives in the project CLAUDE.md. The how-to guides (15-22) reference these rules where relevant.","hierarchy":{"lvl0":"Provider Integration","lvl1":"Provider Integration Documentation","lvl2":"Critical rules (quick reference)","lvl3":""}},
|
|
9629
9629
|
{"objectID":"d991058e6689b3ab9b076a10eb9e61faf98cfce1f7e23915fa6e55987c0a89e1","title":"Reference commits","url":"/docs/provider-integration/README#reference-commits","content":"When in doubt, look at how it was done before:\n\n| Commit | Adds | Best for |\n| ---------- | ------------------------------------------ | ------------------------------------------------------------------------- |\n| c829f4de | DeepSeek, NVIDIA NIM, LM Studio, llama.cpp | Multi-provider PRs that share infrastructure (§01-shared-changes pattern) |\n| 27a31c32 | Voice/Speech (3 TTS + 4 STT + 2 Realtime) | New modality with multiple providers (handler-registry pattern) |\n| 8918f8ef | LiteLLM provider | Single-provider PR with full documentation (41 files) |\n| 3041d26f | OpenAI Compatible | Minimal-comprehensive provider (cleanest 11-file diff) |\n| 9ef4ebee | Amazon SageMaker | Multi-file provider directory (only when truly needed) |","hierarchy":{"lvl0":"Provider Integration","lvl1":"Provider Integration Documentation","lvl2":"Reference commits","lvl3":""}},
|
|
@@ -11177,7 +11177,7 @@
|
|
|
11177
11177
|
{"objectID":"ebaf181b10f535778380a3406185669d4dcd0044636eef6a58a4d4a2ba8dbb18","title":"Task 2: Add a required provider-safety-net CI job","url":"/docs/superpowers/plans/2026-08-15-02-ci-safety-net#task-2-add-a-required-provider-safety-net-ci-job","content":"Files:\nModify: .github/workflows/ci.yml (add new job after test:, lines 10-84; replace the no-op step in quality-gate, lines 301-305)\n\nInterfaces:\nConsumes: pnpm run build, pnpm run test:providers-mocked, pnpm run test:provider-structure (script added in Task 1).\nProduces: new required GitHub Actions job provider-safety-net, whose check-run name (no name:/strategy: set) is literally provider-safety-net — the exact context string used in Task 3's branch-protection fix.\n\nSteps:\n[ ] 2.1 Verify the current job list and the no-op step before editing:\n\n \n\n Expected job list: test:, build-check:, proxy-performance:, quality-gate:, semantic-release-validation: (plus a commented-out # action-smoke-test: block). Expected sed output includes:\n[ ] 2.2 Insert the new job immediately after the test: job's closing (right before the commented # action-smoke-test: block that starts at line 86):\n[ ] 2.3 Replace the no-op quality-gate step (lines 301-305 as of this plan) — remove it entirely, since real validation now runs in the dedicated provider-safety-net job instead of being faked here:\n[ ] 2.4 Validate the YAML parses (GitHub Actions has no local act-free linter in this repo, so use a YAML syntax check):\n\n \n\n Expected: YAML OK.\n[ ] 2.5 Confirm the referenced scripts actually exist and pass locally (this is what CI will run):\n\n \n\n Expected: all three commands exit 0.\n[ ] 2.6 Commit:","hierarchy":{"lvl0":"Superpowers","lvl1":"CI Safety Net Implementation Plan","lvl2":"Task 2: Add a required provider-safety-net CI job","lvl3":""}},
|
|
11178
11178
|
{"objectID":"549847f741171a5bd6cb70ceaf4524139ff7a0b8271e8ab0d24299fa12e2a2f7","title":"Task 3: Fix branch-protection contexts and the test job matrix mismatch","url":"/docs/superpowers/plans/2026-08-15-02-ci-safety-net#task-3-fix-branch-protection-contexts-and-the-test-job-matrix-mismatch","content":"Files:\nModify: .github/settings.yml (two duplicate branches: - name: release protection blocks, lines 173-192 and 193-210)\nModify: .github/workflows/ci.yml (test: job's strategy: matrix: block, lines 10-28)\n\nInterfaces:\nProduces: .github/settings.yml required-context list [\"test\", \"build-check\", \"provider-safety-net\", \"Yama PR Review\"], all four of which now match real, unmatrixed job/check-run names in ci.yml.\n\nDecision — drop the matrix, don't update the context string: ci.yml's test: job currently reports as test (20) because of a single-entry node-version: [20] matrix (.github/workflows/ci.yml:12-14), while .github/settings.yml requires the literal context \"test\". Two fixes are possible: (a) change settings.yml to require \"test (20)\", or (b) drop the single-entry matrix so the job reports as plain \"test\". Choosing (b): a matrix with exactly one entry provides no coverage benefit (it doesn't test multiple Node versions), and the suffixed context name is themselves fragile — any future change to the matrix values (e.g. adding Node 22) silently changes the required-check string and re-breaks branch protection the same way \"build\" broke. A flat job name has no such failure mode.\n\nSteps:\n[ ] 3.1 Verify current mismatch before editing:\n\n \n\n Expected: ci.yml shows strategy: matrix: node-version: [20] and ${{ matrix.node-version }} used at two points; settings.yml shows the string \"build\" appearing twice (once per duplicated block) with no job in ci.yml named build (the real job is build-check).\n[ ] 3.2 Drop the matrix in ci.yml's test: job, hardcoding Node 20:\n[ ] 3.3 Fix both duplicate contexts: blocks in .github/settings.yml in one pass (the two blocks are byte-identical, so a single replace_all edit covers both):\n[ ] 3.4 Confirm both blocks now match by re-grepping:\n\n \n\n Expected: \"test\", \"build-check\", \"provider-safety-net\" each appear exactly twice (once per duplicated protection block); zero remaining bare \"build\" matches.","hierarchy":{"lvl0":"Superpowers","lvl1":"CI Safety Net Implementation Plan","lvl2":"Task 3: Fix branch-protection contexts and the test job matrix mismatch","lvl3":""}},
|
|
11179
11179
|
{"objectID":"7432e68b6096aef4448ab66ddafe1ff3e3a9e1c5077f06fbbb44ce784e9306e1","title":"Task 4: Wire pre-push to a real Husky hook running the cheap no-API tier","url":"/docs/superpowers/plans/2026-08-15-02-ci-safety-net#task-4-wire-pre-push-to-a-real-husky-hook-running-the-cheap-no-api-tier","content":"Files:\nModify: package.json (pre-push script, line 226)\nCreate: .husky/pre-push\n\nInterfaces:\nConsumes: pnpm run build, pnpm run test:providers-mocked, pnpm run test:provider-structure (same three commands as the CI job in Task 2, so a local push fails exactly what CI would fail, before it's pushed).\n\nSteps:\n[ ] 4.1 Verify current state — pre-push script exists but no .husky/pre-push hook file wires it up:\n\n \n\n Expected: package.json shows \"pre-push\": \"pnpm run validate:commit && pnpm run validate:env && pnpm run validate && pnpm run test:ci\"; .husky/ contains only commit-msg, pre-commit, and _ (no pre-push file).\n[ ] 4.2 Redefine the pre-push script to the cheap no-API tier — edit package.json:226:\n[ ] 4.3 Create .husky/pre-push, matching the shebang + sourcing style of the existing .husky/commit-msg:\n[ ] 4.4 Make it executable, matching the other hooks:\n\n \n\n Expected: permissions show -rwxr-xr-x (or equivalent executable bit set).\n[ ] 4.5 Run the hook's own command manually to confirm it passes before relying on the git hook to catch failures:\n\n \n\n Expected: build, mocked-contract suite, and structure suite all run and the command exits 0.\n[ ] 4.6 Commit:","hierarchy":{"lvl0":"Superpowers","lvl1":"CI Safety Net Implementation Plan","lvl2":"Task 4: Wire pre-push to a real Husky hook running the cheap no-API tier","lvl3":""}},
|
|
11180
|
-
{"objectID":"543fd7742534c58f355b84d62438dd4fac7866cc0e3d228a799a78a2282e1a84","title":"Task 5: OpenAI mocked contract section","url":"/docs/superpowers/plans/2026-08-15-02-ci-safety-net#task-5-openai-mocked-contract-section","content":"Files:\nModify: test/continuous-test-suite-providers-mocked.ts (new runOpenAISection() function + wiring into main())\n\nInterfaces:\nConsumes: installMockFetch, record, expect, expectEq from ./utils/mockFetch.js; withMocks, setEnv, openAIChatResponse, results (module-level helpers already in the file); NeuroLink via await import(\"../dist/index.js\").\nProduces: three new TestRecord entries in results: \"LLM openai: happy-path generate()\", \"LLM openai: 401 → AuthenticationError\", \"LLM openai: 429 → RateLimitError\".\n\nVerified request contract (src/lib/providers/openaiChatCompletionsBase.ts:383-399, unoverridden by OpenAI's provider class): default getChatCompletionsURL() returns ${baseURL}/chat/completions with baseURL = \"https://api.openai.com/v1\" (OPENAI_DEFAULT_BASE_URL) → full URL https://api.openai.com/v1/chat/completions; default getAuthHeaders() returns { Authorization: Bearer ${apiKey} }.\n\nVerified error contract (src/lib/providers/openAI/client.ts:135-199, full body read verbatim): buildAPIError always sets a numeric statusCode, so classification is reliable via the statusCode branches alone — statusCode === 401 → AuthenticationError; statusCode === 429 → RateLimitError with the exact literal message \"OpenAI rate limit exceeded. Please try again later.\" (line 185).\n\nSteps:\n[ ] 5.1 Verify the suite's tail structure before inserting (confirms exact insertion points):\n\n \n\n Expected: shows runImageGenSection() ending at line ~1172, the // Section: main comment, then async function main() with a try { await runOpenAICompatSection(); await runReplicateLLMSection(); await runEmbeddingsSection(); await runImageGenSection(); } finally { restoreEnv(); } block
|
|
11180
|
+
{"objectID":"543fd7742534c58f355b84d62438dd4fac7866cc0e3d228a799a78a2282e1a84","title":"Task 5: OpenAI mocked contract section","url":"/docs/superpowers/plans/2026-08-15-02-ci-safety-net#task-5-openai-mocked-contract-section","content":"Files:\nModify: test/continuous-test-suite-providers-mocked.ts (new runOpenAISection() function + wiring into main())\n\nInterfaces:\nConsumes: installMockFetch, record, expect, expectEq from ./utils/mockFetch.js; withMocks, setEnv, openAIChatResponse, results (module-level helpers already in the file); NeuroLink via await import(\"../dist/index.js\").\nProduces: three new TestRecord entries in results: \"LLM openai: happy-path generate()\", \"LLM openai: 401 → AuthenticationError\", \"LLM openai: 429 → RateLimitError\".\n\nVerified request contract (src/lib/providers/openaiChatCompletionsBase.ts:383-399, unoverridden by OpenAI's provider class): default getChatCompletionsURL() returns ${baseURL}/chat/completions with baseURL = \"https://api.openai.com/v1\" (OPENAI_DEFAULT_BASE_URL) → full URL https://api.openai.com/v1/chat/completions; default getAuthHeaders() returns { Authorization: Bearer ${apiKey} }.\n\nVerified error contract (src/lib/providers/openAI/client.ts:135-199, full body read verbatim): buildAPIError always sets a numeric statusCode, so classification is reliable via the statusCode branches alone — statusCode === 401 → AuthenticationError; statusCode === 429 → RateLimitError with the exact literal message \"OpenAI rate limit exceeded. Please try again later.\" (line 185).\n\nSteps:\n[ ] 5.1 Verify the suite's tail structure before inserting (confirms exact insertion points):\n\n \n\n Expected: shows runImageGenSection() ending at line ~1172, the // Section: main comment, then async function main() with a try { await runOpenAICompatSection(); await runReplicateLLMSection(); await runEmbeddingsSection(); await runImageGenSection(); } finally { restoreEnv(); } block.","hierarchy":{"lvl0":"Superpowers","lvl1":"CI Safety Net Implementation Plan","lvl2":"Task 5: OpenAI mocked contract section","lvl3":""}},
|
|
11181
11181
|
{"objectID":"800f6d4129fb41e43c8ff4e542c3554f337a71035ba938eda42ba642c1daacb0","title":"Task 6: Azure mocked contract section","url":"/docs/superpowers/plans/2026-08-15-02-ci-safety-net#task-6-azure-mocked-contract-section","content":"Files:\nModify: test/continuous-test-suite-providers-mocked.ts (new runAzureSection() function + wiring into main())\n\nInterfaces:\nProduces: TestRecord entries \"LLM azure: happy-path generate()\", \"LLM azure: 401 → AuthenticationError\", \"LLM azure: 429 → generic ProviderError (documented gap)\".\n\nVerified request contract (src/lib/providers/azureOpenai.ts, full 292-line file read twice verbatim): getChatCompletionsURL() builds ${azureResourceOrigin}${prefix}/deployments/${deployment}/chat/completions?api-version=${azureApiVersion} where prefix = azureDeploymentPathPrefix.replace(/\\/+$/, \"\") = \"/openai\" for a classic *.openai.azure.com host; deployment = credentials?.deploymentName || modelName || process.env.AZURE_OPENAI_MODEL || process.env.AZURE_OPENAI_DEPLOYMENT || process.env.AZURE_OPENAI_DEPLOYMENT_ID || \"gpt-4o\" — passing model: \"mock-deployment\" directly to nl.generate() sets it with no extra env var; azureApiVersion defaults to APIVersions.AZURE_LATEST = \"2025-04-01-preview\" (src/lib/constants/enums.ts:978); getAuthHeaders() returns {\"api-key\": apiKey} — not Authorization: Bearer.\n\nVerified error contract (formatProviderError, src/lib/providers/azureOpenai.ts, read verbatim this session): 401 works via errorObj.message.includes(\"401\") → AuthenticationError(\"Invalid Azure OpenAI API key or endpoint.\", \"azure\") (an exact, fixed message regardless of upstream body). 429 has no dedicated branch at all — falls through to the generic ProviderError(Azure OpenAI error: ${message}, \"azure\"). This is a real, confirmed classification gap; the test documents it rather than asserting incorrect RateLimitError behavior.\n\nSteps:\n[ ] 6.1 Verify the exact endpoint-building and auth-header logic one more time immediately before writing the mock (guards against drift since the constructor was last read):\n\n \n\n Expected: shows getChatCompletionsURL(modelId) building the URL with the /openai/deployments/.../chat/completions?api-version=...","hierarchy":{"lvl0":"Superpowers","lvl1":"CI Safety Net Implementation Plan","lvl2":"Task 6: Azure mocked contract section","lvl3":""}},
|
|
11182
11182
|
{"objectID":"18c257c7f6d8778192247a7a06e83fbce558857dca542287757aec9b66f6476a","title":"Task 7: Anthropic mocked contract section","url":"/docs/superpowers/plans/2026-08-15-02-ci-safety-net#task-7-anthropic-mocked-contract-section","content":"Files:\nModify: test/continuous-test-suite-providers-mocked.ts (new anthropicMessageResponse() helper + runAnthropicSection() function + wiring into main())\n\nInterfaces:\nProduces: TestRecord entries \"LLM anthropic: happy-path generate()\", \"LLM anthropic: 401 → generic ProviderError (documented gap)\", \"LLM anthropic: 429 → RateLimitError\".\n\nVerified request contract (@anthropic-ai/sdk v0.102.0 source in node_modules, read verbatim this session): default header anthropic-version: '2023-06-01' (client.js:799); apiKeyAuth() returns {'X-Api-Key': apiKey} (client.js:353-357) — not Authorization: Bearer; endpoint POST /v1/messages relative to baseURL=\"https://api.anthropic.com\" (resources/messages/messages.js:35) → full URL https://api.anthropic.com/v1/messages. Interceptable via installMockFetch() because fetchWithRetry() calls the bare fetch() identifier, resolved dynamically from globalThis.fetch (confirmed no local shadow).\n\nVerified error contract (formatProviderError, src/lib/providers/anthropic/client.ts:1668-1727, read verbatim this session): auth branch matches only message.includes(\"API_KEY_INVALID\") || message.includes(\"Invalid API key\") — the SDK's actual 401 message format is ${status} ${msg} (node_modules/@anthropic-ai/sdk/core/error.js:11,18-26), e.g. \"401 invalid x-api-key\", which contains neither literal substring, so a real 401 misclassifies and falls through to the generic ProviderError(Anthropic error: ${message}, ...)— a confirmed gap, documented rather than worked around. 429 correctly matchesmessage.includes(\"429\")(the SDK's 429 message is\"429 \" + rawMessage) → RateLimitErrorwith the exact literal message\"Anthropic rate limit exceeded. Please try again later.\" (line 1698).","hierarchy":{"lvl0":"Superpowers","lvl1":"CI Safety Net Implementation Plan","lvl2":"Task 7: Anthropic mocked contract section","lvl3":""}},
|
|
11183
11183
|
{"objectID":"1ad28e5918317348e1f2c9ba8e0064612d57d3a8ed24d33af1d349cd7481b3ad","title":"Task 8: Vertex construction + formatProviderError contract section","url":"/docs/superpowers/plans/2026-08-15-02-ci-safety-net#task-8-vertex-construction-formatprovidererror-contract-section","content":"Files:\nModify: test/continuous-test-suite-providers-mocked.ts (new runVertexSection() function + wiring into main())\n\nInterfaces:\nConsumes: GoogleVertexProvider from \"../dist/lib/providers/googleVertex/client.js\" (not re-exported from dist/index.js — dynamic-import-only per repo rule 1, confirmed by grep); AuthenticationError, RateLimitError from \"../dist/lib/types/index.js\".\nProduces: TestRecord entries \"Vertex (construction + formatProviderError contract): constructs without throwing\", \"...: 403 → AuthenticationError\", \"...: 429 → RateLimitError\".\n\nWhy construction-only, not fetch interception: Vertex's @google/genai client routes its ADC (Application Default Credentials) token exchange through gaxios, which imports the node-fetch npm package directly rather than calling globalThis.fetch — confirmed by inspecting gaxios's dependency graph in node_modules. installMockFetch() only replaces globalThis.fetch, so it cannot intercept this path. The substitute contract test constructs the real GoogleVertexProvider class (safe — its constructor makes no network call, it only builds a client object) and invokes its formatProviderError() directly with synthetic error objects, verifying the classifier logic in isolation.\n\nVerified classifier (formatProviderError, src/lib/providers/googleVertex/client.ts:8465-8622, read verbatim this session): 401/403/PERMISSION_DENIED/UNAUTHENTICATED/statusCode 401 or 403 → AuthenticationError; QUOTA_EXCEEDED/RATE_LIMIT_EXCEEDED/\"rate limit\"/\"429\"/statusCode 429 or 529//overloaded/i → RateLimitError (with retryDelay scraped via /[\"']?retryDelay[\"']?\\s*[:=]\\s*[\"']?(\\d+(?:\\.\\d+)?s)/). formatProviderError is declared protected (line 8465) — invoked here via a test-only double assertion (provider as unknown as {formatProviderError(...): Error}), which is banned in src/ under project rule 14 but explicitly exempt for test files.","hierarchy":{"lvl0":"Superpowers","lvl1":"CI Safety Net Implementation Plan","lvl2":"Task 8: Vertex construction + formatProviderError contract section","lvl3":""}},
|
|
@@ -11253,13 +11253,13 @@
|
|
|
11253
11253
|
{"objectID":"ced198afaeb9ca974e4e19ad48faa5ff98d58833d98e4cf8e7295056358706e6","title":"Model Metadata Consolidation Implementation Plan","url":"/docs/superpowers/plans/2026-08-15-06-model-metadata-consolidation","content":"Model Metadata Consolidation Implementation Plan\n\nFor agentic workers: REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (- [ ]) syntax for tracking.\n\nGoal: Replace NeuroLink's five independently-maintained, disagreeing model-metadata stores (MODEL_REGISTRY, MODEL_CONTEXT_WINDOWS, the private PRICING table, the private VISION_CAPABILITIES table, and PROVIDER_MAX_TOKENS) with one per-provider model manifest that all five read from, while preserving every existing public function signature.\n\nArchitecture: A new canonical type ProviderModelManifest (in src/lib/types/model.ts) describes, per provider, a defaultContextWindow, optional familyRules (regex-driven patches for unlisted gateway-shaped ids — the same pattern VISION_FAMILY_RULES/SAMPLING_PARAM_REJECTING_FAMILIES already use independently), and a models map keyed by canonical model id. One file per provider under src/lib/models/manifests/<provider>.ts exports its manifest as pure, dependency-free data; src/lib/models/manifestRegistry.ts statically imports all 30 and exposes resolveManifestEntry() / resolveManifestEntryExact() lookup functions implementing the longest-prefix-match cascade pricing.ts's findRates() already pioneered. The five existing stores are migrated one at a time to compute their exported values from the manifest at module-init or call time, with their public signatures byte-identical to today.\n\nTech Stack: TypeScript (strict mode, no interface, named exports only), no new runtime dependencies — manifests are plain object literals imported statically (they carry no heavy provider SDKs, so Critical Rule 1's dynamic-import mandate for providerRegistry.ts factories does not apply here).\n\nSpec:\n$SCRATCH/47d64fa8-f94f-404c-b134-3e117deddba3/scratchpad/areas/gap2-model-metadata-subsystem-model-registry-modelresol.md\n$SCRATCH/47d64fa8-f94f-404c-b134-3e117deddba3/scratchpad/areas/06-message-building-multimodal-adaptation-how-user-in.md\n$SCRATCH/47d64fa8-f94f-404c-b134-3e117deddba3/scratchpad/areas/11-types-models-config.md\n\nGlobal Constraints\npnpm ONLY. pnpm run check / pnpm run lint / pnpm run build. Tests via npx tsx test/continuous-test-suite-<name>.ts + test:<name> scripts.\nTEST HARNESS SKIP HAZARD: NEVER interpolate payloads into assertion messages; break-one-assertion sanity step for new suites.\nRepo rules: ALL types in src/lib/types/; no interface; unique exported type names; types barrel export * only; barrel-only internal type imports; no double assertions; named exports only. EVERY existing public function signature preserved (getContextWindowSize, findRates, calculateCost, supportsVision, getSafeMaxTokens, resolveClaudeMaxTokens, ModelResolver.\\*, modelRegistry helpers) — consumers must not change.\nConventional commits; commit per task; NEVER git push.\nRelated contract (plan 04, separate concern): ProviderDescriptor in src/lib/factories/providerDescriptors.ts covers provider-level identity/env — your manifest is MODEL-level; do not duplicate provider-level fields.\n\nTask 1: Manifest types\n\nFiles:\nModify: src/lib/types/model.ts:271 (append after the existing type block; do not touch anything above line 271)\nTest: none (pure type addition — verified by pnpm run check in the final step)\n\nInterfaces:\nConsumes: nothing (foundational task)\nProduces: ProviderModelManifestEntry, ManifestFamilyRule, ProviderModelManifest — the three types every later task imports from ../types/index.js.\n\nThe manifest's pricingPerMTok is deliberately optional. Some real, current models (e.g. claude-sonnet-5) have no verified price in any existing store — pricing.ts's own PRICING.anthropic table has no entry for it today. Leaving the field absent is honest; inventing a number is not. This has a direct, load-bearing consequence for Task 9: ModelInfo.pricing: ModelPricingInfo (src/lib/types/model.ts:184) has three required (non-optional) numeric fields (inputCostPer1K, outputCostPer1K, currency) — confirmed by reading src/lib/types/model.ts:137-141. Task 9's registry builder resolves this by only ever promoting manifest entries that do carry pricingPerMTok into the rebuilt MODEL_REGISTRY — see Task 9's design note for the full reasoning.\n\nThe manifest also carries an optional curated block for ModelInfo.performance/.useCases/.category. These three fields are today hand-tuned per model in MODEL_REGISTRY (src/lib/models/modelRegistry.ts) — there is no mechanical source for them anywhere else (not in MODEL_CONTEXT_WINDOWS, not in PRICING, not in VISION_CAPABILITIES). For the 25 ids that already have a MODEL_REGISTRY entry today (5 Anthropic, 20 OpenAI), Task 9 must reproduce those exact values byte-for-byte, or its own \"exact old output preserved\" equality test would be false for performance/useCases/category specifically. curated is how those 25 hand-tuned triples travel forward into the manifest instead of being silently dropped and re-derived. Entrie","hierarchy":{"lvl0":"Superpowers","lvl1":"Model Metadata Consolidation Implementation Plan","lvl2":"","lvl3":""}},
|
|
11254
11254
|
{"objectID":"71cd0ef70eecf72cbe1d0ea1b25120b231b899e86a1de0a2683f73d438303f08","title":"Model Metadata Consolidation Implementation Plan","url":"/docs/superpowers/plans/2026-08-15-06-model-metadata-consolidation#model-metadata-consolidation-implementation-plan","content":"For agentic workers: REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (- [ ]) syntax for tracking.\n\nGoal: Replace NeuroLink's five independently-maintained, disagreeing model-metadata stores (MODEL_REGISTRY, MODEL_CONTEXT_WINDOWS, the private PRICING table, the private VISION_CAPABILITIES table, and PROVIDER_MAX_TOKENS) with one per-provider model manifest that all five read from, while preserving every existing public function signature.\n\nArchitecture: A new canonical type ProviderModelManifest (in src/lib/types/model.ts) describes, per provider, a defaultContextWindow, optional familyRules (regex-driven patches for unlisted gateway-shaped ids — the same pattern VISION_FAMILY_RULES/SAMPLING_PARAM_REJECTING_FAMILIES already use independently), and a models map keyed by canonical model id. One file per provider under src/lib/models/manifests/<provider>.ts exports its manifest as pure, dependency-free data; src/lib/models/manifestRegistry.ts statically imports all 30 and exposes resolveManifestEntry() / resolveManifestEntryExact() lookup functions implementing the longest-prefix-match cascade pricing.ts's findRates() already pioneered. The five existing stores are migrated one at a time to compute their exported values from the manifest at module-init or call time, with their public signatures byte-identical to today.\n\nTech Stack: TypeScript (strict mode, no interface, named exports only), no new runtime dependencies — manifests are plain object literals imported statically (they carry no heavy provider SDKs, so Critical Rule 1's dynamic-import mandate for providerRegistry.ts factories does not apply here).","hierarchy":{"lvl0":"Superpowers","lvl1":"Model Metadata Consolidation Implementation Plan","lvl2":"Model Metadata Consolidation Implementation Plan","lvl3":""}},
|
|
11255
11255
|
{"objectID":"c1763978d15838da26ab6eac683885a4f353952c47b379d0ef7c83e62f1d0855","title":"Global Constraints","url":"/docs/superpowers/plans/2026-08-15-06-model-metadata-consolidation#global-constraints","content":"pnpm ONLY. pnpm run check / pnpm run lint / pnpm run build. Tests via npx tsx test/continuous-test-suite-<name>.ts + test:<name> scripts.\nTEST HARNESS SKIP HAZARD: NEVER interpolate payloads into assertion messages; break-one-assertion sanity step for new suites.\nRepo rules: ALL types in src/lib/types/; no interface; unique exported type names; types barrel export * only; barrel-only internal type imports; no double assertions; named exports only. EVERY existing public function signature preserved (getContextWindowSize, findRates, calculateCost, supportsVision, getSafeMaxTokens, resolveClaudeMaxTokens, ModelResolver.\\*, modelRegistry helpers) — consumers must not change.\nConventional commits; commit per task; NEVER git push.\nRelated contract (plan 04, separate concern): ProviderDescriptor in src/lib/factories/providerDescriptors.ts covers provider-level identity/env — your manifest is MODEL-level; do not duplicate provider-level fields.","hierarchy":{"lvl0":"Superpowers","lvl1":"Model Metadata Consolidation Implementation Plan","lvl2":"Global Constraints","lvl3":""}},
|
|
11256
|
-
{"objectID":"e850eedf19d858ea5a8f63fb8925b2330256e21f1d19895caef38c476d0ab2c6","title":"Task 1: Manifest types","url":"/docs/superpowers/plans/2026-08-15-06-model-metadata-consolidation#task-1-manifest-types","content":"Files:\nModify: src/lib/types/model.ts:271 (append after the existing type block; do not touch anything above line 271)\nTest: none (pure type addition — verified by pnpm run check in the final step)\n\nInterfaces:\nConsumes: nothing (foundational task)\nProduces: ProviderModelManifestEntry, ManifestFamilyRule, ProviderModelManifest — the three types every later task imports from ../types/index.js.\n\nThe manifest's pricingPerMTok is deliberately optional. Some real, current models (e.g. claude-sonnet-5) have no verified price in any existing store — pricing.ts's own PRICING.anthropic table has no entry for it today. Leaving the field absent is honest; inventing a number is not. This has a direct, load-bearing consequence for Task 9: ModelInfo.pricing: ModelPricingInfo (src/lib/types/model.ts:184) has three required (non-optional) numeric fields (inputCostPer1K, outputCostPer1K, currency) — confirmed by reading src/lib/types/model.ts:137-141. Task 9's registry builder resolves this by only ever promoting manifest entries that do carry pricingPerMTok into the rebuilt MODEL_REGISTRY — see Task 9's design note for the full reasoning.\n\nThe manifest also carries an optional curated block for ModelInfo.performance/.useCases/.category. These three fields are today hand-tuned per model in MODEL_REGISTRY (src/lib/models/modelRegistry.ts) — there is no mechanical source for them anywhere else (not in MODEL_CONTEXT_WINDOWS, not in PRICING, not in VISION_CAPABILITIES). For the 25 ids that already have a MODEL_REGISTRY entry today (5 Anthropic, 20 OpenAI), Task 9 must reproduce those exact values byte-for-byte, or its own \"exact old output preserved\" equality test would be false for performance/useCases/category specifically. curated is how those 25 hand-tuned triples travel forward into the manifest instead of being silently dropped and re-derived.
|
|
11256
|
+
{"objectID":"e850eedf19d858ea5a8f63fb8925b2330256e21f1d19895caef38c476d0ab2c6","title":"Task 1: Manifest types","url":"/docs/superpowers/plans/2026-08-15-06-model-metadata-consolidation#task-1-manifest-types","content":"Files:\nModify: src/lib/types/model.ts:271 (append after the existing type block; do not touch anything above line 271)\nTest: none (pure type addition — verified by pnpm run check in the final step)\n\nInterfaces:\nConsumes: nothing (foundational task)\nProduces: ProviderModelManifestEntry, ManifestFamilyRule, ProviderModelManifest — the three types every later task imports from ../types/index.js.\n\nThe manifest's pricingPerMTok is deliberately optional. Some real, current models (e.g. claude-sonnet-5) have no verified price in any existing store — pricing.ts's own PRICING.anthropic table has no entry for it today. Leaving the field absent is honest; inventing a number is not. This has a direct, load-bearing consequence for Task 9: ModelInfo.pricing: ModelPricingInfo (src/lib/types/model.ts:184) has three required (non-optional) numeric fields (inputCostPer1K, outputCostPer1K, currency) — confirmed by reading src/lib/types/model.ts:137-141. Task 9's registry builder resolves this by only ever promoting manifest entries that do carry pricingPerMTok into the rebuilt MODEL_REGISTRY — see Task 9's design note for the full reasoning.\n\nThe manifest also carries an optional curated block for ModelInfo.performance/.useCases/.category. These three fields are today hand-tuned per model in MODEL_REGISTRY (src/lib/models/modelRegistry.ts) — there is no mechanical source for them anywhere else (not in MODEL_CONTEXT_WINDOWS, not in PRICING, not in VISION_CAPABILITIES). For the 25 ids that already have a MODEL_REGISTRY entry today (5 Anthropic, 20 OpenAI), Task 9 must reproduce those exact values byte-for-byte, or its own \"exact old output preserved\" equality test would be false for performance/useCases/category specifically. curated is how those 25 hand-tuned triples travel forward into the manifest instead of being silently dropped and re-derived.","hierarchy":{"lvl0":"Superpowers","lvl1":"Model Metadata Consolidation Implementation Plan","lvl2":"Task 1: Manifest types","lvl3":""}},
|
|
11257
11257
|
{"objectID":"b163fedb6334af6e0dcfc15589b1bf773b102afaec1de296f412e0f57c3f0619","title":"Task 2: Anthropic manifest","url":"/docs/superpowers/plans/2026-08-15-06-model-metadata-consolidation#task-2-anthropic-manifest","content":"Files:\nCreate: src/lib/models/manifests/anthropic.ts\nTest: none standalone — covered by Task 14's consistency suite\n\nInterfaces:\nConsumes: ProviderModelManifestEntry, ManifestFamilyRule, ProviderModelManifest (Task 1)\nProduces: export const anthropicManifest: ProviderModelManifest — the shape Task 4's aggregator imports and Task 6/7/8/9/10/11 all read through the manifest registry.\n\nEvery field below is traced to real, currently-committed data — no invented prices, context windows, or capability flags:\ncontextWindow from MODEL_CONTEXT_WINDOWS.anthropic (src/lib/constants/contextWindows.ts:160-182).\nmaxOutputTokens from getClaudeMaxOutputTokens() (src/lib/utils/tokenLimits.ts:141-170) — the regex ladder Critical Rule 3 documents as authoritative (Sonnet/Haiku 4.x → 64000, Opus 4.x → 32000, 3.7-sonnet → 64000, 3.5-family → 8192, 3.0-family → 4096). This is the value already correctly used by the native Anthropic/Vertex+Claude request paths; Task 11 propagates it into PROVIDER_MAX_TOKENS so getSafeMaxTokens() agrees with it too (see Task 11's design note on the documented contradiction).\npricingPerMTok from PRICING.anthropic (src/lib/utils/pricing.ts:26-113), mapping its cacheCreation field to the manifest's cacheWrite name.\nvision from VISION_CAPABILITIES.anthropic + VISION_FAMILY_RULES.anthropic (src/lib/adapters/providerImageAdapter.ts:70-77,107+).\ndisplayName/aliases for the 5 ids that already exist in MODEL_REGISTRY today are copied verbatim from src/lib/models/modelRegistry.ts (CLAUDE_3_5_SONNET → \"Claude 3.5 Sonnet\", CLAUDE_3_5_HAIKU → \"Claude 3.5 Haiku\", CLAUDE_OPUS_4_5/CLAUDE_SONNET_4_5/CLAUDE_4_5_HAIKU per the same file) to avoid any user-visible naming churn in formatModelForDisplay(). The other 10 ids use Anthropic's real public model names — not fabricated, but also not literal copies of any single existing file since none of these 10 previously had a MODEL_REGISTRY entry.","hierarchy":{"lvl0":"Superpowers","lvl1":"Model Metadata Consolidation Implementation Plan","lvl2":"Task 2: Anthropic manifest","lvl3":""}},
|
|
11258
11258
|
{"objectID":"3c6b6bd7f0cef241b71c6f2db0554d7f492980e1663f68d285313c7a14e0c98a","title":"Task 3: OpenAI manifest","url":"/docs/superpowers/plans/2026-08-15-06-model-metadata-consolidation#task-3-openai-manifest","content":"Files:\nCreate: src/lib/models/manifests/openai.ts\nTest: none standalone — covered by Task 14\n\nInterfaces:\nConsumes: ProviderModelManifest (Task 1)\nProduces: export const openaiManifest: ProviderModelManifest\n\n20 entries, one per non-deprecated OpenAIModels MODEL_REGISTRY key (src/lib/models/modelRegistry.ts:30-984) — O1_PREVIEW is excluded (@deprecated, \"Turned off Jul 14, 2025\" per AIProviderName's sibling OpenAIModels enum comment; the manifest models what's actually callable). displayName, aliases, maxOutputTokens, and the four boolean capability flags are copied verbatim from each entry's existing MODEL_REGISTRY block. contextWindow uses MODEL_CONTEXT_WINDOWS.openai (src/lib/constants/contextWindows.ts:183-226) rather than MODEL_REGISTRY's own limits.maxContextTokens where the two disagree — this is a real, demonstrated instance of the \"5 stores disagree\" problem the spec documents: MODEL_REGISTRY's GPT_5 entry says maxContextTokens: 256000, but MODEL_CONTEXT_WINDOWS.openai[\"gpt-5\"] says 400_000. MODEL_CONTEXT_WINDOWS is the actively-maintained, more specific store (its comments track exact release dates and shutdown notices), so it wins as the manifest's source of truth; pricingPerMTok comes from PRICING.openai (src/lib/utils/pricing.ts:162-247).\n\nThree ids — gpt-5.2-chat-latest, gpt-5.2-pro, o3-pro — have no distinct PRICING.openai entry of their own. Today, findRates()'s longest-prefix match silently resolves them to their shorter sibling's rate (gpt-5.2, gpt-5.2, o3 respectively) — confirmed by reading findRates()'s prefix-match loop (src/lib/utils/pricing.ts:705-712).","hierarchy":{"lvl0":"Superpowers","lvl1":"Model Metadata Consolidation Implementation Plan","lvl2":"Task 3: OpenAI manifest","lvl3":""}},
|
|
11259
11259
|
{"objectID":"51b929b137da650ee2d78b5ebe2a4e961dfccffb6d91b0cadd8da8132ba6fc67","title":"Task 4: Manifest registry aggregator","url":"/docs/superpowers/plans/2026-08-15-06-model-metadata-consolidation#task-4-manifest-registry-aggregator","content":"Files:\nCreate: src/lib/models/manifestRegistry.ts\nTest: test/continuous-test-suite-model-manifests.ts (created fully in Task 14; this task only needs pnpm run check)\n\nInterfaces:\nConsumes: anthropicManifest (Task 2), openaiManifest (Task 3), plus 5 more full + 23 minimal manifests (Task 5 — this task is written and tested against the two manifests that exist after Tasks 2-3; Task 5 adds the remaining 28 import lines to the same file as its own step).\nProduces: MANIFEST_REGISTRY: Record<string, ProviderModelManifest>, getManifestForProvider(provider: string): ProviderModelManifest | undefined, getAllManifestProviders(): string[], resolveManifestEntryExact(provider: string, model: string): ProviderModelManifestEntry | undefined, resolveManifestEntry(provider: string, model: string): ProviderModelManifestEntry | undefined — the five symbols every migration task (7-11) imports.\n\nresolveManifestEntryExact never falls back to a provider's _default entry; resolveManifestEntry does. The split exists because pricing.ts's Vertex→Google-Gemini and Bedrock→Anthropic cross-provider fallbacks (src/lib/utils/pricing.ts:714-741) must run before the provider's own _default, and providerImageAdapter.ts's PROXY_PROVIDERS pass-through check must run before any implicit _default short-circuit too — both need the \"give me a real match or nothing\" primitive that resolveManifestEntryExact provides, so they can insert their own special case in between the two. Family rules, when a _default fallback fires, are tested against the original model argument, not the literal string \"_default\" — so an unmatched gateway-shaped id still gets correctly patched.","hierarchy":{"lvl0":"Superpowers","lvl1":"Model Metadata Consolidation Implementation Plan","lvl2":"Task 4: Manifest registry aggregator","lvl3":""}},
|
|
11260
11260
|
{"objectID":"81958a14f6a1274ce14f356efcc03414cba6eb47c816466e4bd5a9ff15bc3301","title":"Task 5: Generator script + remaining 28 manifests","url":"/docs/superpowers/plans/2026-08-15-06-model-metadata-consolidation#task-5-generator-script-remaining-28-manifests","content":"Files:\nCreate: scripts/generate-remaining-manifests.ts\nCreate: src/lib/models/manifests/azure.ts, bedrock.ts, ollama.ts, mistral.ts, google-ai.ts (5 \"full\" providers — generated from existing MODEL_REGISTRY entries)\nCreate: src/lib/models/manifests/openai-compatible.ts, openrouter.ts, vertex.ts, huggingface.ts, litellm.ts, sagemaker.ts, deepseek.ts, nvidia-nim.ts, lm-studio.ts, llamacpp.ts, xai.ts, groq.ts, cohere.ts, together-ai.ts, fireworks.ts, perplexity.ts, cloudflare.ts, replicate.ts, voyage.ts, jina.ts, stability.ts, ideogram.ts, recraft.ts (23 \"minimal\" providers)\nModify: src/lib/models/manifestRegistry.ts:1-8 (add the 28 new import lines + registry entries)\n\nInterfaces:\nConsumes: MODEL_REGISTRY/getModelsByProvider (src/lib/models/modelRegistry.ts — exported, pre-migration shape, still the hand-authored data at this point in the plan since Task 9 hasn't run yet), findRates() is NOT directly importable (private const PRICING backs it, but findRates itself isn't exported either — confirmed by reading pricing.ts's export list) — the generator instead uses the exported calculateCost/hasPricing, and for context/vision/max-tokens uses getContextWindowSize (src/lib/constants/contextWindows.ts, exported), ProviderImageAdapter.supportsVision() (src/lib/adapters/providerImageAdapter.ts, exported), PROVIDER_MAX_TOKENS (src/lib/core/constants.ts, exported).\nProduces: 28 new export const <camelCaseProvider>Manifest: ProviderModelManifest values (one per file), wired into MANIFEST_REGISTRY.\n\nDesign note — why the generator reads only exported symbols. PRICING (src/lib/utils/pricing.ts) and VISION_CAPABILITIES (src/lib/adapters/providerImageAdapter.ts) are both private, unexported consts. A generator script living outside those modules cannot import them directly.","hierarchy":{"lvl0":"Superpowers","lvl1":"Model Metadata Consolidation Implementation Plan","lvl2":"Task 5: Generator script + remaining 28 manifests","lvl3":""}},
|
|
11261
11261
|
{"objectID":"e20d184026c8ea8d983dea441fa532577098941e880ab68fa86994a1acc24a53","title":"Task 6: Reconcile the Anthropic shadow catalog","url":"/docs/superpowers/plans/2026-08-15-06-model-metadata-consolidation#task-6-reconcile-the-anthropic-shadow-catalog","content":"Files:\nModify: src/lib/models/anthropicModels.ts:27-54 (enum), :108-234 (MODEL_METADATA)\nTest: test/continuous-test-suite-model-manifests.ts (Task 14 asserts on this file's output; this task's own verification is a standalone script check)\n\nInterfaces:\nConsumes: resolveManifestEntry (Task 4), anthropicManifest (Task 2)\nProduces: 3 new AnthropicModel enum members (CLAUDE_OPUS_4_5, CLAUDE_SONNET_4_5, CLAUDE_HAIKU_4_5), metadataFromManifest(id: string): AnthropicModelMetadata (new, internal helper — not exported, used only to build MODEL_METADATA). All 18 existing exported helper functions (isModelAvailableForTier, getAvailableModelsForTier, getModelDisplayName, getDefaultModelForTier, getModelMetadata, modelSupportsCapability, getMinimumTierForModel, getModelsWithCapability, getModelsByFamily, getLatestModelsByFamily, validateModelAccess, compareTiers, getContextWindow, getMaxOutputTokens, supportsVision, supportsExtendedThinking, plus the two @deprecated aliases getRecommendedModelForTier/getModelCapabilities) keep their exact signatures — only MODEL_METADATA's values change, sourced from the manifest instead of hand-typed literals.\n\nDesign note. AnthropicModel (src/lib/models/anthropicModels.ts:27-54) is a 9-member enum, independent of both AnthropicModels (src/lib/constants/enums.ts, a third catalog that only supplies MODEL_REGISTRY keys — untouched by this plan, see Out of Scope) and the manifest's 15 canonical ids. It is missing the three 4.5-generation models: CLAUDE_OPUS_4_5, CLAUDE_SONNET_4_5, CLAUDE_HAIKU_4_5. Adding them is this task's scope; four further gaps remain even after this task (claude-opus-4-1, claude-sonnet-5, claude-3-7-sonnet, claude-3-sonnet still have no AnthropicModel member) — flagged explicitly in this plan's Out of Scope section rather than silently left unaddressed, since expanding beyond the assigned 4.5-generation gap is a real scope decision, not an oversight.","hierarchy":{"lvl0":"Superpowers","lvl1":"Model Metadata Consolidation Implementation Plan","lvl2":"Task 6: Reconcile the Anthropic shadow catalog","lvl3":""}},
|
|
11262
|
-
{"objectID":"4bf2e1cfc693dc5307314637b22a769623a1c230b2e198be427c332eaa049c3a","title":"Task 7: Migrate contextWindows.ts","url":"/docs/superpowers/plans/2026-08-15-06-model-metadata-consolidation#task-7-migrate-contextwindowsts","content":"Files:\nModify: src/lib/constants/contextWindows.ts:515-574 (getContextWindowSize)\nTest: standalone script check (folded into Task 14's suite)\n\nInterfaces:\nConsumes: resolveManifestEntry (Task 4)\nProduces: getContextWindowSize(provider: string, model?: string): number — signature unchanged.\n\nDesign note. getContextWindowSize's current 5-step cascade is: dynamic-discovery registry → runtime windows (RUNTIME_CONTEXT_WINDOWS) → static exact match → static prefix match → provider _default → global DEFAULT_CONTEXT_WINDOW (128K). Only the static steps (exact/prefix/_default/global-default — steps 3-6) move to the manifest; the dynamic-discovery registry and RUNTIME_CONTEXT_WINDOWS map stay exactly as they are (they're runtime-populated state, not static data this plan owns) and continue to run first, preserving the documented incident fix (Claude-on-Vertex inheriting Gemini's 1,048,576 default) untouched. normalizeProviderForLookup()'s alias table (PROVIDER_ALIAS_MAP) also stays — the manifest is keyed by canonical AIProviderName values, and normalizeProviderForLookup is what turns \"googleAiStudio\"/\"lmstudio\"/etc into those canonical keys before the manifest lookup runs.\n[ ] Step 1: Write the failing test\n[ ] Step 2: Run it to verify it currently passes (establishes the behavior contract, not a failure)\n\nRun the command from Step 1.\nExpected: PASS (pre-migration): 1000000 — confirms the exact value the migration must preserve.\n[ ] Step 3: Replace the static-fallback portion of getContextWindowSize with a manifest lookup\n\nRead src/lib/constants/contextWindows.ts:515-574 in full before editing — it currently ends with the static-exact → prefix → _default → global-default chain reading from MODEL_CONTEXT_WINDOWS.
|
|
11262
|
+
{"objectID":"4bf2e1cfc693dc5307314637b22a769623a1c230b2e198be427c332eaa049c3a","title":"Task 7: Migrate contextWindows.ts","url":"/docs/superpowers/plans/2026-08-15-06-model-metadata-consolidation#task-7-migrate-contextwindowsts","content":"Files:\nModify: src/lib/constants/contextWindows.ts:515-574 (getContextWindowSize)\nTest: standalone script check (folded into Task 14's suite)\n\nInterfaces:\nConsumes: resolveManifestEntry (Task 4)\nProduces: getContextWindowSize(provider: string, model?: string): number — signature unchanged.\n\nDesign note. getContextWindowSize's current 5-step cascade is: dynamic-discovery registry → runtime windows (RUNTIME_CONTEXT_WINDOWS) → static exact match → static prefix match → provider _default → global DEFAULT_CONTEXT_WINDOW (128K). Only the static steps (exact/prefix/_default/global-default — steps 3-6) move to the manifest; the dynamic-discovery registry and RUNTIME_CONTEXT_WINDOWS map stay exactly as they are (they're runtime-populated state, not static data this plan owns) and continue to run first, preserving the documented incident fix (Claude-on-Vertex inheriting Gemini's 1,048,576 default) untouched. normalizeProviderForLookup()'s alias table (PROVIDER_ALIAS_MAP) also stays — the manifest is keyed by canonical AIProviderName values, and normalizeProviderForLookup is what turns \"googleAiStudio\"/\"lmstudio\"/etc into those canonical keys before the manifest lookup runs.\n[ ] Step 1: Write the failing test\n[ ] Step 2: Run it to verify it currently passes (establishes the behavior contract, not a failure)\n\nRun the command from Step 1.\nExpected: PASS (pre-migration): 1000000 — confirms the exact value the migration must preserve.\n[ ] Step 3: Replace the static-fallback portion of getContextWindowSize with a manifest lookup\n\nRead src/lib/constants/contextWindows.ts:515-574 in full before editing — it currently ends with the static-exact → prefix → _default → global-default chain reading from MODEL_CONTEXT_WINDOWS.","hierarchy":{"lvl0":"Superpowers","lvl1":"Model Metadata Consolidation Implementation Plan","lvl2":"Task 7: Migrate contextWindows.ts","lvl3":""}},
|
|
11263
11263
|
{"objectID":"63a264141f18c9548f6f95baaf74da6ec0dd7eed0692f3bdee2f6e600ba820a1","title":"Task 8: Migrate pricing.ts","url":"/docs/superpowers/plans/2026-08-15-06-model-metadata-consolidation#task-8-migrate-pricingts","content":"Files:\nModify: src/lib/utils/pricing.ts:643-744 (findRates)\nTest: standalone script check (folded into Task 14's suite)\n\nInterfaces:\nConsumes: resolveManifestEntryExact (Task 4)\nProduces: findRates(provider: string, model: string) (module-private, unchanged signature — still returns {input, output, cacheRead?, cacheCreation?} | undefined), calculateCost(), hasPricing() — all unchanged signatures, both barrel-exported from src/lib/index.ts.\n\nDesign note. findRates's current body: normalize provider via PROVIDER_ALIASES, handle the __cross_provider__ sentinel (litellm/openrouter/openaicompatible proxy through to whatever providerPricing search the caller's actual model implies), strip Bedrock ARN/vendor prefixes, exact match, longest-prefix match, Vertex→Google-Gemini fallback (must run before _default), then provider-level _default. Only the \"exact match, longest-prefix match\" core (src/lib/utils/pricing.ts:700-712) becomes a manifest call — the __cross_provider__ proxy search, Bedrock ARN-stripping, and Vertex→Google-Gemini special case all stay exactly as they are, calling the manifest-backed core recursively/directly where they previously indexed into PRICING directly. This is exactly why Task 4 built resolveManifestEntryExact (no implicit _default) as a separate primitive from resolveManifestEntry: the Vertex→Google-Gemini fallback must still run before any _default, and using resolveManifestEntryExact here (never falling back to _default on its own) preserves that exact ordering.\n[ ] Step 1: Write the failing test\n[ ] Step 2: Run it to confirm today's baseline\n\nRun the command from Step 1.\nExpected: PASS (pre-migration): 0.0125 true true\n[ ] Step 3: Replace findRates's exact/prefix core with a manifest call\n\nRead src/lib/utils/pricing.ts:643-744 in full before editing.","hierarchy":{"lvl0":"Superpowers","lvl1":"Model Metadata Consolidation Implementation Plan","lvl2":"Task 8: Migrate pricing.ts","lvl3":""}},
|
|
11264
11264
|
{"objectID":"51a4c27262df8d740cdcbca534a1caccbfff1d1dcd4d0bec931657f2705f9a93","title":"Task 9: Migrate modelRegistry.ts","url":"/docs/superpowers/plans/2026-08-15-06-model-metadata-consolidation#task-9-migrate-modelregistryts","content":"Files:\nModify: src/lib/models/modelRegistry.ts — replace the hand-authored MODEL_REGISTRY object literal (:28-2330, the exact range covering all [OpenAIModels.X]/[AnthropicModels.X] entries) with buildModelRegistryFromManifests(); replace getAvailableProviders() (:2558-2564)\nVerify only, no edit: src/cli/commands/models.ts:17-32,168-182 — confirmed below to already source its --provider choices dynamically from the function this task replaces\nTest: standalone script checks (folded into Task 14's suite)\n\nInterfaces:\nConsumes: getAllManifestProviders, getManifestForProvider (Task 4)\nProduces: MODEL_REGISTRY: Record<string, ModelInfo> (same exported const, now built by a function instead of a literal), getAllModels(), getModelById(), modelSupports(), getModelsByProvider(), calculateCost() (the ModelInfo-based one — distinct from pricing.ts's usage-based calculateCost, see the design note below), formatModelForDisplay(), getAvailableProviders(): AIProviderName[] — every signature unchanged. MODEL_ALIASES (built by iterating MODEL_REGISTRY, :2332-2339) is unaffected since it derives from whatever MODEL_REGISTRY ends up containing. SAMPLING_PARAM_REJECTING_FAMILIES/modelSupportsSamplingParams/resolveSamplingParams (:2477+) are untouched — out of scope, not one of the five stores, and other consumers (ClassifierRouter) depend on them working unchanged.\n\nDesign note — the ModelPricingInfo required-fields gap. ModelInfo.pricing: ModelPricingInfo (src/lib/types/model.ts:184) requires non-optional inputCostPer1K/outputCostPer1K/currency (confirmed: src/lib/types/model.ts:137-141 has no ? on any of the three fields). The manifest's pricingPerMTok is deliberately optional (Task 1).","hierarchy":{"lvl0":"Superpowers","lvl1":"Model Metadata Consolidation Implementation Plan","lvl2":"Task 9: Migrate modelRegistry.ts","lvl3":""}},
|
|
11265
11265
|
{"objectID":"cae6ed9dc6c82eae32630f9ed3fd85abfff82a393946196a218362beb677206e","title":"Task 10: Migrate providerImageAdapter.ts","url":"/docs/superpowers/plans/2026-08-15-06-model-metadata-consolidation#task-10-migrate-providerimageadapterts","content":"Files:\nModify: src/lib/adapters/providerImageAdapter.ts:650-680 (supportsVision), :107+ (keep VISION_CAPABILITIES/VISION_FAMILY_RULES as fallback for providers without a manifest entry — see design note)\nTest: standalone script checks (folded into Task 14's suite)\n\nInterfaces:\nConsumes: resolveManifestEntryExact (Task 4)\nProduces: ProviderImageAdapter.supportsVision(provider: string, model?: string): boolean, getSupportedModels(provider: string): string[], getVisionProviders(): string[] — all unchanged signatures.\n\nDesign note. supportsVision's current cascade: normalize provider → Anthropic-with-ANTHROPIC_BASE_URL-env special case (proxy override, untouched — not model metadata) → VISION_CAPABILITIES[provider] lookup → no-model short-circuit → substring match → VISION_FAMILY_RULES regex fallback → PROXY_PROVIDERS pass-through. The manifest's vision boolean plus its own familyRules cover the \"substring match\" and \"family regex\" steps together (Task 2's anthropic manifest already embeds the same two CLAUDE_MODERN_VISION_FAMILIES regexes as familyRules, applied by resolveManifestEntryExact itself — Task 4). The ANTHROPIC_BASE_URL env override and PROXY_PROVIDERS pass-through are provider-routing concerns, not model metadata — both stay in providerImageAdapter.ts untouched, running before and after the manifest call respectively, exactly as they do today relative to VISION_CAPABILITIES.\n[ ] Step 1: Write the failing test\n[ ] Step 2: Run it to confirm today's baseline\n\nRun the command from Step 1.\nExpected: PASS (pre-migration): true true false\n[ ] Step 3: Route supportsVision through the manifest, falling back to the legacy tables for un-manifested providers\n\nRead src/lib/adapters/providerImageAdapter.ts:650-680 in full before editing.","hierarchy":{"lvl0":"Superpowers","lvl1":"Model Metadata Consolidation Implementation Plan","lvl2":"Task 10: Migrate providerImageAdapter.ts","lvl3":""}},
|
|
@@ -11463,7 +11463,7 @@
|
|
|
11463
11463
|
{"objectID":"efb83ff09d62d10c1c1b9afb67769b19bd4b043702f6517e33bfeab37b3637a0","title":"Task 10: sessionAffinity.ts — the session→account binding store","url":"/docs/superpowers/plans/2026-09-23-proxy-account-routing-policies#task-10-sessionaffinityts-the-sessionaccount-binding-store","content":"Files:\nCreate: src/lib/proxy/sessionAffinity.ts\nTest: test/continuous-test-suite-proxy.ts\n\nInterfaces:\nProduces: bind(sessionId: string, accountKey: string, now: number): void, get(sessionId: string, now: number, idleTtlMs: number): string | undefined, clear(): void, size(): number, and a sessionAffinity namespace object bundling all four. Task 14 (ranking call sites) and Task 16 (binding on success) both import this.\nDesign decision: the spec's get(sessionId, now) is written with two parameters, but idleTtlMs is hot-reloadable per-request config, not a fixed module constant, so it is threaded as an explicit third parameter here — the module has no other way to know the currently configured TTL. get() never refreshes a binding's position or lastServedAt; only bind() does, since the spec's \"idle TTL counts from the session's last served request\" ties freshness to being served, not merely checked.\nDesign decision: the per-record shape ({ accountKey, lastServedAt }) is an inline object type on the Map's generic parameter, not a named type alias, so it does not trigger CLAUDE.md rule 2's \"all type definitions go in src/lib/types/\" for a private, single-use implementation detail with no external consumer.\n[ ] Step 1: Write the failing tests for bind/get, idle expiry, eviction, and clear\n\nAdd to test/continuous-test-suite-proxy.ts:\n[ ] Step 2: Run test to verify it fails\n\nRun: pnpm exec tsx test/continuous-test-suite-proxy.ts\nExpected: FAIL — src/lib/proxy/sessionAffinity.ts does not exist.\n[ ] Step 3: Write the module\n[ ] Step 4: Run test to verify it passes\n\nRun: pnpm exec tsx test/continuous-test-suite-proxy.ts\nExpected: PASS.\n[ ] Step 5: Register the new tests\n[ ] Step 6: Commit (amend)","hierarchy":{"lvl0":"Superpowers","lvl1":"Proxy Account Routing Policies Implementation Plan","lvl2":"Task 10: sessionAffinity.ts — the session→account binding store","lvl3":""}},
|
|
11464
11464
|
{"objectID":"fcfb234c614ebfe696518e8c8ed6c664fccc283a966bed092fc4846951dcbf60","title":"Task 11: accountRanking.ts PR2 extension — compareHeadroomFirst, precedence, spill","url":"/docs/superpowers/plans/2026-09-23-proxy-account-routing-policies#task-11-accountrankingts-pr2-extension-compareheadroomfirst-precedence-spill","content":"Files:\nModify: src/lib/proxy/accountRanking.ts\nTest: test/continuous-test-suite-proxy.ts\n\nInterfaces:\nProduces: compareHeadroomFirst(a, b, metricsByKey, primaryKey): [number, ProxyAccountRoutingReason]; applyAffinityAndPrimary({ orderedAccounts, metricsByKey, affinityKey?, primaryKey?, preferPrimary? }): { orderedAccounts, reason: \"session_affinity\" | \"preferred_primary\" | null, affinitySkippedReason: \"unusable\" | \"session_saturated\" | null }; applySpill({ orderedAccounts, inflightByKey, spillInflight }): { orderedAccounts, spill: { from, to, inflight } | null }; extended rankAccounts({ accounts, metricsByKey, primaryKey, ranking?, affinityKey?, preferPrimary? }): { orderedAccounts, reason, affinitySkippedReason }.\nConsumes: ProxyAccountRankingPolicy (Task 7).\n[ ] Step 1: Write the failing test for compareHeadroomFirst's headroom rung\n\nAdd to test/continuous-test-suite-proxy.ts:\n[ ] Step 2: Run test to verify it fails\n\nRun: pnpm exec tsx test/continuous-test-suite-proxy.ts\nExpected: FAIL — compareHeadroomFirst is not exported yet.\n[ ] Step 3: Add compareHeadroomFirst\n\nAppend to src/lib/proxy/accountRanking.ts:\n[ ] Step 4: Run test to verify it passes\n\nRun: pnpm exec tsx test/continuous-test-suite-proxy.ts\nExpected: PASS.\n[ ] Step 5: Write the failing test for applyAffinityAndPrimary's precedence\n[ ] Step 6: Run test to verify it fails\n\nRun: pnpm exec tsx test/continuous-test-suite-proxy.ts\nExpected: FAIL — applyAffinityAndPrimary is not exported yet.\n[ ] Step 7: Add applyAffinityAndPrimary\n[ ] Step 8: Run test to verify it passes\n\nRun: pnpm exec tsx test/continuous-test-suite-proxy.ts\nExpected: PASS.\n[ ] Step 9: Write the failing test for extended rankAccounts\n[ ] Step 10: Run test to verify it fails\n\nRun: pnpm exec tsx test/continuous-test-suite-proxy.ts\nExpected: FAIL — rankAccounts doesn't yet accept ranking/affinityKey/preferPrimary.","hierarchy":{"lvl0":"Superpowers","lvl1":"Proxy Account Routing Policies Implementation Plan","lvl2":"Task 11: accountRanking.ts PR2 extension — compareHeadroomFirst, precedence, spill","lvl3":""}},
|
|
11465
11465
|
{"objectID":"459ec51703ed8e203d88167801ea903261c07d76d78a0ed74063ef7e9ee7606c","title":"Task 12: orderAccountsByQuotaWithMetrics policy extension and buildRoutingDecision's policySelectionReason","url":"/docs/superpowers/plans/2026-09-23-proxy-account-routing-policies#task-12-orderaccountsbyquotawithmetrics-policy-extension-and-buildroutingdecisions-policyselectionreason","content":"Files:\nModify: src/lib/server/routes/claudeProxyRoutes.ts:2211-2240 (orderAccountsByQuotaWithMetrics), :2381-2515 (buildRoutingDecision), :12292+ (__testHooks.buildQuotaRoutingDecision)\n\nInterfaces:\nConsumes: rankAccounts's extended signature (Task 11).\nProduces: orderAccountsByQuotaWithMetrics(..., policy?: { ranking?, affinityKey?, preferPrimary? }) returns { orderedAccounts, metricsByKey, reason, affinitySkippedReason }; buildRoutingDecision(...) accepts policySelectionReason?, policy?, affinity?, spill?.\n[ ] Step 1: Write the failing test for buildRoutingDecision's override\n[ ] Step 2: Run test to verify it fails\n\nRun: pnpm exec tsx test/continuous-test-suite-proxy.ts\nExpected: FAIL — buildQuotaRoutingDecision doesn't accept a policy argument yet.\n[ ] Step 3: Extend orderAccountsByQuotaWithMetrics\n\norderAccountsByQuota (the label-only wrapper) is untouched — it only ever reads .orderedAccounts off the return value, which keeps working.\n[ ] Step 4: Extend buildRoutingDecision\n\nAdd three new optional fields to its args type and use them in the quotaOrdered branch and the return object:\n\nIn the mode/selectionReason block:\n\nIn the returned object, append after candidates,:\n\nOmitting policySelectionReason/policy/affinity/spill reproduces PR1's exact output — this preserves every existing call site (including Task 6's replay assumptions) without modification.\n[ ] Step 5: Extend __testHooks.buildQuotaRoutingDecision\n[ ] Step 6: Run test to verify it passes\n\nRun: pnpm exec tsx test/continuous-test-suite-proxy.ts\nExpected: PASS.\n[ ] Step 7: Re-run the Task 2 route-order tests to confirm no regression\n\nRun: pnpm exec tsx test/continuous-test-suite-proxy.ts\nExpected: PASS — testOrderAccountsByQuota and runWeeklyExpiryOrderingCases never pass a policy argument, so they exercise the exact PR1 path.\n[ ] Step 8: Register the new test\n[ ] Step 9: Commit (amend)","hierarchy":{"lvl0":"Superpowers","lvl1":"Proxy Account Routing Policies Implementation Plan","lvl2":"Task 12: orderAccountsByQuotaWithMetrics policy extension and buildRoutingDecision's policySelectionReason","lvl3":""}},
|
|
11466
|
-
{"objectID":"b161eed43a95b3a9bb82970cc23098beb4c6b99f70fb03d2797a8a8a711a86a8","title":"Task 13: Thread the Claude Code session id through loadClaudeProxyAccounts","url":"/docs/superpowers/plans/2026-09-23-proxy-account-routing-policies#task-13-thread-the-claude-code-session-id-through-loadclaudeproxyaccounts","content":"Files:\nModify: src/lib/server/routes/claudeProxyRoutes.ts:4618-4641 (signature), :4965-5023 (tail), :9749-9888 (handleAnthropicRoutedClaudeRequest destructure)\nModify: src/lib/types/proxy.ts:1288-1298 (LoadedClaudeAccountContext)\n\nInterfaces:\nProduces: LoadedClaudeAccountContext.sessionId?: string. Task 14 consumes it as selectClaudeProxyAccountOrder's sessionId argument.\n[ ] Step 1: Write the failing test asserting sessionId is threaded through\n\n(Rather than exercising the full route — which needs a live account pool and is covered end-to-end by Task 19 — this task's own test only pins the plumbing hook that Task 19 depends on. Add the hook in Step 4.)\n[ ] Step 2: Run test to verify it fails\n\nRun: pnpm exec tsx test/continuous-test-suite-proxy.ts\nExpected: FAIL.\n[ ] Step 3: Move extractSnapshotBody earlier and add sessionId to the returned context\n\nIn loadClaudeProxyAccounts (currently ending at claudeProxyRoutes.ts:4965-5023), the call:\n\ncurrently runs extractSnapshotBody(body) after selectClaudeProxyAccountOrder has already been called (claudeProxyRoutes.ts:4978). Move the extraction up so sessionId is available before that call. Replace the whole tail:\n\n(ranking, preferPrimary, sessionAffinityEnabled, sessionAffinityIdleTtlMs, spillInflight are added to loadClaudeProxyAccounts's own args/destructure in Task 15, alongside selectClaudeProxyAccountOrder's rewrite in Task 14 — this step only moves the extraction and adds the plumbing that depends on it existing.)
|
|
11466
|
+
{"objectID":"b161eed43a95b3a9bb82970cc23098beb4c6b99f70fb03d2797a8a8a711a86a8","title":"Task 13: Thread the Claude Code session id through loadClaudeProxyAccounts","url":"/docs/superpowers/plans/2026-09-23-proxy-account-routing-policies#task-13-thread-the-claude-code-session-id-through-loadclaudeproxyaccounts","content":"Files:\nModify: src/lib/server/routes/claudeProxyRoutes.ts:4618-4641 (signature), :4965-5023 (tail), :9749-9888 (handleAnthropicRoutedClaudeRequest destructure)\nModify: src/lib/types/proxy.ts:1288-1298 (LoadedClaudeAccountContext)\n\nInterfaces:\nProduces: LoadedClaudeAccountContext.sessionId?: string. Task 14 consumes it as selectClaudeProxyAccountOrder's sessionId argument.\n[ ] Step 1: Write the failing test asserting sessionId is threaded through\n\n(Rather than exercising the full route — which needs a live account pool and is covered end-to-end by Task 19 — this task's own test only pins the plumbing hook that Task 19 depends on. Add the hook in Step 4.)\n[ ] Step 2: Run test to verify it fails\n\nRun: pnpm exec tsx test/continuous-test-suite-proxy.ts\nExpected: FAIL.\n[ ] Step 3: Move extractSnapshotBody earlier and add sessionId to the returned context\n\nIn loadClaudeProxyAccounts (currently ending at claudeProxyRoutes.ts:4965-5023), the call:\n\ncurrently runs extractSnapshotBody(body) after selectClaudeProxyAccountOrder has already been called (claudeProxyRoutes.ts:4978). Move the extraction up so sessionId is available before that call. Replace the whole tail:\n\n(ranking, preferPrimary, sessionAffinityEnabled, sessionAffinityIdleTtlMs, spillInflight are added to loadClaudeProxyAccounts's own args/destructure in Task 15, alongside selectClaudeProxyAccountOrder's rewrite in Task 14 — this step only moves the extraction and adds the plumbing that depends on it existing.)","hierarchy":{"lvl0":"Superpowers","lvl1":"Proxy Account Routing Policies Implementation Plan","lvl2":"Task 13: Thread the Claude Code session id through loadClaudeProxyAccounts","lvl3":""}},
|
|
11467
11467
|
{"objectID":"e56e61ee45c533757ab1712724f47f87a6c187f8556331227e846f7fd211d6e1","title":"Task 14: Rewrite selectClaudeProxyAccountOrder to apply the full precedence chain","url":"/docs/superpowers/plans/2026-09-23-proxy-account-routing-policies#task-14-rewrite-selectclaudeproxyaccountorder-to-apply-the-full-precedence-chain","content":"Files:\nModify: src/lib/server/routes/claudeProxyRoutes.ts:2517-2624\n\nInterfaces:\nConsumes: applyAffinityAndPrimary, applySpill, orderAccountsByQuotaWithMetrics (extended, Task 12), sessionAffinity.get (Task 10), getAccountInflight (Task 3).\nProduces: selectClaudeProxyAccountOrder's new signature, consumed by Task 15's threading through loadClaudeProxyAccounts/handleAnthropicRoutedClaudeRequest.\n[ ] Step 1: Write the failing test for the \"quota routing off, affinity still applies\" case (Review Focus item 1)\n\nThis requires a new __testHooks.selectClaudeProxyAccountOrderForTests — added in Step 4, since selectClaudeProxyAccountOrder itself is route-local.\n[ ] Step 2: Run test to verify it fails\n\nRun: pnpm exec tsx test/continuous-test-suite-proxy.ts\nExpected: FAIL.\n[ ] Step 3: Write the failing test for \"thrown spill on the quota-off path restores the base order\" (Review Focus item 1)\n\nThe non-quota-ordered branch's catch must not leave a partial policy reorder\nin place. Bind session affinity so applyAffinityAndPrimary genuinely\nreorders orderedAccounts (reason: \"session_affinity\"), then force\nmaybeSpill to throw regardless of that reason — its own guard normally\nskips session_affinity/preferred_primary, so a deterministic test-only\nhook (forceSpillThrowForTests, added in Step 5) is the only way to reach\nthe throwing branch on this reason. The assertion is that the pre-policy\norder is served, not the partial [b, a] reorder:\n\nThis requires __testHooks.setForceSpillThrowForTests — added in Step 7,\nalongside forceSpillThrowForTests's declaration in Step 5 and its check\ninside maybeSpill in Step 6.\n[ ] Step 4: Run test to verify it fails\n\nRun: pnpm exec tsx test/continuous-test-suite-proxy.ts\nExpected: FAIL (the hook doesn't exist yet, and even once it does, the\npre-fix catch block doesn't restore orderedAccounts).","hierarchy":{"lvl0":"Superpowers","lvl1":"Proxy Account Routing Policies Implementation Plan","lvl2":"Task 14: Rewrite selectClaudeProxyAccountOrder to apply the full precedence chain","lvl3":""}},
|
|
11468
11468
|
{"objectID":"a9d029337d9908f4581ab3395356e2dc614e59aba997203fb88725a6522b70a9","title":"Task 15: Thread the five policy values through the call chain to /v1/messages","url":"/docs/superpowers/plans/2026-09-23-proxy-account-routing-policies#task-15-thread-the-five-policy-values-through-the-call-chain-to-v1messages","content":"Files:\nModify: src/lib/server/routes/claudeProxyRoutes.ts:4618-4641 (loadClaudeProxyAccounts args), :9749-9888 (handleAnthropicRoutedClaudeRequest args + call site), :10717-10749 (requestRouting fallback literal), :10829-10845 (call into handleAnthropicRoutedClaudeRequest)\n\nInterfaces:\nConsumes: ProxyRuntimeConfigSnapshot's five new fields (Task 9).\nProduces: every function in the chain now accepts and forwards ranking, preferPrimary, sessionAffinityEnabled, sessionAffinityIdleTtlMs, spillInflight.\n[ ] Step 1: Extend loadClaudeProxyAccounts's args and destructure\n\n(the unchanged token-store/cooldown/account-assembly body follows, ending at the Task 13 tail which now passes ranking, preferPrimary, sessionAffinityEnabled, sessionAffinityIdleTtlMs, spillInflight into selectClaudeProxyAccountOrder.)\n[ ] Step 2: Extend handleAnthropicRoutedClaudeRequest's args, destructure, and its call into loadClaudeProxyAccounts\n[ ] Step 3: Extend the POST /v1/messages route's fallback snapshot literal and call site\n\nIn the inline fallback used when runtimeConfigProvider is absent (claudeProxyRoutes.ts:10734-10745):\n\nAnd the call into handleAnthropicRoutedClaudeRequest (claudeProxyRoutes.ts:10829-10845):\n[ ] Step 4: Type check\n\nRun: pnpm run check\nExpected: PASS — this clears the Task 9 Step 4 failure.\n[ ] Step 5: Run the full proxy test suite\n\nRun: pnpm exec tsx test/continuous-test-suite-proxy.ts\nExpected: PASS.\n[ ] Step 6: Commit (amend)","hierarchy":{"lvl0":"Superpowers","lvl1":"Proxy Account Routing Policies Implementation Plan","lvl2":"Task 15: Thread the five policy values through the call chain to /v1/messages","lvl3":""}},
|
|
11469
11469
|
{"objectID":"6f1d084d9a6a60141a153bcc1bdbe70aa5866d1b9f505e5d990ce43a4605089d","title":"Task 16: Bind the session to the account that served the successful response","url":"/docs/superpowers/plans/2026-09-23-proxy-account-routing-policies#task-16-bind-the-session-to-the-account-that-served-the-successful-response","content":"Files:\nModify: src/lib/server/routes/claudeProxyRoutes.ts:10377-10451\n\nInterfaces:\nConsumes: sessionAffinity.bind (Task 10), sessionAffinityEnabled/sessionId (Task 15's threading), account (already in scope as the loop's current account).\n[ ] Step 1: Write the failing test for bind-on-success\n\n(This task's real coverage is the end-to-end CLI test in Task 19, which drives an actual response through the loop; this unit-level check exists only to keep the task independently testable per the plan's \"each task ends with an independently testable deliverable\" rule.)\n[ ] Step 2: Run test to verify it fails\n\nRun: pnpm exec tsx test/continuous-test-suite-proxy.ts\nExpected: this specific test passes trivially since it only calls sessionAffinity directly (already built in Task 10) — run it to confirm the harness wiring, then proceed to the real implementation step, which Task 19 will exercise end-to-end.\n[ ] Step 3: Insert the binding call\n\nIn handleAnthropicRoutedClaudeRequest's attempt loop (claudeProxyRoutes.ts:10441-10443), between the existing lines:\n\nAdd the import at the top of the file, alongside the Task 12 accountRanking.js import:\n[ ] Step 4: Run the full proxy suite\n\nRun: pnpm exec tsx test/continuous-test-suite-proxy.ts\nExpected: PASS.\n[ ] Step 5: Register the new test\n[ ] Step 6: Commit (amend)","hierarchy":{"lvl0":"Superpowers","lvl1":"Proxy Account Routing Policies Implementation Plan","lvl2":"Task 16: Bind the session to the account that served the successful response","lvl3":""}},
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@juspay/neurolink",
|
|
3
|
-
"version": "12.47.
|
|
3
|
+
"version": "12.47.10",
|
|
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": {
|