agentenkit 0.1.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/LICENSE +21 -0
- package/README.md +226 -0
- package/dist/adapters/inline.d.ts +27 -0
- package/dist/adapters/inline.d.ts.map +1 -0
- package/dist/adapters/inline.js +41 -0
- package/dist/adapters/inline.js.map +1 -0
- package/dist/adapters/memory.d.ts +74 -0
- package/dist/adapters/memory.d.ts.map +1 -0
- package/dist/adapters/memory.js +194 -0
- package/dist/adapters/memory.js.map +1 -0
- package/dist/adapters/prisma.d.ts +176 -0
- package/dist/adapters/prisma.d.ts.map +1 -0
- package/dist/adapters/prisma.js +107 -0
- package/dist/adapters/prisma.js.map +1 -0
- package/dist/adapters/qstash.d.ts +36 -0
- package/dist/adapters/qstash.d.ts.map +1 -0
- package/dist/adapters/qstash.js +26 -0
- package/dist/adapters/qstash.js.map +1 -0
- package/dist/adapters/redis.d.ts +49 -0
- package/dist/adapters/redis.d.ts.map +1 -0
- package/dist/adapters/redis.js +60 -0
- package/dist/adapters/redis.js.map +1 -0
- package/dist/adapters/sqlite.d.ts +67 -0
- package/dist/adapters/sqlite.d.ts.map +1 -0
- package/dist/adapters/sqlite.js +199 -0
- package/dist/adapters/sqlite.js.map +1 -0
- package/dist/adapters/upstash.d.ts +48 -0
- package/dist/adapters/upstash.d.ts.map +1 -0
- package/dist/adapters/upstash.js +46 -0
- package/dist/adapters/upstash.js.map +1 -0
- package/dist/admin/default.d.ts +15 -0
- package/dist/admin/default.d.ts.map +1 -0
- package/dist/admin/default.js +22 -0
- package/dist/admin/default.js.map +1 -0
- package/dist/admin/memory.d.ts +29 -0
- package/dist/admin/memory.d.ts.map +1 -0
- package/dist/admin/memory.js +83 -0
- package/dist/admin/memory.js.map +1 -0
- package/dist/admin/postgres.d.ts +43 -0
- package/dist/admin/postgres.d.ts.map +1 -0
- package/dist/admin/postgres.js +201 -0
- package/dist/admin/postgres.js.map +1 -0
- package/dist/admin/sqlite.d.ts +35 -0
- package/dist/admin/sqlite.d.ts.map +1 -0
- package/dist/admin/sqlite.js +187 -0
- package/dist/admin/sqlite.js.map +1 -0
- package/dist/core/admin.d.ts +88 -0
- package/dist/core/admin.d.ts.map +1 -0
- package/dist/core/admin.js +147 -0
- package/dist/core/admin.js.map +1 -0
- package/dist/core/agent.d.ts +29 -0
- package/dist/core/agent.d.ts.map +1 -0
- package/dist/core/agent.js +41 -0
- package/dist/core/agent.js.map +1 -0
- package/dist/core/cache.d.ts +37 -0
- package/dist/core/cache.d.ts.map +1 -0
- package/dist/core/cache.js +68 -0
- package/dist/core/cache.js.map +1 -0
- package/dist/core/context.d.ts +13 -0
- package/dist/core/context.d.ts.map +1 -0
- package/dist/core/context.js +87 -0
- package/dist/core/context.js.map +1 -0
- package/dist/core/deleteThread.d.ts +14 -0
- package/dist/core/deleteThread.d.ts.map +1 -0
- package/dist/core/deleteThread.js +34 -0
- package/dist/core/deleteThread.js.map +1 -0
- package/dist/core/engine.d.ts +79 -0
- package/dist/core/engine.d.ts.map +1 -0
- package/dist/core/engine.js +489 -0
- package/dist/core/engine.js.map +1 -0
- package/dist/core/follow.d.ts +50 -0
- package/dist/core/follow.d.ts.map +1 -0
- package/dist/core/follow.js +153 -0
- package/dist/core/follow.js.map +1 -0
- package/dist/core/hitl.d.ts +98 -0
- package/dist/core/hitl.d.ts.map +1 -0
- package/dist/core/hitl.js +199 -0
- package/dist/core/hitl.js.map +1 -0
- package/dist/core/keys.d.ts +26 -0
- package/dist/core/keys.d.ts.map +1 -0
- package/dist/core/keys.js +32 -0
- package/dist/core/keys.js.map +1 -0
- package/dist/core/loop.d.ts +105 -0
- package/dist/core/loop.d.ts.map +1 -0
- package/dist/core/loop.js +234 -0
- package/dist/core/loop.js.map +1 -0
- package/dist/core/publish.d.ts +18 -0
- package/dist/core/publish.d.ts.map +1 -0
- package/dist/core/publish.js +34 -0
- package/dist/core/publish.js.map +1 -0
- package/dist/core/reclaim.d.ts +20 -0
- package/dist/core/reclaim.d.ts.map +1 -0
- package/dist/core/reclaim.js +56 -0
- package/dist/core/reclaim.js.map +1 -0
- package/dist/core/run.d.ts +8 -0
- package/dist/core/run.d.ts.map +1 -0
- package/dist/core/run.js +102 -0
- package/dist/core/run.js.map +1 -0
- package/dist/core/state.d.ts +50 -0
- package/dist/core/state.d.ts.map +1 -0
- package/dist/core/state.js +39 -0
- package/dist/core/state.js.map +1 -0
- package/dist/core/stop.d.ts +7 -0
- package/dist/core/stop.d.ts.map +1 -0
- package/dist/core/stop.js +15 -0
- package/dist/core/stop.js.map +1 -0
- package/dist/core/stream.d.ts +12 -0
- package/dist/core/stream.d.ts.map +1 -0
- package/dist/core/stream.js +21 -0
- package/dist/core/stream.js.map +1 -0
- package/dist/core/subagent.d.ts +77 -0
- package/dist/core/subagent.d.ts.map +1 -0
- package/dist/core/subagent.js +261 -0
- package/dist/core/subagent.js.map +1 -0
- package/dist/core/tools.d.ts +36 -0
- package/dist/core/tools.d.ts.map +1 -0
- package/dist/core/tools.js +22 -0
- package/dist/core/tools.js.map +1 -0
- package/dist/core/types.d.ts +286 -0
- package/dist/core/types.d.ts.map +1 -0
- package/dist/core/types.js +49 -0
- package/dist/core/types.js.map +1 -0
- package/dist/core/usage.d.ts +40 -0
- package/dist/core/usage.d.ts.map +1 -0
- package/dist/core/usage.js +43 -0
- package/dist/core/usage.js.map +1 -0
- package/dist/index.d.ts +25 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +23 -0
- package/dist/index.js.map +1 -0
- package/dist/ports/admin.d.ts +102 -0
- package/dist/ports/admin.d.ts.map +1 -0
- package/dist/ports/admin.js +2 -0
- package/dist/ports/admin.js.map +1 -0
- package/dist/ports/bus.d.ts +13 -0
- package/dist/ports/bus.d.ts.map +1 -0
- package/dist/ports/bus.js +2 -0
- package/dist/ports/bus.js.map +1 -0
- package/dist/ports/kv.d.ts +16 -0
- package/dist/ports/kv.d.ts.map +1 -0
- package/dist/ports/kv.js +2 -0
- package/dist/ports/kv.js.map +1 -0
- package/dist/ports/queue.d.ts +18 -0
- package/dist/ports/queue.d.ts.map +1 -0
- package/dist/ports/queue.js +2 -0
- package/dist/ports/queue.js.map +1 -0
- package/dist/ports/runtime.d.ts +260 -0
- package/dist/ports/runtime.d.ts.map +1 -0
- package/dist/ports/runtime.js +2 -0
- package/dist/ports/runtime.js.map +1 -0
- package/dist/ports/storage.d.ts +72 -0
- package/dist/ports/storage.d.ts.map +1 -0
- package/dist/ports/storage.js +2 -0
- package/dist/ports/storage.js.map +1 -0
- package/dist/runtime.d.ts +5 -0
- package/dist/runtime.d.ts.map +1 -0
- package/dist/runtime.js +177 -0
- package/dist/runtime.js.map +1 -0
- package/package.json +126 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Eadwin
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
# agentenkit
|
|
2
|
+
|
|
3
|
+
A durable runtime for AI agent runs, as a **library**.
|
|
4
|
+
|
|
5
|
+
It does not own your prompts, models, or tools — the [AI SDK](https://sdk.vercel.ai) does.
|
|
6
|
+
It owns the **lifecycle of a run**: that a run outlives the request that started it,
|
|
7
|
+
survives a worker dying mid-step, can be stopped, parked for a human, resumed exactly
|
|
8
|
+
where it stopped, nested, metered, and watched by several people at once.
|
|
9
|
+
|
|
10
|
+
**[Full documentation](https://eadwincode.github.io/agentic-kit/)** — getting started, concepts, the HTTP contract,
|
|
11
|
+
ports, production settings and troubleshooting.
|
|
12
|
+
|
|
13
|
+
The `§` numbers below refer to a behavioural specification that no longer lives
|
|
14
|
+
in the repository; the [documentation](../../docs/README.md) and the test suite
|
|
15
|
+
now describe that behaviour.
|
|
16
|
+
|
|
17
|
+
## Running locally, with nothing to stand up
|
|
18
|
+
|
|
19
|
+
There is no `createDevRuntime`. Assembling the platform is four adapters and one wire,
|
|
20
|
+
and seeing them is the point — swapping any of them for the durable equivalent later is
|
|
21
|
+
then obvious rather than magic.
|
|
22
|
+
|
|
23
|
+
```ts
|
|
24
|
+
import { Database } from 'bun:sqlite'; // or node:sqlite — see openSqlite
|
|
25
|
+
import { setupAgentCore } from 'agentenkit';
|
|
26
|
+
import { SqliteStorage } from 'agentenkit/adapters/sqlite';
|
|
27
|
+
import { InlineQueue } from 'agentenkit/adapters/inline';
|
|
28
|
+
import { MemoryBus, MemoryKv } from 'agentenkit/adapters/memory';
|
|
29
|
+
import { SqliteAdminStore } from 'agentenkit/admin/sqlite';
|
|
30
|
+
import { openai } from '@ai-sdk/openai';
|
|
31
|
+
|
|
32
|
+
// One file holds both: your tables, and — prefixed `agentic_` — the platform's
|
|
33
|
+
// own operational history (§2.9).
|
|
34
|
+
const db = new Database('agentic-kit.sqlite');
|
|
35
|
+
const queue = new InlineQueue();
|
|
36
|
+
|
|
37
|
+
export const runtime = await setupAgentCore({
|
|
38
|
+
storage: new SqliteStorage(db), // ← later: PrismaStorage, or your own
|
|
39
|
+
admin: new SqliteAdminStore(db), // ← later: PostgresAdminStore
|
|
40
|
+
bus: new MemoryBus(), // ← later: RedisBus
|
|
41
|
+
kv: new MemoryKv(), // ← later: RedisKv
|
|
42
|
+
queue, // ← later: QStashQueue
|
|
43
|
+
resolveModel: (name) => ({ instance: () => openai(name), contextWindow: 128_000 }),
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
// The queue and the worker each need the other, so the queue is attached once
|
|
47
|
+
// the core exists. Nothing dispatches until this line runs.
|
|
48
|
+
queue.bind((job) => runtime.worker.handleJob(job));
|
|
49
|
+
|
|
50
|
+
export const chat = runtime.createStreamTextAgent({ name: 'chat', model: 'gpt-4o' });
|
|
51
|
+
await chat.run({ prompt: 'hi' }); // persisted, dispatched, and running
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
`InlineQueue` is what makes this a real platform rather than a demo: it dispatches on a
|
|
55
|
+
later tick, so `enqueue` returns immediately and a run still outlives the request that
|
|
56
|
+
started it — and it honours `delaySeconds`, so parked approvals expire and blocked jobs
|
|
57
|
+
redrive exactly as they do against a durable queue. What it does not do is survive a
|
|
58
|
+
restart.
|
|
59
|
+
|
|
60
|
+
`openSqlite(file)` picks a driver at runtime — `bun:sqlite` where it exists,
|
|
61
|
+
`node:sqlite` otherwise — if you would rather not import one yourself. Pass `':memory:'`
|
|
62
|
+
for a database that dies with the process.
|
|
63
|
+
|
|
64
|
+
## Install
|
|
65
|
+
|
|
66
|
+
```bash
|
|
67
|
+
bun add agentenkit ai zod
|
|
68
|
+
# optional reference adapters:
|
|
69
|
+
bun add @prisma/client @upstash/redis @upstash/qstash redis
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
## Going to production
|
|
73
|
+
|
|
74
|
+
Same shape, durable pieces. Each line above swaps for one here.
|
|
75
|
+
|
|
76
|
+
```ts
|
|
77
|
+
import { Client } from '@upstash/qstash';
|
|
78
|
+
import { createClient } from 'redis';
|
|
79
|
+
import { PrismaClient } from '@prisma/client';
|
|
80
|
+
import { setupAgentCore } from 'agentenkit';
|
|
81
|
+
import { PrismaStorage } from 'agentenkit/adapters/prisma';
|
|
82
|
+
import { RedisBus, RedisKv } from 'agentenkit/adapters/redis';
|
|
83
|
+
import { QStashQueue } from 'agentenkit/adapters/qstash';
|
|
84
|
+
|
|
85
|
+
const redis = createClient({ url: process.env.REDIS_URL });
|
|
86
|
+
await redis.connect();
|
|
87
|
+
|
|
88
|
+
export const runtime = await setupAgentCore({
|
|
89
|
+
storage: new PrismaStorage(new PrismaClient()), // ← or Mongo / Dynamo / your DB
|
|
90
|
+
bus: new RedisBus(redis), // ← Ably / Kafka / Postgres LISTEN…
|
|
91
|
+
queue: new QStashQueue(
|
|
92
|
+
new Client({ token: process.env.QSTASH_TOKEN! }),
|
|
93
|
+
{ url: 'https://app.example.com/api/queue/agent-run' },
|
|
94
|
+
),
|
|
95
|
+
kv: new RedisKv(redis),
|
|
96
|
+
// `admin` omitted on purpose: with AGENTIC_KIT_ADMIN_DATABASE_URL set, the
|
|
97
|
+
// platform opens Postgres for its own history (§2.9). Pass one to override.
|
|
98
|
+
resolveModel: (name) => ({ instance: () => models[name], contextWindow: 128_000 }),
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
export const chat = runtime.createStreamTextAgent({ name: 'chat', model: 'gpt-4o' });
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
### Operations
|
|
105
|
+
|
|
106
|
+
Runs belong to an agent handle; reads belong to the runtime.
|
|
107
|
+
|
|
108
|
+
```ts
|
|
109
|
+
await chat.run({ prompt: 'hi', state: { orgId } }); // persist + enqueue → 202 (§5.1)
|
|
110
|
+
await chat.stop(threadId); // one write: state → CANCELLED (§2.1)
|
|
111
|
+
await runtime.hitl.respond({ threadId, toolCallId, approved, payload, state }); // §2.5
|
|
112
|
+
await runtime.getThreadSnapshot(threadId, state); // hydrate a client (§2.2)
|
|
113
|
+
const { stream, headers } = runtime.events.sse(threadId, { since, signal }); // SSE, any framework
|
|
114
|
+
for await (const e of runtime.events.follow(threadId, { signal })) { … } // or iterate
|
|
115
|
+
const missed = await runtime.events.since(threadId, lastSeq); // raw replay
|
|
116
|
+
const unsub = await runtime.events.subscribe(threadId, handler); // raw tail
|
|
117
|
+
await runtime.worker.handleJob(job); // queue consumer (§2.8)
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
The Next.js routes in [`examples/nextjs-app`](../../examples/nextjs-app) show the HTTP
|
|
121
|
+
wiring — each handler is a few lines over the runtime.
|
|
122
|
+
|
|
123
|
+
## Run state (§2.10)
|
|
124
|
+
|
|
125
|
+
Whatever you attach to a run reaches **every** storage call it makes, every tool, and
|
|
126
|
+
every nested run — including in a worker that picks the job up hours later, in another
|
|
127
|
+
process, after an approval. The platform never reads it.
|
|
128
|
+
|
|
129
|
+
```ts
|
|
130
|
+
await chat.run({ prompt: 'hi', state: { orgId: 'acme', userId: 'u1' } });
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
```ts
|
|
134
|
+
// Your Storage sees it on every method, as a trailing argument.
|
|
135
|
+
async list(threadId: string, opts, ctx) {
|
|
136
|
+
return this.db.message.findMany({ where: { threadId, orgId: ctx.state.orgId } });
|
|
137
|
+
}
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
Type your own fields by augmenting the interface — no `<TState>` rippling through
|
|
141
|
+
`Storage`, `AgentCore`, tools and subagents before it reaches the one place it is read:
|
|
142
|
+
|
|
143
|
+
```ts
|
|
144
|
+
declare module 'agentenkit' {
|
|
145
|
+
interface AgentRunState { orgId: string; userId: string }
|
|
146
|
+
}
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
## Ports (§3.2) — your data
|
|
150
|
+
|
|
151
|
+
| Port | Role | Reference adapter |
|
|
152
|
+
| :--- | :--- | :--- |
|
|
153
|
+
| `Storage` | threads / messages / events / usage — incl. atomic `claimState` | `PrismaStorage`, `SqliteStorage` |
|
|
154
|
+
| `EventBus` | live fan-out + HITL death notices (at-most-once) | `RedisBus`, `UpstashBus` |
|
|
155
|
+
| `Queue` | durable run dispatch (at-least-once) | `QStashQueue`, `InlineQueue` (dev) |
|
|
156
|
+
| `Kv` | hot state cache, HITL handoff keys, seq/attempt counters | `RedisKv`, `UpstashKv` |
|
|
157
|
+
|
|
158
|
+
Implement any of them for your own stack — `core/` imports nothing else. The
|
|
159
|
+
[`Memory*` adapters](./src/adapters/memory.ts) are a complete implementation used by the
|
|
160
|
+
test suite and double as a template.
|
|
161
|
+
|
|
162
|
+
## The admin store (§2.9) — not yours
|
|
163
|
+
|
|
164
|
+
Run records, step timings and a thread index are the **platform's** data, in the
|
|
165
|
+
platform's own tables. You do not implement `AdminStore`; you read it back:
|
|
166
|
+
|
|
167
|
+
```ts
|
|
168
|
+
await runtime.admin.overview(); // threads and runs by state, plus what's in flight
|
|
169
|
+
await runtime.admin.listRuns({ state: ['FAILED'], since });
|
|
170
|
+
await runtime.admin.stats({ since }); // p50/p95 duration and queue wait, tokens, failures
|
|
171
|
+
await runtime.admin.getRun(runId); // one run: steps, nested runs, timeline
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
Configure nothing and it is SQLite on disk (`AGENTIC_KIT_ADMIN_DB` moves the file).
|
|
175
|
+
Set `AGENTIC_KIT_ADMIN_DATABASE_URL` and it is Postgres — point it at its own database
|
|
176
|
+
or the one you already have; the `agentic_` table prefix keeps them apart. `pg` is an
|
|
177
|
+
optional peer dependency, needed only on that path.
|
|
178
|
+
|
|
179
|
+
```bash
|
|
180
|
+
AGENTIC_KIT_ADMIN_DATABASE_URL=postgresql://user:pass@host/db
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
The store is opened when `setupAgentCore` runs, which is why that call is `await`ed: a
|
|
184
|
+
store that cannot be opened is a startup error rather than a surprise on the first run.
|
|
185
|
+
Quietly falling back to memory would lose every record, and a dashboard showing nothing
|
|
186
|
+
looks exactly like no traffic.
|
|
187
|
+
|
|
188
|
+
Keeping it separate is what lets a dashboard answer "what is running right now" without
|
|
189
|
+
reading your database at all.
|
|
190
|
+
|
|
191
|
+
## Adapter invariants (§3.4)
|
|
192
|
+
|
|
193
|
+
1. `events.append` receives `seq` from `kv.incr('agent:seq:{threadId}')` — monotonic per thread.
|
|
194
|
+
2. `threads.claimState` must be atomic (one conditional UPDATE) — exactly one caller wins.
|
|
195
|
+
3. `queue.enqueue` is at-least-once and the engine is idempotent. An adapter that cannot
|
|
196
|
+
honour `delaySeconds` may deliver immediately, but must never throw for it — a HITL
|
|
197
|
+
expiry is scheduled from inside a parked tool call.
|
|
198
|
+
4. `bus` is at-most-once; the §2.5 watchdog pattern compensates.
|
|
199
|
+
5. Durable thread state lives in `storage.threads`; the kv copy is a hot cache. Writes go to both.
|
|
200
|
+
6. Every run carries an id (§2.1). A worker whose id is no longer current has been
|
|
201
|
+
replaced and must not write state on the live run's behalf.
|
|
202
|
+
|
|
203
|
+
## Behaviour map
|
|
204
|
+
|
|
205
|
+
| Spec | Where in the package |
|
|
206
|
+
| :--- | :--- |
|
|
207
|
+
| §2.1 Detached execution, stop, run identity | `core/run.ts`, `core/stop.ts`, `core/engine.ts`, `core/keys.ts` |
|
|
208
|
+
| §2.2 Multi-user stream | `ports/bus.ts` + `runtime.events` |
|
|
209
|
+
| §2.5 HITL park, respond, expiry, reclaim | `core/hitl.ts`, `core/reclaim.ts` |
|
|
210
|
+
| §2.6 Context ceiling & compaction | `core/context.ts` |
|
|
211
|
+
| §2.7 Subagents as nested runs | `core/subagent.ts`, `core/loop.ts` |
|
|
212
|
+
| §2.8 Queue dispatch + redrive/FAIL policy | `ports/queue.ts`, `core/engine.ts` |
|
|
213
|
+
| §2.9 Operational history | `ports/admin.ts`, `admin/*`, `core/admin.ts` |
|
|
214
|
+
| §2.10 Run state | `core/state.ts` |
|
|
215
|
+
| §5 Reference HTTP integration | `examples/nextjs-app` |
|
|
216
|
+
|
|
217
|
+
## Development
|
|
218
|
+
|
|
219
|
+
Requires [Bun](https://bun.sh) ≥ 1.1.
|
|
220
|
+
|
|
221
|
+
```bash
|
|
222
|
+
bun install
|
|
223
|
+
bun test # runs test/*.test.ts directly on Bun (no build step)
|
|
224
|
+
bun run typecheck # tsc --noEmit over src + tests
|
|
225
|
+
bun run build # tsc emit → dist/ (published artifact)
|
|
226
|
+
```
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { RunJob } from '../core/types.js';
|
|
2
|
+
import type { EnqueueOptions, Queue } from '../ports/queue.js';
|
|
3
|
+
/** An in-process queue that actually dispatches (§2.8).
|
|
4
|
+
*
|
|
5
|
+
* `MemoryQueue` only collects jobs, which is right for tests that drive the
|
|
6
|
+
* worker by hand but useless for running the platform. This one hands each
|
|
7
|
+
* job to the worker on a later tick, so `enqueue` still returns immediately
|
|
8
|
+
* and a run keeps outliving the request that started it — the property the
|
|
9
|
+
* whole design rests on.
|
|
10
|
+
*
|
|
11
|
+
* It honours `delaySeconds`, so the HITL expiry (§2.5) and the lock-conflict
|
|
12
|
+
* redrive (§2.8) work in development exactly as they do against a real queue.
|
|
13
|
+
*
|
|
14
|
+
* What it is NOT: durable. A process restart loses whatever was in flight,
|
|
15
|
+
* which is precisely what the durable adapters exist to fix. Development
|
|
16
|
+
* only. */
|
|
17
|
+
export declare class InlineQueue implements Queue {
|
|
18
|
+
private handler?;
|
|
19
|
+
private readonly pending;
|
|
20
|
+
/** Wired by setupAgentCore once the worker exists — the queue and the worker
|
|
21
|
+
* each need the other, so one of them has to be attached afterwards. */
|
|
22
|
+
bind(handler: (job: RunJob) => Promise<unknown>): void;
|
|
23
|
+
enqueue(job: RunJob, opts?: EnqueueOptions): Promise<void>;
|
|
24
|
+
/** Drop everything still scheduled — for tests and clean shutdown. */
|
|
25
|
+
clear(): void;
|
|
26
|
+
}
|
|
27
|
+
//# sourceMappingURL=inline.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"inline.d.ts","sourceRoot":"","sources":["../../src/adapters/inline.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,KAAK,EAAE,cAAc,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;AAE/D;;;;;;;;;;;;;YAaY;AACZ,qBAAa,WAAY,YAAW,KAAK;IACvC,OAAO,CAAC,OAAO,CAAC,CAAoC;IACpD,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA4C;IAEpE;6EACyE;IACzE,IAAI,CAAC,OAAO,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,GAAG,IAAI;IAIhD,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC;IAYhE,sEAAsE;IACtE,KAAK,IAAI,IAAI;CAId"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/** An in-process queue that actually dispatches (§2.8).
|
|
2
|
+
*
|
|
3
|
+
* `MemoryQueue` only collects jobs, which is right for tests that drive the
|
|
4
|
+
* worker by hand but useless for running the platform. This one hands each
|
|
5
|
+
* job to the worker on a later tick, so `enqueue` still returns immediately
|
|
6
|
+
* and a run keeps outliving the request that started it — the property the
|
|
7
|
+
* whole design rests on.
|
|
8
|
+
*
|
|
9
|
+
* It honours `delaySeconds`, so the HITL expiry (§2.5) and the lock-conflict
|
|
10
|
+
* redrive (§2.8) work in development exactly as they do against a real queue.
|
|
11
|
+
*
|
|
12
|
+
* What it is NOT: durable. A process restart loses whatever was in flight,
|
|
13
|
+
* which is precisely what the durable adapters exist to fix. Development
|
|
14
|
+
* only. */
|
|
15
|
+
export class InlineQueue {
|
|
16
|
+
handler;
|
|
17
|
+
pending = new Set();
|
|
18
|
+
/** Wired by setupAgentCore once the worker exists — the queue and the worker
|
|
19
|
+
* each need the other, so one of them has to be attached afterwards. */
|
|
20
|
+
bind(handler) {
|
|
21
|
+
this.handler = handler;
|
|
22
|
+
}
|
|
23
|
+
async enqueue(job, opts) {
|
|
24
|
+
const timer = setTimeout(() => {
|
|
25
|
+
this.pending.delete(timer);
|
|
26
|
+
// Detached on purpose: a queue consumer's failure is the worker's
|
|
27
|
+
// business (§2.8 redrive), never the enqueuer's.
|
|
28
|
+
void this.handler?.(job)?.catch(() => undefined);
|
|
29
|
+
}, (opts?.delaySeconds ?? 0) * 1000);
|
|
30
|
+
// Never hold a process open just because an expiry is scheduled.
|
|
31
|
+
timer.unref?.();
|
|
32
|
+
this.pending.add(timer);
|
|
33
|
+
}
|
|
34
|
+
/** Drop everything still scheduled — for tests and clean shutdown. */
|
|
35
|
+
clear() {
|
|
36
|
+
for (const t of this.pending)
|
|
37
|
+
clearTimeout(t);
|
|
38
|
+
this.pending.clear();
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
//# sourceMappingURL=inline.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"inline.js","sourceRoot":"","sources":["../../src/adapters/inline.ts"],"names":[],"mappings":"AAGA;;;;;;;;;;;;;YAaY;AACZ,MAAM,OAAO,WAAW;IACd,OAAO,CAAqC;IACnC,OAAO,GAAG,IAAI,GAAG,EAAiC,CAAC;IAEpE;6EACyE;IACzE,IAAI,CAAC,OAA0C;QAC7C,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;IACzB,CAAC;IAED,KAAK,CAAC,OAAO,CAAC,GAAW,EAAE,IAAqB;QAC9C,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE;YAC5B,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YAC3B,kEAAkE;YAClE,iDAAiD;YACjD,KAAK,IAAI,CAAC,OAAO,EAAE,CAAC,GAAG,CAAC,EAAE,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;QACnD,CAAC,EAAE,CAAC,IAAI,EAAE,YAAY,IAAI,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;QACrC,iEAAiE;QAChE,KAA2C,CAAC,KAAK,EAAE,EAAE,CAAC;QACvD,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;IAC1B,CAAC;IAED,sEAAsE;IACtE,KAAK;QACH,KAAK,MAAM,CAAC,IAAI,IAAI,CAAC,OAAO;YAAE,YAAY,CAAC,CAAC,CAAC,CAAC;QAC9C,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;IACvB,CAAC;CACF"}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import type { AgentEvent, ExecutionState, MessageDTO, NewMessage, NewUsage, RunJob, ThreadDTO, UsageTotals } from '../core/types.js';
|
|
2
|
+
import type { Storage } from '../ports/storage.js';
|
|
3
|
+
import type { EventBus } from '../ports/bus.js';
|
|
4
|
+
import type { EnqueueOptions, Queue } from '../ports/queue.js';
|
|
5
|
+
import type { Kv } from '../ports/kv.js';
|
|
6
|
+
/** In-memory Kv — tests and local prototyping. Expiry is enforced lazily on
|
|
7
|
+
* read; incr is synchronous internally, so concurrent callers can never
|
|
8
|
+
* collide on the same counter (§3.4). */
|
|
9
|
+
export declare class MemoryKv implements Kv {
|
|
10
|
+
private m;
|
|
11
|
+
get(key: string): Promise<string | null>;
|
|
12
|
+
set(key: string, value: string, opts?: {
|
|
13
|
+
exSeconds?: number;
|
|
14
|
+
onlyIfNotExists?: boolean;
|
|
15
|
+
}): Promise<boolean>;
|
|
16
|
+
del(key: string): Promise<void>;
|
|
17
|
+
incr(key: string): Promise<number>;
|
|
18
|
+
}
|
|
19
|
+
/** Synchronous in-memory bus. Publishes are delivered to subscribers in order. */
|
|
20
|
+
export declare class MemoryBus implements EventBus {
|
|
21
|
+
private subs;
|
|
22
|
+
readonly published: AgentEvent[];
|
|
23
|
+
publish(threadId: string, event: AgentEvent): Promise<void>;
|
|
24
|
+
subscribe(threadId: string, handler: (e: AgentEvent) => void): Promise<() => void>;
|
|
25
|
+
/** Live subscriptions on a thread — lets a test prove a stream cleaned up
|
|
26
|
+
* after itself rather than leaking one per reconnect. */
|
|
27
|
+
subscribers(threadId: string): number;
|
|
28
|
+
}
|
|
29
|
+
/** In-memory queue with a drain() helper: tests process jobs exactly like the
|
|
30
|
+
* worker would (`await queue.drain(job => runtime.engine.executeWithPolicy(job))`). */
|
|
31
|
+
export declare class MemoryQueue implements Queue {
|
|
32
|
+
readonly items: RunJob[];
|
|
33
|
+
/** Delivery delay requested per enqueue, index-aligned with `items`. */
|
|
34
|
+
readonly delays: Array<number | undefined>;
|
|
35
|
+
enqueue(job: RunJob, opts?: EnqueueOptions): Promise<void>;
|
|
36
|
+
drain(handler: (job: RunJob) => Promise<void>): Promise<number>;
|
|
37
|
+
}
|
|
38
|
+
/** Full in-memory Storage — tests, demos, and a template for custom adapters. */
|
|
39
|
+
export declare class MemoryStorage implements Storage {
|
|
40
|
+
threads: {
|
|
41
|
+
store: Map<string, ThreadDTO>;
|
|
42
|
+
get(t: string): Promise<ThreadDTO | null>;
|
|
43
|
+
create(init?: {
|
|
44
|
+
model?: string;
|
|
45
|
+
}): Promise<ThreadDTO>;
|
|
46
|
+
list(): Promise<ThreadDTO[]>;
|
|
47
|
+
setState(t: string, state: ExecutionState): Promise<void>;
|
|
48
|
+
delete: (t: string) => Promise<void>;
|
|
49
|
+
claimState(t: string, from: ExecutionState, to: ExecutionState): Promise<boolean>;
|
|
50
|
+
};
|
|
51
|
+
messages: {
|
|
52
|
+
store: Map<string, MessageDTO[]>;
|
|
53
|
+
append(t: string, m: NewMessage): Promise<MessageDTO>;
|
|
54
|
+
list(t: string, opts?: {
|
|
55
|
+
agentId?: string | null;
|
|
56
|
+
}): Promise<MessageDTO[]>;
|
|
57
|
+
deleteFrom(t: string, messageId: string): Promise<number>;
|
|
58
|
+
};
|
|
59
|
+
events: {
|
|
60
|
+
store: Map<string, AgentEvent[]>;
|
|
61
|
+
append(t: string, e: AgentEvent): Promise<void>;
|
|
62
|
+
listSince(t: string, sinceSeq: number): Promise<AgentEvent[]>;
|
|
63
|
+
latest(t: string, type: string): Promise<AgentEvent | null>;
|
|
64
|
+
listByType(t: string, type: string): Promise<AgentEvent[]>;
|
|
65
|
+
};
|
|
66
|
+
usage: {
|
|
67
|
+
recorded: (NewUsage & {
|
|
68
|
+
threadId: string;
|
|
69
|
+
})[];
|
|
70
|
+
record(t: string, u: NewUsage): Promise<void>;
|
|
71
|
+
total(t: string): Promise<UsageTotals>;
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
//# sourceMappingURL=memory.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"memory.d.ts","sourceRoot":"","sources":["../../src/adapters/memory.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,cAAc,EAAE,UAAU,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AACrI,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,KAAK,EAAE,cAAc,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;AAC/D,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,gBAAgB,CAAC;AAKzC;;0CAE0C;AAC1C,qBAAa,QAAS,YAAW,EAAE;IACjC,OAAO,CAAC,CAAC,CAA+B;IAClC,GAAG,CAAC,GAAG,EAAE,MAAM;IAMf,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE;QAAE,SAAS,CAAC,EAAE,MAAM,CAAC;QAAC,eAAe,CAAC,EAAE,OAAO,CAAA;KAAE;IAWxF,GAAG,CAAC,GAAG,EAAE,MAAM;IACf,IAAI,CAAC,GAAG,EAAE,MAAM;CAOvB;AAED,kFAAkF;AAClF,qBAAa,SAAU,YAAW,QAAQ;IACxC,OAAO,CAAC,IAAI,CAAmD;IAC/D,QAAQ,CAAC,SAAS,EAAE,UAAU,EAAE,CAAM;IAEhC,OAAO,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,UAAU;IAI3C,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,CAAC,EAAE,UAAU,KAAK,IAAI;IAMlE;8DAC0D;IAC1D,WAAW,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM;CAGtC;AAED;wFACwF;AACxF,qBAAa,WAAY,YAAW,KAAK;IACvC,QAAQ,CAAC,KAAK,EAAE,MAAM,EAAE,CAAM;IAC9B,wEAAwE;IACxE,QAAQ,CAAC,MAAM,EAAE,KAAK,CAAC,MAAM,GAAG,SAAS,CAAC,CAAM;IAC1C,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,cAAc;IAI1C,KAAK,CAAC,OAAO,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC;CAUtE;AAED,iFAAiF;AACjF,qBAAa,aAAc,YAAW,OAAO;IAC3C,OAAO;;eAEQ,MAAM;sBACC;YAAE,KAAK,CAAC,EAAE,MAAM,CAAA;SAAE;;oBASpB,MAAM,SAAS,cAAc;oBAQ7B,MAAM;sBAOJ,MAAM,QAAQ,cAAc,MAAM,cAAc;MAMpE;IAEF,QAAQ;;kBAEU,MAAM,KAAK,UAAU;gBAUvB,MAAM,SAAS;YAAE,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;SAAE;sBAKpC,MAAM,aAAa,MAAM;MAM7C;IAEF,MAAM;;kBAEY,MAAM,KAAK,UAAU;qBAKlB,MAAM,YAAY,MAAM;kBAI3B,MAAM,QAAQ,MAAM;sBAKhB,MAAM,QAAQ,MAAM;MAIxC;IAEF,KAAK;kBACa,CAAC,QAAQ,GAAG;YAAE,QAAQ,EAAE,MAAM,CAAA;SAAE,CAAC,EAAE;kBACnC,MAAM,KAAK,QAAQ;iBACpB,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC;MAa5C;CAIH"}
|
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
const id = () => Math.random().toString(36).slice(2, 12);
|
|
2
|
+
/** In-memory Kv — tests and local prototyping. Expiry is enforced lazily on
|
|
3
|
+
* read; incr is synchronous internally, so concurrent callers can never
|
|
4
|
+
* collide on the same counter (§3.4). */
|
|
5
|
+
export class MemoryKv {
|
|
6
|
+
m = new Map();
|
|
7
|
+
async get(key) {
|
|
8
|
+
const e = this.m.get(key);
|
|
9
|
+
if (!e)
|
|
10
|
+
return null;
|
|
11
|
+
if (e.expiresAt && e.expiresAt < Date.now()) {
|
|
12
|
+
this.m.delete(key);
|
|
13
|
+
return null;
|
|
14
|
+
}
|
|
15
|
+
return e.value;
|
|
16
|
+
}
|
|
17
|
+
async set(key, value, opts) {
|
|
18
|
+
if (opts?.onlyIfNotExists) {
|
|
19
|
+
const existing = this.m.get(key);
|
|
20
|
+
if (existing && !(existing.expiresAt && existing.expiresAt < Date.now()))
|
|
21
|
+
return false;
|
|
22
|
+
}
|
|
23
|
+
this.m.set(key, {
|
|
24
|
+
value,
|
|
25
|
+
expiresAt: opts?.exSeconds ? Date.now() + opts.exSeconds * 1000 : undefined,
|
|
26
|
+
});
|
|
27
|
+
return true;
|
|
28
|
+
}
|
|
29
|
+
async del(key) { this.m.delete(key); }
|
|
30
|
+
async incr(key) {
|
|
31
|
+
// No awaits between read and write — atomic within the event loop
|
|
32
|
+
const e = this.m.get(key);
|
|
33
|
+
const n = Number(e?.value ?? 0) + 1;
|
|
34
|
+
this.m.set(key, { value: String(n), expiresAt: e?.expiresAt });
|
|
35
|
+
return n;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
/** Synchronous in-memory bus. Publishes are delivered to subscribers in order. */
|
|
39
|
+
export class MemoryBus {
|
|
40
|
+
subs = new Map();
|
|
41
|
+
published = [];
|
|
42
|
+
async publish(threadId, event) {
|
|
43
|
+
this.published.push(event);
|
|
44
|
+
for (const h of this.subs.get(threadId) ?? [])
|
|
45
|
+
h(event);
|
|
46
|
+
}
|
|
47
|
+
async subscribe(threadId, handler) {
|
|
48
|
+
let set = this.subs.get(threadId);
|
|
49
|
+
if (!set) {
|
|
50
|
+
set = new Set();
|
|
51
|
+
this.subs.set(threadId, set);
|
|
52
|
+
}
|
|
53
|
+
set.add(handler);
|
|
54
|
+
return () => { set.delete(handler); };
|
|
55
|
+
}
|
|
56
|
+
/** Live subscriptions on a thread — lets a test prove a stream cleaned up
|
|
57
|
+
* after itself rather than leaking one per reconnect. */
|
|
58
|
+
subscribers(threadId) {
|
|
59
|
+
return this.subs.get(threadId)?.size ?? 0;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
/** In-memory queue with a drain() helper: tests process jobs exactly like the
|
|
63
|
+
* worker would (`await queue.drain(job => runtime.engine.executeWithPolicy(job))`). */
|
|
64
|
+
export class MemoryQueue {
|
|
65
|
+
items = [];
|
|
66
|
+
/** Delivery delay requested per enqueue, index-aligned with `items`. */
|
|
67
|
+
delays = [];
|
|
68
|
+
async enqueue(job, opts) {
|
|
69
|
+
this.items.push(job);
|
|
70
|
+
this.delays.push(opts?.delaySeconds);
|
|
71
|
+
}
|
|
72
|
+
async drain(handler) {
|
|
73
|
+
let n = 0;
|
|
74
|
+
while (this.items.length) {
|
|
75
|
+
const job = this.items.shift();
|
|
76
|
+
this.delays.shift();
|
|
77
|
+
await handler(job);
|
|
78
|
+
n++;
|
|
79
|
+
}
|
|
80
|
+
return n;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
/** Full in-memory Storage — tests, demos, and a template for custom adapters. */
|
|
84
|
+
export class MemoryStorage {
|
|
85
|
+
threads = {
|
|
86
|
+
store: new Map(),
|
|
87
|
+
async get(t) { return this.store.get(t) ?? null; },
|
|
88
|
+
async create(init) {
|
|
89
|
+
const now = new Date();
|
|
90
|
+
const t = { id: id(), state: 'IDLE', model: init?.model ?? 'gpt-4o', createdAt: now, updatedAt: now };
|
|
91
|
+
this.store.set(t.id, t);
|
|
92
|
+
return t;
|
|
93
|
+
},
|
|
94
|
+
async list() {
|
|
95
|
+
return [...this.store.values()].sort((a, b) => b.updatedAt.getTime() - a.updatedAt.getTime());
|
|
96
|
+
},
|
|
97
|
+
async setState(t, state) {
|
|
98
|
+
const thread = this.store.get(t);
|
|
99
|
+
if (!thread)
|
|
100
|
+
throw new Error(`Unknown thread ${t}`);
|
|
101
|
+
thread.state = state;
|
|
102
|
+
thread.updatedAt = new Date();
|
|
103
|
+
},
|
|
104
|
+
// Arrow-bound to the MemoryStorage instance: the cascade reaches the
|
|
105
|
+
// sibling sections (messages / events / usage) — §3.2 contract. Run
|
|
106
|
+
// records are not here; they are the platform's own (§2.9).
|
|
107
|
+
delete: async (t) => {
|
|
108
|
+
if (!this.threads.store.has(t))
|
|
109
|
+
throw new Error(`Unknown thread ${t}`);
|
|
110
|
+
this.threads.store.delete(t);
|
|
111
|
+
this.messages.store.delete(t);
|
|
112
|
+
this.events.store.delete(t);
|
|
113
|
+
this.usage.recorded = this.usage.recorded.filter((u) => u.threadId !== t);
|
|
114
|
+
},
|
|
115
|
+
async claimState(t, from, to) {
|
|
116
|
+
const thread = this.store.get(t);
|
|
117
|
+
if (!thread || thread.state !== from)
|
|
118
|
+
return false;
|
|
119
|
+
thread.state = to;
|
|
120
|
+
thread.updatedAt = new Date();
|
|
121
|
+
return true;
|
|
122
|
+
},
|
|
123
|
+
};
|
|
124
|
+
messages = {
|
|
125
|
+
store: new Map(),
|
|
126
|
+
async append(t, m) {
|
|
127
|
+
const dto = {
|
|
128
|
+
id: id(), threadId: t, agentId: m.agentId ?? null,
|
|
129
|
+
role: m.role, content: m.content, createdAt: new Date(),
|
|
130
|
+
};
|
|
131
|
+
let list = this.store.get(t);
|
|
132
|
+
if (!list) {
|
|
133
|
+
list = [];
|
|
134
|
+
this.store.set(t, list);
|
|
135
|
+
}
|
|
136
|
+
list.push(dto);
|
|
137
|
+
return dto;
|
|
138
|
+
},
|
|
139
|
+
async list(t, opts) {
|
|
140
|
+
const rows = this.store.get(t) ?? [];
|
|
141
|
+
if (!opts || !('agentId' in opts))
|
|
142
|
+
return [...rows];
|
|
143
|
+
return rows.filter((m) => (m.agentId ?? null) === (opts.agentId ?? null));
|
|
144
|
+
},
|
|
145
|
+
async deleteFrom(t, messageId) {
|
|
146
|
+
const rows = this.store.get(t) ?? [];
|
|
147
|
+
const from = rows.findIndex((m) => m.id === messageId);
|
|
148
|
+
if (from === -1)
|
|
149
|
+
return 0;
|
|
150
|
+
return rows.splice(from).length;
|
|
151
|
+
},
|
|
152
|
+
};
|
|
153
|
+
events = {
|
|
154
|
+
store: new Map(),
|
|
155
|
+
async append(t, e) {
|
|
156
|
+
let list = this.store.get(t);
|
|
157
|
+
if (!list) {
|
|
158
|
+
list = [];
|
|
159
|
+
this.store.set(t, list);
|
|
160
|
+
}
|
|
161
|
+
list.push(e);
|
|
162
|
+
},
|
|
163
|
+
async listSince(t, sinceSeq) {
|
|
164
|
+
return (this.store.get(t) ?? []).filter((e) => e.seq > sinceSeq)
|
|
165
|
+
.sort((a, b) => a.seq - b.seq);
|
|
166
|
+
},
|
|
167
|
+
async latest(t, type) {
|
|
168
|
+
const list = this.store.get(t) ?? [];
|
|
169
|
+
for (let i = list.length - 1; i >= 0; i--)
|
|
170
|
+
if (list[i].type === type)
|
|
171
|
+
return list[i];
|
|
172
|
+
return null;
|
|
173
|
+
},
|
|
174
|
+
async listByType(t, type) {
|
|
175
|
+
return (this.store.get(t) ?? []).filter((e) => e.type === type)
|
|
176
|
+
.sort((a, b) => a.seq - b.seq);
|
|
177
|
+
},
|
|
178
|
+
};
|
|
179
|
+
usage = {
|
|
180
|
+
recorded: [],
|
|
181
|
+
async record(t, u) { this.recorded.push({ threadId: t, ...u }); },
|
|
182
|
+
async total(t) {
|
|
183
|
+
return this.recorded
|
|
184
|
+
.filter((u) => u.threadId === t)
|
|
185
|
+
.reduce((sum, u) => ({
|
|
186
|
+
inputTokens: sum.inputTokens + u.inputTokens,
|
|
187
|
+
cachedInputTokens: sum.cachedInputTokens + u.cachedInputTokens,
|
|
188
|
+
outputTokens: sum.outputTokens + u.outputTokens,
|
|
189
|
+
totalTokens: sum.totalTokens + u.totalTokens,
|
|
190
|
+
}), { inputTokens: 0, cachedInputTokens: 0, outputTokens: 0, totalTokens: 0 });
|
|
191
|
+
},
|
|
192
|
+
};
|
|
193
|
+
}
|
|
194
|
+
//# sourceMappingURL=memory.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"memory.js","sourceRoot":"","sources":["../../src/adapters/memory.ts"],"names":[],"mappings":"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"}
|