@gtrabanco/pi-nan-provider 1.0.1 → 1.2.1

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/AGENTS.md CHANGED
@@ -172,20 +172,43 @@ Since 1.0.0 the package version **aligns its MAJOR.MINOR with the pi release lin
172
172
  override (maintainer-confirmed 2026-09-05) was withdrawn 2026-09-07 — the
173
173
  updated NaN docs still say 262K "the model's native window" and models.dev
174
174
  agrees at 262,144.
175
+ - **Catalog authority order** (maintainer instruction, 2026-10-14):
176
+ 1. a **manual override**, as long as the docs have not changed since it was
177
+ written; 2. **https://nan.builders/docs/models** — the source of truth;
178
+ 3. **models.dev** (provider `nan`). When the docs change and an override
179
+ predates the change, the docs win, **but the override must be re-verified
180
+ against the live gateway first** — a measured override usually encodes a
181
+ real failure mode the docs may not describe. **When the live probe
182
+ disagrees with the docs, the measurement wins** (maintainer instruction,
183
+ 2026-10-14): the docs' `deepseek-v4-flash` "any value (no effect)" claim
184
+ was disproven by a re-probe, so the measured `none` behavior stayed.
185
+ models.dev is a
186
+ downstream mirror a human updates later than the docs or a Discord
187
+ announcement, so a divergence is never by itself proof the docs are
188
+ wrong. Every divergence or exclusion is recorded with provenance.
175
189
  - **Which models exist**: https://nan.builders/docs/models is the source of
176
190
  truth (maintainer instruction, reaffirmed 2026-09-29), cross-checked against
177
- the `model` param description in https://nan.builders/openapi.json; models.dev
178
- (provider `nan`) supplies the numeric limits for the ids it documents, and
179
- every divergence or exclusion is recorded with provenance.
180
- Official chat models (checked 2026-09-29): community `deepseek-v4-flash`,
191
+ the `model` param description in https://nan.builders/openapi.json. All seven
192
+ chat models declare 1M-token windows where the docs say so —
193
+ `deepseek-v4-flash`, `glm5.3-flash`, `qwen3.8-flash` and `mimo-v2.6-flash` at
194
+ **1,048,576**, `qwen3.6` and `gemma4` at **262,144** — and the first three
195
+ carry a `MANUAL_OVERRIDES.contextWindow` because models.dev lagged (rounded
196
+ 1,000,000 for the first two, stale 262,144 for `qwen3.8-flash`; docs checked
197
+ 2026-10-14).
198
+ Official chat models (checked 2026-10-14): community `deepseek-v4-flash`,
181
199
  `mimo-v2.6-flash`, `qwen3.8-flash`, `glm5.3-flash`, `qwen3.6`, `gemma4`
182
200
  (all text+image vision) + premium-tier `glm5.3`
183
- (~753B MoE, text-only input, 1M context, 400M tokens/rolling 4h window).
184
- glm5.3 is now documented by models.dev too (1M context / 131,072 max output,
185
- checked 2026-09-13) but stays out of the static catalog via
186
- `LIVE_ONLY_MODEL_IDS` (premium tier) so a non-premium key never sees a
187
- model it cannot call when the live `/models` fetch is unavailable; premium
188
- keys still receive it live with conservative placeholder limits.
201
+ (~753B MoE, multimodal text+image+audio+video input, 1M context, 400M
202
+ tokens/rolling 4h window).
203
+ glm5.3 stays out of the static catalog via `LIVE_ONLY_MODEL_IDS` (premium
204
+ tier) so a non-premium key never sees a model it cannot call when the live
205
+ `/models` fetch is unavailable. Premium keys receive it live with its
206
+ DOCUMENTED capabilities, not a blind placeholder: `LIVE_ONLY_MODEL_DATA` in
207
+ `src/fetch-models.ts` (1,048,576 / 131,072, text+image, `thinkingLevelMap
208
+ { off: "low" }`) is applied both by `mergeLiveWithGenerated` and by
209
+ `buildOverlayMap`, so a stored `glm5.3` entry is also corrected. The store
210
+ still decides which ids exist; the table only decides their capabilities
211
+ (issue #19's invariant is intact).
189
212
  Removed by the provider: `glm5.2` (2026-09-05) and `mimo-v2.5` (checked
190
213
  2026-09-29 — zero mentions in the docs and in openapi.json, and models.dev
191
214
  dropped it too; superseded by `mimo-v2.6-flash`). models.dev may re-list a
@@ -247,34 +270,38 @@ Since 1.0.0 the package version **aligns its MAJOR.MINOR with the pi release lin
247
270
  the `SessionEntry` union, expanded `TurnEndEvent`, removed `shouldStopAfterTurn`,
248
271
  `SessionManager` canonical for provider context. The package touches none of them.
249
272
  - Since 0.10.0, this package uses native MCP via `pi.registerMcpServer()`.
250
- Both servers are session-scoped, visible in `/mcp` with source "extension".
273
+ The server is session-scoped, visible in `/mcp` with source "extension".
251
274
  Server names and tool IDs:
252
- - `nan-search` → tools: `mcp__nan_search__web_search`
253
- (official remote, HTTP, `Authorization: Bearer <key>` header)
254
- - `nan-media` → tools: `mcp__nan_media__generate_image/edit_image/text_to_speech/list_voices/speech_to_text/list_models/embed_text/rerank_documents`
255
- (community stdio, `npx -y nan-mcp-server@1.1.2`, 120s timeout; 8 tools as of 1.1.2)
256
- - `exposure: "direct"` on both — tools are declared to the model.
275
+ - `nan-media` → tools: `mcp__nan_media__generate_image/edit_image/text_to_speech/list_voices/speech_to_text/list_models/embed_text/rerank_documents/get_quota`
276
+ (community stdio, `npx -y nan-mcp-server@1.3.0`, 120s timeout; 9 tools as of 1.3.0)
277
+ - `exposure: "direct"` — tools are declared to the model.
257
278
  - User `mcp.json` entries with the same name take precedence.
258
279
  - `/nan-mcp enable/disable` calls `pi.registerMcpServer()` / `pi.unregisterMcpServer()` directly.
259
- - Missing `NAN_API_KEY` at load: web-search server NOT registered (console.warn).
280
+ - Missing `NAN_API_KEY` at load: media server NOT registered (console.warn).
281
+ - **`nan-search` was REMOVED in 1.2.1.** NaN's official remote MCP server
282
+ (`https://api.nan.builders/mcp`) now exposes ZERO tools: `initialize` returns an
283
+ empty `capabilities.tools` and `tools/list` returns `{"tools":[]}` (verified with a
284
+ valid key on 2026-10-15), and NaN deleted every MCP mention from its docs (the old
285
+ `/docs/mcp` redirects to `/docs/agent-setup`). The `web_search` tool no longer
286
+ exists anywhere in NaN's surface. Users must bring their own `web_search`/fetch MCP
287
+ server in `mcp.json` (README documents this). `NAN_MCP_TOOLS` is gone with it.
260
288
  NaN integration facts remain:
261
289
  - pi >=0.99.2 sanitizes MCP tool/namespace names by replacing every character except
262
- `[A-Za-z0-9_]` with `"_"` (0.99.0–0.99.1 kept `-`). So `mcp__nan-search__web_search`
263
- became `mcp__nan_search__web_search` and `mcp__nan-media__*` became
264
- `mcp__nan_media__*`. Server names differing only in `-`/`_` now collide
265
- (`nan-search` and `nan-media` do not collide, they differ in more than one character).
290
+ `[A-Za-z0-9_]` with `"_"` (0.99.0–0.99.1 kept `-`). So `mcp__nan-media__*` keeps its
291
+ underscore form from 0.99.2 onward. (The removed `nan-search` server used to
292
+ demonstrate the hyphen→underscore rename; do not rely on it.)
266
293
  - pi 0.99.2+/1.0 accept `McpServerConfig.description` (system-prompt listing plus
267
294
  tool-search ranking); `validateMcpServerConfig` in 0.99.0–0.99.1 ignores unknown
268
295
  keys, so passing `description` stays compatible.
269
296
  - NaN's official remote MCP server: `https://api.nan.builders/mcp` (host
270
297
  root, NOT /v1; JSON-RPC 2.0 over streamable HTTP, stateless; same `sk-`
271
298
  key, shared rate limit/quota). Spec: https://nan.builders/openapi.json
272
- (tag "MCP"). Currently exposes `web_search`.
299
+ (tag "MCP"). **Currently exposes no tools** (see the removal note above).
273
300
  - Community `nan-mcp-server` (https://github.com/luciferfran/nan-mcp-server):
274
- stdio MCP server, version-pinned via NAN_MEDIA_MCP_VERSION (default 1.1.2)
275
- or full command override via NAN_MEDIA_MCP_COMMAND. Tools (1.1.2): generate_image,
301
+ stdio MCP server, version-pinned via NAN_MEDIA_MCP_VERSION (default 1.3.0)
302
+ or full command override via NAN_MEDIA_MCP_COMMAND. Tools (1.3.0): generate_image,
276
303
  edit_image, text_to_speech, list_voices, speech_to_text, list_models, embed_text,
277
- rerank_documents.
304
+ rerank_documents, get_quota.
278
305
  - Automated check (scripts/check-nan-mcp-server.ts) compares the npm registry
279
306
  against the pin weekly and files a `dependencies` issue when a newer release
280
307
  exists, with a breaking/safe verdict from the live server tool surface.
@@ -293,11 +320,48 @@ Since 1.0.0 the package version **aligns its MAJOR.MINOR with the pi release lin
293
320
  `mcp_servers_change` so pi's report stays silent, and warns once per session;
294
321
  `/nan-mcp enable` persists the toggle without registering. Regression tests:
295
322
  `test/mcp-host-connector.test.ts`.
296
- - **pi 1.0.0 / pi-ai 1.0.0 compat** (verified 2026-10-01): the peer range is now
297
- `">=0.99.0 <2"` (widened from `">=0.99.0 <1"`); the pi-ai 1.0.0 index/compat/types
298
- type surfaces are identical to 0.99.1 (the release only adds a `./models` subpath,
299
- Anthropic federation env consts, and a z.ai CN overflow pattern); the package's
300
- tests and typecheck pass against 1.0.0 unchanged.
323
+ - **`deepseek-v4-flash` reasoning_effort: the docs are stale, the measurement
324
+ wins** (re-probed live 2026-10-14). The docs claim the parameter is "any value
325
+ (no effect)"; a three-model probe disproves it — `none` gave **0** reasoning
326
+ tokens with a full answer on `deepseek-v4-flash`, `mimo-v2.6-flash` and
327
+ `qwen3.6`, while `low` gave 57 / 22 / 951 and omitting the parameter 63 / 17 /
328
+ 905 (`minimal` on deepseek gave 109). So `none` disables reasoning and every
329
+ other value leaves it on. The catalog keeps `reasoningEffortValues: ["none"]`
330
+ and `thinkingLevelMap { off: "none" }`, and `mimo-v2.6-flash` — which the docs
331
+ called "depth not adjustable" — gains `thinkingLevelMap { off: "none" }` for
332
+ the same reason. `qwen3.8-flash` stays unmapped: only `none` was sampled for
333
+ it, so no other level is mapped. Probe: short prompt, `max_tokens: 2048`,
334
+ streaming with `include_usage`; 10 requests, under 50k tokens.
335
+ - **Reasoning-only stream limit** (https://nan.builders/docs/models
336
+ #reasoning-only-stream-limit, checked 2026-10-14): NaN closes a turn that
337
+ produced only reasoning once it passes 45,000 reasoning characters, or after
338
+ 420 s without visible output (600 s once the turn has demonstrably exceeded
339
+ that character count); the character budget also scales with prompt size
340
+ (~150,000 headroom + half the prompt, capped at 300,000). The cut is
341
+ `finish_reason: "length"` on an empty delta plus a final usage chunk marked
342
+ `estimated: true`, `billed: false` and carrying
343
+ `nan_truncation: { reason: "reasoning_only_stream" }`.
344
+ `src/reasoning-only-stream-guard.ts` (issue #21) keys on that marker;
345
+ earlier comment/message text said "60,000 characters" and was corrected to
346
+ the documented figures.
347
+ - **pi 1.2.0 / pi-ai 1.2.0 compat** (verified 2026-10-14, the current verified
348
+ baseline): the peer range stays `">=0.99.0 <2"` (1.2.0 is inside it). The pi-ai
349
+ 1.2.0 index/compat type surface is byte-identical to 1.0.0 (`index.d.ts` diff is
350
+ empty); the only additions are `KnownProvider` gaining `"azure"` (renamed from
351
+ `"azure-openai-responses"` in pi 1.0.3 — not used here), a new
352
+ `"openai-decisions"` classifier API, `SamplingParams`/`SamplingParamsByThinkingLevel`
353
+ type aliases (fields pi-ai already honored; `models.json`-only), and a new
354
+ optional `RefreshModelsContext.baseUrl`. `ThinkingLevelMap`, `ImageModel`,
355
+ `ImageApi`, `OpenAICompletionsCompat`, `createProvider`, `envApiKeyAuth`,
356
+ `registerMcpServer`/`unregisterMcpServer` and `registerVirtualModel` are all
357
+ unchanged, and the `thinkingLevelMap.off` branch in `buildRequest` still fires
358
+ at `api/openai-completions.js` ~line 719. The package's tests (328) and
359
+ typecheck pass against 1.2.0 unchanged; the upgrade is devDependency-only.
360
+ - **pi 1.0.0 / pi-ai 1.0.0 compat** (verified 2026-10-01): the peer range was
361
+ widened to `">=0.99.0 <2"` (from `">=0.99.0 <1"`); the pi-ai 1.0.0
362
+ index/compat/types type surfaces are identical to 0.99.1 (the release only adds
363
+ a `./models` subpath, Anthropic federation env consts, and a z.ai CN overflow
364
+ pattern); the package's tests and typecheck pass against 1.0.0 unchanged.
301
365
  - **Native image models** (verified 2026-10-01): pi 1.0 lets a provider register
302
366
  `ImageModel` entries (`type: "image"`) plus a `Provider.images` implementation map
303
367
  keyed by a custom `ImageApi` id (`"nan-images"`); codemode reaches them with
package/README.es.md CHANGED
@@ -1,11 +1,12 @@
1
1
  # @gtrabanco/pi-nan-provider
2
2
 
3
3
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
4
- [![Version](https://img.shields.io/badge/version-0.11.0-blue)](https://github.com/gtrabanco/pi-nan-provider/releases)
4
+ [![Version](https://img.shields.io/badge/version-1.2.1-blue)](https://github.com/gtrabanco/pi-nan-provider/releases)
5
+ [![Built with NaN](https://nan.builders/badge/built-with-nan-compact.svg)](https://cloud.nan.builders/r/7GK06FX8)
5
6
 
6
- [NaN Builders](https://nan.builders) model provider + MCP nativo para [pi](https://github.com/earendil-works/pi).
7
+ [NaN Builders](https://cloud.nan.builders/r/7GK06FX8) model provider + MCP nativo para [pi](https://github.com/earendil-works/pi).
7
8
 
8
- Registra el proveedor `nan` vía `pi.registerProvider()` usando la API OpenAI-compatible de NaN (`https://api.nan.builders/v1`), y registra servidores MCP nativos con `pi.registerMcpServer()`.
9
+ Registra el proveedor `nan` vía `pi.registerProvider()` usando la API OpenAI-compatible de NaN (`https://api.nan.builders/v1`), y registra el servidor MCP de media de la comunidad con `pi.registerMcpServer()`.
9
10
 
10
11
  ---
11
12
 
@@ -101,22 +102,48 @@ Consigue una clave en la [plataforma NaN](https://cloud.nan.builders/r/7GK06FX8)
101
102
 
102
103
  ## 🔌 MCP nativo
103
104
 
104
- Dado que [pi 0.99.0 incluye un cliente MCP integrado](https://github.com/earendil-works/pi/blob/main/docs/usage.md), este paquete migra sus puentes a MCP nativo (requiere `pi >=0.99, <2` — pi 0.99 hasta 1.0 son compatibles; el rango peer se amplió a `<2` en 0.11.0).
105
+ Dado que [pi 0.99.0 incluye un cliente MCP integrado](https://github.com/earendil-works/pi/blob/main/docs/usage.md), este paquete usa MCP nativo (requiere `pi >=0.99, <2` — pi 0.99 hasta 1.2 son compatibles; el rango peer se amplió a `<2` en 0.11.0).
105
106
 
106
- Ambos puentes están **activados por defecto** (por sesión, visibles en `/mcp`). Usa `/nan-mcp` para gestionarlos.
107
+ El puente de media está **activado por defecto** (por sesión, visible en `/mcp`). Usa `/nan-mcp` para gestionarlo.
107
108
 
108
- > [!TIP]
109
- > ¿Prefieres configurar los servidores MCP de NaN tú mismo? Desde pi 0.99.2/1.0, un servidor MCP HTTP en el `mcp.json` global puede autenticarse con tu token de `/login nan` en vez de una clave copiada: `{ "auth": { "provider": "nan" } }` (solo en el `mcp.json` global; requiere `https`). El registro integrado de `nan-search` sigue usando `NAN_API_KEY`/la credencial almacenada.
109
+ > [!WARNING]
110
+ > **El servidor MCP remoto oficial de NaN ya no expone ninguna herramienta.** Hasta 1.2.0 este paquete
111
+ > incluía un puente `nan-search` apuntando a `https://api.nan.builders/mcp`, que exponía
112
+ > `web_search`. Ese servidor ahora responde a `initialize` con `capabilities.tools` vacío y a
113
+ > `tools/list` con `{"tools":[]}` — verificado con una clave válida el 2026-10-15 — y NaN eliminó toda
114
+ > mención a MCP de su documentación (la antigua página `/docs/mcp` ahora redirige a `/docs/agent-setup`).
115
+ > El puente se eliminó en **1.2.1** porque registrar un servidor que no expone nada solo produce un
116
+ > servidor sin herramientas en `/mcp`.
117
+ >
118
+ > **Trae tu propio `web_search` y fetch.** Instala un servidor MCP que los proporcione (p. ej. el par
119
+ > `fetch` + `brave-search` de los servidores MCP oficiales, o cualquier otro servidor MCP de
120
+ > búsqueda/fetch) y decláralo en tu `mcp.json` global:
121
+ >
122
+ > ```json
123
+ > {
124
+ > "mcpServers": {
125
+ > "fetch": { "command": "uvx", "args": ["mcp-server-fetch"] },
126
+ > "web-search": {
127
+ > "command": "npx",
128
+ > "args": ["-y", "@modelcontextprotocol/server-brave-search"],
129
+ > "env": { "BRAVE_API_KEY": "tu-clave" }
130
+ > }
131
+ > }
132
+ > }
133
+ > ```
134
+ >
135
+ > Vuelve a comprobar `https://api.nan.builders/mcp` periódicamente: si NaN publica herramientas otra
136
+ > vez, este paquete puede restaurar el puente.
110
137
 
111
138
  ### 🛠️ Comando de Gestión: `/nan-mcp`
112
139
 
113
140
  | Comando | Efecto |
114
141
  | :--- | :--- |
115
- | `/nan-mcp status` | Muestra el estado actual de ambos puentes y la resolución de la clave API. |
116
- | `/nan-mcp enable [target]` | Activa `web-search` o `nan-mcp-server` (persiste). |
117
- | `/nan-mcp disable [target]` | Desactiva un puente de forma persistente. |
142
+ | `/nan-mcp status` | Muestra el estado del puente de media y la resolución de la clave API. |
143
+ | `/nan-mcp enable [target]` | Activa `nan-mcp-server` (persiste). |
144
+ | `/nan-mcp disable [target]` | Lo desactiva de forma persistente. |
118
145
 
119
- Ambos puentes resuelven la credencial almacenada de `/login nan` (almacenada → env). Si ninguna se resuelve, el puente no se registra y se muestra un aviso en la salida de estado.
146
+ El puente resuelve la credencial almacenada de `/login nan` (almacenada → env). Si ninguna se resuelve, el servidor no se registra y se muestra un aviso en la salida de estado.
120
147
 
121
148
  > [!NOTE]
122
149
  > El registro ocurre cuando se carga la extensión. Si ejecutas `/login nan` **después** de que la sesión haya empezado, la factoría ya se ejecutó — usa `/reload` (o `/nan-mcp enable`) para registrar los puentes sin reiniciar pi.
@@ -171,15 +198,7 @@ conector con `pi config` → Built-in extensions → `mcp`.
171
198
 
172
199
  ---
173
200
 
174
- ### 1. Servidor MCP oficial de NaN
175
- *Puente oficial para herramientas remotas vía [https://api.nan.builders/mcp](https://nan.builders/docs/api).*
176
-
177
- - **`mcp__nan_search__web_search(query, ...)`**: Realiza búsquedas web a través del gateway de NaN.
178
- > pi 0.99.0–0.99.1 usaba la forma con guiones (`mcp__nan-search__web_search`); pi 0.99.2+ sanitiza
179
- > los nombres de herramientas a solo `[A-Za-z0-9_]`, así que los guiones se convirtieron en
180
- > guiones bajos. La forma con guiones bajos aplica desde 0.99.2 hasta pi 1.0.
181
-
182
- ### 2. Servidor MCP de Media (Comunidad)
201
+ ### Servidor MCP de Media (Comunidad)
183
202
  *Conecta [`nan-mcp-server`](https://github.com/luciferfran/nan-mcp-server) mediante un cliente stdio local mínimo.*
184
203
 
185
204
  - **Por sesión**: El servidor se conecta al registrarse (eager). Aparece en `/mcp` con fuente "extension".
@@ -195,21 +214,20 @@ conector con `pi config` → Built-in extensions → `mcp`.
195
214
  | `mcp__nan_media__list_models` | Listar los ids de modelos que alcanza la key |
196
215
  | `mcp__nan_media__embed_text` | Embeddings de texto (qwen3-embedding) |
197
216
  | `mcp__nan_media__rerank_documents` | Reordenación de documentos (Qwen3-Reranker) |
217
+ | `mcp__nan_media__get_quota` | Cuota de tokens por modelo (usado / tope / restante / reinicio) |
198
218
 
199
- > pi 0.99.0–0.99.1 usaba las formas con guiones (`mcp__nan-search__web_search`,
200
- > `mcp__nan-media__*`); pi 0.99.2+ sanitiza los nombres de herramientas a solo
201
- > `[A-Za-z0-9_]`, así que los guiones se convirtieron en guiones bajos. La forma
202
- > con guiones bajos aplica desde 0.99.2 hasta pi 1.0.
219
+ > pi 0.99.0–0.99.1 usaba la forma con guiones (`mcp__nan-media__*`); pi 0.99.2+ sanitiza los
220
+ > nombres de herramientas a solo `[A-Za-z0-9_]`, así que los guiones se convirtieron en guiones
221
+ > bajos. La forma con guiones bajos aplica desde 0.99.2 hasta pi 1.2.
203
222
 
204
223
  #### 🔧 Configuración del Puente de Media
205
224
 
206
225
  | Variable | Por defecto | Descripción |
207
226
  | :--- | :--- | :--- |
208
227
  | `NAN_MEDIA_MCP` | — | Override por sesión (`0` o `false` para desactivar). |
209
- | `NAN_MEDIA_MCP_VERSION` | `1.1.2` | Versión del servidor fijada (recomendado). |
228
+ | `NAN_MEDIA_MCP_VERSION` | `1.3.0` | Versión del servidor fijada (recomendado). |
210
229
  | `NAN_MEDIA_MCP_COMMAND` | — | Override del comando personalizado. |
211
230
  | `NAN_MEDIA_MCP_TIMEOUT_MS` | `120000` | Timeout por llamada. |
212
- | `NAN_MCP_TOOLS` | — | Override para el puente oficial (`0` para desactivar). |
213
231
 
214
232
  #### 🤖 Detección Automática de Actualizaciones
215
233
 
@@ -330,10 +348,14 @@ Modelos de chat:
330
348
  | :--- | :--- | :--- | :--- | :---: |
331
349
  | `qwen3.6` | 262,144 | 65,536 | texto, imagen | ✅ |
332
350
  | `gemma4` | 262,144 | 32,768 | texto, imagen | ✅ |
333
- | `deepseek-v4-flash` | 1,000,000 | 384,000 | texto, imagen | ✅ |
351
+ | `deepseek-v4-flash` | 1,048,576 | 32,768* | texto, imagen | ✅ |
334
352
  | `mimo-v2.6-flash` | 1,048,576 | 131,072 | texto, imagen | ✅ |
335
- | `glm5.3-flash` | 1,000,000 | 131,072 | texto, imagen | ✅ |
336
- | `qwen3.8-flash` | 262,144 | 131,072 | texto, imagen | ✅ |
353
+ | `glm5.3-flash` | 1,048,576 | 131,072 | texto, imagen | ✅ |
354
+ | `qwen3.8-flash` | 1,048,576 | 131,072 | texto, imagen | ✅ |
355
+
356
+ > Las ventanas de la tabla son las **documentadas** en [los docs de NaN](https://nan.builders/docs/models) (comprobado 2026-10-14), que son la fuente de verdad; models.dev es un espejo que un humano actualiza más tarde y puede ir por detrás. `glm5.3` (tier premium, fuera de la tabla estática) es 1,048,576 / 131,072 con entrada texto+imagen cuando una clave premium lo descubre en vivo.
357
+ >
358
+ > `*` El límite de salida de 32,768 en `deepseek-v4-flash` es el techo de los docs oficiales de NaN para pi (https://nan.builders/docs/pi, "the same set the NaN CLI writes", issue #20, 2026-10-02); models.dev sigue listando 384,000, pero la pasarela rechaza `max_tokens` por encima de ~256k con 403.
337
359
 
338
360
  > [!NOTE]
339
361
  > **Techo práctico con caché de prompt fría (issue #18).** Las ventanas de contexto de la tabla son las ventanas reales de los modelos, pero el borde de api.nan.builders (Cloudflare) aborta las respuestas que superan su Proxy Read Timeout de 120 s. Medido con peticiones frías directas (relleno único, sin caché de prompt; 2026-10-01): 208.036 tokens (~960 KB de cuerpo) respondió en 12,9 s mientras que ~220k y ~286k tokens devolvieron **HTTP 524 `origin_response_timeout`** a los ~126 s; los mismos tamaños con caché cálida responden en ~10 s. El techo práctico para peticiones frías queda por tanto muy por debajo de las ventanas declaradas. Desde 1.0.0 el provider reclasifica un 524 en una petición estimada por encima de 200.000 tokens (`NAN_COLD_CACHE_CEILING_TOKENS`) como desbordamiento de contexto para que pi compacte y reintente en vez de quedarse colgado; un 524 en una petición menor se deja intacto (timeout transitorio genuino).
@@ -363,11 +385,12 @@ El parámetro `reasoning_effort` de NaN controla cuánto piensa el modelo antes
363
385
  | :--- | :--- | :--- |
364
386
  | `glm5.3`, `glm5.3-flash` | `minimal` · `low` · `medium` · `high` · `max` | Completamente controlable — valores más altos permiten al modelo razonar más; `minimal` produce ~38 tokens de razonamiento (issue #16, medido 2026-09-27); `none` NO suprime el razonamiento en glm5.3-flash (13,382 tokens) |
365
387
  | `qwen3.6`, `gemma4` | `none` · `minimal` · `low` · `medium` · `high` · `max` | `none`/`minimal` omiten el razonamiento por completo; otros valores limitan a 2K / 8K / 16K / 32K tokens. `thinking: "off"` envía `reasoning_effort: "none"` automáticamente vía el `thinkingLevelMap` del catálogo — los docs de NaN dicen que sin parámetro estos modelos razonan por defecto (presupuesto de 16,384 tokens), así que `off` debe ser explícito |
366
- | `deepseek-v4-flash` | `none` · `minimal` · `low` · `medium` · `high` · `max` (el catálogo declara ["none"]) | `none` deshabilita el razonamiento de forma fiable (0 tokens de razonamiento, medido 2026-09-27); cualquier otro valor deja 13-14K tokens de razonamiento y causa razonamiento descontrolado (finish_reason:"length" con CERO texto de respuesta) — el catálogo solo declara `none` porque el resto es ruido. `thinking: "off"` ahora envía `reasoning_effort: "none"` automáticamente vía el `thinkingLevelMap` del catálogo |
367
- | `qwen3.8-flash`, `mimo-v2.6-flash` | *(aceptado pero no ajustable)* | El parámetro es aceptado y nunca rechazado, pero el modelo gestiona su propia profundidad de razonamiento — nunca es un error enviar un valor que estos modelos no ajustan |
388
+ | `deepseek-v4-flash` | `none` (el catálogo declara ["none"]) | `none` deshabilita el razonamiento (0 tokens de razonamiento, respuesta completa); cualquier otro valor — incluido `minimal` y omitir el parámetro — lo deja ENCENDIDO (57 / 63 / 109 tokens de razonamiento), así que el catálogo solo declara `none`. Re-sondado en vivo 2026-10-14: los docs de NaN afirman "any value (no effect)", pero gana la medición. `thinking: "off"` envía `reasoning_effort: "none"` automáticamente vía el `thinkingLevelMap` del catálogo — sin él el modelo se descontrola hasta `finish_reason: "length"` sin respuesta (issue #16) |
389
+ | `qwen3.8-flash` | *(aceptado pero no ajustable)* | El parámetro es aceptado y nunca rechazado, pero el modelo gestiona su propia profundidad de razonamiento — nunca es un error enviar un valor que este modelo no ajusta |
390
+ | `mimo-v2.6-flash` | `none` | Los docs lo llamaban "profundidad no ajustable", pero el gateway en vivo (2026-10-14) muestra que `none` da 0 tokens de razonamiento con respuesta completa mientras `low` da 22 y omitirlo 17 — así que `thinking: "off"` envía `reasoning_effort: "none"` vía el `thinkingLevelMap` del catálogo |
368
391
 
369
392
  > [!NOTE]
370
- > `maxTokens` NO limita la fase de razonamiento en los modelos de NaN. La fase de razonamiento corre hasta completarse (o se trunca a ~60,000 caracteres para deepseek-v4-flash) independientemente de `maxTokens` — medido: `max_tokens=512` en deepseek-v4-flash aún consumió 13,376 tokens de completación, todos de razonamiento (26x el techo). Este es un comportamiento del gateway confirmado por el issue #16 (medido 2026-09-27).
393
+ > `maxTokens` NO limita la fase de razonamiento en los modelos de NaN. La fase de razonamiento corre hasta completarse (o se corta en el límite de stream solo-razonamiento de NaN: 45.000 caracteres de razonamiento, o 420 s sin salida visible) independientemente de `maxTokens` — medido: `max_tokens=512` en deepseek-v4-flash aún consumió 13,376 tokens de completación, todos de razonamiento (26x el techo). Este es un comportamiento del gateway confirmado por el issue #16 (medido 2026-09-27).
371
394
 
372
395
  ## 🚀 Desarrollo
373
396
 
@@ -378,4 +401,4 @@ bun test # Ejecutar todos los tests
378
401
  bun run typecheck # Ejecutar typechecking
379
402
  ```
380
403
 
381
- *Las versiones siguen semver estricto. CI publica automáticamente al hacer merge a `main`.*
404
+ *Las versiones siguen semver estricto. CI publica automáticamente al hacer merge a `main`.*
package/README.md CHANGED
@@ -1,11 +1,12 @@
1
1
  # @gtrabanco/pi-nan-provider
2
2
 
3
3
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
4
- [![Version](https://img.shields.io/badge/version-0.11.0-blue)](https://github.com/gtrabanco/pi-nan-provider/releases)
4
+ [![Version](https://img.shields.io/badge/version-1.2.1-blue)](https://github.com/gtrabanco/pi-nan-provider/releases)
5
+ [![Built with NaN](https://nan.builders/badge/built-with-nan-compact.svg)](https://cloud.nan.builders/r/7GK06FX8)
5
6
 
6
- [NaN Builders](https://nan.builders) model provider + native MCP servers for [pi](https://github.com/earendil-works/pi).
7
+ [NaN Builders](https://cloud.nan.builders/r/7GK06FX8) model provider + a native MCP server for [pi](https://github.com/earendil-works/pi).
7
8
 
8
- Registers the `nan` provider via `pi.registerProvider()` using NaN's OpenAI-compatible API (`https://api.nan.builders/v1`), and registers MCP servers via pi's native `pi.registerMcpServer()`.
9
+ Registers the `nan` provider via `pi.registerProvider()` using NaN's OpenAI-compatible API (`https://api.nan.builders/v1`), and registers the community media MCP server via pi's native `pi.registerMcpServer()`.
9
10
 
10
11
  ---
11
12
 
@@ -99,24 +100,50 @@ You can override any model's `compat` per-model in `~/.pi/agent/models.json` (pi
99
100
 
100
101
  Get a key from the [NaN platform](https://cloud.nan.builders/r/7GK06FX8) (user settings → API Keys; referral link).
101
102
 
102
- ## 🔌 Native MCP Servers
103
+ ## 🔌 Native MCP Server
103
104
 
104
- Since [pi 0.99.0 ships a built-in MCP client](https://github.com/earendil-works/pi/blob/main/docs/usage.md), this package migrates its bridges to native MCP (requires `pi >=0.99, <2` — pi 0.99 through 1.0 are supported; the peer range was widened to `<2` in 0.11.0).
105
+ Since [pi 0.99.0 ships a built-in MCP client](https://github.com/earendil-works/pi/blob/main/docs/usage.md), this package bridges to native MCP (requires `pi >=0.99, <2` — pi 0.99 through 1.2 are supported; the peer range was widened to `<2` in 0.11.0).
105
106
 
106
- Both bridges are **enabled by default** (session-scoped, visible in `/mcp`). Use `/nan-mcp` to manage them.
107
+ The media bridge is **enabled by default** (session-scoped, visible in `/mcp`). Use `/nan-mcp` to manage it.
107
108
 
108
- > [!TIP]
109
- > Prefer to configure NaN's MCP servers yourself? Since pi 0.99.2/1.0 an HTTP MCP server in the global `mcp.json` can authenticate with your `/login nan` token instead of a copied key: `{ "auth": { "provider": "nan" } }` (global `mcp.json` only; `https` required). The bundled `nan-search` registration keeps using `NAN_API_KEY`/the stored credential.
109
+ > [!WARNING]
110
+ > **NaN's official remote MCP server no longer exposes any tool.** Until 1.2.0 this package shipped a
111
+ > `nan-search` bridge pointing at `https://api.nan.builders/mcp`, which exposed
112
+ > `web_search`. That server now answers `initialize` with an empty `capabilities.tools` and
113
+ > `tools/list` with `{"tools":[]}` — verified with a valid key on 2026-10-15 — and NaN removed every
114
+ > MCP mention from its documentation (the old `/docs/mcp` page now redirects to `/docs/agent-setup`).
115
+ > The bridge was removed in **1.2.1** because registering a server that exposes nothing only produces
116
+ > a tool-less server in `/mcp`.
117
+ >
118
+ > **Bring your own `web_search` and fetch.** Install an MCP server that provides them (e.g. the
119
+ > `fetch` + `brave-search` pair for the official MCP servers, or any other search/fetch MCP server)
120
+ > and declare it in your global `mcp.json`:
121
+ >
122
+ > ```json
123
+ > {
124
+ > "mcpServers": {
125
+ > "fetch": { "command": "uvx", "args": ["mcp-server-fetch"] },
126
+ > "web-search": {
127
+ > "command": "npx",
128
+ > "args": ["-y", "@modelcontextprotocol/server-brave-search"],
129
+ > "env": { "BRAVE_API_KEY": "your-key" }
130
+ > }
131
+ > }
132
+ > }
133
+ > ```
134
+ >
135
+ > Re-check `https://api.nan.builders/mcp` periodically: if NaN publishes tools again, this package can
136
+ > restore the bridge.
110
137
 
111
138
  ### 🛠️ Management Command: `/nan-mcp`
112
139
 
113
140
  | Command | Effect |
114
141
  | :--- | :--- |
115
- | `/nan-mcp status` | Shows current state of both bridges and API key resolution. |
116
- | `/nan-mcp enable [target]` | Enables `web-search` or `nan-mcp-server` (persisted). |
117
- | `/nan-mcp disable [target]` | Disables a bridge persistently. |
142
+ | `/nan-mcp status` | Shows the media bridge state and API key resolution. |
143
+ | `/nan-mcp enable [target]` | Enables `nan-mcp-server` (persisted). |
144
+ | `/nan-mcp disable [target]` | Disables it persistently. |
118
145
 
119
- Both bridges resolve the stored `/login nan` credential (stored → env). If neither resolves, the bridge does not register and a warning is shown in the status output.
146
+ The bridge resolves the stored `/login nan` credential (stored → env). If neither resolves, the server does not register and a warning is shown in the status output.
120
147
 
121
148
  > [!NOTE]
122
149
  > Registration happens when the extension loads. If you run `/login nan` **after** the session started, the factory has already run — run `/reload` (or `/nan-mcp enable`) to register the bridges without restarting pi.
@@ -168,15 +195,7 @@ registering a server that can never connect. To get MCP in the CLI, enable the c
168
195
 
169
196
  ---
170
197
 
171
- ### 1. Official NaN MCP Server
172
- *Official remote MCP server registered natively via `pi.registerMcpServer()`.*
173
-
174
- - **`mcp__nan_search__web_search(query, ...)`**: Performs web searches through NaN's gateway.
175
- > pi 0.99.0–0.99.1 used the hyphenated form (`mcp__nan-search__web_search`); pi 0.99.2+ sanitizes
176
- > tool names to `[A-Za-z0-9_]` only, so hyphens became underscores. The underscore form applies
177
- > from 0.99.2 onward through pi 1.0.
178
-
179
- ### 2. Community Media MCP Server
198
+ ### Community Media MCP Server
180
199
  *Bridges [`nan-mcp-server`](https://github.com/luciferfran/nan-mcp-server) via a minimal local stdio client.*
181
200
 
182
201
  - **Session-scoped**: The server connects at registration time (eager). Appears in `/mcp` with source "extension".
@@ -192,21 +211,20 @@ registering a server that can never connect. To get MCP in the CLI, enable the c
192
211
  | `mcp__nan_media__list_models` | List the NaN model ids the key can reach |
193
212
  | `mcp__nan_media__embed_text` | Text embeddings (qwen3-embedding) |
194
213
  | `mcp__nan_media__rerank_documents` | Document reranking (Qwen3-Reranker) |
214
+ | `mcp__nan_media__get_quota` | Per-model token quota (used / cap / remaining / reset) |
195
215
 
196
- > pi 0.99.0–0.99.1 used the hyphenated forms (`mcp__nan-search__web_search`,
197
- > `mcp__nan-media__*`); pi 0.99.2+ sanitizes tool names to `[A-Za-z0-9_]` only,
198
- > so hyphens became underscores. The underscore form applies from 0.99.2 onward
199
- > through pi 1.0.
216
+ > pi 0.99.0–0.99.1 used the hyphenated form (`mcp__nan-media__*`); pi 0.99.2+ sanitizes tool
217
+ > names to `[A-Za-z0-9_]` only, so hyphens became underscores. The underscore form applies from
218
+ > 0.99.2 onward through pi 1.2.
200
219
 
201
220
  #### 🔧 Media Bridge Configuration
202
221
 
203
222
  | Variable | Default | Description |
204
223
  | :--- | :--- | :--- |
205
224
  | `NAN_MEDIA_MCP` | — | Per-session override (`0` or `false` to disable). |
206
- | `NAN_MEDIA_MCP_VERSION` | `1.1.2` | Pinned server version (recommended). |
225
+ | `NAN_MEDIA_MCP_VERSION` | `1.3.0` | Pinned server version (recommended). |
207
226
  | `NAN_MEDIA_MCP_COMMAND` | — | Custom command override. |
208
227
  | `NAN_MEDIA_MCP_TIMEOUT_MS` | `120000` | Per-call timeout. |
209
- | `NAN_MCP_TOOLS` | — | Override for the official bridge (`0` to disable). |
210
228
 
211
229
  #### 🤖 Automated Update Detection
212
230
 
@@ -327,12 +345,14 @@ Chat models:
327
345
  | :--- | :--- | :--- | :--- | :---: |
328
346
  | `qwen3.6` | 262,144 | 65,536 | text, image | ✅ |
329
347
  | `gemma4` | 262,144 | 32,768 | text, image | ✅ |
330
- | `deepseek-v4-flash` | 1,000,000 | 32,768* | text, image | ✅ |
348
+ | `deepseek-v4-flash` | 1,048,576 | 32,768* | text, image | ✅ |
331
349
  | `mimo-v2.6-flash` | 1,048,576 | 131,072 | text, image | ✅ |
332
- | `glm5.3-flash` | 1,000,000 | 131,072 | text, image | ✅ |
333
- | `qwen3.8-flash` | 262,144 | 131,072 | text, image | ✅ |
350
+ | `glm5.3-flash` | 1,048,576 | 131,072 | text, image | ✅ |
351
+ | `qwen3.8-flash` | 1,048,576 | 131,072 | text, image | ✅ |
334
352
 
335
353
  > [!NOTE]
354
+ > Context windows above are the **documented** windows from [the NaN docs](https://nan.builders/docs/models) (checked 2026-10-14), which are the source of truth; models.dev is a downstream mirror a human updates later and may lag. `glm5.3` (premium tier, not in the static table above) is 1,048,576 / 131,072 with text+image input when a premium key discovers it live.
355
+ >
336
356
  > `*` deepseek-v4-flash max output 32,768 is the ceiling from the official NaN pi docs (https://nan.builders/docs/pi, "the same set the NaN CLI writes", issue #20, 2026-10-02); models.dev still lists 384,000 but the gateway rejects `max_tokens` above ~256k with 403.
337
357
  >
338
358
  > **Cold prompt cache practical ceiling (issue #18).** The context windows above are the models' real windows, but the api.nan.builders edge (Cloudflare) aborts responses past its 120 s Proxy Read Timeout. Measured with direct cold requests (unique filler, no prompt cache; 2026-10-01): 208,036 tokens (~960 KB body) answered in 12.9 s while ~220k and ~286k tokens returned **HTTP 524 `origin_response_timeout`** at ~126 s; the same sizes with a warm prompt cache answer in ~10 s. The practical ceiling for cold requests is therefore well below the declared windows. Since 1.0.0 the provider reclassifies a 524 on an estimated over-200,000-token request (`NAN_COLD_CACHE_CEILING_TOKENS`) as a context overflow so pi compacts and retries instead of wedging; a 524 on a smaller request is left alone (genuine transient timeout).
@@ -360,10 +380,11 @@ NaN's `reasoning_effort` parameter controls how much the model thinks before ans
360
380
  | :--- | :--- | :--- |
361
381
  | `glm5.3`, `glm5.3-flash` | `minimal` · `low` · `medium` · `high` · `max` | Fully controllable — higher values let the model reason longer; `minimal` yields ~38 reasoning tokens (issue #16, measured 2026-09-27); `none` does NOT suppress reasoning on glm5.3-flash (13,382 tokens) |
362
382
  | `qwen3.6`, `gemma4` | `none` · `minimal` · `low` · `medium` · `high` · `max` | `none`/`minimal` skip reasoning entirely; others cap at 2K / 8K / 16K / 32K tokens. `thinking: "off"` sends `reasoning_effort: "none"` automatically via the catalog's `thinkingLevelMap` — the NaN docs state that with no parameter these models reason by default (16,384-token budget), so off must be explicit |
363
- | `deepseek-v4-flash` | `none` · `minimal` · `low` · `medium` · `high` · `max` (catalog declares ["none"]) | `none` reliably disables reasoning (0 reasoning tokens, measured 2026-09-27); every other value leaves 13-14K reasoning tokens and causes runaway reasoning (finish_reason:"length" with ZERO answer text) — the catalog only declares `none` because the rest are useless. `thinking: "off"` now sends `reasoning_effort: "none"` automatically via the catalog's `thinkingLevelMap` |
364
- | `qwen3.8-flash`, `mimo-v2.6-flash` | *(accepted but not adjustable)* | The parameter is accepted and never rejected, but the model manages its own reasoning depth — it is never an error to send a value these models don't adjust |
383
+ | `deepseek-v4-flash` | `none` (catalog declares ["none"]) | `none` disables reasoning (0 reasoning tokens, a full answer); every other value — including `minimal` and omitting the parameter — leaves it ON (57 / 63 / 109 reasoning tokens), so the catalog declares only `none`. Re-probed live 2026-10-14: the NaN docs claim "any value (no effect)", but the measurement wins. `thinking: "off"` sends `reasoning_effort: "none"` automatically via the catalog's `thinkingLevelMap` — without it the model runs away to `finish_reason: "length"` with no answer (issue #16) |
384
+ | `qwen3.8-flash` | *(accepted but not adjustable)* | The parameter is accepted and never rejected, but the model manages its own reasoning depth — it is never an error to send a value this model doesn't adjust |
385
+ | `mimo-v2.6-flash` | `none` | The docs called this "depth not adjustable", but the live gateway (2026-10-14) shows `none` gives 0 reasoning tokens with a full answer while `low` gives 22 and omitting the parameter 17 — so `thinking: "off"` sends `reasoning_effort: "none"` via the catalog's `thinkingLevelMap` |
365
386
  > [!NOTE]
366
- > `maxTokens` does NOT bound the reasoning phase on NaN models. The reasoning phase runs to completion (or truncates at ~60,000 chars for deepseek-v4-flash) regardless of `maxTokens` — measured: `max_tokens=512` on deepseek-v4-flash still consumed 13,376 completion tokens, all reasoning (26x the ceiling). This is gateway behavior confirmed by issue #16 (measured 2026-09-27).
387
+ > `maxTokens` does NOT bound the reasoning phase on NaN models. The reasoning phase runs to completion (or is cut at NaN's reasoning-only stream limit: 45,000 reasoning characters, or 420 s without visible output) regardless of `maxTokens` — measured: `max_tokens=512` on deepseek-v4-flash still consumed 13,376 completion tokens, all reasoning (26x the ceiling). This is gateway behavior confirmed by issue #16 (measured 2026-09-27).
367
388
 
368
389
 
369
390
  ---
@@ -377,4 +398,4 @@ bun test # Run all tests
377
398
  bun run typecheck # Run typechecking
378
399
  ```
379
400
 
380
- *Releases follow strict semver. CI publishes automatically on merge to `main`.*
401
+ *Releases follow strict semver. CI publishes automatically on merge to `main`.*
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@gtrabanco/pi-nan-provider",
3
- "version": "1.0.1",
4
- "description": "NaN Builders (api.nan.builders) model provider for pi - OpenAI-compatible registration with a models.dev-generated fallback, tier-aware live catalog, and MCP bridges (official web search + optional community media server)",
3
+ "version": "1.2.1",
4
+ "description": "NaN Builders (api.nan.builders) model provider for pi - OpenAI-compatible registration with a models.dev-generated fallback, tier-aware live catalog, and an optional community media MCP bridge",
5
5
  "keywords": [
6
6
  "pi",
7
7
  "pi-package",
@@ -46,8 +46,8 @@
46
46
  "@earendil-works/pi-coding-agent": ">=0.99.0 <2"
47
47
  },
48
48
  "devDependencies": {
49
- "@earendil-works/pi-ai": "1.0.0",
50
- "@earendil-works/pi-coding-agent": "1.0.0",
49
+ "@earendil-works/pi-ai": "1.2.0",
50
+ "@earendil-works/pi-coding-agent": "1.2.0",
51
51
  "@types/bun": "1.4",
52
52
  "typescript": "7"
53
53
  },
@@ -318,7 +318,7 @@ export function renderIssueBody(report: NanMcpServerCheckReport): string {
318
318
  }
319
319
  lines.push("### To bump");
320
320
  lines.push(
321
- `1. Edit \`DEFAULT_NAN_MEDIA_MCP_VERSION\` in \`src/mcp/nan-media.ts\` from \`${report.pinnedVersion}\` to \`${report.latestVersion}\`.`,
321
+ `1. Edit \`DEFAULT_NAN_MEDIA_MCP_VERSION\` in \`src/mcp/media-server.ts\` from \`${report.pinnedVersion}\` to \`${report.latestVersion}\`.`,
322
322
  );
323
323
  lines.push("2. Run \`bun test && bun run typecheck\`.");
324
324
  lines.push(
@@ -79,12 +79,10 @@ const PI_SUPPORTED_INPUT = new Set(["text", "image"]);
79
79
  * (shared with test/generated-catalog.test.ts, which pins that every
80
80
  * override lands on the generated entry with its provenance note).
81
81
  * Capability divergences from models.dev are recorded there, never here.
82
- * MANUAL_NOTES adds provenance-only notes to otherwise-untouched entries.
82
+ * MANUAL_NOTES adds provenance-only notes to otherwise-untouched entries
83
+ * (currently empty; per-model corrections live in MANUAL_OVERRIDES).
83
84
  */
84
- const MANUAL_NOTES: Record<string, string> = {
85
- "qwen3.8-flash":
86
- "contextWindow 262,144: the earlier 1,000,000 override (maintainer-confirmed 2026-09-05) was withdrawn 2026-09-07 — the updated https://nan.builders/docs/models still states '262K token context, the model's native window' and models.dev agrees at 262,144; NaN docs are treated as the most reliable source (maintainer instruction, 2026-09-07).",
87
- };
85
+ const MANUAL_NOTES: Record<string, string> = {};
88
86
 
89
87
  /**
90
88
  * Models the provider has removed but that models.dev may still list.