nexus-ai-pro 2.7.0 → 2.9.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 +119 -3
- package/CHANGELOG.md +241 -1
- package/README.md +21 -3
- package/SECURITY.md +41 -1
- package/dist/batch/manager.js +16 -33
- package/dist/batch/openai-client.d.ts +83 -0
- package/dist/batch/openai-client.js +120 -0
- package/dist/batch/openai.d.ts +12 -21
- package/dist/batch/openai.js +33 -125
- package/dist/batch/poll.d.ts +22 -0
- package/dist/batch/poll.js +30 -0
- package/dist/cli/models.d.ts +36 -0
- package/dist/cli/models.js +170 -0
- package/dist/cli.js +11 -1
- package/dist/deep-agent/helpers.d.ts +4 -0
- package/dist/deep-agent/helpers.js +56 -4
- package/dist/doctor/index.d.ts +16 -1
- package/dist/doctor/index.js +10 -5
- package/dist/embeddings/adapters.d.ts +2 -2
- package/dist/embeddings/adapters.js +24 -13
- package/dist/embeddings/batch-google.d.ts +40 -0
- package/dist/embeddings/batch-google.js +128 -0
- package/dist/embeddings/batch-mock.d.ts +45 -0
- package/dist/embeddings/batch-mock.js +71 -0
- package/dist/embeddings/batch-openai.d.ts +23 -0
- package/dist/embeddings/batch-openai.js +55 -0
- package/dist/embeddings/batch.d.ts +230 -0
- package/dist/embeddings/batch.js +282 -0
- package/dist/embeddings/cache.d.ts +81 -0
- package/dist/embeddings/cache.js +116 -0
- package/dist/embeddings/engine.d.ts +7 -0
- package/dist/embeddings/engine.js +110 -68
- package/dist/embeddings/google-wire.d.ts +32 -0
- package/dist/embeddings/google-wire.js +33 -0
- package/dist/embeddings/index.d.ts +1 -1
- package/dist/embeddings/inputs.d.ts +30 -0
- package/dist/embeddings/inputs.js +103 -0
- package/dist/embeddings/mock.d.ts +7 -1
- package/dist/embeddings/mock.js +8 -2
- package/dist/embeddings/models.js +21 -0
- package/dist/evaluate/online.d.ts +5 -0
- package/dist/evaluate/online.js +74 -5
- package/dist/images/asset-stores.d.ts +47 -1
- package/dist/images/asset-stores.js +135 -2
- package/dist/images/asset-support.d.ts +94 -1
- package/dist/images/asset-support.js +159 -3
- package/dist/images/assets.d.ts +10 -3
- package/dist/images/assets.js +15 -2
- package/dist/lifecycle/budget.d.ts +60 -3
- package/dist/lifecycle/budget.js +147 -3
- package/dist/lifecycle/index.d.ts +2 -2
- package/dist/lifecycle/reservations.d.ts +46 -0
- package/dist/lifecycle/reservations.js +67 -0
- package/dist/media/index.d.ts +244 -0
- package/dist/media/index.js +262 -0
- package/dist/media/mistral.d.ts +34 -0
- package/dist/media/mistral.js +90 -0
- package/dist/media/mock.d.ts +36 -0
- package/dist/media/mock.js +45 -0
- package/dist/media/rag.d.ts +216 -0
- package/dist/media/rag.js +340 -0
- package/dist/models/data.d.ts +87 -0
- package/dist/models/data.js +235 -0
- package/dist/models/registry.d.ts +2 -1
- package/dist/models/registry.js +3 -2
- package/dist/postgres/embedding-cache.d.ts +29 -0
- package/dist/postgres/embedding-cache.js +58 -0
- package/dist/postgres/tenancy.d.ts +26 -1
- package/dist/postgres/tenancy.js +116 -1
- package/dist/postgres/traces.d.ts +2 -1
- package/dist/postgres/traces.js +13 -1
- package/dist/rag/chroma.d.ts +13 -1
- package/dist/rag/chroma.js +36 -13
- package/dist/rag/pinecone.js +2 -2
- package/dist/rag/pipeline.d.ts +17 -2
- package/dist/rag/pipeline.js +95 -14
- package/dist/rag/qdrant.js +2 -2
- package/dist/rag/redis.d.ts +2 -1
- package/dist/rag/redis.js +56 -18
- package/dist/rag/vector-helpers.d.ts +5 -0
- package/dist/rag/vector-helpers.js +7 -0
- package/dist/rag/weaviate.d.ts +15 -1
- package/dist/rag/weaviate.js +75 -12
- package/dist/server/tenancy.d.ts +33 -2
- package/dist/server/tenancy.js +162 -0
- package/dist/sqlite/embedding-cache.d.ts +34 -0
- package/dist/sqlite/embedding-cache.js +61 -0
- package/dist/tracing/index.d.ts +2 -2
- package/dist/tracing/index.js +1 -1
- package/dist/tracing/query.d.ts +5 -1
- package/dist/tracing/query.js +14 -1
- package/dist/tracing/stores.d.ts +2 -2
- package/dist/tracing/stores.js +2 -2
- package/dist/types/config.d.ts +5 -0
- package/dist/types/embeddings.d.ts +87 -5
- package/dist/types/images.d.ts +2 -2
- package/dist/types/lifecycle.d.ts +92 -1
- package/dist/types/tracing.d.ts +20 -1
- package/dist/utils/redis-command.d.ts +15 -0
- package/dist/utils/redis-command.js +5 -0
- package/dist/utils/sha256.d.ts +9 -0
- package/dist/utils/sha256.js +6 -0
- package/dist/utils/vector-bytes.d.ts +11 -0
- package/dist/utils/vector-bytes.js +18 -0
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/dist/video/errors.d.ts +37 -0
- package/dist/video/errors.js +22 -0
- package/dist/video/google.d.ts +52 -0
- package/dist/video/google.js +248 -0
- package/dist/video/index.d.ts +426 -0
- package/dist/video/index.js +666 -0
- package/dist/video/mock.d.ts +62 -0
- package/dist/video/mock.js +97 -0
- package/dist/video/runway.d.ts +47 -0
- package/dist/video/runway.js +241 -0
- package/dist-cjs/batch/manager.js +16 -33
- package/dist-cjs/batch/openai-client.d.ts +83 -0
- package/dist-cjs/batch/openai-client.js +125 -0
- package/dist-cjs/batch/openai.d.ts +12 -21
- package/dist-cjs/batch/openai.js +32 -124
- package/dist-cjs/batch/poll.d.ts +22 -0
- package/dist-cjs/batch/poll.js +33 -0
- package/dist-cjs/cli/models.d.ts +36 -0
- package/dist-cjs/cli/models.js +175 -0
- package/dist-cjs/deep-agent/helpers.d.ts +4 -0
- package/dist-cjs/deep-agent/helpers.js +56 -4
- package/dist-cjs/doctor/index.d.ts +16 -1
- package/dist-cjs/doctor/index.js +10 -5
- package/dist-cjs/embeddings/adapters.d.ts +2 -2
- package/dist-cjs/embeddings/adapters.js +23 -12
- package/dist-cjs/embeddings/batch-google.d.ts +40 -0
- package/dist-cjs/embeddings/batch-google.js +132 -0
- package/dist-cjs/embeddings/batch-mock.d.ts +45 -0
- package/dist-cjs/embeddings/batch-mock.js +75 -0
- package/dist-cjs/embeddings/batch-openai.d.ts +23 -0
- package/dist-cjs/embeddings/batch-openai.js +59 -0
- package/dist-cjs/embeddings/batch.d.ts +230 -0
- package/dist-cjs/embeddings/batch.js +320 -0
- package/dist-cjs/embeddings/cache.d.ts +81 -0
- package/dist-cjs/embeddings/cache.js +125 -0
- package/dist-cjs/embeddings/engine.d.ts +7 -0
- package/dist-cjs/embeddings/engine.js +143 -68
- package/dist-cjs/embeddings/google-wire.d.ts +32 -0
- package/dist-cjs/embeddings/google-wire.js +38 -0
- package/dist-cjs/embeddings/index.d.ts +1 -1
- package/dist-cjs/embeddings/inputs.d.ts +30 -0
- package/dist-cjs/embeddings/inputs.js +141 -0
- package/dist-cjs/embeddings/mock.d.ts +7 -1
- package/dist-cjs/embeddings/mock.js +8 -2
- package/dist-cjs/embeddings/models.js +21 -0
- package/dist-cjs/evaluate/online.d.ts +5 -0
- package/dist-cjs/evaluate/online.js +74 -5
- package/dist-cjs/images/asset-stores.d.ts +47 -1
- package/dist-cjs/images/asset-stores.js +133 -0
- package/dist-cjs/images/asset-support.d.ts +94 -1
- package/dist-cjs/images/asset-support.js +169 -3
- package/dist-cjs/images/assets.d.ts +10 -3
- package/dist-cjs/images/assets.js +17 -1
- package/dist-cjs/lifecycle/budget.d.ts +60 -3
- package/dist-cjs/lifecycle/budget.js +147 -3
- package/dist-cjs/lifecycle/index.d.ts +2 -2
- package/dist-cjs/lifecycle/reservations.d.ts +46 -0
- package/dist-cjs/lifecycle/reservations.js +71 -0
- package/dist-cjs/media/index.d.ts +244 -0
- package/dist-cjs/media/index.js +269 -0
- package/dist-cjs/media/mistral.d.ts +34 -0
- package/dist-cjs/media/mistral.js +94 -0
- package/dist-cjs/media/mock.d.ts +36 -0
- package/dist-cjs/media/mock.js +49 -0
- package/dist-cjs/media/rag.d.ts +216 -0
- package/dist-cjs/media/rag.js +344 -0
- package/dist-cjs/models/data.d.ts +87 -0
- package/dist-cjs/models/data.js +245 -0
- package/dist-cjs/models/registry.d.ts +2 -1
- package/dist-cjs/models/registry.js +3 -2
- package/dist-cjs/postgres/embedding-cache.d.ts +29 -0
- package/dist-cjs/postgres/embedding-cache.js +96 -0
- package/dist-cjs/postgres/tenancy.d.ts +26 -1
- package/dist-cjs/postgres/tenancy.js +115 -0
- package/dist-cjs/postgres/traces.d.ts +2 -1
- package/dist-cjs/postgres/traces.js +13 -1
- package/dist-cjs/rag/chroma.d.ts +13 -1
- package/dist-cjs/rag/chroma.js +35 -12
- package/dist-cjs/rag/pinecone.js +1 -1
- package/dist-cjs/rag/pipeline.d.ts +17 -2
- package/dist-cjs/rag/pipeline.js +95 -14
- package/dist-cjs/rag/qdrant.js +1 -1
- package/dist-cjs/rag/redis.d.ts +2 -1
- package/dist-cjs/rag/redis.js +55 -17
- package/dist-cjs/rag/vector-helpers.d.ts +5 -0
- package/dist-cjs/rag/vector-helpers.js +8 -0
- package/dist-cjs/rag/weaviate.d.ts +15 -1
- package/dist-cjs/rag/weaviate.js +74 -11
- package/dist-cjs/server/tenancy.d.ts +33 -2
- package/dist-cjs/server/tenancy.js +162 -0
- package/dist-cjs/sqlite/embedding-cache.d.ts +34 -0
- package/dist-cjs/sqlite/embedding-cache.js +99 -0
- package/dist-cjs/tracing/index.d.ts +2 -2
- package/dist-cjs/tracing/index.js +3 -1
- package/dist-cjs/tracing/query.d.ts +5 -1
- package/dist-cjs/tracing/query.js +16 -1
- package/dist-cjs/tracing/stores.d.ts +2 -2
- package/dist-cjs/tracing/stores.js +3 -1
- package/dist-cjs/types/config.d.ts +5 -0
- package/dist-cjs/types/embeddings.d.ts +87 -5
- package/dist-cjs/types/images.d.ts +2 -2
- package/dist-cjs/types/lifecycle.d.ts +92 -1
- package/dist-cjs/types/tracing.d.ts +20 -1
- package/dist-cjs/utils/redis-command.d.ts +15 -0
- package/dist-cjs/utils/redis-command.js +8 -0
- package/dist-cjs/utils/sha256.d.ts +9 -0
- package/dist-cjs/utils/sha256.js +7 -0
- package/dist-cjs/utils/vector-bytes.d.ts +11 -0
- package/dist-cjs/utils/vector-bytes.js +22 -0
- package/dist-cjs/version.d.ts +1 -1
- package/dist-cjs/version.js +1 -1
- package/dist-cjs/video/errors.d.ts +37 -0
- package/dist-cjs/video/errors.js +27 -0
- package/dist-cjs/video/google.d.ts +52 -0
- package/dist-cjs/video/google.js +252 -0
- package/dist-cjs/video/index.d.ts +426 -0
- package/dist-cjs/video/index.js +708 -0
- package/dist-cjs/video/mock.d.ts +62 -0
- package/dist-cjs/video/mock.js +101 -0
- package/dist-cjs/video/runway.d.ts +47 -0
- package/dist-cjs/video/runway.js +245 -0
- package/llms.txt +3 -1
- package/package.json +215 -4
package/API_STABILITY.md
CHANGED
|
@@ -41,6 +41,121 @@ 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.9 stage (2.9.0)
|
|
45
|
+
|
|
46
|
+
Everything 2.9 adds is stable from the start and additive, unless this section says otherwise.
|
|
47
|
+
|
|
48
|
+
New and stable:
|
|
49
|
+
- `OperationFamily` gains `video`;
|
|
50
|
+
- `nexus-ai-pro/video`, `/video/google`, `/video/runway`, and `/video/mock` are new and experimental:
|
|
51
|
+
video generation graduates by the checklist once Veo and Runway pass its conformance suite live;
|
|
52
|
+
- `RunQuery.after` with `RunCursor`, and `runCursor()` and `isAfterCursor()` on
|
|
53
|
+
`nexus-ai-pro/tracing`. A store of your own that does not honour `after` still works with the
|
|
54
|
+
online-evaluation worker, which falls back to offsets;
|
|
55
|
+
- `OnlineSchedulePass.paging`;
|
|
56
|
+
- on `nexus-ai-pro/lifecycle`: `BudgetReservation.id`; `BudgetReservationStatus`,
|
|
57
|
+
`BudgetReservationRecord`, `BudgetReservationOutcome`, `BudgetRecoveryReport`, and
|
|
58
|
+
`BudgetRecoverOptions`; `BudgetLedger.renew()`, `settle()`, and `recover()`, all optional;
|
|
59
|
+
`BudgetLedgerOptions.leaseMs` and `uncertain`; `BudgetLedgerWithReport.reservation()`; and the five
|
|
60
|
+
optional reservation methods of `BudgetUsageStore` with `BudgetReservationChange`. The statuses,
|
|
61
|
+
and which outcome moves a reservation from which status, are part of the promise;
|
|
62
|
+
- `hold()`, `settle()`, `renew()`, `lapsed()`, and `reservation()` on `MemoryTenantUsage`,
|
|
63
|
+
`RedisTenantUsage`, and `PostgresTenantUsage`, and the tenancy migration version 2 with its
|
|
64
|
+
reservations table;
|
|
65
|
+
- on `nexus-ai-pro/media/rag`, experimental with the media family: `MediaIndexOptions.manifest` and
|
|
66
|
+
`name`, `MediaIndexEntry`, `MediaIndexReader`, `MediaIndexReport.unchanged`, and
|
|
67
|
+
`MediaIndex.delete()`, `reindex()`, `describe()`, and `list()`.
|
|
68
|
+
|
|
69
|
+
Changed, each to keep a promise the surface already made:
|
|
70
|
+
- `TraceStore.query()` orders runs that share a start time by id, from last to first, as code units,
|
|
71
|
+
so a page means the same on every store. Before, that order was not defined.
|
|
72
|
+
- `MemoryBudgetUsage`, the ledger's default store, records reservations, so `reserve()` returns one
|
|
73
|
+
with an `id`. An online-evaluation worker reserves every run of its evaluators, a run after a crash
|
|
74
|
+
included, where before it reserved only a first.
|
|
75
|
+
- A deep agent with a checkpointer writes the helpers it creates to `<thread>/helpers-created`, so
|
|
76
|
+
`createHelpers.max` holds for a thread across processes, as it says.
|
|
77
|
+
|
|
78
|
+
## 2.8 stage (2.8.0)
|
|
79
|
+
|
|
80
|
+
Everything 2.8 adds is stable from the start and additive, unless this section says otherwise.
|
|
81
|
+
|
|
82
|
+
New and stable:
|
|
83
|
+
- `ChromaVectorStoreOptions.filterFields`;
|
|
84
|
+
- `EmbeddingCacheStore`, `EmbeddingCacheEntry`, and `EmbeddingCacheConfig` with its `store`;
|
|
85
|
+
`nexus-ai-pro/embeddings/cache`: `embeddingCacheKey()` and `EmbeddingCacheContext`, `packVector()`
|
|
86
|
+
and `unpackVector()`, `MemoryEmbeddingCache` and its options, `RedisEmbeddingCache` with its client
|
|
87
|
+
and options, and `tieredEmbeddingCache()`. A key's derivation and a vector's packed layout are part
|
|
88
|
+
of the promise, so a cache one release wrote is read by the next;
|
|
89
|
+
- `EmbeddingModality`, `EmbeddingPart`, and `EmbeddingParts` as `EmbeddingInput`;
|
|
90
|
+
`EmbeddingProviderRequest.contents` with `EmbeddingProviderPart`, `EmbeddingProviderTextPart`, and
|
|
91
|
+
`EmbeddingProviderMediaPart`; `inputModalities` on `EmbeddingProviderCapabilities` and
|
|
92
|
+
`EmbeddingModelCapabilities`, and `costPerImage`; `MockEmbeddingProviderOptions.describeMedia`. An
|
|
93
|
+
adapter that declares no `inputModalities` is sent text only, as before;
|
|
94
|
+
- `nexus-ai-pro/embeddings/batch`: `EmbeddingBatchManager` and its config and runtime, its request,
|
|
95
|
+
item, result, and output types, the `EmbeddingBatchProvider` contract with its info, capabilities,
|
|
96
|
+
request, and item, `batchEmbedder()` with `BatchEmbedder` and its options; the OpenAI and mock
|
|
97
|
+
adapters on `/openai` and `/mock`. `GoogleEmbeddingBatchProvider` on `/google` is experimental
|
|
98
|
+
until a live run is recorded;
|
|
99
|
+
- on `nexus-ai-pro/images/assets`: `AssetStore.putStream()` and `getStream()`, both optional;
|
|
100
|
+
`putAssetStream()` and `readAssetStream()`, `DEFAULT_BUFFERED_ASSET_BYTES`, `AssetByteSource`,
|
|
101
|
+
`StreamAssetInput`, `AssetByteRange`, `AssetStreamOptions`, `StreamAssetDescriptor`, and
|
|
102
|
+
`PutAssetStreamOptions`; `S3LikeClient.putObjectStream()` and `getObjectStream()`, both optional.
|
|
103
|
+
The images family stays experimental, and these with it;
|
|
104
|
+
- `nexus-ai-pro/models/data`: `RegistryData`, `REGISTRY_DATA_FORMAT`, `checkRegistryData()`,
|
|
105
|
+
`parseRegistryData()` with `RegistryDataError`, `bundledRegistryData()`, `withRegistryData()`,
|
|
106
|
+
`diffRegistryData()` with `RegistryDiff` and `RegistryFieldChange`, and `registryDataAgeDays()`;
|
|
107
|
+
`ModelRegistryConfig.verifiedAt` and `DoctorOptions.models`; the commands `nexus models export`,
|
|
108
|
+
`check`, and `refresh`. The `nexus-registry/1` format is read by every 2.x release;
|
|
109
|
+
- `nexus-ai-pro/media`, `/media/mistral`, `/media/mock`, and `/media/rag` are new and experimental: media
|
|
110
|
+
understanding graduates by the checklist, once a vision model and the OCR service pass its
|
|
111
|
+
conformance suite live. `OperationFamily` gains `media`, and `AssetProvenance.operation` gains
|
|
112
|
+
`upload`, both stable;
|
|
113
|
+
- `IngestionPipelineOptions.batchEmbed` and `batchesInFlight`, and `IngestionReport.batches` and
|
|
114
|
+
`batchesRecovered`. `IngestionPipelineOptions.embed` is optional when `batchEmbed` is given;
|
|
115
|
+
- `nexus-ai-pro/postgres/embedding-cache`: `PostgresEmbeddingCache`, its options, and
|
|
116
|
+
`embeddingCacheMigrations()`; `nexus-ai-pro/sqlite/embedding-cache`: `SqliteEmbeddingCache`, its
|
|
117
|
+
options, and `sqliteEmbeddingCacheMigrations()`.
|
|
118
|
+
|
|
119
|
+
Changed, each to keep a promise the surface already made:
|
|
120
|
+
- `OpenAIBatchProvider` refuses `endpoint: '/v1/embeddings'` with a `BatchCapabilityError`; it sent
|
|
121
|
+
chat bodies there, which never embedded anything.
|
|
122
|
+
- The Qdrant, Redis, Pinecone, Weaviate, and Chroma stores refuse a `topK` that is not a positive
|
|
123
|
+
integer with a `RangeError`. An absent `topK`, or 0, still means 5.
|
|
124
|
+
- A replacement in Chroma removes the metadata fields the new version lacks; before, Chroma merged
|
|
125
|
+
them. A Weaviate filter is typed by the collection's schema, so a value of another type than its
|
|
126
|
+
property matches nothing instead of failing the search.
|
|
127
|
+
|
|
128
|
+
### Graduation
|
|
129
|
+
|
|
130
|
+
The Qdrant, Redis, Weaviate, and Chroma vector stores leave experimental status, by the same
|
|
131
|
+
checklist as in 2.4. The live evidence comes from the scheduled live workflow, which runs every
|
|
132
|
+
check against each server; the stand-in evidence runs in CI on every change.
|
|
133
|
+
|
|
134
|
+
**The remote vector stores** (`QdrantVectorStore`, `RedisVectorStore`, `WeaviateVectorStore`,
|
|
135
|
+
`ChromaVectorStore`):
|
|
136
|
+
|
|
137
|
+
| Requirement | Evidence |
|
|
138
|
+
| --- | --- |
|
|
139
|
+
| API stability | Covered by the 2.x compatibility rules, with no planned breaking change |
|
|
140
|
+
| Conformance | The vector store contract and typed filters, against each real server, Redis over RESP3 and RESP2: `tests/vector-stores.live.ts`; against stand-ins that fail as the servers do: `tests/vector-stores.test.ts` |
|
|
141
|
+
| Crash recovery | n/a: a store keeps no run state, and a reload upserts the same ids |
|
|
142
|
+
| Concurrency | Ten writers replacing the same twenty ids at once leave each id as one writer's version, found only by that writer's filters, live and against stand-ins that interleave as a network does |
|
|
143
|
+
| Load | 2,000 chunks written, then 200 searches within a p95 budget of 200 ms on each server: `tests/vector-stores.live.ts` |
|
|
144
|
+
| Tenant isolation | Each store under `tenantVectorStore()`, live and in `tests/tenant-isolation.test.ts` |
|
|
145
|
+
| Security | [Review](./SECURITY.md#the-qdrant-redis-weaviate-and-chroma-vector-stores): four findings fixed, two documented limitations |
|
|
146
|
+
| Upgrade | What the published 2.7.0 wrote is read, filtered, replaced, and deleted by this release, live and in `tests/upgrade-remote-stores.test.ts` |
|
|
147
|
+
| Soak | 1,000 write, search, and delete cycles on each server, with the heap within 8 MB |
|
|
148
|
+
|
|
149
|
+
Chroma graduates in both modes. Without `filterFields`, two writers replacing one id at once can
|
|
150
|
+
leave a stale filter field, which its guide states; with `filterFields`, a replacement stays whole
|
|
151
|
+
under any race.
|
|
152
|
+
|
|
153
|
+
**Still experimental**, each with what remains:
|
|
154
|
+
- **The Pinecone store.** It passes every check against a stand-in, and the live workflow runs the
|
|
155
|
+
same checks against Pinecone once the repository's Pinecone secret is set.
|
|
156
|
+
- **Images.** Recorded live conformance must pass on all three backends. The live workflow records it
|
|
157
|
+
for each backend whose credential is set.
|
|
158
|
+
|
|
44
159
|
## 2.7 stage (2.7.0)
|
|
45
160
|
|
|
46
161
|
Everything 2.7 adds is stable from the start and additive.
|
|
@@ -996,7 +1111,8 @@ accounts are experimental in production readiness. Their contracts follow the 1.
|
|
|
996
1111
|
## Retrieval breadth stage (1.22.0)
|
|
997
1112
|
|
|
998
1113
|
The loaders, the SQLite vector store, the retrievers, and the MCP registry graduated in 2.4; see the
|
|
999
|
-
2.4 stage for their evidence. The Redis,
|
|
1114
|
+
2.4 stage for their evidence. The Redis, Weaviate, and Chroma stores graduated in 2.8; see the 2.8
|
|
1115
|
+
stage. The Pinecone store remains experimental.
|
|
1000
1116
|
|
|
1001
1117
|
The loaders (`nexus-ai-pro/loaders/*`), the Redis, Pinecone, Weaviate, Chroma, and SQLite vector
|
|
1002
1118
|
stores, the retrievers (`nexus-ai-pro/rag/retrievers`), and the MCP registry
|
|
@@ -1028,8 +1144,8 @@ are experimental in production readiness. Their contracts follow the 1.x rules.
|
|
|
1028
1144
|
|
|
1029
1145
|
## Retrieval stores stage (1.20.0)
|
|
1030
1146
|
|
|
1031
|
-
`PostgresVectorStore` graduated in 2.4
|
|
1032
|
-
|
|
1147
|
+
`PostgresVectorStore` graduated in 2.4, and `QdrantVectorStore` in 2.8; see those stages for their
|
|
1148
|
+
evidence.
|
|
1033
1149
|
|
|
1034
1150
|
`PostgresVectorStore` (`nexus-ai-pro/postgres/vectors`) and `QdrantVectorStore` (`nexus-ai-pro/rag/qdrant`)
|
|
1035
1151
|
are experimental in production readiness. The `VectorStore` contract they share with
|
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,244 @@ Notable changes to this project are recorded here. The format follows [Keep a Ch
|
|
|
4
4
|
|
|
5
5
|
## [Unreleased]
|
|
6
6
|
|
|
7
|
+
## [2.9.0] - 2026-10-15
|
|
8
|
+
|
|
9
|
+
Video, and everything shipped, proven.
|
|
10
|
+
|
|
11
|
+
### Added
|
|
12
|
+
|
|
13
|
+
- **Video generation.** `nexus-ai-pro/video`: `VideoManager` makes videos from a prompt, a first or
|
|
14
|
+
last frame, or reference images, through a provider's asynchronous job. `generate()` is a durable
|
|
15
|
+
operation that records the job the moment it exists and each video as it is stored, so
|
|
16
|
+
`recover()` in another worker collects a job whose process died, never submitting it twice, and
|
|
17
|
+
streams each video into an asset store. Each generation runs in the lifecycle's new `video`
|
|
18
|
+
family, and is priced per second by `priceVideo()` from `VIDEO_PRICES`, the Veo 3.1 list prices,
|
|
19
|
+
or the account's own. `start()`, `resume()`, `status()`, `download()`, and `cancel()` work from a
|
|
20
|
+
JSON `VideoJobRef` in any process. A request is checked against the model's capabilities before
|
|
21
|
+
any job, and a failed job is submitted again only when the provider says that may help.
|
|
22
|
+
- `GoogleVideoProvider` (`/video/google`): Veo through its long-running predictions, on the
|
|
23
|
+
Gemini API, the video read from Google's URI with the key, or on Vertex AI, read from Cloud
|
|
24
|
+
Storage or inline.
|
|
25
|
+
- `RunwayVideoProvider` (`/video/runway`): Runway's task API, for its own models and the hosted
|
|
26
|
+
ones it serves, Veo, Gemini Omni Flash, and Seedance among them; each video read from its signed
|
|
27
|
+
URL without the secret.
|
|
28
|
+
- `MockVideoProvider` (`/video/mock`), and `runVideoConformance()`, which all three pass.
|
|
29
|
+
|
|
30
|
+
New guide `docs/video.md`. The family is experimental until Veo and Runway pass the conformance
|
|
31
|
+
suite live. OpenAI's Videos API was removed on 2026-09-24, so there is no OpenAI adapter.
|
|
32
|
+
- **The experimental families, live.** `npm run test:families:live`, and a weekly *Family
|
|
33
|
+
conformance* job beside the vector stores: media understanding's conformance suite against an
|
|
34
|
+
OpenAI or Gemini vision model and Mistral's OCR, on a PDF and a PNG the script builds; a two-input
|
|
35
|
+
batch through the Gemini embedding batch tier, waited on for 20 minutes and cancelled past that;
|
|
36
|
+
and, when the repository variable `NEXUS_LIVE_VIDEO` is set, the video conformance suite on Veo 3.1
|
|
37
|
+
Lite and Runway. Each check runs where its key is set, and what it measured is kept. These are the
|
|
38
|
+
runs media, the Gemini batch tier, and video graduate on.
|
|
39
|
+
- **Paging by cursor.** `RunQuery.after` takes a `RunCursor`, the start time and id of a page's last
|
|
40
|
+
run, and returns only the runs after it; `runCursor()` takes the cursor from a run, and
|
|
41
|
+
`isAfterCursor()` is the test on its own, for a trace store of your own. Every bundled store
|
|
42
|
+
honours it, and `applyQuery()` does for a store that filters in memory. A new Postgres trace store
|
|
43
|
+
migration, version 3, indexes runs in query order.
|
|
44
|
+
- **Budget reservations that outlive their process.** Over a store that records reservations, a
|
|
45
|
+
`budgetLedger()` holds each one as a `BudgetReservationRecord` under a lease (`leaseMs`, 10
|
|
46
|
+
minutes), and moves it with its total in one step: `reserved`, then `settled`, `released`,
|
|
47
|
+
`expired`, or `uncertain`. `recover(resolve)` settles reservations whose lease lapsed by what
|
|
48
|
+
became of each operation, a `BudgetReservationOutcome`; `settle(id, outcome)` does it for one from
|
|
49
|
+
any process; `renew()` extends a lease; and `uncertain: 'charge' | 'release'` says what an unknown
|
|
50
|
+
outcome costs. `MemoryBudgetUsage`, `MemoryTenantUsage`, `RedisTenantUsage`, and
|
|
51
|
+
`PostgresTenantUsage` all record them: Redis keeps a reservation in its total's Cluster slot, so one
|
|
52
|
+
script moves both, and Postgres does it in one statement, in the reservations table of a new
|
|
53
|
+
tenancy migration, version 2. A store of your own records them through five optional methods on
|
|
54
|
+
`BudgetUsageStore`.
|
|
55
|
+
- **A media index that remembers what it holds.** `MediaIndexOptions.manifest`, any `Store`, with a
|
|
56
|
+
`name`, keeps one `MediaIndexEntry` per medium: a hash of its content, source, metadata, and
|
|
57
|
+
indexing options, where it is kept, its pages, its chunk ids, the embedding model, and the
|
|
58
|
+
`MediaIndexReader` that read and described it. `add()` then skips a medium at the same version and
|
|
59
|
+
replaces exactly the chunks and asset of one that changed, and `MediaIndex` gains `delete()`,
|
|
60
|
+
`reindex()`, `describe()`, and `list()`. `MediaIndexReport.unchanged` counts what was skipped. A
|
|
61
|
+
change is recorded as pending first, so a crash leaves nothing the next call cannot finish.
|
|
62
|
+
|
|
63
|
+
### Changed
|
|
64
|
+
|
|
65
|
+
- Runs that started in the same millisecond come by id, from last to first, compared as code units,
|
|
66
|
+
on every trace store. The order of such runs was not defined before, and the memory and Postgres
|
|
67
|
+
stores disagreed on it.
|
|
68
|
+
|
|
69
|
+
### Fixed
|
|
70
|
+
|
|
71
|
+
- An online-evaluation worker reads a backlog of runs that started in the same millisecond through,
|
|
72
|
+
however many pages it spans. Before, it resumed each page at the last run's start time, so a page
|
|
73
|
+
that ended among such runs was read again on every pass, and `drain()` never finished. On a trace
|
|
74
|
+
store of your own that does not honour `RunQuery.after`, the worker pages by offset instead, and
|
|
75
|
+
its `OnlineSchedulePass` says `paging: 'offset'`.
|
|
76
|
+
- A budget reservation held by an online-evaluation worker that dies no longer stays charged for the
|
|
77
|
+
period. The worker records the reservation just before it calls its evaluators, and whoever takes
|
|
78
|
+
over settles it: charged at what the scores cost if they were written, given back if the
|
|
79
|
+
evaluators never ran, and by the ledger's `uncertain` policy if they ran and wrote nothing.
|
|
80
|
+
- An evaluation run again after a crash is reserved and charged. Its evaluators run again to find
|
|
81
|
+
the scores still missing, and before, only a first run drew on the budget.
|
|
82
|
+
- A deep agent resumed after a crash counts the helpers it created before. With a checkpointer, each
|
|
83
|
+
created helper is recorded, with its instructions, on `<thread>/helpers-created` before the call
|
|
84
|
+
that created it returns, so the resumed agent cannot pass `createHelpers.max` and delegates to them
|
|
85
|
+
again by name. Before, the count was kept by the process, and a resumed agent could create `max`
|
|
86
|
+
more and no longer found the ones it had made.
|
|
87
|
+
|
|
88
|
+
### Proof
|
|
89
|
+
|
|
90
|
+
- `tests/video.test.ts`: the mock, Veo on the Gemini API and Vertex AI, and Runway pass the video
|
|
91
|
+
conformance suite against stand-ins for their APIs. A request a model cannot make is refused
|
|
92
|
+
before any job. A generation runs through the lifecycle, streams three megabytes into a
|
|
93
|
+
filesystem store, and is priced per second. A generation whose process dies after submitting, or
|
|
94
|
+
after storing its video, is collected by another worker with one submission and one stored video.
|
|
95
|
+
If the recorded job is ignored, the job is submitted twice.
|
|
96
|
+
- `tests/online-evaluation-paging.test.ts`: the memory, JSONL, and Postgres trace stores order 5,000
|
|
97
|
+
runs, 4,000 of them in one millisecond, identically, and page through them by cursor without a
|
|
98
|
+
repeat or a gap. Ten workers reading 1,000 a page schedule each of them exactly once on every
|
|
99
|
+
store, and on a store that ignores the cursor. The previous worker never reads past the burst.
|
|
100
|
+
- `tests/budget-reservations.test.ts`: on the memory, tenant memory, Redis, and Postgres stores a
|
|
101
|
+
reservation moves with its total, is settled from another process by its operation's outcome, and
|
|
102
|
+
of two processes settling it, one changes the total. An online-evaluation worker killed while
|
|
103
|
+
holding a reservation, before its evaluator, during it, or after its scores, leaves the budget at
|
|
104
|
+
what the judge billed once another worker takes over. With recovery switched off, the same test
|
|
105
|
+
finds the dead worker's estimate still charged.
|
|
106
|
+
- `tests/media-rag.test.ts`: with a manifest, an unchanged medium is neither read nor written, a
|
|
107
|
+
changed one keeps exactly its chunks and one asset, and a deleted one leaves none, with a crash at
|
|
108
|
+
each write of a first index, a change, and a delete. Without the pending record, the crash proof
|
|
109
|
+
fails.
|
|
110
|
+
- `tests/deep-agent-helpers.test.ts`: an agent that created its last allowed helper, killed and
|
|
111
|
+
continued in another process, is refused a second and delegates to the first again by name. Without
|
|
112
|
+
the record read back, the second is created.
|
|
113
|
+
|
|
114
|
+
## [2.8.0] - 2026-10-14
|
|
115
|
+
|
|
116
|
+
Retrieval at production scale, and media that is understood.
|
|
117
|
+
|
|
118
|
+
### Added
|
|
119
|
+
|
|
120
|
+
- **Graduation.** The Qdrant, Redis, Weaviate, and Chroma vector stores leave experimental status.
|
|
121
|
+
Each passes its contract and the graduation checklist against the real server in the scheduled
|
|
122
|
+
live workflow: ten writers racing on the same ids, what 2.7.0 wrote read by this release, tenant
|
|
123
|
+
isolation, a load budget, and a soak. The evidence is in `API_STABILITY.md`, and the threat review
|
|
124
|
+
in `SECURITY.md`. The Pinecone store passes the same checks against a stand-in, and graduates once
|
|
125
|
+
the live workflow runs them against Pinecone.
|
|
126
|
+
- **A shared embedding cache.** `embeddings.cache.store` takes an `EmbeddingCacheStore`, which
|
|
127
|
+
reads every input of a request in one `getMany()` and writes what was embedded in one `setMany()`.
|
|
128
|
+
Keys are SHA-256 hashes from `embeddingCacheKey()`, so no text is a key, and vectors are packed
|
|
129
|
+
float32. On `nexus-ai-pro/embeddings/cache`: `MemoryEmbeddingCache`, `RedisEmbeddingCache` (one
|
|
130
|
+
`MGET` and one script a batch, or a command a key on Redis Cluster), `tieredEmbeddingCache()`, and
|
|
131
|
+
`packVector()` with `unpackVector()`. `PostgresEmbeddingCache` is on
|
|
132
|
+
`nexus-ai-pro/postgres/embedding-cache`, and `SqliteEmbeddingCache` on
|
|
133
|
+
`nexus-ai-pro/sqlite/embedding-cache`, each with its versioned migrations and `purgeExpired()`.
|
|
134
|
+
- **Images, audio, and documents as embedding input.** An `EmbeddingInput` may hold `EmbeddingParts`:
|
|
135
|
+
the text, image, audio, and document parts a message takes, embedded as one vector in the same
|
|
136
|
+
space as text. A model takes the `EmbeddingModality` kinds its registry entry or adapter declares in
|
|
137
|
+
`inputModalities`, and anything else is refused before any call; a fallback that cannot take the
|
|
138
|
+
media is skipped. An adapter receives each input's parts in `EmbeddingProviderRequest.contents`,
|
|
139
|
+
media already resolved to base64 or a URL. Google sends media inline or by a Files API URI, and
|
|
140
|
+
writes `gemini-embedding-2`'s task as the text prefix that model reads instead of a task type; Cohere
|
|
141
|
+
sends text and data-URI images as `inputs`. `gemini-embedding-2` joins the registry, with
|
|
142
|
+
`costPerImage`, and `embed-v4.0` takes images. `MockEmbeddingProviderOptions.describeMedia` puts a
|
|
143
|
+
medium and its caption in one space for tests.
|
|
144
|
+
- **A batch tier for embeddings**, on the new `nexus-ai-pro/embeddings/batch`: `EmbeddingBatchManager`
|
|
145
|
+
submits, polls, collects, and prices at the provider's batch rate, usually half, with `submit()`,
|
|
146
|
+
`start()`, `resume()`, `status()`, and `cancel()`. Adapters: `OpenAIEmbeddingBatchProvider` on
|
|
147
|
+
`/openai`, `GoogleEmbeddingBatchProvider` (`asyncBatchEmbedContent`, media included) on `/google`,
|
|
148
|
+
and `MockEmbeddingBatchProvider` on `/mock`. `batchEmbedder()` gives an ingestion pipeline a batch
|
|
149
|
+
tier.
|
|
150
|
+
- **Ingestion through a batch tier.** `IngestionPipelineOptions.batchEmbed` takes a batch tier in
|
|
151
|
+
place of `embed`. Chunks are gathered into windows, each one provider batch, with `batchesInFlight`
|
|
152
|
+
(4) outstanding, and written in order. A durable run records each batch the moment it is
|
|
153
|
+
submitted, and a retry collects it rather than submitting it again. `IngestionReport` counts
|
|
154
|
+
`batches` and `batchesRecovered`.
|
|
155
|
+
- **Streaming asset stores.** `AssetStore` gains the optional `putStream()` and `getStream()`, and
|
|
156
|
+
`putAssetStream()` with `readAssetStream()` stream through any store, falling back to `put()` and
|
|
157
|
+
`get()`. The filesystem and S3 stores write a stream a chunk at a time, checking its size limit and
|
|
158
|
+
checksum as it flows and leaving nothing behind when either fails, and read it back whole or by an
|
|
159
|
+
`AssetByteRange`. `S3LikeClient` takes an optional `putObjectStream()` and `getObjectStream()`.
|
|
160
|
+
- **Registry data on its own**, on the new `nexus-ai-pro/models/data`: the model and embedding
|
|
161
|
+
registries as a `RegistryData` file (`nexus-registry/1`) the application supplies.
|
|
162
|
+
`checkRegistryData()` and `parseRegistryData()` name every problem with its path,
|
|
163
|
+
`withRegistryData()` layers a file under the application's own entries and over the bundled ones,
|
|
164
|
+
`bundledRegistryData()` exports the bundled data, and `diffRegistryData()` compares two files.
|
|
165
|
+
`models.verifiedAt` measures freshness from the file, in `checkRegistryFreshness()` and `nexus
|
|
166
|
+
doctor`, which takes the configuration as `models`. `nexus models export`, `check`, and `refresh`
|
|
167
|
+
work with the file; `refresh` compares it with each provider's own model list.
|
|
168
|
+
- **Media understanding**, on the new `nexus-ai-pro/media`: `MediaManager` reads a document's or an
|
|
169
|
+
image's text page by page, describes an image, and answers a question about media, routing each
|
|
170
|
+
task to the provider named, its default, or the first that can, and running each call as one
|
|
171
|
+
`media` operation of the client's lifecycle. `modelMediaProvider()` does all three through any
|
|
172
|
+
vision model and the client's own `complete()`; `MistralOcrProvider`, on `/mistral`, reads PDFs,
|
|
173
|
+
slides, and images into Markdown pages with their sizes and picture boxes; `MockMediaProvider`, on
|
|
174
|
+
`/mock`, stands in for tests. `runMediaConformance()` checks any provider. `OperationFamily` gains
|
|
175
|
+
`media`.
|
|
176
|
+
- **Media search and RAG**, on the new `nexus-ai-pro/media/rag`: `createMediaIndex()` keeps media in
|
|
177
|
+
any vector store as their pages' text, captions, and, on a model that takes them, their own
|
|
178
|
+
vectors, and keeps each medium in an asset store, or by its URL, so a hit can hand it back.
|
|
179
|
+
`search()` returns each medium once at its best chunk, `resolve()` returns the medium, and
|
|
180
|
+
`answerFromMedia()` hands the model the retrieved media themselves. `AssetProvenance.operation`
|
|
181
|
+
takes `upload`, for media an application brings in.
|
|
182
|
+
- `ChromaVectorStoreOptions.filterFields`: the fields a search can filter on. Every write then sets
|
|
183
|
+
each declared field, or removes it, so a replacement needs no read and stays whole under any race;
|
|
184
|
+
a filter on another field is refused.
|
|
185
|
+
|
|
186
|
+
### Changed
|
|
187
|
+
|
|
188
|
+
- The Qdrant, Redis, Pinecone, Weaviate, and Chroma stores refuse a `topK` that is not a positive
|
|
189
|
+
integer, before any request. An absent `topK`, or 0, still means 5.
|
|
190
|
+
- `RedisVectorStore` replaces a chunk with one atomic script instead of a delete and a write.
|
|
191
|
+
- An embedding `cache.adapter` is asked for every input at once, where it was asked for one input
|
|
192
|
+
after another: a 2,000-text request made 2,000 sequential reads. Its keys are unchanged, so
|
|
193
|
+
processes of this release and the last share entries during a rollout.
|
|
194
|
+
|
|
195
|
+
### Fixed
|
|
196
|
+
|
|
197
|
+
- `RedisVectorStore` failed on every command with an ioredis client, which also has a
|
|
198
|
+
`sendCommand()` that takes its own command object; it now uses `call()` whenever a client has it.
|
|
199
|
+
It also reads a search reply in RESP3, which ioredis 6 speaks by default, as well as RESP2.
|
|
200
|
+
- `WeaviateVectorStore` failed a search whose filter value had another type than its property, such
|
|
201
|
+
as `'3'` on a number. It now chooses the operand from the collection's schema, read once, so such a
|
|
202
|
+
filter matches nothing, as in every other store, and an `int` property gets `valueInt`.
|
|
203
|
+
- A `topK` from a request could change a Weaviate or Redis query, since both placed it in the query
|
|
204
|
+
text.
|
|
205
|
+
- A replacement could keep a filter field the new version lacks, so a filter, such as a tenant's,
|
|
206
|
+
still found the chunk by its old value. In Chroma, which merges metadata, it happened on every
|
|
207
|
+
replacement, and kept a replaced `source` too; in Redis, when two writers raced.
|
|
208
|
+
- `BatchManager` submitted a batch again when a worker died after submitting it and before collecting
|
|
209
|
+
it, so the provider ran, and billed, both. A submission now records its batch the moment it exists,
|
|
210
|
+
and a later attempt collects that one.
|
|
211
|
+
- `OpenAIBatchProvider` read only the output file, so every request that failed was missing from the
|
|
212
|
+
results; it now reads the error file too. It also refuses the `/v1/embeddings` endpoint its options
|
|
213
|
+
offered, since it sent chat bodies there: embeddings are batched by `OpenAIEmbeddingBatchProvider`.
|
|
214
|
+
- After two writers replaced one object, Weaviate's filter index could return it for a value it no
|
|
215
|
+
longer had. Every filtered hit is now checked against the object's own fields, and the store asks
|
|
216
|
+
for more when a stale entry took a place.
|
|
217
|
+
|
|
218
|
+
### Proof
|
|
219
|
+
|
|
220
|
+
- `npm run test:vectors:live` runs the contract and the graduation checklist against each server,
|
|
221
|
+
Redis over RESP3 and RESP2, and passes 35 of 35 checks locally against Qdrant, Weaviate 1.40.1,
|
|
222
|
+
Chroma 1.0, and Redis Stack with ioredis 6.0.0. The scheduled workflow keeps its measurements.
|
|
223
|
+
- The stand-ins now fail as the servers do: an ioredis-shaped client, RESP3 replies, Weaviate's typed
|
|
224
|
+
filter errors and stale filter entries, Chroma's merged metadata, and a seeded network delay that
|
|
225
|
+
interleaves racing writers. Each failure above reproduces against them on the previous code.
|
|
226
|
+
- `tests/upgrade-remote-stores.test.ts` reads, with this release, what the published 2.7.0 wrote into
|
|
227
|
+
each store.
|
|
228
|
+
- `tests/media-rag.test.ts`: with stand-in models, answers given the retrieved charts are right on
|
|
229
|
+
every question, and answers from the same hits' text on none.
|
|
230
|
+
- `tests/media.test.ts`: the vision-model, Mistral OCR, and mock providers pass the media conformance
|
|
231
|
+
suite, and the wire shapes each sends are asserted.
|
|
232
|
+
- `tests/registry-data.test.ts`: a price raised tenfold in a supplied file makes the next call cost
|
|
233
|
+
ten times as much, for completions and embeddings alike.
|
|
234
|
+
- `npm run bench:streams`, a step of the release gate: a gigabyte goes through the filesystem and S3
|
|
235
|
+
stores and back while memory grows by less than 128 MB.
|
|
236
|
+
- `tests/embedding-batch.test.ts`: an ingestion of 100,000 chunks through a batch tier dies while it
|
|
237
|
+
collects its third window, and across both attempts each of its ten windows is submitted once;
|
|
238
|
+
without the recorded batches, two are submitted twice.
|
|
239
|
+
- `tests/embeddings-media.test.ts`: a text query finds the image it describes through one vector
|
|
240
|
+
space, and media never reaches a model that takes text only.
|
|
241
|
+
- `tests/embedding-cache.test.ts`: a second process embeds a 2,000-text batch with no provider call
|
|
242
|
+
and one cache read, and every store keeps one contract, which the live suite also runs against
|
|
243
|
+
Redis over RESP3 and RESP2.
|
|
244
|
+
|
|
7
245
|
## [2.7.0] - 2026-10-12
|
|
8
246
|
|
|
9
247
|
Agents that do more, and evaluation that runs on its own.
|
|
@@ -2321,7 +2559,9 @@ shared policy vocabulary is in place for a future release that revisits this.
|
|
|
2321
2559
|
- URL fetching rejects unsafe private-network targets and limits response reads.
|
|
2322
2560
|
- CLI and audit findings no longer disclose detected secret values.
|
|
2323
2561
|
|
|
2324
|
-
[Unreleased]: https://github.com/mkhitar-abrahamyan/nexus-ai/compare/v2.
|
|
2562
|
+
[Unreleased]: https://github.com/mkhitar-abrahamyan/nexus-ai/compare/v2.9.0...HEAD
|
|
2563
|
+
[2.9.0]: https://github.com/mkhitar-abrahamyan/nexus-ai/compare/v2.8.0...v2.9.0
|
|
2564
|
+
[2.8.0]: https://github.com/mkhitar-abrahamyan/nexus-ai/compare/v2.7.0...v2.8.0
|
|
2325
2565
|
[2.7.0]: https://github.com/mkhitar-abrahamyan/nexus-ai/compare/v2.6.0...v2.7.0
|
|
2326
2566
|
[2.6.0]: https://github.com/mkhitar-abrahamyan/nexus-ai/compare/v2.5.0...v2.6.0
|
|
2327
2567
|
[2.5.0]: https://github.com/mkhitar-abrahamyan/nexus-ai/compare/v2.4.0...v2.5.0
|
package/README.md
CHANGED
|
@@ -155,6 +155,8 @@ from the doc comments. The guides live in the repository, so these links go to G
|
|
|
155
155
|
| [Loaders](https://github.com/mkhitar-abrahamyan/nexus-ai/blob/main/docs/loaders.md) | Files, Markdown, HTML, CSV, JSON, PDF, web pages, sitemaps, and Git repositories into retrieval |
|
|
156
156
|
| [Retrieval](https://github.com/mkhitar-abrahamyan/nexus-ai/blob/main/docs/retrieval.md) | Hybrid search, reranking, MMR, parent documents, and Redis, Pinecone, Weaviate, and Chroma stores |
|
|
157
157
|
| [Embeddings and retrieval](https://github.com/mkhitar-abrahamyan/nexus-ai/blob/main/docs/embeddings.md) | Embeddings as a routed operation family, and RAG helpers |
|
|
158
|
+
| [Media understanding](https://github.com/mkhitar-abrahamyan/nexus-ai/blob/main/docs/media.md) | Reading documents and images page by page, describing images, and answering questions about them, through any vision model or OCR |
|
|
159
|
+
| [Video generation](https://github.com/mkhitar-abrahamyan/nexus-ai/blob/main/docs/video.md) | Videos from a prompt or a first frame, on Google Veo and Runway, as durable jobs streamed into an asset store and priced per second |
|
|
158
160
|
| [Images (experimental)](https://github.com/mkhitar-abrahamyan/nexus-ai/blob/main/docs/images.md) | Generation and masked edits over three backends, input safety, moderation, asset stores |
|
|
159
161
|
| [Voice](https://github.com/mkhitar-abrahamyan/nexus-ai/blob/main/docs/voice.md) | Transcription, speech, voice turns, and voice sessions |
|
|
160
162
|
| [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 |
|
|
@@ -216,11 +218,13 @@ interface, or enum, has no doc comment, and `npm run docs:guides` fails when a g
|
|
|
216
218
|
every export of the entry points it covers, or its generated reference is stale. Both hold at 100%;
|
|
217
219
|
`--list` names what is missing, and `npm run docs:update` regenerates the references.
|
|
218
220
|
|
|
219
|
-
Real provider conformance,
|
|
221
|
+
Real provider conformance, the vector store contract against real servers, and the experimental
|
|
222
|
+
families against their live services are opt-in:
|
|
220
223
|
|
|
221
224
|
```bash
|
|
222
225
|
npm run test:conformance:real
|
|
223
226
|
npm run test:vectors:live
|
|
227
|
+
npm run test:families:live
|
|
224
228
|
```
|
|
225
229
|
|
|
226
230
|
## Roadmap
|
|
@@ -279,11 +283,25 @@ Shipped so far:
|
|
|
279
283
|
- 2.7 agents that do more, and evaluation that runs on its own: workspace search and a multimodal
|
|
280
284
|
workspace, a container sandbox, an interpreter, helpers that run in the background and survive a
|
|
281
285
|
crash, and tool search on every provider; datasets generated from documents and from the
|
|
282
|
-
guardrails' attacks; and online evaluation on workers, within a budget
|
|
286
|
+
guardrails' attacks; and online evaluation on workers, within a budget;
|
|
287
|
+
- 2.8 retrieval at production scale, and media that is understood: the Qdrant, Redis, Weaviate, and
|
|
288
|
+
Chroma stores out of experimental after their checklist ran against the real servers; a shared
|
|
289
|
+
embedding cache; images, audio, and documents as embedding input; a half-price embedding batch tier
|
|
290
|
+
that ingestion survives a crash through; streaming asset stores; registry data you supply and
|
|
291
|
+
refresh; and reading, describing, and searching media, with answers given the media themselves;
|
|
292
|
+
- 2.9 video, and everything shipped, proven: videos from a prompt or a first frame on Google Veo and
|
|
293
|
+
Runway, as durable jobs another worker collects after a crash, streamed into an asset store and
|
|
294
|
+
priced per second; online evaluation that reads every run however many share a millisecond, and
|
|
295
|
+
budget reservations a dead worker leaves settled by what its call did; a deep agent's helper limit
|
|
296
|
+
across processes; a media index that remembers what it holds; and the experimental families run
|
|
297
|
+
against their live services every week.
|
|
283
298
|
|
|
284
299
|
Upgrading from 1.x: `npx nexus migrate src --write` moves your imports, and
|
|
285
300
|
[MIGRATING.md](https://github.com/mkhitar-abrahamyan/nexus-ai/blob/main/MIGRATING.md) covers the rest.
|
|
286
|
-
Next,
|
|
301
|
+
Next, 2.10 makes every conversation that runs on a worker durable, A2A tasks, ACP turns, and
|
|
302
|
+
realtime sessions, and adds Gemini Live as a second realtime provider; Pinecone, images, the Gemini
|
|
303
|
+
embedding batch tier, media understanding, and video graduate once the live workflow passes against
|
|
304
|
+
each. The
|
|
287
305
|
[roadmap](https://github.com/mkhitar-abrahamyan/nexus-ai/blob/main/ROADMAP.md) lists what comes after, in the order
|
|
288
306
|
applications ask for it.
|
|
289
307
|
|
package/SECURITY.md
CHANGED
|
@@ -52,7 +52,7 @@ what it could do with that input. Each review is published here with its finding
|
|
|
52
52
|
before the surface graduates. A finding is closed in one of two ways: by a fix with a test that
|
|
53
53
|
names the attack, or by a documented limitation that the surface's guide states.
|
|
54
54
|
|
|
55
|
-
These reviews were done for 2.4, and for 2.5 where a review says so.
|
|
55
|
+
These reviews were done for 2.4, and for 2.5 and 2.8 where a review says so.
|
|
56
56
|
|
|
57
57
|
### SQLite adapters
|
|
58
58
|
|
|
@@ -77,6 +77,46 @@ Trust boundary: metadata filters, which applications often build from a request.
|
|
|
77
77
|
|
|
78
78
|
Findings: none.
|
|
79
79
|
|
|
80
|
+
### The Qdrant, Redis, Weaviate, and Chroma vector stores
|
|
81
|
+
|
|
82
|
+
Reviewed for 2.8, when they graduated. Pinecone's adapter was reviewed with them.
|
|
83
|
+
|
|
84
|
+
Trust boundary: a search's `topK` and metadata filter, which applications often build from a
|
|
85
|
+
request; and the server, which the store trusts as it trusts its own database. Credentials travel
|
|
86
|
+
only in headers, never in a URL or an error message.
|
|
87
|
+
- Qdrant, Pinecone, and Chroma receive a filter as JSON. Qdrant's keys are placed under `metadata.`,
|
|
88
|
+
so a filter cannot reach a chunk's content or vector.
|
|
89
|
+
- Redis filters only on the fields the index declares. A filter value is tagged with its type, and
|
|
90
|
+
every character that is not a letter or a digit is escaped.
|
|
91
|
+
- Weaviate's query is GraphQL. The collection and every filtered property must be a valid name, and
|
|
92
|
+
each value is a quoted literal.
|
|
93
|
+
|
|
94
|
+
Findings:
|
|
95
|
+
- **Fixed in 2.8: a `topK` from a request could change a Weaviate or Redis query.** Both stores
|
|
96
|
+
placed it in the query text, so `5) { … }` became part of the query. Every remote store now refuses
|
|
97
|
+
a `topK` that is not a positive integer before anything is sent. Proof: that value, a fraction, a
|
|
98
|
+
negative number, and `NaN` are refused by all five stores.
|
|
99
|
+
- **Fixed in 2.8: a replacement could keep a filter field the new version lacks.** A filter could
|
|
100
|
+
then still find the chunk by its old value, and that includes the `tenantId` that
|
|
101
|
+
`tenantVectorStore()` filters on.
|
|
102
|
+
- Chroma merges metadata on upsert, so it happened on every replacement.
|
|
103
|
+
- Redis deleted and rewrote a chunk in two commands, so it happened when two writers raced.
|
|
104
|
+
|
|
105
|
+
Chroma now removes each field the new version lacks, and Redis replaces a chunk in one atomic
|
|
106
|
+
script. Proof: ten writers race on the same twenty ids, live and against stand-ins that interleave
|
|
107
|
+
as a network does, and each id ends as exactly one writer's version.
|
|
108
|
+
- **Fixed in 2.8: Weaviate's filter index can keep an entry for a value an object no longer has**,
|
|
109
|
+
after two writers replace it at once (seen on Weaviate 1.40.1). The store now checks every filtered
|
|
110
|
+
hit against the object's own fields, and asks for more when a stale entry took a place. A result
|
|
111
|
+
always matches its filter.
|
|
112
|
+
- **Documented limitation: Chroma without `filterFields` reads before it replaces**, so two writers
|
|
113
|
+
replacing one id at once can leave a stale field. With `filterFields`, every write sets each
|
|
114
|
+
declared field, and a replacement stays whole under any race.
|
|
115
|
+
- **Documented limitation: the Redis store has no timeout of its own.** It sends through the client
|
|
116
|
+
you pass, so the client's command timeout applies.
|
|
117
|
+
- `tenantVectorStore()` checks each result's id and tenant stamp as well as filtering, so a stale
|
|
118
|
+
filter entry in any server cannot hand one tenant another's chunk.
|
|
119
|
+
|
|
80
120
|
### Loaders
|
|
81
121
|
|
|
82
122
|
Trust boundary: everything a loader reads is untrusted. A repository, a website, a sitemap, or an
|
package/dist/batch/manager.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { isTerminalBatchStatus } from '../types/batch.js';
|
|
2
1
|
import { OperationRunner } from '../operations/runner.js';
|
|
3
2
|
import { estimateCost } from '../optimizer/cost.js';
|
|
4
3
|
import { DEFAULT_CURRENCY } from '../optimizer/cost.js';
|
|
5
4
|
import { generateRequestId } from '../utils/ids.js';
|
|
6
5
|
import { withLifecycle } from '../lifecycle/run.js';
|
|
7
6
|
import { BatchCapabilityError, BatchProviderNotFoundError, BatchValidationError } from './errors.js';
|
|
7
|
+
import { pollUntilSettled } from './poll.js';
|
|
8
8
|
const DEFAULT_POLL_INTERVAL_MS = 30_000;
|
|
9
9
|
const DEFAULT_MAX_POLL_INTERVAL_MS = 300_000;
|
|
10
10
|
const DEFAULT_TIMEOUT_MS = 26 * 60 * 60 * 1000;
|
|
@@ -58,7 +58,11 @@ export class BatchManager {
|
|
|
58
58
|
idempotencyKey: request.idempotencyKey,
|
|
59
59
|
attempt: operation.attempt,
|
|
60
60
|
};
|
|
61
|
-
|
|
61
|
+
let ref = operation.previousHeartbeat?.batchRef;
|
|
62
|
+
if (!ref) {
|
|
63
|
+
ref = await provider.submit(request, context);
|
|
64
|
+
await operation.heartbeat({ batchRef: ref });
|
|
65
|
+
}
|
|
62
66
|
operation.report({ completed: 0, total: request.items.length, message: `submitted as ${ref.id}` });
|
|
63
67
|
return this.collect(provider, ref, request, operation, context);
|
|
64
68
|
}, (result) => ({ cost: result.cost.amount })), {
|
|
@@ -103,22 +107,16 @@ export class BatchManager {
|
|
|
103
107
|
});
|
|
104
108
|
}
|
|
105
109
|
async collect(provider, ref, request, operation, context) {
|
|
106
|
-
const
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
message: state.status,
|
|
117
|
-
});
|
|
118
|
-
await delay(interval, context.signal);
|
|
119
|
-
interval = Math.min(Math.round(interval * 1.5), maxInterval);
|
|
120
|
-
state = await provider.poll(ref, context);
|
|
121
|
-
}
|
|
110
|
+
const state = await pollUntilSettled(() => provider.poll(ref, context), {
|
|
111
|
+
intervalMs: request.pollIntervalMs ?? this.config.pollIntervalMs ?? DEFAULT_POLL_INTERVAL_MS,
|
|
112
|
+
maxIntervalMs: this.config.maxPollIntervalMs ?? DEFAULT_MAX_POLL_INTERVAL_MS,
|
|
113
|
+
signal: context.signal,
|
|
114
|
+
onState: (current) => operation?.report({
|
|
115
|
+
completed: current.counts?.completed,
|
|
116
|
+
total: current.counts?.total,
|
|
117
|
+
message: current.status,
|
|
118
|
+
}),
|
|
119
|
+
});
|
|
122
120
|
const items = state.status === 'completed' ? await provider.results(ref, context) : [];
|
|
123
121
|
const counts = state.counts ?? countItems(items, request.items?.length);
|
|
124
122
|
const usage = sumUsage(items);
|
|
@@ -232,18 +230,3 @@ function sumUsage(items) {
|
|
|
232
230
|
}
|
|
233
231
|
return { inputTokens, outputTokens, totalTokens: inputTokens + outputTokens };
|
|
234
232
|
}
|
|
235
|
-
function delay(ms, signal) {
|
|
236
|
-
if (ms <= 0)
|
|
237
|
-
return Promise.resolve();
|
|
238
|
-
return new Promise((resolve) => {
|
|
239
|
-
const timer = setTimeout(() => {
|
|
240
|
-
signal?.removeEventListener('abort', onAbort);
|
|
241
|
-
resolve();
|
|
242
|
-
}, ms);
|
|
243
|
-
function onAbort() {
|
|
244
|
-
clearTimeout(timer);
|
|
245
|
-
resolve();
|
|
246
|
-
}
|
|
247
|
-
signal?.addEventListener('abort', onAbort, { once: true });
|
|
248
|
-
});
|
|
249
|
-
}
|