nexus-ai-pro 2.3.0 → 2.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.
- package/API_STABILITY.md +186 -0
- package/CHANGELOG.md +184 -1
- package/README.md +14 -5
- package/SECURITY.md +140 -0
- package/dist/adapter-kit/contracts.d.ts +87 -0
- package/dist/adapter-kit/contracts.js +237 -0
- package/dist/adapter-kit/errors.d.ts +39 -0
- package/dist/adapter-kit/errors.js +52 -0
- package/dist/adapter-kit/index.d.ts +144 -0
- package/dist/adapter-kit/index.js +178 -0
- package/dist/adapter-kit/semver.d.ts +12 -0
- package/dist/adapter-kit/semver.js +55 -0
- package/dist/agent/middleware/pii.js +2 -33
- package/dist/core/secure-stream.js +4 -3
- package/dist/embeddings/adapters.js +2 -1
- package/dist/evals/judge.js +2 -5
- package/dist/evaluate/cache.d.ts +0 -14
- package/dist/evaluate/cache.js +0 -30
- package/dist/evaluate/file-cache.d.ts +15 -0
- package/dist/evaluate/file-cache.js +30 -0
- package/dist/evaluate/index.d.ts +2 -1
- package/dist/evaluate/index.js +2 -1
- package/dist/evaluate/review.js +2 -2
- package/dist/evaluate/run.js +2 -2
- package/dist/evaluate/version.js +3 -3
- package/dist/graph/graph.js +2 -2
- package/dist/graph/node-cache.js +3 -3
- package/dist/hallucination/rag.d.ts +4 -1
- package/dist/hallucination/rag.js +6 -1
- package/dist/images/asset-stores.js +2 -3
- package/dist/images/asset-support.js +2 -2
- package/dist/images/assets.js +1 -2
- package/dist/images/evals.js +4 -4
- package/dist/insights/proposals.js +1 -2
- package/dist/insights/regressions.d.ts +26 -2
- package/dist/insights/regressions.js +129 -3
- package/dist/loaders/git.js +8 -1
- package/dist/loaders/web.js +7 -1
- package/dist/mcp/client.d.ts +14 -0
- package/dist/mcp/client.js +59 -1
- package/dist/mcp/registry.d.ts +6 -0
- package/dist/mcp/registry.js +7 -0
- package/dist/prompts/file.js +28 -11
- package/dist/protocols/a2a.d.ts +235 -0
- package/dist/protocols/a2a.js +386 -0
- package/dist/protocols/acp.d.ts +87 -0
- package/dist/protocols/acp.js +322 -0
- package/dist/protocols/ag-ui.d.ts +120 -0
- package/dist/protocols/ag-ui.js +180 -0
- package/dist/protocols/shared.d.ts +80 -0
- package/dist/protocols/shared.js +49 -0
- package/dist/providers/anthropic.js +1 -0
- package/dist/providers/cohere.js +2 -2
- package/dist/providers/google.js +2 -11
- package/dist/providers/openai.js +1 -0
- package/dist/rag/file-ingestion.js +15 -9
- package/dist/runtime/detect.d.ts +17 -0
- package/dist/runtime/detect.js +16 -0
- package/dist/runtime/index.d.ts +19 -0
- package/dist/runtime/index.js +7 -0
- package/dist/security/injection-detector.d.ts +2 -0
- package/dist/security/injection-detector.js +7 -1
- package/dist/security/input-guard.js +5 -2
- package/dist/security/output-guard.js +8 -4
- package/dist/security/pii-detector.js +22 -6
- package/dist/security/prompt-hardening.js +6 -2
- package/dist/security/semantic-injection-classifier.d.ts +2 -1
- package/dist/security/semantic-injection-classifier.js +31 -35
- package/dist/security/upload-scanner.d.ts +8 -0
- package/dist/security/upload-scanner.js +51 -9
- package/dist/server/deployments.d.ts +63 -1
- package/dist/server/deployments.js +75 -2
- package/dist/server/runs.d.ts +9 -0
- package/dist/server/runs.js +20 -0
- package/dist/server/server.js +5 -0
- package/dist/testing/record.js +2 -2
- package/dist/tracing/stores.js +2 -1
- package/dist/tracing/tracer.js +2 -2
- package/dist/types/config.d.ts +20 -0
- package/dist/types/server.d.ts +6 -0
- package/dist/utils/base64.d.ts +4 -0
- package/dist/utils/base64.js +21 -0
- package/dist/utils/checksums.d.ts +22 -0
- package/dist/utils/checksums.js +39 -0
- package/dist/utils/ids.d.ts +8 -0
- package/dist/utils/ids.js +26 -2
- package/dist/utils/sha256.d.ts +22 -0
- package/dist/utils/sha256.js +120 -0
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/dist-cjs/adapter-kit/contracts.d.ts +87 -0
- package/dist-cjs/adapter-kit/contracts.js +243 -0
- package/dist-cjs/adapter-kit/errors.d.ts +39 -0
- package/dist-cjs/adapter-kit/errors.js +57 -0
- package/dist-cjs/adapter-kit/index.d.ts +144 -0
- package/dist-cjs/adapter-kit/index.js +194 -0
- package/dist-cjs/adapter-kit/semver.d.ts +12 -0
- package/dist-cjs/adapter-kit/semver.js +59 -0
- package/dist-cjs/agent/middleware/pii.js +4 -35
- package/dist-cjs/core/secure-stream.js +4 -3
- package/dist-cjs/embeddings/adapters.js +2 -1
- package/dist-cjs/evals/judge.js +2 -5
- package/dist-cjs/evaluate/cache.d.ts +0 -14
- package/dist-cjs/evaluate/cache.js +1 -65
- package/dist-cjs/evaluate/file-cache.d.ts +15 -0
- package/dist-cjs/evaluate/file-cache.js +67 -0
- package/dist-cjs/evaluate/index.d.ts +2 -1
- package/dist-cjs/evaluate/index.js +3 -2
- package/dist-cjs/evaluate/review.js +2 -2
- package/dist-cjs/evaluate/run.js +2 -2
- package/dist-cjs/evaluate/version.js +3 -3
- package/dist-cjs/graph/graph.js +2 -2
- package/dist-cjs/graph/node-cache.js +3 -3
- package/dist-cjs/hallucination/rag.d.ts +4 -1
- package/dist-cjs/hallucination/rag.js +6 -1
- package/dist-cjs/images/asset-stores.js +2 -3
- package/dist-cjs/images/asset-support.js +2 -2
- package/dist-cjs/images/assets.js +1 -2
- package/dist-cjs/images/evals.js +4 -4
- package/dist-cjs/insights/proposals.js +1 -2
- package/dist-cjs/insights/regressions.d.ts +26 -2
- package/dist-cjs/insights/regressions.js +129 -3
- package/dist-cjs/loaders/git.js +8 -1
- package/dist-cjs/loaders/web.js +7 -1
- package/dist-cjs/mcp/client.d.ts +14 -0
- package/dist-cjs/mcp/client.js +60 -1
- package/dist-cjs/mcp/registry.d.ts +6 -0
- package/dist-cjs/mcp/registry.js +7 -0
- package/dist-cjs/prompts/file.js +28 -11
- package/dist-cjs/protocols/a2a.d.ts +235 -0
- package/dist-cjs/protocols/a2a.js +393 -0
- package/dist-cjs/protocols/acp.d.ts +87 -0
- package/dist-cjs/protocols/acp.js +326 -0
- package/dist-cjs/protocols/ag-ui.d.ts +120 -0
- package/dist-cjs/protocols/ag-ui.js +186 -0
- package/dist-cjs/protocols/shared.d.ts +80 -0
- package/dist-cjs/protocols/shared.js +59 -0
- package/dist-cjs/providers/anthropic.js +1 -0
- package/dist-cjs/providers/cohere.js +2 -2
- package/dist-cjs/providers/google.js +3 -12
- package/dist-cjs/providers/openai.js +1 -0
- package/dist-cjs/rag/file-ingestion.js +14 -8
- package/dist-cjs/runtime/detect.d.ts +17 -0
- package/dist-cjs/runtime/detect.js +19 -0
- package/dist-cjs/runtime/index.d.ts +19 -0
- package/dist-cjs/runtime/index.js +31 -0
- package/dist-cjs/security/injection-detector.d.ts +2 -0
- package/dist-cjs/security/injection-detector.js +7 -1
- package/dist-cjs/security/input-guard.js +5 -2
- package/dist-cjs/security/output-guard.js +8 -4
- package/dist-cjs/security/pii-detector.js +22 -6
- package/dist-cjs/security/prompt-hardening.js +6 -2
- package/dist-cjs/security/semantic-injection-classifier.d.ts +2 -1
- package/dist-cjs/security/semantic-injection-classifier.js +31 -35
- package/dist-cjs/security/upload-scanner.d.ts +8 -0
- package/dist-cjs/security/upload-scanner.js +53 -9
- package/dist-cjs/server/deployments.d.ts +63 -1
- package/dist-cjs/server/deployments.js +75 -2
- package/dist-cjs/server/runs.d.ts +9 -0
- package/dist-cjs/server/runs.js +20 -0
- package/dist-cjs/server/server.js +5 -0
- package/dist-cjs/testing/record.js +2 -2
- package/dist-cjs/tracing/stores.js +2 -1
- package/dist-cjs/tracing/tracer.js +2 -2
- package/dist-cjs/types/config.d.ts +20 -0
- package/dist-cjs/types/server.d.ts +6 -0
- package/dist-cjs/utils/base64.d.ts +4 -0
- package/dist-cjs/utils/base64.js +25 -0
- package/dist-cjs/utils/checksums.d.ts +22 -0
- package/dist-cjs/utils/checksums.js +46 -0
- package/dist-cjs/utils/ids.d.ts +8 -0
- package/dist-cjs/utils/ids.js +28 -2
- package/dist-cjs/utils/sha256.d.ts +22 -0
- package/dist-cjs/utils/sha256.js +125 -0
- package/dist-cjs/version.d.ts +1 -1
- package/dist-cjs/version.js +1 -1
- package/llms.txt +5 -2
- package/package.json +76 -6
package/API_STABILITY.md
CHANGED
|
@@ -41,6 +41,178 @@ 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.4 stage (2.4.0)
|
|
45
|
+
|
|
46
|
+
Everything 2.4 adds is stable from the start and additive. These security fixes tighten behavior,
|
|
47
|
+
as the compatibility rules allow:
|
|
48
|
+
- the upload scanner checks the larger of the declared and actual sizes;
|
|
49
|
+
- an allowlist refuses a file with no MIME type;
|
|
50
|
+
- textual bytes are scanned;
|
|
51
|
+
- secret findings carry a preview instead of the value;
|
|
52
|
+
- card and phone matches must pass their checks.
|
|
53
|
+
|
|
54
|
+
New and stable:
|
|
55
|
+
- `confidence`, `minErrorRateIncrease`, `minFeedbackDrop`, and `resamples` on `watchCanaries()`;
|
|
56
|
+
the same options and `seed` on `compareRuns()`; `Regression.interval`;
|
|
57
|
+
- `Deployments.evaluate()` with `RunEvaluationOptions` and `RunEvaluationReport`;
|
|
58
|
+
- `RunRecord.feedback`, `RunManager.addFeedback()`, and `POST /runs/:id/feedback`;
|
|
59
|
+
- `nexus-ai-pro/adapter-kit`: the `define*()` builders, `Adapter`, `AdapterDefinition`,
|
|
60
|
+
`AdapterReport`, `AdapterError` and its codes, the contract runners, and the capability types.
|
|
61
|
+
Contract checks may be added in a minor release when they test something the contract already
|
|
62
|
+
promised. A new check for a new promise arrives behind a capability an adapter must declare.
|
|
63
|
+
- `nexus-ai-pro/protocols/ag-ui`, `nexus-ai-pro/protocols/a2a`, and `nexus-ai-pro/protocols/acp`:
|
|
64
|
+
the handlers, `a2aClient()`, `a2aTool()`, `serveAcp()`, and their types. Each speaks the
|
|
65
|
+
protocol version it names. A minor release may send an event or answer a method it did not
|
|
66
|
+
before, as a protocol adds them. An event or field already sent keeps its meaning. A new major
|
|
67
|
+
version of a protocol arrives beside the old one, not in its place.
|
|
68
|
+
- `nexus-ai-pro/runtime`, `runtimeInfo()`, `RuntimeInfo`, and `RuntimeName`, which may gain
|
|
69
|
+
names in a minor release; the `fetch` option on the OpenAI, Anthropic, Google, and Cohere
|
|
70
|
+
provider configurations.
|
|
71
|
+
- Portability, for the client, the kernel, the provider adapters, graphs, agents, and the agent
|
|
72
|
+
protocols: none of them starts needing Node.js in a minor release, and the build fails if one
|
|
73
|
+
does.
|
|
74
|
+
|
|
75
|
+
Without `confidence`, a canary is judged as before.
|
|
76
|
+
|
|
77
|
+
These security fixes tighten more behavior, each closing a finding of a graduation review in
|
|
78
|
+
[SECURITY.md](./SECURITY.md#threat-reviews):
|
|
79
|
+
- the Git loader never follows a symbolic link, nor a path that leaves the checkout;
|
|
80
|
+
- a gzipped sitemap may inflate to 50 MB at most, the sitemap protocol's maximum;
|
|
81
|
+
- a local MCP server inherits only what a process needs to run, not this process's environment.
|
|
82
|
+
`inheritEnv` restores the old behavior, by name or entirely;
|
|
83
|
+
- a canary is judged on runs, so each run counts once per feedback key, as the mean of its scores;
|
|
84
|
+
- the file prompt store's label compare-and-set holds within one process;
|
|
85
|
+
- changes to one deployment through one `Deployments` object apply in order.
|
|
86
|
+
|
|
87
|
+
### Graduation
|
|
88
|
+
|
|
89
|
+
A surface left experimental status in 2.4 only when every requirement in
|
|
90
|
+
[How an item graduates](./ROADMAP.md#how-an-item-graduates) had evidence. That evidence is below.
|
|
91
|
+
"n/a" names a requirement that does not apply, and says why. Every test named here runs in CI.
|
|
92
|
+
Load and soak budgets are checked by `npm run bench:surfaces` and `npm run bench:runtime`, which are
|
|
93
|
+
part of `check:release`. Upgrade tests run against the published 2.3.0 package, installed as a
|
|
94
|
+
development alias.
|
|
95
|
+
|
|
96
|
+
Every graduated surface is covered by the 2.x compatibility rules, with no breaking change planned.
|
|
97
|
+
That is the "API stability" requirement, met by all of them.
|
|
98
|
+
|
|
99
|
+
**The SQLite adapters** (`nexus-ai-pro/sqlite` and its subpaths):
|
|
100
|
+
|
|
101
|
+
| Requirement | Evidence |
|
|
102
|
+
| --- | --- |
|
|
103
|
+
| Conformance | The operation store, store, and vector store contracts: `tests/sqlite.test.ts`, `tests/vector-stores.test.ts` |
|
|
104
|
+
| Crash recovery | A crash at every durable boundary resumes to the uninterrupted state: `tests/crash-injection.test.ts` |
|
|
105
|
+
| Concurrency | Ten workers race one thread, one idempotency key, one queue, and one budget: `tests/ten-workers.test.ts` |
|
|
106
|
+
| Load | `checkpoint.sqlite` and `operations.claim-10k-queued` in `runtime-budget.json`; `sqlite.vectors-query-2k` and `sqlite.store-put-get-search` in `surface-budget.json` |
|
|
107
|
+
| Tenant isolation | Every SQLite store: `tests/tenant-isolation.test.ts` |
|
|
108
|
+
| Security | [Review](./SECURITY.md#sqlite-adapters): no findings |
|
|
109
|
+
| Upgrade | A 2.3 file upgrades in place, and a 2.3 worker shares its queue: `tests/upgrade-previous-minor.test.ts`; likewise from 2.0: `tests/upgrade.test.ts` |
|
|
110
|
+
| Soak | 20,000 queue lifecycles and 2,000 open, migrate, and close cycles, with flat memory and no handle left open |
|
|
111
|
+
|
|
112
|
+
**The Postgres and SQLite vector stores** (`PostgresVectorStore`, `SqliteVectorStore`):
|
|
113
|
+
|
|
114
|
+
| Requirement | Evidence |
|
|
115
|
+
| --- | --- |
|
|
116
|
+
| Conformance | The vector store contract on pgvector and on SQLite: `tests/vector-stores.test.ts`. The retriever contract over each: `tests/graduation-conformance.test.ts` |
|
|
117
|
+
| Crash recovery | n/a: a store keeps no run state, and a reload upserts the same ids |
|
|
118
|
+
| Concurrency | Ten writers upserting the same ids at once leave one whole row per id: `tests/graduation-conformance.test.ts` |
|
|
119
|
+
| Load | `sqlite.vectors-query-2k` and `postgres.vectors-query-1k` in `surface-budget.json` |
|
|
120
|
+
| Tenant isolation | Both stores: `tests/tenant-isolation.test.ts` |
|
|
121
|
+
| Security | [Review](./SECURITY.md#the-postgres-and-sqlite-vector-stores): no findings |
|
|
122
|
+
| Upgrade | A table 2.3 wrote is searched and filtered here: `tests/upgrade-previous-minor.test.ts` |
|
|
123
|
+
| Soak | 1,000 write, search, and delete cycles on pgvector |
|
|
124
|
+
|
|
125
|
+
**The loaders** (`nexus-ai-pro/loaders/*`):
|
|
126
|
+
|
|
127
|
+
| Requirement | Evidence |
|
|
128
|
+
| --- | --- |
|
|
129
|
+
| Conformance | Every format, the web loader through the SSRF-safe fetch, and Git cloned and in place: `tests/loaders.test.ts` |
|
|
130
|
+
| Crash recovery | n/a: a loader keeps no state, and reloading replaces the same chunks |
|
|
131
|
+
| Concurrency | n/a: a loader shares no records |
|
|
132
|
+
| Load | `loaders.markdown-csv-html` in `surface-budget.json` |
|
|
133
|
+
| Tenant isolation | n/a: a loader stores nothing; the store it loads into is isolated |
|
|
134
|
+
| Security | [Review](./SECURITY.md#loaders): two findings, both fixed |
|
|
135
|
+
| Upgrade | The same files give the same ids and text as in 2.3: `tests/upgrade-previous-minor.test.ts` |
|
|
136
|
+
| Soak | 2,000 load cycles |
|
|
137
|
+
|
|
138
|
+
**The retrievers** (`nexus-ai-pro/rag/retrievers`):
|
|
139
|
+
|
|
140
|
+
| Requirement | Evidence |
|
|
141
|
+
| --- | --- |
|
|
142
|
+
| Conformance | The retriever contract on `KeywordIndex`, on a vector retriever over memory, SQLite, and pgvector, and on `hybridRetriever()`: `tests/graduation-conformance.test.ts` |
|
|
143
|
+
| Crash recovery | n/a: an index is held in memory, and rebuilt by loading |
|
|
144
|
+
| Concurrency | n/a: an index belongs to one process |
|
|
145
|
+
| Load | `retrievers.keyword-query-5k` and `retrievers.hybrid-query` in `surface-budget.json` |
|
|
146
|
+
| Tenant isolation | Filters narrow every retriever, by the contract; the stores behind them are isolated |
|
|
147
|
+
| Security | [Review](./SECURITY.md#retrievers): no findings |
|
|
148
|
+
| Upgrade | The same corpus ranks the same, score for score, as in 2.3: `tests/upgrade-previous-minor.test.ts` |
|
|
149
|
+
| Soak | 50,000 add and delete cycles |
|
|
150
|
+
|
|
151
|
+
**The MCP registry** (`nexus-ai-pro/mcp/registry`):
|
|
152
|
+
|
|
153
|
+
| Requirement | Evidence |
|
|
154
|
+
| --- | --- |
|
|
155
|
+
| Conformance | Servers over the protocol in process and as a real child process: `tests/mcp-registry.test.ts` |
|
|
156
|
+
| Crash recovery | A server that fails to start is reported, and the rest serve: `tests/mcp-registry.test.ts` |
|
|
157
|
+
| Concurrency | n/a: a registry shares no records |
|
|
158
|
+
| Load | `mcp.registry-tools-10-servers` in `surface-budget.json` |
|
|
159
|
+
| Tenant isolation | n/a: a registry stores nothing |
|
|
160
|
+
| Security | [Review](./SECURITY.md#mcp-registry): one finding, fixed |
|
|
161
|
+
| Upgrade | A configuration reads the same as in 2.3: `tests/upgrade-previous-minor.test.ts` |
|
|
162
|
+
| Soak | 1,000 connect, call, and close cycles, with no handle left open |
|
|
163
|
+
|
|
164
|
+
**The context hub** (`nexus-ai-pro/context-hub`):
|
|
165
|
+
|
|
166
|
+
| Requirement | Evidence |
|
|
167
|
+
| --- | --- |
|
|
168
|
+
| Conformance | The same behavior on memory, files, Redis, and Postgres: `tests/graduation-conformance.test.ts` |
|
|
169
|
+
| Crash recovery | A commit is content-addressed, so repeating an interrupted one writes the same version: `tests/context-hub.test.ts` |
|
|
170
|
+
| Concurrency | Two hubs racing for one label never both win, on every backend: `tests/graduation-conformance.test.ts` |
|
|
171
|
+
| Load | `context-hub.commit-resolve` in `surface-budget.json` |
|
|
172
|
+
| Tenant isolation | Context bundles: `tests/tenant-isolation.test.ts` |
|
|
173
|
+
| Security | [Review](./SECURITY.md#context-hub): one finding, fixed |
|
|
174
|
+
| Upgrade | A bundle has the same version as in 2.3, and a 2.3 export imports: `tests/upgrade-previous-minor.test.ts` |
|
|
175
|
+
| Soak | 2,000 commit, resolve, and render cycles |
|
|
176
|
+
|
|
177
|
+
**Insights** (`nexus-ai-pro/insights`):
|
|
178
|
+
|
|
179
|
+
| Requirement | Evidence |
|
|
180
|
+
| --- | --- |
|
|
181
|
+
| Conformance | The same issues from runs in memory and in Postgres: `tests/graduation-conformance.test.ts`; proposals in memory and in files: `tests/insights.test.ts` |
|
|
182
|
+
| Crash recovery | n/a: analysis is read-only, and a proposal is one write |
|
|
183
|
+
| Concurrency | n/a: a proposal is decided once, by a person |
|
|
184
|
+
| Load | `insights.find-issues-5k-runs` in `surface-budget.json` |
|
|
185
|
+
| Tenant isolation | Insights read through the trace store, which is isolated: `tests/tenant-isolation.test.ts` |
|
|
186
|
+
| Security | [Review](./SECURITY.md#insights): no findings |
|
|
187
|
+
| Upgrade | A 2.3 proposal reads here, and errors group under the same signatures: `tests/upgrade-previous-minor.test.ts` |
|
|
188
|
+
| Soak | 300 clustering cycles |
|
|
189
|
+
|
|
190
|
+
**Tenant limits and the server's worker queue** (`nexus-ai-pro/server/tenancy`, and the queue
|
|
191
|
+
`createAgentServer()` runs on its operation store):
|
|
192
|
+
|
|
193
|
+
| Requirement | Evidence |
|
|
194
|
+
| --- | --- |
|
|
195
|
+
| Conformance | Tenant usage in memory and in Redis; the queue on every operation store: `tests/deployments.test.ts`, `tests/operations.test.ts` |
|
|
196
|
+
| Crash recovery | A crash at every durable boundary resumes to the same state, and a draining worker hands a run to another: `tests/crash-injection.test.ts`, `tests/deployments.test.ts` |
|
|
197
|
+
| Concurrency | Ten workers drain one queue, and spend one tenant budget without over-granting a slot: `tests/ten-workers.test.ts` |
|
|
198
|
+
| Load | `tenancy.admit-release` in `surface-budget.json`; `operations.claim-10k-queued` and `server.sse-fanout` in `runtime-budget.json` |
|
|
199
|
+
| Tenant isolation | Operations: `tests/tenant-isolation.test.ts` |
|
|
200
|
+
| Security | [Review](./SECURITY.md#tenant-limits-and-the-worker-queue): no findings |
|
|
201
|
+
| Upgrade | A 2.3 worker and a 2.4 worker drain one queue: `tests/upgrade-previous-minor.test.ts` |
|
|
202
|
+
| Soak | 50,000 admit and release cycles, and 500 replica lifecycles with no timer left running |
|
|
203
|
+
|
|
204
|
+
**Still experimental**, each with what remains:
|
|
205
|
+
- **Deployments** (`nexus-ai-pro/server/deployments`). Two replicas changing one deployment in the
|
|
206
|
+
same instant can lose one change, because the state store has no atomic compare-and-set. Every
|
|
207
|
+
other requirement has evidence above or in its review.
|
|
208
|
+
- **Images.** Recorded live conformance must pass on all three backends. The scheduled live workflow
|
|
209
|
+
now records it, wherever a backend's credential is set.
|
|
210
|
+
- **The Qdrant, Redis, Pinecone, Weaviate, and Chroma vector stores.** The contract must pass against
|
|
211
|
+
the real servers, not only stubs. The scheduled live workflow now runs it against each one as a
|
|
212
|
+
service container, and Pinecone runs when its secret is set.
|
|
213
|
+
- **The studio and its accounts.** A threat review of its sign-in, sessions, and roles, and a soak
|
|
214
|
+
of its server, are still to do.
|
|
215
|
+
|
|
44
216
|
## 2.3 stage (2.3.0)
|
|
45
217
|
|
|
46
218
|
Everything 2.3 adds is stable from the start and additive: no default changes meaning.
|
|
@@ -618,6 +790,9 @@ of the 1.x line.
|
|
|
618
790
|
|
|
619
791
|
## Deployment stage (1.24.0)
|
|
620
792
|
|
|
793
|
+
Tenant limits and the worker queue graduated in 2.4; see the 2.4 stage for their evidence.
|
|
794
|
+
Deployments remain experimental.
|
|
795
|
+
|
|
621
796
|
Deployments (`nexus-ai-pro/server/deployments`), tenant limits (`nexus-ai-pro/server/tenancy`), and the
|
|
622
797
|
server's worker queue are experimental in production readiness. Their contracts follow the 1.x rules.
|
|
623
798
|
|
|
@@ -632,6 +807,9 @@ server's worker queue are experimental in production readiness. Their contracts
|
|
|
632
807
|
|
|
633
808
|
## Team platform stage (1.23.0)
|
|
634
809
|
|
|
810
|
+
The context hub and insights graduated in 2.4; see the 2.4 stage for their evidence. The studio's
|
|
811
|
+
accounts remain experimental.
|
|
812
|
+
|
|
635
813
|
The context hub (`nexus-ai-pro/context-hub`), insights (`nexus-ai-pro/insights`), and the studio's
|
|
636
814
|
accounts are experimental in production readiness. Their contracts follow the 1.x rules.
|
|
637
815
|
|
|
@@ -644,6 +822,9 @@ accounts are experimental in production readiness. Their contracts follow the 1.
|
|
|
644
822
|
|
|
645
823
|
## Retrieval breadth stage (1.22.0)
|
|
646
824
|
|
|
825
|
+
The loaders, the SQLite vector store, the retrievers, and the MCP registry graduated in 2.4; see the
|
|
826
|
+
2.4 stage for their evidence. The Redis, Pinecone, Weaviate, and Chroma stores remain experimental.
|
|
827
|
+
|
|
647
828
|
The loaders (`nexus-ai-pro/loaders/*`), the Redis, Pinecone, Weaviate, Chroma, and SQLite vector
|
|
648
829
|
stores, the retrievers (`nexus-ai-pro/rag/retrievers`), and the MCP registry
|
|
649
830
|
(`nexus-ai-pro/mcp/registry`) are experimental in production readiness. Their contracts follow the
|
|
@@ -660,6 +841,8 @@ stores, the retrievers (`nexus-ai-pro/rag/retrievers`), and the MCP registry
|
|
|
660
841
|
|
|
661
842
|
## Durable execution stage (1.21.0)
|
|
662
843
|
|
|
844
|
+
The SQLite adapters graduated in 2.4; see the 2.4 stage for their evidence.
|
|
845
|
+
|
|
663
846
|
Functional workflows (`nexus-ai-pro/graph/functional`) and the SQLite adapters (`nexus-ai-pro/sqlite`)
|
|
664
847
|
are experimental in production readiness. Their contracts follow the 1.x rules.
|
|
665
848
|
|
|
@@ -672,6 +855,9 @@ are experimental in production readiness. Their contracts follow the 1.x rules.
|
|
|
672
855
|
|
|
673
856
|
## Retrieval stores stage (1.20.0)
|
|
674
857
|
|
|
858
|
+
`PostgresVectorStore` graduated in 2.4; see the 2.4 stage for its evidence. `QdrantVectorStore`
|
|
859
|
+
remains experimental.
|
|
860
|
+
|
|
675
861
|
`PostgresVectorStore` (`nexus-ai-pro/postgres/vectors`) and `QdrantVectorStore` (`nexus-ai-pro/rag/qdrant`)
|
|
676
862
|
are experimental in production readiness. The `VectorStore` contract they share with
|
|
677
863
|
`MemoryVectorStore` follows the 1.x rules: a minor release may add optional methods and options, not
|
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,188 @@ Notable changes to this project are recorded here. The format follows [Keep a Ch
|
|
|
4
4
|
|
|
5
5
|
## [Unreleased]
|
|
6
6
|
|
|
7
|
+
## [2.4.0] - 2026-10-08
|
|
8
|
+
|
|
9
|
+
Graduation and interoperability.
|
|
10
|
+
|
|
11
|
+
### Added
|
|
12
|
+
|
|
13
|
+
- **Canaries judged with confidence, and on quality.**
|
|
14
|
+
- `watchCanaries({ confidence })` judges each metric the way an evaluation comparison judges a
|
|
15
|
+
score: a seeded bootstrap interval that must not reach zero, and a minimum effect —
|
|
16
|
+
`minErrorRateIncrease`, the latency and cost margins, and `minFeedbackDrop`. A real regression
|
|
17
|
+
rolls back; noise and a trivially small change do not. `compareRuns()` takes the same options,
|
|
18
|
+
and each `Regression` carries its `interval`.
|
|
19
|
+
- `Deployments.evaluate()` scores an assistant's finished runs with evaluators from
|
|
20
|
+
`nexus-ai-pro/evaluate`, and records the scores as run feedback. A canary that answers worse is
|
|
21
|
+
then rolled back like one that fails more. Sampling is stable by run id, and a run is scored
|
|
22
|
+
once per source.
|
|
23
|
+
- Runs carry `feedback`. `POST /runs/:id/feedback` and `RunManager.addFeedback()` record a
|
|
24
|
+
person's rating as well.
|
|
25
|
+
- **An adapter kit**, on the new `nexus-ai-pro/adapter-kit`, for building adapters outside this
|
|
26
|
+
repository:
|
|
27
|
+
- `defineProviderAdapter()`, `defineEmbeddingsAdapter()`, `defineVectorStoreAdapter()`,
|
|
28
|
+
`defineRetrieverAdapter()`, and `defineStoreAdapter()`. Each takes a capability declaration
|
|
29
|
+
and the range of releases the adapter supports, read as npm reads ranges.
|
|
30
|
+
- Every instance normalizes its failures into an `AdapterError` with a code and `retryable`, and
|
|
31
|
+
reports each call to an `onCall` telemetry hook.
|
|
32
|
+
- `verify()` runs the adapter's contract suite, skipping only what it declares it cannot do, with
|
|
33
|
+
a benchmark held to the p95 budgets it declares.
|
|
34
|
+
- The vector-store, retriever, and store contracts ship as `runVectorStoreContract()`,
|
|
35
|
+
`runRetrieverContract()`, and `runStoreContract()`, with no test framework needed.
|
|
36
|
+
- **Agent protocols**, each on its own entry point and with no dependency:
|
|
37
|
+
- `nexus-ai-pro/protocols/ag-ui`: `agUiHandler()` serves a graph to any AG-UI frontend as
|
|
38
|
+
Server-Sent Events: each step, text as it streams, tool calls with their results, and the final
|
|
39
|
+
state. A run that needs approval finishes with an interrupt, and a resume entry on the same
|
|
40
|
+
thread continues it. `agUiEvents()` yields the same events for any other transport.
|
|
41
|
+
- `nexus-ai-pro/protocols/a2a`: `a2aHandler()` serves a graph as an A2A 1.0 agent: its card,
|
|
42
|
+
`SendMessage`, `SendStreamingMessage`, `GetTask`, and `CancelTask`. A context is a
|
|
43
|
+
conversation, and a task that needs approval asks for input and continues when a message answers
|
|
44
|
+
it. `a2aClient()` calls any A2A agent, and `a2aTool()` makes one a tool that declares the
|
|
45
|
+
host it reaches, so a permission policy decides it.
|
|
46
|
+
- `nexus-ai-pro/protocols/acp`: `serveAcp()` puts a graph in a code editor over the Agent
|
|
47
|
+
Client Protocol. The editor sees streamed text and thought, each tool call with its kind, file,
|
|
48
|
+
and diff, and the plan from `write_todos`. It asks the person to approve calls, and keeps an
|
|
49
|
+
always-allow or always-reject choice for the session.
|
|
50
|
+
- **A portable kernel**, on the new `nexus-ai-pro/runtime`: messages, responses, the provider and
|
|
51
|
+
tool contracts, streaming, and capabilities, in one small import that reaches nothing Node-only.
|
|
52
|
+
`runtimeInfo()` names the runtime the code is on.
|
|
53
|
+
- **The client, the provider adapters, graphs, agents, and the agent protocols run on Deno, Bun,
|
|
54
|
+
edge runtimes, and browsers.**
|
|
55
|
+
- Ids come from Web Crypto.
|
|
56
|
+
- SHA-256 for node-cache keys and dataset versions is computed in plain JavaScript where the
|
|
57
|
+
runtime has no synchronous native digest. The digests are identical, so existing cache keys
|
|
58
|
+
still match.
|
|
59
|
+
- Base64 and UTF-8 byte counts no longer need `Buffer`.
|
|
60
|
+
- 125 of 157 entry points now run anywhere. The new runtimes guide lists the rest, each with
|
|
61
|
+
exactly what it needs.
|
|
62
|
+
- The OpenAI, Anthropic, Google, and Cohere providers take a `fetch` option: a platform's bound
|
|
63
|
+
fetch, a proxy, or a test stub.
|
|
64
|
+
- **Measured graduation.** These surfaces leave experimental status, each with evidence for every
|
|
65
|
+
requirement of the graduation checklist, published in `API_STABILITY.md`:
|
|
66
|
+
- the SQLite adapters;
|
|
67
|
+
- the Postgres and SQLite vector stores;
|
|
68
|
+
- the loaders and the retrievers;
|
|
69
|
+
- the MCP registry;
|
|
70
|
+
- the context hub and insights;
|
|
71
|
+
- tenant limits and the server's worker queue.
|
|
72
|
+
|
|
73
|
+
Deployments, images, the Qdrant, Redis, Pinecone, Weaviate, and Chroma vector stores, and the
|
|
74
|
+
studio stay experimental, each with the requirement that remains named.
|
|
75
|
+
- `inheritEnv` on a local MCP server, in `StdioClientOptions` and in the registry's server
|
|
76
|
+
configuration: which of this process's environment variables the server inherits.
|
|
77
|
+
- Load and soak budgets for every graduated surface, held in CI by `npm run bench:surfaces`. A soak
|
|
78
|
+
fails on heap growth, on a handle left open, or on a timer never cleared, unref'd ones included.
|
|
79
|
+
- The scheduled live workflow records image conformance on every backend with a credential, and
|
|
80
|
+
runs the vector store contract against real Qdrant, Chroma, Weaviate, and Redis servers.
|
|
81
|
+
|
|
82
|
+
### Security
|
|
83
|
+
|
|
84
|
+
Testing the security code to depth found these gaps, and each is closed:
|
|
85
|
+
|
|
86
|
+
- **The upload scanner trusted the caller.**
|
|
87
|
+
- A declared `sizeBytes` could carry a larger file past `maxBytes`; the larger of the declared and
|
|
88
|
+
actual sizes is now checked.
|
|
89
|
+
- `run.exe.`, `run.exe ` (Windows drops the trailing dot or space), and a name with a control
|
|
90
|
+
character such as `run.exe\0.txt` passed the extension block; names are now read as the file
|
|
91
|
+
system reads them, and a control character is itself a critical finding.
|
|
92
|
+
- Content given as bytes, which is how upload middleware delivers it, was never scanned; textual
|
|
93
|
+
bytes are now decoded and scanned.
|
|
94
|
+
- A file with no MIME type passed an allowlist; an allowlist now fails closed. Types are compared
|
|
95
|
+
without parameters, so `text/plain; charset=utf-8` is `text/plain`.
|
|
96
|
+
- **File ingestion read what it never scanned.** Text an extractor returns from a PDF or an image is
|
|
97
|
+
now scanned like a text file. A text file given as bytes is ingested rather than skipped.
|
|
98
|
+
- **The input guard put secrets in its findings.** A finding now carries a short preview, such as
|
|
99
|
+
`ghp_… (40 characters)`, never the secret. The SSRF check also catches `[::1]`, all of
|
|
100
|
+
`127.0.0.0/8`, and the Google and Alibaba metadata hosts.
|
|
101
|
+
- **Prompt hardening could be escaped.** User text holding the delimiter closed the block early; each
|
|
102
|
+
occurrence inside the text is now broken apart. The text parts of multi-part messages are wrapped
|
|
103
|
+
too.
|
|
104
|
+
- **The injection detectors read text as typed, not as the model reads it.** Both now fold
|
|
105
|
+
full-width letters and drop zero-width characters first, so `IGNORE previous instructions` and
|
|
106
|
+
`ignore previous instructions` are found. `neutralize()` leaves clean text exactly as it was.
|
|
107
|
+
- **The PII detector and the output guard took any long number for a card or a phone.** A
|
|
108
|
+
millisecond timestamp or an order id was masked, and in the output guard a card's last digits
|
|
109
|
+
could survive because the phone pattern claimed the rest first. Card numbers must now pass Luhn,
|
|
110
|
+
and phone numbers need 10 to 15 digits with a separator or a leading `+`. Cards are claimed before
|
|
111
|
+
phones, and a span one kind has claimed is not reported again as another.
|
|
112
|
+
- **Retrieved context reads as data.** `withRagContext()` now tells the model that the context is
|
|
113
|
+
data, not instructions.
|
|
114
|
+
|
|
115
|
+
The graduation reviews, published in `SECURITY.md`, found these, and each is closed:
|
|
116
|
+
|
|
117
|
+
- **The Git loader followed symbolic links.** A repository with a tracked link to a file of the host,
|
|
118
|
+
such as `~/.ssh/id_rsa`, had that file loaded into a knowledge base. A link is now never followed,
|
|
119
|
+
nor a path that leaves the checkout.
|
|
120
|
+
- **A gzipped sitemap could be a decompression bomb.** Inflation now stops at 50 MB, the sitemap
|
|
121
|
+
protocol's maximum, and the loader reports the sitemap.
|
|
122
|
+
- **A local MCP server inherited this process's whole environment**, every API key and database URL
|
|
123
|
+
included. It now starts with its `env` and only what a process needs to run: the path, the home
|
|
124
|
+
and temporary directories, the locale, the Windows system variables, proxies, and certificates.
|
|
125
|
+
Name what else a server needs in `env`, or set `inheritEnv`.
|
|
126
|
+
- **One caller's ratings could decide a canary.** Feedback was counted per rating, so a hundred low
|
|
127
|
+
ratings of one run met the minimum sample alone, and could roll back a canary or keep a bad one
|
|
128
|
+
alive. Each run now counts once per feedback key, as the mean of its ratings.
|
|
129
|
+
- **The file prompt store could lose a label move.** Its compare-and-set was a read and then a write,
|
|
130
|
+
so two moves at once in one process could both succeed, the later erasing the earlier. Label
|
|
131
|
+
writes to one file are now serialized across the process.
|
|
132
|
+
- **Two changes at once to one deployment, on one replica, could lose one**, such as a guard's
|
|
133
|
+
rollback and an operator's promotion. They now apply in order. Changes from two replicas in the
|
|
134
|
+
same instant still can, which keeps deployments experimental.
|
|
135
|
+
|
|
136
|
+
### Fixed
|
|
137
|
+
|
|
138
|
+
- The agent server's guide called the server experimental, though it has been stable since 2.0.
|
|
139
|
+
- Bundling the client for an edge runtime failed: it reached the file-based evaluation cache, which
|
|
140
|
+
loads `node:fs`. `FileEvaluationCache` now lives in a module of its own, still exported from
|
|
141
|
+
`nexus-ai-pro/evaluate`.
|
|
142
|
+
- `extractCitations()` and `validateCitations()` read a Markdown link `[text](url)` as a citation,
|
|
143
|
+
and `[doc-1, doc-2]` as one id; links are ignored and lists are split.
|
|
144
|
+
- The semantic injection classifier embeds a request in one call instead of one per message, and
|
|
145
|
+
`detectSync()` honours `enabled: false` as `detect()` did.
|
|
146
|
+
|
|
147
|
+
### Proof
|
|
148
|
+
|
|
149
|
+
- Grounding and verification, file ingestion, the upload scanner, the PII detector, and both
|
|
150
|
+
injection detectors are tested to the package's own coverage:
|
|
151
|
+
- grounding, the PII detector, prompt hardening, and the upload scanner at 100% of lines;
|
|
152
|
+
- file ingestion, which no test loaded before, at 97%.
|
|
153
|
+
- Each security fix above is a test that names the attack it stops or the false positive it rules
|
|
154
|
+
out.
|
|
155
|
+
- A canary seeded with a quality regression is rolled back. The proof runs on a real server: 300
|
|
156
|
+
runs, online evaluation recording the scores, and the guard reading them. A canary whose quality
|
|
157
|
+
differs only within the noise keeps its share. A difference that 20,000 runs make significant, but
|
|
158
|
+
that is under the minimum effect, is not a regression either.
|
|
159
|
+
- A community-style adapter, built only from the kit, passes its contract suite. It is a vector store
|
|
160
|
+
in plain JavaScript inside the clean-install test's consumer project, importing nothing but
|
|
161
|
+
`nexus-ai-pro/adapter-kit` from the installed tarball. A deliberately broken store fails exactly the
|
|
162
|
+
checks it breaks.
|
|
163
|
+
- A Nexus agent and a remote agent complete tasks over A2A in both directions:
|
|
164
|
+
- A client that writes raw JSON-RPC, as the specification describes it, drives the served agent
|
|
165
|
+
through a conversation, an approval, streaming, cancellation, and each error code.
|
|
166
|
+
- The client and tool complete tasks against a stub agent written from the specification alone.
|
|
167
|
+
- One Nexus agent calls another through the tool.
|
|
168
|
+
- A frontend renders a run through AG-UI with a plain `fetch` and Server-Sent Events parser, and
|
|
169
|
+
no Nexus client code, approval and resume included.
|
|
170
|
+
- An editor's end of an ACP connection approves an edit, and sees the plan, the diff, and the
|
|
171
|
+
answer.
|
|
172
|
+
- The kernel's tests pass on Node.js, Deno, Bun, and Vercel's edge runtime, and CI runs all four.
|
|
173
|
+
The tests are written against web-standard APIs only, with no test framework and nothing of Node's,
|
|
174
|
+
and they cover a provider over `fetch`, the client, a cached graph, an agent, and A2A and AG-UI.
|
|
175
|
+
A check walks every entry point's imports, static and dynamic. It fails the build when the client,
|
|
176
|
+
the kernel, a provider adapter, graphs, agents, or a protocol reaches anything Node-only.
|
|
177
|
+
- Every graduated surface passes its contract on every backend it supports. For the context hub,
|
|
178
|
+
that is memory, files, Redis, and Postgres, with two hubs racing for one label and never both
|
|
179
|
+
winning. For the retrievers, it is a vector retriever over memory, SQLite, and pgvector, besides
|
|
180
|
+
the keyword and hybrid retrievers.
|
|
181
|
+
- What the published 2.3.0 package wrote, this release reads, and what it derived, this release
|
|
182
|
+
derives the same: a SQLite file shared by a 2.3 and a 2.4 worker, a pgvector table, loader ids,
|
|
183
|
+
retriever rankings, MCP configurations, context bundle versions and exports, insight proposals
|
|
184
|
+
and error signatures, and canary routing, thread by thread.
|
|
185
|
+
- Each security fix has a test that names the attack, and fails on the code before it. The Git test
|
|
186
|
+
runs on Linux, where links are tracked as links, and the race test holds both writers until both
|
|
187
|
+
arrive, so it does not depend on timing.
|
|
188
|
+
|
|
7
189
|
## [2.3.0] - 2026-10-06
|
|
8
190
|
|
|
9
191
|
Agents that act safely, on production retrieval.
|
|
@@ -1777,7 +1959,8 @@ shared policy vocabulary is in place for a future release that revisits this.
|
|
|
1777
1959
|
- URL fetching rejects unsafe private-network targets and limits response reads.
|
|
1778
1960
|
- CLI and audit findings no longer disclose detected secret values.
|
|
1779
1961
|
|
|
1780
|
-
[Unreleased]: https://github.com/mkhitar-abrahamyan/nexus-ai/compare/v2.
|
|
1962
|
+
[Unreleased]: https://github.com/mkhitar-abrahamyan/nexus-ai/compare/v2.4.0...HEAD
|
|
1963
|
+
[2.4.0]: https://github.com/mkhitar-abrahamyan/nexus-ai/compare/v2.3.0...v2.4.0
|
|
1781
1964
|
[2.3.0]: https://github.com/mkhitar-abrahamyan/nexus-ai/compare/v2.2.0...v2.3.0
|
|
1782
1965
|
[2.2.0]: https://github.com/mkhitar-abrahamyan/nexus-ai/compare/v2.1.0...v2.2.0
|
|
1783
1966
|
[2.1.0]: https://github.com/mkhitar-abrahamyan/nexus-ai/compare/v2.0.0...v2.1.0
|
package/README.md
CHANGED
|
@@ -8,7 +8,10 @@ team can share.
|
|
|
8
8
|
Import only what you use. The root import is the client and nothing else, and every other capability
|
|
9
9
|
has its own entry point with a size budget CI enforces; [the packaging guide](https://github.com/mkhitar-abrahamyan/nexus-ai/blob/main/docs/packaging.md)
|
|
10
10
|
publishes what each one costs. The package has no required dependencies: a graph-only application
|
|
11
|
-
loads
|
|
11
|
+
loads 81 KB, and installs nothing but this package.
|
|
12
|
+
The client, the provider adapters, graphs, agents, and the agent protocols run on Node.js, Deno,
|
|
13
|
+
Bun, edge runtimes, and browsers; [the runtimes guide](https://github.com/mkhitar-abrahamyan/nexus-ai/blob/main/docs/runtimes.md)
|
|
14
|
+
lists the entry points that need Node.js, and why.
|
|
12
15
|
|
|
13
16
|
- NPM: https://www.npmjs.com/package/nexus-ai-pro
|
|
14
17
|
- GitHub: https://github.com/mkhitar-abrahamyan/nexus-ai
|
|
@@ -136,6 +139,7 @@ from the doc comments. The guides live in the repository, so these links go to G
|
|
|
136
139
|
| [The deep-agent preset](https://github.com/mkhitar-abrahamyan/nexus-ai/blob/main/docs/deep-agents.md) | Long, multi-step agents: a plan, a sandboxed workspace, helpers, skills, and a context that stays small |
|
|
137
140
|
| [Long-term memory](https://github.com/mkhitar-abrahamyan/nexus-ai/blob/main/docs/memory.md) | Namespaced memory with semantic search, in memory or Redis |
|
|
138
141
|
| [MCP](https://github.com/mkhitar-abrahamyan/nexus-ai/blob/main/docs/mcp.md) | Borrowing tools from MCP servers, a registry of many, and serving your own |
|
|
142
|
+
| [Agent protocols](https://github.com/mkhitar-abrahamyan/nexus-ai/blob/main/docs/protocols.md) | Serving an agent to user interfaces over AG-UI, to other agents over A2A, and to code editors over ACP, and calling remote agents as tools |
|
|
139
143
|
| [Traces](https://github.com/mkhitar-abrahamyan/nexus-ai/blob/main/docs/tracing.md) | Run trees, queries, feedback, comparison, and alerts |
|
|
140
144
|
| [Evaluation](https://github.com/mkhitar-abrahamyan/nexus-ai/blob/main/docs/evaluation.md) | Datasets, evaluators, experiments, comparisons with a verdict, review queues, LLM judges |
|
|
141
145
|
| [Context hub](https://github.com/mkhitar-abrahamyan/nexus-ai/blob/main/docs/context-hub.md) | Prompts, instructions, tools, and skills versioned together, promoted through gates, and moved between projects |
|
|
@@ -156,6 +160,7 @@ from the doc comments. The guides live in the repository, so these links go to G
|
|
|
156
160
|
| [Realtime voice](https://github.com/mkhitar-abrahamyan/nexus-ai/blob/main/docs/realtime.md) | Browser and server realtime sessions with barge-in, tools, and exports |
|
|
157
161
|
| [Telephony](https://github.com/mkhitar-abrahamyan/nexus-ai/blob/main/docs/telephony.md) | Calls, webhooks, phone numbers, and phone agents on realtime sessions |
|
|
158
162
|
| [Testing](https://github.com/mkhitar-abrahamyan/nexus-ai/blob/main/docs/testing.md) | Recording and replaying provider traffic, and conformance suites |
|
|
163
|
+
| [Adapter kit](https://github.com/mkhitar-abrahamyan/nexus-ai/blob/main/docs/adapter-kit.md) | Building a provider, store, or retriever outside this repository, and verifying it against the same contracts |
|
|
159
164
|
| [Studio](https://github.com/mkhitar-abrahamyan/nexus-ai/blob/main/docs/studio.md) | A shared UI for traces, threads, approvals, experiments, prompts, deployments, costs, and health, as a separate package |
|
|
160
165
|
| [Agent server](https://github.com/mkhitar-abrahamyan/nexus-ai/blob/main/docs/server.md) | Self-hosted HTTP server for assistants: threads, durable runs, resumable streams, cron, a worker queue, and metrics |
|
|
161
166
|
| [Deployments](https://github.com/mkhitar-abrahamyan/nexus-ai/blob/main/docs/deployments.md) | Revisions and canaries with automatic rollback, autoscaling on Kubernetes and Helm, and per-tenant limits |
|
|
@@ -163,6 +168,7 @@ from the doc comments. The guides live in the repository, so these links go to G
|
|
|
163
168
|
| [Workflows](https://github.com/mkhitar-abrahamyan/nexus-ai/blob/main/docs/workflows.md) | Ready-made chains and domain workflows |
|
|
164
169
|
| [Command line](https://github.com/mkhitar-abrahamyan/nexus-ai/blob/main/docs/cli.md) | The `nexus` command |
|
|
165
170
|
| [Packaging and install weight](https://github.com/mkhitar-abrahamyan/nexus-ai/blob/main/docs/packaging.md) | Every entry point and what it costs |
|
|
171
|
+
| [Runtimes](https://github.com/mkhitar-abrahamyan/nexus-ai/blob/main/docs/runtimes.md) | The portable kernel, and running the client, providers, graphs, and agents on Deno, Bun, edge runtimes, and browsers |
|
|
166
172
|
|
|
167
173
|
## Examples
|
|
168
174
|
|
|
@@ -256,13 +262,16 @@ Shipped so far:
|
|
|
256
262
|
- 2.3 agents that act safely, on production retrieval: capabilities and permission policies, a
|
|
257
263
|
sandbox contract, a middleware catalog, server authentication with one principal on every run,
|
|
258
264
|
keyword search in Postgres and Elasticsearch with rerankers, durable ingestion, and a deep-agent
|
|
259
|
-
preset
|
|
265
|
+
preset;
|
|
266
|
+
- 2.4 graduation and interoperability: SQLite, loaders, retrievers, the MCP registry, the context
|
|
267
|
+
hub, insights, and tenant limits out of experimental with published evidence; canaries judged with
|
|
268
|
+
confidence and on quality; an adapter kit; AG-UI, A2A, and ACP; and a portable kernel, with the
|
|
269
|
+
client, providers, graphs, and agents running on Deno, Bun, edge runtimes, and browsers.
|
|
260
270
|
|
|
261
271
|
Upgrading from 1.x: `npx nexus migrate src --write` moves your imports, and
|
|
262
272
|
[MIGRATING.md](https://github.com/mkhitar-abrahamyan/nexus-ai/blob/main/MIGRATING.md) covers the rest.
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
releases after it.
|
|
273
|
+
What comes next is on the [roadmap](https://github.com/mkhitar-abrahamyan/nexus-ai/blob/main/ROADMAP.md):
|
|
274
|
+
the gaps 2.4 left open, and the work applications ask for after them.
|
|
266
275
|
|
|
267
276
|
## Before Production
|
|
268
277
|
|
package/SECURITY.md
CHANGED
|
@@ -44,3 +44,143 @@ Nexus guardrails reduce common AI application risks, but they are not a complete
|
|
|
44
44
|
- Browser WebRTC still requires a backend security boundary. A direct media path reduces latency; it
|
|
45
45
|
does not remove the need for server-owned credentials, session policy, tool authorization, abuse
|
|
46
46
|
monitoring, and provider-side safety controls.
|
|
47
|
+
|
|
48
|
+
## Threat reviews
|
|
49
|
+
|
|
50
|
+
Every surface that leaves experimental status is reviewed for how untrusted input reaches it and
|
|
51
|
+
what it could do with that input. Each review is published here with its findings, which are closed
|
|
52
|
+
before the surface graduates. A finding is closed in one of two ways: by a fix with a test that
|
|
53
|
+
names the attack, or by a documented limitation that the surface's guide states.
|
|
54
|
+
|
|
55
|
+
These reviews were done for 2.4.
|
|
56
|
+
|
|
57
|
+
### SQLite adapters
|
|
58
|
+
|
|
59
|
+
Trust boundary: an application's data, an operation's payload, and metadata filters that may come
|
|
60
|
+
from a request.
|
|
61
|
+
- Table names are checked against a strict pattern and quoted. Every value, including each metadata
|
|
62
|
+
filter key and its JSON path, is a bound parameter, so a filter cannot change a statement.
|
|
63
|
+
- A migration records its checksum, and a changed migration is refused rather than reapplied.
|
|
64
|
+
- Every change to an operation is one `UPDATE … WHERE sequence = expected`, so two workers sharing
|
|
65
|
+
a file never both claim it. The ten-worker race tests run on SQLite.
|
|
66
|
+
- Tenant data is scoped by key prefix, and the isolation suite runs on every SQLite store.
|
|
67
|
+
|
|
68
|
+
Findings: none.
|
|
69
|
+
|
|
70
|
+
### The Postgres and SQLite vector stores
|
|
71
|
+
|
|
72
|
+
Trust boundary: metadata filters, which applications often build from a request.
|
|
73
|
+
- The pgvector store sends a filter as one bound `jsonb` containment parameter, and quotes its table
|
|
74
|
+
and index names.
|
|
75
|
+
- The SQLite store binds each key's JSON path and value, and matches a value's JSON type as well as
|
|
76
|
+
its value, so `"1"` never matches `1`.
|
|
77
|
+
|
|
78
|
+
Findings: none.
|
|
79
|
+
|
|
80
|
+
### Loaders
|
|
81
|
+
|
|
82
|
+
Trust boundary: everything a loader reads is untrusted. A repository, a website, a sitemap, or an
|
|
83
|
+
uploaded file may be written by an attacker who wants it in a knowledge base, or who wants the
|
|
84
|
+
loader to read something else.
|
|
85
|
+
- Web pages and sitemaps go through the SSRF-safe fetch. Private, loopback, and cloud-metadata
|
|
86
|
+
addresses are refused, every redirect is checked again, and bodies are capped.
|
|
87
|
+
- The Git loader runs `git` without a shell. It disables the `ext::` transport, puts `--` before
|
|
88
|
+
the repository, and refuses a repository that starts with `-`.
|
|
89
|
+
- `loadDirectory()` does not follow symbolic links.
|
|
90
|
+
|
|
91
|
+
Findings, both fixed in 2.4:
|
|
92
|
+
- **The Git loader followed symbolic links.** A tracked link such as `notes.md` pointing to
|
|
93
|
+
`~/.ssh/id_rsa` was read and ingested, so a knowledge base could quote a file of the host. A
|
|
94
|
+
link is now never followed, nor a path that resolves outside the checkout. Proof: a repository
|
|
95
|
+
holding a tracked link to a file outside it loads without that file, cloned and in place. On
|
|
96
|
+
Linux, the test fails on the earlier loader.
|
|
97
|
+
- **A gzipped sitemap could be a decompression bomb.** A few megabytes of gzip inflated without a
|
|
98
|
+
limit. Inflation now stops at 50 MB, the sitemap protocol's own maximum. Proof: 60 MB of gzip
|
|
99
|
+
that inflates past it is refused.
|
|
100
|
+
|
|
101
|
+
### Retrievers
|
|
102
|
+
|
|
103
|
+
Trust boundary: queries come from users, and documents may hold text written to steer a model.
|
|
104
|
+
- Tokenizing is one linear regular expression, with no backtracking on hostile input.
|
|
105
|
+
- Filters compare values; they never become code or a query language.
|
|
106
|
+
- A model reranker or query-variant generator reads documents and queries as data in its prompt. Its
|
|
107
|
+
output is parsed as JSON and used only to order or widen a search, never to call a tool.
|
|
108
|
+
|
|
109
|
+
Findings: none.
|
|
110
|
+
|
|
111
|
+
### MCP registry
|
|
112
|
+
|
|
113
|
+
Trust boundary: the configuration file is trusted, since it names programs to run. What a server
|
|
114
|
+
says about itself is not: its tool names, its descriptions, and its results.
|
|
115
|
+
- A server's tools are prefixed with its name by default, so one server cannot shadow another's
|
|
116
|
+
tool.
|
|
117
|
+
- Allow and deny lists limit what agents see, and deny wins.
|
|
118
|
+
- A tool from a server declares no capabilities. A permission policy denies such a tool unless its
|
|
119
|
+
`undeclared` rule says otherwise, and `humanApproval()` asks about it by default.
|
|
120
|
+
- `${NAME}` placeholders keep credentials out of the file. A missing variable is named in the error,
|
|
121
|
+
never its value.
|
|
122
|
+
|
|
123
|
+
Finding, fixed in 2.4: **a local server inherited this process's whole environment.** Any
|
|
124
|
+
`npx`-started server, which is usually third-party code, saw every API key and database URL the
|
|
125
|
+
application held. A server now starts with `env` and only what a process needs to run: the path,
|
|
126
|
+
the home and temporary directories, the locale, proxies, and certificates. The new `inheritEnv`
|
|
127
|
+
option widens this by name, or entirely. Proof: a real child process started by the transport sees
|
|
128
|
+
the variables it was given, and not a secret set in the parent.
|
|
129
|
+
|
|
130
|
+
### Context hub
|
|
131
|
+
|
|
132
|
+
Trust boundary: an imported bundle may come from another team or another organization. Who may
|
|
133
|
+
commit and promote is the application's access control, which the studio's roles enforce.
|
|
134
|
+
- An import recomputes each bundle's and each prompt's content version, and refuses one whose content
|
|
135
|
+
changed after export.
|
|
136
|
+
- A bundle names tools, but `bindTools()` binds only implementations the application supplies, so
|
|
137
|
+
a bundle cannot add code.
|
|
138
|
+
- Promotion runs the label's gates, an experiment over the exact version among them.
|
|
139
|
+
- Labels move by compare-and-set, so a promotion decided on a stale version is refused.
|
|
140
|
+
|
|
141
|
+
Finding, fixed in 2.4: **the file store's compare-and-set could lose a move.** Two label moves at
|
|
142
|
+
once in one process could both pass the check, and the later write erased the earlier one. Label
|
|
143
|
+
writes to one file are now serialized across the process. Proof: two hubs whose writes are held
|
|
144
|
+
until both arrive race for one label on every backend, and on the file store the earlier code
|
|
145
|
+
loses a move every time. Several processes promoting the same label at once still need the Redis or
|
|
146
|
+
Postgres store, as the prompts guide says.
|
|
147
|
+
|
|
148
|
+
### Insights
|
|
149
|
+
|
|
150
|
+
Trust boundary: runs and their errors carry user data, and a model proposes fixes.
|
|
151
|
+
- An error signature replaces numbers, quoted values, URLs, ids, and long hexadecimal strings, so a
|
|
152
|
+
cluster's summary does not carry a customer's data.
|
|
153
|
+
- A model's proposed fix is parsed as data, evaluated on a dataset, and never applied without a
|
|
154
|
+
person. A promotion still runs the label's gates.
|
|
155
|
+
- A proposal id is checked against a strict pattern before it becomes a file name.
|
|
156
|
+
|
|
157
|
+
Findings: none.
|
|
158
|
+
|
|
159
|
+
### Tenant limits and the worker queue
|
|
160
|
+
|
|
161
|
+
Trust boundary: a tenant is whoever the application's `authenticate()` says, never a header the
|
|
162
|
+
server trusts by itself.
|
|
163
|
+
- Concurrency, rate, and budget limits are kept in a shared store, so several replicas enforce one
|
|
164
|
+
limit. Admission and release are tested by ten racing workers.
|
|
165
|
+
- A run is released exactly once, however it ends.
|
|
166
|
+
- The queue claims an operation under a lease in one atomic step on every store. A lost lease
|
|
167
|
+
cancels the run's signal, and a crash at any durable boundary resumes to the same state.
|
|
168
|
+
|
|
169
|
+
Findings: none.
|
|
170
|
+
|
|
171
|
+
### Deployments (reviewed; still experimental)
|
|
172
|
+
|
|
173
|
+
Findings:
|
|
174
|
+
- **Fixed in 2.4: one caller's ratings could decide a canary.** A canary was judged on feedback
|
|
175
|
+
entries, not on runs. A hundred low ratings of one run met the minimum sample alone, and could
|
|
176
|
+
roll back a canary for everyone, or keep a bad one alive. Each run now counts once per feedback
|
|
177
|
+
key, as the mean of its ratings.
|
|
178
|
+
- **Fixed in 2.4: two changes at once on one replica could lose one**, such as a guard's rollback
|
|
179
|
+
and an operator's promotion. Changes to one deployment now apply in order.
|
|
180
|
+
- **Open: two replicas changing one deployment in the same instant can lose one change.** The
|
|
181
|
+
server's state store has no atomic compare-and-set. Until it does, deployments stay experimental.
|
|
182
|
+
The guide says to make changes from one place, or to pass `expectedVersion` and retry a conflict.
|
|
183
|
+
- **Documented limitation: `bucket()` spreads sequential ids unevenly.** Ids that differ only in their
|
|
184
|
+
last characters spread unevenly over a few hundred threads. Random ids, which the server gives by
|
|
185
|
+
default, spread evenly. The function's output is part of the stability promise, so it is not
|
|
186
|
+
changed in 2.x.
|