nexus-ai-pro 2.21.0 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (179) hide show
  1. package/API_STABILITY.md +98 -2
  2. package/CHANGELOG.md +165 -1
  3. package/MIGRATING.md +151 -17
  4. package/README.md +15 -7
  5. package/SECURITY.md +16 -2
  6. package/dist/agent/openapi.d.ts +88 -13
  7. package/dist/agent/openapi.js +527 -32
  8. package/dist/cli/migrate.d.ts +5 -4
  9. package/dist/cli/migrate.js +18 -1
  10. package/dist/core/defaults.d.ts +12 -12
  11. package/dist/core/defaults.js +2 -2
  12. package/dist/core/secure-stream.js +4 -1
  13. package/dist/decisions/completion.js +2 -2
  14. package/dist/decisions/typesafe.d.ts +11 -3
  15. package/dist/decisions/typesafe.js +28 -9
  16. package/dist/doctor/index.js +1 -1
  17. package/dist/embeddings/adapters.d.ts +1 -1
  18. package/dist/embeddings/adapters.js +3 -3
  19. package/dist/embeddings/batch-google.d.ts +27 -8
  20. package/dist/embeddings/batch-google.js +112 -36
  21. package/dist/embeddings/batch-mock.js +1 -1
  22. package/dist/embeddings/batch.js +10 -4
  23. package/dist/embeddings/engine.js +14 -13
  24. package/dist/embeddings/index.d.ts +1 -1
  25. package/dist/embeddings/inputs.d.ts +26 -3
  26. package/dist/embeddings/inputs.js +84 -5
  27. package/dist/embeddings/mock.js +1 -1
  28. package/dist/embeddings/models.js +39 -4
  29. package/dist/graph/checkpoint-migration.d.ts +0 -6
  30. package/dist/graph/index.d.ts +1 -1
  31. package/dist/loaders/csv.d.ts +23 -1
  32. package/dist/loaders/csv.js +125 -72
  33. package/dist/loaders/index.d.ts +7 -2
  34. package/dist/loaders/input.d.ts +6 -0
  35. package/dist/loaders/input.js +42 -1
  36. package/dist/loaders/json.d.ts +14 -3
  37. package/dist/loaders/json.js +171 -20
  38. package/dist/loaders/web.d.ts +55 -0
  39. package/dist/loaders/web.js +20 -1
  40. package/dist/mcp/client.d.ts +54 -5
  41. package/dist/mcp/client.js +171 -20
  42. package/dist/mcp/http.d.ts +45 -0
  43. package/dist/mcp/http.js +233 -0
  44. package/dist/mcp/index.d.ts +4 -2
  45. package/dist/mcp/index.js +3 -1
  46. package/dist/mcp/protocol.d.ts +107 -0
  47. package/dist/mcp/sampling.d.ts +41 -0
  48. package/dist/mcp/sampling.js +52 -0
  49. package/dist/mcp/server.d.ts +96 -14
  50. package/dist/mcp/server.js +274 -59
  51. package/dist/models/data.js +20 -1
  52. package/dist/operations/adapters.d.ts +6 -5
  53. package/dist/protocols/a2a-grpc.js +10 -3
  54. package/dist/protocols/a2a-signing.d.ts +65 -0
  55. package/dist/protocols/a2a-signing.js +133 -0
  56. package/dist/protocols/a2a.d.ts +14 -0
  57. package/dist/protocols/a2a.js +44 -8
  58. package/dist/providers/cohere.js +16 -2
  59. package/dist/providers/google.js +7 -1
  60. package/dist/providers/ollama.d.ts +1 -1
  61. package/dist/providers/ollama.js +35 -27
  62. package/dist/providers/openai.js +6 -2
  63. package/dist/rag/pinecone.d.ts +63 -2
  64. package/dist/rag/pinecone.js +80 -0
  65. package/dist/realtime/conversation.js +18 -0
  66. package/dist/realtime/gemini-live.transport.d.ts +28 -3
  67. package/dist/realtime/gemini-live.transport.js +170 -32
  68. package/dist/realtime/session.d.ts +2 -0
  69. package/dist/realtime/session.js +19 -4
  70. package/dist/realtime/types.d.ts +35 -3
  71. package/dist/security/output-guard.js +4 -1
  72. package/dist/server/auth.d.ts +263 -2
  73. package/dist/server/auth.js +432 -5
  74. package/dist/server/deployments.d.ts +2 -2
  75. package/dist/telephony/index.d.ts +1 -1
  76. package/dist/telephony/manager.d.ts +8 -1
  77. package/dist/telephony/manager.js +13 -0
  78. package/dist/telephony/providers/telnyx.d.ts +18 -5
  79. package/dist/telephony/providers/telnyx.js +44 -7
  80. package/dist/telephony/providers/twilio.d.ts +3 -1
  81. package/dist/telephony/providers/twilio.js +16 -0
  82. package/dist/tracing/tracer.d.ts +2 -2
  83. package/dist/types/embeddings.d.ts +47 -5
  84. package/dist/types/messages.d.ts +7 -0
  85. package/dist/types/principal.d.ts +1 -1
  86. package/dist/types/response.d.ts +5 -0
  87. package/dist/types/telephony.d.ts +38 -0
  88. package/dist/version.d.ts +1 -1
  89. package/dist/version.js +1 -1
  90. package/dist/voice/providers/google.d.ts +44 -0
  91. package/dist/voice/providers/google.js +215 -0
  92. package/dist-cjs/agent/openapi.d.ts +88 -13
  93. package/dist-cjs/agent/openapi.js +529 -32
  94. package/dist-cjs/cli/migrate.d.ts +5 -4
  95. package/dist-cjs/cli/migrate.js +18 -1
  96. package/dist-cjs/core/defaults.d.ts +12 -12
  97. package/dist-cjs/core/defaults.js +2 -2
  98. package/dist-cjs/core/secure-stream.js +4 -1
  99. package/dist-cjs/decisions/completion.js +2 -2
  100. package/dist-cjs/decisions/typesafe.d.ts +11 -3
  101. package/dist-cjs/decisions/typesafe.js +28 -9
  102. package/dist-cjs/doctor/index.js +1 -1
  103. package/dist-cjs/embeddings/adapters.d.ts +1 -1
  104. package/dist-cjs/embeddings/adapters.js +3 -3
  105. package/dist-cjs/embeddings/batch-google.d.ts +27 -8
  106. package/dist-cjs/embeddings/batch-google.js +112 -36
  107. package/dist-cjs/embeddings/batch-mock.js +1 -1
  108. package/dist-cjs/embeddings/batch.js +9 -3
  109. package/dist-cjs/embeddings/engine.js +13 -12
  110. package/dist-cjs/embeddings/index.d.ts +1 -1
  111. package/dist-cjs/embeddings/inputs.d.ts +26 -3
  112. package/dist-cjs/embeddings/inputs.js +89 -5
  113. package/dist-cjs/embeddings/mock.js +1 -1
  114. package/dist-cjs/embeddings/models.js +39 -4
  115. package/dist-cjs/graph/checkpoint-migration.d.ts +0 -6
  116. package/dist-cjs/graph/index.d.ts +1 -1
  117. package/dist-cjs/loaders/csv.d.ts +23 -1
  118. package/dist-cjs/loaders/csv.js +126 -71
  119. package/dist-cjs/loaders/index.d.ts +7 -2
  120. package/dist-cjs/loaders/input.d.ts +6 -0
  121. package/dist-cjs/loaders/input.js +43 -1
  122. package/dist-cjs/loaders/json.d.ts +14 -3
  123. package/dist-cjs/loaders/json.js +170 -19
  124. package/dist-cjs/loaders/web.d.ts +55 -0
  125. package/dist-cjs/loaders/web.js +21 -1
  126. package/dist-cjs/mcp/client.d.ts +54 -5
  127. package/dist-cjs/mcp/client.js +171 -20
  128. package/dist-cjs/mcp/http.d.ts +45 -0
  129. package/dist-cjs/mcp/http.js +236 -0
  130. package/dist-cjs/mcp/index.d.ts +4 -2
  131. package/dist-cjs/mcp/index.js +5 -1
  132. package/dist-cjs/mcp/protocol.d.ts +107 -0
  133. package/dist-cjs/mcp/sampling.d.ts +41 -0
  134. package/dist-cjs/mcp/sampling.js +55 -0
  135. package/dist-cjs/mcp/server.d.ts +96 -14
  136. package/dist-cjs/mcp/server.js +273 -58
  137. package/dist-cjs/models/data.js +20 -1
  138. package/dist-cjs/operations/adapters.d.ts +6 -5
  139. package/dist-cjs/protocols/a2a-grpc.js +10 -3
  140. package/dist-cjs/protocols/a2a-signing.d.ts +65 -0
  141. package/dist-cjs/protocols/a2a-signing.js +140 -0
  142. package/dist-cjs/protocols/a2a.d.ts +14 -0
  143. package/dist-cjs/protocols/a2a.js +49 -9
  144. package/dist-cjs/providers/cohere.js +16 -2
  145. package/dist-cjs/providers/google.js +7 -1
  146. package/dist-cjs/providers/ollama.d.ts +1 -1
  147. package/dist-cjs/providers/ollama.js +35 -27
  148. package/dist-cjs/providers/openai.js +6 -2
  149. package/dist-cjs/rag/pinecone.d.ts +63 -2
  150. package/dist-cjs/rag/pinecone.js +81 -0
  151. package/dist-cjs/realtime/conversation.js +18 -0
  152. package/dist-cjs/realtime/gemini-live.transport.d.ts +28 -3
  153. package/dist-cjs/realtime/gemini-live.transport.js +170 -32
  154. package/dist-cjs/realtime/session.d.ts +2 -0
  155. package/dist-cjs/realtime/session.js +19 -4
  156. package/dist-cjs/realtime/types.d.ts +35 -3
  157. package/dist-cjs/security/output-guard.js +4 -1
  158. package/dist-cjs/server/auth.d.ts +263 -2
  159. package/dist-cjs/server/auth.js +437 -5
  160. package/dist-cjs/server/deployments.d.ts +2 -2
  161. package/dist-cjs/telephony/index.d.ts +1 -1
  162. package/dist-cjs/telephony/manager.d.ts +8 -1
  163. package/dist-cjs/telephony/manager.js +13 -0
  164. package/dist-cjs/telephony/providers/telnyx.d.ts +18 -5
  165. package/dist-cjs/telephony/providers/telnyx.js +44 -7
  166. package/dist-cjs/telephony/providers/twilio.d.ts +3 -1
  167. package/dist-cjs/telephony/providers/twilio.js +16 -0
  168. package/dist-cjs/tracing/tracer.d.ts +2 -2
  169. package/dist-cjs/types/embeddings.d.ts +47 -5
  170. package/dist-cjs/types/messages.d.ts +7 -0
  171. package/dist-cjs/types/principal.d.ts +1 -1
  172. package/dist-cjs/types/response.d.ts +5 -0
  173. package/dist-cjs/types/telephony.d.ts +38 -0
  174. package/dist-cjs/version.d.ts +1 -1
  175. package/dist-cjs/version.js +1 -1
  176. package/dist-cjs/voice/providers/google.d.ts +44 -0
  177. package/dist-cjs/voice/providers/google.js +252 -0
  178. package/llms.txt +1 -1
  179. package/package.json +18 -1
package/API_STABILITY.md CHANGED
@@ -1,7 +1,7 @@
1
1
  # API Stability Policy
2
2
 
3
- This policy describes compatibility guarantees for `nexus-ai-pro`. The 2.x guarantees apply beginning
4
- with version 2.0.0, as the 1.x guarantees applied from 1.0.0. The sections for the 1.x stages below
3
+ This policy describes compatibility guarantees for `nexus-ai-pro`. The 3.x guarantees apply beginning
4
+ with version 3.0.0, as the 2.x guarantees applied from 2.0.0 and the 1.x guarantees from 1.0.0. The sections for the 1.x stages below
5
5
  still describe each surface; where they say "the 1.x rules", read the rules of the current major line.
6
6
 
7
7
  ## Release stages
@@ -67,6 +67,102 @@ graduation:
67
67
  | Upgrade | A migration test from the previous minor |
68
68
  | Soak | A long-running test with flat memory and no leaked handles |
69
69
 
70
+ ## 3.0 stage (3.0.0)
71
+
72
+ 3.0 is a major release. It turns on the three defaults 2.21 previewed — incremental tracing on a
73
+ durable trace store, the Redis operation store's dispatch index, and `hash-v2` for a deployment first
74
+ recorded — and removes `OpenApiTools.skipped` and `GraphCheckpointV2`, both deprecated in 2.x. Nothing
75
+ stored changes: checkpoints of version 1 and 2, the state store's keys, operation records, and recorded
76
+ deployments read as they did, and the state store's keys are read by every later 3.x.
77
+ `useDefaults('2.x')` and `NEXUS_DEFAULTS=2.x` keep 2.x's three defaults through 3.x.
78
+ [MIGRATING.md](./MIGRATING.md) covers each change. The rollout is proven against the published 2.21.0
79
+ package, in `tests/upgrade-3.test.ts`: a 2.21 worker and a 3.0 worker share a Redis prefix, each
80
+ claiming what it should and 3.0 finding the rest after one `reindex()`, and 2.21 and 3.0 replicas
81
+ place every thread alike, whichever records a deployment first.
82
+
83
+ Removed: `OpenApiTools.skipped`, always empty since 2.22, and `GraphCheckpointV2`, for `GraphCheckpoint`.
84
+ Everything else 3.0 adds is stable from the start and additive, unless this section says otherwise.
85
+
86
+ ### Graduation
87
+
88
+ The studio's sign-in leaves experimental status: `oidcSignIn()`, `OidcSignInOptions`,
89
+ `SIGN_IN_COOKIE`, and the `/auth/login`, `/auth/callback`, and `/auth/logout` routes.
90
+
91
+ | Requirement | Evidence |
92
+ | --- | --- |
93
+ | API stability | Covered by the compatibility rules, with no planned breaking change |
94
+ | Conformance | Signs a person in through Dex v2.46.0, run in a container on every build, where a wrong password is kept and a reused code refused: `studio/test/signin-dex.test.ts`; every way a callback can be wrong, a token for another client among them, against a provider written from the specification: `studio/test/signin.test.ts` |
95
+ | Crash recovery | n/a: it keeps nothing; a session is a signed cookie, and a sign-in in progress is one the person carries |
96
+ | Concurrency | A sign-in begun on one replica finishes on another, and every replica sharing the secret reads the session: `studio/test/signin.test.ts` |
97
+ | Load | 500 reads on a sign-in session cost at most twice the same reads on a personal token: `studio/test/signin.test.ts` |
98
+ | Tenant isolation | A tenant from a claim reads only that tenant's sources, comments, and audit entries: `studio/test/signin.test.ts`, `studio/test/tenants.test.ts` |
99
+ | Security | [Review](./SECURITY.md#the-studio-and-its-accounts), reviewed for 2.22, its findings closed |
100
+ | Upgrade | A session sealed by 2.22.0 is read: `studio/test/signin.test.ts` |
101
+ | Soak | 1,000 sign-ins and their reads with flat memory: `studio/test/signin.test.ts` |
102
+
103
+ ## 2.22 stage (2.22.0)
104
+
105
+ Everything 2.22 adds is stable from the start and additive, unless this section says otherwise.
106
+
107
+ New and stable: `StreamChunk.logprobs`; in `nexus-ai-pro/protocols/a2a`, `signA2aCard()`,
108
+ `verifyA2aCard()`, `canonicalA2aCard()`, `A2aCardSignatureError`, `A2aCardSigner`, `A2aCardKeyResolver`,
109
+ `A2aSignatureAlgorithm`, `A2aJsonWebKey`, `A2aCryptoKey`, `A2aServerOptions.sign`, and
110
+ `A2aClientOptions.verifyCard`, which `A2aGrpcClientOptions` takes too; in `nexus-ai-pro/mcp`,
111
+ `mcpHttpHandler()`, `McpHttpOptions`, `McpHttpHandler`, `samplingFrom()`, `McpSamplingOptions`,
112
+ `McpSamplingClient`, `McpServerPrompt`, `McpPromptArgument`, `McpPromptMessage`, `McpServerResource`,
113
+ the server's `registerPrompt()`, `registerResource()`, `resourceUpdated()`, `createMessage()`,
114
+ `elicit()`, `listRoots()`, and `onRootsChanged()`, the client's `sampling`, `elicitation`, and `roots`
115
+ options, `onPromptsChanged()`, `onResourcesChanged()`, `onResourceUpdated()`, `subscribeResource()`,
116
+ `unsubscribeResource()`, and `rootsChanged()`, `HttpClientOptions.listen`, the protocol types
117
+ `McpSamplingRequest`, `McpSamplingResult`, `McpSamplingMessage`, `McpSamplingContent`,
118
+ `McpModelPreferences`, `McpElicitationRequest`, `McpElicitationResult`, `McpRoot`, and
119
+ `McpCallerRequests`, and `ToolContext.mcp`; in `nexus-ai-pro/agent/openapi`, `swaggerToOpenApi()`,
120
+ `bundleOpenApiDocument()`, `OpenApiBundleOptions`, `OpenApiCredential`, `OpenApiWebhook`,
121
+ `OpenApiToolsOptions.credentials`, `OpenApiOperation.security`, `OpenApiTools.webhooks`, and
122
+ `loadOpenApiTools()`'s `references`, `maxDocuments`, and `maxBytes`; in `nexus-ai-pro/server/auth`,
123
+ `createJwtSigner()`, `JwtSigner`, `JwtSignerOptions`, `JwtSignOptions`, `generateJwtKey()`,
124
+ `jwksHandler()`, `createApiKeyStore()`, `ApiKeyStore`, `ApiKeyStoreOptions`, `ApiKeyRecord`,
125
+ `IssuedApiKey`, `ApiKeyIssueOptions`, `createSessions()`, `Sessions`, `SessionOptions`,
126
+ `SessionCookieOptions`, `SessionRecord`, and `StartedSession`, and the principal method `session`; in
127
+ `nexus-ai-pro/rag/pinecone`, `PineconeVectorStore.create()`, `ensurePineconeIndex()`,
128
+ `PineconeIndexOptions`, `PineconeIndex`, and `PineconeCreateOptions`, experimental with the store;
129
+ `TypeSafeDecisionProviderOptions.pictures`; and in `nexus-ai-pro/embeddings`, `EmbeddingVideoPart`, the
130
+ modality `video`, `EmbeddingMeta.unpricedMedia`, and `EmbeddingModelCapabilities`'
131
+ `costPerAudioSecond`, `costPerVideoFrame`, `videoFrames`, `maxAudioSeconds`, and `maxVideoSeconds`; in
132
+ the loaders, `FileInput`'s stream form, `CsvRowParser`, `JsonLoaderOptions.recordsAt`,
133
+ `WebLoaderOptions.render` and `renderBelow`, `browserRenderer()`, `WebPageRenderer`, `WebPageToRender`,
134
+ `RenderingBrowser`, and `BrowserRendererOptions`; in the realtime family, `ImageItem`, the `message.image`
135
+ event, and `RealtimeConversationOptions.recordImages`; in telephony, `TelephonyGatherResult`,
136
+ `EndGatherRequest`, `parseGatherResult()` and `endGather()` on the manager and the providers, and
137
+ `TelnyxTelephonyProviderConfig.transcriptionEngine`; in the studio, `StudioOptions.tenantSources`,
138
+ `StudioUser.tenant`, `StudioAuditEntry.tenant`, `StudioComment.tenant`, `StudioAuditQuery`,
139
+ `HeaderAuthOptions.tenant`, `BearerAuthOptions.tenant`, `StudioSignIn`, and `StudioOptions.signIn`.
140
+ Experimental: in the studio, `oidcSignIn()`, `OidcSignInOptions`, `SIGN_IN_COOKIE`, and the
141
+ `/auth/` routes, until a sign-in against a live provider is recorded; `nexus-ai-pro/voice/google`,
142
+ `GoogleVoiceProvider` and `GoogleVoiceProviderConfig`, until a live run is recorded.
143
+ The state store keys and sessions are kept in, under `nexus/server`, is read by every later 2.x.
144
+
145
+ Changed on purpose: an answer the output guard changes or blocks keeps no `logprobs`, streamed or
146
+ not; a typed decision of a model that reports the chosen token alone is sampled; an Ollama stream
147
+ honours `stop`. An MCP server declares prompts and resource subscriptions at `initialize` whatever it
148
+ was given, and serves every transport connected to it rather than the last; a tool it runs gets a
149
+ `signal` and `mcp` in its context. The HTTP client transport returns from `send()` before a streamed
150
+ answer ends, sends `mcp-protocol-version`, and sends a `DELETE` when closed with a session. OpenAPI
151
+ tools are made of operations with any request body, where those with a body other than JSON or a form
152
+ were skipped, and of Swagger 2.0 documents, which were refused; `loadOpenApiTools()` reads no more of
153
+ a document than `maxBytes`. With `credentials` given, an operation whose security cannot be met fails
154
+ before it is sent.
155
+
156
+ A TypeSafe AI request with pictures is multipart unless `pictures: 'base64'`, and its size is counted
157
+ in bytes. gemini-embedding-2's audio and video are priced, where they cost nothing before, and audio
158
+ past 180 seconds or video past 120 is refused before the call. A Google embedding batch over 20 MB is
159
+ sent as a file, where it was refused. Gemini Live acts on `updateSession()`, which it ignored. A
160
+ realtime record holds the images sent, as `image` items, which a consumer that switches on every item
161
+ type meets for the first time. A Telnyx gather for speech transcribes the caller, where it was
162
+ refused.
163
+
164
+ Deprecated: `OpenApiTools.skipped`, always empty, is removed in 3.0.
165
+
70
166
  ## 2.21 stage (2.21.0)
71
167
 
72
168
  Everything 2.21 adds is stable from the start and additive, unless this section says otherwise.
package/CHANGELOG.md CHANGED
@@ -4,6 +4,168 @@ Notable changes to this project are recorded here. The format follows [Keep a Ch
4
4
 
5
5
  ## [Unreleased]
6
6
 
7
+ ## [3.0.0] - 2026-10-30
8
+
9
+ 3.0, a major release. It turns on the three defaults 2.21 previewed, and removes the two names 2.x
10
+ deprecated; nothing stored changes, and `useDefaults('2.x')` keeps 2.x's defaults for an application
11
+ that upgrades first. [MIGRATING.md](./MIGRATING.md) covers each change, and `nexus migrate` finds what
12
+ it touches.
13
+
14
+ ### Breaking
15
+
16
+ - **A tracer on a durable store writes as it runs.** `TracerOptions.incremental` defaults to true on a
17
+ store whose `durable` is not `false`: each run is written as it starts and again as it ends, so a
18
+ run in a process that dies is not lost, at twice the writes. A store in memory still writes at the end.
19
+ - **The Redis operation store keeps its dispatch index**, where the client has `zadd`, `zrem`, and
20
+ `zrangebyscore`, so a claim reads the same few records however long the queue. Work a worker
21
+ without the index queued is found once `reindex()` runs: call it once the last 2.x worker sharing the
22
+ prefix has stopped.
23
+ - **A deployment first recorded on 3.0 places threads by `hash-v2`**, which spreads sequential ids
24
+ evenly. A deployment already recorded keeps its strategy, so no thread moves.
25
+ - **`OpenApiTools.skipped` is removed.** It was always empty since every operation became a tool.
26
+ - **`GraphCheckpointV2` is removed**, for `GraphCheckpoint`, which it named. `nexus migrate` renames it.
27
+
28
+ ### Changed
29
+
30
+ - **The studio's sign-in is stable.** Every build signs a person in through Dex, an OpenID Connect
31
+ provider run in a container: its configuration read, the code exchanged with the client secret and
32
+ PKCE, its ID token verified against its keys, a wrong password kept at Dex, and a used code refused.
33
+ `oidcSignIn()`, `OidcSignInOptions`, `SIGN_IN_COOKIE`, and the `/auth/` routes leave experimental
34
+ status, with their evidence in API_STABILITY.md.
35
+ - **Gemini's voice is in the live workflow.** It speaks a sentence in one of Gemini's voices and hears it
36
+ back; it graduates when that run passes.
37
+
38
+ ## [2.22.0] - 2026-10-29
39
+
40
+ MCP over streamable HTTP both ways, OpenAPI tools that send each operation's credentials, tokens, keys,
41
+ and sessions the server issues, and a studio that signs people in and serves many tenants; with signed
42
+ A2A cards, embeddings of video, loaders that stream, Gemini's voice, and the kernel in Firefox and
43
+ WebKit.
44
+
45
+ ### Added
46
+
47
+ - **Log probabilities from a stream.** Each `text` chunk's `StreamChunk.logprobs` holds its tokens'
48
+ log probabilities, from OpenAI's Chat Completions and Responses API, Gemini, Ollama, and Cohere, so
49
+ the chunks' together are what `complete()` reports.
50
+ - Cohere reports log probabilities, `complete()` and streamed: a piece of text at a time, each piece's
51
+ the sum of its tokens', with no alternatives.
52
+ - **MCP both ways.** A server offers prompts (`McpServerPrompt`, `registerPrompt()`), resources a client
53
+ subscribes to (`resourceUpdated()`), and tells every client each list's changes; a tool it runs may ask
54
+ the client that called it for a completion from its model, an answer from its person, or its roots,
55
+ through `context.mcp`, and is stopped when the client cancels it. A client answers a server's
56
+ `sampling`, `elicitation`, and `roots` with handlers of its own, `samplingFrom()` answering with
57
+ the application's own model, and hears each list change and each resource it subscribed to.
58
+ - **MCP over streamable HTTP, both ways.** `mcpHttpHandler()` serves an `McpServer` as a Web handler:
59
+ a session per client, a stream of events per request carrying the server's progress and questions
60
+ before its answer, a `GET` stream for what it sends of its own accord, `DELETE` to end a session, and
61
+ a request from another origin refused. The client's HTTP transport reads a stream as it comes, so a
62
+ question in the middle of a call arrives in time, listens on a `GET` stream with `listen`, sends the
63
+ protocol version, and ends its session on `close()`. The nightly interoperability run drives the
64
+ server with `@modelcontextprotocol/sdk`'s own client: its tools, a completion asked mid-call, its
65
+ progress, a prompt, and a subscribed resource's change.
66
+ - **Signed A2A cards.** `signA2aCard()` and `verifyA2aCard()`, with `canonicalA2aCard()`, sign and check
67
+ a card as protocol 1.0 does, a flattened JWS over its canonical form, which is the A2A project's SDK's
68
+ form: a card either signs, the other verifies. A handler's `sign` signs every card it serves, each
69
+ tenant's and the extended card included, and a client's `verifyCard` makes no call until a signature
70
+ on the card holds. ES256, ES384, ES512, RS256, RS384, RS512, PS256, PS384, PS512, and Ed25519, by the
71
+ Web Crypto API alone. The nightly interoperability run checks both directions against `@a2a-js/sdk`.
72
+ - **OpenAPI credentials.** Tools read from an OpenAPI document send the credentials each operation's
73
+ security asks for, from `credentials` given by scheme name, or chosen per call: an API key in a
74
+ header, query parameter, or cookie; HTTP Basic, bearer, or another HTTP scheme; and an OAuth 2.0 or
75
+ OpenID Connect token, held, or fetched by the client-credentials flow for the operation's scopes and
76
+ kept until a minute before it expires. An operation whose alternatives none can be met fails before
77
+ anything is sent, naming them. Each `OpenApiOperation` carries its `security`.
78
+ - **Swagger 2.0, and references to other documents.** A Swagger 2.0 document is read as the OpenAPI 3.0
79
+ one it describes, which `swaggerToOpenApi()` returns. `bundleOpenApiDocument()` reads in the other
80
+ documents a document's references name, on its own origin by default, or as `references` allows,
81
+ within `maxDocuments` and `maxBytes`; `loadOpenApiTools()` does so itself.
82
+ - OpenAPI tools send a multipart form, its file fields given as base64, a text or XML body, and a body
83
+ of bytes, such as an image, so every operation becomes a tool. `webhooks` lists what the API sends
84
+ the application, its webhooks and its operations' callbacks, each with its JSON body's schema.
85
+ - **Tokens, keys, and sessions the server issues.** `createJwtSigner()` issues tokens with a secret, a
86
+ PEM or JWK private key, or a Web Crypto key pair, and `issue()` writes a principal under the claim
87
+ names `jwtAuth()` reads back; `generateJwtKey()` makes a key, and `jwksHandler()` publishes the
88
+ public halves, for a rotation that refuses no live token. `createApiKeyStore()` issues, rotates with
89
+ a grace period, and revokes API keys, kept as hashes in the server's state store with when each was
90
+ last used. `createSessions()` signs browsers in after a sign-in of the application's own: an
91
+ `HttpOnly`, `Secure`, `SameSite=Lax` cookie of a random secret whose hash alone is kept, an idle
92
+ and a total lifetime, sign-out here or everywhere, and a request from another site's page refused.
93
+ - **A Pinecone store makes its own index.** `PineconeVectorStore.create()` creates a serverless index
94
+ with the cosine metric and the store's width, or uses one of that name that fits, waits until it is
95
+ ready, and returns a store over its host; `ensurePineconeIndex()` does the first part alone.
96
+ - TypeSafe AI is sent a decision's pictures as parts of a multipart request, as bytes, so three
97
+ pictures of 10 MiB fit in the 32 MiB a request holds; `TypeSafeDecisionProviderOptions.pictures`
98
+ set to `base64` sends them within the JSON, as before.
99
+ - **Embeddings of video, and audio and video priced by length.** An `EmbeddingVideoPart` holds a video
100
+ by its bytes, base64, or a URL, such as a Files API URI, and gemini-embedding-2 embeds it. Audio is
101
+ priced by the second and video by the frame the model takes, one a second and at most 32 on
102
+ gemini-embedding-2, at $0.00016 a second and $0.00079 a frame, each length read from the media's own
103
+ headers; a budget counts them before the call. Media longer than a model's `maxAudioSeconds` or
104
+ `maxVideoSeconds` is refused before it is sent, and media whose length cannot be read is counted in
105
+ `unpricedMedia`. A registry data file sets these prices and limits too, each checked when it loads.
106
+ - A Google embedding batch over 20 MB, up to 2 GB, is uploaded as a JSONL file through the Files API, and
107
+ its results are read from the file the batch writes, matched to their inputs by key.
108
+ - **CSV and JSON stream through.** `loadCsv()` and `loadJson()` read a file as it arrives and yield each
109
+ row or record as soon as it is read: a path in chunks, or a `FileInput` that is now also a stream,
110
+ such as a response's body. `CsvRowParser` parses CSV a piece at a time, and `recordsAt` names the
111
+ array of records inside a JSON document, such as `data.items`, read item by item. A file larger than
112
+ memory goes to the store a batch at a time.
113
+ - **Pages built by script.** `loadWebPages()` takes a `render` of the application's own for a page
114
+ whose text a script builds, and `browserRenderer()` makes one from a Playwright or Puppeteer browser,
115
+ with no browser a dependency of the package.
116
+ - **Gemini voice.** `GoogleVoiceProvider`, on `nexus-ai-pro/voice/google`, speaks in Gemini's voices, as
117
+ WAV or raw PCM, whichever its model answers with, directed by a system instruction that is never
118
+ spoken; and transcribes with a text model that hears the audio, inline or by a Files API URI, guided
119
+ by its language and the names it may hold. Experimental until a live run is recorded.
120
+ - **Gemini Live changes its setup mid-call.** `updateSession()` on Gemini Live sets the session up again
121
+ between turns, on a new socket resumed from the latest handle: instructions, voice, language,
122
+ modalities, tools, turn detection, the model, and Gemini's own setup fields. What is sent meanwhile
123
+ waits, and the conversation carries on.
124
+ - **Images in the realtime record.** An image sent in a realtime conversation is kept as an `ImageItem`,
125
+ with its digest and, unless `recordImages` is `digest`, the image, and a resumed session gives it
126
+ back to the model. Video frames are not kept.
127
+ - **Telnyx gathers speech.** A gather that listens for speech on Telnyx transcribes the caller's side of
128
+ the call, with its prompts spoken and keys still taken, until `endGather()`. `parseGatherResult()`
129
+ reads what a gather collected on either provider, Twilio's `SpeechResult` and `Digits` or Telnyx's
130
+ `call.transcription` and `call.gather.ended`, as one `TelephonyGatherResult`.
131
+ - **The studio signs people in, and serves many tenants.** `oidcSignIn()` signs people in with any
132
+ OpenID Connect provider, with no proxy in front: the code flow with PKCE, a state, and a nonce, the ID
133
+ token verified against the provider's keys, and a signed session cookie that replicas share, with
134
+ sign-out at the provider too. A person's `tenant`, from a claim, a header, or the users file, picks
135
+ the sources they read, from `tenantSources`; they see their tenant's comments and audit entries
136
+ alone, and their page token is bound to it.
137
+ - **The kernel in Firefox and WebKit.** The portable kernel's own tests, the file Node.js, Deno, Bun,
138
+ and the edge runtime run, now run in a browser page too, in headless Chromium on every build and in
139
+ Firefox and WebKit, Safari's engine, in CI, with a graph, an agent with a streaming tool, and AG-UI.
140
+ - **Cohere's Embed 5.** `embed-v5.0-pro` and `embed-v5.0-fast` are in the registry, with their
141
+ sizes from 256 to 2,048, 128,000 tokens, and images. Cohere publishes no per-token price for them,
142
+ so they are registered without one.
143
+
144
+ ### Changed
145
+
146
+ - A TypeSafe AI request with pictures is multipart by default, and its 32 MiB is counted in bytes, not
147
+ characters, so a state of text outside ASCII is refused before it is sent rather than by the API.
148
+ - `loadCsv()` and `loadJson()` yield their first document before the rest of the file is read; a JSON
149
+ file whose array of records is cut short is refused as such, after the records before the cut.
150
+ - An OpenAPI operation with a multipart or other non-JSON body becomes a tool, where it was skipped; a
151
+ Swagger 2.0 document is read, where it was refused; and `loadOpenApiTools()` refuses a document over
152
+ `maxBytes`, 5 MB by default, reading no further.
153
+
154
+ ### Deprecated
155
+
156
+ - `OpenApiTools.skipped`, always empty now that every operation becomes a tool. It is removed in 3.0.
157
+
158
+ ### Fixed
159
+
160
+ - **An answer the output guard redacts keeps no log probabilities.** They name the tokens the model
161
+ wrote, so a redacted address or connection string was still spelled out in `response.logprobs`; now
162
+ they are dropped wherever the guard changes or blocks the text, streamed or not.
163
+ - The Google embedding batch adapter reads inline results under the name Google's API reference gives
164
+ them, `inlinedResponses`, as well as its clients' name.
165
+ - A typed decision asked of a model that reports only the chosen token's log probability, with no
166
+ alternatives, is sampled, where it was read as certain.
167
+ - An Ollama stream stops at the request's `stop` sequences, as a call does.
168
+
7
169
  ## [2.21.0] - 2026-10-26
8
170
 
9
171
  Typed decisions about pictures, compatibility records gathered from community adapters' own CI, and
@@ -3361,7 +3523,9 @@ shared policy vocabulary is in place for a future release that revisits this.
3361
3523
  - URL fetching rejects unsafe private-network targets and limits response reads.
3362
3524
  - CLI and audit findings no longer disclose detected secret values.
3363
3525
 
3364
- [Unreleased]: https://github.com/mkhitar-abrahamyan/nexus-ai/compare/v2.21.0...HEAD
3526
+ [Unreleased]: https://github.com/mkhitar-abrahamyan/nexus-ai/compare/v3.0.0...HEAD
3527
+ [3.0.0]: https://github.com/mkhitar-abrahamyan/nexus-ai/compare/v2.22.0...v3.0.0
3528
+ [2.22.0]: https://github.com/mkhitar-abrahamyan/nexus-ai/compare/v2.21.0...v2.22.0
3365
3529
  [2.21.0]: https://github.com/mkhitar-abrahamyan/nexus-ai/compare/v2.20.2...v2.21.0
3366
3530
  [2.20.2]: https://github.com/mkhitar-abrahamyan/nexus-ai/compare/v2.20.1...v2.20.2
3367
3531
  [2.20.1]: https://github.com/mkhitar-abrahamyan/nexus-ai/compare/v2.20.0...v2.20.1
package/MIGRATING.md CHANGED
@@ -1,4 +1,138 @@
1
- # Migrating to 2.0
1
+ # Migrating
2
+
3
+ - [To 3.0](#migrating-to-30), from 2.x
4
+ - [To 2.0](#migrating-to-20), from 1.x
5
+
6
+ ## Migrating to 3.0
7
+
8
+ 3.0 turns on three defaults that 2.x kept opt-in, and removes two names 2.x deprecated. Nothing stored
9
+ changes: checkpoints, operation records, the server's state, and recorded deployments read as 2.x
10
+ wrote them. Most code compiles unchanged, but the three defaults change what a deployment does, so read
11
+ each before the upgrade reaches production.
12
+
13
+ To upgrade first and take the defaults later, keep 2.x's for now, on every replica:
14
+
15
+ ```ts
16
+ import { useDefaults } from 'nexus-ai-pro/config';
17
+
18
+ useDefaults('2.x'); // before creating a tracer, an operation store, or a deployment
19
+ ```
20
+
21
+ or set `NEXUS_DEFAULTS=2.x` in the environment. Then `npx nexus doctor --upgrade 3.0` says what turning
22
+ them on would change for your deployment, and `npx nexus migrate src` finds the removed names.
23
+
24
+ | Change | The codemod | By hand |
25
+ | --- | --- | --- |
26
+ | [A tracer on a durable store writes as it runs](#a-tracer-on-a-durable-store-writes-as-it-runs) | — | Expect twice the trace writes; close abandoned runs |
27
+ | [The Redis operation store keeps its index](#the-redis-operation-store-keeps-its-index) | — | Call `reindex()` once no worker without the index is left |
28
+ | [A new deployment places threads by `hash-v2`](#a-new-deployment-places-threads-by-hash-v2) | — | Give `bucket()` the deployment's strategy |
29
+ | [`OpenApiTools.skipped` is removed](#openapitoolsskipped-is-removed) | Lists each read | Delete it |
30
+ | [`GraphCheckpointV2` is removed](#graphcheckpointv2-is-removed) | Renames it | — |
31
+ | [`useDefaults('3.0')` changes nothing](#usedefaults30-changes-nothing) | Lists each call | Delete it |
32
+
33
+ ### A tracer on a durable store writes as it runs
34
+
35
+ `TracerOptions.incremental` defaults to true on a store whose `durable` is not `false`. Each run is
36
+ written when it starts and again when it ends, so a run in a process that dies stays in the store with
37
+ every run beneath it that finished, and a run in progress can be watched. A store in memory, such as
38
+ `MemoryTraceStore`, still writes each trace when its root finishes.
39
+
40
+ - A store takes twice the writes, and a JSON Lines file twice the lines, the later one winning.
41
+ - A run a dead process left stays `running` until `closeAbandonedRuns()` closes it. Call it when a
42
+ worker starts, or on a schedule.
43
+ - Sampling is decided when the root starts. A trace not sampled is held in memory and written at the
44
+ end when tail sampling keeps it, so `keepErrors` still shows every failure.
45
+ - A store of your own that keeps runs only in memory says `durable: false`, and is written at the end.
46
+
47
+ ```ts
48
+ // Before: 2.x wrote each trace when its root finished
49
+ const tracer = new Tracer({ store });
50
+
51
+ // After, to keep that
52
+ const tracer = new Tracer({ store, incremental: false });
53
+ ```
54
+
55
+ ### The Redis operation store keeps its index
56
+
57
+ `RedisOperationStore` keeps queued work in a sorted set by age, and leased work in one by lease expiry,
58
+ wherever its client has `zadd`, `zrem`, and `zrangebyscore`. A claim then reads the same few records
59
+ with 100,000 operations queued as with 1,000. A client without those commands is not refused: the store
60
+ reads every record, as 2.x did.
61
+
62
+ A worker without the index, as every 2.x worker is unless asked, writes records without index
63
+ entries, so work it queues is in the index only once `reindex()` adds it. Either way works:
64
+
65
+ - **Roll 3.0 out, then reindex.** While 2.x workers run, they claim what they queued. Once the last of
66
+ them has stopped, call `reindex()` once, so the 3.0 workers find what was left. It is safe while
67
+ workers are busy.
68
+ - **Turn the index on first, on 2.x.** On 2.2 or later, give every worker sharing the prefix
69
+ `index: true`, or on 2.21 `useDefaults('3.0')`, and call `reindex()` once; 3.0 then changes nothing.
70
+
71
+ ```ts
72
+ const operations = new RedisOperationStore(redis);
73
+ await operations.reindex(); // once no worker without the index shares the prefix
74
+ ```
75
+
76
+ `index: false` keeps 2.x's behaviour.
77
+
78
+ ### A new deployment places threads by `hash-v2`
79
+
80
+ A deployment first recorded on 3.0 places new threads and stateless runs by `hash-v2`, which spreads
81
+ sequential ids, such as `user-1` to `user-500`, as evenly as random ones. A deployment already recorded
82
+ keeps the strategy it records, `fnv1a-v1` before 3.0, so no thread moves through the upgrade;
83
+ `Deployments.bucketing()` moves one when you choose to.
84
+
85
+ `bucket()` still places a key by `fnv1a-v1` unless it is given a strategy, so code that predicts where a
86
+ thread lands passes the deployment's:
87
+
88
+ ```ts
89
+ // Before
90
+ const onCanary = bucket(`support:${threadId}`) < 0.1;
91
+
92
+ // After
93
+ const deployment = await deployments.get('support');
94
+ const onCanary = bucket(`support:${threadId}`, deployment?.bucketStrategy) < 0.1;
95
+ ```
96
+
97
+ `bucketStrategy: 'fnv1a-v1'` on `Deployments.assistant()` keeps 2.x's strategy for a deployment not
98
+ yet recorded. During a rolling upgrade, the replica that first records a deployment, by its first
99
+ canary or split, decides its strategy, and every replica of 2.5 or later then reads it from the record;
100
+ pass `bucketStrategy` to choose rather than leave it to the replica.
101
+
102
+ ### `OpenApiTools.skipped` is removed
103
+
104
+ Every operation of an OpenAPI document becomes a tool since 2.22, its body sent whatever its type, so
105
+ `skipped` was always empty. Delete each read. The codemod lists them, in files that use the OpenAPI
106
+ tools.
107
+
108
+ ### `GraphCheckpointV2` is removed
109
+
110
+ It was another name for `GraphCheckpoint`, kept since 1.25. The codemod renames it and keeps your local
111
+ name:
112
+
113
+ ```ts
114
+ // Before
115
+ import type { GraphCheckpointV2 } from 'nexus-ai-pro/graph';
116
+
117
+ // After
118
+ import type { GraphCheckpoint as GraphCheckpointV2 } from 'nexus-ai-pro/graph';
119
+ ```
120
+
121
+ ### `useDefaults('3.0')` changes nothing
122
+
123
+ An application that previewed 3.0 with `useDefaults('3.0')` or `NEXUS_DEFAULTS=3.0` already runs as 3.0
124
+ does. The call and the variable change nothing now, and can go. `useDefaults('2.x')` and
125
+ `NEXUS_DEFAULTS=2.x` keep 2.x's three defaults through 3.x.
126
+
127
+ ### What does not change
128
+
129
+ - Checkpoints of version 1 and 2 are read by both checkpointers and by `migrateCheckpoint()`.
130
+ - The server's state keys, sessions, API keys, operation records, and recorded deployments read as 2.x
131
+ wrote them.
132
+ - Every other default, and every API this guide does not name.
133
+ - Node.js 22 or later.
134
+
135
+ ## Migrating to 2.0
2
136
 
3
137
  2.0.0 removes what the 1.x line deprecated, and runs every call of every family through one
4
138
  lifecycle. Most applications change only their imports, and a codemod does that.
@@ -31,7 +165,7 @@ upgrade, and work through the table.
31
165
  | [Claude 4.6 onward think adaptively](#claude-46-onward-think-adaptively) | — | Nothing |
32
166
  | [Tool calls reach providers whole](#tool-calls-reach-providers-whole) | — | Nothing |
33
167
 
34
- ## The root import keeps only the core
168
+ ### The root import keeps only the core
35
169
 
36
170
  In 2.0, `nexus-ai-pro` exports the core client and nothing else:
37
171
 
@@ -71,7 +205,7 @@ is in the [packaging guide](https://github.com/mkhitar-abrahamyan/nexus-ai/blob/
71
205
 
72
206
  The root import now costs about 325 KB, down from 572 KB.
73
207
 
74
- ## Validators and Node types are optional
208
+ ### Validators and Node types are optional
75
209
 
76
210
  `zod`, `ajv`, `ajv-formats`, and `@types/node` are optional peer dependencies. A production install
77
211
  is the package alone, about 5.3 MB instead of 12.3 MB.
@@ -88,7 +222,7 @@ install. A zod shape is checked through each field's own `safeParse`.
88
222
  The request check in the guardrails, `SchemaValidator`, no longer uses zod. It reports the same
89
223
  fields by the same paths; the wording of its findings changed.
90
224
 
91
- ## A response's `estimatedCost` is removed
225
+ ### A response's `estimatedCost` is removed
92
226
 
93
227
  The formatted string on a response's metadata is gone. Read the numeric cost, and format it yourself:
94
228
 
@@ -104,7 +238,7 @@ if (cost) console.log(new Intl.NumberFormat('en-US', { style: 'currency', curren
104
238
  A plan's `estimatedCost`, from `ai.plan()`, is an object and stays. A custom provider that set the
105
239
  string should drop it; `buildMeta()` fills `usage` and `cost`.
106
240
 
107
- ## Modalities say which way they flow
241
+ ### Modalities say which way they flow
108
242
 
109
243
  A model's `modalities` list mixed inputs and outputs: `vision` meant an image in, and `image` meant an
110
244
  image out. 2.0 removes it, and the `Modality` type with it. Every entry declares `inputModalities` and
@@ -128,7 +262,7 @@ models: { registry: { 'my-model': { inputModalities: ['text', 'image'], outputMo
128
262
  In routing requirements, replace `modalities` with `inputModalities` or `outputModalities`.
129
263
  `modalitiesOf()` still reads both lists, and now requires both.
130
264
 
131
- ## Checkpoints are version 2
265
+ ### Checkpoints are version 2
132
266
 
133
267
  A checkpoint 2.x writes has a `version` of 2, an `id`, its `tasks` always spelled out, and every
134
268
  pending question in `interrupts`. The single `interrupt` field is gone.
@@ -152,7 +286,7 @@ so a thread left waiting resumes after the upgrade.
152
286
  | Build a checkpoint by hand | Use `toCheckpoint()`, which fills in the version, id, tasks, and questions |
153
287
  | Named `GraphCheckpointV2` | It still compiles; it is now another name for `GraphCheckpoint` |
154
288
 
155
- ## Options that were never read are removed
289
+ ### Options that were never read are removed
156
290
 
157
291
  These were accepted and ignored, and warned once per process since they were deprecated. The codemod
158
292
  lists each one it finds.
@@ -170,11 +304,11 @@ lists each one it finds.
170
304
  Delete them. Nothing changes, because nothing read them. Approval before a tool runs is
171
305
  `interruptOn` on `createAgent()`.
172
306
 
173
- ## `ImageManagerConfig` is removed
307
+ ### `ImageManagerConfig` is removed
174
308
 
175
309
  It was another name for `ImageConfig`. The codemod renames the import and keeps your local name.
176
310
 
177
- ## Pipeline step names are a closed list
311
+ ### Pipeline step names are a closed list
178
312
 
179
313
  `PipelineStepName` lists the built-in stages only, so a `switch` over it can be exhaustive. A step you
180
314
  add with `use()` is recorded as `customStep`, with its own name in `custom`.
@@ -195,7 +329,7 @@ Metrics for a custom step keep its own name as their `step` label.
195
329
  `PipelineRunner` are generic over the request and the response. Both default to a completion's, so
196
330
  existing code compiles unchanged.
197
331
 
198
- ## Streams open on their first read
332
+ ### Streams open on their first read
199
333
 
200
334
  `ai.stream()` returns at once. Authorization, the rate limit, guardrails, routing, and the budget run
201
335
  when the stream is first read, so their errors come out of the loop:
@@ -216,7 +350,7 @@ Streams now get what completions always had. They are audited and counted, the c
216
350
  circuit breaker apply, and the `done` chunk carries the request id and a cost priced on the routed
217
351
  model.
218
352
 
219
- ## Every call runs through the lifecycle
353
+ ### Every call runs through the lifecycle
220
354
 
221
355
  Completions, streams, embeddings, voice, telephony, images, realtime sessions, graphs, agents, jobs,
222
356
  and batches share one [lifecycle](https://github.com/mkhitar-abrahamyan/nexus-ai/blob/main/docs/lifecycle.md).
@@ -244,7 +378,7 @@ To use the lifecycle, set `lifecycle` on the client: an `authorize` callback, a
244
378
  `hooks`. Pass `ai.lifecycle` to graphs, agents, workflows, realtime sessions, queues, and batches to
245
379
  make their runs operations of the client too.
246
380
 
247
- ## Responses are priced on the routed model
381
+ ### Responses are priced on the routed model
248
382
 
249
383
  The client now prices each response on the model the request was routed to, as the registry names
250
384
  it. Providers often answer with a dated snapshot name the registry does not file. In 1.x, pricing on
@@ -252,7 +386,7 @@ that echo cost the call nothing, so OpenAI responses could show a cost of 0, and
252
386
  DeepSeek, and Cohere models filed under a prefix. Expect those costs to be priced in 2.0, and budgets
253
387
  to count them. A charge the provider reports, with `basis: 'reported'`, is kept as it is.
254
388
 
255
- ## The model registry is current
389
+ ### The model registry is current
256
390
 
257
391
  The bundled registry was checked against each provider's documentation on 2026-10-02.
258
392
 
@@ -269,7 +403,7 @@ The bundled registry was checked against each provider's documentation on 2026-1
269
403
 
270
404
  `describeModel()` shows what a name resolves to and when its entry was verified.
271
405
 
272
- ## Claude 4.6 onward think adaptively
406
+ ### Claude 4.6 onward think adaptively
273
407
 
274
408
  From the 4.6 generation on, Claude takes adaptive thinking and an effort level, not a thinking budget.
275
409
  After 4.6 a budget is rejected, so 1.x requests with `reasoning` failed on those models. 2.0 sends what
@@ -277,7 +411,7 @@ each model accepts, and the [core guide](docs/core.md#reasoning) has the details
277
411
  your code. From 4.7 on, Claude also rejects a non-default `temperature` or `topP`, so the client
278
412
  drops one and records a capability warning.
279
413
 
280
- ## Tool calls reach providers whole
414
+ ### Tool calls reach providers whole
281
415
 
282
416
  In 1.x the OpenAI, Anthropic, and Google adapters dropped a conversation's tool calls and the ids that
283
417
  link results to them. A real tool loop could fail on its second turn. 2.0 sends both the way each API
@@ -287,7 +421,7 @@ Two things are new beside it. A tool can return `toolOutput()`, whose text, imag
287
421
  references go back as the tool message itself. And a model that produces images returns them on
288
422
  `response.assets`.
289
423
 
290
- ## For provider authors
424
+ ### For provider authors
291
425
 
292
426
  The provider contracts only grew:
293
427
 
@@ -298,6 +432,6 @@ The provider contracts only grew:
298
432
 
299
433
  A provider written for 1.x compiles unchanged.
300
434
 
301
- ## Runtime
435
+ ### Runtime
302
436
 
303
437
  2.0 runs on Node 22 and newer.
package/README.md CHANGED
@@ -341,13 +341,21 @@ Shipped so far:
341
341
  evaluated with nothing sent, and one A2A handler serving many tenants, each seeing only its own;
342
342
  - 2.21 typed decisions about pictures, a yes or no, a choice, a score, or a box around something in
343
343
  one, from TypeSafe AI's Jev or any vision model; community adapters' compatibility records gathered
344
- from their own CI, a failing one turning red; and 3.0's defaults behind one switch today.
345
-
346
- Upgrading from 1.x: `npx nexus migrate src --write` moves your imports, and
347
- [MIGRATING.md](https://github.com/mkhitar-abrahamyan/nexus-ai/blob/main/MIGRATING.md) covers the rest.
348
- Next, in 2.22, Pinecone, images, the Gemini embedding batch tier, media understanding, video, typed
349
- decisions, Gemini Live, SIP, and both phone providers graduate once the live workflow passes against
350
- each. The
344
+ from their own CI, a failing one turning red; and 3.0's defaults behind one switch today;
345
+ - 2.22 MCP over streamable HTTP both ways, with prompts, resources, and a server's questions back to
346
+ the client; OpenAPI tools that send each operation's credentials; tokens, API keys, and sessions the
347
+ server issues; and a studio that signs people in with your identity provider and serves many
348
+ tenants, each seeing only its own;
349
+ - 3.0 the three defaults 2.21 previewed, on: tracing written as it runs, the Redis dispatch index, and
350
+ `hash-v2` for a new deployment, with `useDefaults('2.x')` for an application that upgrades first;
351
+ and the studio's sign-in, stable, proven against a real OpenID Connect provider on every build.
352
+
353
+ Upgrading from 2.x: 3.0 turns on three defaults 2.x kept opt-in, and `useDefaults('2.x')` keeps them
354
+ off until you are ready; from 1.x, `npx nexus migrate src --write` moves your imports.
355
+ [MIGRATING.md](https://github.com/mkhitar-abrahamyan/nexus-ai/blob/main/MIGRATING.md) covers both.
356
+ Next, in 3.1, Pinecone, images, the Gemini embedding batch tier, media understanding, video, typed
357
+ decisions, Gemini Live, SIP, both phone providers, and Gemini's voice graduate once the live workflow
358
+ passes against each. The
351
359
  [roadmap](https://github.com/mkhitar-abrahamyan/nexus-ai/blob/main/ROADMAP.md) lists what comes after, in the order
352
360
  applications ask for it.
353
361
 
package/SECURITY.md CHANGED
@@ -281,9 +281,23 @@ Findings, each fixed in 2.5 with a test in `studio/test/security.test.ts`:
281
281
  - **A proposal's pull-request link was rendered as stored.** The content security policy already
282
282
  blocked a `javascript:` address. Only `http` and `https` links are rendered now.
283
283
 
284
+ Signing in and tenants, reviewed for 2.22, with tests in `studio/test/signin.test.ts`,
285
+ `studio/test/tenants.test.ts`, and, against Dex, a real provider, `studio/test/signin-dex.test.ts`:
286
+ - The provider's configuration must name the issuer the studio was given. An ID token must verify
287
+ against the provider's keys, name that issuer and the studio's client as its audience, and carry
288
+ the sign-in's nonce; a token for several clients must name the studio as `azp`.
289
+ - The state, nonce, and PKCE verifier travel in a cookie signed for that purpose alone, for ten
290
+ minutes, so a callback from another browser, a late one, or a changed one is refused, and a sign-in
291
+ cookie is never taken as a session.
292
+ - The page to come back to is always a path on the studio, never another site.
293
+ - A tenant's people read only what `tenantSources` gives for their tenant. The studio itself keeps
294
+ comments and audit entries to their tenant, whatever the store does, and binds the page token to it.
295
+ `headerAuth()` with a tenant header refuses a request that lacks it.
296
+
284
297
  Documented limitations, which the studio guide states:
285
- - The studio has no tenants of its own. Every account sees every source the studio is given, so a
286
- tenant's people get a studio over that tenant's `tenantScope()` views.
298
+ - Someone without a tenant reads the studio's own sources, the operators' view.
299
+ - A session is a signed cookie, so one person's cannot be ended before it expires; rotating the
300
+ sign-in secret signs everyone out. Signing out is a plain link, which another site can follow.
287
301
  - A page token stays valid while the secret, the user, and their role do. Rotate `secret` to revoke
288
302
  every page at once.
289
303
  - Someone without a session who opens another person's personal link is signed in as that person.