@devxiyang/agent-kernel 0.0.2 → 0.0.5
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 +409 -268
- package/dist/core/agent/agent.d.ts +4 -4
- package/dist/core/agent/agent.d.ts.map +1 -1
- package/dist/core/agent/agent.js +13 -6
- package/dist/core/agent/agent.js.map +1 -1
- package/dist/core/kernel/index.d.ts +2 -0
- package/dist/core/kernel/index.d.ts.map +1 -1
- package/dist/core/kernel/index.js +1 -0
- package/dist/core/kernel/index.js.map +1 -1
- package/dist/core/kernel/kernel-cache.d.ts +37 -0
- package/dist/core/kernel/kernel-cache.d.ts.map +1 -0
- package/dist/core/kernel/kernel-cache.js +47 -0
- package/dist/core/kernel/kernel-cache.js.map +1 -0
- package/package.json +3 -2
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 devxiyang
|
|
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
CHANGED
|
@@ -1,60 +1,45 @@
|
|
|
1
1
|
# agent-kernel
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
-
|
|
6
|
-
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
- `StreamFn
|
|
13
|
-
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
```
|
|
25
|
-
|
|
26
|
-
## Feature Map
|
|
27
|
-
|
|
28
|
-
- Provider-agnostic runtime via `StreamFn`
|
|
29
|
-
- Real-time events (`text_delta`, `tool_call`, `tool_result`, `step_done`, etc.)
|
|
30
|
-
- Tool execution loop with automatic parameter validation (TypeBox + `Value.Parse`)
|
|
31
|
-
- Validation errors returned as `tool_result` so the LLM can self-correct
|
|
32
|
-
- Persistent sessions via `createAgent({ session: { dir, sessionId } })`
|
|
33
|
-
- Conversation compaction via `kernel.compact(fromId, toId, summaryText)`
|
|
34
|
-
- Strong TypeScript types — `execute` input is inferred from the TypeBox schema
|
|
35
|
-
- **Parallel tool execution** — run all tool calls in a single turn concurrently
|
|
36
|
-
- **Tool timeout** — per-call deadline; timed-out tools return an error result automatically
|
|
37
|
-
- **Auto-compaction hook** — `onContextFull` fires when the context window is full
|
|
38
|
-
- **Stream error retry** — automatic retry with fixed delay for transient LLM errors
|
|
39
|
-
- **Session metadata** — attach a `title` (or any custom field) to a session; read it back from `listSessions`
|
|
3
|
+
[](https://www.npmjs.com/package/@devxiyang/agent-kernel)
|
|
4
|
+
[](https://www.npmjs.com/package/@devxiyang/agent-kernel)
|
|
5
|
+
[](./LICENSE)
|
|
6
|
+
[](https://www.typescriptlang.org/)
|
|
7
|
+
|
|
8
|
+
A provider-agnostic agent runtime for TypeScript. Bring your own LLM — `agent-kernel` handles the loop, tool execution, event streaming, and conversation persistence.
|
|
9
|
+
|
|
10
|
+
## Features
|
|
11
|
+
|
|
12
|
+
- **Provider-agnostic** — implement one `StreamFn` adapter for any LLM backend (OpenAI, Anthropic, Vercel AI SDK, etc.)
|
|
13
|
+
- **Real-time event stream** — `text_delta`, `tool_call`, `tool_result`, `step_done`, and more
|
|
14
|
+
- **Typed tool execution** — TypeBox schemas drive runtime validation, coercion, and LLM schema generation
|
|
15
|
+
- **Parallel tool execution** — run all tool calls in a turn concurrently
|
|
16
|
+
- **Tool timeout** — per-call deadline; timed-out tools return an error result the LLM can handle
|
|
17
|
+
- **Persistent sessions** — optional file-backed conversation history, survives restarts
|
|
18
|
+
- **Conversation compaction** — replace old entries with a summary to stay within context limits
|
|
19
|
+
- **Auto-compaction hook** — `onContextFull` fires when the token budget is reached
|
|
20
|
+
- **Steering & follow-up** — inject messages mid-run without re-prompting
|
|
21
|
+
- **Stream error retry** — automatic retry with configurable delay for transient LLM errors
|
|
22
|
+
- **Session metadata** — attach titles and custom fields to sessions; query with `listSessions`
|
|
23
|
+
- **Kernel cache** — LRU + TTL in-memory cache for session kernels
|
|
40
24
|
|
|
41
25
|
## Install
|
|
42
26
|
|
|
43
27
|
```bash
|
|
44
28
|
npm install @devxiyang/agent-kernel
|
|
45
|
-
npm install @sinclair/typebox
|
|
46
|
-
npm install openai # if using OpenAI SDK adapter
|
|
47
|
-
npm install ai @ai-sdk/openai # if using Vercel AI SDK adapter
|
|
48
29
|
```
|
|
49
30
|
|
|
50
|
-
|
|
31
|
+
`@sinclair/typebox` is a required peer dependency for tool parameter schemas:
|
|
51
32
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
- `@devxiyang/agent-kernel/event-stream` — `EventStream`
|
|
33
|
+
```bash
|
|
34
|
+
npm install @sinclair/typebox
|
|
35
|
+
```
|
|
56
36
|
|
|
57
|
-
|
|
37
|
+
Optional — install the LLM SDK of your choice:
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
npm install openai # OpenAI SDK
|
|
41
|
+
npm install ai @ai-sdk/openai # Vercel AI SDK
|
|
42
|
+
```
|
|
58
43
|
|
|
59
44
|
## Quick Start
|
|
60
45
|
|
|
@@ -62,7 +47,7 @@ npm install ai @ai-sdk/openai # if using Vercel AI SDK adapter
|
|
|
62
47
|
import { Type } from '@sinclair/typebox'
|
|
63
48
|
import { createAgent, type StreamFn, type AgentTool } from '@devxiyang/agent-kernel'
|
|
64
49
|
|
|
65
|
-
//
|
|
50
|
+
// 1. Implement StreamFn for your LLM provider (see adapter examples below)
|
|
66
51
|
const stream: StreamFn = async (messages, _tools, onEvent) => {
|
|
67
52
|
const last = messages.filter((m) => m.role === 'user').at(-1)
|
|
68
53
|
const reply = `Echo: ${typeof last?.content === 'string' ? last.content : '[multi-part]'}`
|
|
@@ -74,34 +59,357 @@ const stream: StreamFn = async (messages, _tools, onEvent) => {
|
|
|
74
59
|
}
|
|
75
60
|
}
|
|
76
61
|
|
|
77
|
-
|
|
78
|
-
|
|
62
|
+
// 2. Define tools
|
|
79
63
|
const tools: AgentTool[] = [
|
|
80
64
|
{
|
|
81
65
|
name: 'get_time',
|
|
82
66
|
description: 'Returns the current UTC time as an ISO string.',
|
|
83
|
-
parameters:
|
|
67
|
+
parameters: Type.Object({}),
|
|
84
68
|
execute: async () => ({ content: new Date().toISOString(), isError: false }),
|
|
85
69
|
},
|
|
86
70
|
]
|
|
87
71
|
|
|
72
|
+
// 3. Create agent and subscribe to events
|
|
88
73
|
const agent = createAgent({ stream, tools, maxSteps: 8 })
|
|
89
74
|
|
|
90
75
|
agent.subscribe((event) => {
|
|
91
76
|
if (event.type === 'text_delta') process.stdout.write(event.delta)
|
|
92
77
|
})
|
|
93
78
|
|
|
79
|
+
// 4. Send a message and wait for completion
|
|
94
80
|
agent.prompt({ type: 'user', payload: { parts: [{ type: 'text', text: 'What time is it?' }] } })
|
|
95
81
|
await agent.waitForIdle()
|
|
96
82
|
```
|
|
97
83
|
|
|
84
|
+
## Module Index
|
|
85
|
+
|
|
86
|
+
| Import path | Contents |
|
|
87
|
+
|---|---|
|
|
88
|
+
| `@devxiyang/agent-kernel` | `Agent`, `createAgent`, `runLoop`, `wrapTool`, `EventStream`, all types |
|
|
89
|
+
| `@devxiyang/agent-kernel/agent` | Agent module only |
|
|
90
|
+
| `@devxiyang/agent-kernel/kernel` | `createKernel`, `KernelCache`, `listSessions`, `deleteSession`, `updateSessionMeta`, kernel types |
|
|
91
|
+
| `@devxiyang/agent-kernel/event-stream` | `EventStream` |
|
|
92
|
+
|
|
93
|
+
## Core Concepts
|
|
94
|
+
|
|
95
|
+
| Concept | Description |
|
|
96
|
+
|---|---|
|
|
97
|
+
| `Agent` | Stateful runtime — orchestrates the model loop, tool execution, and event emission |
|
|
98
|
+
| `Kernel` | Conversation store (in-memory or file-backed) with branching and compaction |
|
|
99
|
+
| `KernelCache` | LRU + TTL cache for reusing kernel instances across requests |
|
|
100
|
+
| `StreamFn` | Provider adapter — one function that calls your LLM and emits stream events |
|
|
101
|
+
| `AgentTool` | Executable unit with a TypeBox schema for validation and provider schema generation |
|
|
102
|
+
| `EventStream` | Async-iterable push stream primitive used internally by the loop |
|
|
103
|
+
|
|
104
|
+
---
|
|
105
|
+
|
|
106
|
+
## Agent API
|
|
107
|
+
|
|
108
|
+
### Sending messages
|
|
109
|
+
|
|
110
|
+
```ts
|
|
111
|
+
// Start a new run (throws if agent is already running)
|
|
112
|
+
agent.prompt(entry)
|
|
113
|
+
|
|
114
|
+
// Send a message — the agent decides whether to start a new run or queue it
|
|
115
|
+
// Safe to call whether the agent is idle or running
|
|
116
|
+
agent.followUp(entry)
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
Use `followUp` when you don't want to manage the agent's running state yourself. It starts a new run when idle and queues the message for the next run otherwise. `prompt` is a lower-level method that gives you explicit control: it throws if the agent is already running, forcing you to decide between `followUp` and `steer`.
|
|
120
|
+
|
|
121
|
+
### Steering (mid-run interruption)
|
|
122
|
+
|
|
123
|
+
`steer` injects a message that the loop picks up *between tool calls* in the current run. Unlike `followUp`, it interrupts the current turn rather than waiting for the run to finish.
|
|
124
|
+
|
|
125
|
+
```ts
|
|
126
|
+
// Safe to call while the agent is running
|
|
127
|
+
agent.steer({ type: 'user', payload: { parts: [{ type: 'text', text: 'Actually, focus only on security.' }] } })
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
When a steering message arrives, the loop skips any remaining tool calls in the current batch (writing `"Skipped: user interrupted."` results to keep the conversation consistent) and immediately processes the steering message.
|
|
131
|
+
|
|
132
|
+
**`steer` vs `followUp`**
|
|
133
|
+
|
|
134
|
+
| | `followUp` | `steer` |
|
|
135
|
+
|---|---|---|
|
|
136
|
+
| When processed | After the current run ends | Between tool calls in the current run |
|
|
137
|
+
| Effect | Continues the outer loop | Interrupts the current tool batch |
|
|
138
|
+
| Use case | Next user turn | Real-time redirection mid-task |
|
|
139
|
+
|
|
140
|
+
### Waiting for completion
|
|
141
|
+
|
|
142
|
+
```ts
|
|
143
|
+
await agent.waitForIdle()
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
Resolves when the agent is truly idle — no running loop and no queued follow-up messages. Useful in request-response contexts (e.g., IPC handlers) where the caller needs to wait for all events to be dispatched before returning.
|
|
147
|
+
|
|
148
|
+
```ts
|
|
149
|
+
// IPC handler pattern
|
|
150
|
+
async function handleMessage(entry: AgentEntry) {
|
|
151
|
+
agent.followUp(entry)
|
|
152
|
+
await agent.waitForIdle()
|
|
153
|
+
// all events have been dispatched to subscribers
|
|
154
|
+
}
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
If a subscriber calls `followUp` inside an `agent_end` handler, `waitForIdle` will continue waiting for that follow-up run to finish as well.
|
|
158
|
+
|
|
159
|
+
### Recovery
|
|
160
|
+
|
|
161
|
+
```ts
|
|
162
|
+
// Resume after an error or abort, or drain queued follow-up/steering messages
|
|
163
|
+
// Throws if already running or nothing to continue from
|
|
164
|
+
agent.continue()
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
### Aborting and resetting
|
|
168
|
+
|
|
169
|
+
```ts
|
|
170
|
+
agent.abort() // cancel the current run (no-op if idle)
|
|
171
|
+
agent.reset() // clear all queues and transient state (throws if running)
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
### Subscribing to events
|
|
175
|
+
|
|
176
|
+
```ts
|
|
177
|
+
const unsubscribe = agent.subscribe((event) => {
|
|
178
|
+
switch (event.type) {
|
|
179
|
+
case 'agent_start': /* run began */ break
|
|
180
|
+
case 'turn_start': /* LLM call starting */ break
|
|
181
|
+
case 'text_delta': /* streaming text chunk */ break
|
|
182
|
+
case 'reasoning_delta': /* streaming reasoning chunk */ break
|
|
183
|
+
case 'tool_call': /* tool invocation */ break
|
|
184
|
+
case 'tool_update': /* partial tool progress */ break
|
|
185
|
+
case 'tool_result': /* tool finished */ break
|
|
186
|
+
case 'message_end': /* assistant message committed */ break
|
|
187
|
+
case 'step_done': /* step usage stats */ break
|
|
188
|
+
case 'turn_end': /* turn finished with tool results */ break
|
|
189
|
+
case 'agent_end': /* run finished (check event.error) */ break
|
|
190
|
+
}
|
|
191
|
+
})
|
|
192
|
+
|
|
193
|
+
// Stop receiving events
|
|
194
|
+
unsubscribe()
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
### Inspecting state
|
|
198
|
+
|
|
199
|
+
```ts
|
|
200
|
+
const { isRunning, streamEntry, pendingToolCalls, error } = agent.state
|
|
201
|
+
|
|
202
|
+
// Access the underlying kernel
|
|
203
|
+
const entries = agent.kernel.read()
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
---
|
|
207
|
+
|
|
208
|
+
## Kernel
|
|
209
|
+
|
|
210
|
+
The `Kernel` is the conversation store. It holds the full message history as an in-memory linked tree and optionally persists it to `kernel.jsonl`.
|
|
211
|
+
|
|
212
|
+
### Creating a kernel
|
|
213
|
+
|
|
214
|
+
```ts
|
|
215
|
+
import { createKernel } from '@devxiyang/agent-kernel/kernel'
|
|
216
|
+
|
|
217
|
+
// In-memory only (useful for testing)
|
|
218
|
+
const kernel = createKernel()
|
|
219
|
+
|
|
220
|
+
// File-backed — loads from disk if session exists
|
|
221
|
+
const kernel = createKernel({
|
|
222
|
+
dir: './.agent-sessions',
|
|
223
|
+
sessionId: 'my-session',
|
|
224
|
+
meta: { title: 'Code review assistant' },
|
|
225
|
+
})
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
### Reading conversation history
|
|
229
|
+
|
|
230
|
+
```ts
|
|
231
|
+
// All entries on the current branch (root → leaf)
|
|
232
|
+
const entries = kernel.read()
|
|
233
|
+
|
|
234
|
+
// Most recent entry (or null if empty)
|
|
235
|
+
const last = kernel.peek()
|
|
236
|
+
|
|
237
|
+
// Build provider-agnostic messages for passing to StreamFn
|
|
238
|
+
const messages = kernel.buildMessages()
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
### Appending entries
|
|
242
|
+
|
|
243
|
+
```ts
|
|
244
|
+
kernel.append({ type: 'user', payload: { parts: [{ type: 'text', text: 'Hello' }] } })
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
The `Agent` calls `append` automatically during the loop. Call it directly only when working with a bare kernel outside of an agent.
|
|
248
|
+
|
|
249
|
+
### Context budget
|
|
250
|
+
|
|
251
|
+
```ts
|
|
252
|
+
// Set a token limit; onContextFull fires when contextSize >= limit
|
|
253
|
+
kernel.budget.set(80_000)
|
|
254
|
+
|
|
255
|
+
console.log(kernel.contextSize) // input tokens from the last assistant entry
|
|
256
|
+
console.log(kernel.budget.limit) // current limit
|
|
257
|
+
console.log(kernel.budget.used) // same as contextSize
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
### Compaction
|
|
261
|
+
|
|
262
|
+
Replace a range of entries with a summary to reduce context size:
|
|
263
|
+
|
|
264
|
+
```ts
|
|
265
|
+
const entries = kernel.read()
|
|
266
|
+
// Compact the first half of the conversation
|
|
267
|
+
kernel.compact(
|
|
268
|
+
entries[0].id,
|
|
269
|
+
entries[Math.floor(entries.length / 2)].id,
|
|
270
|
+
'Summary: discussed project setup and requirements.',
|
|
271
|
+
)
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
Compaction rewrites `kernel.jsonl` to the clean current branch and appends a divider to `log.jsonl`.
|
|
275
|
+
|
|
276
|
+
### Branching
|
|
277
|
+
|
|
278
|
+
```ts
|
|
279
|
+
// Rewind the conversation to a past entry (discards entries after toId in memory)
|
|
280
|
+
kernel.branch(toId)
|
|
281
|
+
```
|
|
282
|
+
|
|
283
|
+
### Session files
|
|
284
|
+
|
|
285
|
+
Each session writes three files to `<dir>/<sessionId>/`:
|
|
286
|
+
|
|
287
|
+
| File | Contents |
|
|
288
|
+
|---|---|
|
|
289
|
+
| `kernel.jsonl` | Current branch only; rewritten on compaction |
|
|
290
|
+
| `log.jsonl` | Append-only full history; never compacted; used for UI display |
|
|
291
|
+
| `meta.json` | Session metadata (`createdAt`, `title`, custom fields) |
|
|
292
|
+
|
|
293
|
+
---
|
|
294
|
+
|
|
295
|
+
## KernelCache
|
|
296
|
+
|
|
297
|
+
When an agent handles multiple sessions, recreating a `Kernel` from `kernel.jsonl` on every request adds unnecessary I/O. `KernelCache` keeps hot kernels in memory with LRU eviction and TTL expiry.
|
|
298
|
+
|
|
299
|
+
```ts
|
|
300
|
+
import { KernelCache } from '@devxiyang/agent-kernel/kernel'
|
|
301
|
+
|
|
302
|
+
const cache = new KernelCache({
|
|
303
|
+
dir: './.agent-sessions',
|
|
304
|
+
maxSize: 100, // keep at most 100 kernels in memory (default: 50)
|
|
305
|
+
ttl: 15 * 60_000, // evict after 15 min of inactivity (default: 30 min)
|
|
306
|
+
})
|
|
307
|
+
```
|
|
308
|
+
|
|
309
|
+
### Per-request pattern
|
|
310
|
+
|
|
311
|
+
```ts
|
|
312
|
+
async function handleRequest(sessionId: string, text: string) {
|
|
313
|
+
// Kernel is reused across requests; Agent is lightweight, created fresh each time
|
|
314
|
+
const kernel = cache.get(sessionId)
|
|
315
|
+
const agent = new Agent(kernel, { stream, tools, maxSteps: 8 })
|
|
316
|
+
|
|
317
|
+
agent.subscribe(event => { /* forward events to client */ })
|
|
318
|
+
|
|
319
|
+
agent.followUp({ type: 'user', payload: { parts: [{ type: 'text', text }] } })
|
|
320
|
+
await agent.waitForIdle()
|
|
321
|
+
}
|
|
322
|
+
```
|
|
323
|
+
|
|
324
|
+
The `Agent` is cheap to construct (no I/O, no async work) so creating one per request is fine. Only the `Kernel` — which holds the in-memory conversation tree — benefits from caching.
|
|
325
|
+
|
|
326
|
+
### Cache API
|
|
327
|
+
|
|
328
|
+
```ts
|
|
329
|
+
// Get or create a kernel for sessionId; updates LRU order and resets TTL
|
|
330
|
+
const kernel = cache.get(sessionId)
|
|
331
|
+
|
|
332
|
+
// Optionally pass metadata written to meta.json on first creation
|
|
333
|
+
const kernel = cache.get(sessionId, { title: 'My session' })
|
|
334
|
+
|
|
335
|
+
// Remove a specific session from cache (kernel.jsonl is not touched)
|
|
336
|
+
cache.evict(sessionId)
|
|
337
|
+
|
|
338
|
+
// Remove all cached kernels
|
|
339
|
+
cache.clear()
|
|
340
|
+
|
|
341
|
+
// Number of kernels currently cached
|
|
342
|
+
cache.size
|
|
343
|
+
```
|
|
344
|
+
|
|
345
|
+
---
|
|
346
|
+
|
|
347
|
+
## Persistent Sessions
|
|
348
|
+
|
|
349
|
+
```ts
|
|
350
|
+
import { createAgent } from '@devxiyang/agent-kernel'
|
|
351
|
+
|
|
352
|
+
const agent = createAgent({
|
|
353
|
+
stream, tools, maxSteps: 8,
|
|
354
|
+
session: {
|
|
355
|
+
dir: './.agent-sessions',
|
|
356
|
+
sessionId: 'my-session',
|
|
357
|
+
meta: { title: 'Code review assistant' },
|
|
358
|
+
},
|
|
359
|
+
})
|
|
360
|
+
|
|
361
|
+
agent.prompt({ type: 'user', payload: { parts: [{ type: 'text', text: 'Summarize our last discussion.' }] } })
|
|
362
|
+
await agent.waitForIdle()
|
|
363
|
+
|
|
364
|
+
// Manual compaction when context grows
|
|
365
|
+
const entries = agent.kernel.read()
|
|
366
|
+
if (entries.length > 12) {
|
|
367
|
+
agent.kernel.compact(entries[0].id, entries[8].id, 'Summary of earlier context.')
|
|
368
|
+
}
|
|
369
|
+
```
|
|
370
|
+
|
|
371
|
+
## Session Management
|
|
372
|
+
|
|
373
|
+
```ts
|
|
374
|
+
import { listSessions, deleteSession, updateSessionMeta } from '@devxiyang/agent-kernel/kernel'
|
|
375
|
+
|
|
376
|
+
// List all sessions, sorted by most recently updated
|
|
377
|
+
const sessions = listSessions('./.agent-sessions')
|
|
378
|
+
// [
|
|
379
|
+
// { sessionId: 'my-session', updatedAt: 1740000000000, messageCount: 12,
|
|
380
|
+
// meta: { createdAt: 1739999000000, title: 'Code review assistant' } },
|
|
381
|
+
// ]
|
|
382
|
+
|
|
383
|
+
// Rename a session
|
|
384
|
+
updateSessionMeta('./.agent-sessions', 'my-session', { title: 'New title' })
|
|
385
|
+
|
|
386
|
+
// Delete a session
|
|
387
|
+
deleteSession('./.agent-sessions', 'my-session')
|
|
388
|
+
```
|
|
389
|
+
|
|
390
|
+
All functions are safe to call on non-existent paths — `listSessions` returns `[]`, the others are silent no-ops.
|
|
391
|
+
|
|
392
|
+
### `SessionInfo` type
|
|
393
|
+
|
|
394
|
+
```ts
|
|
395
|
+
type SessionMeta = {
|
|
396
|
+
createdAt: number // Unix ms — set once, never overwritten
|
|
397
|
+
title?: string
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
type SessionInfo = {
|
|
401
|
+
sessionId: string
|
|
402
|
+
updatedAt: number // log.jsonl mtime in milliseconds
|
|
403
|
+
messageCount: number // entries in log.jsonl
|
|
404
|
+
meta: SessionMeta | null
|
|
405
|
+
}
|
|
406
|
+
```
|
|
407
|
+
|
|
98
408
|
---
|
|
99
409
|
|
|
100
410
|
## Defining Tools
|
|
101
411
|
|
|
102
|
-
|
|
103
|
-
arguments before calling `execute`; validation errors are returned as `tool_result` so the LLM
|
|
104
|
-
can retry with corrected parameters.
|
|
412
|
+
TypeBox schemas in `parameters` drive both runtime validation and the JSON Schema passed to the LLM. The `execute` input type is inferred — no manual annotation needed.
|
|
105
413
|
|
|
106
414
|
```ts
|
|
107
415
|
import { Type } from '@sinclair/typebox'
|
|
@@ -112,7 +420,6 @@ const searchSchema = Type.Object({
|
|
|
112
420
|
limit: Type.Optional(Type.Number({ description: 'Max results (default 10)' })),
|
|
113
421
|
})
|
|
114
422
|
|
|
115
|
-
// typeof searchSchema drives the input type — no manual annotation needed
|
|
116
423
|
const searchTool: AgentTool<typeof searchSchema> = {
|
|
117
424
|
name: 'search_docs',
|
|
118
425
|
description: 'Search project documentation by query.',
|
|
@@ -128,16 +435,12 @@ const searchTool: AgentTool<typeof searchSchema> = {
|
|
|
128
435
|
}
|
|
129
436
|
```
|
|
130
437
|
|
|
131
|
-
|
|
132
|
-
provider adapters can pass `tool.parameters` directly to any LLM API.
|
|
438
|
+
Validation errors are returned as `isError: true` tool results so the LLM can self-correct.
|
|
133
439
|
|
|
134
440
|
---
|
|
135
441
|
|
|
136
442
|
## Implementing a `StreamFn`
|
|
137
443
|
|
|
138
|
-
`StreamFn` receives the current conversation messages and the full tool list on every call.
|
|
139
|
-
Use `tools` to generate the provider-specific schema — no hardcoding needed.
|
|
140
|
-
|
|
141
444
|
```ts
|
|
142
445
|
type StreamFn = (
|
|
143
446
|
messages: AgentMessage[],
|
|
@@ -147,30 +450,27 @@ type StreamFn = (
|
|
|
147
450
|
) => Promise<LLMStepResult>
|
|
148
451
|
```
|
|
149
452
|
|
|
453
|
+
The function receives the full conversation and tool list on every call. Use `tool.parameters` (plain JSON Schema) to generate provider-specific tool definitions.
|
|
454
|
+
|
|
150
455
|
---
|
|
151
456
|
|
|
152
|
-
##
|
|
457
|
+
## Adapter Examples
|
|
153
458
|
|
|
154
|
-
|
|
459
|
+
### OpenAI SDK
|
|
155
460
|
|
|
156
461
|
```ts
|
|
157
462
|
import OpenAI from 'openai'
|
|
158
|
-
import type {
|
|
463
|
+
import type { StreamFn, ToolCallInfo } from '@devxiyang/agent-kernel'
|
|
159
464
|
|
|
160
465
|
const client = new OpenAI({ apiKey: process.env.OPENAI_API_KEY })
|
|
161
466
|
|
|
162
|
-
function toOpenAIMessages(messages: AgentMessage[]) {
|
|
163
|
-
return messages.map((m) => ({
|
|
164
|
-
role: m.role as 'user' | 'assistant' | 'tool',
|
|
165
|
-
content: typeof m.content === 'string' ? m.content : JSON.stringify(m.content),
|
|
166
|
-
}))
|
|
167
|
-
}
|
|
168
|
-
|
|
169
467
|
export const openaiStream: StreamFn = async (messages, tools, onEvent, signal) => {
|
|
170
468
|
const response = await client.responses.create({
|
|
171
469
|
model: 'gpt-4o',
|
|
172
|
-
input:
|
|
173
|
-
|
|
470
|
+
input: messages.map((m) => ({
|
|
471
|
+
role: m.role as 'user' | 'assistant' | 'tool',
|
|
472
|
+
content: typeof m.content === 'string' ? m.content : JSON.stringify(m.content),
|
|
473
|
+
})),
|
|
174
474
|
tools: tools.map((t) => ({
|
|
175
475
|
type: 'function' as const,
|
|
176
476
|
name: t.name,
|
|
@@ -218,70 +518,21 @@ export const openaiStream: StreamFn = async (messages, tools, onEvent, signal) =
|
|
|
218
518
|
},
|
|
219
519
|
}
|
|
220
520
|
}
|
|
221
|
-
|
|
222
|
-
// Usage
|
|
223
|
-
import { Type } from '@sinclair/typebox'
|
|
224
|
-
import { createAgent } from '@devxiyang/agent-kernel'
|
|
225
|
-
|
|
226
|
-
const searchSchema = Type.Object({
|
|
227
|
-
query: Type.String({ description: 'Search query string' }),
|
|
228
|
-
})
|
|
229
|
-
|
|
230
|
-
const agent = createAgent({
|
|
231
|
-
stream: openaiStream,
|
|
232
|
-
tools: [
|
|
233
|
-
{
|
|
234
|
-
name: 'search_docs',
|
|
235
|
-
description: 'Search project documentation by query.',
|
|
236
|
-
parameters: searchSchema,
|
|
237
|
-
execute: async (_id, input) => ({
|
|
238
|
-
content: `Results for: ${input.query}`,
|
|
239
|
-
isError: false,
|
|
240
|
-
}),
|
|
241
|
-
},
|
|
242
|
-
],
|
|
243
|
-
maxSteps: 10,
|
|
244
|
-
})
|
|
245
|
-
|
|
246
|
-
agent.subscribe((e) => { if (e.type === 'text_delta') process.stdout.write(e.delta) })
|
|
247
|
-
agent.prompt({ type: 'user', payload: { parts: [{ type: 'text', text: 'Find compact API docs' }] } })
|
|
248
|
-
await agent.waitForIdle()
|
|
249
521
|
```
|
|
250
522
|
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
## Example: Vercel AI SDK v6 Adapter
|
|
254
|
-
|
|
255
|
-
Uses `streamText` from `ai`. Tools without an `execute` function are returned as tool calls
|
|
256
|
-
for our loop to handle. `jsonSchema()` wraps TypeBox schemas as AI SDK-compatible schemas.
|
|
523
|
+
### Vercel AI SDK
|
|
257
524
|
|
|
258
525
|
```ts
|
|
259
526
|
import { streamText, jsonSchema, tool } from 'ai'
|
|
260
527
|
import { openai } from '@ai-sdk/openai'
|
|
261
|
-
import type {
|
|
262
|
-
|
|
263
|
-
function toAISDKMessages(messages: AgentMessage[]) {
|
|
264
|
-
return messages.map((m) => {
|
|
265
|
-
if (m.role === 'tool') {
|
|
266
|
-
// tool_result entries — AI SDK expects role 'tool'
|
|
267
|
-
const payload = m.content as { toolCallId: string; content: string }
|
|
268
|
-
return { role: 'tool' as const, content: [{ type: 'tool-result' as const, toolCallId: payload.toolCallId, result: payload.content }] }
|
|
269
|
-
}
|
|
270
|
-
return {
|
|
271
|
-
role: m.role as 'user' | 'assistant',
|
|
272
|
-
content: typeof m.content === 'string' ? m.content : JSON.stringify(m.content),
|
|
273
|
-
}
|
|
274
|
-
})
|
|
275
|
-
}
|
|
528
|
+
import type { StreamFn, ToolCallInfo } from '@devxiyang/agent-kernel'
|
|
276
529
|
|
|
277
530
|
export const aiSdkStream: StreamFn = async (messages, tools, onEvent, signal) => {
|
|
278
|
-
// Build AI SDK tool definitions — no execute, our loop handles execution
|
|
279
531
|
const aiTools = Object.fromEntries(
|
|
280
532
|
tools.map((t) => [
|
|
281
533
|
t.name,
|
|
282
534
|
tool({
|
|
283
535
|
description: t.description,
|
|
284
|
-
// jsonSchema() accepts any plain JSON Schema — TypeBox schemas qualify
|
|
285
536
|
inputSchema: t.parameters ? jsonSchema(t.parameters) : jsonSchema({ type: 'object', properties: {} }),
|
|
286
537
|
}),
|
|
287
538
|
]),
|
|
@@ -289,9 +540,12 @@ export const aiSdkStream: StreamFn = async (messages, tools, onEvent, signal) =>
|
|
|
289
540
|
|
|
290
541
|
const result = streamText({
|
|
291
542
|
model: openai('gpt-4o'),
|
|
292
|
-
messages:
|
|
543
|
+
messages: messages.map((m) => ({
|
|
544
|
+
role: m.role as 'user' | 'assistant',
|
|
545
|
+
content: typeof m.content === 'string' ? m.content : JSON.stringify(m.content),
|
|
546
|
+
})),
|
|
293
547
|
tools: aiTools,
|
|
294
|
-
maxSteps: 1,
|
|
548
|
+
maxSteps: 1,
|
|
295
549
|
abortSignal: signal,
|
|
296
550
|
})
|
|
297
551
|
|
|
@@ -326,200 +580,87 @@ export const aiSdkStream: StreamFn = async (messages, tools, onEvent, signal) =>
|
|
|
326
580
|
},
|
|
327
581
|
}
|
|
328
582
|
}
|
|
329
|
-
|
|
330
|
-
// Usage
|
|
331
|
-
import { Type } from '@sinclair/typebox'
|
|
332
|
-
import { createAgent } from '@devxiyang/agent-kernel'
|
|
333
|
-
|
|
334
|
-
const searchSchema = Type.Object({
|
|
335
|
-
query: Type.String({ description: 'Search query string' }),
|
|
336
|
-
})
|
|
337
|
-
|
|
338
|
-
const agent = createAgent({
|
|
339
|
-
stream: aiSdkStream,
|
|
340
|
-
tools: [
|
|
341
|
-
{
|
|
342
|
-
name: 'search_docs',
|
|
343
|
-
description: 'Search project documentation by query.',
|
|
344
|
-
parameters: searchSchema,
|
|
345
|
-
execute: async (_id, input) => ({
|
|
346
|
-
content: `Results for: ${input.query}`,
|
|
347
|
-
isError: false,
|
|
348
|
-
}),
|
|
349
|
-
},
|
|
350
|
-
],
|
|
351
|
-
maxSteps: 10,
|
|
352
|
-
})
|
|
353
|
-
|
|
354
|
-
agent.subscribe((e) => { if (e.type === 'text_delta') process.stdout.write(e.delta) })
|
|
355
|
-
agent.prompt({ type: 'user', payload: { parts: [{ type: 'text', text: 'Find compact API docs' }] } })
|
|
356
|
-
await agent.waitForIdle()
|
|
357
583
|
```
|
|
358
584
|
|
|
359
585
|
---
|
|
360
586
|
|
|
361
|
-
## Advanced
|
|
587
|
+
## Advanced Options
|
|
362
588
|
|
|
363
589
|
### Parallel Tool Execution
|
|
364
590
|
|
|
365
|
-
|
|
591
|
+
Run all tool calls in a turn concurrently. If a steering message arrives after execution, results are discarded and replaced with skipped markers.
|
|
366
592
|
|
|
367
593
|
```ts
|
|
368
|
-
const agent = createAgent({
|
|
369
|
-
stream, tools, maxSteps: 10,
|
|
370
|
-
parallelTools: true,
|
|
371
|
-
})
|
|
594
|
+
const agent = createAgent({ stream, tools, maxSteps: 10, parallelTools: true })
|
|
372
595
|
```
|
|
373
596
|
|
|
374
597
|
### Tool Timeout
|
|
375
598
|
|
|
376
|
-
|
|
599
|
+
Per-call deadline in milliseconds. Timed-out tools return `isError: true` so the LLM can handle the failure.
|
|
377
600
|
|
|
378
601
|
```ts
|
|
379
|
-
const agent = createAgent({
|
|
380
|
-
stream, tools, maxSteps: 10,
|
|
381
|
-
toolTimeout: 15_000, // 15 s per tool call
|
|
382
|
-
})
|
|
383
|
-
```
|
|
384
|
-
|
|
385
|
-
### Auto-Compaction Hook (`onContextFull`)
|
|
386
|
-
|
|
387
|
-
Fires after a step when `kernel.contextSize >= kernel.budget.limit`. The callback is responsible for compacting the kernel; the loop just provides the hook.
|
|
388
|
-
|
|
389
|
-
```ts
|
|
390
|
-
const agent = createAgent({
|
|
391
|
-
stream, tools, maxSteps: 10,
|
|
392
|
-
onContextFull: async (kernel) => {
|
|
393
|
-
const entries = kernel.read()
|
|
394
|
-
const from = entries[0].id
|
|
395
|
-
const to = entries[Math.floor(entries.length / 2)].id
|
|
396
|
-
kernel.compact(from, to, 'Earlier context summarised.')
|
|
397
|
-
},
|
|
398
|
-
})
|
|
399
|
-
|
|
400
|
-
agent.kernel.budget.set(80_000) // tokens — trigger at 80 k input tokens
|
|
602
|
+
const agent = createAgent({ stream, tools, maxSteps: 10, toolTimeout: 15_000 })
|
|
401
603
|
```
|
|
402
604
|
|
|
403
|
-
Only fires when `budget.limit` is explicitly set (the default is `Infinity`).
|
|
404
|
-
|
|
405
605
|
### Stream Error Retry
|
|
406
606
|
|
|
407
|
-
|
|
607
|
+
Retry transient LLM errors with a fixed delay. Abort signals are respected — no retry after abort.
|
|
408
608
|
|
|
409
609
|
```ts
|
|
410
610
|
const agent = createAgent({
|
|
411
611
|
stream, tools, maxSteps: 10,
|
|
412
|
-
retryOnError: {
|
|
413
|
-
maxAttempts: 3, // total attempts including the first
|
|
414
|
-
delayMs: 500,
|
|
415
|
-
},
|
|
612
|
+
retryOnError: { maxAttempts: 3, delayMs: 500 },
|
|
416
613
|
})
|
|
417
614
|
```
|
|
418
615
|
|
|
419
|
-
|
|
616
|
+
### Auto-Compaction (`onContextFull`)
|
|
420
617
|
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
## Persistent Session + Kernel Compaction
|
|
618
|
+
Fires after a step when `kernel.contextSize >= kernel.budget.limit`. Set `kernel.budget` to activate.
|
|
424
619
|
|
|
425
620
|
```ts
|
|
426
|
-
import { createAgent } from '@devxiyang/agent-kernel'
|
|
427
|
-
|
|
428
621
|
const agent = createAgent({
|
|
429
|
-
stream
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
dir: './.agent-sessions',
|
|
434
|
-
sessionId: 'demo-session-001',
|
|
622
|
+
stream, tools, maxSteps: 10,
|
|
623
|
+
onContextFull: async (kernel) => {
|
|
624
|
+
const entries = kernel.read()
|
|
625
|
+
kernel.compact(entries[0].id, entries[Math.floor(entries.length / 2)].id, 'Earlier context summarised.')
|
|
435
626
|
},
|
|
436
627
|
})
|
|
437
628
|
|
|
438
|
-
agent.
|
|
439
|
-
await agent.waitForIdle()
|
|
440
|
-
|
|
441
|
-
// Compact old entries when context grows
|
|
442
|
-
const entries = agent.kernel.read()
|
|
443
|
-
if (entries.length > 12) {
|
|
444
|
-
const fromId = entries[0].id
|
|
445
|
-
const toId = entries[Math.min(8, entries.length - 1)].id
|
|
446
|
-
agent.kernel.compact(fromId, toId, 'Summary of earlier context and decisions.')
|
|
447
|
-
}
|
|
629
|
+
agent.kernel.budget.set(80_000) // trigger at 80 k input tokens
|
|
448
630
|
```
|
|
449
631
|
|
|
450
|
-
Session files are written under `./.agent-sessions/<sessionId>/` (`kernel.jsonl`, `log.jsonl`).
|
|
451
|
-
|
|
452
632
|
---
|
|
453
633
|
|
|
454
|
-
##
|
|
634
|
+
## Tool Hooks (`wrapTool`)
|
|
455
635
|
|
|
456
|
-
|
|
636
|
+
Intercept tool calls before or after execution without modifying the original tool.
|
|
457
637
|
|
|
458
638
|
```ts
|
|
459
|
-
import {
|
|
460
|
-
listSessions,
|
|
461
|
-
deleteSession,
|
|
462
|
-
updateSessionMeta,
|
|
463
|
-
} from '@devxiyang/agent-kernel/kernel'
|
|
464
|
-
|
|
465
|
-
// List all sessions, sorted by most recently updated
|
|
466
|
-
const sessions = listSessions('./.agent-sessions')
|
|
467
|
-
// [
|
|
468
|
-
// { sessionId: 'demo-001', updatedAt: 1740000000000, messageCount: 12,
|
|
469
|
-
// meta: { createdAt: 1739999000000, title: 'My first session' } },
|
|
470
|
-
// { sessionId: 'demo-002', updatedAt: 1739000000000, messageCount: 4,
|
|
471
|
-
// meta: { createdAt: 1738999000000 } },
|
|
472
|
-
// ]
|
|
473
|
-
|
|
474
|
-
// Delete a session
|
|
475
|
-
deleteSession('./.agent-sessions', 'demo-001')
|
|
639
|
+
import { wrapTool } from '@devxiyang/agent-kernel'
|
|
476
640
|
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
Pass `meta` when creating a session to set an initial title or other fields. `createdAt` is set automatically on first creation and is never overwritten.
|
|
484
|
-
|
|
485
|
-
```ts
|
|
486
|
-
const agent = createAgent({
|
|
487
|
-
stream, tools, maxSteps: 8,
|
|
488
|
-
session: {
|
|
489
|
-
dir: './.agent-sessions',
|
|
490
|
-
sessionId: 'my-session',
|
|
491
|
-
meta: { title: 'Code review assistant' },
|
|
641
|
+
const guardedTool = wrapTool(myTool, {
|
|
642
|
+
before: async (toolCallId, toolName, input) => {
|
|
643
|
+
if (!isAllowed(input)) return { action: 'block', reason: 'Not permitted.' }
|
|
644
|
+
},
|
|
645
|
+
after: async (toolCallId, toolName, result) => {
|
|
646
|
+
return { content: redact(result.content) }
|
|
492
647
|
},
|
|
493
648
|
})
|
|
494
649
|
```
|
|
495
650
|
|
|
496
|
-
`
|
|
497
|
-
|
|
498
|
-
```ts
|
|
499
|
-
type SessionMeta = {
|
|
500
|
-
createdAt: number // Unix ms — set once at creation
|
|
501
|
-
title?: string
|
|
502
|
-
}
|
|
503
|
-
|
|
504
|
-
type SessionInfo = {
|
|
505
|
-
sessionId: string // directory name used as session ID
|
|
506
|
-
updatedAt: number // log.jsonl mtime in milliseconds
|
|
507
|
-
messageCount: number // number of entries in log.jsonl
|
|
508
|
-
meta: SessionMeta | null
|
|
509
|
-
}
|
|
510
|
-
```
|
|
511
|
-
|
|
512
|
-
All functions are safe to call on non-existent paths — `listSessions` returns `[]`,
|
|
513
|
-
`deleteSession` and `updateSessionMeta` are silent no-ops when the session does not exist.
|
|
651
|
+
`before` can return `{ action: 'block', reason }` to skip execution; the reason is returned as `isError: true`. `after` can override `content`, `isError`, or `details`.
|
|
514
652
|
|
|
515
653
|
---
|
|
516
654
|
|
|
517
|
-
## Build
|
|
518
|
-
|
|
519
|
-
Compiled files and type declarations are generated into `dist/`.
|
|
655
|
+
## Build & Test
|
|
520
656
|
|
|
521
657
|
```bash
|
|
522
|
-
npm run build # compile TypeScript
|
|
658
|
+
npm run build # compile TypeScript → dist/
|
|
523
659
|
npm run typecheck # type-check without emitting
|
|
524
660
|
npm test # run unit tests (vitest)
|
|
661
|
+
npm run test:watch # watch mode
|
|
525
662
|
```
|
|
663
|
+
|
|
664
|
+
## License
|
|
665
|
+
|
|
666
|
+
[MIT](./LICENSE)
|
|
@@ -94,9 +94,9 @@ export declare class Agent {
|
|
|
94
94
|
*/
|
|
95
95
|
steer(entries: AgentEntry | AgentEntry[]): void;
|
|
96
96
|
/**
|
|
97
|
-
*
|
|
98
|
-
*
|
|
99
|
-
*
|
|
97
|
+
* Send one or more entries to the agent.
|
|
98
|
+
* If idle, starts a new run immediately. If already running, queues the
|
|
99
|
+
* entries for the next outer-loop iteration (same behaviour as before).
|
|
100
100
|
*/
|
|
101
101
|
followUp(entries: AgentEntry | AgentEntry[]): void;
|
|
102
102
|
/** Cancel the current run. No-op if not running. */
|
|
@@ -107,7 +107,7 @@ export declare class Agent {
|
|
|
107
107
|
* Throws if called while running — abort() first.
|
|
108
108
|
*/
|
|
109
109
|
reset(): void;
|
|
110
|
-
/** Resolves when the agent
|
|
110
|
+
/** Resolves when the agent is truly idle (no running loop, no queued follow-ups). */
|
|
111
111
|
waitForIdle(): Promise<void>;
|
|
112
112
|
private _run;
|
|
113
113
|
private _consume;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agent.d.ts","sourceRoot":"","sources":["../../../src/core/agent/agent.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,WAAW,CAAA;AAG3D,OAAO,KAAK,EACV,UAAU,EACV,UAAU,EAEV,YAAY,EACZ,SAAS,EACT,QAAQ,EAER,SAAS,EACV,MAAM,SAAS,CAAA;AAIhB,MAAM,WAAW,UAAU;IACzB,qDAAqD;IACrD,SAAS,EAAS,OAAO,CAAA;IACzB,mEAAmE;IACnE,WAAW,EAAO,UAAU,GAAG,IAAI,CAAA;IACnC,yCAAyC;IACzC,gBAAgB,EAAE,GAAG,CAAC,MAAM,CAAC,CAAA;IAC7B,4DAA4D;IAC5D,KAAK,EAAa,MAAM,GAAG,IAAI,CAAA;CAChC;AAID;;;;;;GAMG;AACH,qBAAa,KAAK;IAChB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAa;IAErC,OAAO,CAAC,OAAO,CAAoB;IACnC,OAAO,CAAC,MAAM,CAAwB;IACtC,OAAO,CAAC,SAAS,CAAgB;IACjC,OAAO,CAAC,iBAAiB,CAAkC;IAC3D,OAAO,CAAC,UAAU,CAAkC;IACpD,OAAO,CAAC,aAAa,CAAe;IACpC,OAAO,CAAC,aAAa,CAAe;IACpC,OAAO,CAAC,cAAc,CAAkC;IACxD,OAAO,CAAC,cAAc,CAAkC;IACxD,OAAO,CAAC,YAAY,CAAkC;IACtD,OAAO,CAAC,aAAa,CAAkC;IAEvD,OAAO,CAAC,gBAAgB,CAA+B;IACvD,OAAO,CAAC,eAAe,CAAiD;IAExE,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAmB;IAClD,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAmB;IAClD,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAyC;IAGpE,OAAO,CAAC,YAAY,CAA8B;IAClD,OAAO,CAAC,WAAW,CAAW;IAC9B,OAAO,CAAC,gBAAgB,CAAO;IAC/B,OAAO,CAAC,gBAAgB,CAAqB;IAC7C,OAAO,CAAC,iBAAiB,CAAoB;IAC7C,OAAO,CAAC,MAAM,CAAgC;gBAElC,MAAM,EAAE,WAAW,EAAE,OAAO,EAAE,YAAY;IAiBtD,4EAA4E;IAC5E,IAAI,MAAM,IAAI,WAAW,CAAwB;IAEjD,yDAAyD;IACzD,IAAI,KAAK,IAAI,UAAU,CAOtB;IAID,yEAAyE;IACzE,SAAS,CAAC,MAAM,EAAE,QAAQ,GAAG,IAAI;IACjC,2DAA2D;IAC3D,QAAQ,CAAC,KAAK,EAAE,SAAS,EAAE,GAAG,IAAI;IAClC,8EAA8E;IAC9E,WAAW,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI;IACnC,gEAAgE;IAChE,eAAe,CAAC,IAAI,EAAE,SAAS,GAAG,IAAI;IACtC,iEAAiE;IACjE,eAAe,CAAC,IAAI,EAAE,SAAS,GAAG,IAAI;IAItC;;;OAGG;IACH,SAAS,CAAC,EAAE,EAAE,CAAC,KAAK,EAAE,UAAU,KAAK,IAAI,GAAG,MAAM,IAAI;IAOtD;;;OAGG;IACH,MAAM,CAAC,OAAO,EAAE,UAAU,GAAG,UAAU,EAAE,GAAG,IAAI;IAahD;;;;OAIG;IACH,QAAQ,IAAI,IAAI;IA0BhB;;;;OAIG;IACH,KAAK,CAAC,OAAO,EAAE,UAAU,GAAG,UAAU,EAAE,GAAG,IAAI;IAI/C;;;;OAIG;IACH,QAAQ,CAAC,OAAO,EAAE,UAAU,GAAG,UAAU,EAAE,GAAG,IAAI;
|
|
1
|
+
{"version":3,"file":"agent.d.ts","sourceRoot":"","sources":["../../../src/core/agent/agent.ts"],"names":[],"mappings":"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"}
|
package/dist/core/agent/agent.js
CHANGED
|
@@ -143,12 +143,16 @@ export class Agent {
|
|
|
143
143
|
this._steeringQueue.push(...(Array.isArray(entries) ? entries : [entries]));
|
|
144
144
|
}
|
|
145
145
|
/**
|
|
146
|
-
*
|
|
147
|
-
*
|
|
148
|
-
*
|
|
146
|
+
* Send one or more entries to the agent.
|
|
147
|
+
* If idle, starts a new run immediately. If already running, queues the
|
|
148
|
+
* entries for the next outer-loop iteration (same behaviour as before).
|
|
149
149
|
*/
|
|
150
150
|
followUp(entries) {
|
|
151
151
|
this._followUpQueue.push(...(Array.isArray(entries) ? entries : [entries]));
|
|
152
|
+
if (!this.state.isRunning) {
|
|
153
|
+
this._error = null;
|
|
154
|
+
this._run();
|
|
155
|
+
}
|
|
152
156
|
}
|
|
153
157
|
// ── Abort ───────────────────────────────────────────────────────────────
|
|
154
158
|
/** Cancel the current run. No-op if not running. */
|
|
@@ -175,13 +179,13 @@ export class Agent {
|
|
|
175
179
|
this._error = null;
|
|
176
180
|
}
|
|
177
181
|
// ── Wait ────────────────────────────────────────────────────────────────
|
|
178
|
-
/** Resolves when the agent
|
|
182
|
+
/** Resolves when the agent is truly idle (no running loop, no queued follow-ups). */
|
|
179
183
|
async waitForIdle() {
|
|
180
|
-
|
|
184
|
+
while (this._runningPromise) {
|
|
181
185
|
try {
|
|
182
186
|
await this._runningPromise;
|
|
183
187
|
}
|
|
184
|
-
catch { /*
|
|
188
|
+
catch { /* errors propagate via subscribe */ }
|
|
185
189
|
}
|
|
186
190
|
}
|
|
187
191
|
// ── Private ─────────────────────────────────────────────────────────────
|
|
@@ -219,6 +223,9 @@ export class Agent {
|
|
|
219
223
|
finally {
|
|
220
224
|
this._abortController = null;
|
|
221
225
|
this._runningPromise = null;
|
|
226
|
+
if (this._followUpQueue.length > 0) {
|
|
227
|
+
this._run();
|
|
228
|
+
}
|
|
222
229
|
}
|
|
223
230
|
}
|
|
224
231
|
_handleEvent(event) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agent.js","sourceRoot":"","sources":["../../../src/core/agent/agent.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAGH,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAA;AACxC,OAAO,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAA;AAyBhC,gFAAgF;AAEhF;;;;;;GAMG;AACH,MAAM,OAAO,KAAK;IACC,OAAO,CAAa;IAE7B,OAAO,CAAoB;IAC3B,MAAM,CAAwB;IAC9B,SAAS,CAAgB;IACzB,iBAAiB,CAAkC;IACnD,UAAU,CAAkC;IAC5C,aAAa,CAAe;IAC5B,aAAa,CAAe;IAC5B,cAAc,CAAkC;IAChD,cAAc,CAAkC;IAChD,YAAY,CAAkC;IAC9C,aAAa,CAAkC;IAE/C,gBAAgB,GAA2B,IAAI,CAAA;IAC/C,eAAe,GAA6C,IAAI,CAAA;IAEvD,cAAc,GAAiB,EAAE,CAAA;IACjC,cAAc,GAAiB,EAAE,CAAA;IACjC,UAAU,GAAG,IAAI,GAAG,EAA+B,CAAA;IAEpE,0EAA0E;IAClE,YAAY,GAA0B,IAAI,CAAA;IAC1C,WAAW,GAAS,EAAE,CAAA;IACtB,gBAAgB,GAAK,EAAE,CAAA;IACvB,gBAAgB,GAAmB,EAAE,CAAA;IACrC,iBAAiB,GAAG,IAAI,GAAG,EAAU,CAAA;IACrC,MAAM,GAA4B,IAAI,CAAA;IAE9C,YAAY,MAAmB,EAAE,OAAqB;QACpD,IAAI,CAAC,OAAO,GAAa,MAAM,CAAA;QAC/B,IAAI,CAAC,OAAO,GAAa,OAAO,CAAC,MAAM,CAAA;QACvC,IAAI,CAAC,MAAM,GAAc,OAAO,CAAC,KAAK,CAAA;QACtC,IAAI,CAAC,SAAS,GAAW,OAAO,CAAC,QAAQ,CAAA;QACzC,IAAI,CAAC,iBAAiB,GAAG,OAAO,CAAC,gBAAgB,CAAA;QACjD,IAAI,CAAC,UAAU,GAAU,OAAO,CAAC,SAAS,CAAA;QAC1C,IAAI,CAAC,aAAa,GAAO,OAAO,CAAC,YAAY,IAAI,eAAe,CAAA;QAChE,IAAI,CAAC,aAAa,GAAO,OAAO,CAAC,YAAY,IAAI,eAAe,CAAA;QAChE,IAAI,CAAC,cAAc,GAAM,OAAO,CAAC,aAAa,CAAA;QAC9C,IAAI,CAAC,cAAc,GAAM,OAAO,CAAC,aAAa,CAAA;QAC9C,IAAI,CAAC,YAAY,GAAQ,OAAO,CAAC,WAAW,CAAA;QAC5C,IAAI,CAAC,aAAa,GAAO,OAAO,CAAC,YAAY,CAAA;IAC/C,CAAC;IAED,0EAA0E;IAE1E,4EAA4E;IAC5E,IAAI,MAAM,KAAkB,OAAO,IAAI,CAAC,OAAO,CAAA,CAAC,CAAC;IAEjD,yDAAyD;IACzD,IAAI,KAAK;QACP,OAAO;YACL,SAAS,EAAS,IAAI,CAAC,gBAAgB,KAAK,IAAI;YAChD,WAAW,EAAO,IAAI,CAAC,YAAY;YACnC,gBAAgB,EAAE,IAAI,CAAC,iBAAiB;YACxC,KAAK,EAAa,IAAI,CAAC,MAAM;SAC9B,CAAA;IACH,CAAC;IAED,4EAA4E;IAE5E,yEAAyE;IACzE,SAAS,CAAC,MAAgB,IAAe,IAAI,CAAC,OAAO,GAAG,MAAM,CAAA,CAAC,CAAC;IAChE,2DAA2D;IAC3D,QAAQ,CAAC,KAAkB,IAAc,IAAI,CAAC,MAAM,GAAG,KAAK,CAAA,CAAC,CAAC;IAC9D,8EAA8E;IAC9E,WAAW,CAAC,QAAgB,IAAa,IAAI,CAAC,SAAS,GAAG,QAAQ,CAAA,CAAC,CAAC;IACpE,gEAAgE;IAChE,eAAe,CAAC,IAAe,IAAU,IAAI,CAAC,aAAa,GAAG,IAAI,CAAA,CAAC,CAAC;IACpE,iEAAiE;IACjE,eAAe,CAAC,IAAe,IAAU,IAAI,CAAC,aAAa,GAAG,IAAI,CAAA,CAAC,CAAC;IAEpE,2EAA2E;IAE3E;;;OAGG;IACH,SAAS,CAAC,EAA+B;QACvC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC,CAAA;QACvB,OAAO,GAAG,EAAE,GAAG,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC,CAAA,CAAC,CAAC,CAAA;IAC7C,CAAC;IAED,2EAA2E;IAE3E;;;OAGG;IACH,MAAM,CAAC,OAAkC;QACvC,IAAI,IAAI,CAAC,KAAK,CAAC,SAAS,EAAE,CAAC;YACzB,MAAM,IAAI,KAAK,CAAC,wEAAwE,CAAC,CAAA;QAC3F,CAAC;QAED,KAAK,MAAM,KAAK,IAAI,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC;YACjE,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,CAAA;QAC5B,CAAC;QAED,IAAI,CAAC,MAAM,GAAG,IAAI,CAAA;QAClB,IAAI,CAAC,IAAI,EAAE,CAAA;IACb,CAAC;IAED;;;;OAIG;IACH,QAAQ;QACN,IAAI,IAAI,CAAC,KAAK,CAAC,SAAS,EAAE,CAAC;YACzB,MAAM,IAAI,KAAK,CAAC,2BAA2B,CAAC,CAAA;QAC9C,CAAC;QAED,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,CAAA;QACrC,IAAI,CAAC,SAAS,EAAE,CAAC;YACf,MAAM,IAAI,KAAK,CAAC,0DAA0D,CAAC,CAAA;QAC7E,CAAC;QAED,MAAM,SAAS,GAAG,IAAI,CAAC,cAAc,CAAC,MAAM,GAAG,CAAC,IAAI,IAAI,CAAC,cAAc,CAAC,MAAM,GAAG,CAAC,CAAA;QAElF,IAAI,SAAS,CAAC,IAAI,KAAK,WAAW,EAAE,CAAC;YACnC,MAAM,EAAE,UAAU,EAAE,GAAG,SAAS,CAAC,OAAO,CAAA;YACxC,MAAM,WAAW,GAAG,UAAU,KAAK,OAAO,IAAI,UAAU,KAAK,SAAS,CAAA;YACtE,IAAI,CAAC,WAAW,IAAI,CAAC,SAAS,EAAE,CAAC;gBAC/B,MAAM,IAAI,KAAK,CAAC,6DAA6D,CAAC,CAAA;YAChF,CAAC;QACH,CAAC;QAED,IAAI,CAAC,MAAM,GAAG,IAAI,CAAA;QAClB,IAAI,CAAC,IAAI,EAAE,CAAA;IACb,CAAC;IAED,2EAA2E;IAE3E;;;;OAIG;IACH,KAAK,CAAC,OAAkC;QACtC,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAA;IAC7E,CAAC;IAED;;;;OAIG;IACH,QAAQ,CAAC,OAAkC;QACzC,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAA;
|
|
1
|
+
{"version":3,"file":"agent.js","sourceRoot":"","sources":["../../../src/core/agent/agent.ts"],"names":[],"mappings":"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"}
|
|
@@ -7,6 +7,8 @@
|
|
|
7
7
|
export type { Usage, DataContent, TextPart, ImagePart, AudioPart, VideoPart, FilePart, ContentPart, ImageMediaType, AudioMediaType, VideoMediaType, FileMediaType, StopReason, ToolCallInfo, AgentEntry, AgentMessage, StoredEntry, AppendResult, CompactionEntry, TokenBudget, AgentKernel, KernelOptions, SessionMeta, } from './types';
|
|
8
8
|
export { COMPACTION_TYPE } from './types';
|
|
9
9
|
export { createKernel } from './kernel';
|
|
10
|
+
export type { KernelCacheOptions } from './kernel-cache';
|
|
11
|
+
export { KernelCache } from './kernel-cache';
|
|
10
12
|
export type { SessionInfo } from './session-store';
|
|
11
13
|
export { listSessions, deleteSession, updateSessionMeta } from './session-store';
|
|
12
14
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/core/kernel/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,YAAY,EACV,KAAK,EACL,WAAW,EACX,QAAQ,EACR,SAAS,EACT,SAAS,EACT,SAAS,EACT,QAAQ,EACR,WAAW,EACX,cAAc,EACd,cAAc,EACd,cAAc,EACd,aAAa,EACb,UAAU,EACV,YAAY,EACZ,UAAU,EACV,YAAY,EACZ,WAAW,EACX,YAAY,EACZ,eAAe,EACf,WAAW,EACX,WAAW,EACX,aAAa,EACb,WAAW,GACZ,MAAM,SAAS,CAAA;AAEhB,OAAO,EAAE,eAAe,EAAE,MAAM,SAAS,CAAA;AAEzC,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAA;AAEvC,YAAY,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAA;AAClD,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAA"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/core/kernel/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,YAAY,EACV,KAAK,EACL,WAAW,EACX,QAAQ,EACR,SAAS,EACT,SAAS,EACT,SAAS,EACT,QAAQ,EACR,WAAW,EACX,cAAc,EACd,cAAc,EACd,cAAc,EACd,aAAa,EACb,UAAU,EACV,YAAY,EACZ,UAAU,EACV,YAAY,EACZ,WAAW,EACX,YAAY,EACZ,eAAe,EACf,WAAW,EACX,WAAW,EACX,aAAa,EACb,WAAW,GACZ,MAAM,SAAS,CAAA;AAEhB,OAAO,EAAE,eAAe,EAAE,MAAM,SAAS,CAAA;AAEzC,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAA;AAEvC,YAAY,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAA;AACxD,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAA;AAE5C,YAAY,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAA;AAClD,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/core/kernel/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AA4BH,OAAO,EAAE,eAAe,EAAE,MAAM,SAAS,CAAA;AAEzC,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAA;AAGvC,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAA"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/core/kernel/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AA4BH,OAAO,EAAE,eAAe,EAAE,MAAM,SAAS,CAAA;AAEzC,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAA;AAGvC,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAA;AAG5C,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAA"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import type { AgentKernel, KernelOptions } from './types';
|
|
2
|
+
export interface KernelCacheOptions {
|
|
3
|
+
/** Base directory for session persistence (passed to createKernel). */
|
|
4
|
+
dir: string;
|
|
5
|
+
/** Maximum number of kernels to keep in memory. LRU eviction. Default: 50 */
|
|
6
|
+
maxSize?: number;
|
|
7
|
+
/** Milliseconds of inactivity before a kernel is evicted. Default: 30 minutes */
|
|
8
|
+
ttl?: number;
|
|
9
|
+
/** Injectable time source for testing. Defaults to performance or Date. */
|
|
10
|
+
perf?: {
|
|
11
|
+
now(): number;
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* In-memory LRU cache of AgentKernel instances keyed by sessionId.
|
|
16
|
+
*
|
|
17
|
+
* Kernels are expensive to recreate because loadFromFile replays kernel.jsonl
|
|
18
|
+
* on every cold start. KernelCache keeps hot sessions in memory and evicts
|
|
19
|
+
* them by LRU order or TTL, falling back to file-based restore on cache miss.
|
|
20
|
+
*/
|
|
21
|
+
export declare class KernelCache {
|
|
22
|
+
private readonly _dir;
|
|
23
|
+
private readonly _cache;
|
|
24
|
+
constructor(options: KernelCacheOptions);
|
|
25
|
+
/**
|
|
26
|
+
* Return the cached kernel for sessionId, or create one from disk.
|
|
27
|
+
* Updates LRU order and TTL on every call.
|
|
28
|
+
*/
|
|
29
|
+
get(sessionId: string, meta?: KernelOptions['meta']): AgentKernel;
|
|
30
|
+
/** Remove a specific session from the cache. */
|
|
31
|
+
evict(sessionId: string): void;
|
|
32
|
+
/** Remove all cached kernels. */
|
|
33
|
+
clear(): void;
|
|
34
|
+
/** Number of kernels currently in cache. */
|
|
35
|
+
get size(): number;
|
|
36
|
+
}
|
|
37
|
+
//# sourceMappingURL=kernel-cache.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"kernel-cache.d.ts","sourceRoot":"","sources":["../../../src/core/kernel/kernel-cache.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,SAAS,CAAA;AAIzD,MAAM,WAAW,kBAAkB;IACjC,uEAAuE;IACvE,GAAG,EAAE,MAAM,CAAA;IACX,6EAA6E;IAC7E,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,iFAAiF;IACjF,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,2EAA2E;IAC3E,IAAI,CAAC,EAAE;QAAE,GAAG,IAAI,MAAM,CAAA;KAAE,CAAA;CACzB;AAID;;;;;;GAMG;AACH,qBAAa,WAAW;IACtB,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAU;IAC/B,OAAO,CAAC,QAAQ,CAAC,MAAM,CAA+B;gBAE1C,OAAO,EAAE,kBAAkB;IASvC;;;OAGG;IACH,GAAG,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,aAAa,CAAC,MAAM,CAAC,GAAG,WAAW;IASjE,gDAAgD;IAChD,KAAK,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI;IAI9B,iCAAiC;IACjC,KAAK,IAAI,IAAI;IAIb,4CAA4C;IAC5C,IAAI,IAAI,IAAI,MAAM,CAEjB;CACF"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { LRUCache } from 'lru-cache';
|
|
2
|
+
import { createKernel } from './kernel';
|
|
3
|
+
// ─── KernelCache ──────────────────────────────────────────────────────────────
|
|
4
|
+
/**
|
|
5
|
+
* In-memory LRU cache of AgentKernel instances keyed by sessionId.
|
|
6
|
+
*
|
|
7
|
+
* Kernels are expensive to recreate because loadFromFile replays kernel.jsonl
|
|
8
|
+
* on every cold start. KernelCache keeps hot sessions in memory and evicts
|
|
9
|
+
* them by LRU order or TTL, falling back to file-based restore on cache miss.
|
|
10
|
+
*/
|
|
11
|
+
export class KernelCache {
|
|
12
|
+
_dir;
|
|
13
|
+
_cache;
|
|
14
|
+
constructor(options) {
|
|
15
|
+
this._dir = options.dir;
|
|
16
|
+
this._cache = new LRUCache({
|
|
17
|
+
max: options.maxSize ?? 50,
|
|
18
|
+
ttl: options.ttl ?? 30 * 60 * 1000,
|
|
19
|
+
...(options.perf && { perf: options.perf }),
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Return the cached kernel for sessionId, or create one from disk.
|
|
24
|
+
* Updates LRU order and TTL on every call.
|
|
25
|
+
*/
|
|
26
|
+
get(sessionId, meta) {
|
|
27
|
+
const cached = this._cache.get(sessionId);
|
|
28
|
+
if (cached)
|
|
29
|
+
return cached;
|
|
30
|
+
const kernel = createKernel({ dir: this._dir, sessionId, meta });
|
|
31
|
+
this._cache.set(sessionId, kernel);
|
|
32
|
+
return kernel;
|
|
33
|
+
}
|
|
34
|
+
/** Remove a specific session from the cache. */
|
|
35
|
+
evict(sessionId) {
|
|
36
|
+
this._cache.delete(sessionId);
|
|
37
|
+
}
|
|
38
|
+
/** Remove all cached kernels. */
|
|
39
|
+
clear() {
|
|
40
|
+
this._cache.clear();
|
|
41
|
+
}
|
|
42
|
+
/** Number of kernels currently in cache. */
|
|
43
|
+
get size() {
|
|
44
|
+
return this._cache.size;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
//# sourceMappingURL=kernel-cache.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"kernel-cache.js","sourceRoot":"","sources":["../../../src/core/kernel/kernel-cache.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAA;AACpC,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAA;AAgBvC,iFAAiF;AAEjF;;;;;;GAMG;AACH,MAAM,OAAO,WAAW;IACL,IAAI,CAAU;IACd,MAAM,CAA+B;IAEtD,YAAY,OAA2B;QACrC,IAAI,CAAC,IAAI,GAAK,OAAO,CAAC,GAAG,CAAA;QACzB,IAAI,CAAC,MAAM,GAAG,IAAI,QAAQ,CAAsB;YAC9C,GAAG,EAAG,OAAO,CAAC,OAAO,IAAI,EAAE;YAC3B,GAAG,EAAG,OAAO,CAAC,GAAG,IAAQ,EAAE,GAAG,EAAE,GAAG,IAAI;YACvC,GAAG,CAAC,OAAO,CAAC,IAAI,IAAI,EAAE,IAAI,EAAE,OAAO,CAAC,IAAI,EAAE,CAAC;SAC5C,CAAC,CAAA;IACJ,CAAC;IAED;;;OAGG;IACH,GAAG,CAAC,SAAiB,EAAE,IAA4B;QACjD,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,SAAS,CAAC,CAAA;QACzC,IAAI,MAAM;YAAE,OAAO,MAAM,CAAA;QAEzB,MAAM,MAAM,GAAG,YAAY,CAAC,EAAE,GAAG,EAAE,IAAI,CAAC,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAA;QAChE,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,SAAS,EAAE,MAAM,CAAC,CAAA;QAClC,OAAO,MAAM,CAAA;IACf,CAAC;IAED,gDAAgD;IAChD,KAAK,CAAC,SAAiB;QACrB,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC,CAAA;IAC/B,CAAC;IAED,iCAAiC;IACjC,KAAK;QACH,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,CAAA;IACrB,CAAC;IAED,4CAA4C;IAC5C,IAAI,IAAI;QACN,OAAO,IAAI,CAAC,MAAM,CAAC,IAAI,CAAA;IACzB,CAAC;CACF"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@devxiyang/agent-kernel",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.5",
|
|
4
4
|
"description": "Agent kernel and loop library",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -52,6 +52,7 @@
|
|
|
52
52
|
"vitest": "^4.0.18"
|
|
53
53
|
},
|
|
54
54
|
"dependencies": {
|
|
55
|
-
"@sinclair/typebox": "^0.34.48"
|
|
55
|
+
"@sinclair/typebox": "^0.34.48",
|
|
56
|
+
"lru-cache": "^11.2.6"
|
|
56
57
|
}
|
|
57
58
|
}
|