goatchain 0.0.30 → 0.0.32
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +174 -106
- package/dist/index.d.ts +1 -1
- package/dist/index.js +416 -425
- package/dist/middleware/contextCompressionMiddleware.d.ts +21 -169
- package/dist/state/types.d.ts +3 -55
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -28,6 +28,7 @@ hooks: {
|
|
|
28
28
|
```
|
|
29
29
|
|
|
30
30
|
If you need both, use:
|
|
31
|
+
|
|
31
32
|
- `preToolUse` to rewrite tool arguments/tool call
|
|
32
33
|
- `permissionRequest` to allow or block execution
|
|
33
34
|
|
|
@@ -115,6 +116,7 @@ const session = await agent.createSession({
|
|
|
115
116
|
interface CreateSessionOptions {
|
|
116
117
|
sessionId?: string // Custom session ID
|
|
117
118
|
model?: ModelRef // Optional model override
|
|
119
|
+
variants?: ModelRef[] // Optional fallback model refs
|
|
118
120
|
maxIterations?: number // Max agent loop iterations (default: 1000)
|
|
119
121
|
cwd?: string // Working directory for file operations
|
|
120
122
|
messageQueueConfig?: {
|
|
@@ -124,14 +126,15 @@ interface CreateSessionOptions {
|
|
|
124
126
|
requestParams?: {
|
|
125
127
|
temperature?: number // Model temperature
|
|
126
128
|
maxTokens?: number // Max output tokens
|
|
127
|
-
|
|
129
|
+
stop?: string[] // Optional stop sequences
|
|
130
|
+
[key: string]: unknown // Provider-specific request params
|
|
128
131
|
}
|
|
129
132
|
}
|
|
130
133
|
```
|
|
131
134
|
|
|
132
135
|
### Working Directory (CWD) Configuration
|
|
133
136
|
|
|
134
|
-
You can set a working directory for the session, which will be automatically applied to
|
|
137
|
+
You can set a working directory for the session, which will be automatically applied to tools that support `setCwd()` (for example `Read`, `Write`, `Edit`, `Glob`, `Grep`, and `Bash`):
|
|
135
138
|
|
|
136
139
|
```typescript
|
|
137
140
|
// Set CWD when creating a session
|
|
@@ -273,7 +276,7 @@ for await (const event of session.receive()) {
|
|
|
273
276
|
break
|
|
274
277
|
|
|
275
278
|
case 'tool_call_start':
|
|
276
|
-
console.log(`\nCalling tool: ${event.
|
|
279
|
+
console.log(`\nCalling tool: ${event.toolName ?? event.callId}`)
|
|
277
280
|
break
|
|
278
281
|
|
|
279
282
|
case 'tool_result':
|
|
@@ -289,30 +292,28 @@ for await (const event of session.receive()) {
|
|
|
289
292
|
console.log(`\nConversation done: ${event.stopReason}`)
|
|
290
293
|
console.log(`Total tokens: ${event.usage?.totalTokens}`)
|
|
291
294
|
break
|
|
292
|
-
|
|
293
|
-
case 'error':
|
|
294
|
-
console.error(`Error: ${event.error}`)
|
|
295
|
-
break
|
|
296
295
|
}
|
|
297
296
|
}
|
|
298
297
|
```
|
|
299
298
|
|
|
300
299
|
### Session Event Types
|
|
301
300
|
|
|
302
|
-
| Event Type
|
|
303
|
-
|
|
|
304
|
-
| `
|
|
305
|
-
| `text_delta`
|
|
306
|
-
| `thinking_start`
|
|
307
|
-
| `
|
|
308
|
-
| `
|
|
309
|
-
| `
|
|
310
|
-
| `
|
|
311
|
-
| `
|
|
312
|
-
| `
|
|
313
|
-
| `iteration_end`
|
|
314
|
-
| `
|
|
315
|
-
| `
|
|
301
|
+
| Event Type | Description | Key Fields |
|
|
302
|
+
| ------------------------------------------------------- | ------------------------------------------------ | -------------------------------------------------- |
|
|
303
|
+
| `session_created` | New session stream starts | `sessionId` |
|
|
304
|
+
| `text_start` / `text_delta` / `text_end` | Assistant text stream | `delta`, `content` |
|
|
305
|
+
| `thinking_start` / `thinking_delta` / `thinking_end` | Model reasoning stream | `delta`, `content` |
|
|
306
|
+
| `tool_call_start` / `tool_call_delta` / `tool_call_end` | Tool call lifecycle | `callId`, `toolName`, `toolCall` |
|
|
307
|
+
| `tool_output_start` / `tool_output_delta` | Live tool stdout/stderr stream | `tool_call_id`, `delta`, `isStderr` |
|
|
308
|
+
| `tool_result` | Tool execution result | `tool_call_id`, `result`, `isError` |
|
|
309
|
+
| `tool_approval_requested` | High-risk tool needs approval | `tool_call_id`, `toolName`, `riskLevel`, `args` |
|
|
310
|
+
| `requires_action` | Execution paused for approval or AskUser answers | `kind`, `checkpoint`, `checkpointRef`, `questions` |
|
|
311
|
+
| `tool_skipped` | Tool execution skipped | `tool_call_id`, `toolName`, `reason` |
|
|
312
|
+
| `iteration_start` / `iteration_end` | Agent loop iteration lifecycle | `iteration`, `usage` |
|
|
313
|
+
| `subagent_event` | Forwarded subagent status | `subagentId`, `subagentType`, `phase` |
|
|
314
|
+
| `compression_start` / `compression_end` | Context compression lifecycle | `tokensBefore`, `tokensAfter`, `strategy` |
|
|
315
|
+
| `hook_evaluation` | Prompt-hook evaluation lifecycle | `hookName`, `phase`, `status` |
|
|
316
|
+
| `done` | Stream finished | `stopReason`, `modelStopReason`, `error`, `usage` |
|
|
316
317
|
|
|
317
318
|
### Session State Management
|
|
318
319
|
|
|
@@ -321,7 +322,7 @@ for await (const event of session.receive()) {
|
|
|
321
322
|
console.log(session.messages) // Message[]
|
|
322
323
|
|
|
323
324
|
// Check session status
|
|
324
|
-
console.log(session.status) // '
|
|
325
|
+
console.log(session.status) // 'active' | 'paused' | 'completed' | 'error' | 'archived'
|
|
325
326
|
|
|
326
327
|
// Get token usage
|
|
327
328
|
console.log(session.usage)
|
|
@@ -381,8 +382,8 @@ for await (const event of session.receive()) {
|
|
|
381
382
|
}
|
|
382
383
|
}
|
|
383
384
|
|
|
384
|
-
// Session now contains full conversation history
|
|
385
|
-
console.log(session.messages.length) //
|
|
385
|
+
// Session now contains the full conversation history plus the system prompt
|
|
386
|
+
console.log(session.messages.length) // 5 (system + 2 user + 2 assistant)
|
|
386
387
|
```
|
|
387
388
|
|
|
388
389
|
### Resuming Sessions
|
|
@@ -419,7 +420,7 @@ for await (const event of resumed.receive()) {
|
|
|
419
420
|
}
|
|
420
421
|
```
|
|
421
422
|
|
|
422
|
-
### Session
|
|
423
|
+
### Session Utilities
|
|
423
424
|
|
|
424
425
|
```typescript
|
|
425
426
|
// Add message manually
|
|
@@ -431,8 +432,9 @@ session.addMessage({
|
|
|
431
432
|
// Save session state manually
|
|
432
433
|
await session.save()
|
|
433
434
|
|
|
434
|
-
//
|
|
435
|
-
|
|
435
|
+
// Advanced: direct message mutation is allowed, but prefer snapshots/checkpoints
|
|
436
|
+
// when you need reproducible restore flows.
|
|
437
|
+
session.messages.push({ role: 'assistant', content: 'Synthetic entry' })
|
|
436
438
|
```
|
|
437
439
|
|
|
438
440
|
## 🤖 Agent Configuration
|
|
@@ -477,7 +479,9 @@ interface AgentOptions {
|
|
|
477
479
|
agent.setModel({ provider: 'openai', modelId: 'gpt-4o-mini' })
|
|
478
480
|
|
|
479
481
|
// Switch to another concrete model client instance
|
|
480
|
-
const otherModelClient = createModel({
|
|
482
|
+
const otherModelClient = createModel({
|
|
483
|
+
adapter: createOpenAIAdapter({ defaultModelId: 'gpt-4o' }),
|
|
484
|
+
})
|
|
481
485
|
agent.setModel(otherModelClient)
|
|
482
486
|
```
|
|
483
487
|
|
|
@@ -504,21 +508,22 @@ await sessionManager.destroy('session-id')
|
|
|
504
508
|
|
|
505
509
|
GoatChain SDK exports the following built-in tools:
|
|
506
510
|
|
|
507
|
-
| Tool Class
|
|
508
|
-
|
|
|
509
|
-
| `ReadTool`
|
|
510
|
-
| `WriteTool`
|
|
511
|
-
| `EditTool`
|
|
512
|
-
| `GlobTool`
|
|
513
|
-
| `GrepTool`
|
|
514
|
-
| `BashTool`
|
|
515
|
-
| `WebSearchTool`
|
|
516
|
-
| `WebFetchTool`
|
|
517
|
-
| `
|
|
518
|
-
| `
|
|
519
|
-
| `
|
|
520
|
-
| `
|
|
521
|
-
| `
|
|
511
|
+
| Tool Class | Runtime Name | Category | Purpose |
|
|
512
|
+
| ------------------- | ----------------- | ----------- | ------------------------------------------------------------------------- |
|
|
513
|
+
| `ReadTool` | `Read` | File | Read file content (text, binary metadata, and selected converted formats) |
|
|
514
|
+
| `WriteTool` | `Write` | File | Create or overwrite files |
|
|
515
|
+
| `EditTool` | `Edit` | File | In-place text replacement edits |
|
|
516
|
+
| `GlobTool` | `Glob` | File/Search | Find files by glob pattern |
|
|
517
|
+
| `GrepTool` | `Grep` | File/Search | Search file contents by pattern |
|
|
518
|
+
| `BashTool` | `Bash` | Command | Execute shell commands |
|
|
519
|
+
| `WebSearchTool` | `WebSearch` | Web | Search the web (e.g. via Serper API) |
|
|
520
|
+
| `WebFetchTool` | `WebFetch` | Web | Fetch and extract content from a specific URL |
|
|
521
|
+
| `TaskTool` | `Task` | Subagent | Run a registered subagent task (for example Explore) |
|
|
522
|
+
| `TodoWriteTool` | `TodoWrite` | Planning | Manage structured todo lists |
|
|
523
|
+
| `TodoPlanTool` | `TodoPlan` | Planning | Create/update planning todos for plan flows |
|
|
524
|
+
| `AskUserTool` | `AskUserQuestion` | Interaction | Ask the user structured follow-up questions |
|
|
525
|
+
| `EnterPlanModeTool` | `EnterPlanMode` | Mode | Enter plan mode |
|
|
526
|
+
| `ExitPlanModeTool` | `ExitPlanMode` | Mode | Exit plan mode |
|
|
522
527
|
|
|
523
528
|
```typescript
|
|
524
529
|
import {
|
|
@@ -621,14 +626,14 @@ tools.register(
|
|
|
621
626
|
|
|
622
627
|
**How each file tool uses `cwd`:**
|
|
623
628
|
|
|
624
|
-
| Tool
|
|
625
|
-
|
|
|
626
|
-
| `ReadTool`
|
|
627
|
-
| `WriteTool` | Writes/overwrites files
|
|
628
|
-
| `EditTool`
|
|
629
|
-
| `GlobTool`
|
|
630
|
-
| `GrepTool`
|
|
631
|
-
| `BashTool`
|
|
629
|
+
| Tool | What it does | How `cwd` is applied | Per-call override | Extra sandbox options |
|
|
630
|
+
| ----------- | ------------------------------------------------- | ---------------------------------------- | -------------------------------------- | ------------------------------------------------------- |
|
|
631
|
+
| `ReadTool` | Reads files (and some converted formats) | Relative `file_path` resolves from `cwd` | `file_path` can be absolute | `allowedDirectory`, `fileBlacklist`, `disableBlacklist` |
|
|
632
|
+
| `WriteTool` | Writes/overwrites files | Relative `file_path` resolves from `cwd` | `file_path` can be absolute | `allowedDirectory`, `fileBlacklist`, `disableBlacklist` |
|
|
633
|
+
| `EditTool` | Replaces `old_string` with `new_string` in a file | Relative `file_path` resolves from `cwd` | `file_path` can be absolute | `fileBlacklist`, `disableBlacklist` |
|
|
634
|
+
| `GlobTool` | Finds files by pattern | Search root defaults to `cwd` | `path` argument can change search root | `fileBlacklist`, `disableBlacklist` |
|
|
635
|
+
| `GrepTool` | Searches text content in files | Search runs under `cwd` | `path` argument narrows search scope | `fileBlacklist`, `disableBlacklist` |
|
|
636
|
+
| `BashTool` | Runs shell commands | Commands execute in `cwd` | `workdir` argument overrides per call | None |
|
|
632
637
|
|
|
633
638
|
**Directory & Protection Options:**
|
|
634
639
|
|
|
@@ -741,26 +746,41 @@ interface AgentHooks {
|
|
|
741
746
|
userPromptSubmit?:
|
|
742
747
|
| ((ctx: UserPromptSubmitContext) => Promise<UserPromptSubmitResult>)
|
|
743
748
|
| PromptHookEntry
|
|
744
|
-
| Array<
|
|
749
|
+
| Array<
|
|
750
|
+
| ((ctx: UserPromptSubmitContext) => Promise<UserPromptSubmitResult>)
|
|
751
|
+
| PromptHookEntry
|
|
752
|
+
>
|
|
745
753
|
|
|
746
754
|
// Tool lifecycle
|
|
747
755
|
// - Can modify tool call with modifiedToolCall
|
|
748
756
|
preToolUse?:
|
|
749
757
|
| ((ctx: ToolHookContext) => Promise<PreToolUseResult | void>)
|
|
750
758
|
| PromptHookEntry
|
|
751
|
-
| Array<
|
|
759
|
+
| Array<
|
|
760
|
+
| ((ctx: ToolHookContext) => Promise<PreToolUseResult | void>)
|
|
761
|
+
| PromptHookEntry
|
|
762
|
+
>
|
|
752
763
|
permissionRequest?:
|
|
753
764
|
| ((ctx: ToolHookContext) => Promise<PermissionRequestResult>)
|
|
754
765
|
| PromptHookEntry
|
|
755
|
-
| Array<
|
|
766
|
+
| Array<
|
|
767
|
+
| ((ctx: ToolHookContext) => Promise<PermissionRequestResult>)
|
|
768
|
+
| PromptHookEntry
|
|
769
|
+
>
|
|
756
770
|
postToolUse?:
|
|
757
771
|
| ((ctx: ToolHookContext, result: unknown) => Promise<void>)
|
|
758
772
|
| PromptHookEntry
|
|
759
|
-
| Array<
|
|
773
|
+
| Array<
|
|
774
|
+
| ((ctx: ToolHookContext, result: unknown) => Promise<void>)
|
|
775
|
+
| PromptHookEntry
|
|
776
|
+
>
|
|
760
777
|
postToolUseFailure?:
|
|
761
778
|
| ((ctx: ToolHookContext, error: Error) => Promise<void>)
|
|
762
779
|
| PromptHookEntry
|
|
763
|
-
| Array<
|
|
780
|
+
| Array<
|
|
781
|
+
| ((ctx: ToolHookContext, error: Error) => Promise<void>)
|
|
782
|
+
| PromptHookEntry
|
|
783
|
+
>
|
|
764
784
|
|
|
765
785
|
// Subagent lifecycle (used by parallel task/subagent middleware)
|
|
766
786
|
subagentStart?: (ctx: SubagentStartContext) => Promise<void>
|
|
@@ -997,7 +1017,12 @@ const agent = new Agent({
|
|
|
997
1017
|
name: 'MyAgent',
|
|
998
1018
|
systemPrompt: 'You are helpful.',
|
|
999
1019
|
model,
|
|
1000
|
-
tools:
|
|
1020
|
+
tools: (() => {
|
|
1021
|
+
const tools = new ToolRegistry()
|
|
1022
|
+
tools.register(new ReadTool())
|
|
1023
|
+
tools.register(new WriteTool())
|
|
1024
|
+
return tools
|
|
1025
|
+
})(),
|
|
1001
1026
|
})
|
|
1002
1027
|
|
|
1003
1028
|
// Create session with hooks
|
|
@@ -1232,7 +1257,7 @@ const session = await agent.createSession({
|
|
|
1232
1257
|
|
|
1233
1258
|
### Tool Context
|
|
1234
1259
|
|
|
1235
|
-
The `toolContext` parameter in `send()` and `receive()`
|
|
1260
|
+
The `toolContext` parameter in `send()` and `receive()` is used for approval state and AskUser resume data:
|
|
1236
1261
|
|
|
1237
1262
|
```typescript
|
|
1238
1263
|
session.send('Do something risky', {
|
|
@@ -1245,8 +1270,14 @@ session.send('Do something risky', {
|
|
|
1245
1270
|
tool_call_id_456: { approved: false, reason: 'Too dangerous' },
|
|
1246
1271
|
},
|
|
1247
1272
|
},
|
|
1248
|
-
|
|
1249
|
-
|
|
1273
|
+
askUser: {
|
|
1274
|
+
answers: {
|
|
1275
|
+
tool_call_id_789: {
|
|
1276
|
+
framework: 'React',
|
|
1277
|
+
styling: 'Tailwind CSS',
|
|
1278
|
+
},
|
|
1279
|
+
},
|
|
1280
|
+
},
|
|
1250
1281
|
},
|
|
1251
1282
|
})
|
|
1252
1283
|
```
|
|
@@ -1263,7 +1294,7 @@ outer:before → inner:before → exec (model.stream) → inner:after → outer:
|
|
|
1263
1294
|
|
|
1264
1295
|
```typescript
|
|
1265
1296
|
// Add named middleware (recommended)
|
|
1266
|
-
agent.use(async (state, next) => {
|
|
1297
|
+
await agent.use(async (state, next) => {
|
|
1267
1298
|
const start = Date.now()
|
|
1268
1299
|
console.log(`[${state.iteration}] Before model call`)
|
|
1269
1300
|
|
|
@@ -1280,7 +1311,7 @@ agent.removeMiddleware('logging')
|
|
|
1280
1311
|
console.log(agent.middlewareNames) // ['logging', 'compression', ...]
|
|
1281
1312
|
|
|
1282
1313
|
// Use unsubscribe function
|
|
1283
|
-
const unsubscribe = agent.use(middleware, 'temp')
|
|
1314
|
+
const unsubscribe = await agent.use(middleware, 'temp')
|
|
1284
1315
|
unsubscribe() // Remove middleware
|
|
1285
1316
|
```
|
|
1286
1317
|
|
|
@@ -1294,10 +1325,10 @@ Adds planning phase before execution:
|
|
|
1294
1325
|
import { createPlanModeMiddleware } from 'goatchain'
|
|
1295
1326
|
|
|
1296
1327
|
// Automatically named 'plan_mode'
|
|
1297
|
-
agent.use(createPlanModeMiddleware())
|
|
1328
|
+
await agent.use(createPlanModeMiddleware())
|
|
1298
1329
|
|
|
1299
1330
|
// With custom configuration
|
|
1300
|
-
agent.use(
|
|
1331
|
+
await agent.use(
|
|
1301
1332
|
createPlanModeMiddleware({
|
|
1302
1333
|
name: 'my-plan', // Custom name
|
|
1303
1334
|
planPrompt: 'Create a detailed plan...', // Custom prompt
|
|
@@ -1307,35 +1338,36 @@ agent.use(
|
|
|
1307
1338
|
|
|
1308
1339
|
#### Context Compression Middleware
|
|
1309
1340
|
|
|
1310
|
-
Automatically compresses context when
|
|
1341
|
+
Automatically compresses context from the full raw transcript when the prompt approaches the model context window. The middleware now:
|
|
1342
|
+
|
|
1343
|
+
- reuses any persisted rolling summary first
|
|
1344
|
+
- removes old `tool` messages before touching the current round
|
|
1345
|
+
- preserves the last user round
|
|
1346
|
+
- performs at most one AI summary pass per overflow event
|
|
1347
|
+
- guarantees the final prompt stays within `contextLength` or fails locally before the model call
|
|
1348
|
+
- can emit per-stage snapshots in the large E2E example for inspection
|
|
1311
1349
|
|
|
1312
1350
|
```typescript
|
|
1313
1351
|
import { createContextCompressionMiddleware } from 'goatchain'
|
|
1314
1352
|
|
|
1315
1353
|
// Automatically named 'context_compression'
|
|
1316
|
-
agent.use(
|
|
1354
|
+
await agent.use(
|
|
1317
1355
|
createContextCompressionMiddleware({
|
|
1318
|
-
|
|
1319
|
-
protectedTurns: 2, // Keep last 2 conversation turns
|
|
1320
|
-
model: model,
|
|
1321
|
-
stateStore: agent.stateStore,
|
|
1322
|
-
toolCompressionTarget: 0.45, // Compress to 45% of maxTokens
|
|
1323
|
-
minKeepToolResults: 5, // Keep last 5 tool results
|
|
1324
|
-
// Optional: Enable detailed logging
|
|
1325
|
-
enableLogging: true,
|
|
1326
|
-
logFilePath: 'compression-logs.jsonl',
|
|
1356
|
+
contextLength: 128000,
|
|
1327
1357
|
}),
|
|
1328
1358
|
)
|
|
1329
1359
|
```
|
|
1330
1360
|
|
|
1331
|
-
|
|
1361
|
+
The large E2E example writes `round-N/stage1.json` through `stage4.json` under `examples/output/context-compression-large-e2e/` by default, so you can inspect each compression step directly.
|
|
1362
|
+
|
|
1363
|
+
See [`src/spec/middleware.md`](./src/spec/middleware.md) for the full middleware and compression spec.
|
|
1332
1364
|
|
|
1333
1365
|
### Custom Middleware Examples
|
|
1334
1366
|
|
|
1335
1367
|
#### Logging Middleware
|
|
1336
1368
|
|
|
1337
1369
|
```typescript
|
|
1338
|
-
agent.use(async (state, next) => {
|
|
1370
|
+
await agent.use(async (state, next) => {
|
|
1339
1371
|
console.log(`Iteration ${state.iteration}:`, {
|
|
1340
1372
|
messages: state.messages.length,
|
|
1341
1373
|
pendingTools: state.pendingToolCalls.length,
|
|
@@ -1355,7 +1387,7 @@ agent.use(async (state, next) => {
|
|
|
1355
1387
|
#### Error Handling Middleware
|
|
1356
1388
|
|
|
1357
1389
|
```typescript
|
|
1358
|
-
agent.use(async (state, next) => {
|
|
1390
|
+
await agent.use(async (state, next) => {
|
|
1359
1391
|
try {
|
|
1360
1392
|
return await next(state)
|
|
1361
1393
|
} catch (error) {
|
|
@@ -1375,7 +1407,7 @@ import { RateLimiter } from 'some-rate-limiter'
|
|
|
1375
1407
|
|
|
1376
1408
|
const limiter = new RateLimiter({ requestsPerMinute: 60 })
|
|
1377
1409
|
|
|
1378
|
-
agent.use(async (state, next) => {
|
|
1410
|
+
await agent.use(async (state, next) => {
|
|
1379
1411
|
await limiter.acquire()
|
|
1380
1412
|
return next(state)
|
|
1381
1413
|
}, 'rate-limiter')
|
|
@@ -1384,7 +1416,7 @@ agent.use(async (state, next) => {
|
|
|
1384
1416
|
#### Custom Retry Middleware
|
|
1385
1417
|
|
|
1386
1418
|
```typescript
|
|
1387
|
-
agent.use(async (state, next) => {
|
|
1419
|
+
await agent.use(async (state, next) => {
|
|
1388
1420
|
let retries = 3
|
|
1389
1421
|
|
|
1390
1422
|
while (retries > 0) {
|
|
@@ -1414,10 +1446,12 @@ interface AgentLoopState {
|
|
|
1414
1446
|
iteration: number // Current iteration number
|
|
1415
1447
|
pendingToolCalls: ToolCallWithResult[] // Pending tool executions
|
|
1416
1448
|
currentResponse: string // Current LLM response
|
|
1449
|
+
currentThinking?: string // Current reasoning content, if the model emits it
|
|
1417
1450
|
shouldContinue: boolean // Whether to continue loop
|
|
1418
1451
|
stopReason?: string // Reason for stopping
|
|
1419
|
-
usage
|
|
1452
|
+
usage: Usage // Cumulative token usage
|
|
1420
1453
|
error?: Error // Error if any
|
|
1454
|
+
metadata: Record<string, unknown> // Middleware/hook shared runtime data
|
|
1421
1455
|
}
|
|
1422
1456
|
```
|
|
1423
1457
|
|
|
@@ -1540,8 +1574,15 @@ Implement custom state stores:
|
|
|
1540
1574
|
interface StateStore {
|
|
1541
1575
|
deleteOnComplete: boolean
|
|
1542
1576
|
|
|
1577
|
+
save<T>(sessionId: string, key: string, data: T): Promise<void>
|
|
1578
|
+
load<T>(sessionId: string, key: string): Promise<T | undefined>
|
|
1579
|
+
delete(sessionId: string, key: string): Promise<void>
|
|
1580
|
+
listKeys(sessionId: string): Promise<string[]>
|
|
1581
|
+
listSessions(): Promise<string[]>
|
|
1582
|
+
|
|
1583
|
+
// Checkpoint helpers
|
|
1543
1584
|
saveCheckpoint(checkpoint: AgentLoopCheckpoint): Promise<void>
|
|
1544
|
-
loadCheckpoint(sessionId: string): Promise<AgentLoopCheckpoint |
|
|
1585
|
+
loadCheckpoint(sessionId: string): Promise<AgentLoopCheckpoint | undefined>
|
|
1545
1586
|
deleteCheckpoint(sessionId: string): Promise<void>
|
|
1546
1587
|
listCheckpoints(): Promise<AgentLoopCheckpoint[]>
|
|
1547
1588
|
}
|
|
@@ -1559,17 +1600,8 @@ interface AgentLoopCheckpoint {
|
|
|
1559
1600
|
### Manual Checkpoint Management
|
|
1560
1601
|
|
|
1561
1602
|
```typescript
|
|
1562
|
-
//
|
|
1563
|
-
|
|
1564
|
-
sessionId: session.id,
|
|
1565
|
-
messages: session.messages,
|
|
1566
|
-
iteration: 3,
|
|
1567
|
-
usage: session.usage,
|
|
1568
|
-
createdAt: Date.now(),
|
|
1569
|
-
updatedAt: Date.now(),
|
|
1570
|
-
})
|
|
1571
|
-
|
|
1572
|
-
// Load checkpoint
|
|
1603
|
+
// Prefer SDK-managed checkpoints during session.receive().
|
|
1604
|
+
// You can still inspect or clean them up manually:
|
|
1573
1605
|
const checkpoint = await stateStore.loadCheckpoint('session-id')
|
|
1574
1606
|
|
|
1575
1607
|
// List all checkpoints
|
|
@@ -1649,7 +1681,7 @@ for await (const event of session.receive()) {
|
|
|
1649
1681
|
if (event.type === 'text_delta') {
|
|
1650
1682
|
process.stdout.write(event.delta)
|
|
1651
1683
|
} else if (event.type === 'tool_call_start') {
|
|
1652
|
-
console.log(`\nCalling: ${event.
|
|
1684
|
+
console.log(`\nCalling: ${event.toolName}`)
|
|
1653
1685
|
} else if (event.type === 'tool_result') {
|
|
1654
1686
|
console.log(`Result: ${JSON.stringify(event.result).slice(0, 100)}...`)
|
|
1655
1687
|
}
|
|
@@ -1730,7 +1762,7 @@ const agent = new Agent({
|
|
|
1730
1762
|
})
|
|
1731
1763
|
|
|
1732
1764
|
// Add logging middleware
|
|
1733
|
-
agent.use(async (state, next) => {
|
|
1765
|
+
await agent.use(async (state, next) => {
|
|
1734
1766
|
console.log(`\n=== Iteration ${state.iteration} ===`)
|
|
1735
1767
|
const result = await next(state)
|
|
1736
1768
|
console.log(`Tokens used: ${result.usage?.totalTokens || 0}`)
|
|
@@ -1738,7 +1770,7 @@ agent.use(async (state, next) => {
|
|
|
1738
1770
|
}, 'logger')
|
|
1739
1771
|
|
|
1740
1772
|
// Add plan mode
|
|
1741
|
-
agent.use(createPlanModeMiddleware())
|
|
1773
|
+
await agent.use(createPlanModeMiddleware())
|
|
1742
1774
|
|
|
1743
1775
|
const session = await agent.createSession()
|
|
1744
1776
|
session.send('Create a todo list app with React and TypeScript')
|
|
@@ -1804,7 +1836,12 @@ import {
|
|
|
1804
1836
|
Agent,
|
|
1805
1837
|
createModel,
|
|
1806
1838
|
createOpenAIAdapter,
|
|
1807
|
-
|
|
1839
|
+
ToolRegistry,
|
|
1840
|
+
ReadTool,
|
|
1841
|
+
WriteTool,
|
|
1842
|
+
EditTool,
|
|
1843
|
+
GlobTool,
|
|
1844
|
+
GrepTool,
|
|
1808
1845
|
} from 'goatchain'
|
|
1809
1846
|
|
|
1810
1847
|
const model = createModel({
|
|
@@ -1814,11 +1851,18 @@ const model = createModel({
|
|
|
1814
1851
|
}),
|
|
1815
1852
|
})
|
|
1816
1853
|
|
|
1854
|
+
const tools = new ToolRegistry()
|
|
1855
|
+
tools.register(new ReadTool())
|
|
1856
|
+
tools.register(new WriteTool())
|
|
1857
|
+
tools.register(new EditTool())
|
|
1858
|
+
tools.register(new GlobTool())
|
|
1859
|
+
tools.register(new GrepTool())
|
|
1860
|
+
|
|
1817
1861
|
const agent = new Agent({
|
|
1818
1862
|
name: 'File Agent',
|
|
1819
1863
|
systemPrompt: 'You are a file management assistant.',
|
|
1820
1864
|
model,
|
|
1821
|
-
tools
|
|
1865
|
+
tools,
|
|
1822
1866
|
})
|
|
1823
1867
|
|
|
1824
1868
|
// Set working directory at session creation
|
|
@@ -1925,7 +1969,7 @@ for await (const event of session.receive()) {
|
|
|
1925
1969
|
if (event.type === 'text_delta') {
|
|
1926
1970
|
process.stdout.write(event.delta)
|
|
1927
1971
|
} else if (event.type === 'tool_call_start') {
|
|
1928
|
-
console.log(`\n[Tool] ${event.
|
|
1972
|
+
console.log(`\n[Tool] ${event.toolName}`)
|
|
1929
1973
|
}
|
|
1930
1974
|
}
|
|
1931
1975
|
```
|
|
@@ -2114,7 +2158,7 @@ session.setCwd('/path/to/project')
|
|
|
2114
2158
|
#### Properties
|
|
2115
2159
|
|
|
2116
2160
|
- `id: string` - Session ID
|
|
2117
|
-
- `status: SessionStatus` - Session status ('
|
|
2161
|
+
- `status: SessionStatus` - Session status (`'active' | 'paused' | 'completed' | 'error' | 'archived'`)
|
|
2118
2162
|
- `messages: Message[]` - Message history
|
|
2119
2163
|
- `usage: Usage` - Token usage statistics
|
|
2120
2164
|
- `createdAt: number` - Creation timestamp
|
|
@@ -2125,9 +2169,12 @@ session.setCwd('/path/to/project')
|
|
|
2125
2169
|
```typescript
|
|
2126
2170
|
interface Message {
|
|
2127
2171
|
role: 'system' | 'user' | 'assistant' | 'tool'
|
|
2128
|
-
content:
|
|
2129
|
-
|
|
2130
|
-
|
|
2172
|
+
content: MessageContent
|
|
2173
|
+
reasoning_content?: string // Assistant messages
|
|
2174
|
+
tool_calls?: ToolCall[] // Assistant messages
|
|
2175
|
+
tool_call_id?: string // Tool messages
|
|
2176
|
+
name?: string
|
|
2177
|
+
isError?: boolean // Tool messages
|
|
2131
2178
|
}
|
|
2132
2179
|
```
|
|
2133
2180
|
|
|
@@ -2145,10 +2192,17 @@ interface Usage {
|
|
|
2145
2192
|
|
|
2146
2193
|
```typescript
|
|
2147
2194
|
type AgentEvent =
|
|
2195
|
+
| TextStartEvent
|
|
2148
2196
|
| TextDeltaEvent
|
|
2197
|
+
| TextEndEvent
|
|
2149
2198
|
| ToolCallStartEvent
|
|
2150
2199
|
| ToolCallDeltaEvent
|
|
2151
2200
|
| ToolCallEndEvent
|
|
2201
|
+
| ToolOutputStartEvent
|
|
2202
|
+
| ToolOutputDeltaEvent
|
|
2203
|
+
| ToolApprovalRequestedEvent
|
|
2204
|
+
| RequiresActionEvent
|
|
2205
|
+
| ToolSkippedEvent
|
|
2152
2206
|
| ToolResultEvent
|
|
2153
2207
|
| ThinkingStartEvent
|
|
2154
2208
|
| ThinkingDeltaEvent
|
|
@@ -2156,7 +2210,6 @@ type AgentEvent =
|
|
|
2156
2210
|
| IterationStartEvent
|
|
2157
2211
|
| IterationEndEvent
|
|
2158
2212
|
| DoneEvent
|
|
2159
|
-
| ErrorEvent
|
|
2160
2213
|
|
|
2161
2214
|
interface TextDeltaEvent {
|
|
2162
2215
|
type: 'text_delta'
|
|
@@ -2165,8 +2218,15 @@ interface TextDeltaEvent {
|
|
|
2165
2218
|
|
|
2166
2219
|
interface ToolCallStartEvent {
|
|
2167
2220
|
type: 'tool_call_start'
|
|
2168
|
-
|
|
2169
|
-
|
|
2221
|
+
callId: string
|
|
2222
|
+
toolName?: string
|
|
2223
|
+
}
|
|
2224
|
+
|
|
2225
|
+
interface RequiresActionEvent {
|
|
2226
|
+
type: 'requires_action'
|
|
2227
|
+
kind: 'tool_approval' | 'ask_user'
|
|
2228
|
+
checkpoint?: AgentLoopCheckpoint
|
|
2229
|
+
checkpointRef?: { sessionId: string }
|
|
2170
2230
|
}
|
|
2171
2231
|
|
|
2172
2232
|
interface ToolResultEvent {
|
|
@@ -2178,6 +2238,7 @@ interface ToolResultEvent {
|
|
|
2178
2238
|
|
|
2179
2239
|
interface DoneEvent {
|
|
2180
2240
|
type: 'done'
|
|
2241
|
+
finalResponse?: string
|
|
2181
2242
|
stopReason:
|
|
2182
2243
|
| 'max_iterations'
|
|
2183
2244
|
| 'final_response'
|
|
@@ -2185,6 +2246,13 @@ interface DoneEvent {
|
|
|
2185
2246
|
| 'cancelled'
|
|
2186
2247
|
| 'approval_required'
|
|
2187
2248
|
| 'max_follow_ups'
|
|
2249
|
+
modelStopReason?: 'tool_call' | 'final' | 'length' | 'error' | 'cancelled'
|
|
2250
|
+
error?: {
|
|
2251
|
+
code?: string
|
|
2252
|
+
message: string
|
|
2253
|
+
status?: number
|
|
2254
|
+
retryable?: boolean
|
|
2255
|
+
}
|
|
2188
2256
|
usage?: Usage
|
|
2189
2257
|
}
|
|
2190
2258
|
```
|
package/dist/index.d.ts
CHANGED
|
@@ -37,4 +37,4 @@ export { AskUserTool, BashTool, EditTool, GlobTool, GrepTool, ReadTool, softWrap
|
|
|
37
37
|
export type { BashArgs, BashResult, RiskLevel, ToolApprovalResult, ToolApprovalSettings, ToolApprovalStrategy, ToolExecutionContext, ToolExecutionContextInput, ToolRunUsage, } from './tool';
|
|
38
38
|
export type { AskUserArgs, AskUserResult, DeliveryMode, EditArgs, EditResult, FetchFormat, GlobArgs, GlobResult, GrepArgs, GrepOutputMode, GrepResult, Question, QuestionOption, ReadArgs, ReadResult, TodoItem, TodoPlanArgs, TodoPlanResult, TodoStatus, TodoWriteArgs, TodoWriteResult, WebFetchArgs, WebFetchResult, WebSearchArgs, WebSearchResult, WriteArgs, WriteResult, } from './tool';
|
|
39
39
|
export * from './tool/converters';
|
|
40
|
-
export type { AgentEvent, AgentEventType, AgentLoopCheckpoint, AssistantMessage, BaseEvent, CallModelOnceOptions, CallModelOnceResult, CallToolResult, CompletionAssessedEvent, CompressionEndEvent, CompressionStartEvent, ContentBlock, DoneEvent, HookEvaluationEvent, ImageContent, IterationEndEvent, IterationStartEvent, JSONSchemaProperty, Message, MessageContent, MessageRole, SystemMessage, TextContent, TextDeltaEvent, TextEndEvent, TextStartEvent, ThinkingDeltaEvent, Tool, ToolCall, ToolCallDeltaEvent, ToolCallEndEvent, ToolCallStartEvent, ToolMessage, ToolResultEvent, Usage, UserMessage, } from './types';
|
|
40
|
+
export type { AgentEvent, AgentEventType, AgentLoopCheckpoint, AssistantMessage, BaseEvent, CallModelOnceOptions, CallModelOnceResult, CallToolResult, CompletionAssessedEvent, CompressionEndEvent, CompressionStartEvent, ContentBlock, DoneEvent, HookEvaluationEvent, ImageContent, IterationEndEvent, IterationStartEvent, JSONSchemaProperty, Message, MessageContent, MessageRole, SessionSnapshot, SystemMessage, TextContent, TextDeltaEvent, TextEndEvent, TextStartEvent, ThinkingDeltaEvent, Tool, ToolCall, ToolCallDeltaEvent, ToolCallEndEvent, ToolCallStartEvent, ToolMessage, ToolResultEvent, Usage, UserMessage, } from './types';
|