nexus-ai-pro 1.2.1 → 1.4.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 (65) hide show
  1. package/API_STABILITY.md +42 -1
  2. package/CHANGELOG.md +97 -1
  3. package/README.md +116 -6
  4. package/ROADMAP.md +359 -209
  5. package/dist/capabilities/negotiate.d.ts +38 -0
  6. package/dist/capabilities/negotiate.js +190 -0
  7. package/dist/core/nexus.js +35 -3
  8. package/dist/core/usage.d.ts +58 -0
  9. package/dist/core/usage.js +97 -0
  10. package/dist/index.d.ts +9 -6
  11. package/dist/index.js +5 -3
  12. package/dist/models/registry.d.ts +60 -1
  13. package/dist/models/registry.js +82 -5
  14. package/dist/optimizer/cost.d.ts +10 -0
  15. package/dist/optimizer/cost.js +54 -2
  16. package/dist/providers/anthropic.js +169 -32
  17. package/dist/providers/cohere.js +4 -0
  18. package/dist/providers/google.d.ts +9 -0
  19. package/dist/providers/google.js +81 -37
  20. package/dist/providers/ollama.d.ts +2 -0
  21. package/dist/providers/ollama.js +27 -29
  22. package/dist/providers/openai.d.ts +8 -1
  23. package/dist/providers/openai.js +121 -32
  24. package/dist/security/schema-validator.d.ts +4 -4
  25. package/dist/telephony/providers/twilio.js +12 -0
  26. package/dist/types/capabilities.d.ts +34 -0
  27. package/dist/types/capabilities.js +1 -0
  28. package/dist/types/config.d.ts +26 -1
  29. package/dist/types/messages.d.ts +75 -0
  30. package/dist/types/planning.d.ts +7 -0
  31. package/dist/types/providers.d.ts +75 -0
  32. package/dist/types/providers.js +90 -1
  33. package/dist/types/response.d.ts +48 -1
  34. package/dist/types/telephony.d.ts +17 -0
  35. package/dist-cjs/capabilities/negotiate.d.ts +38 -0
  36. package/dist-cjs/capabilities/negotiate.js +195 -0
  37. package/dist-cjs/core/nexus.js +35 -3
  38. package/dist-cjs/core/usage.d.ts +58 -0
  39. package/dist-cjs/core/usage.js +104 -0
  40. package/dist-cjs/index.d.ts +9 -6
  41. package/dist-cjs/index.js +22 -4
  42. package/dist-cjs/models/registry.d.ts +60 -1
  43. package/dist-cjs/models/registry.js +85 -4
  44. package/dist-cjs/optimizer/cost.d.ts +10 -0
  45. package/dist-cjs/optimizer/cost.js +56 -3
  46. package/dist-cjs/providers/anthropic.js +168 -31
  47. package/dist-cjs/providers/cohere.js +4 -0
  48. package/dist-cjs/providers/google.d.ts +9 -0
  49. package/dist-cjs/providers/google.js +81 -37
  50. package/dist-cjs/providers/ollama.d.ts +2 -0
  51. package/dist-cjs/providers/ollama.js +27 -29
  52. package/dist-cjs/providers/openai.d.ts +8 -1
  53. package/dist-cjs/providers/openai.js +121 -32
  54. package/dist-cjs/security/schema-validator.d.ts +4 -4
  55. package/dist-cjs/telephony/providers/twilio.js +12 -0
  56. package/dist-cjs/types/capabilities.d.ts +34 -0
  57. package/dist-cjs/types/capabilities.js +2 -0
  58. package/dist-cjs/types/config.d.ts +26 -1
  59. package/dist-cjs/types/messages.d.ts +75 -0
  60. package/dist-cjs/types/planning.d.ts +7 -0
  61. package/dist-cjs/types/providers.d.ts +75 -0
  62. package/dist-cjs/types/providers.js +91 -2
  63. package/dist-cjs/types/response.d.ts +48 -1
  64. package/dist-cjs/types/telephony.d.ts +17 -0
  65. package/package.json +15 -2
package/API_STABILITY.md CHANGED
@@ -26,7 +26,48 @@ Source files, `dist` file paths, examples, test helpers that are not exported, a
26
26
  - Security fixes may tighten validation or blocking behavior in a patch release when preserving the old behavior would leave users exposed.
27
27
  - Provider behavior can change when an upstream API changes; Nexus will preserve its normalized request and response contracts where possible.
28
28
 
29
- The package is ESM-only and supports Node.js 22 or newer. CommonJS `require()` and deep imports into `dist` or `src` are not supported.
29
+ ## Module formats
30
+
31
+ Since 1.2.0 the package ships parallel ESM and CommonJS builds and supports Node.js 22 or newer.
32
+ Both are covered by this policy:
33
+
34
+ - every export subpath carries `import` and `require` conditions, each resolving to its own build and
35
+ its own declarations, so a CommonJS consumer never lands on ESM declarations;
36
+ - `typesVersions` maps each subpath to its CommonJS declarations, so subpath types resolve under
37
+ `moduleResolution: "node10"` without a consumer migrating its `tsconfig.json`;
38
+ - dropping either build, or removing a subpath from either condition, requires a major release.
39
+
40
+ Deep imports into `dist`, `dist-cjs`, or `src` are not supported. Import only from `nexus-ai-pro` or
41
+ one of its explicit subpaths.
42
+
43
+ ## Capability negotiation stage
44
+
45
+ `negotiateCompletionRequest()`, `NexusCapabilityError`, `CapabilityPolicy`, `CapabilityWarning`, and
46
+ the `nexus-ai-pro/capabilities` subpath are public and follow the 1.x rules.
47
+
48
+ Which options a given model accepts is registry data, not a compatibility guarantee. A model's
49
+ declared capabilities, cache lifetimes, reasoning effort levels, and prices can change in a minor
50
+ release when a provider changes its lineup, and new normalized warning entries may be added. What is
51
+ guaranteed is the behavior of each policy: `strict` throws before the provider call, `warn` records a
52
+ warning and continues, `off` sends the request unchanged, and an option a model does not mention is
53
+ always passed through rather than refused.
54
+
55
+ `ResponseMeta.usage` and `ResponseMeta.cost` are public normalized shapes. Reported token counts and
56
+ prices originate with the provider or with bundled defaults and are not compatibility guarantees;
57
+ `cost.basis` distinguishes the two. `ResponseMeta.estimatedCost` is deprecated in favor of
58
+ `cost.amount` and will be removed in the next major release.
59
+
60
+ ## Telephony API stage
61
+
62
+ The `nexus-ai-pro/telephony`, `telephony/twilio`, and `telephony/realtime-bridge` subpaths are public
63
+ and follow the 1.x rules. This covers `TelephonyManager`, the `TelephonyProvider` contract, the
64
+ normalized call, media-stream, status-callback, and phone-number types, the TwiML helpers, and the
65
+ realtime bridge.
66
+
67
+ Provider payloads under `raw`, TwiML markup details beyond the documented helper options, webhook
68
+ signature formats, upstream call-status vocabularies, and carrier behavior are controlled by the
69
+ provider and are not normalized guarantees. `TelephonyProvider` methods are optional by design, so a
70
+ provider adapter may implement any subset; adding a new optional method is a minor change.
30
71
 
31
72
  ## Realtime API stage
32
73
 
package/CHANGELOG.md CHANGED
@@ -4,6 +4,97 @@ Notable changes to this project are recorded here. The format follows [Keep a Ch
4
4
 
5
5
  ## [Unreleased]
6
6
 
7
+ ## [1.4.0] - 2026-08-25
8
+
9
+ Request parity and cost truth: the completion request can now express what current models actually
10
+ do, and the response reports what the call really cost. Every addition is an optional field or a new
11
+ union member, so existing code is unaffected.
12
+
13
+ ### Added
14
+
15
+ - **Provider prompt caching.** `CompletionRequest.cache` selects `off`, `auto`, or `explicit` mode
16
+ with a `5m` or `1h` lifetime, and `Message.cache` / `ToolDefinition.cache` mark the end of a
17
+ cacheable prefix. The Anthropic adapter translates marks into `cache_control` breakpoints,
18
+ respecting the four-breakpoint limit by keeping the deepest marks, and every adapter reports what
19
+ the provider actually reused.
20
+ - **Reasoning controls.** `CompletionRequest.reasoning` carries `effort`, `maxTokens`, and `summary`.
21
+ These map to OpenAI `reasoning_effort` and the Responses `reasoning` field, Anthropic extended
22
+ thinking with a token budget, and Gemini `thinkingConfig`. A new `'reasoning'` `StreamChunk`
23
+ variant carries reasoning summaries, kept separate from `'text'` so existing consumers that switch
24
+ on chunk type see no change.
25
+ - **Tool and sampling controls.** `toolChoice`, `parallelToolCalls`, `seed`, `topK`,
26
+ `frequencyPenalty`, and `presencePenalty` on `CompletionRequest`, mapped per provider.
27
+ - **Structured usage and numeric cost.** `ResponseMeta.usage` reports input, output, cached-read,
28
+ cached-write, and reasoning tokens; `ResponseMeta.cost` reports a numeric amount with a currency
29
+ and an `estimated` or `reported` basis. Cached reads and cache writes are priced at their own
30
+ rates, with a long-lived write costing more than a short-lived one. `models.cachePricing`
31
+ overrides the bundled multipliers.
32
+ - **Capability negotiation.** `negotiateCompletionRequest()` reconciles a request against the routed
33
+ model under a `strict`, `warn`, or `off` policy, set through `capabilities.policy` or per request
34
+ through `capabilityPolicy`. Refused options are reported on `ResponseMeta.capabilityWarnings` and
35
+ in `plan()` warnings. An option the registry does not mention is passed through: absence means
36
+ unknown, not unsupported, so an application-registered model is never restricted by fields it does
37
+ not declare, and `off` guarantees a newer provider feature is never blocked by stale metadata.
38
+ - **Registry provenance.** Model entries accept `verifiedAt` and `source`; `MODEL_ALIAS_METADATA`
39
+ reports each alias's stage and whether its target floats between releases. `describeModel()`,
40
+ `checkRegistryFreshness()`, and `assertRegistryFreshness()` make drift visible instead of silent.
41
+ - **Streamed usage on OpenAI.** `stream_options.include_usage` is requested for OpenAI and Azure, so
42
+ a streamed response reports real tokens and cost rather than zeros. Other OpenAI-compatible
43
+ servers opt in with the new `streamUsage` provider option.
44
+ - A `nexus-ai-pro/capabilities` subpath for the negotiation API.
45
+
46
+ ### Fixed
47
+
48
+ - Claude 5 models were declared as non-reasoning. The registry decided extended-thinking support by
49
+ looking for a `4` in the family name, which is absent from `claude-sonnet-5.0`, `claude-haiku-5.0`,
50
+ and `claude-fable-5.0`. Support is now derived from the family version, so every release from 3.7
51
+ onward is reported correctly, together with the thinking budget each model can accept.
52
+ - The Anthropic adapter priced every completion at a hardcoded $0.003/$0.015 per 1k tokens instead of
53
+ using the model registry, so cost was wrong for every Claude model except one. All adapters now
54
+ share one pricing path.
55
+ - Streamed Anthropic and Google responses reported zero tokens and `$0.00`. Both now carry the
56
+ provider's own usage totals on the final chunk.
57
+ - Google reasoning summaries could be concatenated into visible output. Parts marked `thought` are
58
+ excluded from content and emitted as `'reasoning'` chunks instead.
59
+ - A chat stream that ended without a finish reason produced no `done` chunk, leaving consumers
60
+ without terminal metadata.
61
+
62
+ ### Changed
63
+
64
+ - `ResponseMeta.estimatedCost` is deprecated in favor of the numeric `cost` object. It is still
65
+ populated and stays until the next major release. The metrics path no longer parses money out of
66
+ its own display string.
67
+ - `ResponseMeta.tokensInput` keeps its original meaning of every prompt token; the uncached share
68
+ billed at the standard rate is `usage.inputTokens`. Adapters whose provider folds cached tokens
69
+ into one prompt total subtract them so no token is priced twice.
70
+ - `resolveModel()` no longer merges the bundled and application registries into a new object on each
71
+ call. It reads both maps directly, which removes a per-request allocation from the hot path;
72
+ `getModelRegistry()` and `getModelAliases()` are unchanged as the merged views.
73
+ - Coverage gates raised from 70/60/60 to 82% lines, 67% branches, and 73% functions, with new tests
74
+ for the agent loop, the rules router, the evaluation metric library, and the Google, Ollama, and
75
+ Cohere adapters. The gates sit a couple of points below the lowest figure the supported Node
76
+ versions report, because Node 22 and Node 24 do not count functions identically: the same suite
77
+ measures 78.7% on Node 22 and 75.9% on Node 24. A gate set from one version alone fails on the
78
+ other.
79
+
80
+ ### Notes
81
+
82
+ Image operations keep their existing strict capability behavior. An unsupported image option changes
83
+ the artifact that comes back, so silently dropping one is worse than refusing the request; the
84
+ shared policy vocabulary is in place for a future release that revisits this.
85
+
86
+ ## [1.3.0] - 2026-08-17
87
+
88
+ ### Added
89
+
90
+ - SMS routing on `updatePhoneNumber`. `UpdatePhoneNumberRequest` now carries `smsUrl`, `smsMethod`,
91
+ `smsFallbackUrl`, and `smsFallbackMethod`, and the Twilio provider maps them to `SmsUrl`,
92
+ `SmsMethod`, `SmsFallbackUrl`, and `SmsFallbackMethod`. Only the voice leg could be repointed
93
+ before, so an application holding SMS-enabled numbers had to drop to the provider SDK to say where
94
+ inbound messages should be delivered.
95
+ - `TelephonyPhoneNumber` reports the number's current `smsUrl`, `smsMethod`, `smsFallbackUrl`, and
96
+ `smsFallbackMethod`, so message routing can be verified the same way voice routing already is.
97
+
7
98
  ## [1.2.1] - 2026-08-10
8
99
 
9
100
  ### Fixed
@@ -110,6 +201,11 @@ Notable changes to this project are recorded here. The format follows [Keep a Ch
110
201
  - URL fetching rejects unsafe private-network targets and limits response reads.
111
202
  - CLI and audit findings no longer disclose detected secret values.
112
203
 
113
- [Unreleased]: https://github.com/mkhitar-abrahamyan/nexus-ai/compare/v1.0.0...HEAD
204
+ [Unreleased]: https://github.com/mkhitar-abrahamyan/nexus-ai/compare/v1.4.0...HEAD
205
+ [1.4.0]: https://github.com/mkhitar-abrahamyan/nexus-ai/compare/v1.3.0...v1.4.0
206
+ [1.3.0]: https://github.com/mkhitar-abrahamyan/nexus-ai/compare/v1.2.1...v1.3.0
207
+ [1.2.1]: https://github.com/mkhitar-abrahamyan/nexus-ai/compare/v1.2.0...v1.2.1
208
+ [1.2.0]: https://github.com/mkhitar-abrahamyan/nexus-ai/compare/v1.1.0...v1.2.0
209
+ [1.1.0]: https://github.com/mkhitar-abrahamyan/nexus-ai/compare/v1.0.0...v1.1.0
114
210
  [1.0.0]: https://github.com/mkhitar-abrahamyan/nexus-ai/releases/tag/v1.0.0
115
211
  [0.9.0]: https://github.com/mkhitar-abrahamyan/nexus-ai/releases/tag/v0.9.0
package/README.md CHANGED
@@ -239,7 +239,112 @@ console.log(plan.fitsContext);
239
239
  console.log(plan.warnings);
240
240
  ```
241
241
 
242
- `plan()` does not call a provider. It estimates route, token use, context fit, cost, guardrail findings, and warnings.
242
+ `plan()` does not call a provider. It estimates route, token use, context fit, cost, guardrail findings, and warnings, including any option the routed model cannot honor.
243
+
244
+ ### Reasoning
245
+
246
+ ```ts
247
+ const response = await ai.complete({
248
+ model: 'auto',
249
+ messages: [{ role: 'user', content: 'Find the bug in this migration plan.' }],
250
+ reasoning: { effort: 'high', summary: 'auto' },
251
+ });
252
+
253
+ console.log(response.meta.usage?.reasoningTokens);
254
+ ```
255
+
256
+ `effort` is the portable control. It maps to OpenAI `reasoning_effort` and the Responses `reasoning`
257
+ field, Anthropic extended thinking, and Gemini `thinkingConfig`. Use `reasoning.maxTokens` when you
258
+ want to set a thinking budget directly instead of by level.
259
+
260
+ Requesting a summary emits `reasoning` stream chunks, which stay separate from visible output:
261
+
262
+ ```ts
263
+ for await (const chunk of ai.stream({ model: 'auto', messages, reasoning: { summary: 'auto' } })) {
264
+ if (chunk.type === 'reasoning') process.stderr.write(chunk.content ?? '');
265
+ if (chunk.type === 'text') process.stdout.write(chunk.content ?? '');
266
+ }
267
+ ```
268
+
269
+ ### Prompt Caching
270
+
271
+ Providers charge far less for a prompt prefix they have already processed. `mode: 'auto'` is the
272
+ default and reports whatever the provider reused on its own. `mode: 'explicit'` sends caller-placed
273
+ breakpoints to providers that accept them, such as Anthropic:
274
+
275
+ ```ts
276
+ const response = await ai.complete({
277
+ model: 'anthropic/best',
278
+ cache: { mode: 'explicit', ttl: '1h' },
279
+ messages: [
280
+ { role: 'system', content: longPolicyDocument, cache: true },
281
+ { role: 'user', content: 'Does clause 14 apply here?' },
282
+ ],
283
+ });
284
+
285
+ console.log(response.meta.usage?.cachedReadTokens);
286
+ console.log(response.meta.cost?.amount);
287
+ ```
288
+
289
+ Mark the end of the stable prefix, not every message. A provider caps how many breakpoints it
290
+ accepts (Anthropic allows four); when there are more marks than slots, the deepest ones are kept,
291
+ because a deeper breakpoint caches strictly more of the prompt.
292
+
293
+ ### Usage and Cost
294
+
295
+ Every response carries a numeric cost and a full token breakdown:
296
+
297
+ ```ts
298
+ const { usage, cost } = response.meta;
299
+
300
+ console.log(usage?.inputTokens); // billed at the standard input rate
301
+ console.log(usage?.cachedReadTokens); // served from the provider cache
302
+ console.log(usage?.cachedWriteTokens); // written into the provider cache
303
+ console.log(usage?.reasoningTokens); // share of output spent on reasoning
304
+ console.log(cost?.amount, cost?.currency, cost?.basis);
305
+ ```
306
+
307
+ `meta.tokensInput` keeps its original meaning of every prompt token, cached or not.
308
+ `meta.estimatedCost` is deprecated in favor of `cost.amount`. Bundled prices are defaults, not
309
+ financial truth; override them with `models.registry`, or adjust cache rates with
310
+ `models.cachePricing`.
311
+
312
+ ### Capability Negotiation
313
+
314
+ Requests are reconciled against the routed model before the provider is called:
315
+
316
+ ```ts
317
+ const ai = new NexusAI({
318
+ providers: { openai: { apiKey: process.env.OPENAI_API_KEY! } },
319
+ capabilities: { policy: 'warn' }, // 'strict' | 'warn' (default) | 'off'
320
+ });
321
+
322
+ const response = await ai.complete({ model: 'auto', messages, seed: 7 });
323
+ console.log(response.meta.capabilityWarnings);
324
+ ```
325
+
326
+ - `strict` throws a `NexusCapabilityError` before spending anything.
327
+ - `warn` drops or clamps the option and records it on `meta.capabilityWarnings`.
328
+ - `off` sends the request exactly as written.
329
+
330
+ An option a model does not declare is always passed through — absence means the registry does not
331
+ know, not that the provider refuses — so a model you register yourself is never restricted by fields
332
+ it omits. Set `capabilityPolicy: 'off'` on a single request to reach a provider feature that is
333
+ newer than the bundled registry.
334
+
335
+ Registry provenance is inspectable, and a release check can fail on stale data:
336
+
337
+ ```ts
338
+ import { describeModel, assertRegistryFreshness } from 'nexus-ai-pro';
339
+
340
+ console.log(describeModel('anthropic/best'));
341
+ // { model: 'claude-opus-4-8', verifiedAt: '…', alias: { stage: 'stable', floating: true }, … }
342
+
343
+ assertRegistryFreshness({ maxAgeDays: 120 });
344
+ ```
345
+
346
+ A `floating` alias resolves by intent rather than to a pinned model, so its target can change between
347
+ releases. Pin the resolved model when a run has to be reproducible.
243
348
 
244
349
  ### Streaming
245
350
 
@@ -254,7 +359,9 @@ for await (const chunk of stream) {
254
359
  }
255
360
  ```
256
361
 
257
- All providers normalize streaming chunks to `text`, `tool_call`, `done`, or `error`.
362
+ All providers normalize streaming chunks to `text`, `reasoning`, `tool_call`, `done`, or `error`.
363
+ Reasoning summaries only arrive when the request asks for them, so a consumer that switches on
364
+ `chunk.type` keeps receiving visible output only.
258
365
 
259
366
  When security is enabled, output streams are correctness-first: Nexus buffers and validates the
260
367
  complete output before yielding any chunk, up to 1 MiB or 100,000 chunks. This prevents secrets,
@@ -1022,6 +1129,7 @@ import { NexusAI } from 'nexus-ai-pro/core';
1022
1129
  import { createNexusConfig } from 'nexus-ai-pro/config';
1023
1130
  import { TokenOptimizer } from 'nexus-ai-pro/optimizer';
1024
1131
  import { ContextWindowManager } from 'nexus-ai-pro/context';
1132
+ import { negotiateCompletionRequest } from 'nexus-ai-pro/capabilities';
1025
1133
  import { guardrailPolicy } from 'nexus-ai-pro/security';
1026
1134
  import { RedisCacheAdapter } from 'nexus-ai-pro/cache';
1027
1135
  import { DeepSeekProvider } from 'nexus-ai-pro/providers/deepseek';
@@ -1086,10 +1194,12 @@ npm run test:conformance:real
1086
1194
 
1087
1195
  ## Roadmap
1088
1196
 
1089
- The experimental image foundation now includes portable asset types, `ImageManager`, provider
1090
- capability negotiation, local operation handles, visual-safety hooks, deterministic conformance, and an
1091
- opt-in OpenAI adapter. Durable operations, production asset storage, additional providers, and
1092
- media-specific evaluations remain planned in [ROADMAP.md](./ROADMAP.md).
1197
+ 1.4.0 closed the completion-request gap: prompt caching, reasoning controls, tool and sampling
1198
+ controls, structured usage with numeric cost, and capability negotiation with registry provenance.
1199
+
1200
+ Next is durable execution — an operation state machine, provider batch APIs, distributed rate
1201
+ limiting and circuit breaking, first-class embeddings, and filesystem/S3 asset stores — followed by
1202
+ image portability and promotion out of experimental. See [ROADMAP.md](./ROADMAP.md).
1093
1203
 
1094
1204
  ## Production Notes
1095
1205