goatchain 0.0.29 → 0.0.31
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 +413 -116
- package/dist/acp-adapter/history-normalizer.d.ts +10 -0
- package/dist/acp-adapter/index.d.ts +2 -0
- package/dist/acp-adapter/types.d.ts +4 -0
- package/dist/agent/agent.d.ts +14 -3
- package/dist/agent/hooks/index.d.ts +1 -1
- package/dist/agent/hooks/manager.d.ts +18 -1
- package/dist/agent/hooks/prompt-executor.d.ts +28 -0
- package/dist/agent/hooks/types.d.ts +32 -6
- package/dist/agent/index.d.ts +1 -1
- package/dist/agent/middleware.d.ts +10 -2
- package/dist/agent/types.d.ts +12 -0
- package/dist/index.d.ts +10 -10
- package/dist/index.js +492 -482
- package/dist/middleware/contextCompressionMiddleware.d.ts +22 -161
- package/dist/middleware/longRunningMiddleware.d.ts +6 -0
- package/dist/middleware/parallelSubagentMiddleware.d.ts +7 -1
- package/dist/model/anthropic/createAnthropicAdapter.d.ts +5 -0
- package/dist/session/executors/ToolExecutor.d.ts +4 -0
- package/dist/session/index.d.ts +1 -0
- package/dist/session/session.d.ts +36 -3
- package/dist/session/types/index.d.ts +1 -0
- package/dist/session/types/messageQueue.d.ts +29 -0
- package/dist/session/utils/MessageQueue.d.ts +23 -0
- package/dist/state/types.d.ts +36 -26
- package/dist/types/common.d.ts +12 -0
- package/dist/types/event.d.ts +63 -2
- package/dist/types/index.d.ts +1 -0
- package/dist/types/snapshot.d.ts +11 -0
- package/package.json +22 -22
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,19 +116,25 @@ 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
|
|
122
|
+
messageQueueConfig?: {
|
|
123
|
+
autoProcessQueue?: boolean // Auto-process queued messages (default: true)
|
|
124
|
+
maxQueueSize?: number // Optional queue length limit
|
|
125
|
+
}
|
|
120
126
|
requestParams?: {
|
|
121
127
|
temperature?: number // Model temperature
|
|
122
128
|
maxTokens?: number // Max output tokens
|
|
123
|
-
|
|
129
|
+
stop?: string[] // Optional stop sequences
|
|
130
|
+
[key: string]: unknown // Provider-specific request params
|
|
124
131
|
}
|
|
125
132
|
}
|
|
126
133
|
```
|
|
127
134
|
|
|
128
135
|
### Working Directory (CWD) Configuration
|
|
129
136
|
|
|
130
|
-
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`):
|
|
131
138
|
|
|
132
139
|
```typescript
|
|
133
140
|
// Set CWD when creating a session
|
|
@@ -161,13 +168,70 @@ session.send('What is the weather today?')
|
|
|
161
168
|
|
|
162
169
|
// Multiple messages in sequence
|
|
163
170
|
session.send('First question')
|
|
164
|
-
// Wait for response...
|
|
165
171
|
session.send('Follow-up question')
|
|
166
172
|
```
|
|
167
173
|
|
|
168
174
|
#### Send Options
|
|
169
175
|
|
|
170
|
-
You can pass options to `send()` to control tool execution, approval, and more:
|
|
176
|
+
You can pass options to `send()` to control priority, tool execution, approval, and more:
|
|
177
|
+
|
|
178
|
+
```typescript
|
|
179
|
+
// Higher priority messages are processed first (smaller number = higher priority)
|
|
180
|
+
session.send('Low priority', { priority: 10 })
|
|
181
|
+
session.send('High priority', { priority: 1 })
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
`send()` returns a message ID that can be used for queue management:
|
|
185
|
+
|
|
186
|
+
```typescript
|
|
187
|
+
const messageId = session.send('Can be cancelled later')
|
|
188
|
+
session.cancelQueuedMessage(messageId)
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
#### Message Queue
|
|
192
|
+
|
|
193
|
+
Session now supports queue-based messaging by default. You can enqueue multiple messages safely even while a previous `receive()` is running.
|
|
194
|
+
|
|
195
|
+
```typescript
|
|
196
|
+
const session = await agent.createSession()
|
|
197
|
+
|
|
198
|
+
session.send('First message')
|
|
199
|
+
session.send('Second message')
|
|
200
|
+
|
|
201
|
+
// Batch enqueue with priority
|
|
202
|
+
session.sendBatch([
|
|
203
|
+
{ input: 'Task A', priority: 2 },
|
|
204
|
+
{ input: 'Task B', priority: 1 },
|
|
205
|
+
])
|
|
206
|
+
|
|
207
|
+
// Inspect queue state
|
|
208
|
+
const queue = session.getQueueStatus()
|
|
209
|
+
console.log(queue.length, queue.isProcessing)
|
|
210
|
+
|
|
211
|
+
// Remove queued messages
|
|
212
|
+
session.clearQueue()
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
Manual queue mode:
|
|
216
|
+
|
|
217
|
+
```typescript
|
|
218
|
+
const session = await agent.createSession({
|
|
219
|
+
messageQueueConfig: { autoProcessQueue: false },
|
|
220
|
+
})
|
|
221
|
+
|
|
222
|
+
session.send('Message 1')
|
|
223
|
+
session.send('Message 2')
|
|
224
|
+
|
|
225
|
+
for await (const event of session.receive()) {
|
|
226
|
+
// only Message 1
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
for await (const event of session.receive()) {
|
|
230
|
+
// Message 2
|
|
231
|
+
}
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
Tool context and approval options still work as before:
|
|
171
235
|
|
|
172
236
|
```typescript
|
|
173
237
|
// Auto-approve all tools for this request
|
|
@@ -212,7 +276,7 @@ for await (const event of session.receive()) {
|
|
|
212
276
|
break
|
|
213
277
|
|
|
214
278
|
case 'tool_call_start':
|
|
215
|
-
console.log(`\nCalling tool: ${event.
|
|
279
|
+
console.log(`\nCalling tool: ${event.toolName ?? event.callId}`)
|
|
216
280
|
break
|
|
217
281
|
|
|
218
282
|
case 'tool_result':
|
|
@@ -228,30 +292,28 @@ for await (const event of session.receive()) {
|
|
|
228
292
|
console.log(`\nConversation done: ${event.stopReason}`)
|
|
229
293
|
console.log(`Total tokens: ${event.usage?.totalTokens}`)
|
|
230
294
|
break
|
|
231
|
-
|
|
232
|
-
case 'error':
|
|
233
|
-
console.error(`Error: ${event.error}`)
|
|
234
|
-
break
|
|
235
295
|
}
|
|
236
296
|
}
|
|
237
297
|
```
|
|
238
298
|
|
|
239
299
|
### Session Event Types
|
|
240
300
|
|
|
241
|
-
| Event Type
|
|
242
|
-
|
|
|
243
|
-
| `
|
|
244
|
-
| `text_delta`
|
|
245
|
-
| `thinking_start`
|
|
246
|
-
| `
|
|
247
|
-
| `
|
|
248
|
-
| `
|
|
249
|
-
| `
|
|
250
|
-
| `
|
|
251
|
-
| `
|
|
252
|
-
| `iteration_end`
|
|
253
|
-
| `
|
|
254
|
-
| `
|
|
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` |
|
|
255
317
|
|
|
256
318
|
### Session State Management
|
|
257
319
|
|
|
@@ -260,7 +322,7 @@ for await (const event of session.receive()) {
|
|
|
260
322
|
console.log(session.messages) // Message[]
|
|
261
323
|
|
|
262
324
|
// Check session status
|
|
263
|
-
console.log(session.status) // '
|
|
325
|
+
console.log(session.status) // 'active' | 'paused' | 'completed' | 'error' | 'archived'
|
|
264
326
|
|
|
265
327
|
// Get token usage
|
|
266
328
|
console.log(session.usage)
|
|
@@ -320,8 +382,8 @@ for await (const event of session.receive()) {
|
|
|
320
382
|
}
|
|
321
383
|
}
|
|
322
384
|
|
|
323
|
-
// Session now contains full conversation history
|
|
324
|
-
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)
|
|
325
387
|
```
|
|
326
388
|
|
|
327
389
|
### Resuming Sessions
|
|
@@ -358,7 +420,7 @@ for await (const event of resumed.receive()) {
|
|
|
358
420
|
}
|
|
359
421
|
```
|
|
360
422
|
|
|
361
|
-
### Session
|
|
423
|
+
### Session Utilities
|
|
362
424
|
|
|
363
425
|
```typescript
|
|
364
426
|
// Add message manually
|
|
@@ -370,8 +432,9 @@ session.addMessage({
|
|
|
370
432
|
// Save session state manually
|
|
371
433
|
await session.save()
|
|
372
434
|
|
|
373
|
-
//
|
|
374
|
-
|
|
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' })
|
|
375
438
|
```
|
|
376
439
|
|
|
377
440
|
## 🤖 Agent Configuration
|
|
@@ -416,7 +479,9 @@ interface AgentOptions {
|
|
|
416
479
|
agent.setModel({ provider: 'openai', modelId: 'gpt-4o-mini' })
|
|
417
480
|
|
|
418
481
|
// Switch to another concrete model client instance
|
|
419
|
-
const otherModelClient = createModel({
|
|
482
|
+
const otherModelClient = createModel({
|
|
483
|
+
adapter: createOpenAIAdapter({ defaultModelId: 'gpt-4o' }),
|
|
484
|
+
})
|
|
420
485
|
agent.setModel(otherModelClient)
|
|
421
486
|
```
|
|
422
487
|
|
|
@@ -443,21 +508,22 @@ await sessionManager.destroy('session-id')
|
|
|
443
508
|
|
|
444
509
|
GoatChain SDK exports the following built-in tools:
|
|
445
510
|
|
|
446
|
-
| Tool Class
|
|
447
|
-
|
|
|
448
|
-
| `ReadTool`
|
|
449
|
-
| `WriteTool`
|
|
450
|
-
| `EditTool`
|
|
451
|
-
| `GlobTool`
|
|
452
|
-
| `GrepTool`
|
|
453
|
-
| `BashTool`
|
|
454
|
-
| `WebSearchTool`
|
|
455
|
-
| `WebFetchTool`
|
|
456
|
-
| `
|
|
457
|
-
| `
|
|
458
|
-
| `
|
|
459
|
-
| `
|
|
460
|
-
| `
|
|
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 |
|
|
461
527
|
|
|
462
528
|
```typescript
|
|
463
529
|
import {
|
|
@@ -560,14 +626,14 @@ tools.register(
|
|
|
560
626
|
|
|
561
627
|
**How each file tool uses `cwd`:**
|
|
562
628
|
|
|
563
|
-
| Tool
|
|
564
|
-
|
|
|
565
|
-
| `ReadTool`
|
|
566
|
-
| `WriteTool` | Writes/overwrites files
|
|
567
|
-
| `EditTool`
|
|
568
|
-
| `GlobTool`
|
|
569
|
-
| `GrepTool`
|
|
570
|
-
| `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 |
|
|
571
637
|
|
|
572
638
|
**Directory & Protection Options:**
|
|
573
639
|
|
|
@@ -677,23 +743,63 @@ interface AgentHooks {
|
|
|
677
743
|
sessionStart?: (ctx: SessionStartContext) => Promise<void>
|
|
678
744
|
sessionEnd?: (ctx: SessionEndContext) => Promise<void>
|
|
679
745
|
stop?: (ctx: StopContext) => Promise<void>
|
|
680
|
-
userPromptSubmit?:
|
|
746
|
+
userPromptSubmit?:
|
|
747
|
+
| ((ctx: UserPromptSubmitContext) => Promise<UserPromptSubmitResult>)
|
|
748
|
+
| PromptHookEntry
|
|
749
|
+
| Array<
|
|
750
|
+
| ((ctx: UserPromptSubmitContext) => Promise<UserPromptSubmitResult>)
|
|
751
|
+
| PromptHookEntry
|
|
752
|
+
>
|
|
681
753
|
|
|
682
754
|
// Tool lifecycle
|
|
683
755
|
// - Can modify tool call with modifiedToolCall
|
|
684
|
-
preToolUse?:
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
756
|
+
preToolUse?:
|
|
757
|
+
| ((ctx: ToolHookContext) => Promise<PreToolUseResult | void>)
|
|
758
|
+
| PromptHookEntry
|
|
759
|
+
| Array<
|
|
760
|
+
| ((ctx: ToolHookContext) => Promise<PreToolUseResult | void>)
|
|
761
|
+
| PromptHookEntry
|
|
762
|
+
>
|
|
763
|
+
permissionRequest?:
|
|
764
|
+
| ((ctx: ToolHookContext) => Promise<PermissionRequestResult>)
|
|
765
|
+
| PromptHookEntry
|
|
766
|
+
| Array<
|
|
767
|
+
| ((ctx: ToolHookContext) => Promise<PermissionRequestResult>)
|
|
768
|
+
| PromptHookEntry
|
|
769
|
+
>
|
|
770
|
+
postToolUse?:
|
|
771
|
+
| ((ctx: ToolHookContext, result: unknown) => Promise<void>)
|
|
772
|
+
| PromptHookEntry
|
|
773
|
+
| Array<
|
|
774
|
+
| ((ctx: ToolHookContext, result: unknown) => Promise<void>)
|
|
775
|
+
| PromptHookEntry
|
|
776
|
+
>
|
|
777
|
+
postToolUseFailure?:
|
|
778
|
+
| ((ctx: ToolHookContext, error: Error) => Promise<void>)
|
|
779
|
+
| PromptHookEntry
|
|
780
|
+
| Array<
|
|
781
|
+
| ((ctx: ToolHookContext, error: Error) => Promise<void>)
|
|
782
|
+
| PromptHookEntry
|
|
783
|
+
>
|
|
688
784
|
|
|
689
785
|
// Subagent lifecycle (used by parallel task/subagent middleware)
|
|
690
786
|
subagentStart?: (ctx: SubagentStartContext) => Promise<void>
|
|
691
|
-
subagentStop?:
|
|
787
|
+
subagentStop?:
|
|
788
|
+
| ((ctx: SubagentStopContext) => Promise<void>)
|
|
789
|
+
| PromptHookEntry
|
|
790
|
+
| Array<((ctx: SubagentStopContext) => Promise<void>) | PromptHookEntry>
|
|
692
791
|
}
|
|
693
792
|
|
|
694
793
|
// Backward-compatible alias
|
|
695
794
|
type ToolHooks = AgentHooks
|
|
696
795
|
|
|
796
|
+
interface PromptHookEntry {
|
|
797
|
+
type: 'prompt'
|
|
798
|
+
prompt: string // use $ARGUMENTS to inject serialized input
|
|
799
|
+
model?: { provider: string; modelId: string }
|
|
800
|
+
timeoutMs?: number // default: 30000
|
|
801
|
+
}
|
|
802
|
+
|
|
697
803
|
interface BaseHookContext {
|
|
698
804
|
sessionId: string
|
|
699
805
|
}
|
|
@@ -782,6 +888,113 @@ interface SubagentStopContext extends BaseHookContext {
|
|
|
782
888
|
}
|
|
783
889
|
```
|
|
784
890
|
|
|
891
|
+
### Prompt Hook Evaluation
|
|
892
|
+
|
|
893
|
+
Prompt hooks are evaluation-only in current SDK behavior:
|
|
894
|
+
|
|
895
|
+
- Prompt evaluation does not change execution decisions or mutate input/tool calls
|
|
896
|
+
- Supported prompt hooks: `userPromptSubmit`, `preToolUse`, `permissionRequest`, `postToolUse`, `postToolUseFailure`, `subagentStop`
|
|
897
|
+
- `permissionRequest` prompt evaluation only runs when the approval path is entered
|
|
898
|
+
- Each evaluation is persisted in `session.metadata._hookEvaluations`
|
|
899
|
+
|
|
900
|
+
Prompt evaluation emits `hook_evaluation` stream events with `phase`:
|
|
901
|
+
|
|
902
|
+
- `start`
|
|
903
|
+
- `stream` (text delta)
|
|
904
|
+
- `end` (status/result/error)
|
|
905
|
+
|
|
906
|
+
`hook_evaluation` event shape:
|
|
907
|
+
|
|
908
|
+
```typescript
|
|
909
|
+
interface HookEvaluationEvent extends BaseEvent {
|
|
910
|
+
type: 'hook_evaluation'
|
|
911
|
+
evaluationId: string
|
|
912
|
+
hookName:
|
|
913
|
+
| 'permissionRequest'
|
|
914
|
+
| 'preToolUse'
|
|
915
|
+
| 'postToolUse'
|
|
916
|
+
| 'postToolUseFailure'
|
|
917
|
+
| 'subagentStop'
|
|
918
|
+
| 'userPromptSubmit'
|
|
919
|
+
phase: 'start' | 'stream' | 'end'
|
|
920
|
+
prompt?: string
|
|
921
|
+
input?: unknown
|
|
922
|
+
delta?: string
|
|
923
|
+
rawResponse?: string
|
|
924
|
+
result?: unknown
|
|
925
|
+
usage?: Usage
|
|
926
|
+
durationMs?: number
|
|
927
|
+
status?: 'success' | 'error' | 'timeout'
|
|
928
|
+
error?: { code?: string; message: string }
|
|
929
|
+
toolCallId?: string
|
|
930
|
+
}
|
|
931
|
+
```
|
|
932
|
+
|
|
933
|
+
Metadata persistence shape:
|
|
934
|
+
|
|
935
|
+
```typescript
|
|
936
|
+
session.metadata._hookEvaluations = {
|
|
937
|
+
preToolUse: [
|
|
938
|
+
{
|
|
939
|
+
evaluationId: '...',
|
|
940
|
+
timestamp: 1730000000000,
|
|
941
|
+
hookName: 'preToolUse',
|
|
942
|
+
prompt: '...',
|
|
943
|
+
input: { ... },
|
|
944
|
+
status: 'success',
|
|
945
|
+
durationMs: 120,
|
|
946
|
+
rawResponse: '{"ok":true}',
|
|
947
|
+
result: { ok: true },
|
|
948
|
+
usage: { promptTokens: 100, completionTokens: 20, totalTokens: 120 },
|
|
949
|
+
toolCallId: 'call_123',
|
|
950
|
+
},
|
|
951
|
+
],
|
|
952
|
+
}
|
|
953
|
+
```
|
|
954
|
+
|
|
955
|
+
Complete prompt hook example (function hook + prompt hook + event handling):
|
|
956
|
+
|
|
957
|
+
```typescript
|
|
958
|
+
import { Agent } from 'goatchain'
|
|
959
|
+
import type { HookEvaluationEvent } from 'goatchain'
|
|
960
|
+
|
|
961
|
+
const session = await agent.createSession({
|
|
962
|
+
hooks: {
|
|
963
|
+
preToolUse: [
|
|
964
|
+
async (ctx) => {
|
|
965
|
+
// normal behavior hook
|
|
966
|
+
return undefined
|
|
967
|
+
},
|
|
968
|
+
{
|
|
969
|
+
type: 'prompt',
|
|
970
|
+
prompt: 'Analyze this tool call: $ARGUMENTS',
|
|
971
|
+
},
|
|
972
|
+
],
|
|
973
|
+
permissionRequest: {
|
|
974
|
+
type: 'prompt',
|
|
975
|
+
prompt: 'Review approval context: $ARGUMENTS',
|
|
976
|
+
},
|
|
977
|
+
},
|
|
978
|
+
})
|
|
979
|
+
|
|
980
|
+
session.send('Do the task', {
|
|
981
|
+
toolContext: {
|
|
982
|
+
approval: { strategy: 'high_risk' },
|
|
983
|
+
},
|
|
984
|
+
})
|
|
985
|
+
|
|
986
|
+
for await (const event of session.receive()) {
|
|
987
|
+
if (event.type === 'hook_evaluation') {
|
|
988
|
+
const ev = event as HookEvaluationEvent
|
|
989
|
+
if (ev.phase === 'end') {
|
|
990
|
+
console.log('hook evaluation done:', ev.hookName, ev.status, ev.result)
|
|
991
|
+
}
|
|
992
|
+
}
|
|
993
|
+
}
|
|
994
|
+
|
|
995
|
+
console.log(session.metadata?._hookEvaluations)
|
|
996
|
+
```
|
|
997
|
+
|
|
785
998
|
### Hook Execution Order
|
|
786
999
|
|
|
787
1000
|
Typical order in one run:
|
|
@@ -804,7 +1017,12 @@ const agent = new Agent({
|
|
|
804
1017
|
name: 'MyAgent',
|
|
805
1018
|
systemPrompt: 'You are helpful.',
|
|
806
1019
|
model,
|
|
807
|
-
tools:
|
|
1020
|
+
tools: (() => {
|
|
1021
|
+
const tools = new ToolRegistry()
|
|
1022
|
+
tools.register(new ReadTool())
|
|
1023
|
+
tools.register(new WriteTool())
|
|
1024
|
+
return tools
|
|
1025
|
+
})(),
|
|
808
1026
|
})
|
|
809
1027
|
|
|
810
1028
|
// Create session with hooks
|
|
@@ -1039,7 +1257,7 @@ const session = await agent.createSession({
|
|
|
1039
1257
|
|
|
1040
1258
|
### Tool Context
|
|
1041
1259
|
|
|
1042
|
-
The `toolContext` parameter in `send()` and `receive()`
|
|
1260
|
+
The `toolContext` parameter in `send()` and `receive()` is used for approval state and AskUser resume data:
|
|
1043
1261
|
|
|
1044
1262
|
```typescript
|
|
1045
1263
|
session.send('Do something risky', {
|
|
@@ -1052,8 +1270,14 @@ session.send('Do something risky', {
|
|
|
1052
1270
|
tool_call_id_456: { approved: false, reason: 'Too dangerous' },
|
|
1053
1271
|
},
|
|
1054
1272
|
},
|
|
1055
|
-
|
|
1056
|
-
|
|
1273
|
+
askUser: {
|
|
1274
|
+
answers: {
|
|
1275
|
+
tool_call_id_789: {
|
|
1276
|
+
framework: 'React',
|
|
1277
|
+
styling: 'Tailwind CSS',
|
|
1278
|
+
},
|
|
1279
|
+
},
|
|
1280
|
+
},
|
|
1057
1281
|
},
|
|
1058
1282
|
})
|
|
1059
1283
|
```
|
|
@@ -1070,7 +1294,7 @@ outer:before → inner:before → exec (model.stream) → inner:after → outer:
|
|
|
1070
1294
|
|
|
1071
1295
|
```typescript
|
|
1072
1296
|
// Add named middleware (recommended)
|
|
1073
|
-
agent.use(async (state, next) => {
|
|
1297
|
+
await agent.use(async (state, next) => {
|
|
1074
1298
|
const start = Date.now()
|
|
1075
1299
|
console.log(`[${state.iteration}] Before model call`)
|
|
1076
1300
|
|
|
@@ -1087,7 +1311,7 @@ agent.removeMiddleware('logging')
|
|
|
1087
1311
|
console.log(agent.middlewareNames) // ['logging', 'compression', ...]
|
|
1088
1312
|
|
|
1089
1313
|
// Use unsubscribe function
|
|
1090
|
-
const unsubscribe = agent.use(middleware, 'temp')
|
|
1314
|
+
const unsubscribe = await agent.use(middleware, 'temp')
|
|
1091
1315
|
unsubscribe() // Remove middleware
|
|
1092
1316
|
```
|
|
1093
1317
|
|
|
@@ -1101,10 +1325,10 @@ Adds planning phase before execution:
|
|
|
1101
1325
|
import { createPlanModeMiddleware } from 'goatchain'
|
|
1102
1326
|
|
|
1103
1327
|
// Automatically named 'plan_mode'
|
|
1104
|
-
agent.use(createPlanModeMiddleware())
|
|
1328
|
+
await agent.use(createPlanModeMiddleware())
|
|
1105
1329
|
|
|
1106
1330
|
// With custom configuration
|
|
1107
|
-
agent.use(
|
|
1331
|
+
await agent.use(
|
|
1108
1332
|
createPlanModeMiddleware({
|
|
1109
1333
|
name: 'my-plan', // Custom name
|
|
1110
1334
|
planPrompt: 'Create a detailed plan...', // Custom prompt
|
|
@@ -1114,35 +1338,36 @@ agent.use(
|
|
|
1114
1338
|
|
|
1115
1339
|
#### Context Compression Middleware
|
|
1116
1340
|
|
|
1117
|
-
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
|
|
1118
1349
|
|
|
1119
1350
|
```typescript
|
|
1120
1351
|
import { createContextCompressionMiddleware } from 'goatchain'
|
|
1121
1352
|
|
|
1122
1353
|
// Automatically named 'context_compression'
|
|
1123
|
-
agent.use(
|
|
1354
|
+
await agent.use(
|
|
1124
1355
|
createContextCompressionMiddleware({
|
|
1125
|
-
|
|
1126
|
-
protectedTurns: 2, // Keep last 2 conversation turns
|
|
1127
|
-
model: model,
|
|
1128
|
-
stateStore: agent.stateStore,
|
|
1129
|
-
toolCompressionTarget: 0.45, // Compress to 45% of maxTokens
|
|
1130
|
-
minKeepToolResults: 5, // Keep last 5 tool results
|
|
1131
|
-
// Optional: Enable detailed logging
|
|
1132
|
-
enableLogging: true,
|
|
1133
|
-
logFilePath: 'compression-logs.jsonl',
|
|
1356
|
+
contextLength: 128000,
|
|
1134
1357
|
}),
|
|
1135
1358
|
)
|
|
1136
1359
|
```
|
|
1137
1360
|
|
|
1138
|
-
|
|
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.
|
|
1139
1364
|
|
|
1140
1365
|
### Custom Middleware Examples
|
|
1141
1366
|
|
|
1142
1367
|
#### Logging Middleware
|
|
1143
1368
|
|
|
1144
1369
|
```typescript
|
|
1145
|
-
agent.use(async (state, next) => {
|
|
1370
|
+
await agent.use(async (state, next) => {
|
|
1146
1371
|
console.log(`Iteration ${state.iteration}:`, {
|
|
1147
1372
|
messages: state.messages.length,
|
|
1148
1373
|
pendingTools: state.pendingToolCalls.length,
|
|
@@ -1162,7 +1387,7 @@ agent.use(async (state, next) => {
|
|
|
1162
1387
|
#### Error Handling Middleware
|
|
1163
1388
|
|
|
1164
1389
|
```typescript
|
|
1165
|
-
agent.use(async (state, next) => {
|
|
1390
|
+
await agent.use(async (state, next) => {
|
|
1166
1391
|
try {
|
|
1167
1392
|
return await next(state)
|
|
1168
1393
|
} catch (error) {
|
|
@@ -1182,7 +1407,7 @@ import { RateLimiter } from 'some-rate-limiter'
|
|
|
1182
1407
|
|
|
1183
1408
|
const limiter = new RateLimiter({ requestsPerMinute: 60 })
|
|
1184
1409
|
|
|
1185
|
-
agent.use(async (state, next) => {
|
|
1410
|
+
await agent.use(async (state, next) => {
|
|
1186
1411
|
await limiter.acquire()
|
|
1187
1412
|
return next(state)
|
|
1188
1413
|
}, 'rate-limiter')
|
|
@@ -1191,7 +1416,7 @@ agent.use(async (state, next) => {
|
|
|
1191
1416
|
#### Custom Retry Middleware
|
|
1192
1417
|
|
|
1193
1418
|
```typescript
|
|
1194
|
-
agent.use(async (state, next) => {
|
|
1419
|
+
await agent.use(async (state, next) => {
|
|
1195
1420
|
let retries = 3
|
|
1196
1421
|
|
|
1197
1422
|
while (retries > 0) {
|
|
@@ -1221,10 +1446,12 @@ interface AgentLoopState {
|
|
|
1221
1446
|
iteration: number // Current iteration number
|
|
1222
1447
|
pendingToolCalls: ToolCallWithResult[] // Pending tool executions
|
|
1223
1448
|
currentResponse: string // Current LLM response
|
|
1449
|
+
currentThinking?: string // Current reasoning content, if the model emits it
|
|
1224
1450
|
shouldContinue: boolean // Whether to continue loop
|
|
1225
1451
|
stopReason?: string // Reason for stopping
|
|
1226
|
-
usage
|
|
1452
|
+
usage: Usage // Cumulative token usage
|
|
1227
1453
|
error?: Error // Error if any
|
|
1454
|
+
metadata: Record<string, unknown> // Middleware/hook shared runtime data
|
|
1228
1455
|
}
|
|
1229
1456
|
```
|
|
1230
1457
|
|
|
@@ -1347,8 +1574,15 @@ Implement custom state stores:
|
|
|
1347
1574
|
interface StateStore {
|
|
1348
1575
|
deleteOnComplete: boolean
|
|
1349
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
|
|
1350
1584
|
saveCheckpoint(checkpoint: AgentLoopCheckpoint): Promise<void>
|
|
1351
|
-
loadCheckpoint(sessionId: string): Promise<AgentLoopCheckpoint |
|
|
1585
|
+
loadCheckpoint(sessionId: string): Promise<AgentLoopCheckpoint | undefined>
|
|
1352
1586
|
deleteCheckpoint(sessionId: string): Promise<void>
|
|
1353
1587
|
listCheckpoints(): Promise<AgentLoopCheckpoint[]>
|
|
1354
1588
|
}
|
|
@@ -1366,17 +1600,8 @@ interface AgentLoopCheckpoint {
|
|
|
1366
1600
|
### Manual Checkpoint Management
|
|
1367
1601
|
|
|
1368
1602
|
```typescript
|
|
1369
|
-
//
|
|
1370
|
-
|
|
1371
|
-
sessionId: session.id,
|
|
1372
|
-
messages: session.messages,
|
|
1373
|
-
iteration: 3,
|
|
1374
|
-
usage: session.usage,
|
|
1375
|
-
createdAt: Date.now(),
|
|
1376
|
-
updatedAt: Date.now(),
|
|
1377
|
-
})
|
|
1378
|
-
|
|
1379
|
-
// Load checkpoint
|
|
1603
|
+
// Prefer SDK-managed checkpoints during session.receive().
|
|
1604
|
+
// You can still inspect or clean them up manually:
|
|
1380
1605
|
const checkpoint = await stateStore.loadCheckpoint('session-id')
|
|
1381
1606
|
|
|
1382
1607
|
// List all checkpoints
|
|
@@ -1456,7 +1681,7 @@ for await (const event of session.receive()) {
|
|
|
1456
1681
|
if (event.type === 'text_delta') {
|
|
1457
1682
|
process.stdout.write(event.delta)
|
|
1458
1683
|
} else if (event.type === 'tool_call_start') {
|
|
1459
|
-
console.log(`\nCalling: ${event.
|
|
1684
|
+
console.log(`\nCalling: ${event.toolName}`)
|
|
1460
1685
|
} else if (event.type === 'tool_result') {
|
|
1461
1686
|
console.log(`Result: ${JSON.stringify(event.result).slice(0, 100)}...`)
|
|
1462
1687
|
}
|
|
@@ -1537,7 +1762,7 @@ const agent = new Agent({
|
|
|
1537
1762
|
})
|
|
1538
1763
|
|
|
1539
1764
|
// Add logging middleware
|
|
1540
|
-
agent.use(async (state, next) => {
|
|
1765
|
+
await agent.use(async (state, next) => {
|
|
1541
1766
|
console.log(`\n=== Iteration ${state.iteration} ===`)
|
|
1542
1767
|
const result = await next(state)
|
|
1543
1768
|
console.log(`Tokens used: ${result.usage?.totalTokens || 0}`)
|
|
@@ -1545,7 +1770,7 @@ agent.use(async (state, next) => {
|
|
|
1545
1770
|
}, 'logger')
|
|
1546
1771
|
|
|
1547
1772
|
// Add plan mode
|
|
1548
|
-
agent.use(createPlanModeMiddleware())
|
|
1773
|
+
await agent.use(createPlanModeMiddleware())
|
|
1549
1774
|
|
|
1550
1775
|
const session = await agent.createSession()
|
|
1551
1776
|
session.send('Create a todo list app with React and TypeScript')
|
|
@@ -1611,7 +1836,12 @@ import {
|
|
|
1611
1836
|
Agent,
|
|
1612
1837
|
createModel,
|
|
1613
1838
|
createOpenAIAdapter,
|
|
1614
|
-
|
|
1839
|
+
ToolRegistry,
|
|
1840
|
+
ReadTool,
|
|
1841
|
+
WriteTool,
|
|
1842
|
+
EditTool,
|
|
1843
|
+
GlobTool,
|
|
1844
|
+
GrepTool,
|
|
1615
1845
|
} from 'goatchain'
|
|
1616
1846
|
|
|
1617
1847
|
const model = createModel({
|
|
@@ -1621,11 +1851,18 @@ const model = createModel({
|
|
|
1621
1851
|
}),
|
|
1622
1852
|
})
|
|
1623
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
|
+
|
|
1624
1861
|
const agent = new Agent({
|
|
1625
1862
|
name: 'File Agent',
|
|
1626
1863
|
systemPrompt: 'You are a file management assistant.',
|
|
1627
1864
|
model,
|
|
1628
|
-
tools
|
|
1865
|
+
tools,
|
|
1629
1866
|
})
|
|
1630
1867
|
|
|
1631
1868
|
// Set working directory at session creation
|
|
@@ -1732,7 +1969,7 @@ for await (const event of session.receive()) {
|
|
|
1732
1969
|
if (event.type === 'text_delta') {
|
|
1733
1970
|
process.stdout.write(event.delta)
|
|
1734
1971
|
} else if (event.type === 'tool_call_start') {
|
|
1735
|
-
console.log(`\n[Tool] ${event.
|
|
1972
|
+
console.log(`\n[Tool] ${event.toolName}`)
|
|
1736
1973
|
}
|
|
1737
1974
|
}
|
|
1738
1975
|
```
|
|
@@ -1824,12 +2061,39 @@ agent.setModel({ provider: 'openai', modelId: 'gpt-4o-mini' })
|
|
|
1824
2061
|
|
|
1825
2062
|
#### Methods
|
|
1826
2063
|
|
|
1827
|
-
**`send(input):
|
|
2064
|
+
**`send(input, options?): string`**
|
|
1828
2065
|
|
|
1829
|
-
|
|
2066
|
+
Enqueue a message and return its queue message ID.
|
|
1830
2067
|
|
|
1831
2068
|
```typescript
|
|
1832
|
-
session.send('Hello!')
|
|
2069
|
+
const id = session.send('Hello!')
|
|
2070
|
+
```
|
|
2071
|
+
|
|
2072
|
+
**`sendBatch(messages): string[]`**
|
|
2073
|
+
|
|
2074
|
+
Batch enqueue messages and return queue message IDs.
|
|
2075
|
+
|
|
2076
|
+
```typescript
|
|
2077
|
+
const ids = session.sendBatch([
|
|
2078
|
+
{ input: 'task-1', priority: 1 },
|
|
2079
|
+
{ input: 'task-2', priority: 2 },
|
|
2080
|
+
])
|
|
2081
|
+
```
|
|
2082
|
+
|
|
2083
|
+
**`cancelQueuedMessage(messageId): boolean`**
|
|
2084
|
+
|
|
2085
|
+
Cancel a queued message by ID.
|
|
2086
|
+
|
|
2087
|
+
```typescript
|
|
2088
|
+
session.cancelQueuedMessage(id)
|
|
2089
|
+
```
|
|
2090
|
+
|
|
2091
|
+
**`getQueueStatus(): MessageQueueStatus`**
|
|
2092
|
+
|
|
2093
|
+
Query queue length, preview list, processing status, and config.
|
|
2094
|
+
|
|
2095
|
+
```typescript
|
|
2096
|
+
console.log(session.getQueueStatus())
|
|
1833
2097
|
```
|
|
1834
2098
|
|
|
1835
2099
|
**`receive(options?): AsyncGenerator<AgentEvent>`**
|
|
@@ -1894,7 +2158,7 @@ session.setCwd('/path/to/project')
|
|
|
1894
2158
|
#### Properties
|
|
1895
2159
|
|
|
1896
2160
|
- `id: string` - Session ID
|
|
1897
|
-
- `status: SessionStatus` - Session status ('
|
|
2161
|
+
- `status: SessionStatus` - Session status (`'active' | 'paused' | 'completed' | 'error' | 'archived'`)
|
|
1898
2162
|
- `messages: Message[]` - Message history
|
|
1899
2163
|
- `usage: Usage` - Token usage statistics
|
|
1900
2164
|
- `createdAt: number` - Creation timestamp
|
|
@@ -1905,9 +2169,12 @@ session.setCwd('/path/to/project')
|
|
|
1905
2169
|
```typescript
|
|
1906
2170
|
interface Message {
|
|
1907
2171
|
role: 'system' | 'user' | 'assistant' | 'tool'
|
|
1908
|
-
content:
|
|
1909
|
-
|
|
1910
|
-
|
|
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
|
|
1911
2178
|
}
|
|
1912
2179
|
```
|
|
1913
2180
|
|
|
@@ -1925,10 +2192,17 @@ interface Usage {
|
|
|
1925
2192
|
|
|
1926
2193
|
```typescript
|
|
1927
2194
|
type AgentEvent =
|
|
2195
|
+
| TextStartEvent
|
|
1928
2196
|
| TextDeltaEvent
|
|
2197
|
+
| TextEndEvent
|
|
1929
2198
|
| ToolCallStartEvent
|
|
1930
2199
|
| ToolCallDeltaEvent
|
|
1931
2200
|
| ToolCallEndEvent
|
|
2201
|
+
| ToolOutputStartEvent
|
|
2202
|
+
| ToolOutputDeltaEvent
|
|
2203
|
+
| ToolApprovalRequestedEvent
|
|
2204
|
+
| RequiresActionEvent
|
|
2205
|
+
| ToolSkippedEvent
|
|
1932
2206
|
| ToolResultEvent
|
|
1933
2207
|
| ThinkingStartEvent
|
|
1934
2208
|
| ThinkingDeltaEvent
|
|
@@ -1936,7 +2210,6 @@ type AgentEvent =
|
|
|
1936
2210
|
| IterationStartEvent
|
|
1937
2211
|
| IterationEndEvent
|
|
1938
2212
|
| DoneEvent
|
|
1939
|
-
| ErrorEvent
|
|
1940
2213
|
|
|
1941
2214
|
interface TextDeltaEvent {
|
|
1942
2215
|
type: 'text_delta'
|
|
@@ -1945,8 +2218,15 @@ interface TextDeltaEvent {
|
|
|
1945
2218
|
|
|
1946
2219
|
interface ToolCallStartEvent {
|
|
1947
2220
|
type: 'tool_call_start'
|
|
1948
|
-
|
|
1949
|
-
|
|
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 }
|
|
1950
2230
|
}
|
|
1951
2231
|
|
|
1952
2232
|
interface ToolResultEvent {
|
|
@@ -1958,6 +2238,7 @@ interface ToolResultEvent {
|
|
|
1958
2238
|
|
|
1959
2239
|
interface DoneEvent {
|
|
1960
2240
|
type: 'done'
|
|
2241
|
+
finalResponse?: string
|
|
1961
2242
|
stopReason:
|
|
1962
2243
|
| 'max_iterations'
|
|
1963
2244
|
| 'final_response'
|
|
@@ -1965,6 +2246,13 @@ interface DoneEvent {
|
|
|
1965
2246
|
| 'cancelled'
|
|
1966
2247
|
| 'approval_required'
|
|
1967
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
|
+
}
|
|
1968
2256
|
usage?: Usage
|
|
1969
2257
|
}
|
|
1970
2258
|
```
|
|
@@ -2023,7 +2311,7 @@ classDiagram
|
|
|
2023
2311
|
+status: SessionStatus
|
|
2024
2312
|
+messages: Message[]
|
|
2025
2313
|
+usage: Usage
|
|
2026
|
-
+send(input):
|
|
2314
|
+
+send(input, options?): string
|
|
2027
2315
|
+receive(): AsyncGenerator~AgentEvent~
|
|
2028
2316
|
+save(): Promise~void~
|
|
2029
2317
|
}
|
|
@@ -2075,7 +2363,13 @@ See [docs/cli.md](./docs/cli.md) and [docs/server.md](./docs/server.md) for deta
|
|
|
2075
2363
|
Expose DimCode as an Agent Client Protocol server for editor integrations:
|
|
2076
2364
|
|
|
2077
2365
|
```bash
|
|
2078
|
-
|
|
2366
|
+
dim acp
|
|
2367
|
+
```
|
|
2368
|
+
|
|
2369
|
+
For source checkouts, use a cwd-independent command:
|
|
2370
|
+
|
|
2371
|
+
```bash
|
|
2372
|
+
node /absolute/path/to/GoatChain/scripts/acpx-agent.mjs
|
|
2079
2373
|
```
|
|
2080
2374
|
|
|
2081
2375
|
**Configuration for Zed** (`settings.json`):
|
|
@@ -2084,13 +2378,16 @@ bun run acp-server
|
|
|
2084
2378
|
{
|
|
2085
2379
|
"agent_servers": {
|
|
2086
2380
|
"dimcode": {
|
|
2087
|
-
"command": "
|
|
2088
|
-
"args": ["
|
|
2381
|
+
"command": "/absolute/path/to/dim",
|
|
2382
|
+
"args": ["acp"]
|
|
2089
2383
|
}
|
|
2090
2384
|
}
|
|
2091
2385
|
}
|
|
2092
2386
|
```
|
|
2093
2387
|
|
|
2388
|
+
For OpenClaw `acpx`, use either `/absolute/path/to/dim acp` or `node /absolute/path/to/GoatChain/scripts/acpx-agent.mjs`.
|
|
2389
|
+
Do not use `bun run acp-server` there; it depends on the launcher cwd being the GoatChain repo root.
|
|
2390
|
+
|
|
2094
2391
|
See [docs/acp-server.md](./docs/acp-server.md) for details.
|
|
2095
2392
|
|
|
2096
2393
|
## 📚 Documentation
|