nexus-ai-pro 1.9.0 → 1.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (84) hide show
  1. package/API_STABILITY.md +70 -4
  2. package/CHANGELOG.md +161 -2
  3. package/README.md +272 -82
  4. package/dist/agent/loop.d.ts +0 -1
  5. package/dist/agent/loop.js +23 -10
  6. package/dist/connectors/web.d.ts +3 -13
  7. package/dist/connectors/web.js +14 -342
  8. package/dist/graph/checkpointer.d.ts +11 -2
  9. package/dist/graph/checkpointer.js +22 -8
  10. package/dist/graph/errors.d.ts +26 -3
  11. package/dist/graph/errors.js +29 -3
  12. package/dist/graph/graph.d.ts +31 -5
  13. package/dist/graph/graph.js +398 -79
  14. package/dist/graph/index.d.ts +3 -3
  15. package/dist/graph/index.js +2 -2
  16. package/dist/images/codec.d.ts +26 -0
  17. package/dist/images/codec.js +200 -0
  18. package/dist/images/comfyui.d.ts +83 -0
  19. package/dist/images/comfyui.js +330 -0
  20. package/dist/images/evals.d.ts +146 -0
  21. package/dist/images/evals.js +299 -0
  22. package/dist/images/google.d.ts +43 -0
  23. package/dist/images/google.js +264 -0
  24. package/dist/images/image-header.d.ts +35 -0
  25. package/dist/images/image-header.js +128 -0
  26. package/dist/images/inputs.d.ts +62 -0
  27. package/dist/images/inputs.js +168 -0
  28. package/dist/images/manager.d.ts +7 -0
  29. package/dist/images/manager.js +37 -4
  30. package/dist/images/moderation.d.ts +46 -0
  31. package/dist/images/moderation.js +144 -0
  32. package/dist/images/openai.d.ts +11 -3
  33. package/dist/images/openai.js +24 -8
  34. package/dist/images/transform.d.ts +65 -0
  35. package/dist/images/transform.js +135 -0
  36. package/dist/testing/image-provider-conformance.d.ts +5 -1
  37. package/dist/testing/image-provider-conformance.js +42 -3
  38. package/dist/types/agent.d.ts +6 -0
  39. package/dist/types/graph.d.ts +119 -6
  40. package/dist/types/graph.js +15 -0
  41. package/dist/types/images.d.ts +23 -0
  42. package/dist/utils/safe-fetch.d.ts +56 -0
  43. package/dist/utils/safe-fetch.js +375 -0
  44. package/dist-cjs/agent/loop.d.ts +0 -1
  45. package/dist-cjs/agent/loop.js +24 -11
  46. package/dist-cjs/connectors/web.d.ts +3 -13
  47. package/dist-cjs/connectors/web.js +18 -346
  48. package/dist-cjs/graph/checkpointer.d.ts +11 -2
  49. package/dist-cjs/graph/checkpointer.js +22 -8
  50. package/dist-cjs/graph/errors.d.ts +26 -3
  51. package/dist-cjs/graph/errors.js +31 -4
  52. package/dist-cjs/graph/graph.d.ts +31 -5
  53. package/dist-cjs/graph/graph.js +396 -77
  54. package/dist-cjs/graph/index.d.ts +3 -3
  55. package/dist-cjs/graph/index.js +3 -1
  56. package/dist-cjs/images/codec.d.ts +26 -0
  57. package/dist-cjs/images/codec.js +207 -0
  58. package/dist-cjs/images/comfyui.d.ts +83 -0
  59. package/dist-cjs/images/comfyui.js +369 -0
  60. package/dist-cjs/images/evals.d.ts +146 -0
  61. package/dist-cjs/images/evals.js +340 -0
  62. package/dist-cjs/images/google.d.ts +43 -0
  63. package/dist-cjs/images/google.js +301 -0
  64. package/dist-cjs/images/image-header.d.ts +35 -0
  65. package/dist-cjs/images/image-header.js +141 -0
  66. package/dist-cjs/images/inputs.d.ts +62 -0
  67. package/dist-cjs/images/inputs.js +174 -0
  68. package/dist-cjs/images/manager.d.ts +7 -0
  69. package/dist-cjs/images/manager.js +37 -4
  70. package/dist-cjs/images/moderation.d.ts +46 -0
  71. package/dist-cjs/images/moderation.js +148 -0
  72. package/dist-cjs/images/openai.d.ts +11 -3
  73. package/dist-cjs/images/openai.js +57 -8
  74. package/dist-cjs/images/transform.d.ts +65 -0
  75. package/dist-cjs/images/transform.js +145 -0
  76. package/dist-cjs/testing/image-provider-conformance.d.ts +5 -1
  77. package/dist-cjs/testing/image-provider-conformance.js +42 -3
  78. package/dist-cjs/types/agent.d.ts +6 -0
  79. package/dist-cjs/types/graph.d.ts +119 -6
  80. package/dist-cjs/types/graph.js +17 -1
  81. package/dist-cjs/types/images.d.ts +23 -0
  82. package/dist-cjs/utils/safe-fetch.d.ts +56 -0
  83. package/dist-cjs/utils/safe-fetch.js +383 -0
  84. package/package.json +81 -2
package/API_STABILITY.md CHANGED
@@ -106,6 +106,41 @@ exactly-once provider execution. Those capabilities will use additive adapters a
106
106
  `MemoryAssetStore` is likewise process-local and does not promise cross-process durability or shared
107
107
  tenant state.
108
108
 
109
+ ### Image portability (1.10.0)
110
+
111
+ The following are public under the same 1.x rules. None is exported from the root or from
112
+ `nexus-ai-pro/images`:
113
+
114
+ - `nexus-ai-pro/images/google`
115
+ - `nexus-ai-pro/images/comfyui`
116
+ - `nexus-ai-pro/images/transform`, which re-exports the PNG codec and header helpers
117
+ - `nexus-ai-pro/images/inputs`
118
+ - `nexus-ai-pro/images/moderation`
119
+ - `nexus-ai-pro/images/evals`
120
+
121
+ The following changes are additive:
122
+
123
+ - `ImageConfig.inputResolver` and `ImageConfig.tenantId` are optional. With no resolver, requests are
124
+ handled exactly as before.
125
+ - `ImageAssetResolver` and `ImageAssetResolverContext` are new types.
126
+ - Output from the new modules is still generative. Backend wire shapes such as Imagen `:predict` and
127
+ the ComfyUI queue API are upstream contracts outside this policy, like `raw`.
128
+
129
+ Behaviour that changed:
130
+
131
+ - **OpenAI masks and transparency.** `OpenAIImageProvider` now declares `supportsMask: true` and
132
+ `supportsTransparency: true`, and accepts masked edits. A mask whose size differs from the input is
133
+ still refused unless `resizeMode` allows resampling. `background: 'transparent'` is refused only with
134
+ JPEG output.
135
+ - **Withheld outputs.** A provider finding with `source: 'output'`, `action: 'block'`, and
136
+ `metadata.withheld: true` describes an image the provider removed before responding. The manager
137
+ accepts one fewer asset per such finding, and does not let that finding block the images that were
138
+ returned. Any other blocking finding still blocks the whole result.
139
+ - **Masked-edit conformance case.** `runImageProviderConformance` adds a `masked-image-edit` case for
140
+ providers that declare `supportsMask`. Pass `testMask: false` to skip it.
141
+ - **`UrlPolicyError`.** Safe-fetch policy refusals are now this subclass of `Error`. Their messages are
142
+ unchanged.
143
+
109
144
  ## Embeddings API stage
110
145
 
111
146
  The `nexus-ai-pro/embeddings` family is public and follows the 1.x rules, including the explicit
@@ -242,10 +277,41 @@ to Redis is not a checkpoint.
242
277
  and threading the schema through it would force an annotation on every construction for no benefit.
243
278
  The graph casts at that boundary and hands typed state back through `state()` and `history()`.
244
279
 
245
- Scheduling within a superstep is not a guarantee. Nodes in a fan-out currently run in edge order and
246
- sequentially; running them concurrently is a valid future change, so a node must not depend on
247
- observing another node's write within the same superstep — that is what channels are for. The default
248
- `maxSteps` may change; pass it explicitly when a run depends on the bound.
280
+ `compile()` without a checkpointer uses an in-process `MemoryGraphCheckpointer` capped at 1,000
281
+ threads (since 1.10.0; earlier releases created none). `checkpointer: false` disables checkpointing. A
282
+ run started without a `threadId` reports its generated id on the result.
283
+
284
+ Also since 1.10.0:
285
+
286
+ - A paused or failed superstep records its already finished nodes in the optional `completed` field.
287
+ Those nodes are not run again, and their edges still count when the step completes.
288
+ - Writing checkpoint N drops any stored checkpoints at or after N, so a rewound thread has one
289
+ timeline. Keeping several branches is planned work (forks), not current behaviour.
290
+ - A subgraph interrupt surfaces as an interrupt of the parent node.
291
+ - `onProgress` receives `context.report()` calls.
292
+
293
+ Scheduling within a superstep is not a guarantee, and 1.11.0 makes use of that: tasks in a
294
+ superstep now run concurrently, bounded by `maxConcurrency` (default 16, settable per compile and per
295
+ run; `1` is strictly sequential). A node still must not depend on observing another node's write
296
+ within the same superstep — that is what channels are for. What is guaranteed is that writes are
297
+ reduced in task order rather than completion order, so a replay of the same decisions produces the
298
+ same state. The default `maxSteps` and `maxConcurrency` may change; pass them explicitly when a run
299
+ depends on the bound.
300
+
301
+ Also since 1.11.0, all additive:
302
+
303
+ - `Send` creates one task per value, with the task's input on `context.input`. Task ids are derived
304
+ from the step and the order produced, and appear in the checkpoint's optional `tasks` field, which
305
+ is written only when it says more than `next` does.
306
+ - `NodeOptions` on `addNode` carries `retry`, `timeoutMs`, and `ends`; `compile({ retry })` sets the
307
+ default policy. Retrying is off unless asked for. A timeout raises `GraphNodeTimeoutError`.
308
+ - `onNodeError` chooses `fail-fast` (default) or `settle` for the siblings of a failed task.
309
+ - A paused checkpoint and result carry `interrupts`, every question the step asked;
310
+ `interrupt` remains the first of them. `resumeInterrupts()` and `resumeInterruptsWith()` answer any
311
+ subset by interrupt id. Interrupt ids are keyed by task, so ids written by earlier releases for
312
+ ordinary nodes still resolve.
313
+ - `context.taskId` and `context.attempt` are new. Step events carry `tasks` and `attempts` when there
314
+ is something to report.
249
315
 
250
316
  ## Deprecation process
251
317
 
package/CHANGELOG.md CHANGED
@@ -4,7 +4,164 @@ Notable changes to this project are recorded here. The format follows [Keep a Ch
4
4
 
5
5
  ## [Unreleased]
6
6
 
7
- ## [Unreleased]
7
+ ## [1.11.0] - 2026-09-18
8
+
9
+ Parallel graphs. A fan-out that looks parallel now runs in parallel, a graph can fan out over data it
10
+ discovers at run time, and a node can retry or time out on its own.
11
+
12
+ ### Added
13
+
14
+ - **Concurrent supersteps.** Every task in a superstep starts together: four branches of 300 ms
15
+ finish in about 310 ms, where they used to take 1,253 ms. `npm run bench:graph` measures it and
16
+ fails if the gain disappears.
17
+ - `maxConcurrency` bounds how many run at once. It defaults to 16, is settable per compile and per
18
+ run, and `1` restores strictly sequential execution.
19
+ - Writes are reduced in task order, never completion order, so timing cannot change the state a
20
+ replay produces.
21
+ - A superstep with a single task skips the scheduler, so a linear graph pays nothing for this.
22
+ - **`Send`, for fan-out over run-time data.** A router can return `new Send(node, input)` values,
23
+ creating one task per value, each reading its own `context.input`. Fifty-seven URLs become
24
+ fifty-seven tasks of one node in one superstep.
25
+ - Each copy is checkpointed separately, so a resume re-runs only the copies that did not finish.
26
+ - Task ids come from the step and the order produced, so a replay rebuilds the same tasks.
27
+ - `addNode(name, fn, { ends })` declares `Send` targets, keeping reachability checks exact.
28
+ - **Per-node retries and timeouts.** `addNode(name, fn, { retry, timeoutMs })`, with
29
+ `compile({ retry })` as the default for every node.
30
+ - Retrying is off unless asked for, because only the application knows whether a node is
31
+ idempotent. Interrupts, aborts, and validation errors are never retried.
32
+ - `context.attempt` tells a node which try it is on, and step events report the attempts a task
33
+ needed.
34
+ - A timeout aborts the node's signal and fails that attempt with `GraphNodeTimeoutError`, even if
35
+ the node ignores its signal.
36
+ - **`onNodeError`.** When a task fails, its siblings are aborted (`fail-fast`, the default) or left to
37
+ finish (`settle`). Either way, what they already wrote is kept.
38
+ - **Several questions at once.** Parallel tasks can each interrupt. Paused checkpoints and results
39
+ carry `interrupts`, and `resumeInterrupts()` answers any subset by id. A single question still works
40
+ exactly as before through `resume()`.
41
+ - **Install weight is now measured honestly.** The size table only ever counted this package's own
42
+ files, so a small entry point could quietly force a large dependency on the consumer.
43
+ - `npm run size:check` follows bare imports too, and the README table gains a column for what each
44
+ entry point makes you install. Most entry points force nothing: `/graph`, `/operations`,
45
+ `/batch`, `/embeddings`, and every image subpath import no third-party package at all. The root
46
+ import, `/core`, `/config`, and `/security` pull in 3.4 to 4.7 MB, because JSON-schema and Zod
47
+ validation live there.
48
+ - The clean-install test now measures and bounds the whole production install: 10.0 MB of
49
+ `node_modules`, of which 3.0 MB is this package.
50
+
51
+ ### Fixed
52
+
53
+ - **A retry no longer lets the process exit while it waits.** The backoff timer was unref'd, so a run
54
+ waiting to retry could be abandoned by an otherwise idle process.
55
+
56
+ ## [1.10.0] - 2026-09-16
57
+
58
+ Image portability. Three image backends now sit behind one contract: OpenAI, Google Imagen, and a
59
+ self-hosted ComfyUI server. Masked edits work on all three, and every input is validated before any
60
+ provider sees it. Visual moderation inspects both the request and the generated images. Image output
61
+ can be evaluated for alignment, rendered text, preservation, and safety. Each piece is its own subpath,
62
+ and none is loaded by the root import.
63
+
64
+ ### Added
65
+
66
+ - **Google Imagen adapter** (`nexus-ai-pro/images/google`). It calls the `:predict` protocol on the
67
+ Gemini API with an API key, or on Vertex AI with a bearer token, for generation and masked
68
+ inpainting.
69
+ - It differs from OpenAI, and negotiation says so. Output is sized by aspect ratio, so `dimensions`
70
+ is refused. `seed` and `negativePrompt` are supported.
71
+ - A seed disables the watermark, and the result reports that as a warning.
72
+ - When Imagen filters some images in a batch, the images that passed are still returned.
73
+ - **ComfyUI adapter** (`nexus-ai-pro/images/comfyui`) for a self-hosted server.
74
+ - It uploads inputs, queues a workflow, polls with backoff, and downloads saved outputs.
75
+ - It records the seed it used, even when the caller chose none, so a good run can be reproduced.
76
+ - It removes an abandoned or failed prompt from the queue and interrupts it, so the GPU is not left
77
+ working on a result nobody is waiting for.
78
+ - The workflow graph belongs to the application. Stock text-to-image and inpainting builders are
79
+ included.
80
+ - **Mask conversion** (`nexus-ai-pro/images/transform`). You draw a mask once, with either polarity, and
81
+ it becomes OpenAI's alpha channel or the white-is-editable greyscale that Imagen and ComfyUI read.
82
+ - A size mismatch is refused unless `resizeMode` allows `stretch`, `contain`, or `cover`. Resampling
83
+ is nearest-neighbour, so a binary mask gains no grey fringe, and `contain` padding is never
84
+ editable.
85
+ - Partly transparent pixels count as non-editable, so a soft brush edge never widens an edit.
86
+ - The PNG codec loads on the first masked request. An application that never masks never pays for
87
+ it.
88
+ - `AssetTransformer` is an injection seam for applications that want JPEG or WebP masks.
89
+ - **Validated inputs** (`nexus-ai-pro/images/inputs`). `ImageInputResolver` applies the same checks to
90
+ byte uploads, remote URLs, and stored assets, and plugs into `ImageConfig.inputResolver`.
91
+ - The type is decided by the bytes. A declared or served MIME type that disagrees is refused rather
92
+ than corrected.
93
+ - Byte and pixel limits are enforced. The pixel limit is read from the header before decoding, so a
94
+ small file claiming a huge canvas is refused without allocating anything.
95
+ - Remote fetches get the web connector's SSRF protection: pinned DNS, redirect revalidation, and
96
+ blocking of private networks and cloud metadata.
97
+ - Refusals are `ImageInputError`s with a machine-readable `reason`.
98
+ - **Visual moderation** (`nexus-ai-pro/images/moderation`). `createOpenAIVisualModeration` screens the
99
+ prompt, input and reference images, and every generated image, because an innocuous prompt can
100
+ still produce an unsafe image.
101
+ - Block and review thresholds can be set per category.
102
+ - If the moderation call fails, the request is blocked unless `failOpen` is set.
103
+ - A stored output that cannot be sent for moderation is routed to review.
104
+ - `combineSafetyPolicies` runs several policies and keeps every finding.
105
+ - **Media evaluation** (`nexus-ai-pro/images/evals`). `MediaEvalRunner` checks four things:
106
+ - prompt alignment, using an injected judge;
107
+ - rendered text, using OCR and edit distance;
108
+ - edit preservation, using a perceptual hash that survives re-encoding;
109
+ - blocking behaviour, reported as false-positive and false-negative rates.
110
+
111
+ Every case runs repeatedly and reports mean, spread, and a 95% interval, plus latency, cost, error,
112
+ and failover figures. Scores inside a configured uncertainty band go to a `ReviewQueue` instead of
113
+ being decided automatically.
114
+ - **A masked-edit conformance case.** It runs for every provider that declares `supportsMask`. The
115
+ fixture is a literal PNG, so the testing entry point does not load the codec.
116
+
117
+ ### Changed
118
+
119
+ - **OpenAI masked edits and transparency are enabled.** `OpenAIImageProvider` now declares
120
+ `supportsMask` and `supportsTransparency`. `background: 'transparent'` is refused only with JPEG
121
+ output.
122
+ - **A provider can explain missing images.** A blocking output finding marked `metadata.withheld`
123
+ counts toward the requested image count, and it does not block the images that were returned. Any
124
+ other blocking finding still blocks the whole result.
125
+ - **SSRF protection is shared.** It moved out of the web connector into one module that the connector
126
+ and image inputs both use. The web connector behaves the same, and its security tests pass
127
+ unchanged. Policy refusals are now a `UrlPolicyError`, with the same messages.
128
+ - **Graphs checkpoint by default, as the documentation always said.** `compile()` now uses an
129
+ in-process `MemoryGraphCheckpointer` when none is given, so `interrupt()`, `state()`, and
130
+ `history()` work without setup. The default keeps at most 1,000 threads, dropping the least recently
131
+ written one, so a service that never resumes cannot grow without limit. `maxThreads` is configurable,
132
+ and `checkpointer: false` turns checkpointing off. Before this fix, `compile()` created no
133
+ checkpointer and `interrupt()` threw.
134
+ - **The whole-package size limit is higher.** The new modules are about 200 KB unpacked across both
135
+ builds, so the tarball limit rose from 460 KB to 500 KB packed and from 2.85 MB to 3.1 MB unpacked.
136
+ No existing import got heavier because of them. Each new module has its own per-subpath budget, and
137
+ the root import loads none of them.
138
+
139
+ ### Fixed
140
+
141
+ - **A failed graph step no longer re-runs the siblings that finished.** The failed checkpoint used to
142
+ discard their writes, so `continue()` ran them again and repeated their side effects. It now keeps
143
+ those writes, and `continue()` retries only the nodes that did not finish.
144
+ - **Finished siblings still route onward after a paused or failed step resumes.** The checkpoint
145
+ carried only the unfinished nodes, so the outgoing edges of siblings that had already finished were
146
+ lost. A new optional `completed` field on the checkpoint records those siblings.
147
+ - **A subgraph that asks a question now pauses its parent.** `asNode()` used to treat an interrupted
148
+ subgraph as finished: the parent merged its partial state and carried on. The parent now interrupts
149
+ with the same question, and resuming the parent passes the answer into the subgraph, which continues
150
+ where it stopped. A subgraph that asks several questions works across several resumes.
151
+ - **Rewinding no longer leaves checkpoints from the abandoned timeline.** After `resumeFrom(step)`,
152
+ both checkpointers kept the later steps, so `state()` could return a step that no longer existed.
153
+ Writing a step now drops any stored steps at or after it.
154
+ - **`context.report()` works.** It did nothing. Progress now reaches the new
155
+ `GraphRunOptions.onProgress` callback, and a callback that throws does not fail the node.
156
+ - **`CompileOptions.name` is used.** It was documented but never read. It is now recorded on every
157
+ checkpoint as `metadata.graph`.
158
+ - **An unnamed graph run now reports its thread id.** `invoke()` without a `threadId` returned
159
+ `threadId: ''` even though it had generated one, so the run could not be inspected or resumed.
160
+ - **`AgentLoop` no longer runs a tool with arguments the model did not send.** Malformed tool-call
161
+ JSON, or arguments that are not an object, used to become `{}` and the tool ran anyway. The tool is
162
+ now skipped, and the parse error goes back to the model as the tool result.
163
+ - **`AgentLoop` says why it stopped.** `AgentResult.stopReason` is `completed` or `max_iterations`, so
164
+ a caller can tell a final answer from a run that hit the iteration limit.
8
165
 
9
166
  ## [1.9.0] - 2026-09-15
10
167
 
@@ -457,7 +614,9 @@ shared policy vocabulary is in place for a future release that revisits this.
457
614
  - URL fetching rejects unsafe private-network targets and limits response reads.
458
615
  - CLI and audit findings no longer disclose detected secret values.
459
616
 
460
- [Unreleased]: https://github.com/mkhitar-abrahamyan/nexus-ai/compare/v1.9.0...HEAD
617
+ [Unreleased]: https://github.com/mkhitar-abrahamyan/nexus-ai/compare/v1.11.0...HEAD
618
+ [1.11.0]: https://github.com/mkhitar-abrahamyan/nexus-ai/compare/v1.10.0...v1.11.0
619
+ [1.10.0]: https://github.com/mkhitar-abrahamyan/nexus-ai/compare/v1.9.0...v1.10.0
461
620
  [1.9.0]: https://github.com/mkhitar-abrahamyan/nexus-ai/compare/v1.8.0...v1.9.0
462
621
  [1.8.0]: https://github.com/mkhitar-abrahamyan/nexus-ai/compare/v1.7.0...v1.8.0
463
622
  [1.7.0]: https://github.com/mkhitar-abrahamyan/nexus-ai/compare/v1.6.0...v1.7.0