nexus-ai-pro 1.12.0 → 1.14.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 +27 -0
- package/CHANGELOG.md +66 -1
- package/README.md +160 -0
- package/dist/agent/create-agent.d.ts +119 -0
- package/dist/agent/create-agent.js +176 -0
- package/dist/agent/index.d.ts +5 -0
- package/dist/agent/index.js +4 -0
- package/dist/agent/middleware.d.ts +46 -0
- package/dist/agent/middleware.js +77 -0
- package/dist/graph/graph.js +1 -0
- package/dist/mcp/client.d.ts +106 -0
- package/dist/mcp/client.js +243 -0
- package/dist/mcp/index.d.ts +3 -0
- package/dist/mcp/index.js +3 -0
- package/dist/mcp/protocol.d.ts +71 -0
- package/dist/mcp/protocol.js +68 -0
- package/dist/mcp/server.d.ts +46 -0
- package/dist/mcp/server.js +155 -0
- package/dist/store/index.d.ts +2 -0
- package/dist/store/index.js +1 -0
- package/dist/store/memory.d.ts +41 -0
- package/dist/store/memory.js +182 -0
- package/dist/store/redis.d.ts +49 -0
- package/dist/store/redis.js +128 -0
- package/dist/tracing/alerts.d.ts +60 -0
- package/dist/tracing/alerts.js +98 -0
- package/dist/tracing/compare.d.ts +31 -0
- package/dist/tracing/compare.js +69 -0
- package/dist/tracing/index.d.ts +6 -0
- package/dist/tracing/index.js +5 -0
- package/dist/tracing/instrument.d.ts +47 -0
- package/dist/tracing/instrument.js +138 -0
- package/dist/tracing/stores.d.ts +53 -0
- package/dist/tracing/stores.js +192 -0
- package/dist/tracing/tracer.d.ts +73 -0
- package/dist/tracing/tracer.js +182 -0
- package/dist/types/graph.d.ts +10 -0
- package/dist/types/store.d.ts +61 -0
- package/dist/types/store.js +9 -0
- package/dist/types/tracing.d.ts +102 -0
- package/dist/types/tracing.js +10 -0
- package/dist-cjs/agent/create-agent.d.ts +119 -0
- package/dist-cjs/agent/create-agent.js +181 -0
- package/dist-cjs/agent/index.d.ts +5 -0
- package/dist-cjs/agent/index.js +16 -0
- package/dist-cjs/agent/middleware.d.ts +46 -0
- package/dist-cjs/agent/middleware.js +82 -0
- package/dist-cjs/graph/graph.js +1 -0
- package/dist-cjs/mcp/client.d.ts +106 -0
- package/dist-cjs/mcp/client.js +282 -0
- package/dist-cjs/mcp/index.d.ts +3 -0
- package/dist-cjs/mcp/index.js +15 -0
- package/dist-cjs/mcp/protocol.d.ts +71 -0
- package/dist-cjs/mcp/protocol.js +77 -0
- package/dist-cjs/mcp/server.d.ts +46 -0
- package/dist-cjs/mcp/server.js +160 -0
- package/dist-cjs/store/index.d.ts +2 -0
- package/dist-cjs/store/index.js +6 -0
- package/dist-cjs/store/memory.d.ts +41 -0
- package/dist-cjs/store/memory.js +190 -0
- package/dist-cjs/store/redis.d.ts +49 -0
- package/dist-cjs/store/redis.js +132 -0
- package/dist-cjs/tracing/alerts.d.ts +60 -0
- package/dist-cjs/tracing/alerts.js +104 -0
- package/dist-cjs/tracing/compare.d.ts +31 -0
- package/dist-cjs/tracing/compare.js +73 -0
- package/dist-cjs/tracing/index.d.ts +6 -0
- package/dist-cjs/tracing/index.js +21 -0
- package/dist-cjs/tracing/instrument.d.ts +47 -0
- package/dist-cjs/tracing/instrument.js +142 -0
- package/dist-cjs/tracing/stores.d.ts +53 -0
- package/dist-cjs/tracing/stores.js +202 -0
- package/dist-cjs/tracing/tracer.d.ts +73 -0
- package/dist-cjs/tracing/tracer.js +187 -0
- package/dist-cjs/types/graph.d.ts +10 -0
- package/dist-cjs/types/store.d.ts +61 -0
- package/dist-cjs/types/store.js +10 -0
- package/dist-cjs/types/tracing.d.ts +102 -0
- package/dist-cjs/types/tracing.js +11 -0
- package/package.json +66 -1
package/API_STABILITY.md
CHANGED
|
@@ -328,6 +328,33 @@ Also since 1.12.0, all additive:
|
|
|
328
328
|
- A subgraph node's thread id is `<parent thread>:<task id>`, which equals the previous
|
|
329
329
|
`<parent thread>:<node>` for any node not reached through `Send`.
|
|
330
330
|
|
|
331
|
+
## Agent, store, MCP, and tracing stages (1.14.0)
|
|
332
|
+
|
|
333
|
+
The `nexus-ai-pro/agent`, `nexus-ai-pro/store`, `nexus-ai-pro/store/redis`, and `nexus-ai-pro/mcp`
|
|
334
|
+
subpaths are public and follow the 1.x rules. None is exported from the root import.
|
|
335
|
+
|
|
336
|
+
- `createAgent()` returns a compiled graph, so the graph guarantees above apply to an agent: a
|
|
337
|
+
superstep is atomic with respect to checkpointing, a finished task is never re-run by a resume, and
|
|
338
|
+
an approval survives a restart. The agent's state channels (`messages`, `iterations`, `answer`,
|
|
339
|
+
`stopReason`) are a normalized shape; what a model decides to put in them is not.
|
|
340
|
+
- `Store` is the contract; `MemoryStore` and `RedisStore` implement it. Ranking from a semantic search
|
|
341
|
+
depends on the embedding function a caller injects and is not a guarantee. `MemoryStore` is
|
|
342
|
+
process-local and bounded, and drops the least recently written item past `maxItems`.
|
|
343
|
+
- The MCP subpath implements a subset of the Model Context Protocol: initialize, tools, resources, and
|
|
344
|
+
prompts, over stdio and HTTP. Protocol versions and server behaviour are upstream contracts outside
|
|
345
|
+
this policy. Server-initiated streaming, sampling, and roots are not implemented; new methods may be
|
|
346
|
+
added in a minor release.
|
|
347
|
+
- `nexus-ai-pro/tracing` is public: `Tracer`, the `TraceStore` contract, `MemoryTraceStore`,
|
|
348
|
+
`JsonlTraceStore`, `traceGraph()`, `traceModelClient()`, `compareTraces()`, and `AlertEvaluator`.
|
|
349
|
+
The `Run`, `RunTree`, and `RunQuery` shapes are normalized; what a model puts in a run's inputs and
|
|
350
|
+
outputs is not. New `RunKind` values and query fields may be added in a minor release. Sampling is
|
|
351
|
+
probabilistic by definition, so which traces are kept is not a guarantee, but the tail rules are:
|
|
352
|
+
an error, a run past `keepSlowerThanMs`, or one past `keepCostlierThan` is always kept.
|
|
353
|
+
- `agentAsTool()` and the bundled middleware (`summarizeHistory`, `redactMessages`, `limitToolCalls`)
|
|
354
|
+
are public and additive.
|
|
355
|
+
- `AgentLoop`, `tool()`, and `ToolExecutor` keep their behaviour and are re-exported from
|
|
356
|
+
`nexus-ai-pro/agent` as well as the root.
|
|
357
|
+
|
|
331
358
|
## Deprecation process
|
|
332
359
|
|
|
333
360
|
Deprecated APIs are marked with `@deprecated` in declarations and described in the changelog. Removals
|
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,70 @@ Notable changes to this project are recorded here. The format follows [Keep a Ch
|
|
|
4
4
|
|
|
5
5
|
## [Unreleased]
|
|
6
6
|
|
|
7
|
+
## [1.14.0] - 2026-09-20
|
|
8
|
+
|
|
9
|
+
The memory, agent, and MCP work planned for 1.13.0 ships here together with tracing, so no 1.13.0 was
|
|
10
|
+
published.
|
|
11
|
+
|
|
12
|
+
Memory, agents, MCP, and traces. An agent is now a graph rather than a loop, so it inherits
|
|
13
|
+
approvals, parallel tool calls, and durability. A store gives it memory that outlives a thread, MCP
|
|
14
|
+
connects it to tools this package does not have to ship, and every run can be recorded as a tree you
|
|
15
|
+
can search, compare, and alert on.
|
|
16
|
+
|
|
17
|
+
### Added
|
|
18
|
+
|
|
19
|
+
- **`nexus-ai-pro/agent` and `createAgent()`.** Returns a compiled graph, so an agent gets
|
|
20
|
+
checkpoints, resume, forks, events, and a diagram from the graph runtime rather than from code
|
|
21
|
+
written twice.
|
|
22
|
+
- Tool calls run as parallel tasks, bounded by `toolConcurrency`.
|
|
23
|
+
- `interruptOn` makes a tool wait for a human. The approval is a checkpoint, so it can arrive days
|
|
24
|
+
later from another process, and it can approve, refuse with a reason the model sees, or approve
|
|
25
|
+
with corrected arguments.
|
|
26
|
+
- Middleware wraps the model call (`beforeModel`, `afterModel`) and each tool call
|
|
27
|
+
(`wrapToolCall`).
|
|
28
|
+
- `stopReason` distinguishes a finished answer from one that ran out of iterations, and malformed
|
|
29
|
+
tool arguments never reach a tool.
|
|
30
|
+
- `AgentLoop` is unchanged, for the case that wants none of this.
|
|
31
|
+
- **`nexus-ai-pro/store`, long-term memory.** Namespaced tuples, `put`/`get`/`delete`/`search`/
|
|
32
|
+
`listNamespaces`, TTLs, and field filters.
|
|
33
|
+
- Semantic search ranks by any embedding function you inject, so the store never imports the
|
|
34
|
+
embeddings runtime; without an index, a query matches text.
|
|
35
|
+
- `MemoryStore` is bounded, like the graph's memory checkpointer. `RedisStore`
|
|
36
|
+
(`nexus-ai-pro/store/redis`) shares memory across processes through a client-like interface.
|
|
37
|
+
- `compile({ store })` hands it to every node as `context.store`.
|
|
38
|
+
- **`nexus-ai-pro/tracing`, run trees you can query.** Metrics say how it is going; a trace says what
|
|
39
|
+
happened.
|
|
40
|
+
- Every family has a run kind: model, tool, graph, node, agent, retriever, embedding, image, voice,
|
|
41
|
+
realtime, operation. A run carries inputs, outputs, timing, tokens, cost, tags, and errors.
|
|
42
|
+
- `traceGraph()` turns the graph's own event stream into a run tree, so nothing inside the graph
|
|
43
|
+
knows about tracing and an untraced run pays nothing. `traceModelClient()` nests each model call
|
|
44
|
+
inside the node that made it, with its tokens and cost.
|
|
45
|
+
- Tail sampling keeps every error, slow run, and expensive run whatever the head rate is, because
|
|
46
|
+
the decision is made when a trace finishes.
|
|
47
|
+
- Redaction runs before storage: hidden fields are never written, and a `redact` hook gets the last
|
|
48
|
+
word.
|
|
49
|
+
- `MemoryTraceStore` is bounded; `JsonlTraceStore` appends to a file that survives a restart and can
|
|
50
|
+
be read back, pruned, and rotated.
|
|
51
|
+
- Queries filter by kind, status, name, model, tags, metadata, latency, cost, time, and feedback.
|
|
52
|
+
`tree()` assembles a trace, `formatTree()` prints it, and `compareTraces()` reports what changed
|
|
53
|
+
between two runs of the same shape.
|
|
54
|
+
- `recordFeedback()` attaches scores from people or from evaluators.
|
|
55
|
+
- `AlertEvaluator` runs rules over stored runs — error rate, latency percentiles, cost, count — and
|
|
56
|
+
every alert carries the runs that tripped it. `createWebhookNotifier()` posts them.
|
|
57
|
+
- **Bundled agent middleware.** `summarizeHistory` keeps a long transcript from growing without
|
|
58
|
+
bound, `redactMessages` keeps secrets out of provider requests and responses, and `limitToolCalls`
|
|
59
|
+
caps how often a tool may run.
|
|
60
|
+
- **`agentAsTool()`.** Gives one agent to another as a tool, so a supervisor can delegate while
|
|
61
|
+
keeping control. Each agent keeps its own memory, approvals, and thread.
|
|
62
|
+
|
|
63
|
+
- **`nexus-ai-pro/mcp`, both directions of the Model Context Protocol.** Implemented directly, with
|
|
64
|
+
no protocol SDK dependency.
|
|
65
|
+
- `McpClient` lists and calls tools, reads resources and prompts, and `toNexusTools()` turns a
|
|
66
|
+
server's tools into tools an agent can call, with optional name prefixes.
|
|
67
|
+
- `McpServer` exposes this application's tools and resources to other assistants.
|
|
68
|
+
- Stdio and HTTP transports are included, and the transport is an interface, so a client and a
|
|
69
|
+
server can be wired together in memory for a test.
|
|
70
|
+
|
|
7
71
|
## [1.12.0] - 2026-09-20
|
|
8
72
|
|
|
9
73
|
Graph control and introspection. A node can route itself, a run can pause at breakpoints and be
|
|
@@ -653,7 +717,8 @@ shared policy vocabulary is in place for a future release that revisits this.
|
|
|
653
717
|
- URL fetching rejects unsafe private-network targets and limits response reads.
|
|
654
718
|
- CLI and audit findings no longer disclose detected secret values.
|
|
655
719
|
|
|
656
|
-
[Unreleased]: https://github.com/mkhitar-abrahamyan/nexus-ai/compare/v1.
|
|
720
|
+
[Unreleased]: https://github.com/mkhitar-abrahamyan/nexus-ai/compare/v1.14.0...HEAD
|
|
721
|
+
[1.14.0]: https://github.com/mkhitar-abrahamyan/nexus-ai/compare/v1.12.0...v1.14.0
|
|
657
722
|
[1.12.0]: https://github.com/mkhitar-abrahamyan/nexus-ai/compare/v1.11.0...v1.12.0
|
|
658
723
|
[1.11.0]: https://github.com/mkhitar-abrahamyan/nexus-ai/compare/v1.10.0...v1.11.0
|
|
659
724
|
[1.10.0]: https://github.com/mkhitar-abrahamyan/nexus-ai/compare/v1.9.0...v1.10.0
|
package/README.md
CHANGED
|
@@ -655,6 +655,161 @@ private to the subgraph.
|
|
|
655
655
|
|
|
656
656
|
The graph is not in the root import. It costs nothing to a user who does not build graphs.
|
|
657
657
|
|
|
658
|
+
## Agents
|
|
659
|
+
|
|
660
|
+
An agent is a graph, so everything above applies to it: checkpoints, human approval, parallel work,
|
|
661
|
+
forks, events, and a diagram.
|
|
662
|
+
|
|
663
|
+
```ts
|
|
664
|
+
import { createAgent, agentInput, tool } from 'nexus-ai-pro/agent';
|
|
665
|
+
|
|
666
|
+
const agent = createAgent({
|
|
667
|
+
client: ai, // anything with complete(); NexusAI qualifies
|
|
668
|
+
systemPrompt: 'You are a support engineer.',
|
|
669
|
+
tools: [refundTool, emailTool],
|
|
670
|
+
interruptOn: { send_email: true }, // this one waits for a human
|
|
671
|
+
store, // long-term memory, below
|
|
672
|
+
checkpointer, // survives a restart
|
|
673
|
+
});
|
|
674
|
+
|
|
675
|
+
const run = await agent.invoke(agentInput('Refund order 1182 and tell the customer'), { threadId });
|
|
676
|
+
run.state.answer; // the final text
|
|
677
|
+
run.state.stopReason; // 'completed' | 'max_iterations'
|
|
678
|
+
```
|
|
679
|
+
|
|
680
|
+
**Tool calls run in parallel.** Each call the model requests becomes its own task, bounded by
|
|
681
|
+
`toolConcurrency`, so three lookups take as long as the slowest one.
|
|
682
|
+
|
|
683
|
+
**Approval is an interrupt, not a callback.** A tool listed in `interruptOn` pauses the run and
|
|
684
|
+
checkpoints it. The answer can approve, refuse with a reason the model sees, or approve with
|
|
685
|
+
corrected arguments:
|
|
686
|
+
|
|
687
|
+
```ts
|
|
688
|
+
if (run.status === 'awaiting_input') {
|
|
689
|
+
await agent.resumeWith(threadId, { approved: true, args: { to: 'billing@example.com' } });
|
|
690
|
+
}
|
|
691
|
+
```
|
|
692
|
+
|
|
693
|
+
Because it is a checkpoint, the approval can arrive days later, from another process.
|
|
694
|
+
|
|
695
|
+
**Middleware** wraps the parts worth controlling: `beforeModel` adjusts the request, `afterModel`
|
|
696
|
+
inspects or replaces the response, and `wrapToolCall` surrounds each tool call for logging, timing,
|
|
697
|
+
or policy. `AgentLoop` remains for the simple case that needs none of this.
|
|
698
|
+
|
|
699
|
+
## Long-term Memory
|
|
700
|
+
|
|
701
|
+
A checkpoint remembers one conversation. A store remembers across them:
|
|
702
|
+
|
|
703
|
+
```ts
|
|
704
|
+
import { MemoryStore } from 'nexus-ai-pro/store';
|
|
705
|
+
|
|
706
|
+
const store = new MemoryStore({ index: { embed, fields: ['text'] } }); // embed is yours
|
|
707
|
+
await store.put(['tenant-7', 'users', 'alice'], 'tone', { text: 'prefers brief answers' });
|
|
708
|
+
|
|
709
|
+
// In any node or tool, in any thread, later:
|
|
710
|
+
const memories = await context.store.search(['tenant-7', 'users', 'alice'], { query: 'how do they like answers?' });
|
|
711
|
+
```
|
|
712
|
+
|
|
713
|
+
Namespaces are tuples, so `['tenant-7', 'users', 'alice']` is both a place to put something and a
|
|
714
|
+
prefix to search. Items can expire with `ttlMs`, be filtered by field, and be ranked semantically by
|
|
715
|
+
any embedding function you inject — the store never imports the embeddings runtime, and without an
|
|
716
|
+
index a query falls back to matching text. `RedisStore` from `nexus-ai-pro/store/redis` carries the
|
|
717
|
+
same contract across processes through a client-like interface, so no Redis package is a dependency
|
|
718
|
+
here.
|
|
719
|
+
|
|
720
|
+
## MCP
|
|
721
|
+
|
|
722
|
+
The Model Context Protocol, both directions, implemented directly rather than through an SDK:
|
|
723
|
+
|
|
724
|
+
```ts
|
|
725
|
+
import { McpClient, createStdioTransport } from 'nexus-ai-pro/mcp';
|
|
726
|
+
import { Tracer, MemoryTraceStore } from 'nexus-ai-pro/tracing';
|
|
727
|
+
|
|
728
|
+
const client = new McpClient(createStdioTransport({ command: 'npx', args: ['-y', 'some-mcp-server'] }));
|
|
729
|
+
const agent = createAgent({ client: ai, tools: await client.toNexusTools({ prefix: 'files' }) });
|
|
730
|
+
```
|
|
731
|
+
|
|
732
|
+
That is how this package reaches a broad tool ecosystem without maintaining a catalogue of
|
|
733
|
+
integrations: anything exposed over MCP becomes tools an agent can call. The server direction lends
|
|
734
|
+
your tools out the same way, so a tool written once with `tool()` serves an agent here and an editor
|
|
735
|
+
elsewhere:
|
|
736
|
+
|
|
737
|
+
```ts
|
|
738
|
+
import { McpServer, createStdioServerTransport } from 'nexus-ai-pro/mcp';
|
|
739
|
+
|
|
740
|
+
await new McpServer({ name: 'my-app', tools: [refundTool] }).connect(createStdioServerTransport());
|
|
741
|
+
```
|
|
742
|
+
|
|
743
|
+
Stdio and HTTP transports are included, and the transport is an interface, so a test can wire a
|
|
744
|
+
client to a server in memory.
|
|
745
|
+
|
|
746
|
+
## Traces
|
|
747
|
+
|
|
748
|
+
Metrics say how it is going. A trace says what happened: the run tree of one request, with its
|
|
749
|
+
inputs, outputs, tokens, cost, and errors, stored where you can search it.
|
|
750
|
+
|
|
751
|
+
```ts
|
|
752
|
+
import { Tracer, MemoryTraceStore, traceGraph, traceModelClient } from 'nexus-ai-pro/tracing';
|
|
753
|
+
|
|
754
|
+
const tracer = new Tracer({
|
|
755
|
+
store: new MemoryTraceStore(), // or JsonlTraceStore({ file })
|
|
756
|
+
sampling: { rate: 0.05, keepErrors: true }, // 5% of traces, plus every failure
|
|
757
|
+
redaction: { hideFields: ['apiKey', 'user.email'] },
|
|
758
|
+
});
|
|
759
|
+
|
|
760
|
+
const tracing = traceGraph(tracer, { name: 'support-agent', kind: 'agent' });
|
|
761
|
+
const agent = createAgent({ client: traceModelClient(ai, tracer, { parent: () => tracing.runFor('model') }) });
|
|
762
|
+
|
|
763
|
+
const run = await agent.invoke(agentInput(question), { threadId, ...tracing.runOptions });
|
|
764
|
+
await tracing.finish(run);
|
|
765
|
+
```
|
|
766
|
+
|
|
767
|
+
**Nothing inside the graph knows about tracing.** The graph already reports every task starting,
|
|
768
|
+
retrying, and finishing; a trace is that stream written down as a tree. An application that does not
|
|
769
|
+
trace creates no context, allocates nothing, and does no per-call work.
|
|
770
|
+
|
|
771
|
+
**Tail sampling keeps what matters.** A 5% rate still records every error, every run slower than a
|
|
772
|
+
threshold, and every run more expensive than one, because the decision is made when the trace
|
|
773
|
+
finishes rather than when it starts.
|
|
774
|
+
|
|
775
|
+
**Redaction happens before storage**, so a field you hide is never written, and a `redact` hook gets
|
|
776
|
+
the last word on every run.
|
|
777
|
+
|
|
778
|
+
**Then ask questions of it:**
|
|
779
|
+
|
|
780
|
+
```ts
|
|
781
|
+
const failures = await store.query({ status: 'error', kind: 'model', since: yesterday, minLatencyMs: 2000 });
|
|
782
|
+
const tree = await store.tree(failures[0].traceId);
|
|
783
|
+
console.log(formatTree(tree));
|
|
784
|
+
|
|
785
|
+
await tracer.recordFeedback(runId, { key: 'thumbs', score: 0, source: 'user' });
|
|
786
|
+
```
|
|
787
|
+
|
|
788
|
+
`compareTraces(a, b)` lays two runs of the same shape side by side and reports what changed — the
|
|
789
|
+
step that got slower, the tool that stopped being called, the output that differs — which is how
|
|
790
|
+
"it worked yesterday" becomes an answerable question.
|
|
791
|
+
|
|
792
|
+
**Alerts** run the same queries on a timer, and carry the runs that tripped them:
|
|
793
|
+
|
|
794
|
+
```ts
|
|
795
|
+
import { AlertEvaluator, createWebhookNotifier } from 'nexus-ai-pro/tracing';
|
|
796
|
+
|
|
797
|
+
const alerts = new AlertEvaluator(
|
|
798
|
+
store,
|
|
799
|
+
[
|
|
800
|
+
{ name: 'error rate', metric: 'errorRate', threshold: 0.05, minRuns: 20 },
|
|
801
|
+
{ name: 'p95 latency', metric: 'latencyP95', threshold: 8000 },
|
|
802
|
+
{ name: 'hourly spend', metric: 'cost', threshold: 25, windowMs: 3_600_000 },
|
|
803
|
+
],
|
|
804
|
+
{ notifier: createWebhookNotifier({ url: process.env.ALERT_WEBHOOK! }) },
|
|
805
|
+
);
|
|
806
|
+
|
|
807
|
+
setInterval(() => void alerts.evaluate(), 60_000);
|
|
808
|
+
```
|
|
809
|
+
|
|
810
|
+
An alert names the rule, the measured value, and three runs that contributed, so the next step is
|
|
811
|
+
reading them rather than starting an investigation.
|
|
812
|
+
|
|
658
813
|
## Provider Batch Tiers
|
|
659
814
|
|
|
660
815
|
Both OpenAI and Anthropic sell an asynchronous tier at roughly half price, in exchange for a
|
|
@@ -1925,6 +2080,7 @@ only, so it never appears in an import graph.
|
|
|
1925
2080
|
| `nexus-ai-pro/providers/llamacpp` | 77 KB | 13% | none |
|
|
1926
2081
|
| `nexus-ai-pro/providers/lmstudio` | 77 KB | 13% | none |
|
|
1927
2082
|
| `nexus-ai-pro/providers/openai` | 77 KB | 13% | none |
|
|
2083
|
+
| `nexus-ai-pro/agent` | 76 KB | 12% | none |
|
|
1928
2084
|
| `nexus-ai-pro/providers/anthropic` | 70 KB | 11% | none |
|
|
1929
2085
|
| `nexus-ai-pro/providers/google` | 66 KB | 11% | none |
|
|
1930
2086
|
| `nexus-ai-pro/images` | 65 KB | 11% | none |
|
|
@@ -1940,6 +2096,7 @@ only, so it never appears in an import graph.
|
|
|
1940
2096
|
| `nexus-ai-pro/models` | 35 KB | 6% | none |
|
|
1941
2097
|
| `nexus-ai-pro/images/inputs` | 31 KB | 5% | none |
|
|
1942
2098
|
| `nexus-ai-pro/realtime/openai-websocket` | 29 KB | 5% | none |
|
|
2099
|
+
| `nexus-ai-pro/tracing` | 26 KB | 4% | none |
|
|
1943
2100
|
| `nexus-ai-pro/evals` | 23 KB | 4% | none |
|
|
1944
2101
|
| `nexus-ai-pro/images/transform` | 22 KB | 4% | none |
|
|
1945
2102
|
| `nexus-ai-pro/images/stores` | 22 KB | 4% | none |
|
|
@@ -1948,6 +2105,7 @@ only, so it never appears in an import graph.
|
|
|
1948
2105
|
| `nexus-ai-pro/images/openai` | 19 KB | 3% | none |
|
|
1949
2106
|
| `nexus-ai-pro/realtime/mock` | 19 KB | 3% | none |
|
|
1950
2107
|
| `nexus-ai-pro/voice` | 18 KB | 3% | none |
|
|
2108
|
+
| `nexus-ai-pro/mcp` | 18 KB | 3% | none |
|
|
1951
2109
|
| `nexus-ai-pro/images/comfyui` | 17 KB | 3% | none |
|
|
1952
2110
|
| `nexus-ai-pro/embeddings/adapters` | 17 KB | 3% | none |
|
|
1953
2111
|
| `nexus-ai-pro/realtime/conversation` | 16 KB | 3% | none |
|
|
@@ -1961,6 +2119,7 @@ only, so it never appears in an import graph.
|
|
|
1961
2119
|
| `nexus-ai-pro/images/mock` | 12 KB | 2% | none |
|
|
1962
2120
|
| `nexus-ai-pro/optimizer` | 11 KB | 2% | none |
|
|
1963
2121
|
| `nexus-ai-pro/voice/session` | 11 KB | 2% | none |
|
|
2122
|
+
| `nexus-ai-pro/store/redis` | 11 KB | 2% | none |
|
|
1964
2123
|
| `nexus-ai-pro/providers` | 10 KB | 2% | none |
|
|
1965
2124
|
| `nexus-ai-pro/providers/base` | 10 KB | 2% | none |
|
|
1966
2125
|
| `nexus-ai-pro/embeddings/models` | 10 KB | 2% | none |
|
|
@@ -1971,6 +2130,7 @@ only, so it never appears in an import graph.
|
|
|
1971
2130
|
| `nexus-ai-pro/capabilities` | 8 KB | 1% | none |
|
|
1972
2131
|
| `nexus-ai-pro/telephony/realtime-bridge` | 7 KB | 1% | none |
|
|
1973
2132
|
| `nexus-ai-pro/graph/visualize` | 6 KB | 1.0% | none |
|
|
2133
|
+
| `nexus-ai-pro/store` | 6 KB | 1.0% | none |
|
|
1974
2134
|
| `nexus-ai-pro/providers/errors` | 5 KB | 0.8% | none |
|
|
1975
2135
|
| `nexus-ai-pro/embeddings/mock` | 5 KB | 0.8% | none |
|
|
1976
2136
|
| `nexus-ai-pro/cache/semantic-cache` | 5 KB | 0.8% | none |
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import { type CompiledGraph } from '../graph/graph.js';
|
|
2
|
+
import type { GraphCheckpointer, NodeContext } from '../types/graph.js';
|
|
3
|
+
import type { CompletionRequest, Message, ToolDefinition } from '../types/messages.js';
|
|
4
|
+
import type { NexusResponse } from '../types/response.js';
|
|
5
|
+
import type { Store } from '../types/store.js';
|
|
6
|
+
/**
|
|
7
|
+
* An agent as a graph.
|
|
8
|
+
*
|
|
9
|
+
* `AgentLoop` is a `while` loop: it cannot be paused, resumed after a restart, inspected halfway, or
|
|
10
|
+
* made to run two tool calls at once, because a loop has nowhere to keep that state. The same agent
|
|
11
|
+
* expressed as a graph inherits all of it — checkpoints, human approval through `interrupt()`,
|
|
12
|
+
* parallel tool tasks through `Send`, forks, events, and a Mermaid diagram — without this module
|
|
13
|
+
* implementing any of them. `AgentLoop` stays for the simple case that wants none of that.
|
|
14
|
+
*/
|
|
15
|
+
/** The model call an agent makes. Injected, so this module needs no provider runtime. */
|
|
16
|
+
export interface AgentModelClient {
|
|
17
|
+
complete(request: CompletionRequest): Promise<NexusResponse>;
|
|
18
|
+
}
|
|
19
|
+
export interface AgentToolCall {
|
|
20
|
+
id: string;
|
|
21
|
+
name: string;
|
|
22
|
+
args: Record<string, unknown>;
|
|
23
|
+
}
|
|
24
|
+
/** What an approver may answer: allow, refuse with a reason, or allow with corrected arguments. */
|
|
25
|
+
export type AgentApproval = boolean | {
|
|
26
|
+
approved: true;
|
|
27
|
+
args?: Record<string, unknown>;
|
|
28
|
+
} | {
|
|
29
|
+
approved: false;
|
|
30
|
+
reason?: string;
|
|
31
|
+
};
|
|
32
|
+
export interface AgentApprovalPolicy {
|
|
33
|
+
/** The question an operator sees. Defaults to naming the tool and its arguments. */
|
|
34
|
+
reason?: (call: AgentToolCall) => string;
|
|
35
|
+
}
|
|
36
|
+
export interface AgentMiddleware {
|
|
37
|
+
name?: string;
|
|
38
|
+
/** Adjusts the request before it is sent: trim history, add context, swap the model. */
|
|
39
|
+
beforeModel?(context: {
|
|
40
|
+
request: CompletionRequest;
|
|
41
|
+
state: AgentState;
|
|
42
|
+
store?: Store;
|
|
43
|
+
}): CompletionRequest | void | Promise<CompletionRequest | void>;
|
|
44
|
+
/** Inspects or replaces the response: redact, validate, count. */
|
|
45
|
+
afterModel?(context: {
|
|
46
|
+
response: NexusResponse;
|
|
47
|
+
state: AgentState;
|
|
48
|
+
store?: Store;
|
|
49
|
+
}): NexusResponse | void | Promise<NexusResponse | void>;
|
|
50
|
+
/** Wraps a tool call, so a policy can log it, time it, or refuse it. */
|
|
51
|
+
wrapToolCall?(call: AgentToolCall, next: () => Promise<AgentToolResult>): Promise<AgentToolResult> | AgentToolResult;
|
|
52
|
+
}
|
|
53
|
+
export interface AgentToolResult {
|
|
54
|
+
ok: boolean;
|
|
55
|
+
result?: unknown;
|
|
56
|
+
error?: string;
|
|
57
|
+
}
|
|
58
|
+
export interface CreateAgentOptions {
|
|
59
|
+
client: AgentModelClient;
|
|
60
|
+
model?: string;
|
|
61
|
+
tools?: ToolDefinition[];
|
|
62
|
+
systemPrompt?: string;
|
|
63
|
+
/** Model calls before the agent stops with `stopReason: 'max_iterations'`. Defaults to 8. */
|
|
64
|
+
maxIterations?: number;
|
|
65
|
+
/** Tool calls run at once. Defaults to 8; `1` runs them one at a time. */
|
|
66
|
+
toolConcurrency?: number;
|
|
67
|
+
/** Tools that need human approval before they run, keyed by tool name. */
|
|
68
|
+
interruptOn?: Record<string, AgentApprovalPolicy | true>;
|
|
69
|
+
middleware?: AgentMiddleware[];
|
|
70
|
+
/** Long-term memory, available to tools and middleware as `store`. */
|
|
71
|
+
store?: Store;
|
|
72
|
+
checkpointer?: GraphCheckpointer | false;
|
|
73
|
+
name?: string;
|
|
74
|
+
temperature?: number;
|
|
75
|
+
maxTokens?: number;
|
|
76
|
+
responseFormat?: CompletionRequest['responseFormat'];
|
|
77
|
+
metadata?: Record<string, unknown>;
|
|
78
|
+
}
|
|
79
|
+
declare const agentChannels: () => {
|
|
80
|
+
messages: import("../types/graph.js").Channel<Message[]>;
|
|
81
|
+
iterations: import("../types/graph.js").Channel<number>;
|
|
82
|
+
answer: import("../types/graph.js").Channel<string>;
|
|
83
|
+
stopReason: import("../types/graph.js").Channel<AgentStopReason | undefined>;
|
|
84
|
+
};
|
|
85
|
+
export type AgentChannels = ReturnType<typeof agentChannels>;
|
|
86
|
+
export type AgentState = {
|
|
87
|
+
messages: Message[];
|
|
88
|
+
iterations: number;
|
|
89
|
+
answer: string;
|
|
90
|
+
stopReason?: AgentStopReason;
|
|
91
|
+
};
|
|
92
|
+
export type AgentStopReason = 'completed' | 'max_iterations';
|
|
93
|
+
export type AgentGraph = CompiledGraph<AgentChannels>;
|
|
94
|
+
/** Wraps a question into the state an agent starts from. */
|
|
95
|
+
export declare function agentInput(goal: string): {
|
|
96
|
+
messages: Message[];
|
|
97
|
+
};
|
|
98
|
+
/**
|
|
99
|
+
* Builds an agent and returns it as a compiled graph.
|
|
100
|
+
*
|
|
101
|
+
* Run it like any graph: `agent.invoke(agentInput('...'), { threadId })`. The result's `answer` is
|
|
102
|
+
* the final text, and `stopReason` says whether the agent finished or ran out of iterations.
|
|
103
|
+
*/
|
|
104
|
+
export declare function createAgent(options: CreateAgentOptions): AgentGraph;
|
|
105
|
+
/**
|
|
106
|
+
* Turns an agent into a tool another agent can call.
|
|
107
|
+
*
|
|
108
|
+
* The simplest multi-agent shape: a supervisor keeps control and delegates, rather than handing over
|
|
109
|
+
* the conversation. The specialist runs as its own graph, with its own memory and approvals, and
|
|
110
|
+
* returns its answer as the tool result.
|
|
111
|
+
*/
|
|
112
|
+
export declare function agentAsTool(options: {
|
|
113
|
+
agent: AgentGraph;
|
|
114
|
+
name: string;
|
|
115
|
+
description: string;
|
|
116
|
+
/** Threads the specialist's runs, so its work is resumable too. Defaults to a fresh thread. */
|
|
117
|
+
threadId?: (goal: string) => string;
|
|
118
|
+
}): ToolDefinition;
|
|
119
|
+
export type { NodeContext };
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
import { appendList, counter, lastValue } from '../graph/channels.js';
|
|
2
|
+
import { createGraph } from '../graph/graph.js';
|
|
3
|
+
import { Command, END, Send } from '../types/graph.js';
|
|
4
|
+
import { ToolExecutor } from './tool.js';
|
|
5
|
+
const agentChannels = () => ({
|
|
6
|
+
messages: appendList(),
|
|
7
|
+
iterations: counter(),
|
|
8
|
+
answer: lastValue(''),
|
|
9
|
+
stopReason: lastValue(undefined),
|
|
10
|
+
});
|
|
11
|
+
/** Wraps a question into the state an agent starts from. */
|
|
12
|
+
export function agentInput(goal) {
|
|
13
|
+
return { messages: [{ role: 'user', content: goal }] };
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Builds an agent and returns it as a compiled graph.
|
|
17
|
+
*
|
|
18
|
+
* Run it like any graph: `agent.invoke(agentInput('...'), { threadId })`. The result's `answer` is
|
|
19
|
+
* the final text, and `stopReason` says whether the agent finished or ran out of iterations.
|
|
20
|
+
*/
|
|
21
|
+
export function createAgent(options) {
|
|
22
|
+
if (typeof options.client?.complete !== 'function') {
|
|
23
|
+
throw new TypeError('createAgent needs a client with a complete() method');
|
|
24
|
+
}
|
|
25
|
+
const maxIterations = Math.max(1, options.maxIterations ?? 8);
|
|
26
|
+
const executor = new ToolExecutor(options.tools ?? []);
|
|
27
|
+
const middleware = options.middleware ?? [];
|
|
28
|
+
const approvals = options.interruptOn ?? {};
|
|
29
|
+
const graph = createGraph({ channels: agentChannels() })
|
|
30
|
+
.addNode('model', async (context) => {
|
|
31
|
+
const state = context.state;
|
|
32
|
+
let request = {
|
|
33
|
+
model: options.model ?? 'auto',
|
|
34
|
+
messages: [
|
|
35
|
+
...(options.systemPrompt ? [{ role: 'system', content: options.systemPrompt }] : []),
|
|
36
|
+
...state.messages,
|
|
37
|
+
],
|
|
38
|
+
...(options.tools?.length ? { tools: executor.list() } : {}),
|
|
39
|
+
...(options.temperature === undefined ? {} : { temperature: options.temperature }),
|
|
40
|
+
...(options.maxTokens === undefined ? {} : { maxTokens: options.maxTokens }),
|
|
41
|
+
...(options.responseFormat ? { responseFormat: options.responseFormat } : {}),
|
|
42
|
+
...(options.metadata ? { metadata: options.metadata } : {}),
|
|
43
|
+
};
|
|
44
|
+
for (const item of middleware) {
|
|
45
|
+
request = (await item.beforeModel?.({ request, state, store: options.store })) ?? request;
|
|
46
|
+
}
|
|
47
|
+
let response = await options.client.complete(request);
|
|
48
|
+
for (const item of middleware) {
|
|
49
|
+
response = (await item.afterModel?.({ response, state, store: options.store })) ?? response;
|
|
50
|
+
}
|
|
51
|
+
const assistant = {
|
|
52
|
+
role: 'assistant',
|
|
53
|
+
content: response.content,
|
|
54
|
+
...(response.toolCalls?.length ? { toolCalls: response.toolCalls } : {}),
|
|
55
|
+
};
|
|
56
|
+
const calls = response.toolCalls ?? [];
|
|
57
|
+
if (calls.length === 0) {
|
|
58
|
+
return new Command({
|
|
59
|
+
update: { messages: [assistant], iterations: 1, answer: response.content, stopReason: 'completed' },
|
|
60
|
+
goto: END,
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
if (state.iterations + 1 >= maxIterations) {
|
|
64
|
+
// The model still wants tools but has used its budget; say so rather than pretending the
|
|
65
|
+
// last message is an answer.
|
|
66
|
+
return new Command({
|
|
67
|
+
update: { messages: [assistant], iterations: 1, answer: response.content, stopReason: 'max_iterations' },
|
|
68
|
+
goto: END,
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
return new Command({
|
|
72
|
+
update: { messages: [assistant], iterations: 1 },
|
|
73
|
+
goto: calls.map((call) => new Send('tools', call)),
|
|
74
|
+
});
|
|
75
|
+
}, { ends: ['tools', END] })
|
|
76
|
+
.addNode('tools', async (context) => {
|
|
77
|
+
const call = context.input;
|
|
78
|
+
const parsed = parseArguments(call.function.arguments);
|
|
79
|
+
if (!parsed.ok) {
|
|
80
|
+
return { messages: [toolMessage(call, { ok: false, error: parsed.error })] };
|
|
81
|
+
}
|
|
82
|
+
let args = parsed.args;
|
|
83
|
+
const description = { id: call.id, name: call.function.name, args };
|
|
84
|
+
const policy = approvals[description.name];
|
|
85
|
+
if (policy) {
|
|
86
|
+
const decision = context.interrupt({
|
|
87
|
+
reason: (policy === true ? undefined : policy.reason?.(description)) ?? defaultReason(description),
|
|
88
|
+
payload: description,
|
|
89
|
+
});
|
|
90
|
+
const verdict = normalizeApproval(decision);
|
|
91
|
+
if (!verdict.approved) {
|
|
92
|
+
return {
|
|
93
|
+
messages: [toolMessage(call, { ok: false, error: verdict.reason ?? 'A human refused this tool call' })],
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
if (verdict.args)
|
|
97
|
+
args = verdict.args;
|
|
98
|
+
}
|
|
99
|
+
const run = async () => executor.execute(description.name, args);
|
|
100
|
+
const result = await middleware.reduceRight((next, item) => item.wrapToolCall
|
|
101
|
+
? () => Promise.resolve(item.wrapToolCall?.({ ...description, args }, next))
|
|
102
|
+
: next, run)();
|
|
103
|
+
return { messages: [toolMessage(call, result)] };
|
|
104
|
+
}, { ends: ['model'] })
|
|
105
|
+
.setEntry('model')
|
|
106
|
+
.addEdge('tools', 'model');
|
|
107
|
+
return graph.compile({
|
|
108
|
+
// Each iteration is two supersteps, plus the entry and a margin for a paused approval.
|
|
109
|
+
maxSteps: maxIterations * 2 + 4,
|
|
110
|
+
maxConcurrency: options.toolConcurrency ?? 8,
|
|
111
|
+
...(options.checkpointer === undefined ? {} : { checkpointer: options.checkpointer }),
|
|
112
|
+
...(options.store ? { store: options.store } : {}),
|
|
113
|
+
...(options.name ? { name: options.name } : {}),
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Turns an agent into a tool another agent can call.
|
|
118
|
+
*
|
|
119
|
+
* The simplest multi-agent shape: a supervisor keeps control and delegates, rather than handing over
|
|
120
|
+
* the conversation. The specialist runs as its own graph, with its own memory and approvals, and
|
|
121
|
+
* returns its answer as the tool result.
|
|
122
|
+
*/
|
|
123
|
+
export function agentAsTool(options) {
|
|
124
|
+
return {
|
|
125
|
+
name: options.name,
|
|
126
|
+
description: options.description,
|
|
127
|
+
parameters: {
|
|
128
|
+
type: 'object',
|
|
129
|
+
properties: { goal: { type: 'string', description: 'What this agent should do' } },
|
|
130
|
+
required: ['goal'],
|
|
131
|
+
},
|
|
132
|
+
execute: async (args) => {
|
|
133
|
+
const goal = String(args.goal ?? '');
|
|
134
|
+
const result = await options.agent.invoke(agentInput(goal), {
|
|
135
|
+
...(options.threadId ? { threadId: options.threadId(goal) } : {}),
|
|
136
|
+
});
|
|
137
|
+
if (result.status === 'awaiting_input') {
|
|
138
|
+
return `The ${options.name} agent is waiting for a human: ${result.interrupt?.reason ?? 'approval needed'}`;
|
|
139
|
+
}
|
|
140
|
+
return result.state.answer;
|
|
141
|
+
},
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
/** Turns a tool result into the message the model reads next. */
|
|
145
|
+
function toolMessage(call, result) {
|
|
146
|
+
return {
|
|
147
|
+
role: 'tool',
|
|
148
|
+
toolCallId: call.id,
|
|
149
|
+
content: JSON.stringify(result.ok ? (result.result ?? null) : { error: result.error }),
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
function defaultReason(call) {
|
|
153
|
+
return `Run tool "${call.name}" with ${JSON.stringify(call.args)}?`;
|
|
154
|
+
}
|
|
155
|
+
function normalizeApproval(decision) {
|
|
156
|
+
if (typeof decision === 'boolean')
|
|
157
|
+
return { approved: decision };
|
|
158
|
+
return decision.approved
|
|
159
|
+
? { approved: true, ...(decision.args ? { args: decision.args } : {}) }
|
|
160
|
+
: { approved: false, ...(decision.reason ? { reason: decision.reason } : {}) };
|
|
161
|
+
}
|
|
162
|
+
/** Arguments the model did not actually send must never reach a tool. */
|
|
163
|
+
function parseArguments(raw) {
|
|
164
|
+
if (!raw?.trim())
|
|
165
|
+
return { ok: true, args: {} };
|
|
166
|
+
try {
|
|
167
|
+
const parsed = JSON.parse(raw);
|
|
168
|
+
if (typeof parsed === 'object' && parsed !== null && !Array.isArray(parsed))
|
|
169
|
+
return { ok: true, args: parsed };
|
|
170
|
+
return { ok: false, error: 'Tool arguments must be a JSON object; the tool was not run' };
|
|
171
|
+
}
|
|
172
|
+
catch (error) {
|
|
173
|
+
const reason = error instanceof Error ? error.message : String(error);
|
|
174
|
+
return { ok: false, error: `Tool arguments are not valid JSON (${reason}); the tool was not run` };
|
|
175
|
+
}
|
|
176
|
+
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { AgentLoop, type AgentModelClient as AgentLoopModelClient } from './loop.js';
|
|
2
|
+
export { tool, ToolExecutor } from './tool.js';
|
|
3
|
+
export { limitToolCalls, redactMessages, type RedactOptions, summarizeHistory, type SummarizeOptions, } from './middleware.js';
|
|
4
|
+
export { agentAsTool, agentInput, type AgentApproval, type AgentApprovalPolicy, type AgentChannels, type AgentGraph, type AgentMiddleware, type AgentModelClient, type AgentState, type AgentStopReason, type AgentToolCall, type AgentToolResult, createAgent, type CreateAgentOptions, } from './create-agent.js';
|
|
5
|
+
export type { AgentConfig, AgentResult, AgentStep, ToolExecutionResult } from '../types/agent.js';
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import type { Message } from '../types/messages.js';
|
|
2
|
+
import type { AgentMiddleware } from './create-agent.js';
|
|
3
|
+
/**
|
|
4
|
+
* Middleware that ships with the agent.
|
|
5
|
+
*
|
|
6
|
+
* Each is small on purpose: the seam matters more than the set, and an application's real policy is
|
|
7
|
+
* usually its own. These cover the three every long-running agent needs — a transcript that does not
|
|
8
|
+
* grow forever, secrets that never reach a provider, and a cap on tool use.
|
|
9
|
+
*/
|
|
10
|
+
export interface SummarizeOptions {
|
|
11
|
+
/** Messages kept verbatim at the end of the transcript. Defaults to 6. */
|
|
12
|
+
keepLast?: number;
|
|
13
|
+
/** Summarizing starts once the transcript passes this many messages. Defaults to 20. */
|
|
14
|
+
triggerAfter?: number;
|
|
15
|
+
/** Turns the older messages into one summary. Usually a cheap model. */
|
|
16
|
+
summarize: (messages: Message[]) => Promise<string> | string;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Replaces the older half of a long transcript with a summary.
|
|
20
|
+
*
|
|
21
|
+
* An agent that runs for hours otherwise re-sends its whole history on every call, which costs more
|
|
22
|
+
* each turn and eventually exceeds the context window.
|
|
23
|
+
*/
|
|
24
|
+
export declare function summarizeHistory(options: SummarizeOptions): AgentMiddleware;
|
|
25
|
+
export interface RedactOptions {
|
|
26
|
+
/** Patterns replaced before a message reaches the provider. */
|
|
27
|
+
patterns: readonly RegExp[];
|
|
28
|
+
replacement?: string;
|
|
29
|
+
/** Also redact what the model sends back, for anything written to logs or state. */
|
|
30
|
+
redactOutput?: boolean;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Redacts matching text from requests, and optionally from responses.
|
|
34
|
+
*
|
|
35
|
+
* For an agent whose transcript may contain a key, an account number, or anything else that should
|
|
36
|
+
* not leave the process. The full security pipeline is in `nexus-ai-pro/security`; this is the small
|
|
37
|
+
* version that needs no configuration.
|
|
38
|
+
*/
|
|
39
|
+
export declare function redactMessages(options: RedactOptions): AgentMiddleware;
|
|
40
|
+
/**
|
|
41
|
+
* Caps how often a tool may be called in one run.
|
|
42
|
+
*
|
|
43
|
+
* A model that loops on the same call otherwise burns the iteration budget, and with an expensive
|
|
44
|
+
* tool it burns money too.
|
|
45
|
+
*/
|
|
46
|
+
export declare function limitToolCalls(limits: Record<string, number>): AgentMiddleware;
|