nexus-ai-pro 2.2.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 +225 -0
- package/CHANGELOG.md +325 -1
- package/README.md +20 -6
- 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/capabilities.d.ts +39 -0
- package/dist/agent/capabilities.js +36 -0
- package/dist/agent/create-agent.d.ts +61 -11
- package/dist/agent/create-agent.js +136 -22
- package/dist/agent/index.d.ts +3 -2
- package/dist/agent/index.js +1 -1
- package/dist/agent/middleware/approval.d.ts +26 -0
- package/dist/agent/middleware/approval.js +23 -0
- package/dist/agent/{middleware.d.ts → middleware/basic.d.ts} +5 -4
- package/dist/agent/{middleware.js → middleware/basic.js} +3 -5
- package/dist/agent/middleware/context-editor.d.ts +52 -0
- package/dist/agent/middleware/context-editor.js +66 -0
- package/dist/agent/middleware/filesystem.d.ts +44 -0
- package/dist/agent/middleware/filesystem.js +83 -0
- package/dist/agent/middleware/index.d.ts +19 -0
- package/dist/agent/middleware/index.js +9 -0
- package/dist/agent/middleware/limits.d.ts +42 -0
- package/dist/agent/middleware/limits.js +52 -0
- package/dist/agent/middleware/models.d.ts +48 -0
- package/dist/agent/middleware/models.js +44 -0
- package/dist/agent/middleware/pii.d.ts +67 -0
- package/dist/agent/middleware/pii.js +142 -0
- package/dist/agent/middleware/retry.d.ts +66 -0
- package/dist/agent/middleware/retry.js +59 -0
- package/dist/agent/middleware/shared.d.ts +41 -0
- package/dist/agent/middleware/shared.js +73 -0
- package/dist/agent/middleware/tool-selector.d.ts +64 -0
- package/dist/agent/middleware/tool-selector.js +106 -0
- package/dist/agent/permissions.d.ts +113 -0
- package/dist/agent/permissions.js +180 -0
- package/dist/agent/sandbox.d.ts +151 -0
- package/dist/agent/sandbox.js +257 -0
- package/dist/agent/tool.d.ts +8 -3
- package/dist/agent/tool.js +14 -3
- package/dist/core/secure-stream.js +4 -3
- package/dist/deep-agent/index.d.ts +109 -0
- package/dist/deep-agent/index.js +216 -0
- 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/functional.d.ts +9 -0
- package/dist/graph/functional.js +20 -3
- package/dist/graph/graph.js +27 -6
- package/dist/graph/lint.d.ts +4 -1
- package/dist/graph/lint.js +35 -0
- 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/postgres/fulltext.d.ts +67 -0
- package/dist/postgres/fulltext.js +91 -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/elasticsearch.d.ts +71 -0
- package/dist/rag/elasticsearch.js +130 -0
- package/dist/rag/file-ingestion.js +15 -9
- package/dist/rag/pipeline.d.ts +140 -0
- package/dist/rag/pipeline.js +187 -0
- package/dist/rag/rerankers.d.ts +92 -0
- package/dist/rag/rerankers.js +97 -0
- package/dist/rag/retrievers.d.ts +12 -1
- 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/assistant.d.ts +5 -1
- package/dist/server/assistant.js +4 -2
- package/dist/server/auth.d.ts +250 -0
- package/dist/server/auth.js +392 -0
- 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/store/memory.d.ts +10 -0
- package/dist/store/memory.js +10 -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/graph.d.ts +38 -0
- package/dist/types/messages.d.ts +36 -2
- package/dist/types/principal.d.ts +21 -0
- package/dist/types/principal.js +1 -0
- package/dist/types/server.d.ts +8 -9
- 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/utils/tenant.d.ts +11 -0
- package/dist/utils/tenant.js +14 -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/capabilities.d.ts +39 -0
- package/dist-cjs/agent/capabilities.js +41 -0
- package/dist-cjs/agent/create-agent.d.ts +61 -11
- package/dist-cjs/agent/create-agent.js +136 -22
- package/dist-cjs/agent/index.d.ts +3 -2
- package/dist-cjs/agent/index.js +4 -4
- package/dist-cjs/agent/middleware/approval.d.ts +26 -0
- package/dist-cjs/agent/middleware/approval.js +26 -0
- package/dist-cjs/agent/{middleware.d.ts → middleware/basic.d.ts} +5 -4
- package/dist-cjs/agent/{middleware.js → middleware/basic.js} +3 -5
- package/dist-cjs/agent/middleware/context-editor.d.ts +52 -0
- package/dist-cjs/agent/middleware/context-editor.js +70 -0
- package/dist-cjs/agent/middleware/filesystem.d.ts +44 -0
- package/dist-cjs/agent/middleware/filesystem.js +86 -0
- package/dist-cjs/agent/middleware/index.d.ts +19 -0
- package/dist-cjs/agent/middleware/index.js +28 -0
- package/dist-cjs/agent/middleware/limits.d.ts +42 -0
- package/dist-cjs/agent/middleware/limits.js +57 -0
- package/dist-cjs/agent/middleware/models.d.ts +48 -0
- package/dist-cjs/agent/middleware/models.js +48 -0
- package/dist-cjs/agent/middleware/pii.d.ts +67 -0
- package/dist-cjs/agent/middleware/pii.js +147 -0
- package/dist-cjs/agent/middleware/retry.d.ts +66 -0
- package/dist-cjs/agent/middleware/retry.js +63 -0
- package/dist-cjs/agent/middleware/shared.d.ts +41 -0
- package/dist-cjs/agent/middleware/shared.js +83 -0
- package/dist-cjs/agent/middleware/tool-selector.d.ts +64 -0
- package/dist-cjs/agent/middleware/tool-selector.js +109 -0
- package/dist-cjs/agent/permissions.d.ts +113 -0
- package/dist-cjs/agent/permissions.js +189 -0
- package/dist-cjs/agent/sandbox.d.ts +151 -0
- package/dist-cjs/agent/sandbox.js +297 -0
- package/dist-cjs/agent/tool.d.ts +8 -3
- package/dist-cjs/agent/tool.js +14 -3
- package/dist-cjs/core/secure-stream.js +4 -3
- package/dist-cjs/deep-agent/index.d.ts +109 -0
- package/dist-cjs/deep-agent/index.js +219 -0
- 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/functional.d.ts +9 -0
- package/dist-cjs/graph/functional.js +20 -3
- package/dist-cjs/graph/graph.js +27 -6
- package/dist-cjs/graph/lint.d.ts +4 -1
- package/dist-cjs/graph/lint.js +35 -0
- 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/postgres/fulltext.d.ts +67 -0
- package/dist-cjs/postgres/fulltext.js +129 -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/elasticsearch.d.ts +71 -0
- package/dist-cjs/rag/elasticsearch.js +135 -0
- package/dist-cjs/rag/file-ingestion.js +14 -8
- package/dist-cjs/rag/pipeline.d.ts +140 -0
- package/dist-cjs/rag/pipeline.js +191 -0
- package/dist-cjs/rag/rerankers.d.ts +92 -0
- package/dist-cjs/rag/rerankers.js +107 -0
- package/dist-cjs/rag/retrievers.d.ts +12 -1
- 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/assistant.d.ts +5 -1
- package/dist-cjs/server/assistant.js +4 -2
- package/dist-cjs/server/auth.d.ts +250 -0
- package/dist-cjs/server/auth.js +402 -0
- 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/store/memory.d.ts +10 -0
- package/dist-cjs/store/memory.js +10 -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/graph.d.ts +38 -0
- package/dist-cjs/types/messages.d.ts +36 -2
- package/dist-cjs/types/principal.d.ts +21 -0
- package/dist-cjs/types/principal.js +2 -0
- package/dist-cjs/types/server.d.ts +8 -9
- 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/utils/tenant.d.ts +11 -0
- package/dist-cjs/utils/tenant.js +15 -0
- package/dist-cjs/version.d.ts +1 -1
- package/dist-cjs/version.js +1 -1
- package/llms.txt +7 -3
- package/package.json +193 -6
package/API_STABILITY.md
CHANGED
|
@@ -41,6 +41,217 @@ 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
|
+
|
|
216
|
+
## 2.3 stage (2.3.0)
|
|
217
|
+
|
|
218
|
+
Everything 2.3 adds is stable from the start and additive: no default changes meaning.
|
|
219
|
+
|
|
220
|
+
- `ToolDefinition.capabilities` and the capability grammar; `permissionPolicy()`, `PermissionPolicy`,
|
|
221
|
+
`PermissionRules`, `PermissionRequest`, `PermissionVerdict`, `PermissionDecision`,
|
|
222
|
+
`PermissionPolicyLike`, `parseCapability()`, `capabilitiesOf()`, `isSensitiveCapability()`, and
|
|
223
|
+
`normalizePath()` (`nexus-ai-pro/agent/permissions`); `CreateAgentOptions.permissions`;
|
|
224
|
+
- the sandbox contract: `Sandbox`, its option, result, and isolation types, `sandboxTools()`,
|
|
225
|
+
`runSandboxConformance()` and its report types, `SandboxPathError` (`nexus-ai-pro/agent/sandbox`).
|
|
226
|
+
`processSandbox()` is a development reference and may change; conformance checks may be added;
|
|
227
|
+
- `NodeOptions.effects` and `interrupts`, `CompileOptions.tools`, `GraphToolDescription`, and the lint
|
|
228
|
+
codes `SENSITIVE_TOOL_WITHOUT_APPROVAL`, `UNDECLARED_TOOL_CAPABILITIES`, and
|
|
229
|
+
`SIDE_EFFECT_BEFORE_INTERRUPT`;
|
|
230
|
+
- `nexus-ai-pro/agent/middleware` and every middleware and option type on it;
|
|
231
|
+
`AgentMiddleware.wrapModelCall`, `AgentMiddlewareContext`, `AgentModelCallContext`, the third
|
|
232
|
+
argument of `wrapToolCall`, `next(call)`, and `AgentStopReason` `'stopped'`. The PII patterns
|
|
233
|
+
may be tightened in a minor release to cut false positives, and new `PiiKind` members may be
|
|
234
|
+
added;
|
|
235
|
+
- `nexus-ai-pro/server/auth`: `jwtAuth()`, `apiKeyAuth()`, `trustedProxyAuth()`, `anyAuth()`,
|
|
236
|
+
`createJwtVerifier()`, `hashApiKey()`, `JwtError` and its codes, and every option type. New
|
|
237
|
+
`JwtAlgorithm` and `JwtErrorCode` members may be added;
|
|
238
|
+
- `Principal.roles`, `method`, and `claims`; `GraphRunOptions.principal`, `NodeContext.principal`,
|
|
239
|
+
`WorkflowRunOptions.principal`, and `WorkflowContext.principal`; `ToolContext` and the second
|
|
240
|
+
argument of `ToolDefinition.execute`; `AgentMiddlewareContext.principal` and
|
|
241
|
+
`PermissionRequest.principal`. A checkpoint's `metadata.userId` is recorded when a run has a
|
|
242
|
+
principal with a subject;
|
|
243
|
+
- `SparseRetriever`; `PostgresKeywordIndex` and `keywordIndexMigrations()`
|
|
244
|
+
(`nexus-ai-pro/postgres/fulltext`); `ElasticsearchKeywordIndex` and `ElasticsearchError`
|
|
245
|
+
(`nexus-ai-pro/rag/elasticsearch`); and every reranker and option type on
|
|
246
|
+
`nexus-ai-pro/rag/rerankers`. The default endpoints of hosted rerankers follow their providers'
|
|
247
|
+
current API versions;
|
|
248
|
+
- `nexus-ai-pro/rag/pipeline`: `createIngestionPipeline()`, `ingestionExecutor()`, and their types.
|
|
249
|
+
The manifest's layout under `['nexus', 'ingestion', <name>]` is stable: a later release reads a
|
|
250
|
+
manifest an earlier one wrote;
|
|
251
|
+
- `nexus-ai-pro/deep-agent`: `createDeepAgent()`, `DeepAgentOptions`, `DeepSubagent`, and
|
|
252
|
+
`DeepSkill`, and the names and arguments of the tools it gives the model (`write_todos`,
|
|
253
|
+
`delegate`, `load_skill`, `edit_file`). The wording of its system prompt may change in any release.
|
|
254
|
+
|
|
44
255
|
## 2.2 stage (2.2.0)
|
|
45
256
|
|
|
46
257
|
Everything 2.2 adds is stable from the start and additive: no default changes meaning.
|
|
@@ -579,6 +790,9 @@ of the 1.x line.
|
|
|
579
790
|
|
|
580
791
|
## Deployment stage (1.24.0)
|
|
581
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
|
+
|
|
582
796
|
Deployments (`nexus-ai-pro/server/deployments`), tenant limits (`nexus-ai-pro/server/tenancy`), and the
|
|
583
797
|
server's worker queue are experimental in production readiness. Their contracts follow the 1.x rules.
|
|
584
798
|
|
|
@@ -593,6 +807,9 @@ server's worker queue are experimental in production readiness. Their contracts
|
|
|
593
807
|
|
|
594
808
|
## Team platform stage (1.23.0)
|
|
595
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
|
+
|
|
596
813
|
The context hub (`nexus-ai-pro/context-hub`), insights (`nexus-ai-pro/insights`), and the studio's
|
|
597
814
|
accounts are experimental in production readiness. Their contracts follow the 1.x rules.
|
|
598
815
|
|
|
@@ -605,6 +822,9 @@ accounts are experimental in production readiness. Their contracts follow the 1.
|
|
|
605
822
|
|
|
606
823
|
## Retrieval breadth stage (1.22.0)
|
|
607
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
|
+
|
|
608
828
|
The loaders (`nexus-ai-pro/loaders/*`), the Redis, Pinecone, Weaviate, Chroma, and SQLite vector
|
|
609
829
|
stores, the retrievers (`nexus-ai-pro/rag/retrievers`), and the MCP registry
|
|
610
830
|
(`nexus-ai-pro/mcp/registry`) are experimental in production readiness. Their contracts follow the
|
|
@@ -621,6 +841,8 @@ stores, the retrievers (`nexus-ai-pro/rag/retrievers`), and the MCP registry
|
|
|
621
841
|
|
|
622
842
|
## Durable execution stage (1.21.0)
|
|
623
843
|
|
|
844
|
+
The SQLite adapters graduated in 2.4; see the 2.4 stage for their evidence.
|
|
845
|
+
|
|
624
846
|
Functional workflows (`nexus-ai-pro/graph/functional`) and the SQLite adapters (`nexus-ai-pro/sqlite`)
|
|
625
847
|
are experimental in production readiness. Their contracts follow the 1.x rules.
|
|
626
848
|
|
|
@@ -633,6 +855,9 @@ are experimental in production readiness. Their contracts follow the 1.x rules.
|
|
|
633
855
|
|
|
634
856
|
## Retrieval stores stage (1.20.0)
|
|
635
857
|
|
|
858
|
+
`PostgresVectorStore` graduated in 2.4; see the 2.4 stage for its evidence. `QdrantVectorStore`
|
|
859
|
+
remains experimental.
|
|
860
|
+
|
|
636
861
|
`PostgresVectorStore` (`nexus-ai-pro/postgres/vectors`) and `QdrantVectorStore` (`nexus-ai-pro/rag/qdrant`)
|
|
637
862
|
are experimental in production readiness. The `VectorStore` contract they share with
|
|
638
863
|
`MemoryVectorStore` follows the 1.x rules: a minor release may add optional methods and options, not
|
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,328 @@ 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
|
+
|
|
189
|
+
## [2.3.0] - 2026-10-06
|
|
190
|
+
|
|
191
|
+
Agents that act safely, on production retrieval.
|
|
192
|
+
|
|
193
|
+
### Added
|
|
194
|
+
|
|
195
|
+
- **Capabilities and permission policies.** A tool declares what each call does —
|
|
196
|
+
`filesystem:write:<path>`, `network:<host>`, `shell:<command>`, `code`, or an effect of the
|
|
197
|
+
application's own — as a list or a function of its arguments. `permissionPolicy()`, on the new
|
|
198
|
+
`nexus-ai-pro/agent/permissions`, grants filesystem globs, network hosts, and shell command
|
|
199
|
+
prefixes, and decides each call: allow, deny, or ask. Paths are normalized before any grant sees
|
|
200
|
+
them, and a command that chains, pipes, or substitutes is never granted by a prefix.
|
|
201
|
+
`createAgent({ permissions })` enforces it before a tool runs: a denied call never runs, an `ask`
|
|
202
|
+
interrupts as `interruptOn` does, and arguments an approver edits are decided again.
|
|
203
|
+
- **A sandbox contract**, on the new `nexus-ai-pro/agent/sandbox`: the `Sandbox` interface a
|
|
204
|
+
container, VM, or hosted interpreter fills; `sandboxTools()`, whose calls declare exactly the
|
|
205
|
+
command or path they use; `runSandboxConformance()`, which proves any sandbox against the
|
|
206
|
+
contract; and `processSandbox()`, a reference for development that is never a security boundary
|
|
207
|
+
and says so.
|
|
208
|
+
- **The linter reads capabilities.** `SENSITIVE_TOOL_WITHOUT_APPROVAL` reports a tool that writes, runs
|
|
209
|
+
commands or code, or reaches the network with neither approval nor a policy;
|
|
210
|
+
`UNDECLARED_TOOL_CAPABILITIES` a tool whose effects cannot be judged; and
|
|
211
|
+
`SIDE_EFFECT_BEFORE_INTERRUPT` a node that declares `effects` and `interrupts`. An agent's graph
|
|
212
|
+
describes its tools for it.
|
|
213
|
+
- **A middleware catalog**, on the new `nexus-ai-pro/agent/middleware`, each a separate import:
|
|
214
|
+
`modelRetry()`, `modelFallback()` (to another model or another client), `dynamicModel()`,
|
|
215
|
+
`toolRetry()` (which by default repeats only a call that cannot have changed anything),
|
|
216
|
+
`toolSelector()` (by rule, embedding similarity, or both), `contextEditor()` (clears old tool
|
|
217
|
+
results in batches, so a prompt cache keeps working), `piiMiddleware()` (validated card numbers
|
|
218
|
+
and IBANs; redact, mask, hash, or block), `humanApproval()` (per call, in band or out of band),
|
|
219
|
+
`modelCallLimit()` (per run and per thread, the thread count shared through the store), and
|
|
220
|
+
`filesystemContext()` (instruction files in, large results out to a file). The three existing
|
|
221
|
+
middleware are there too.
|
|
222
|
+
- **A wider middleware seam.** `wrapModelCall` wraps the model call itself, and may call `next()`
|
|
223
|
+
again to retry or fall back. Every hook receives an `AgentMiddlewareContext`: the state, the
|
|
224
|
+
store, the thread and tenant, the run's signal, and `interrupt()`. `context.stop()` ends a run
|
|
225
|
+
with an answer and the new `stopReason: 'stopped'`. A `wrapToolCall` can pass `next()` changed
|
|
226
|
+
arguments, which the permission policy decides again.
|
|
227
|
+
- **Server authentication**, on the new `nexus-ai-pro/server/auth`. It is built on Web Crypto, with no
|
|
228
|
+
dependency:
|
|
229
|
+
- `jwtAuth()` takes an identity provider's key set (cached, and refetched when a token names a new
|
|
230
|
+
key), a public key, or a shared secret, and checks issuer, audience, expiry, and age. It refuses
|
|
231
|
+
`alg: none` and key confusion, and requires an audience with a key set.
|
|
232
|
+
- `apiKeyAuth()` compares keys by their SHA-256 hash, from `hashApiKey()`.
|
|
233
|
+
- `trustedProxyAuth()` refuses to exist without proof that the proxy sent the request.
|
|
234
|
+
- `anyAuth()` combines hooks.
|
|
235
|
+
- `createJwtVerifier()` verifies tokens outside the server.
|
|
236
|
+
- **One Principal, everywhere a run goes.** It gains `roles`, `method`, and `claims`.
|
|
237
|
+
- Graph and workflow runs take a `principal`, which nodes read as `context.principal`. Its tenant
|
|
238
|
+
becomes the run's, and its subject is recorded on every checkpoint and in the run's trace.
|
|
239
|
+
- `graphAssistant()` passes the authenticated caller on.
|
|
240
|
+
- Tools receive a `ToolContext` as the second argument of `execute`: the principal, the thread
|
|
241
|
+
and tenant, the run's signal, and the tenant's store.
|
|
242
|
+
- Middleware and permission policies see the principal too.
|
|
243
|
+
- **Sparse retrieval as a contract.** A `SparseRetriever` is keyword search that takes writes, so it
|
|
244
|
+
fuses with vector search and stays in step with a vector store. `KeywordIndex` is one. Two more
|
|
245
|
+
ship:
|
|
246
|
+
- `PostgresKeywordIndex` (`nexus-ai-pro/postgres/fulltext`) uses Postgres full-text search, with a
|
|
247
|
+
GIN index and ranking in the database. With `shared`, it searches a pgvector table through a
|
|
248
|
+
generated column, so hybrid search keeps one copy of the data.
|
|
249
|
+
- `ElasticsearchKeywordIndex` (`nexus-ai-pro/rag/elasticsearch`) works with Elasticsearch or
|
|
250
|
+
OpenSearch over the REST API, with no client library.
|
|
251
|
+
- **Rerankers**, on the new `nexus-ai-pro/rag/rerankers`, with no SDK:
|
|
252
|
+
- `cohereReranker()`, `voyageReranker()`, and `jinaReranker()` for hosted APIs;
|
|
253
|
+
- `teiReranker()` for a self-hosted cross-encoder;
|
|
254
|
+
- `httpReranker()` for any other API;
|
|
255
|
+
- `crossEncoderReranker()` for a model run in process.
|
|
256
|
+
- **Durable ingestion**, on the new `nexus-ai-pro/rag/pipeline`. `createIngestionPipeline()` keeps a
|
|
257
|
+
manifest in any `Store`: each document's content version, its chunking, the embedding model, and
|
|
258
|
+
each chunk's version. A run:
|
|
259
|
+
- embeds only new and changed chunks; chunks are named by their text, so one that only moved keeps
|
|
260
|
+
its embedding;
|
|
261
|
+
- deletes the chunks and documents that are gone;
|
|
262
|
+
- keeps keyword indexes in step;
|
|
263
|
+
- writes to the stores before the manifest.
|
|
264
|
+
|
|
265
|
+
`ingestionExecutor()` runs it as a durable operation, and a retry starts at the document the
|
|
266
|
+
failed attempt stopped on.
|
|
267
|
+
- **A deep-agent preset**, on the new `nexus-ai-pro/deep-agent`. `createDeepAgent()` is
|
|
268
|
+
`createAgent()` composed with:
|
|
269
|
+
- a plan, kept in the transcript;
|
|
270
|
+
- a sandboxed workspace, with `edit_file` for precise changes and commands granted by name;
|
|
271
|
+
- helpers behind one `delegate` tool, which never get a tool that needs approval;
|
|
272
|
+
- skills loaded on demand;
|
|
273
|
+
- instruction files and context offloading;
|
|
274
|
+
- context editing, optional tool selection, and a default permission policy.
|
|
275
|
+
|
|
276
|
+
It returns the same compiled graph as any agent; it is not a new engine.
|
|
277
|
+
- `processSandbox()` loads Node's modules when first used, so `nexus-ai-pro/agent/sandbox`, and a
|
|
278
|
+
deep agent over a container sandbox, import on any runtime.
|
|
279
|
+
|
|
280
|
+
### Fixed
|
|
281
|
+
|
|
282
|
+
- `MemoryStore` swept every item for expiry on every write, so writing n items took time
|
|
283
|
+
proportional to n². It now sweeps only once an item has a time to live, and at most once a second.
|
|
284
|
+
Expired items were already hidden from reads.
|
|
285
|
+
|
|
286
|
+
- `limitToolCalls()` counted calls in memory shared by every run of an agent, so one thread's calls
|
|
287
|
+
used up another's limit, and the count never reset. It now counts per run from the transcript.
|
|
288
|
+
- A subgraph run through `asNode()` now runs for its parent's tenant, so its store is the tenant's
|
|
289
|
+
view, as the parent's is.
|
|
290
|
+
- `sandboxTools()` file tools accept a path that names the mount, such as `/workspace/notes.txt`,
|
|
291
|
+
as well as one relative to it, and say in their descriptions which to use.
|
|
292
|
+
|
|
293
|
+
### Proof
|
|
294
|
+
|
|
295
|
+
- In a real agent tool loop, a write outside the workspace and a request to an unlisted host are
|
|
296
|
+
refused before their tools run, and a granted command that needs approval waits for a person.
|
|
297
|
+
- The process sandbox passes the conformance suite, and a sandbox that leaks the host's environment
|
|
298
|
+
and writes outside its root fails exactly those two checks.
|
|
299
|
+
- An agent over 150 tools completes 40 tasks, a third of them needing two tools, with
|
|
300
|
+
`toolSelector()` at equal quality: every task succeeds either way. Input tokens per task fall from
|
|
301
|
+
about 64,000 to about 5,200, and latency by about 70%: the model's time computed from
|
|
302
|
+
each request's size, plus the agent's own measured time. Two experiments, reported by
|
|
303
|
+
`compareExperiments()`, show it.
|
|
304
|
+
- Each middleware is proved in a real agent loop. For example:
|
|
305
|
+
- a charge that timed out is never retried;
|
|
306
|
+
- an approver who raises a refund past what the policy allows has the edit refused;
|
|
307
|
+
- two agents sharing a store share one thread budget;
|
|
308
|
+
- a 45,000-character tool result reaches the transcript as a preview and a file.
|
|
309
|
+
- A JWT from a test identity provider is verified against its key set and reaches an agent's tool
|
|
310
|
+
call as a `Principal` with its subject, tenant, roles, and scopes.
|
|
311
|
+
- The tool's writes land in that tenant's view of the store.
|
|
312
|
+
- The checkpoint records who ran the step.
|
|
313
|
+
- Another tenant's token gets 404 for the thread.
|
|
314
|
+
- Expired, wrong-audience, wrong-issuer, unsigned, and forged tokens are refused.
|
|
315
|
+
- The provider rotates its key with one refetch.
|
|
316
|
+
- On the stored support dataset, on real Postgres with full-text search and pgvector, hybrid retrieval
|
|
317
|
+
beats vector-only: recall@5 0.71 → 0.97 and mean reciprocal rank 0.51 → 0.71, both with a 95%
|
|
318
|
+
interval above zero. A hosted reranker and a local cross-encoder, compared in the same experiment,
|
|
319
|
+
each lift mean reciprocal rank to 0.97. One contract test runs against all four keyword indexes.
|
|
320
|
+
- An ingestion of 100,000 documents dies halfway inside a durable operation. Its retry starts at the
|
|
321
|
+
document the first attempt stopped on, and embeds no chunk that had finished. A second run after
|
|
322
|
+
ten documents are edited embeds exactly ten chunks and deletes their old versions.
|
|
323
|
+
- A deep agent completes a multi-step task on a fixture repository inside the reference sandbox. It
|
|
324
|
+
plans, runs the failing test, reads and edits the bug, verifies the fix, has a helper review it,
|
|
325
|
+
loads a skill, and records the change; the test then passes outside the agent. Along the way, a
|
|
326
|
+
30,000-character log is offloaded to a file. The default policy refuses an unlisted command, a
|
|
327
|
+
chained command, a write outside the workspace, and an ungranted tool.
|
|
328
|
+
|
|
7
329
|
## [2.2.0] - 2026-10-05
|
|
8
330
|
|
|
9
331
|
Production scale and safe upgrades. Every database schema is versioned, so an upgrade applies only
|
|
@@ -1637,7 +1959,9 @@ shared policy vocabulary is in place for a future release that revisits this.
|
|
|
1637
1959
|
- URL fetching rejects unsafe private-network targets and limits response reads.
|
|
1638
1960
|
- CLI and audit findings no longer disclose detected secret values.
|
|
1639
1961
|
|
|
1640
|
-
[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
|
|
1964
|
+
[2.3.0]: https://github.com/mkhitar-abrahamyan/nexus-ai/compare/v2.2.0...v2.3.0
|
|
1641
1965
|
[2.2.0]: https://github.com/mkhitar-abrahamyan/nexus-ai/compare/v2.1.0...v2.2.0
|
|
1642
1966
|
[2.1.0]: https://github.com/mkhitar-abrahamyan/nexus-ai/compare/v2.0.0...v2.1.0
|
|
1643
1967
|
[2.0.0]: https://github.com/mkhitar-abrahamyan/nexus-ai/compare/v1.25.0...v2.0.0
|