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 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
- topP?: number // Nucleus sampling parameter
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 all file operation tools (Read, Write, Edit, Glob, Grep, Bash, AstGrepSearch, AstGrepReplace):
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.name}`)
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 | Description | Key Fields |
303
- | ----------------- | --------------------------- | --------------------- |
304
- | `iteration_start` | Agent loop iteration begins | `iteration` |
305
- | `text_delta` | Partial text response | `delta` |
306
- | `thinking_start` | Reasoning phase begins | - |
307
- | `thinking_delta` | Reasoning content | `delta` |
308
- | `thinking_end` | Reasoning phase ends | - |
309
- | `tool_call_start` | Tool invocation begins | `name`, `id` |
310
- | `tool_call_delta` | Tool arguments stream | `delta` |
311
- | `tool_call_end` | Tool call complete | `name`, `args` |
312
- | `tool_result` | Tool execution result | `result`, `error` |
313
- | `iteration_end` | Iteration complete | `usage`, `iteration` |
314
- | `done` | Stream finished | `stopReason`, `usage` |
315
- | `error` | Error occurred | `error` |
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) // 'idle' | 'running' | 'completed' | 'error'
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) // 4 (2 user, 2 assistant)
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 Lifecycle Hooks
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
- // Clear session history
435
- session.messages = []
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({ adapter: createOpenAIAdapter({ defaultModelId: 'gpt-4o' }) })
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 | Runtime Name | Category | Purpose |
508
- | --- | --- | --- | --- |
509
- | `ReadTool` | `Read` | File | Read file content (text, binary metadata, and selected converted formats) |
510
- | `WriteTool` | `Write` | File | Create or overwrite files |
511
- | `EditTool` | `Edit` | File | In-place text replacement edits |
512
- | `GlobTool` | `Glob` | File/Search | Find files by glob pattern |
513
- | `GrepTool` | `Grep` | File/Search | Search file contents by pattern |
514
- | `BashTool` | `Bash` | Command | Execute shell commands |
515
- | `WebSearchTool` | `WebSearch` | Web | Search the web (e.g. via Serper API) |
516
- | `WebFetchTool` | `WebFetch` | Web | Fetch and extract content from a specific URL |
517
- | `TodoWriteTool` | `TodoWrite` | Planning | Manage structured todo lists |
518
- | `TodoPlanTool` | `TodoPlan` | Planning | Create/update planning todos for plan flows |
519
- | `AskUserTool` | `AskUserQuestion` | Interaction | Ask the user structured follow-up questions |
520
- | `EnterPlanModeTool` | `EnterPlanMode` | Mode | Enter plan mode |
521
- | `ExitPlanModeTool` | `ExitPlanMode` | Mode | Exit plan mode |
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 | What it does | How `cwd` is applied | Per-call override | Extra sandbox options |
625
- | --- | --- | --- | --- | --- |
626
- | `ReadTool` | Reads files (and some converted formats) | Relative `file_path` resolves from `cwd` | `file_path` can be absolute | `allowedDirectory`, `fileBlacklist`, `disableBlacklist` |
627
- | `WriteTool` | Writes/overwrites files | Relative `file_path` resolves from `cwd` | `file_path` can be absolute | `allowedDirectory`, `fileBlacklist`, `disableBlacklist` |
628
- | `EditTool` | Replaces `old_string` with `new_string` in a file | Relative `file_path` resolves from `cwd` | `file_path` can be absolute | `fileBlacklist`, `disableBlacklist` |
629
- | `GlobTool` | Finds files by pattern | Search root defaults to `cwd` | `path` argument can change search root | `fileBlacklist`, `disableBlacklist` |
630
- | `GrepTool` | Searches text content in files | Search runs under `cwd` | `path` argument narrows search scope | `fileBlacklist`, `disableBlacklist` |
631
- | `BashTool` | Runs shell commands | Commands execute in `cwd` | `workdir` argument overrides per call | None |
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<((ctx: UserPromptSubmitContext) => Promise<UserPromptSubmitResult>) | PromptHookEntry>
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<((ctx: ToolHookContext) => Promise<PreToolUseResult | void>) | PromptHookEntry>
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<((ctx: ToolHookContext) => Promise<PermissionRequestResult>) | PromptHookEntry>
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<((ctx: ToolHookContext, result: unknown) => Promise<void>) | PromptHookEntry>
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<((ctx: ToolHookContext, error: Error) => Promise<void>) | PromptHookEntry>
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: new ToolRegistry().register(new ReadTool()).register(new WriteTool()),
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()` allows passing additional context:
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
- // Your custom context
1249
- custom: { userId: '123', environment: 'production' },
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 token limit is reached using a two-stage strategy:
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
- maxTokens: 128000,
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
- See [Context Compression Logging Guide](./docs/context-compression-logging.md) for details on monitoring compression behavior.
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?: Usage // Token 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 | null>
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
- // Save checkpoint manually
1563
- await stateStore.saveCheckpoint({
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.name}`)
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
- createBuiltinTools,
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: createBuiltinTools(), // All file tools included
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.name}`)
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 ('idle' | 'running' | 'completed' | 'error')
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: string | ToolCall[] | ToolResult[]
2129
- name?: string // For tool messages
2130
- toolCallId?: string // For tool messages
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
- id: string
2169
- name: string
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';