nexus-ai-pro 0.8.1 → 0.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 +32 -0
- package/CHANGELOG.md +35 -0
- package/README.md +30 -7
- package/ROADMAP.md +188 -0
- package/SECURITY.md +15 -0
- package/dist/agent/tool.js +3 -1
- package/dist/cache/adapters.js +3 -1
- package/dist/cli.js +29 -13
- package/dist/connectors/web.d.ts +12 -0
- package/dist/connectors/web.js +359 -22
- package/dist/context/window.js +10 -15
- package/dist/core/nexus.d.ts +2 -2
- package/dist/core/nexus.js +61 -20
- package/dist/core/response-format.js +32 -53
- package/dist/core/secure-stream.d.ts +1 -1
- package/dist/core/secure-stream.js +135 -26
- package/dist/embeddings/providers.js +3 -3
- package/dist/evals/judge.js +1 -3
- package/dist/evals/metrics.js +2 -4
- package/dist/evals/runner.js +2 -6
- package/dist/hallucination/consistency.js +1 -3
- package/dist/hallucination/factual.js +4 -6
- package/dist/hallucination/knowledge-graph.js +7 -9
- package/dist/hallucination/rag.js +4 -2
- package/dist/hallucination/verification.js +32 -9
- package/dist/next/route-handler.js +1 -1
- package/dist/ops/audit-logger.js +29 -1
- package/dist/ops/health.js +1 -3
- package/dist/ops/metrics.js +5 -2
- package/dist/optimizer/cost.js +2 -2
- package/dist/optimizer/densifier.js +7 -4
- package/dist/optimizer/index.js +2 -3
- package/dist/pipeline/types.d.ts +1 -1
- package/dist/providers/anthropic.js +4 -2
- package/dist/providers/base.js +76 -18
- package/dist/providers/cohere.js +2 -2
- package/dist/providers/errors.js +8 -10
- package/dist/providers/google.js +6 -4
- package/dist/providers/groq.js +1 -1
- package/dist/providers/mistral.js +1 -1
- package/dist/providers/openai.js +22 -12
- package/dist/rag/file-ingestion.js +1 -1
- package/dist/rag/ingestion.js +5 -4
- package/dist/router/auto-router.js +13 -9
- package/dist/router/failover.d.ts +10 -3
- package/dist/router/failover.js +250 -50
- package/dist/security/index.d.ts +3 -2
- package/dist/security/index.js +45 -6
- package/dist/security/injection-calibration.js +6 -2
- package/dist/security/injection-detector.js +21 -7
- package/dist/security/input-guard.js +28 -14
- package/dist/security/output-guard.d.ts +8 -0
- package/dist/security/output-guard.js +146 -57
- package/dist/security/prompt-hardening.js +2 -1
- package/dist/security/schema-validator.js +5 -8
- package/dist/security/upload-scanner.js +3 -1
- package/dist/telephony/providers/twilio.js +14 -10
- package/dist/testing/provider-conformance.js +4 -4
- package/dist/types/config.d.ts +6 -0
- package/dist/types/providers.js +22 -10
- package/dist/utils/ids.js +1 -1
- package/dist/utils/tokenizer.js +17 -14
- package/dist/voice/manager.js +1 -3
- package/dist/voice/providers/openai.js +4 -2
- package/dist/voice/session.js +6 -14
- package/dist/workflow/chains.js +19 -8
- package/dist/workflow/domain.js +28 -12
- package/package.json +129 -45
- package/EXPLANATION.md +0 -434
- package/assets/nexus-ai-pro-presentation.jpg +0 -0
- package/examples/agent.ts +0 -69
- package/examples/basic.ts +0 -37
- package/examples/bullmq-worker.ts +0 -36
- package/examples/classifier-calibration.ts +0 -7
- package/examples/cli-eval.json +0 -16
- package/examples/config-builder.ts +0 -18
- package/examples/create-nexus.ts +0 -15
- package/examples/custom-provider.ts +0 -16
- package/examples/domain-workflows.ts +0 -38
- package/examples/exports/README.md +0 -10
- package/examples/exports/config.ts +0 -18
- package/examples/exports/providers.ts +0 -33
- package/examples/exports/root.ts +0 -54
- package/examples/exports/runtime-modules.ts +0 -40
- package/examples/feature-flags.ts +0 -65
- package/examples/minimal.ts +0 -45
- package/examples/ocr-pdf-ingestion.ts +0 -42
- package/examples/optimizer.ts +0 -43
- package/examples/otel-express.ts +0 -47
- package/examples/otel-node-http.ts +0 -46
- package/examples/persisted-vector-store.ts +0 -42
- package/examples/security.ts +0 -69
package/API_STABILITY.md
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# API Stability Policy
|
|
2
|
+
|
|
3
|
+
This policy describes compatibility guarantees for `nexus-ai-pro` beginning with version 0.9.0.
|
|
4
|
+
|
|
5
|
+
## Release stages
|
|
6
|
+
|
|
7
|
+
The package is pre-1.0. Minor releases may contain breaking changes when they are necessary, but those changes will be called out in the changelog with migration guidance. Patch releases are intended to remain backward compatible.
|
|
8
|
+
|
|
9
|
+
The following surfaces are public and covered by this policy:
|
|
10
|
+
|
|
11
|
+
- exports documented in the root package or an explicit `package.json` subpath;
|
|
12
|
+
- exported TypeScript types and runtime symbols;
|
|
13
|
+
- documented configuration keys, response shapes, and CLI commands.
|
|
14
|
+
|
|
15
|
+
Source files, `dist` file paths, examples, test helpers that are not exported, and undocumented implementation details are not public API. Import only from `nexus-ai-pro` or one of its explicit subpaths.
|
|
16
|
+
|
|
17
|
+
## Compatibility rules
|
|
18
|
+
|
|
19
|
+
- A public symbol will not be removed or incompatibly changed in a patch release.
|
|
20
|
+
- Deprecations will be documented before removal whenever practical.
|
|
21
|
+
- New optional fields, providers, exports, error subclasses, and enum-like union members may be added in a minor release.
|
|
22
|
+
- TypeScript improvements that expose previously invalid usage may arrive in a patch release.
|
|
23
|
+
- Security fixes may tighten validation or blocking behavior in a patch release when preserving the old behavior would leave users exposed.
|
|
24
|
+
- Provider behavior can change when an upstream API changes; Nexus will preserve its normalized request and response contracts where possible.
|
|
25
|
+
|
|
26
|
+
The package is ESM-only and supports Node.js 22 or newer. CommonJS `require()` and deep imports into `dist` or `src` are not supported.
|
|
27
|
+
|
|
28
|
+
## Deprecation process
|
|
29
|
+
|
|
30
|
+
Deprecated APIs are marked with `@deprecated` in declarations and described in the changelog. During the 0.x series, removal will not normally occur earlier than the next minor release. After 1.0, removals will be reserved for major releases, except when an urgent security issue requires otherwise.
|
|
31
|
+
|
|
32
|
+
Report accidental compatibility regressions through the project issue tracker. Security issues should follow [SECURITY.md](./SECURITY.md).
|
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
Notable changes to this project are recorded here. The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and releases use semantic versioning while accounting for the pre-1.0 stability policy.
|
|
4
|
+
|
|
5
|
+
## [Unreleased]
|
|
6
|
+
|
|
7
|
+
## [0.9.0] - 2026-07-15
|
|
8
|
+
|
|
9
|
+
### Added
|
|
10
|
+
|
|
11
|
+
- Full JSON Schema validation through Ajv and standard format validation through `ajv-formats`.
|
|
12
|
+
- Node.js 22 and 24 CI gates for linting, builds, tests, consumer type checks, and packed-package installation.
|
|
13
|
+
- OIDC trusted publishing with npm provenance for tagged releases.
|
|
14
|
+
- API stability, security, and contribution policies.
|
|
15
|
+
- Biome formatting/lint gates, test/example type checks, and built-in Node.js coverage thresholds.
|
|
16
|
+
|
|
17
|
+
### Changed
|
|
18
|
+
|
|
19
|
+
- The supported runtime is now Node.js 22 or newer and the package is explicitly ESM-only.
|
|
20
|
+
- Provider, cache, and job entry points now use an explicit export map instead of wildcard exports.
|
|
21
|
+
- Published tarballs contain the runtime and essential package documentation, excluding repository examples and marketing assets.
|
|
22
|
+
- Provider peer dependency ranges are bounded to tested SDK lines.
|
|
23
|
+
- Build and publish scripts always clean and rebuild `dist` before packing.
|
|
24
|
+
- Security-enabled output streams validate the complete bounded response before yielding chunks.
|
|
25
|
+
|
|
26
|
+
### Fixed
|
|
27
|
+
|
|
28
|
+
- Blocking output policies now stop unsafe completions instead of returning blocked content as successful output.
|
|
29
|
+
- Streaming redaction protects values that cross provider chunk boundaries.
|
|
30
|
+
- Provider timeouts abort in-flight completion and streaming requests.
|
|
31
|
+
- URL fetching rejects unsafe private-network targets and limits response reads.
|
|
32
|
+
- CLI and audit findings no longer disclose detected secret values.
|
|
33
|
+
|
|
34
|
+
[Unreleased]: https://github.com/mkhitar-abrahamyan/nexus-ai/compare/v0.9.0...HEAD
|
|
35
|
+
[0.9.0]: https://github.com/mkhitar-abrahamyan/nexus-ai/releases/tag/v0.9.0
|
package/README.md
CHANGED
|
@@ -7,6 +7,7 @@ Use the whole pipeline for production AI features, or turn pieces off when you o
|
|
|
7
7
|
- NPM: https://www.npmjs.com/package/nexus-ai-pro
|
|
8
8
|
- GitHub: https://github.com/mkhitar-abrahamyan/nexus-ai
|
|
9
9
|
- Full technical notes and manual test cases: [NEXUS.md](./NEXUS.md)
|
|
10
|
+
- Planned image generation and infrastructure work: [ROADMAP.md](./ROADMAP.md)
|
|
10
11
|
|
|
11
12
|
## Install
|
|
12
13
|
|
|
@@ -14,6 +15,8 @@ Use the whole pipeline for production AI features, or turn pieces off when you o
|
|
|
14
15
|
npm install nexus-ai-pro
|
|
15
16
|
```
|
|
16
17
|
|
|
18
|
+
Requires Node.js 22 or newer. `nexus-ai-pro` is ESM-only: use `import` from an ES module rather than CommonJS `require()`.
|
|
19
|
+
|
|
17
20
|
Install only the provider SDKs your app uses. The OpenAI SDK also powers OpenAI-compatible adapters such as OpenRouter, Groq, Mistral, DeepSeek, Azure OpenAI, LM Studio, and llama.cpp.
|
|
18
21
|
|
|
19
22
|
```bash
|
|
@@ -246,6 +249,12 @@ for await (const chunk of stream) {
|
|
|
246
249
|
|
|
247
250
|
All providers normalize streaming chunks to `text`, `tool_call`, `done`, or `error`.
|
|
248
251
|
|
|
252
|
+
When security is enabled, output streams are correctness-first: Nexus buffers and validates the
|
|
253
|
+
complete output before yielding any chunk, up to 1 MiB or 100,000 chunks. This prevents secrets,
|
|
254
|
+
PII, and blocked phrases split across provider chunks from leaking partially, at the cost of
|
|
255
|
+
token-by-token latency. `security: 'off'` preserves immediate streaming when that trade-off is
|
|
256
|
+
explicitly acceptable for the application.
|
|
257
|
+
|
|
249
258
|
### Tools and Agents
|
|
250
259
|
|
|
251
260
|
```ts
|
|
@@ -559,6 +568,12 @@ Useful helpers:
|
|
|
559
568
|
- URL and tool allowlist checks
|
|
560
569
|
- reusable policies through `guardrailPolicy(...)`
|
|
561
570
|
- `hardenPrompt(...)` for clearly delimiting untrusted input
|
|
571
|
+
- `createFetchUrlTool(...)` with DNS pinning, redirect validation, private-network blocking, and
|
|
572
|
+
bounded response reads
|
|
573
|
+
|
|
574
|
+
CLI scans and audit records redact detected values by default. `nexus scan --reveal-values` is
|
|
575
|
+
restricted to an interactive terminal; raw audit data requires both `includeSensitiveData: true`
|
|
576
|
+
and an explicit custom sink.
|
|
562
577
|
|
|
563
578
|
## Caching, Jobs, and Evals
|
|
564
579
|
|
|
@@ -670,7 +685,7 @@ import { RedisCacheAdapter } from 'nexus-ai-pro/cache';
|
|
|
670
685
|
import { DeepSeekProvider } from 'nexus-ai-pro/providers/deepseek';
|
|
671
686
|
```
|
|
672
687
|
|
|
673
|
-
Provider SDKs are optional peer dependencies. The package is ESM-
|
|
688
|
+
Provider SDKs are optional peer dependencies. The package is ESM-only, supports Node.js 22+, and is marked with `sideEffects: false`. Only the entry points listed in the package export map are public; deep imports into `dist` or `src` are unsupported.
|
|
674
689
|
|
|
675
690
|
## Examples
|
|
676
691
|
|
|
@@ -686,7 +701,7 @@ npm run example:optimizer
|
|
|
686
701
|
npm run example:agent
|
|
687
702
|
```
|
|
688
703
|
|
|
689
|
-
|
|
704
|
+
Repository example files cover:
|
|
690
705
|
|
|
691
706
|
- OpenTelemetry with Node HTTP and Express
|
|
692
707
|
- BullMQ workers
|
|
@@ -701,19 +716,27 @@ Included example files cover:
|
|
|
701
716
|
|
|
702
717
|
```bash
|
|
703
718
|
npm install
|
|
704
|
-
npm run
|
|
705
|
-
npm
|
|
706
|
-
npm run test:types
|
|
707
|
-
npm run test:clean-install
|
|
708
|
-
npm run test:conformance:mock
|
|
719
|
+
npm run check
|
|
720
|
+
npm run check:release
|
|
709
721
|
```
|
|
710
722
|
|
|
723
|
+
`check` runs formatting and lint gates, source/test/example type checks, the build, unit and mock
|
|
724
|
+
conformance tests, coverage thresholds, package import checks, and an external type-consumer test.
|
|
725
|
+
`check:release` additionally verifies the dry-run tarball and a clean packed-package install.
|
|
726
|
+
|
|
711
727
|
Real provider conformance is opt-in:
|
|
712
728
|
|
|
713
729
|
```bash
|
|
714
730
|
npm run test:conformance:real
|
|
715
731
|
```
|
|
716
732
|
|
|
733
|
+
## Roadmap
|
|
734
|
+
|
|
735
|
+
The next recommended feature family is first-class image generation and editing through a
|
|
736
|
+
provider-neutral `ImageManager`, portable asset types, durable operation handles, visual safety,
|
|
737
|
+
asset storage, and media-specific evaluations. The design and prioritized infrastructure backlog
|
|
738
|
+
are in [ROADMAP.md](./ROADMAP.md).
|
|
739
|
+
|
|
717
740
|
## Production Notes
|
|
718
741
|
|
|
719
742
|
- Use direct or rules-based routing when model choice is already known.
|
package/ROADMAP.md
ADDED
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
# nexus-ai-pro Roadmap
|
|
2
|
+
|
|
3
|
+
This roadmap is a design proposal, not a compatibility promise. Stable and experimental
|
|
4
|
+
surfaces are defined in [API_STABILITY.md](./API_STABILITY.md).
|
|
5
|
+
|
|
6
|
+
## Recommended next release: first-class image generation
|
|
7
|
+
|
|
8
|
+
Image generation should be a separate operation family rather than another variation of
|
|
9
|
+
`complete()`. Text completions and generated assets have different request shapes, response
|
|
10
|
+
lifecycles, costs, safety checks, storage needs, and retry semantics.
|
|
11
|
+
|
|
12
|
+
The first public surface could look like this:
|
|
13
|
+
|
|
14
|
+
```ts
|
|
15
|
+
const result = await ai.images.generate({
|
|
16
|
+
model: 'auto',
|
|
17
|
+
prompt: 'A clean product photograph of a red mechanical keyboard',
|
|
18
|
+
aspectRatio: '16:9',
|
|
19
|
+
quality: 'high',
|
|
20
|
+
delivery: { kind: 'bytes', format: 'png' },
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
await ai.images.edit({
|
|
24
|
+
model: 'auto',
|
|
25
|
+
prompt: 'Replace the background with a softly lit studio wall',
|
|
26
|
+
input: result.assets[0],
|
|
27
|
+
mask: {
|
|
28
|
+
location: { kind: 'bytes', data: maskBytes },
|
|
29
|
+
mimeType: 'image/png',
|
|
30
|
+
polarity: 'white-is-editable',
|
|
31
|
+
},
|
|
32
|
+
references: [styleReference],
|
|
33
|
+
});
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
`auto` should resolve through versioned, verified aliases instead of making a model name part of
|
|
37
|
+
the durable API. OpenAI currently supports one-shot generation and editing through the Image API,
|
|
38
|
+
while the Responses API supports conversational, multi-turn image workflows. See the
|
|
39
|
+
[official image generation guide](https://developers.openai.com/api/docs/guides/image-generation)
|
|
40
|
+
and [GPT Image 2 model page](https://developers.openai.com/api/docs/models/gpt-image-2).
|
|
41
|
+
|
|
42
|
+
### Recommended API boundary
|
|
43
|
+
|
|
44
|
+
- Add a lightweight `ImageManager` in `nexus-ai-pro/images`, following the voice manager pattern.
|
|
45
|
+
- Expose `ai.images.generate()`, `ai.images.edit()`, and `ai.images.submit()`.
|
|
46
|
+
- Let `generate()` and `edit()` wait for a result. Let `submit()` return an
|
|
47
|
+
`OperationHandle<TResult>` with `status()`, `result()`, `cancel()`, and `events()`.
|
|
48
|
+
- Add `registerImageProvider()`, `hasImageProvider()`, and `listImageProviders()`.
|
|
49
|
+
- Keep provider-neutral types in the core export and optional integrations in exports such as
|
|
50
|
+
`nexus-ai-pro/images/openai` and `nexus-ai-pro/images/comfyui`.
|
|
51
|
+
|
|
52
|
+
### Media types
|
|
53
|
+
|
|
54
|
+
- Prefer `Uint8Array`, `Blob`, URLs, and web streams in public types; keep Node `Buffer` as a
|
|
55
|
+
convenience input rather than the portable core type.
|
|
56
|
+
- Use discriminated asset locations instead of several optional fields:
|
|
57
|
+
`{ kind: 'bytes'; data: Uint8Array }`, `{ kind: 'url'; url; expiresAt? }`, or
|
|
58
|
+
`{ kind: 'stored'; uri; assetId }`.
|
|
59
|
+
- Define `AssetInput`, `AssetDescriptor`, `ImageGenerateRequest`, `ImageEditRequest`,
|
|
60
|
+
`ImageResult`, `MediaUsage`, `MediaSafetyFinding`, `OperationEvent`, and
|
|
61
|
+
`OperationHandle<TResult>`.
|
|
62
|
+
- Keep dimensions, MIME type, checksum, storage location, and provenance on each asset. Put
|
|
63
|
+
latency, cost, route, and usage in result-level `OperationMeta`.
|
|
64
|
+
- Make `input`, `mask`, and `references` explicit for editing. Define mask polarity, sizing, and
|
|
65
|
+
resize rules so adapters cannot silently reinterpret a request.
|
|
66
|
+
- Model generation, editing, masking/inpainting, variations, and background transparency as
|
|
67
|
+
explicit capabilities.
|
|
68
|
+
- Split model capabilities into `inputModalities` and `outputModalities`, and retire the current
|
|
69
|
+
semantic overlap between `vision`, `image`, and `pdf`.
|
|
70
|
+
|
|
71
|
+
### Provider architecture
|
|
72
|
+
|
|
73
|
+
- Introduce `ImageProvider` independently of the completion-shaped `BaseProvider`.
|
|
74
|
+
- Give every provider family a shared internal `ProviderCallContext` containing abort signal,
|
|
75
|
+
deadline, request ID, trace context, and idempotency key.
|
|
76
|
+
- Start with a deterministic mock provider and one hosted provider supporting generation and edit.
|
|
77
|
+
- Add a second cloud adapter and local ComfyUI before stabilizing the API; this exposes assumptions
|
|
78
|
+
around masks, seeds, negative prompts, polling, formats, and quality controls.
|
|
79
|
+
- Negotiate operation, input MIME types, mask support, dimensions, aspect ratio, transparency,
|
|
80
|
+
output format, and count. Unsupported options must fail or produce an explicit warning.
|
|
81
|
+
- Route by capability, latency, cost, quality, residency, and safety policy.
|
|
82
|
+
|
|
83
|
+
### Asset and job pipeline
|
|
84
|
+
|
|
85
|
+
- Add an `AssetStore` interface with `put`, `get`, `stat`, `delete`, `sign`, retention, tenant
|
|
86
|
+
ownership, checksums, and streaming. Start with bounded memory/filesystem adapters, then add
|
|
87
|
+
S3-compatible storage.
|
|
88
|
+
- Treat provider URLs as temporary delivery locations, never as durable storage.
|
|
89
|
+
- Resolve remote inputs with SSRF protection, MIME sniffing, byte/pixel limits,
|
|
90
|
+
decompression-bomb protection, and a redirect policy.
|
|
91
|
+
- Put metadata stripping, provenance, and image transforms behind optional `AssetTransformer`
|
|
92
|
+
adapters so the core install stays small.
|
|
93
|
+
- Add visual input and output moderation; text-only security checks are not sufficient.
|
|
94
|
+
- Keep idempotency separate from generative caching. An idempotency key replays the same accepted
|
|
95
|
+
operation. Caching remains opt-in and keys on model version, policy version, parameters, and
|
|
96
|
+
source-asset hashes.
|
|
97
|
+
- Build a real operation state machine: queued, running, succeeded, failed, cancelling, cancelled,
|
|
98
|
+
and expired. Add leases/heartbeats, progress events, delayed retry, dead-letter handling,
|
|
99
|
+
cancellation, timestamps, signed webhooks, and trace propagation.
|
|
100
|
+
- Queue asset references only; never JSON-serialize binary media into job payloads.
|
|
101
|
+
- Reserve and reconcile budget using provider-appropriate pricing such as per-image, megapixel, or
|
|
102
|
+
compute time. Ambiguous timeouts must not create duplicate assets or charges.
|
|
103
|
+
|
|
104
|
+
### Image evaluation
|
|
105
|
+
|
|
106
|
+
- Prompt/image semantic alignment and OCR accuracy for generated text.
|
|
107
|
+
- Perceptual similarity for edit preservation.
|
|
108
|
+
- Safety-policy pass rate and false-positive tracking.
|
|
109
|
+
- Latency, cost, retry, and provider failover metrics.
|
|
110
|
+
- Repeated-run statistical baselines for stochastic output, plus human-review queues.
|
|
111
|
+
- Brand/style reference kits, campaign variant matrices, prompt presets, and reproducibility
|
|
112
|
+
manifests.
|
|
113
|
+
- A generic evaluation target or parallel `MediaEvalRunner`; string-only golden-file tests are not
|
|
114
|
+
a useful image-quality gate.
|
|
115
|
+
|
|
116
|
+
## Infrastructure improvements
|
|
117
|
+
|
|
118
|
+
### One lifecycle for every operation
|
|
119
|
+
|
|
120
|
+
Create an internal typed lifecycle and adapt existing operations to it incrementally:
|
|
121
|
+
|
|
122
|
+
`validate -> authorize -> input policy -> resolve assets -> route -> reserve budget -> execute ->`
|
|
123
|
+
`output policy -> persist -> reconcile cost -> audit`
|
|
124
|
+
|
|
125
|
+
Completions, streams, embeddings, voice, images, and jobs should share the same authorization,
|
|
126
|
+
budget, hooks, audit, metrics, and finalization stages, including cache hits. Transport-specific
|
|
127
|
+
code should only perform the provider call and normalize its result.
|
|
128
|
+
|
|
129
|
+
### Provider compatibility automation
|
|
130
|
+
|
|
131
|
+
- Maintain provider contract tests for minimum and latest supported SDK versions.
|
|
132
|
+
- Generate the model registry from versioned provider data with `verifiedAt` and source fields.
|
|
133
|
+
- Mark aliases as stable, preview, or deprecated and emit opt-in deprecation warnings.
|
|
134
|
+
- Record/replay provider fixtures so most conformance tests run without credentials.
|
|
135
|
+
- Detect capability drift so provider option loss cannot happen silently.
|
|
136
|
+
|
|
137
|
+
### Durable production primitives
|
|
138
|
+
|
|
139
|
+
- Distributed rate-limit and circuit-breaker adapters.
|
|
140
|
+
- Idempotency, request deduplication, cancellation, progress, and operation-event adapters.
|
|
141
|
+
- Persistent conversation/session stores.
|
|
142
|
+
- Webhook delivery with signatures, retries, and a dead-letter queue.
|
|
143
|
+
- Resumable background operations for image/video generation and large eval runs.
|
|
144
|
+
- GPU-aware local scheduling, leases, heartbeats, and backpressure.
|
|
145
|
+
|
|
146
|
+
### Observability and governance
|
|
147
|
+
|
|
148
|
+
- Standard operation spans and metrics across provider, model, modality, cache, retry, and cost.
|
|
149
|
+
- Tenant/project budget policies with reservation and reconciliation of actual usage.
|
|
150
|
+
- Redaction-safe audit records with stable finding IDs rather than sensitive values.
|
|
151
|
+
- OpenTelemetry semantic conventions plus trace propagation through queues and webhooks.
|
|
152
|
+
- An optional local control plane for approvals, traces, evals, costs, provider health, assets,
|
|
153
|
+
retention, and queued operations.
|
|
154
|
+
|
|
155
|
+
### Smaller install surface
|
|
156
|
+
|
|
157
|
+
- Keep a small provider-neutral core.
|
|
158
|
+
- Move heavy or environment-specific integrations into optional exports or a future scoped package
|
|
159
|
+
family, including OpenTelemetry, BullMQ, image transforms, and provider adapters.
|
|
160
|
+
- Make browser/edge compatibility explicit by isolating Node filesystem, crypto, DNS, and stream
|
|
161
|
+
dependencies behind adapters.
|
|
162
|
+
|
|
163
|
+
## Additional feature backlog
|
|
164
|
+
|
|
165
|
+
1. True mixed text/asset outputs and tool results that pass asset references without base64 JSON.
|
|
166
|
+
2. OCR, captioning, visual question answering, image embeddings, and visual moderation.
|
|
167
|
+
3. Realtime voice/video sessions with interruption handling, turn detection, and live tool calls.
|
|
168
|
+
4. Video generation through the same asynchronous operation, job, and asset contracts.
|
|
169
|
+
5. Media search and RAG using image embeddings.
|
|
170
|
+
6. MCP client/server adapters with asset and tool interoperability.
|
|
171
|
+
7. Human approval checkpoints for high-impact tools and generated-media publication.
|
|
172
|
+
8. Policy-as-code presets versioned independently from the runtime.
|
|
173
|
+
9. Prompt/workflow versioning with offline replay and A/B evaluation.
|
|
174
|
+
10. Multi-tenant credential-vault adapters and per-provider residency routing.
|
|
175
|
+
|
|
176
|
+
## Suggested delivery order
|
|
177
|
+
|
|
178
|
+
1. Stabilize the shared operation lifecycle and provider conformance suite.
|
|
179
|
+
2. Add portable media types, `ImageManager`, `ImageProvider`, and a deterministic mock provider.
|
|
180
|
+
3. Ship one hosted generate/edit adapter, bounded local asset storage, and visual safety hooks as
|
|
181
|
+
experimental APIs.
|
|
182
|
+
4. Add the production asset store and operation state machine with progress, cancellation,
|
|
183
|
+
idempotency, and cost reconciliation.
|
|
184
|
+
5. Add a second cloud provider and local ComfyUI to validate portability.
|
|
185
|
+
6. Add true multimodal outputs and media evaluation.
|
|
186
|
+
7. Promote the media API only after packed-package tests, provider conformance, and image evals
|
|
187
|
+
cover the supported capability matrix.
|
|
188
|
+
|
package/SECURITY.md
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# Security Policy
|
|
2
|
+
|
|
3
|
+
## Supported versions
|
|
4
|
+
|
|
5
|
+
Security fixes are provided for the latest published minor release. Users should upgrade to the newest `0.9.x` patch as fixes become available.
|
|
6
|
+
|
|
7
|
+
## Reporting a vulnerability
|
|
8
|
+
|
|
9
|
+
Please use [GitHub private vulnerability reporting](https://github.com/mkhitar-abrahamyan/nexus-ai/security/advisories/new). Do not open a public issue for an undisclosed vulnerability and do not include real credentials, personal data, or exploit targets in a report.
|
|
10
|
+
|
|
11
|
+
Include the affected version, impact, a minimal reproduction, and any suggested mitigation. You can expect an acknowledgement within five business days. A confirmed issue will be coordinated privately until a fix and disclosure plan are ready.
|
|
12
|
+
|
|
13
|
+
## Scope and safe operation
|
|
14
|
+
|
|
15
|
+
Nexus guardrails reduce common AI application risks, but they are not a complete authorization or security boundary. Applications remain responsible for access control, provider-side safety controls, tool authorization, network egress policy, secret storage, and review of high-impact model actions.
|
package/dist/agent/tool.js
CHANGED
|
@@ -9,7 +9,9 @@ export function tool(definition) {
|
|
|
9
9
|
export class ToolExecutor {
|
|
10
10
|
tools = new Map();
|
|
11
11
|
constructor(tools = []) {
|
|
12
|
-
|
|
12
|
+
for (const toolDefinition of tools) {
|
|
13
|
+
this.register(toolDefinition);
|
|
14
|
+
}
|
|
13
15
|
}
|
|
14
16
|
register(toolDefinition) {
|
|
15
17
|
this.tools.set(toolDefinition.name, toolDefinition);
|
package/dist/cache/adapters.js
CHANGED
|
@@ -64,7 +64,9 @@ export class SQLiteCacheAdapter {
|
|
|
64
64
|
return JSON.parse(row.value);
|
|
65
65
|
}
|
|
66
66
|
set(key, value, ttlSeconds = 300) {
|
|
67
|
-
this.db
|
|
67
|
+
this.db
|
|
68
|
+
.prepare(`INSERT OR REPLACE INTO ${this.table} (key, value, expires_at) VALUES (?, ?, ?)`)
|
|
69
|
+
.run?.(key, JSON.stringify(value), Date.now() + ttlSeconds * 1000);
|
|
68
70
|
}
|
|
69
71
|
delete(key) {
|
|
70
72
|
this.db.prepare(`DELETE FROM ${this.table} WHERE key = ?`).run?.(key);
|
package/dist/cli.js
CHANGED
|
@@ -7,11 +7,12 @@ import { EvalRunner } from './evals/runner.js';
|
|
|
7
7
|
import { NexusAI } from './core/nexus.js';
|
|
8
8
|
import { listKnownModels, listModelsForProvider, getModelCapabilities } from './models/registry.js';
|
|
9
9
|
import { SecurityPipeline } from './security/index.js';
|
|
10
|
+
import { redactSensitiveText } from './security/output-guard.js';
|
|
10
11
|
import { UploadScanner } from './security/upload-scanner.js';
|
|
11
12
|
import { TokenOptimizer } from './optimizer/index.js';
|
|
12
13
|
const DEFAULT_SCAN_MAX_BYTES = 1_000_000;
|
|
13
14
|
const IGNORED_DIRS = new Set(['.git', 'node_modules', 'dist', 'coverage', '.next', '.turbo']);
|
|
14
|
-
const BOOLEAN_FLAGS = new Set(['all', 'densify', 'fail', 'help', 'json', 'print']);
|
|
15
|
+
const BOOLEAN_FLAGS = new Set(['all', 'densify', 'fail', 'help', 'json', 'print', 'reveal-values']);
|
|
15
16
|
async function main() {
|
|
16
17
|
const [command, ...rest] = process.argv.slice(2);
|
|
17
18
|
const parsed = parseArgs(rest);
|
|
@@ -37,6 +38,13 @@ async function main() {
|
|
|
37
38
|
}
|
|
38
39
|
}
|
|
39
40
|
async function runScan({ positionals, flags }) {
|
|
41
|
+
const revealValues = flagBool(flags, 'reveal-values');
|
|
42
|
+
if (revealValues && flagBool(flags, 'json')) {
|
|
43
|
+
throw new Error('--reveal-values cannot be combined with --json because structured output is commonly persisted');
|
|
44
|
+
}
|
|
45
|
+
if (revealValues && !process.stdout.isTTY) {
|
|
46
|
+
throw new Error('--reveal-values requires an interactive terminal');
|
|
47
|
+
}
|
|
40
48
|
const roots = positionals.length ? positionals : ['.'];
|
|
41
49
|
const maxBytes = numberFlag(flags, 'max-bytes') ?? DEFAULT_SCAN_MAX_BYTES;
|
|
42
50
|
const files = await collectFiles(roots, flagBool(flags, 'all'));
|
|
@@ -65,16 +73,20 @@ async function runScan({ positionals, flags }) {
|
|
|
65
73
|
}
|
|
66
74
|
}
|
|
67
75
|
const ok = !findings.some((finding) => finding.severity === 'high' || finding.severity === 'critical');
|
|
76
|
+
const displayedFindings = revealValues ? findings : findings.map(sanitizeCliFinding);
|
|
68
77
|
if (flagBool(flags, 'json')) {
|
|
69
|
-
writeJson({ ok, scannedFiles: files.length, findings });
|
|
78
|
+
writeJson({ ok, scannedFiles: files.length, findings: displayedFindings });
|
|
70
79
|
}
|
|
71
80
|
else {
|
|
72
81
|
console.log(`Scanned ${files.length} file${files.length === 1 ? '' : 's'}.`);
|
|
73
|
-
if (!
|
|
82
|
+
if (!displayedFindings.length) {
|
|
74
83
|
console.log('No secrets, PII, or prompt-injection risks found.');
|
|
75
84
|
}
|
|
76
85
|
else {
|
|
77
|
-
|
|
86
|
+
if (revealValues) {
|
|
87
|
+
console.error('WARNING: displaying raw sensitive finding values in this interactive terminal.');
|
|
88
|
+
}
|
|
89
|
+
for (const finding of displayedFindings) {
|
|
78
90
|
const value = finding.value ? ` (${truncate(finding.value, 96)})` : '';
|
|
79
91
|
console.log(`${finding.severity.toUpperCase()} ${finding.type} ${finding.file}: ${finding.message}${value}`);
|
|
80
92
|
}
|
|
@@ -249,9 +261,7 @@ async function readRequest(file, flags) {
|
|
|
249
261
|
};
|
|
250
262
|
}
|
|
251
263
|
function isCompletionRequest(value) {
|
|
252
|
-
return isRecord(value)
|
|
253
|
-
&& typeof value.model === 'string'
|
|
254
|
-
&& Array.isArray(value.messages);
|
|
264
|
+
return isRecord(value) && typeof value.model === 'string' && Array.isArray(value.messages);
|
|
255
265
|
}
|
|
256
266
|
async function loadEvalFile(file) {
|
|
257
267
|
const fullPath = path.resolve(file);
|
|
@@ -311,6 +321,14 @@ function isUsefulCliFinding(finding) {
|
|
|
311
321
|
const digits = finding.value?.replace(/\D/g, '') || '';
|
|
312
322
|
return digits.length >= 10;
|
|
313
323
|
}
|
|
324
|
+
function sanitizeCliFinding(finding) {
|
|
325
|
+
return {
|
|
326
|
+
...finding,
|
|
327
|
+
file: redactSensitiveText(finding.file),
|
|
328
|
+
message: redactSensitiveText(finding.message),
|
|
329
|
+
value: finding.value === undefined ? undefined : '[REDACTED]',
|
|
330
|
+
};
|
|
331
|
+
}
|
|
314
332
|
function parseArgs(args) {
|
|
315
333
|
const positionals = [];
|
|
316
334
|
const flags = {};
|
|
@@ -385,10 +403,7 @@ function writeJson(value) {
|
|
|
385
403
|
console.log(JSON.stringify(value, null, 2));
|
|
386
404
|
}
|
|
387
405
|
function printTable(rows, columns) {
|
|
388
|
-
const widths = Object.fromEntries(columns.map((column) => [
|
|
389
|
-
column,
|
|
390
|
-
Math.max(column.length, ...rows.map((row) => row[column].length)),
|
|
391
|
-
]));
|
|
406
|
+
const widths = Object.fromEntries(columns.map((column) => [column, Math.max(column.length, ...rows.map((row) => row[column].length))]));
|
|
392
407
|
console.log(columns.map((column) => column.padEnd(widths[column])).join(' '));
|
|
393
408
|
console.log(columns.map((column) => '-'.repeat(widths[column])).join(' '));
|
|
394
409
|
for (const row of rows) {
|
|
@@ -405,7 +420,7 @@ function printHelp() {
|
|
|
405
420
|
console.log(`nexus-ai-pro CLI
|
|
406
421
|
|
|
407
422
|
Usage:
|
|
408
|
-
nexus scan [paths...] [--json] [--max-bytes 1000000] [--no-fail]
|
|
423
|
+
nexus scan [paths...] [--json] [--max-bytes 1000000] [--no-fail] [--reveal-values]
|
|
409
424
|
nexus models [--provider openai] [--json]
|
|
410
425
|
nexus eval <eval.json|eval.mjs> [--json]
|
|
411
426
|
nexus optimize [request.json|prompt.txt] [--model gpt-5-mini] [--max-input-tokens 4000] [--densify] [--json]
|
|
@@ -413,6 +428,7 @@ Usage:
|
|
|
413
428
|
Eval files can export { cases, client } or { cases, config }. JSON cases may use "expected", "contains", and "match": "includes" | "exact" | "regex".`);
|
|
414
429
|
}
|
|
415
430
|
main().catch((error) => {
|
|
416
|
-
|
|
431
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
432
|
+
console.error(redactSensitiveText(message));
|
|
417
433
|
process.exitCode = 1;
|
|
418
434
|
});
|
package/dist/connectors/web.d.ts
CHANGED
|
@@ -1,8 +1,20 @@
|
|
|
1
1
|
import type { ToolDefinition } from '../types/messages.js';
|
|
2
|
+
export type WebResolvedAddress = string | {
|
|
3
|
+
address: string;
|
|
4
|
+
family?: 4 | 6;
|
|
5
|
+
};
|
|
2
6
|
export interface WebConnectorOptions {
|
|
3
7
|
allowedDomains?: string[];
|
|
4
8
|
timeoutMs?: number;
|
|
5
9
|
userAgent?: string;
|
|
10
|
+
maxResponseBytes?: number;
|
|
11
|
+
maxRedirects?: number;
|
|
12
|
+
/** Explicitly allow loopback/private targets, for example a trusted local development service. */
|
|
13
|
+
allowPrivateNetworks?: boolean;
|
|
14
|
+
/** Cloud metadata endpoints remain denied unless this separate high-risk opt-in is enabled. */
|
|
15
|
+
allowCloudMetadata?: boolean;
|
|
16
|
+
/** Optional resolver for split-horizon DNS or deterministic tests. Every returned address is validated. */
|
|
17
|
+
resolveHostname?: (hostname: string) => Promise<readonly WebResolvedAddress[]>;
|
|
6
18
|
}
|
|
7
19
|
export declare function createFetchUrlTool(options?: WebConnectorOptions): ToolDefinition;
|
|
8
20
|
export declare function createSearchTool(search: (query: string) => Promise<unknown>, name?: string): ToolDefinition;
|