nexus-ai-pro 2.16.0 → 2.18.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 (92) hide show
  1. package/API_STABILITY.md +57 -0
  2. package/CHANGELOG.md +131 -1
  3. package/README.md +10 -4
  4. package/dist/agent/capabilities.d.ts +3 -0
  5. package/dist/evaluate/media.d.ts +6 -2
  6. package/dist/evaluate/media.js +7 -21
  7. package/dist/index.d.ts +1 -1
  8. package/dist/mcp/client.d.ts +86 -4
  9. package/dist/mcp/client.js +191 -18
  10. package/dist/mcp/index.d.ts +2 -2
  11. package/dist/mcp/index.js +2 -2
  12. package/dist/mcp/server.d.ts +13 -1
  13. package/dist/mcp/server.js +28 -6
  14. package/dist/protocols/acp-editor.d.ts +16 -2
  15. package/dist/protocols/acp-editor.js +56 -17
  16. package/dist/protocols/acp.d.ts +8 -0
  17. package/dist/protocols/acp.js +1 -0
  18. package/dist/router/failover.js +19 -1
  19. package/dist/server/index.d.ts +1 -0
  20. package/dist/server/list-page.d.ts +38 -0
  21. package/dist/server/list-page.js +49 -0
  22. package/dist/server/regions.d.ts +15 -1
  23. package/dist/server/regions.js +70 -0
  24. package/dist/server/runs.d.ts +24 -0
  25. package/dist/server/runs.js +18 -4
  26. package/dist/server/server.js +17 -5
  27. package/dist/tracing/index.d.ts +2 -2
  28. package/dist/tracing/instrument.d.ts +7 -2
  29. package/dist/tracing/instrument.js +69 -2
  30. package/dist/tracing/otlp-proto.js +18 -0
  31. package/dist/tracing/otlp.d.ts +26 -1
  32. package/dist/tracing/otlp.js +19 -0
  33. package/dist/tracing/tracer.d.ts +36 -1
  34. package/dist/tracing/tracer.js +68 -2
  35. package/dist/types/response.d.ts +18 -0
  36. package/dist/types/tracing.d.ts +32 -0
  37. package/dist/utils/media-duration.d.ts +20 -0
  38. package/dist/utils/media-duration.js +334 -0
  39. package/dist/version.d.ts +1 -1
  40. package/dist/version.js +1 -1
  41. package/dist/video/google.d.ts +50 -11
  42. package/dist/video/google.js +270 -19
  43. package/dist/video/index.d.ts +64 -6
  44. package/dist/video/index.js +134 -15
  45. package/dist/video/mock.js +12 -1
  46. package/dist/video/runway.d.ts +10 -1
  47. package/dist/video/runway.js +102 -2
  48. package/dist-cjs/agent/capabilities.d.ts +3 -0
  49. package/dist-cjs/evaluate/media.d.ts +6 -2
  50. package/dist-cjs/evaluate/media.js +9 -21
  51. package/dist-cjs/index.d.ts +1 -1
  52. package/dist-cjs/mcp/client.d.ts +86 -4
  53. package/dist-cjs/mcp/client.js +193 -18
  54. package/dist-cjs/mcp/index.d.ts +2 -2
  55. package/dist-cjs/mcp/index.js +4 -1
  56. package/dist-cjs/mcp/server.d.ts +13 -1
  57. package/dist-cjs/mcp/server.js +29 -6
  58. package/dist-cjs/protocols/acp-editor.d.ts +16 -2
  59. package/dist-cjs/protocols/acp-editor.js +55 -16
  60. package/dist-cjs/protocols/acp.d.ts +8 -0
  61. package/dist-cjs/protocols/acp.js +1 -0
  62. package/dist-cjs/router/failover.js +19 -1
  63. package/dist-cjs/server/index.d.ts +1 -0
  64. package/dist-cjs/server/list-page.d.ts +38 -0
  65. package/dist-cjs/server/list-page.js +56 -0
  66. package/dist-cjs/server/regions.d.ts +15 -1
  67. package/dist-cjs/server/regions.js +70 -0
  68. package/dist-cjs/server/runs.d.ts +24 -0
  69. package/dist-cjs/server/runs.js +18 -4
  70. package/dist-cjs/server/server.js +17 -5
  71. package/dist-cjs/tracing/index.d.ts +2 -2
  72. package/dist-cjs/tracing/instrument.d.ts +7 -2
  73. package/dist-cjs/tracing/instrument.js +69 -2
  74. package/dist-cjs/tracing/otlp-proto.js +18 -0
  75. package/dist-cjs/tracing/otlp.d.ts +26 -1
  76. package/dist-cjs/tracing/otlp.js +19 -0
  77. package/dist-cjs/tracing/tracer.d.ts +36 -1
  78. package/dist-cjs/tracing/tracer.js +68 -2
  79. package/dist-cjs/types/response.d.ts +18 -0
  80. package/dist-cjs/types/tracing.d.ts +32 -0
  81. package/dist-cjs/utils/media-duration.d.ts +20 -0
  82. package/dist-cjs/utils/media-duration.js +337 -0
  83. package/dist-cjs/version.d.ts +1 -1
  84. package/dist-cjs/version.js +1 -1
  85. package/dist-cjs/video/google.d.ts +50 -11
  86. package/dist-cjs/video/google.js +269 -18
  87. package/dist-cjs/video/index.d.ts +64 -6
  88. package/dist-cjs/video/index.js +134 -15
  89. package/dist-cjs/video/mock.js +12 -1
  90. package/dist-cjs/video/runway.d.ts +10 -1
  91. package/dist-cjs/video/runway.js +102 -2
  92. package/package.json +1 -1
package/API_STABILITY.md CHANGED
@@ -41,6 +41,63 @@ Both are covered by this policy:
41
41
  Deep imports into `dist`, `dist-cjs`, or `src` are not supported. Import only from `nexus-ai-pro` or
42
42
  one of its explicit subpaths.
43
43
 
44
+ ## 2.18 stage (2.18.0)
45
+
46
+ Everything 2.18 adds is stable from the start and additive, unless this section says otherwise.
47
+
48
+ New and stable:
49
+ - in `nexus-ai-pro/tracing`: `RunEvent`, `RunLink`, `RunAttributeValue`, `RunEventInput`, `RunLinkInput`,
50
+ `Run.events`, `droppedEvents`, and `links`, `Tracer.event()`, `RunHandle.event()` and `link()`,
51
+ `StartRunOptions.links`, `FinishRunOptions.events` and `links`, `TracerOptions.maxEventsPerRun`, and
52
+ the event names `retry`, `failover`, `progress`, `guardrail`, `cache`, and `capability_warning`;
53
+ - in `nexus-ai-pro/tracing/otlp`: `OtlpSpanEvent`, `OtlpSpanLink`, and `OtlpSpan.events`,
54
+ `droppedEventsCount`, and `links`;
55
+ - in the root: `ResponseAttempt` and `ResponseMeta.failedAttempts`;
56
+ - in `nexus-ai-pro/evaluate/media`: `readMediaDuration()` and `MediaDuration`;
57
+ - in `nexus-ai-pro/video`, experimental with the family: `VideoModelCapabilities.maxInputVideoSeconds`;
58
+ - in `nexus-ai-pro/server/regions`: `RegionalGatewayOptions.lists`, `RegionListGap`, and a merged
59
+ list's `regions`, `incomplete`, and `nextCursor`;
60
+ - in `nexus-ai-pro/server`: `ListPage`, `RunManager.listThreads()` and `listRuns()`, and the lists'
61
+ `cursor` and `nextCursor`;
62
+ - in `nexus-ai-pro/mcp`: `McpClientOptions.reconnect`, `McpClient.onToolsChanged()`, and
63
+ `SseClientOptions.reopen`;
64
+ - in `nexus-ai-pro/video`, experimental with the family: `VideoGenerateRequest.referenceVideos` and
65
+ `VideoProviderRequest.referenceVideos`, the `reference-videos` input kind,
66
+ `VideoModelCapabilities.maxReferenceVideos` and `referenceVideoSeconds`, and
67
+ `VideoConformanceOptions.referenceVideo`;
68
+ - in `nexus-ai-pro/video/google`, experimental with the family:
69
+ `GoogleVideoProviderConfig.interactionsBaseUrl`, and Gemini Omni Flash on Vertex AI.
70
+
71
+ Changed on purpose:
72
+ - a list through the regional gateway is merged from every region the tenant may reach;
73
+ `lists: 'home'` keeps the earlier answer;
74
+ - an agent server's lists are ordered by last write, then id, and a `limit` that is not a whole
75
+ number above 0 is refused;
76
+ - `McpServer` says `tools.listChanged`, and `register()` sends the notification;
77
+ - `VideoInputKind` widens with `reference-videos`.
78
+
79
+ ## 2.17 stage (2.17.0)
80
+
81
+ Everything 2.17 adds is stable from the start and additive, unless this section says otherwise.
82
+
83
+ New and stable:
84
+ - in `nexus-ai-pro/mcp`: `createSseTransport()`, `SseClientOptions`, `mcpToolCapabilities()`,
85
+ `mcpToolAnnotations()`, `McpToolAnnotations`, `McpToolsOptions`, and `McpToolDescriptor.annotations`;
86
+ the capability kinds `mcp.read`, `mcp.write`, and `mcp.destructive`;
87
+ - in `nexus-ai-pro/protocols/acp/editor`: `AcpEditorOptions.mcpToolCapabilities` and
88
+ `AcpEditor.mcpCapabilities`; in `nexus-ai-pro/protocols/acp`: `AcpEditorBridge.mcpCapabilities`;
89
+ - in `nexus-ai-pro/video`, experimental with the family: `VideoSource`, `VideoGenerateRequest.video`,
90
+ `VideoProviderRequest.video`, the `VideoInputKind` values `extend` and `edit`,
91
+ `VideoModelCapabilities.extendDurations`, `requires`, and `continuesJobs`,
92
+ `VideoProviderCapabilities.inputVideoMimeTypes`, and `VideoConformanceOptions.video`; Gemini Omni
93
+ Flash in `nexus-ai-pro/video/google`, and video to video in `nexus-ai-pro/video/runway`.
94
+
95
+ Changed on purpose: `acpEditor()` reads MCP tool annotations by default. A policy that allowed the
96
+ editor's MCP tools as undeclared (`undeclared: 'allow'`) now decides annotated tools by their
97
+ capabilities; `mcpToolCapabilities: false` keeps the earlier decisions. `GoogleVideoProvider`'s
98
+ default models follow Google's shutdown of the Veo 3.1 previews: Gemini Omni Flash on the Gemini API,
99
+ and the generally available Veo 3.1 models on Vertex AI.
100
+
44
101
  ## 2.16 stage (2.16.0)
45
102
 
46
103
  Everything 2.16 adds is stable from the start and additive, unless this section says otherwise.
package/CHANGELOG.md CHANGED
@@ -4,6 +4,134 @@ Notable changes to this project are recorded here. The format follows [Keep a Ch
4
4
 
5
5
  ## [Unreleased]
6
6
 
7
+ ## [2.18.0] - 2026-10-22
8
+
9
+ Span events and links, media that knows its length, a tenant's threads and runs listed and paged
10
+ across all of its regions, MCP servers that reconnect and change their tools mid-session, and videos
11
+ made after reference videos.
12
+
13
+ ### Added
14
+
15
+ - **Span events and links.** A run records what happened inside it as `RunEvent` values, each at its
16
+ time, and the runs it came from beside its parent as `RunLink` values. `Tracer.event()` records on
17
+ the run in scope, `RunHandle.event()` and `link()` on one run; `StartRunOptions.links` take a link
18
+ or a W3C `traceparent`, and `FinishRunOptions` take the `events` and `links` a run learns as it
19
+ ends. `maxEventsPerRun` (128) keeps a run's events bounded, counting the rest as `droppedEvents`.
20
+ Both reach OTLP as span events and links, in JSON, in protobuf, and over gRPC. The studio shows them
21
+ on a run, each link opening the run it names, and `#/traces/<trace>/<run>` opens one run of a trace.
22
+ - **Events where they happen.** A graph's retry is a `retry` event of its task's run, a tool's
23
+ progress a `progress` event of the tool's, and a task after a step of several, such as a fan-out's
24
+ join, links to each of them. A model run has the attempts that failed before its answer, as `retry`
25
+ and `failover` at the times they failed, and its guardrails, cache answer, and capability warnings.
26
+ - **Failed attempts on the response.** `ResponseMeta.failedAttempts` lists each `ResponseAttempt` that
27
+ failed before the answer: its provider, model, error, category, and time; a stream's last chunk
28
+ carries them too.
29
+ - **Media that knows its length.** `readMediaDuration()`, on `nexus-ai-pro/evaluate/media`, reads the
30
+ length of WAV, MP4 and MOV (fragmented MP4 included), WebM and Matroska, MP3, Ogg Vorbis and Opus,
31
+ and FLAC from their own headers, with no dependency. `mediaChecks()` holds audio and video to a
32
+ `durationMs` range with it, and a video model's `maxInputVideoSeconds` refuses a longer video before
33
+ it is sent: 10 seconds on Gemini Omni Flash, 30 on Veo.
34
+ - **Lists across regions.** The regional gateway answers `GET /threads` and `GET /runs` from every
35
+ region the tenant may reach, merged newest first and cut to the limit, naming the regions that
36
+ answered and, as `RegionListGap` values under `incomplete`, those that were down or failed. A
37
+ refusal every region gives is the answer. `lists: 'home'` keeps the home region's list alone.
38
+ - **Lists that page.** An agent server's `GET /threads`, `GET /runs`, and `GET /threads/:id/runs`
39
+ take a `cursor` and answer with a `nextCursor` while more follow; `RunManager.listThreads()` and
40
+ `listRuns()` return a `ListPage`. A cursor names a place in the order every region lists by, so the
41
+ regional gateway pages a merged list with it too, each record once, in order, however the records
42
+ fall between regions. A region that does not page by it contributes only what comes after it.
43
+ - **MCP that reconnects.** With `McpClientOptions.reconnect`, a client whose connection closed opens
44
+ it again at the next request and greets the server again: an SSE stream that ended, with
45
+ `SseClientOptions.reopen`, or a stdio server that exited, started again. A stream that cannot open,
46
+ or names no endpoint in time, is let go at once, so the next request tries again.
47
+ - **Tools that change.** `McpClient.onToolsChanged()` hears a server's
48
+ `notifications/tools/list_changed`. `McpServer.register()` sends one to a connected client, and the
49
+ server says it will. The editor bridge reconnects an editor's SSE servers within a session and lists
50
+ a server's tools again before the turn after it says they changed, keeping the last list when that
51
+ fails.
52
+ - **Reference videos.** `VideoGenerateRequest.referenceVideos` gives a model videos to take after.
53
+ Models declare `reference-videos` among their inputs, with `maxReferenceVideos` and
54
+ `referenceVideoSeconds`, each and together, read from a video's headers before it is sent. Gemini
55
+ Omni Flash takes three of three seconds each, as does Runway's `gemini_omni_flash_1.1`; Runway's
56
+ Seedance 2 models, `hailuo3`, and `wan3` take 15 seconds together, beside reference images. The
57
+ conformance suite checks them with `referenceVideo`.
58
+ - **Gemini Omni Flash on Vertex AI.** `GoogleVideoProvider` serves `gemini-omni-1.1-flash-preview` on
59
+ Vertex AI's Interactions API, at the global location for the project its `baseUrl` names, or at
60
+ `interactionsBaseUrl`.
61
+
62
+ ### Changed
63
+
64
+ - A list of threads or runs through the regional gateway comes from every region the tenant may
65
+ reach, not its home region alone; `RegionalGatewayOptions.lists: 'home'` keeps the 2.17 answer.
66
+ - An agent server lists threads and runs by when each was last written, then by id, the order its
67
+ cursor pages by. A `limit` that is not a whole number above 0 is refused with a 400.
68
+ - `McpServer` says its tools change, as `tools.listChanged`, and `register()` tells a connected
69
+ client.
70
+ - `VideoInputKind` has `reference-videos`; a `switch` over it that names every kind needs the new one.
71
+ - Tested on Node.js 26 as well as 22 and 24: CI runs the release gate on each, on the newest patch of
72
+ its line, so a Node.js security release, such as 2026-10-21's, is what the package is tested and
73
+ published on the day it ships.
74
+
75
+ ### Fixed
76
+
77
+ - A tenant's threads and runs on a server several tenants share: a list read the newest records of
78
+ every tenant and then kept the tenant's, so another tenant's newer ones could crowd its page out,
79
+ down to an empty one. A list now reads until the tenant's page is full.
80
+ - The studio showed a run's metadata, its feedback, and a tool's progress as
81
+ `[object HTMLHeadingElement]` rather than their content.
82
+
83
+ ## [2.17.0] - 2026-10-21
84
+
85
+ The editor's MCP servers over every transport, decided by what their servers say they do; and video
86
+ extended or edited on every provider, with Gemini Omni Flash on Google's Interactions API.
87
+
88
+ ### Added
89
+
90
+ - **Video extended or edited.** A `VideoGenerateRequest` takes a `video`, a `VideoSource`: `extend`
91
+ continues it, and `edit` changes it as the prompt says. The video is an input (bytes, a URL, or a
92
+ stored asset), or `from` a finished job of the same provider, which continues from what it holds
93
+ with nothing uploaded. Models declare `extend` and `edit` among their `inputs`, with
94
+ `extendDurations`, `continuesJobs`, and `requires`, and providers their `inputVideoMimeTypes`;
95
+ anything a model cannot do is refused before it is sent, and the input travels with a durable
96
+ generation. The conformance suite checks extending and editing, and continuing a job.
97
+ - **Gemini Omni Flash on the Interactions API.** `GoogleVideoProvider` serves `gemini-omni-1.1-flash`
98
+ as a background interaction: 3 to 10 seconds at 360p to 4k, from a prompt, a first frame, or
99
+ reference images, extending and editing videos, continuing its own interactions by id, cancelled and
100
+ deleted with them. It is priced at its 720p token rate.
101
+ - **Veo extends on Vertex AI.** Veo 3.1 extends a video in Cloud Storage by seven seconds, or a job of
102
+ its own when `storageUri` keeps its videos there, and makes up to four videos a request.
103
+ - **Runway's video to video.** `gemini_omni_flash_1.1` extends and edits, `gemini_omni_flash` edits,
104
+ and `aleph2`, now among the models, only edits, from a video by URL, inline up to 5 MB, or a task's
105
+ own video.
106
+
107
+ - **MCP over SSE.** `createSseTransport()`, on `nexus-ai-pro/mcp`, speaks to a server over HTTP with
108
+ Server-Sent Events, MCP's transport before streamable HTTP: one `GET` on the event stream, a `POST`
109
+ per message to the endpoint the stream names, kept to the stream's origin. An ACP agent connects the
110
+ SSE servers an editor offers, beside stdio and HTTP.
111
+ - **MCP tools that declare what they do.** `toNexusTools({ capabilities: true })` gives each tool the
112
+ capabilities its server's annotations describe, from `mcpToolCapabilities()`: `mcp.read`,
113
+ `mcp.write`, or `mcp.destructive` under the server's name, and `network` for one that reaches
114
+ beyond it, with the specification's defaults for a hint left out. A permission policy then decides a
115
+ server's tools as it decides the agent's own: `{ custom: { 'mcp.read': 'allow' } }` runs a lookup
116
+ and refuses a delete, with no rule naming either. A function decides per tool instead.
117
+ - **The package's MCP server says what its tools do.** `McpServer` lists each tool with the
118
+ annotations its capabilities give it, from `mcpToolAnnotations()`, never claiming less than the
119
+ tool may do.
120
+
121
+ ### Changed
122
+
123
+ - **Google's video defaults follow its shutdown of the Veo 3.1 previews on 2026-10-22.** On the Gemini
124
+ API, `GoogleVideoProvider` serves Gemini Omni Flash by default; on Vertex AI, the generally
125
+ available `veo-3.1-generate-001` and `veo-3.1-fast-generate-001`, and `veo-3.1-lite-generate-001`.
126
+ Name the preview models in `models` to keep them until Google stops serving them.
127
+ - `acpEditor()` reads its MCP servers' annotations by default (`mcpToolCapabilities`), so an
128
+ annotated tool is decided by its capabilities rather than as undeclared; `mcpToolCapabilities: false`
129
+ keeps the 2.16 behaviour. A tool its server says nothing about is undeclared, as before.
130
+ - The ACP agent tells the editor, in `initialize`, that it connects MCP servers over HTTP and SSE, so
131
+ an editor that follows the protocol offers them; before, it offered only stdio servers.
132
+ - The nightly interoperability check offers the ACP agent MCP servers built with
133
+ `@modelcontextprotocol/sdk` over stdio, HTTP, and SSE.
134
+
7
135
  ## [2.16.0] - 2026-10-20
8
136
 
9
137
  A2A on all three of its bindings over one set of tasks, and webhooks told the answer as it is written.
@@ -3051,7 +3179,9 @@ shared policy vocabulary is in place for a future release that revisits this.
3051
3179
  - URL fetching rejects unsafe private-network targets and limits response reads.
3052
3180
  - CLI and audit findings no longer disclose detected secret values.
3053
3181
 
3054
- [Unreleased]: https://github.com/mkhitar-abrahamyan/nexus-ai/compare/v2.16.0...HEAD
3182
+ [Unreleased]: https://github.com/mkhitar-abrahamyan/nexus-ai/compare/v2.18.0...HEAD
3183
+ [2.18.0]: https://github.com/mkhitar-abrahamyan/nexus-ai/compare/v2.17.0...v2.18.0
3184
+ [2.17.0]: https://github.com/mkhitar-abrahamyan/nexus-ai/compare/v2.16.0...v2.17.0
3055
3185
  [2.16.0]: https://github.com/mkhitar-abrahamyan/nexus-ai/compare/v2.15.1...v2.16.0
3056
3186
  [2.15.1]: https://github.com/mkhitar-abrahamyan/nexus-ai/compare/v2.15.0...v2.15.1
3057
3187
  [2.15.0]: https://github.com/mkhitar-abrahamyan/nexus-ai/compare/v2.14.0...v2.15.0
package/README.md CHANGED
@@ -324,13 +324,19 @@ Shipped so far:
324
324
  [page](https://github.com/mkhitar-abrahamyan/nexus-ai/blob/main/COMPATIBILITY.md) lists them;
325
325
  - 2.16 A2A over every binding: one agent served over JSON-RPC, HTTP+JSON, and gRPC from one task
326
326
  store, so a caller on any binding continues a task another started, and webhooks told the answer
327
- as it is written.
327
+ as it is written;
328
+ - 2.17 the editor's MCP servers over every transport, and video you can extend or edit: an ACP agent
329
+ connects stdio, HTTP, and SSE servers and decides each tool by what its server says it does, and a
330
+ video is extended from its own job or edited on Gemini Omni Flash, Veo, and Runway;
331
+ - 2.18 span events and links, as OpenTelemetry has them, media that knows its length from its own
332
+ headers, a tenant's threads and runs listed and paged across all of its regions, MCP servers that
333
+ reconnect and change their tools within a session, and videos made after reference videos.
328
334
 
329
335
  Upgrading from 1.x: `npx nexus migrate src --write` moves your imports, and
330
336
  [MIGRATING.md](https://github.com/mkhitar-abrahamyan/nexus-ai/blob/main/MIGRATING.md) covers the rest.
331
- Next, 2.17 connects the MCP servers an editor gives an ACP agent over SSE as well as stdio and HTTP,
332
- and reads what their tools declare they do, so a permission policy covers them without a rule for
333
- each. Pinecone, images, the Gemini
337
+ Next, 2.19 reads a service's own API description into emulated tools, and lets an emulator hold
338
+ what a whole evaluation did, so examples that build on each other are evaluated with nothing sent.
339
+ Pinecone, images, the Gemini
334
340
  embedding batch tier, media understanding, video, Gemini Live, SIP, and both phone providers
335
341
  graduate once the live workflow passes against each. The
336
342
  [roadmap](https://github.com/mkhitar-abrahamyan/nexus-ai/blob/main/ROADMAP.md) lists what comes after, in the order
@@ -9,6 +9,9 @@ import type { ToolDefinition } from '../types/messages.js';
9
9
  * | `network`, `network:<host or URL>` | Opens a network connection, to a host when given |
10
10
  * | `shell`, `shell:<command line>` | Runs a shell command |
11
11
  * | `code` | Runs code it was given, as an interpreter does |
12
+ * | `mcp.read:<server>/<tool>` | An MCP tool its server says only reads |
13
+ * | `mcp.write:<server>/<tool>` | An MCP tool its server says changes things but destroys nothing |
14
+ * | `mcp.destructive:<server>/<tool>` | An MCP tool its server says may destroy or overwrite |
12
15
  * | `<name>`, `<name>:<detail>` | Anything the application names, such as `payments:refund` |
13
16
  *
14
17
  * A tool that declares `capabilities: []` does nothing to the world; one that declares none at all
@@ -5,6 +5,7 @@
5
5
  */
6
6
  import { type JudgeClient } from '../evals/judge.js';
7
7
  import type { EvaluationContext, Evaluator, MediaPart } from '../types/evaluate.js';
8
+ export { type MediaDuration, readMediaDuration } from '../utils/media-duration.js';
8
9
  /** What kind of medium something is. */
9
10
  export type MediaSubjectKind = 'image' | 'audio' | 'video' | 'document' | 'other';
10
11
  /** A medium read for judging: what it is, and as much of it as could be read. */
@@ -27,7 +28,10 @@ export interface ResolvedMedia {
27
28
  width?: number;
28
29
  /** Height in pixels. */
29
30
  height?: number;
30
- /** Duration in milliseconds, read from a WAV header. */
31
+ /**
32
+ * Duration in milliseconds, read from the file's own headers: WAV, MP4 and MOV, WebM and Matroska,
33
+ * MP3, Ogg (Vorbis and Opus), and FLAC.
34
+ */
31
35
  durationMs?: number;
32
36
  /** Why its bytes could not be read, when they could not. */
33
37
  unreadable?: string;
@@ -93,7 +97,7 @@ export interface MediaCheckOptions extends MediaResolveOptions, MediaSelection {
93
97
  ratio: number;
94
98
  tolerance?: number;
95
99
  };
96
- /** The duration in milliseconds allowed, for audio whose header says it. */
100
+ /** The duration in milliseconds allowed, for audio or video whose headers say it. */
97
101
  durationMs?: MediaRange;
98
102
  /** A medium whose measurement could not be read passes or fails that check. Defaults to `fail`. */
99
103
  unknown?: 'pass' | 'fail';
@@ -4,6 +4,8 @@ import { decodeBase64, encodeBase64 } from '../utils/base64.js';
4
4
  import { sha256Hex } from '../utils/sha256.js';
5
5
  import { withProvenance } from './provenance.js';
6
6
  import { asMediaPart, mediaParts } from './trace.js';
7
+ import { readMediaDuration } from '../utils/media-duration.js';
8
+ export { readMediaDuration } from '../utils/media-duration.js';
7
9
  export function mediaOf(context, from = 'output') {
8
10
  const traced = (direction) => (context.trace?.media ?? []).filter((item) => item.direction === direction).map((item) => item.part);
9
11
  const output = () => {
@@ -65,11 +67,11 @@ export async function resolveMedia(part, options = {}) {
65
67
  resolved.kind = 'document';
66
68
  }
67
69
  else {
68
- const wav = wavDuration(bytes);
69
- if (wav !== undefined) {
70
- resolved.mimeType = 'audio/wav';
71
- resolved.kind = 'audio';
72
- resolved.durationMs = wav;
70
+ const read = readMediaDuration(bytes);
71
+ if (read) {
72
+ resolved.mimeType = read.mimeType;
73
+ resolved.kind = read.kind;
74
+ resolved.durationMs = read.durationMs;
73
75
  }
74
76
  }
75
77
  }
@@ -410,22 +412,6 @@ function mimeMatches(pattern, mimeType) {
410
412
  return mimeType.startsWith(pattern.slice(0, -1));
411
413
  return pattern === mimeType;
412
414
  }
413
- function wavDuration(bytes) {
414
- if (!startsWith(bytes, 'RIFF') || ascii(bytes, 8, 4) !== 'WAVE')
415
- return undefined;
416
- const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
417
- let byteRate;
418
- for (let at = 12; at + 8 <= bytes.length;) {
419
- const id = ascii(bytes, at, 4);
420
- const size = view.getUint32(at + 4, true);
421
- if (id === 'fmt ' && at + 16 <= bytes.length)
422
- byteRate = view.getUint32(at + 16, true);
423
- if (id === 'data')
424
- return byteRate ? Math.round((size / byteRate) * 1000) : undefined;
425
- at += 8 + size + (size % 2);
426
- }
427
- return undefined;
428
- }
429
415
  function startsWith(bytes, text) {
430
416
  return ascii(bytes, 0, text.length) === text;
431
417
  }
package/dist/index.d.ts CHANGED
@@ -20,7 +20,7 @@ export { tool, toolOutput } from './agent/tool.js';
20
20
  export type { CacheHint, CompletionRequest, Message, MessageRole, ContentPart, PromptCacheConfig, ReasoningConfig, TextContent, ImageContent, AudioContent, BinaryBuffer, VideoContent, AssetContent, ToolChoice, ToolDefinition, ToolCallResult, ToolOutput, } from './types/messages.js';
21
21
  export type { CapabilityConfig, CapabilityPolicy, CapabilityWarning, CapabilityWarningAction, } from './types/capabilities.js';
22
22
  export type { CostEstimate, NexusPlan, } from './types/planning.js';
23
- export type { NexusResponse, NexusStream, ResponseCost, ResponseMeta, StreamChunk, TokenUsage, ToolCall, } from './types/response.js';
23
+ export type { NexusResponse, NexusStream, ResponseAttempt, ResponseCost, ResponseMeta, StreamChunk, TokenUsage, ToolCall, } from './types/response.js';
24
24
  export type { NexusAIConfig, ProvidersConfig, OpenAIProviderConfig, AnthropicProviderConfig, GoogleProviderConfig, OllamaProviderConfig, GroqProviderConfig, MistralProviderConfig, CohereProviderConfig, CustomProviderConfig, DeepSeekProviderConfig, AzureOpenAIProviderConfig, LMStudioProviderConfig, LlamaCppProviderConfig, RoutingConfig, RoutingRule, RoutingStrategy, FallbackConfig, ResponseFormatConfig, RetryConfig, CostBudgetConfig, AuditLogConfig, AuditLogEvent, LoggerConfig, LogEvent, LogLevel, RateLimitConfig, } from './types/config.js';
25
25
  export type { ContextSummaryConfig, ContextSummaryInput, ContextSummaryMode, ContextSummarizer, ContextWindowConfig, ContextWindowResult, ContextWindowStrategy, ContextWindowUsage, } from './types/context-window.js';
26
26
  export type { AliasMetadata, AliasStage, CacheTtl, InputModality, ModelCapabilities, ModelEndpoint, ModelStatus, OutputModality, PromptCachingCapability, ProviderCapabilities, ReasoningEffort, RoutingModelPreference, } from './types/providers.js';
@@ -1,5 +1,21 @@
1
1
  import type { ToolDefinition } from '../types/messages.js';
2
2
  import { type McpTransport } from './protocol.js';
3
+ /**
4
+ * What a server says a tool does, as MCP's tool annotations: hints, which a client trusts only as far
5
+ * as it trusts the server. A hint left out takes the specification's default.
6
+ */
7
+ export interface McpToolAnnotations {
8
+ /** A name for people. */
9
+ title?: string;
10
+ /** It changes nothing. Defaults to false. */
11
+ readOnlyHint?: boolean;
12
+ /** When it changes things, it may destroy or overwrite them, not only add. Defaults to true. */
13
+ destructiveHint?: boolean;
14
+ /** Calling it again with the same arguments changes nothing more. Defaults to false. */
15
+ idempotentHint?: boolean;
16
+ /** It reaches things beyond the server, such as the web. Defaults to true. */
17
+ openWorldHint?: boolean;
18
+ }
3
19
  /** A tool an MCP server offers. */
4
20
  export interface McpToolDescriptor {
5
21
  /** The tool's name. */
@@ -8,6 +24,33 @@ export interface McpToolDescriptor {
8
24
  description?: string;
9
25
  /** JSON Schema for the arguments. */
10
26
  inputSchema?: Record<string, unknown>;
27
+ /** What the server says the tool does. */
28
+ annotations?: McpToolAnnotations;
29
+ }
30
+ /**
31
+ * The capabilities an MCP tool declares, from what its server says of it in its annotations, so a
32
+ * permission policy decides it as it decides any tool:
33
+ * - `mcp.read:<server>/<tool>` for a tool that only reads;
34
+ * - `mcp.write:<server>/<tool>` for one that changes things but destroys nothing;
35
+ * - `mcp.destructive:<server>/<tool>` for one that may destroy or overwrite;
36
+ * - and `network`, beside it, for one that reaches beyond its server.
37
+ *
38
+ * A hint left out takes the specification's default: not read-only, destructive, and open. A tool
39
+ * with no annotations at all declares nothing, `undefined`, so a policy decides it as undeclared.
40
+ */
41
+ export declare function mcpToolCapabilities(tool: McpToolDescriptor, server: string): string[] | undefined;
42
+ /** Options for `McpClient.toNexusTools()`. */
43
+ export interface McpToolsOptions {
44
+ /** Put before each tool's name with an underscore, so two servers' `search` tools differ. */
45
+ prefix?: string;
46
+ /**
47
+ * The capabilities each tool declares: `true` reads them from the server's annotations, with
48
+ * `mcpToolCapabilities()`, under the server's name (the prefix, or the name the server gives); a
49
+ * function decides them per tool. Without it, a tool declares none, as before 2.17.
50
+ */
51
+ capabilities?: boolean | ((tool: McpToolDescriptor) => readonly string[] | undefined);
52
+ /** The server's name in each capability, when `capabilities` is `true`. Defaults to the prefix. */
53
+ server?: string;
11
54
  }
12
55
  /** A resource an MCP server offers. */
13
56
  export interface McpResourceDescriptor {
@@ -48,6 +91,14 @@ export interface McpClientOptions {
48
91
  };
49
92
  /** How long a request waits before failing. Defaults to 30 seconds. */
50
93
  timeoutMs?: number;
94
+ /**
95
+ * When the transport closes, as an SSE stream that ends or a server process that exits does, the
96
+ * next request opens it again and repeats the handshake, since the server's session went with it.
97
+ * Requests in flight still fail, and a client closed with `close()` stays closed. Needs a transport
98
+ * that can open again: `createStdioTransport` starts a new process, `createSseTransport` with
99
+ * `reopen` a new stream.
100
+ */
101
+ reconnect?: boolean;
51
102
  }
52
103
  /**
53
104
  * Talks to an MCP server.
@@ -66,7 +117,15 @@ export declare class McpClient {
66
117
  private initialized;
67
118
  private connecting;
68
119
  private serverInfo;
120
+ /** Who hears that the server's tools changed. */
121
+ private readonly toolsChanged;
122
+ private stopped;
69
123
  constructor(transport: McpTransport, options?: McpClientOptions);
124
+ /**
125
+ * Hears each `notifications/tools/list_changed` the server sends: its tools are no longer what
126
+ * `listTools()` returned. Returns a function that stops hearing.
127
+ */
128
+ onToolsChanged(handler: () => void): () => void;
70
129
  /**
71
130
  * Performs the handshake and returns the server's name and version. Called automatically by the
72
131
  * first request that needs it; requests made together share one handshake.
@@ -109,9 +168,7 @@ export declare class McpClient {
109
168
  * Names are prefixed when asked, because two servers can both offer `search` and a model has to be
110
169
  * able to tell them apart.
111
170
  */
112
- toNexusTools(options?: {
113
- prefix?: string;
114
- }): Promise<ToolDefinition[]>;
171
+ toNexusTools(options?: McpToolsOptions): Promise<ToolDefinition[]>;
115
172
  /** Closes the connection and rejects every request still waiting. */
116
173
  close(): Promise<void>;
117
174
  private request;
@@ -149,7 +206,8 @@ export declare function serverEnvironment(source: Record<string, string | undefi
149
206
  * Runs an MCP server as a child process and speaks to it over its stdin and stdout.
150
207
  *
151
208
  * The transport most MCP servers ship with. `node:child_process` is imported lazily, so a browser
152
- * or edge build that only uses the HTTP transport never reaches for it.
209
+ * or edge build that only uses the HTTP transport never reaches for it. When the process exits, the
210
+ * transport closes; started again, it runs a new one.
153
211
  */
154
212
  export declare function createStdioTransport(options: StdioClientOptions): McpTransport;
155
213
  /** Connects to a remote MCP server over HTTP. */
@@ -168,3 +226,27 @@ export interface HttpClientOptions {
168
226
  * calling a tool needs.
169
227
  */
170
228
  export declare function createHttpTransport(options: HttpClientOptions): McpTransport;
229
+ /** Connects to a remote MCP server over HTTP with Server-Sent Events, the transport before streamable HTTP. */
230
+ export interface SseClientOptions {
231
+ /** The server's event stream: a `GET` here opens it, and the server names where to post messages. */
232
+ url: string;
233
+ /** Headers sent with the stream's request and with every message, such as authorization. */
234
+ headers?: Record<string, string>;
235
+ /** Replaces the global `fetch`. */
236
+ fetch?: typeof globalThis.fetch;
237
+ /** How long to wait for the server to name where messages go, in milliseconds. Defaults to 10 seconds. */
238
+ timeoutMs?: number;
239
+ /**
240
+ * Opens a new stream when the next message is sent after the stream ended, rather than staying
241
+ * closed. The server starts a new session on it, so an `McpClient` with `reconnect` greets it again.
242
+ */
243
+ reopen?: boolean;
244
+ }
245
+ /**
246
+ * Speaks to an MCP server over HTTP with Server-Sent Events, as MCP's 2024-11-05 transport: one
247
+ * long `GET` the server answers on, and a `POST` per message to the endpoint the stream names
248
+ * first. The endpoint must be on the stream's own origin, so a server cannot send the messages, and
249
+ * their headers, anywhere else. When the stream ends, the transport closes; with `reopen`, the next
250
+ * message opens a new one.
251
+ */
252
+ export declare function createSseTransport(options: SseClientOptions): McpTransport;