@oni.bot/core 0.6.1
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/README.md +308 -0
- package/dist/agents/context.d.ts +24 -0
- package/dist/agents/context.d.ts.map +1 -0
- package/dist/agents/context.js +93 -0
- package/dist/agents/context.js.map +1 -0
- package/dist/agents/define-agent.d.ts +10 -0
- package/dist/agents/define-agent.d.ts.map +1 -0
- package/dist/agents/define-agent.js +121 -0
- package/dist/agents/define-agent.js.map +1 -0
- package/dist/agents/functional-agent.d.ts +12 -0
- package/dist/agents/functional-agent.d.ts.map +1 -0
- package/dist/agents/functional-agent.js +115 -0
- package/dist/agents/functional-agent.js.map +1 -0
- package/dist/agents/index.d.ts +6 -0
- package/dist/agents/index.d.ts.map +1 -0
- package/dist/agents/index.js +7 -0
- package/dist/agents/index.js.map +1 -0
- package/dist/agents/types.d.ts +62 -0
- package/dist/agents/types.d.ts.map +1 -0
- package/dist/agents/types.js +8 -0
- package/dist/agents/types.js.map +1 -0
- package/dist/checkpoint.d.ts +27 -0
- package/dist/checkpoint.d.ts.map +1 -0
- package/dist/checkpoint.js +91 -0
- package/dist/checkpoint.js.map +1 -0
- package/dist/checkpointers/index.d.ts +4 -0
- package/dist/checkpointers/index.d.ts.map +1 -0
- package/dist/checkpointers/index.js +5 -0
- package/dist/checkpointers/index.js.map +1 -0
- package/dist/checkpointers/namespaced.d.ts +12 -0
- package/dist/checkpointers/namespaced.d.ts.map +1 -0
- package/dist/checkpointers/namespaced.js +37 -0
- package/dist/checkpointers/namespaced.js.map +1 -0
- package/dist/checkpointers/postgres.d.ts +13 -0
- package/dist/checkpointers/postgres.d.ts.map +1 -0
- package/dist/checkpointers/postgres.js +100 -0
- package/dist/checkpointers/postgres.js.map +1 -0
- package/dist/checkpointers/sqlite.d.ts +14 -0
- package/dist/checkpointers/sqlite.d.ts.map +1 -0
- package/dist/checkpointers/sqlite.js +98 -0
- package/dist/checkpointers/sqlite.js.map +1 -0
- package/dist/context.d.ts +24 -0
- package/dist/context.d.ts.map +1 -0
- package/dist/context.js +47 -0
- package/dist/context.js.map +1 -0
- package/dist/coordination/index.d.ts +3 -0
- package/dist/coordination/index.d.ts.map +1 -0
- package/dist/coordination/index.js +3 -0
- package/dist/coordination/index.js.map +1 -0
- package/dist/coordination/pubsub.d.ts +38 -0
- package/dist/coordination/pubsub.d.ts.map +1 -0
- package/dist/coordination/pubsub.js +73 -0
- package/dist/coordination/pubsub.js.map +1 -0
- package/dist/coordination/request-reply.d.ts +40 -0
- package/dist/coordination/request-reply.d.ts.map +1 -0
- package/dist/coordination/request-reply.js +77 -0
- package/dist/coordination/request-reply.js.map +1 -0
- package/dist/errors.d.ts +27 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +41 -0
- package/dist/errors.js.map +1 -0
- package/dist/events/bus.d.ts +13 -0
- package/dist/events/bus.d.ts.map +1 -0
- package/dist/events/bus.js +52 -0
- package/dist/events/bus.js.map +1 -0
- package/dist/events/index.d.ts +3 -0
- package/dist/events/index.d.ts.map +1 -0
- package/dist/events/index.js +3 -0
- package/dist/events/index.js.map +1 -0
- package/dist/events/types.d.ts +87 -0
- package/dist/events/types.d.ts.map +1 -0
- package/dist/events/types.js +2 -0
- package/dist/events/types.js.map +1 -0
- package/dist/functional.d.ts +36 -0
- package/dist/functional.d.ts.map +1 -0
- package/dist/functional.js +103 -0
- package/dist/functional.js.map +1 -0
- package/dist/graph.d.ts +74 -0
- package/dist/graph.d.ts.map +1 -0
- package/dist/graph.js +119 -0
- package/dist/graph.js.map +1 -0
- package/dist/guardrails/audit.d.ts +13 -0
- package/dist/guardrails/audit.d.ts.map +1 -0
- package/dist/guardrails/audit.js +31 -0
- package/dist/guardrails/audit.js.map +1 -0
- package/dist/guardrails/budget.d.ts +30 -0
- package/dist/guardrails/budget.d.ts.map +1 -0
- package/dist/guardrails/budget.js +154 -0
- package/dist/guardrails/budget.js.map +1 -0
- package/dist/guardrails/filters.d.ts +24 -0
- package/dist/guardrails/filters.d.ts.map +1 -0
- package/dist/guardrails/filters.js +87 -0
- package/dist/guardrails/filters.js.map +1 -0
- package/dist/guardrails/index.d.ts +8 -0
- package/dist/guardrails/index.d.ts.map +1 -0
- package/dist/guardrails/index.js +9 -0
- package/dist/guardrails/index.js.map +1 -0
- package/dist/guardrails/permissions.d.ts +9 -0
- package/dist/guardrails/permissions.d.ts.map +1 -0
- package/dist/guardrails/permissions.js +29 -0
- package/dist/guardrails/permissions.js.map +1 -0
- package/dist/guardrails/types.d.ts +30 -0
- package/dist/guardrails/types.d.ts.map +1 -0
- package/dist/guardrails/types.js +2 -0
- package/dist/guardrails/types.js.map +1 -0
- package/dist/hitl/index.d.ts +5 -0
- package/dist/hitl/index.d.ts.map +1 -0
- package/dist/hitl/index.js +3 -0
- package/dist/hitl/index.js.map +1 -0
- package/dist/hitl/interrupt.d.ts +81 -0
- package/dist/hitl/interrupt.d.ts.map +1 -0
- package/dist/hitl/interrupt.js +116 -0
- package/dist/hitl/interrupt.js.map +1 -0
- package/dist/hitl/resume.d.ts +33 -0
- package/dist/hitl/resume.d.ts.map +1 -0
- package/dist/hitl/resume.js +72 -0
- package/dist/hitl/resume.js.map +1 -0
- package/dist/index.d.ts +57 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +58 -0
- package/dist/index.js.map +1 -0
- package/dist/injected.d.ts +26 -0
- package/dist/injected.d.ts.map +1 -0
- package/dist/injected.js +25 -0
- package/dist/injected.js.map +1 -0
- package/dist/inspect.d.ts +31 -0
- package/dist/inspect.d.ts.map +1 -0
- package/dist/inspect.js +139 -0
- package/dist/inspect.js.map +1 -0
- package/dist/messages/index.d.ts +66 -0
- package/dist/messages/index.d.ts.map +1 -0
- package/dist/messages/index.js +123 -0
- package/dist/messages/index.js.map +1 -0
- package/dist/models/anthropic.d.ts +6 -0
- package/dist/models/anthropic.d.ts.map +1 -0
- package/dist/models/anthropic.js +317 -0
- package/dist/models/anthropic.js.map +1 -0
- package/dist/models/google.d.ts +3 -0
- package/dist/models/google.d.ts.map +1 -0
- package/dist/models/google.js +310 -0
- package/dist/models/google.js.map +1 -0
- package/dist/models/index.d.ts +6 -0
- package/dist/models/index.d.ts.map +1 -0
- package/dist/models/index.js +5 -0
- package/dist/models/index.js.map +1 -0
- package/dist/models/ollama.d.ts +7 -0
- package/dist/models/ollama.d.ts.map +1 -0
- package/dist/models/ollama.js +205 -0
- package/dist/models/ollama.js.map +1 -0
- package/dist/models/openai.d.ts +3 -0
- package/dist/models/openai.d.ts.map +1 -0
- package/dist/models/openai.js +331 -0
- package/dist/models/openai.js.map +1 -0
- package/dist/models/types.d.ts +77 -0
- package/dist/models/types.d.ts.map +1 -0
- package/dist/models/types.js +2 -0
- package/dist/models/types.js.map +1 -0
- package/dist/prebuilt/index.d.ts +5 -0
- package/dist/prebuilt/index.d.ts.map +1 -0
- package/dist/prebuilt/index.js +4 -0
- package/dist/prebuilt/index.js.map +1 -0
- package/dist/prebuilt/react-agent.d.ts +35 -0
- package/dist/prebuilt/react-agent.d.ts.map +1 -0
- package/dist/prebuilt/react-agent.js +55 -0
- package/dist/prebuilt/react-agent.js.map +1 -0
- package/dist/prebuilt/tool-node.d.ts +15 -0
- package/dist/prebuilt/tool-node.d.ts.map +1 -0
- package/dist/prebuilt/tool-node.js +61 -0
- package/dist/prebuilt/tool-node.js.map +1 -0
- package/dist/pregel.d.ts +48 -0
- package/dist/pregel.d.ts.map +1 -0
- package/dist/pregel.js +583 -0
- package/dist/pregel.js.map +1 -0
- package/dist/retry.d.ts +3 -0
- package/dist/retry.d.ts.map +1 -0
- package/dist/retry.js +40 -0
- package/dist/retry.js.map +1 -0
- package/dist/store/index.d.ts +90 -0
- package/dist/store/index.d.ts.map +1 -0
- package/dist/store/index.js +214 -0
- package/dist/store/index.js.map +1 -0
- package/dist/stream-events.d.ts +15 -0
- package/dist/stream-events.d.ts.map +1 -0
- package/dist/stream-events.js +53 -0
- package/dist/stream-events.js.map +1 -0
- package/dist/streaming.d.ts +56 -0
- package/dist/streaming.d.ts.map +1 -0
- package/dist/streaming.js +143 -0
- package/dist/streaming.js.map +1 -0
- package/dist/swarm/graph.d.ts +184 -0
- package/dist/swarm/graph.d.ts.map +1 -0
- package/dist/swarm/graph.js +534 -0
- package/dist/swarm/graph.js.map +1 -0
- package/dist/swarm/index.d.ts +11 -0
- package/dist/swarm/index.d.ts.map +1 -0
- package/dist/swarm/index.js +10 -0
- package/dist/swarm/index.js.map +1 -0
- package/dist/swarm/mailbox.d.ts +12 -0
- package/dist/swarm/mailbox.d.ts.map +1 -0
- package/dist/swarm/mailbox.js +36 -0
- package/dist/swarm/mailbox.js.map +1 -0
- package/dist/swarm/pool.d.ts +27 -0
- package/dist/swarm/pool.d.ts.map +1 -0
- package/dist/swarm/pool.js +87 -0
- package/dist/swarm/pool.js.map +1 -0
- package/dist/swarm/registry.d.ts +37 -0
- package/dist/swarm/registry.d.ts.map +1 -0
- package/dist/swarm/registry.js +115 -0
- package/dist/swarm/registry.js.map +1 -0
- package/dist/swarm/supervisor.d.ts +18 -0
- package/dist/swarm/supervisor.d.ts.map +1 -0
- package/dist/swarm/supervisor.js +117 -0
- package/dist/swarm/supervisor.js.map +1 -0
- package/dist/swarm/types.d.ts +111 -0
- package/dist/swarm/types.d.ts.map +1 -0
- package/dist/swarm/types.js +16 -0
- package/dist/swarm/types.js.map +1 -0
- package/dist/tools/define.d.ts +14 -0
- package/dist/tools/define.d.ts.map +1 -0
- package/dist/tools/define.js +39 -0
- package/dist/tools/define.js.map +1 -0
- package/dist/tools/index.d.ts +3 -0
- package/dist/tools/index.d.ts.map +1 -0
- package/dist/tools/index.js +2 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/tools/types.d.ts +23 -0
- package/dist/tools/types.d.ts.map +1 -0
- package/dist/tools/types.js +2 -0
- package/dist/tools/types.js.map +1 -0
- package/dist/types.d.ts +204 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +45 -0
- package/dist/types.js.map +1 -0
- package/package.json +108 -0
package/README.md
ADDED
|
@@ -0,0 +1,308 @@
|
|
|
1
|
+
# @oni.bot/core
|
|
2
|
+
|
|
3
|
+
> The graph execution engine for agent swarms — build single agents or orchestrate multi-agent systems in TypeScript.
|
|
4
|
+
> Zero dependencies. Full TypeScript generics. Pregel-based superstep engine. 7 swarm templates.
|
|
5
|
+
|
|
6
|
+
Part of the **ONI Platform** (Open Neural Infrastructure).
|
|
7
|
+
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
## What It Is
|
|
11
|
+
|
|
12
|
+
`@oni.bot/core` is a graph execution framework in TypeScript with production-ready swarm orchestration. Build single agents or multi-agent swarms with:
|
|
13
|
+
|
|
14
|
+
- **State management** — typed channels with pluggable reducers (`lastValue`, `appendList`, `mergeObject`, `ephemeralValue`)
|
|
15
|
+
- **Graph execution** — Pregel superstep model with parallel node execution, fan-out/fan-in, map-reduce
|
|
16
|
+
- **5 stream modes** — `values`, `updates`, `debug`, `messages` (token-level), and `custom` events
|
|
17
|
+
- **Checkpointing** — Memory, SQLite, PostgreSQL, or custom backends with time travel and fork
|
|
18
|
+
- **Human-in-the-loop** — compile-time interrupts + runtime `interrupt()` with resume, typed input, approval, selection
|
|
19
|
+
- **Messages** — smart reducer with deduplication, `RemoveMessage`, `UpdateMessage`, filtering, trimming
|
|
20
|
+
- **Cross-thread Store** — namespaced KV store with semantic search for agent long-term memory
|
|
21
|
+
- **Runtime context** — `getConfig()`, `getStore()`, `getStreamWriter()` via AsyncLocalStorage
|
|
22
|
+
- **Swarm orchestration** — 7 swarm templates: hierarchical, fan-out, pipeline, peer-network, map-reduce, debate, hierarchical-mesh
|
|
23
|
+
- **Functional API** — `task()`, `entrypoint()`, `pipe()`, `branch()` as alternatives to the builder pattern
|
|
24
|
+
- **Prebuilt agents** — `createReactAgent()` with bring-your-own LLM
|
|
25
|
+
- **Injected tools** — tools that auto-receive state + store from runtime context
|
|
26
|
+
- **Graph inspection** — topology descriptors, Mermaid diagrams, cycle detection
|
|
27
|
+
|
|
28
|
+
---
|
|
29
|
+
|
|
30
|
+
## Installation
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
npm install @oni.bot/core
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
**Optional peer dependencies:**
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
npm install better-sqlite3 # for SqliteCheckpointer
|
|
40
|
+
npm install pg # for PostgresCheckpointer
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
---
|
|
44
|
+
|
|
45
|
+
## Quick Start
|
|
46
|
+
|
|
47
|
+
### Minimal graph
|
|
48
|
+
|
|
49
|
+
```ts
|
|
50
|
+
import { StateGraph, START, END, lastValue, appendList } from "@oni.bot/core";
|
|
51
|
+
|
|
52
|
+
type MyState = { query: string; answer: string; log: string[] };
|
|
53
|
+
|
|
54
|
+
const graph = new StateGraph<MyState>({
|
|
55
|
+
channels: {
|
|
56
|
+
query: lastValue(() => ""),
|
|
57
|
+
answer: lastValue(() => ""),
|
|
58
|
+
log: appendList(() => []),
|
|
59
|
+
},
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
graph.addNode("agent", async (state) => {
|
|
63
|
+
return { answer: `Response to: ${state.query}`, log: ["agent ran"] };
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
graph.addEdge(START, "agent");
|
|
67
|
+
graph.addEdge("agent", END);
|
|
68
|
+
|
|
69
|
+
const app = graph.compile();
|
|
70
|
+
const result = await app.invoke({ query: "What is ONI?" });
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
### Streaming
|
|
74
|
+
|
|
75
|
+
```ts
|
|
76
|
+
for await (const event of app.stream({ query: "hello" }, { streamMode: "updates" })) {
|
|
77
|
+
console.log(event.node, event.data);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// Multiple modes simultaneously
|
|
81
|
+
for await (const evt of app.stream(input, { streamMode: ["values", "messages"] })) {
|
|
82
|
+
if (evt.mode === "messages") process.stdout.write(evt.data.chunk);
|
|
83
|
+
}
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
### Functional API
|
|
87
|
+
|
|
88
|
+
```ts
|
|
89
|
+
import { entrypoint, lastValue } from "@oni.bot/core";
|
|
90
|
+
|
|
91
|
+
const app = entrypoint(
|
|
92
|
+
{ channels: { query: lastValue(() => ""), answer: lastValue(() => "") } },
|
|
93
|
+
async (state) => ({ answer: await myLLM(state.query) })
|
|
94
|
+
);
|
|
95
|
+
|
|
96
|
+
const result = await app.invoke({ query: "hello" });
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
---
|
|
100
|
+
|
|
101
|
+
## Swarm Templates
|
|
102
|
+
|
|
103
|
+
Build multi-agent systems with pre-wired templates. Each template configures routing, coordination, and error handling automatically.
|
|
104
|
+
|
|
105
|
+
### Hierarchical (Supervisor -> Workers)
|
|
106
|
+
|
|
107
|
+
```ts
|
|
108
|
+
import { SwarmGraph } from "@oni.bot/core/swarm";
|
|
109
|
+
|
|
110
|
+
const swarm = SwarmGraph.hierarchical<MyState>({
|
|
111
|
+
supervisor: { model: myModel, strategy: "llm", maxRounds: 10 },
|
|
112
|
+
agents: [researcher, writer, critic],
|
|
113
|
+
onError: "fallback",
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
const app = swarm.compile();
|
|
117
|
+
const result = await app.invoke({ task: "Write a blog post about AI" });
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
### All 7 Templates
|
|
121
|
+
|
|
122
|
+
| Template | Use case | Pattern |
|
|
123
|
+
|---|---|---|
|
|
124
|
+
| `SwarmGraph.hierarchical()` | Supervisor routes to workers | Supervisor -> Agent -> Supervisor -> END |
|
|
125
|
+
| `SwarmGraph.fanOut()` | Parallel execution + aggregation | Send to all -> Collect -> Reduce |
|
|
126
|
+
| `SwarmGraph.pipeline()` | Sequential processing chain | A -> B -> C -> END |
|
|
127
|
+
| `SwarmGraph.peerNetwork()` | Agents hand off to each other | Dynamic peer-to-peer routing |
|
|
128
|
+
| `SwarmGraph.mapReduce()` | Distribute N items across pool | Split -> AgentPool -> Collect -> Reduce |
|
|
129
|
+
| `SwarmGraph.debate()` | Multi-round argumentation | Judge -> Debaters -> Judge -> consensus? |
|
|
130
|
+
| `SwarmGraph.hierarchicalMesh()` | Nested supervisor teams | Coordinator -> Team subgraphs -> Coordinator |
|
|
131
|
+
|
|
132
|
+
See `examples/swarm/` for complete runnable examples of each template.
|
|
133
|
+
|
|
134
|
+
### Single Agent — No Swarm Required
|
|
135
|
+
|
|
136
|
+
The swarm layer is purely additive. If you just need one agent:
|
|
137
|
+
|
|
138
|
+
```ts
|
|
139
|
+
import { defineAgent } from "@oni.bot/core/agents";
|
|
140
|
+
import { anthropic } from "@oni.bot/core/models";
|
|
141
|
+
|
|
142
|
+
const agent = defineAgent({
|
|
143
|
+
name: "assistant",
|
|
144
|
+
model: anthropic("claude-sonnet-4-6"),
|
|
145
|
+
tools: [webSearch],
|
|
146
|
+
systemPrompt: "You are a helpful assistant.",
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
const result = await agent.invoke({ messages: [{ role: "user", content: "Hello!" }] });
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
Entry points at every level: `ONIModel` -> `defineAgent()` -> `StateGraph` -> `SwarmGraph`.
|
|
153
|
+
|
|
154
|
+
---
|
|
155
|
+
|
|
156
|
+
## Features at a Glance
|
|
157
|
+
|
|
158
|
+
| Feature | Description | Example | Guide |
|
|
159
|
+
|---|---|---|---|
|
|
160
|
+
| Channels | Typed state with pluggable reducers | `examples/ephemeral-channels.ts` | [Section 2](docs/GUIDE.md#2-channels-deep-dive) |
|
|
161
|
+
| Command routing | State update + routing in one return | `examples/command-routing.ts` | [Section 3](docs/GUIDE.md#3-edges-and-routing) |
|
|
162
|
+
| Token streaming | `messages` mode + `getStreamWriter()` | `examples/messages-stream.ts` | [Section 4](docs/GUIDE.md#4-streaming) |
|
|
163
|
+
| Multi-stream | Multiple stream modes simultaneously | `examples/multi-stream.ts` | [Section 4](docs/GUIDE.md#4-streaming) |
|
|
164
|
+
| Custom events | Emit named events via StreamWriter | `examples/custom-stream.ts` | [Section 4](docs/GUIDE.md#4-streaming) |
|
|
165
|
+
| Messages | Smart reducer, helpers, RemoveMessage | `examples/messages-reducer.ts` | [Section 5](docs/GUIDE.md#5-messages) |
|
|
166
|
+
| Checkpointing | Memory, SQLite, PostgreSQL backends | `examples/time-travel.ts` | [Section 6](docs/GUIDE.md#6-checkpointing) |
|
|
167
|
+
| HITL interrupts | `interrupt()`, `getUserApproval()` | `examples/hitl/` | [Section 7](docs/GUIDE.md#7-human-in-the-loop) |
|
|
168
|
+
| Dynamic interrupts | Runtime breakpoint conditions | `examples/dynamic-interrupt.ts` | [Section 7](docs/GUIDE.md#7-human-in-the-loop) |
|
|
169
|
+
| Cross-thread Store | Namespaced KV with semantic search | `examples/store-memory.ts` | [Section 8](docs/GUIDE.md#8-cross-thread-store) |
|
|
170
|
+
| Subgraphs | Nested skeletons + Command.PARENT | `examples/subgraph.ts` | [Section 9](docs/GUIDE.md#9-subgraphs) |
|
|
171
|
+
| Parallel fan-out | Static + dynamic (Send API) | `examples/parallel-fanout.ts` | [Section 10](docs/GUIDE.md#10-parallel-execution) |
|
|
172
|
+
| Map-reduce | Send + fan-in barrier | `examples/map-reduce.ts` | [Section 10](docs/GUIDE.md#10-parallel-execution) |
|
|
173
|
+
| Runtime context | `getConfig()`, `getStore()`, etc. | `examples/runtime-context.ts` | [Section 11](docs/GUIDE.md#11-runtime-context) |
|
|
174
|
+
| Retry + cache | Per-node retry policy with backoff | `examples/retry-policy.ts` | [Section 12](docs/GUIDE.md#12-retry-and-cache) |
|
|
175
|
+
| Functional API | `task`, `entrypoint`, `pipe`, `branch` | `examples/functional-api.ts` | [Section 13](docs/GUIDE.md#13-functional-api) |
|
|
176
|
+
| ReAct agent | Prebuilt agent loop with tools | `examples/react-agent.ts` | [Section 14](docs/GUIDE.md#14-prebuilt-components) |
|
|
177
|
+
| Graph inspection | Topology, Mermaid, cycle detection | `examples/graph-inspection.ts` | [Section 16](docs/GUIDE.md#16-graph-inspection) |
|
|
178
|
+
| Time travel | `getHistory`, `getStateAt`, `forkFrom` | `examples/time-travel.ts` | [Section 17](docs/GUIDE.md#17-time-travel) |
|
|
179
|
+
| Swarm | 7 templates + Supervisor, Handoff, retry-fallback, coordination | `examples/swarm/` | [Section 18](docs/GUIDE.md#18-swarm-orchestration) |
|
|
180
|
+
|
|
181
|
+
---
|
|
182
|
+
|
|
183
|
+
## Core Concepts
|
|
184
|
+
|
|
185
|
+
### Channels
|
|
186
|
+
|
|
187
|
+
Every state field has a **channel** — a reducer + default factory that controls how concurrent updates merge.
|
|
188
|
+
|
|
189
|
+
```ts
|
|
190
|
+
import { lastValue, appendList, mergeObject, ephemeralValue } from "@oni.bot/core";
|
|
191
|
+
|
|
192
|
+
const channels = {
|
|
193
|
+
query: lastValue(() => ""), // last write wins
|
|
194
|
+
messages: appendList(() => []), // arrays concatenate
|
|
195
|
+
context: mergeObject(() => ({})), // shallow merge
|
|
196
|
+
scratch: ephemeralValue(() => null), // resets each superstep
|
|
197
|
+
};
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
### Nodes, edges, compile
|
|
201
|
+
|
|
202
|
+
```ts
|
|
203
|
+
graph.addNode("agent", async (state, config?) => {
|
|
204
|
+
return { answer: "partial update" }; // or Command, or void
|
|
205
|
+
});
|
|
206
|
+
|
|
207
|
+
graph.addEdge(START, "agent");
|
|
208
|
+
graph.addConditionalEdges("agent", (state) => state.done ? END : "tools");
|
|
209
|
+
|
|
210
|
+
const app = graph.compile({ checkpointer, store });
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
### Invoke / Stream / Batch
|
|
214
|
+
|
|
215
|
+
```ts
|
|
216
|
+
const result = await app.invoke(input, { threadId: "t1" });
|
|
217
|
+
const stream = app.stream(input, { streamMode: "updates" });
|
|
218
|
+
const results = await app.batch([input1, input2]);
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
For the full progressive tutorial, see **[docs/GUIDE.md](docs/GUIDE.md)**.
|
|
222
|
+
|
|
223
|
+
---
|
|
224
|
+
|
|
225
|
+
## Sub-module Exports
|
|
226
|
+
|
|
227
|
+
Tree-shakeable sub-module imports for bundle optimization:
|
|
228
|
+
|
|
229
|
+
| Import path | Contents |
|
|
230
|
+
|---|---|
|
|
231
|
+
| `@oni.bot/core` | Everything (116+ exports) |
|
|
232
|
+
| `@oni.bot/core/prebuilt` | `createReactAgent`, `createToolNode`, `toolsCondition`, types |
|
|
233
|
+
| `@oni.bot/core/swarm` | `SwarmGraph` (7 templates), `AgentRegistry`, `AgentPool`, `Handoff`, `Supervisor`, `Mailbox`, coordination |
|
|
234
|
+
| `@oni.bot/core/hitl` | `interrupt`, `getUserInput`, `getUserApproval`, `getUserSelection`, session store |
|
|
235
|
+
| `@oni.bot/core/store` | `BaseStore`, `InMemoryStore`, `NamespacedStore`, `AgentMemoryStore` |
|
|
236
|
+
| `@oni.bot/core/messages` | `messagesChannel`, `messagesReducer`, helpers, `RemoveMessage`, `UpdateMessage` |
|
|
237
|
+
| `@oni.bot/core/checkpointers` | `SqliteCheckpointer`, `PostgresCheckpointer`, `NamespacedCheckpointer` |
|
|
238
|
+
| `@oni.bot/core/functional` | `task`, `entrypoint`, `pipe`, `branch` |
|
|
239
|
+
| `@oni.bot/core/inspect` | `buildGraphDescriptor`, `toMermaidDetailed` |
|
|
240
|
+
| `@oni.bot/core/streaming` | `emitToken`, `TokenStreamWriter`, `StreamWriterImpl` |
|
|
241
|
+
| `@oni.bot/core/models` | `ONIModel`, `anthropic()`, `openai()` model factories |
|
|
242
|
+
| `@oni.bot/core/agents` | `defineAgent`, `agent()`, `AgentContext`, types |
|
|
243
|
+
| `@oni.bot/core/coordination` | `RequestReplyBroker`, `PubSub` coordination primitives |
|
|
244
|
+
| `@oni.bot/core/guardrails` | `InputGuardrail`, `OutputGuardrail`, guardrail types |
|
|
245
|
+
| `@oni.bot/core/tools` | `defineTool`, `createInjectedTool`, tool types |
|
|
246
|
+
|
|
247
|
+
---
|
|
248
|
+
|
|
249
|
+
## Architecture
|
|
250
|
+
|
|
251
|
+
```
|
|
252
|
+
@oni.bot/core v0.6.0
|
|
253
|
+
├── StateGraph / MessageGraph ← fluent graph builder
|
|
254
|
+
│ ├── addNode / addSubgraph ← nodes are async functions or compiled skeletons
|
|
255
|
+
│ ├── addEdge / addConditional ← static + dynamic routing
|
|
256
|
+
│ └── compile()
|
|
257
|
+
│ └── ONIPregelRunner ← superstep execution engine
|
|
258
|
+
│ ├── parallel node execution (Promise.all per superstep)
|
|
259
|
+
│ ├── channel reducers (state merging)
|
|
260
|
+
│ ├── edge resolution + Command routing
|
|
261
|
+
│ ├── Send API (dynamic fan-out)
|
|
262
|
+
│ ├── checkpointing (Memory / SQLite / Postgres / custom)
|
|
263
|
+
│ ├── interrupt handling (boundary + in-node)
|
|
264
|
+
│ ├── retry engine (exponential backoff)
|
|
265
|
+
│ ├── runtime context (AsyncLocalStorage)
|
|
266
|
+
│ └── stream writer (tokens + custom events + messages)
|
|
267
|
+
│
|
|
268
|
+
├── Messages ← smart reducer, dedup, RemoveMessage, UpdateMessage
|
|
269
|
+
├── HITL ← interrupt(), getUserInput, sessions, resume
|
|
270
|
+
├── Store ← BaseStore, InMemoryStore, NamespacedStore, AgentMemoryStore
|
|
271
|
+
├── Swarm ← SwarmGraph (7 templates), Supervisor, Handoff, AgentPool, coordination
|
|
272
|
+
│ ├── Templates ← hierarchical, fanOut, pipeline, peerNetwork, mapReduce, debate, hierarchicalMesh
|
|
273
|
+
│ ├── Coordination ← RequestReplyBroker, PubSub (lazy auto-wired)
|
|
274
|
+
│ └── Retry ← retry-then-fallback error recovery
|
|
275
|
+
├── Functional ← task, entrypoint, pipe, branch
|
|
276
|
+
├── Prebuilt ← createReactAgent, createToolNode, toolsCondition
|
|
277
|
+
├── Inspect ← graph descriptors, Mermaid, cycle detection
|
|
278
|
+
├── Injected Tools ← createInjectedTool (state + store auto-injected)
|
|
279
|
+
├── Stream Events ← streamEvents v2 protocol
|
|
280
|
+
└── Errors ← ONIError hierarchy, ONIInterrupt
|
|
281
|
+
```
|
|
282
|
+
|
|
283
|
+
---
|
|
284
|
+
|
|
285
|
+
## ONI Platform
|
|
286
|
+
|
|
287
|
+
`@oni.bot/core` is the foundation layer. Other ONI packages build on top:
|
|
288
|
+
|
|
289
|
+
| Package | Built on |
|
|
290
|
+
|---|---|
|
|
291
|
+
| `@oni/agentOS` | AgentOS ADE — multi-agent orchestration |
|
|
292
|
+
| `@oni/vectorforge` | VectorForge — knowledge base & SOP retrieval |
|
|
293
|
+
| `@oni/cic` | CIC Agent Assist — call center intelligence |
|
|
294
|
+
| `@oni/oats` | OATS — Five9 AI Agent Assist integration |
|
|
295
|
+
|
|
296
|
+
---
|
|
297
|
+
|
|
298
|
+
## Documentation
|
|
299
|
+
|
|
300
|
+
- **[Developer Guide](docs/GUIDE.md)** — Progressive tutorial from zero to advanced (19 sections)
|
|
301
|
+
- **[API Reference](docs/API.md)** — Complete reference for all 116+ public exports
|
|
302
|
+
- **[Examples](examples/)** — 30+ runnable example files covering every feature
|
|
303
|
+
|
|
304
|
+
---
|
|
305
|
+
|
|
306
|
+
## License
|
|
307
|
+
|
|
308
|
+
MIT — ONI Platform
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { ONIModel } from "../models/types.js";
|
|
2
|
+
import type { ToolDefinition } from "../tools/types.js";
|
|
3
|
+
import type { ONIConfig } from "../types.js";
|
|
4
|
+
import type { BaseStore } from "../store/index.js";
|
|
5
|
+
import type { StreamWriter } from "../context.js";
|
|
6
|
+
import type { AgentContext, SwarmMessageView } from "./types.js";
|
|
7
|
+
export interface BuildAgentContextOptions<S = Record<string, unknown>> {
|
|
8
|
+
model?: ONIModel;
|
|
9
|
+
tools?: ToolDefinition[];
|
|
10
|
+
agentName: string;
|
|
11
|
+
systemPrompt?: string;
|
|
12
|
+
config: ONIConfig;
|
|
13
|
+
store: BaseStore | null;
|
|
14
|
+
state: S;
|
|
15
|
+
streamWriter: StreamWriter | null;
|
|
16
|
+
remainingSteps: number;
|
|
17
|
+
onSend: (agent: string, payload: unknown) => void;
|
|
18
|
+
getInbox: () => SwarmMessageView[];
|
|
19
|
+
onRequest: (agent: string, payload: unknown) => Promise<unknown>;
|
|
20
|
+
onReply: (msg: SwarmMessageView, payload: unknown) => void;
|
|
21
|
+
onPublish: (topic: string, data: unknown) => void;
|
|
22
|
+
}
|
|
23
|
+
export declare function buildAgentContext<S = Record<string, unknown>>(opts: BuildAgentContextOptions<S>): AgentContext<S>;
|
|
24
|
+
//# sourceMappingURL=context.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../src/agents/context.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EACV,QAAQ,EAMT,MAAM,oBAAoB,CAAC;AAC5B,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACxD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAC7C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AACnD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAClD,OAAO,KAAK,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAMjE,MAAM,WAAW,wBAAwB,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IACnE,KAAK,CAAC,EAAE,QAAQ,CAAC;IACjB,KAAK,CAAC,EAAE,cAAc,EAAE,CAAC;IACzB,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,CAAC,EAAE,MAAM,CAAC;IAGtB,MAAM,EAAE,SAAS,CAAC;IAClB,KAAK,EAAE,SAAS,GAAG,IAAI,CAAC;IACxB,KAAK,EAAE,CAAC,CAAC;IACT,YAAY,EAAE,YAAY,GAAG,IAAI,CAAC;IAClC,cAAc,EAAE,MAAM,CAAC;IAGvB,MAAM,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,KAAK,IAAI,CAAC;IAClD,QAAQ,EAAE,MAAM,gBAAgB,EAAE,CAAC;IACnC,SAAS,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IACjE,OAAO,EAAE,CAAC,GAAG,EAAE,gBAAgB,EAAE,OAAO,EAAE,OAAO,KAAK,IAAI,CAAC;IAC3D,SAAS,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;CACnD;AAMD,wBAAgB,iBAAiB,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC3D,IAAI,EAAE,wBAAwB,CAAC,CAAC,CAAC,GAChC,YAAY,CAAC,CAAC,CAAC,CAkHjB"}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
// ============================================================
|
|
2
|
+
// @oni.bot/core — AgentContext Builder
|
|
3
|
+
// ============================================================
|
|
4
|
+
// Factory that assembles an AgentContext from runtime parts.
|
|
5
|
+
// Used by both defineAgent() and agent() factories.
|
|
6
|
+
// ============================================================
|
|
7
|
+
// ----------------------------------------------------------------
|
|
8
|
+
// buildAgentContext — assemble a full AgentContext
|
|
9
|
+
// ----------------------------------------------------------------
|
|
10
|
+
export function buildAgentContext(opts) {
|
|
11
|
+
const { model, tools = [], agentName, systemPrompt, config, store, state, streamWriter, remainingSteps, onSend, getInbox, onRequest, onReply, onPublish, } = opts;
|
|
12
|
+
// Convert ToolDefinition[] to LLMToolDef[] for model.chat/stream
|
|
13
|
+
const llmTools = tools.map((t) => ({
|
|
14
|
+
name: t.name,
|
|
15
|
+
description: t.description,
|
|
16
|
+
parameters: t.schema,
|
|
17
|
+
}));
|
|
18
|
+
// Build the ChatParams base (system prompt + tools)
|
|
19
|
+
function makeChatParams(messages) {
|
|
20
|
+
return {
|
|
21
|
+
messages,
|
|
22
|
+
tools: llmTools.length > 0 ? llmTools : undefined,
|
|
23
|
+
systemPrompt,
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
return {
|
|
27
|
+
// ---- LLM interaction ----
|
|
28
|
+
async chat(messages) {
|
|
29
|
+
if (!model) {
|
|
30
|
+
throw new Error(`Agent "${agentName}" has no model configured. Pass a model via options to use chat().`);
|
|
31
|
+
}
|
|
32
|
+
return model.chat(makeChatParams(messages));
|
|
33
|
+
},
|
|
34
|
+
async *stream(messages) {
|
|
35
|
+
if (!model) {
|
|
36
|
+
throw new Error(`Agent "${agentName}" has no model configured. Pass a model via options to use stream().`);
|
|
37
|
+
}
|
|
38
|
+
yield* model.stream(makeChatParams(messages));
|
|
39
|
+
},
|
|
40
|
+
async executeTools(calls) {
|
|
41
|
+
const toolMap = new Map(tools.map((t) => [t.name, t]));
|
|
42
|
+
return Promise.all(calls.map(async (call) => {
|
|
43
|
+
const tool = toolMap.get(call.name);
|
|
44
|
+
if (!tool) {
|
|
45
|
+
return {
|
|
46
|
+
toolCallId: call.id,
|
|
47
|
+
name: call.name,
|
|
48
|
+
result: `Tool "${call.name}" not found`,
|
|
49
|
+
isError: true,
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
try {
|
|
53
|
+
// Build a manual ToolContext — we don't rely on AsyncLocalStorage here
|
|
54
|
+
// because agent nodes run inside Pregel which provides context, and we
|
|
55
|
+
// want the tool to receive our explicit config/store/state.
|
|
56
|
+
const toolCtx = {
|
|
57
|
+
config,
|
|
58
|
+
store,
|
|
59
|
+
state: state,
|
|
60
|
+
emit: (event, data) => {
|
|
61
|
+
if (streamWriter)
|
|
62
|
+
streamWriter.emit(event, data);
|
|
63
|
+
},
|
|
64
|
+
};
|
|
65
|
+
const result = await tool.execute(call.args, toolCtx);
|
|
66
|
+
return { toolCallId: call.id, name: call.name, result };
|
|
67
|
+
}
|
|
68
|
+
catch (err) {
|
|
69
|
+
return {
|
|
70
|
+
toolCallId: call.id,
|
|
71
|
+
name: call.name,
|
|
72
|
+
result: String(err),
|
|
73
|
+
isError: true,
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
}));
|
|
77
|
+
},
|
|
78
|
+
// ---- Coordination ----
|
|
79
|
+
send: onSend,
|
|
80
|
+
inbox: getInbox,
|
|
81
|
+
request: onRequest,
|
|
82
|
+
reply: onReply,
|
|
83
|
+
publish: onPublish,
|
|
84
|
+
// ---- Runtime context ----
|
|
85
|
+
config,
|
|
86
|
+
store,
|
|
87
|
+
state,
|
|
88
|
+
streamWriter,
|
|
89
|
+
remainingSteps,
|
|
90
|
+
agentName,
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
//# sourceMappingURL=context.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context.js","sourceRoot":"","sources":["../../src/agents/context.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { DefineAgentOptions, AgentNode } from "./types.js";
|
|
2
|
+
/**
|
|
3
|
+
* defineAgent — create a declarative ReAct agent
|
|
4
|
+
*
|
|
5
|
+
* The returned AgentNode._nodeFn is suitable for use as a graph node.
|
|
6
|
+
* It expects the state to have an optional `messages` field (ONIModelMessage[])
|
|
7
|
+
* and returns `{ messages }` with the conversation appended.
|
|
8
|
+
*/
|
|
9
|
+
export declare function defineAgent<S extends Record<string, unknown> = Record<string, unknown>>(opts: DefineAgentOptions): AgentNode<S>;
|
|
10
|
+
//# sourceMappingURL=define-agent.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"define-agent.d.ts","sourceRoot":"","sources":["../../src/agents/define-agent.ts"],"names":[],"mappings":"AAiBA,OAAO,KAAK,EAAE,kBAAkB,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAEhE;;;;;;GAMG;AACH,wBAAgB,WAAW,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACrF,IAAI,EAAE,kBAAkB,GACvB,SAAS,CAAC,CAAC,CAAC,CAuHd"}
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
// ============================================================
|
|
2
|
+
// @oni.bot/core — defineAgent() — Declarative Agent Factory
|
|
3
|
+
// ============================================================
|
|
4
|
+
// Creates an AgentNode that runs a ReAct loop automatically:
|
|
5
|
+
// 1. Seed messages from state.messages
|
|
6
|
+
// 2. Loop up to maxSteps:
|
|
7
|
+
// a. Call model.chat with messages + systemPrompt + tools
|
|
8
|
+
// b. Track token usage, break if maxTokens exceeded
|
|
9
|
+
// c. Push assistant message
|
|
10
|
+
// d. If no toolCalls -> break (done)
|
|
11
|
+
// e. Execute tools with manual ToolContext
|
|
12
|
+
// f. Push tool result messages
|
|
13
|
+
// 3. Return { messages }
|
|
14
|
+
// ============================================================
|
|
15
|
+
/**
|
|
16
|
+
* defineAgent — create a declarative ReAct agent
|
|
17
|
+
*
|
|
18
|
+
* The returned AgentNode._nodeFn is suitable for use as a graph node.
|
|
19
|
+
* It expects the state to have an optional `messages` field (ONIModelMessage[])
|
|
20
|
+
* and returns `{ messages }` with the conversation appended.
|
|
21
|
+
*/
|
|
22
|
+
export function defineAgent(opts) {
|
|
23
|
+
const { name, description, model, tools = [], systemPrompt, maxSteps = 10, maxTokens, } = opts;
|
|
24
|
+
// Pre-compute LLMToolDef[] from ToolDefinition[]
|
|
25
|
+
const llmTools = tools.map((t) => ({
|
|
26
|
+
name: t.name,
|
|
27
|
+
description: t.description,
|
|
28
|
+
parameters: t.schema,
|
|
29
|
+
}));
|
|
30
|
+
const _nodeFn = async (state, config) => {
|
|
31
|
+
// 1. Seed messages from state
|
|
32
|
+
const existingMessages = (Array.isArray(state.messages)
|
|
33
|
+
? state.messages
|
|
34
|
+
: []);
|
|
35
|
+
const messages = [...existingMessages];
|
|
36
|
+
let totalTokens = 0;
|
|
37
|
+
// 2. ReAct loop
|
|
38
|
+
for (let step = 0; step < maxSteps; step++) {
|
|
39
|
+
// a. Call model.chat
|
|
40
|
+
const response = await model.chat({
|
|
41
|
+
messages,
|
|
42
|
+
tools: llmTools.length > 0 ? llmTools : undefined,
|
|
43
|
+
systemPrompt,
|
|
44
|
+
});
|
|
45
|
+
// b. Track token usage
|
|
46
|
+
totalTokens += response.usage.inputTokens + response.usage.outputTokens;
|
|
47
|
+
// c. Push assistant message
|
|
48
|
+
const assistantMsg = {
|
|
49
|
+
role: "assistant",
|
|
50
|
+
content: response.content,
|
|
51
|
+
};
|
|
52
|
+
if (response.toolCalls && response.toolCalls.length > 0) {
|
|
53
|
+
assistantMsg.toolCalls = response.toolCalls;
|
|
54
|
+
}
|
|
55
|
+
messages.push(assistantMsg);
|
|
56
|
+
// Check maxTokens budget
|
|
57
|
+
if (maxTokens !== undefined && totalTokens >= maxTokens) {
|
|
58
|
+
break;
|
|
59
|
+
}
|
|
60
|
+
// d. If no tool calls -> done
|
|
61
|
+
if (!response.toolCalls || response.toolCalls.length === 0) {
|
|
62
|
+
break;
|
|
63
|
+
}
|
|
64
|
+
// e. Execute tools with manual ToolContext
|
|
65
|
+
const toolMap = new Map(tools.map((t) => [t.name, t]));
|
|
66
|
+
const toolResults = await Promise.all(response.toolCalls.map(async (call) => {
|
|
67
|
+
const tool = toolMap.get(call.name);
|
|
68
|
+
if (!tool) {
|
|
69
|
+
return {
|
|
70
|
+
toolCallId: call.id,
|
|
71
|
+
name: call.name,
|
|
72
|
+
result: `Tool "${call.name}" not found`,
|
|
73
|
+
isError: true,
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
try {
|
|
77
|
+
const toolCtx = {
|
|
78
|
+
config: config ?? {},
|
|
79
|
+
store: null,
|
|
80
|
+
state: state,
|
|
81
|
+
emit: () => { },
|
|
82
|
+
};
|
|
83
|
+
const result = await tool.execute(call.args, toolCtx);
|
|
84
|
+
return { toolCallId: call.id, name: call.name, result };
|
|
85
|
+
}
|
|
86
|
+
catch (err) {
|
|
87
|
+
return {
|
|
88
|
+
toolCallId: call.id,
|
|
89
|
+
name: call.name,
|
|
90
|
+
result: String(err),
|
|
91
|
+
isError: true,
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
}));
|
|
95
|
+
// f. Push tool result messages
|
|
96
|
+
for (const tr of toolResults) {
|
|
97
|
+
messages.push({
|
|
98
|
+
role: "tool",
|
|
99
|
+
content: typeof tr.result === "string" ? tr.result : JSON.stringify(tr.result),
|
|
100
|
+
toolCallId: tr.toolCallId,
|
|
101
|
+
name: tr.name,
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
// 3. Return updated messages (only the new ones appended during this run)
|
|
106
|
+
const newMessages = messages.slice(existingMessages.length);
|
|
107
|
+
return { messages: newMessages };
|
|
108
|
+
};
|
|
109
|
+
return {
|
|
110
|
+
name,
|
|
111
|
+
description,
|
|
112
|
+
model,
|
|
113
|
+
tools,
|
|
114
|
+
systemPrompt,
|
|
115
|
+
maxSteps,
|
|
116
|
+
maxTokens,
|
|
117
|
+
_nodeFn,
|
|
118
|
+
_isAgent: true,
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
//# sourceMappingURL=define-agent.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"define-agent.js","sourceRoot":"","sources":["../../src/agents/define-agent.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { AgentNode, AgentContext, FunctionalAgentOptions } from "./types.js";
|
|
2
|
+
type AgentHandler<S> = (ctx: AgentContext<S>) => Promise<Partial<S>> | Partial<S>;
|
|
3
|
+
/**
|
|
4
|
+
* agent() — create a functional agent node
|
|
5
|
+
*
|
|
6
|
+
* Overloads:
|
|
7
|
+
* agent(name, handler)
|
|
8
|
+
* agent(name, opts, handler)
|
|
9
|
+
*/
|
|
10
|
+
export declare function agent<S extends Record<string, unknown> = Record<string, unknown>>(name: string, fnOrOpts: AgentHandler<S> | FunctionalAgentOptions, fn?: AgentHandler<S>): AgentNode<S>;
|
|
11
|
+
export {};
|
|
12
|
+
//# sourceMappingURL=functional-agent.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"functional-agent.d.ts","sourceRoot":"","sources":["../../src/agents/functional-agent.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAE,SAAS,EAAE,YAAY,EAAE,sBAAsB,EAAoB,MAAM,YAAY,CAAC;AAQpG,KAAK,YAAY,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,YAAY,CAAC,CAAC,CAAC,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;AAElF;;;;;;GAMG;AACH,wBAAgB,KAAK,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC/E,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,YAAY,CAAC,CAAC,CAAC,GAAG,sBAAsB,EAClD,EAAE,CAAC,EAAE,YAAY,CAAC,CAAC,CAAC,GACnB,SAAS,CAAC,CAAC,CAAC,CAkHd"}
|