goatchain 0.0.28 → 0.0.30

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
@@ -117,6 +117,10 @@ interface CreateSessionOptions {
117
117
  model?: ModelRef // Optional model override
118
118
  maxIterations?: number // Max agent loop iterations (default: 1000)
119
119
  cwd?: string // Working directory for file operations
120
+ messageQueueConfig?: {
121
+ autoProcessQueue?: boolean // Auto-process queued messages (default: true)
122
+ maxQueueSize?: number // Optional queue length limit
123
+ }
120
124
  requestParams?: {
121
125
  temperature?: number // Model temperature
122
126
  maxTokens?: number // Max output tokens
@@ -161,13 +165,70 @@ session.send('What is the weather today?')
161
165
 
162
166
  // Multiple messages in sequence
163
167
  session.send('First question')
164
- // Wait for response...
165
168
  session.send('Follow-up question')
166
169
  ```
167
170
 
168
171
  #### Send Options
169
172
 
170
- You can pass options to `send()` to control tool execution, approval, and more:
173
+ You can pass options to `send()` to control priority, tool execution, approval, and more:
174
+
175
+ ```typescript
176
+ // Higher priority messages are processed first (smaller number = higher priority)
177
+ session.send('Low priority', { priority: 10 })
178
+ session.send('High priority', { priority: 1 })
179
+ ```
180
+
181
+ `send()` returns a message ID that can be used for queue management:
182
+
183
+ ```typescript
184
+ const messageId = session.send('Can be cancelled later')
185
+ session.cancelQueuedMessage(messageId)
186
+ ```
187
+
188
+ #### Message Queue
189
+
190
+ Session now supports queue-based messaging by default. You can enqueue multiple messages safely even while a previous `receive()` is running.
191
+
192
+ ```typescript
193
+ const session = await agent.createSession()
194
+
195
+ session.send('First message')
196
+ session.send('Second message')
197
+
198
+ // Batch enqueue with priority
199
+ session.sendBatch([
200
+ { input: 'Task A', priority: 2 },
201
+ { input: 'Task B', priority: 1 },
202
+ ])
203
+
204
+ // Inspect queue state
205
+ const queue = session.getQueueStatus()
206
+ console.log(queue.length, queue.isProcessing)
207
+
208
+ // Remove queued messages
209
+ session.clearQueue()
210
+ ```
211
+
212
+ Manual queue mode:
213
+
214
+ ```typescript
215
+ const session = await agent.createSession({
216
+ messageQueueConfig: { autoProcessQueue: false },
217
+ })
218
+
219
+ session.send('Message 1')
220
+ session.send('Message 2')
221
+
222
+ for await (const event of session.receive()) {
223
+ // only Message 1
224
+ }
225
+
226
+ for await (const event of session.receive()) {
227
+ // Message 2
228
+ }
229
+ ```
230
+
231
+ Tool context and approval options still work as before:
171
232
 
172
233
  ```typescript
173
234
  // Auto-approve all tools for this request
@@ -677,23 +738,48 @@ interface AgentHooks {
677
738
  sessionStart?: (ctx: SessionStartContext) => Promise<void>
678
739
  sessionEnd?: (ctx: SessionEndContext) => Promise<void>
679
740
  stop?: (ctx: StopContext) => Promise<void>
680
- userPromptSubmit?: (ctx: UserPromptSubmitContext) => Promise<UserPromptSubmitResult>
741
+ userPromptSubmit?:
742
+ | ((ctx: UserPromptSubmitContext) => Promise<UserPromptSubmitResult>)
743
+ | PromptHookEntry
744
+ | Array<((ctx: UserPromptSubmitContext) => Promise<UserPromptSubmitResult>) | PromptHookEntry>
681
745
 
682
746
  // Tool lifecycle
683
747
  // - Can modify tool call with modifiedToolCall
684
- preToolUse?: (ctx: ToolHookContext) => Promise<PreToolUseResult | void>
685
- permissionRequest?: (ctx: ToolHookContext) => Promise<PermissionRequestResult>
686
- postToolUse?: (ctx: ToolHookContext, result: unknown) => Promise<void>
687
- postToolUseFailure?: (ctx: ToolHookContext, error: Error) => Promise<void>
748
+ preToolUse?:
749
+ | ((ctx: ToolHookContext) => Promise<PreToolUseResult | void>)
750
+ | PromptHookEntry
751
+ | Array<((ctx: ToolHookContext) => Promise<PreToolUseResult | void>) | PromptHookEntry>
752
+ permissionRequest?:
753
+ | ((ctx: ToolHookContext) => Promise<PermissionRequestResult>)
754
+ | PromptHookEntry
755
+ | Array<((ctx: ToolHookContext) => Promise<PermissionRequestResult>) | PromptHookEntry>
756
+ postToolUse?:
757
+ | ((ctx: ToolHookContext, result: unknown) => Promise<void>)
758
+ | PromptHookEntry
759
+ | Array<((ctx: ToolHookContext, result: unknown) => Promise<void>) | PromptHookEntry>
760
+ postToolUseFailure?:
761
+ | ((ctx: ToolHookContext, error: Error) => Promise<void>)
762
+ | PromptHookEntry
763
+ | Array<((ctx: ToolHookContext, error: Error) => Promise<void>) | PromptHookEntry>
688
764
 
689
765
  // Subagent lifecycle (used by parallel task/subagent middleware)
690
766
  subagentStart?: (ctx: SubagentStartContext) => Promise<void>
691
- subagentStop?: (ctx: SubagentStopContext) => Promise<void>
767
+ subagentStop?:
768
+ | ((ctx: SubagentStopContext) => Promise<void>)
769
+ | PromptHookEntry
770
+ | Array<((ctx: SubagentStopContext) => Promise<void>) | PromptHookEntry>
692
771
  }
693
772
 
694
773
  // Backward-compatible alias
695
774
  type ToolHooks = AgentHooks
696
775
 
776
+ interface PromptHookEntry {
777
+ type: 'prompt'
778
+ prompt: string // use $ARGUMENTS to inject serialized input
779
+ model?: { provider: string; modelId: string }
780
+ timeoutMs?: number // default: 30000
781
+ }
782
+
697
783
  interface BaseHookContext {
698
784
  sessionId: string
699
785
  }
@@ -710,9 +796,6 @@ interface ToolHookContext extends BaseHookContext {
710
796
  toolContext: ToolExecutionContext
711
797
  }
712
798
 
713
- // `HookContext` is kept as a backward-compatible alias of ToolHookContext
714
- type HookContext = ToolHookContext
715
-
716
799
  interface PermissionRequestResult {
717
800
  // If true, passes permission checks and skips approval flow
718
801
  // (tool still goes through normal middleware/disabled checks)
@@ -785,6 +868,113 @@ interface SubagentStopContext extends BaseHookContext {
785
868
  }
786
869
  ```
787
870
 
871
+ ### Prompt Hook Evaluation
872
+
873
+ Prompt hooks are evaluation-only in current SDK behavior:
874
+
875
+ - Prompt evaluation does not change execution decisions or mutate input/tool calls
876
+ - Supported prompt hooks: `userPromptSubmit`, `preToolUse`, `permissionRequest`, `postToolUse`, `postToolUseFailure`, `subagentStop`
877
+ - `permissionRequest` prompt evaluation only runs when the approval path is entered
878
+ - Each evaluation is persisted in `session.metadata._hookEvaluations`
879
+
880
+ Prompt evaluation emits `hook_evaluation` stream events with `phase`:
881
+
882
+ - `start`
883
+ - `stream` (text delta)
884
+ - `end` (status/result/error)
885
+
886
+ `hook_evaluation` event shape:
887
+
888
+ ```typescript
889
+ interface HookEvaluationEvent extends BaseEvent {
890
+ type: 'hook_evaluation'
891
+ evaluationId: string
892
+ hookName:
893
+ | 'permissionRequest'
894
+ | 'preToolUse'
895
+ | 'postToolUse'
896
+ | 'postToolUseFailure'
897
+ | 'subagentStop'
898
+ | 'userPromptSubmit'
899
+ phase: 'start' | 'stream' | 'end'
900
+ prompt?: string
901
+ input?: unknown
902
+ delta?: string
903
+ rawResponse?: string
904
+ result?: unknown
905
+ usage?: Usage
906
+ durationMs?: number
907
+ status?: 'success' | 'error' | 'timeout'
908
+ error?: { code?: string; message: string }
909
+ toolCallId?: string
910
+ }
911
+ ```
912
+
913
+ Metadata persistence shape:
914
+
915
+ ```typescript
916
+ session.metadata._hookEvaluations = {
917
+ preToolUse: [
918
+ {
919
+ evaluationId: '...',
920
+ timestamp: 1730000000000,
921
+ hookName: 'preToolUse',
922
+ prompt: '...',
923
+ input: { ... },
924
+ status: 'success',
925
+ durationMs: 120,
926
+ rawResponse: '{"ok":true}',
927
+ result: { ok: true },
928
+ usage: { promptTokens: 100, completionTokens: 20, totalTokens: 120 },
929
+ toolCallId: 'call_123',
930
+ },
931
+ ],
932
+ }
933
+ ```
934
+
935
+ Complete prompt hook example (function hook + prompt hook + event handling):
936
+
937
+ ```typescript
938
+ import { Agent } from 'goatchain'
939
+ import type { HookEvaluationEvent } from 'goatchain'
940
+
941
+ const session = await agent.createSession({
942
+ hooks: {
943
+ preToolUse: [
944
+ async (ctx) => {
945
+ // normal behavior hook
946
+ return undefined
947
+ },
948
+ {
949
+ type: 'prompt',
950
+ prompt: 'Analyze this tool call: $ARGUMENTS',
951
+ },
952
+ ],
953
+ permissionRequest: {
954
+ type: 'prompt',
955
+ prompt: 'Review approval context: $ARGUMENTS',
956
+ },
957
+ },
958
+ })
959
+
960
+ session.send('Do the task', {
961
+ toolContext: {
962
+ approval: { strategy: 'high_risk' },
963
+ },
964
+ })
965
+
966
+ for await (const event of session.receive()) {
967
+ if (event.type === 'hook_evaluation') {
968
+ const ev = event as HookEvaluationEvent
969
+ if (ev.phase === 'end') {
970
+ console.log('hook evaluation done:', ev.hookName, ev.status, ev.result)
971
+ }
972
+ }
973
+ }
974
+
975
+ console.log(session.metadata?._hookEvaluations)
976
+ ```
977
+
788
978
  ### Hook Execution Order
789
979
 
790
980
  Typical order in one run:
@@ -1827,12 +2017,39 @@ agent.setModel({ provider: 'openai', modelId: 'gpt-4o-mini' })
1827
2017
 
1828
2018
  #### Methods
1829
2019
 
1830
- **`send(input): void`**
2020
+ **`send(input, options?): string`**
1831
2021
 
1832
- Send a message to the session.
2022
+ Enqueue a message and return its queue message ID.
1833
2023
 
1834
2024
  ```typescript
1835
- session.send('Hello!')
2025
+ const id = session.send('Hello!')
2026
+ ```
2027
+
2028
+ **`sendBatch(messages): string[]`**
2029
+
2030
+ Batch enqueue messages and return queue message IDs.
2031
+
2032
+ ```typescript
2033
+ const ids = session.sendBatch([
2034
+ { input: 'task-1', priority: 1 },
2035
+ { input: 'task-2', priority: 2 },
2036
+ ])
2037
+ ```
2038
+
2039
+ **`cancelQueuedMessage(messageId): boolean`**
2040
+
2041
+ Cancel a queued message by ID.
2042
+
2043
+ ```typescript
2044
+ session.cancelQueuedMessage(id)
2045
+ ```
2046
+
2047
+ **`getQueueStatus(): MessageQueueStatus`**
2048
+
2049
+ Query queue length, preview list, processing status, and config.
2050
+
2051
+ ```typescript
2052
+ console.log(session.getQueueStatus())
1836
2053
  ```
1837
2054
 
1838
2055
  **`receive(options?): AsyncGenerator<AgentEvent>`**
@@ -2026,7 +2243,7 @@ classDiagram
2026
2243
  +status: SessionStatus
2027
2244
  +messages: Message[]
2028
2245
  +usage: Usage
2029
- +send(input): void
2246
+ +send(input, options?): string
2030
2247
  +receive(): AsyncGenerator~AgentEvent~
2031
2248
  +save(): Promise~void~
2032
2249
  }
@@ -2078,7 +2295,13 @@ See [docs/cli.md](./docs/cli.md) and [docs/server.md](./docs/server.md) for deta
2078
2295
  Expose DimCode as an Agent Client Protocol server for editor integrations:
2079
2296
 
2080
2297
  ```bash
2081
- bun run acp-server
2298
+ dim acp
2299
+ ```
2300
+
2301
+ For source checkouts, use a cwd-independent command:
2302
+
2303
+ ```bash
2304
+ node /absolute/path/to/GoatChain/scripts/acpx-agent.mjs
2082
2305
  ```
2083
2306
 
2084
2307
  **Configuration for Zed** (`settings.json`):
@@ -2087,13 +2310,16 @@ bun run acp-server
2087
2310
  {
2088
2311
  "agent_servers": {
2089
2312
  "dimcode": {
2090
- "command": "pnpm",
2091
- "args": ["--dir", "/path/to/DimCode", "acp-server"]
2313
+ "command": "/absolute/path/to/dim",
2314
+ "args": ["acp"]
2092
2315
  }
2093
2316
  }
2094
2317
  }
2095
2318
  ```
2096
2319
 
2320
+ For OpenClaw `acpx`, use either `/absolute/path/to/dim acp` or `node /absolute/path/to/GoatChain/scripts/acpx-agent.mjs`.
2321
+ Do not use `bun run acp-server` there; it depends on the launcher cwd being the GoatChain repo root.
2322
+
2097
2323
  See [docs/acp-server.md](./docs/acp-server.md) for details.
2098
2324
 
2099
2325
  ## 📚 Documentation
@@ -0,0 +1,10 @@
1
+ import type { Message } from '../types';
2
+ import type { ACPMessage } from './types';
3
+ export type NormalizeAcpHistoryOptions = Readonly<{
4
+ dropTrailingPendingUserInput?: boolean;
5
+ }>;
6
+ type SessionLikeMessage = Exclude<Message, {
7
+ role: 'system';
8
+ }>;
9
+ export declare function normalizeAcpHistoryToSessionMessages(acpMessages: readonly ACPMessage[], options?: NormalizeAcpHistoryOptions): SessionLikeMessage[];
10
+ export {};
@@ -7,6 +7,8 @@
7
7
  * @packageDocumentation
8
8
  */
9
9
  export { ACPAgent } from './ACPAgent';
10
+ export { normalizeAcpHistoryToSessionMessages } from './history-normalizer';
11
+ export type { NormalizeAcpHistoryOptions } from './history-normalizer';
10
12
  export { ProtocolConverter } from './ProtocolConverter';
11
13
  export { SessionRouter } from './SessionRouter';
12
14
  export type { ACPAgentOptions, ACPContent, ACPMessage, ACPMetadata, ACPRole, ACPToolCall, ExtendedAgentEvent, SessionContext, SubagentMetadata, } from './types';
@@ -40,6 +40,10 @@ export interface ACPMessage {
40
40
  */
41
41
  export interface ACPMetadata {
42
42
  session_id?: string;
43
+ stream_id?: string;
44
+ run_id?: string;
45
+ seq?: number;
46
+ replayed?: boolean;
43
47
  signal?: AbortSignal;
44
48
  [key: string]: unknown;
45
49
  }
@@ -95,8 +95,11 @@ export declare class Agent {
95
95
  * Middleware follows an immutable pattern - it receives state and returns new state via next().
96
96
  *
97
97
  * If the middleware provides a `__createTools` function, the tools will be automatically
98
- * registered with a namespace prefix (`<middlewareName>_<toolName>`) and automatically
99
- * unregistered when the middleware is removed.
98
+ * registered with a namespace prefix (`<middlewareName>_<toolName>`) by default and
99
+ * automatically unregistered when the middleware is removed.
100
+ *
101
+ * If middleware sets `__toolNamespacePrefix = false`, tools are registered with their
102
+ * original names (`tool.name`) without `<middlewareName>_` prefix.
100
103
  *
101
104
  * @param fn - Middleware function
102
105
  * @param name - Optional name for the middleware. If not provided:
@@ -120,13 +123,21 @@ export declare class Agent {
120
123
  * // Override default name
121
124
  * await agent.use(createPlanModeMiddleware(), 'my_plan_mode');
122
125
  *
123
- * // Middleware with tools (auto-registers tools with namespace)
126
+ * // Middleware with tools (auto-registers tools with namespace by default)
124
127
  * const middleware: Middleware = async (state, next) => next(state);
125
128
  * middleware.__middlewareName = 'plan_mode';
126
129
  * middleware.__createTools = async () => [new EnterPlanModeTool()];
127
130
  * await agent.use(middleware);
128
131
  * // Tool registered as: 'plan_mode_EnterPlanMode'
129
132
  *
133
+ * // Register middleware tool without prefix
134
+ * const subagentMiddleware: Middleware = async (state, next) => next(state);
135
+ * subagentMiddleware.__middlewareName = 'parallel_subagent';
136
+ * subagentMiddleware.__toolNamespacePrefix = false;
137
+ * subagentMiddleware.__createTools = async () => [new TaskTool()];
138
+ * await agent.use(subagentMiddleware);
139
+ * // Tool registered as: 'Task'
140
+ *
130
141
  * // Anonymous middleware (auto-named)
131
142
  * const unsubscribe = await agent.use(async (state, next) => {
132
143
  * const compressed = { ...state, messages: compress(state.messages) };
@@ -1,2 +1,2 @@
1
1
  export { HookManager } from './manager';
2
- export type { AgentHooks, BaseHookContext, HookContext, PermissionRequestHook, PermissionRequestResult, PostToolUseFailureHook, PostToolUseHook, PreToolUseHook, PreToolUseResult, SessionEndContext, SessionEndHook, SessionStartContext, SessionStartHook, StopContext, StopHook, SubagentStartContext, SubagentStartHook, SubagentStopContext, SubagentStopHook, ToolHookContext, ToolHooks, UserPromptSubmitContext, UserPromptSubmitHook, UserPromptSubmitResult, } from './types';
2
+ export type { AgentHooks, BaseHookContext, PermissionRequestHook, PermissionRequestHookEntry, PermissionRequestResult, PostToolUseFailureHook, PostToolUseFailureHookEntry, PostToolUseHook, PostToolUseHookEntry, PreToolUseHook, PreToolUseHookEntry, PreToolUseResult, PromptHookEntry, SessionEndContext, SessionEndHook, SessionStartContext, SessionStartHook, StopContext, StopHook, SubagentStartContext, SubagentStartHook, SubagentStopContext, SubagentStopHook, SubagentStopHookEntry, ToolHookContext, ToolHooks, UserPromptSubmitContext, UserPromptSubmitHook, UserPromptSubmitHookEntry, UserPromptSubmitResult, } from './types';
@@ -1,15 +1,32 @@
1
- import type { AgentHooks, HookContext, PermissionRequestResult, PreToolUseResult, SessionEndContext, SessionStartContext, SubagentStartContext, StopContext, SubagentStopContext, UserPromptSubmitContext, UserPromptSubmitResult } from './types';
1
+ import type { AgentHooks, PermissionRequestResult, PreToolUseResult, SessionEndContext, SessionStartContext, SubagentStartContext, StopContext, SubagentStopContext, ToolHookContext, UserPromptSubmitContext, UserPromptSubmitResult } from './types';
2
+ import type { ModelClient } from '../../model/types';
3
+ import type { HookEvaluationEvent } from '../../types';
4
+ interface HookManagerOptions {
5
+ modelClient?: ModelClient;
6
+ emitEvent?: (event: Omit<HookEvaluationEvent, 'sessionId'>) => void;
7
+ getSessionMetadata?: () => Record<string, unknown>;
8
+ }
2
9
  export declare class HookManager {
3
10
  private readonly hooks;
4
- constructor(hooks?: AgentHooks);
5
- executePermissionRequest(context: HookContext): Promise<PermissionRequestResult>;
6
- executePreToolUse(context: HookContext): Promise<PreToolUseResult | void>;
11
+ private readonly modelClient?;
12
+ private readonly emitEvent?;
13
+ private readonly getSessionMetadata?;
14
+ constructor(hooks?: AgentHooks, options?: HookManagerOptions);
15
+ hasPermissionRequestFunction(): boolean;
16
+ private toCompactUsage;
17
+ private getToolCallIdFromInput;
18
+ private recordEvaluation;
19
+ private evaluatePromptHook;
20
+ executePermissionRequest(context: ToolHookContext): Promise<PermissionRequestResult>;
21
+ evaluatePermissionRequestPrompt(context: ToolHookContext): Promise<void>;
22
+ executePreToolUse(context: ToolHookContext): Promise<PreToolUseResult | void>;
7
23
  executeUserPromptSubmit(context: UserPromptSubmitContext): Promise<UserPromptSubmitResult>;
8
24
  executeSessionStart(context: SessionStartContext): Promise<void>;
9
25
  executeSessionEnd(context: SessionEndContext): Promise<void>;
10
- executePostToolUse(context: HookContext, result: unknown): Promise<void>;
11
- executePostToolUseFailure(context: HookContext, error: Error): Promise<void>;
26
+ executePostToolUse(context: ToolHookContext, result: unknown): Promise<void>;
27
+ executePostToolUseFailure(context: ToolHookContext, error: Error): Promise<void>;
12
28
  executeStop(context: StopContext): Promise<void>;
13
29
  executeSubagentStart(context: SubagentStartContext): Promise<void>;
14
30
  executeSubagentStop(context: SubagentStopContext): Promise<void>;
15
31
  }
32
+ export {};
@@ -0,0 +1,28 @@
1
+ import type { ModelClient } from '../../model/types';
2
+ import type { HookEvaluationEvent, Usage } from '../../types';
3
+ import type { PromptHookEntry } from './types';
4
+ export type PromptEvaluableHookName = 'permissionRequest' | 'preToolUse' | 'postToolUse' | 'postToolUseFailure' | 'subagentStop' | 'userPromptSubmit';
5
+ export interface ExecutePromptHookOptions {
6
+ hookName: PromptEvaluableHookName;
7
+ sessionId: string;
8
+ input: unknown;
9
+ entry: PromptHookEntry;
10
+ modelClient?: ModelClient;
11
+ toolCallId?: string;
12
+ emitEvent?: (event: Omit<HookEvaluationEvent, 'sessionId'>) => void;
13
+ }
14
+ export interface PromptHookExecutionResult {
15
+ evaluationId: string;
16
+ hookName: PromptEvaluableHookName;
17
+ renderedPrompt: string;
18
+ status: 'success' | 'error' | 'timeout';
19
+ durationMs: number;
20
+ rawResponse?: string;
21
+ result?: unknown;
22
+ usage?: Usage;
23
+ error?: {
24
+ code?: string;
25
+ message: string;
26
+ };
27
+ }
28
+ export declare function executePromptHook(options: ExecutePromptHookOptions): Promise<PromptHookExecutionResult>;
@@ -1,4 +1,5 @@
1
1
  import type { ModelStopReason } from '../../model/types';
2
+ import type { ModelRef } from '../../model/types';
2
3
  import type { ToolExecutionContext } from '../../tool';
3
4
  import type { Message, MessageContent, ToolCall, Usage } from '../../types';
4
5
  export interface BaseHookContext {
@@ -6,14 +7,11 @@ export interface BaseHookContext {
6
7
  }
7
8
  /**
8
9
  * Context for tool-level hooks (PermissionRequest, PreToolUse, PostToolUse, PostToolUseFailure).
9
- * Also exported as `HookContext` for backward compatibility.
10
10
  */
11
11
  export interface ToolHookContext extends BaseHookContext {
12
12
  toolCall: ToolCall;
13
13
  toolContext: ToolExecutionContext;
14
14
  }
15
- /** @deprecated Use `ToolHookContext` instead. Kept for backward compatibility. */
16
- export type HookContext = ToolHookContext;
17
15
  export interface SessionStartContext extends BaseHookContext {
18
16
  /** Whether this run starts from a new session or a resumed state/checkpoint. */
19
17
  startReason: 'new' | 'resume';
@@ -84,6 +82,25 @@ export interface UserPromptSubmitResult {
84
82
  allow: boolean;
85
83
  modifiedInput?: MessageContent;
86
84
  }
85
+ export interface PromptHookEntry {
86
+ type: 'prompt';
87
+ /**
88
+ * Prompt template used for evaluation.
89
+ * `$ARGUMENTS` (if present) will be replaced with serialized hook input.
90
+ * If absent, serialized hook input is appended to the end of the prompt.
91
+ */
92
+ prompt: string;
93
+ /**
94
+ * Optional model override for this hook evaluation.
95
+ * Defaults to the session's configured model.
96
+ */
97
+ model?: ModelRef;
98
+ /**
99
+ * Optional timeout in milliseconds for this evaluation.
100
+ * Defaults to 30_000ms.
101
+ */
102
+ timeoutMs?: number;
103
+ }
87
104
  export type PermissionRequestHook = (ctx: ToolHookContext) => Promise<PermissionRequestResult>;
88
105
  export type PreToolUseHook = (ctx: ToolHookContext) => Promise<PreToolUseResult | void>;
89
106
  export type PostToolUseHook = (ctx: ToolHookContext, result: unknown) => Promise<void>;
@@ -94,17 +111,23 @@ export type SessionEndHook = (ctx: SessionEndContext) => Promise<void>;
94
111
  export type SubagentStartHook = (ctx: SubagentStartContext) => Promise<void>;
95
112
  export type SubagentStopHook = (ctx: SubagentStopContext) => Promise<void>;
96
113
  export type UserPromptSubmitHook = (ctx: UserPromptSubmitContext) => Promise<UserPromptSubmitResult>;
114
+ export type PermissionRequestHookEntry = PermissionRequestHook | PromptHookEntry;
115
+ export type PreToolUseHookEntry = PreToolUseHook | PromptHookEntry;
116
+ export type PostToolUseHookEntry = PostToolUseHook | PromptHookEntry;
117
+ export type PostToolUseFailureHookEntry = PostToolUseFailureHook | PromptHookEntry;
118
+ export type SubagentStopHookEntry = SubagentStopHook | PromptHookEntry;
119
+ export type UserPromptSubmitHookEntry = UserPromptSubmitHook | PromptHookEntry;
97
120
  export interface AgentHooks {
98
121
  sessionStart?: SessionStartHook;
99
- permissionRequest?: PermissionRequestHook;
100
- preToolUse?: PreToolUseHook;
101
- postToolUse?: PostToolUseHook;
102
- postToolUseFailure?: PostToolUseFailureHook;
122
+ permissionRequest?: PermissionRequestHookEntry | PermissionRequestHookEntry[];
123
+ preToolUse?: PreToolUseHookEntry | PreToolUseHookEntry[];
124
+ postToolUse?: PostToolUseHookEntry | PostToolUseHookEntry[];
125
+ postToolUseFailure?: PostToolUseFailureHookEntry | PostToolUseFailureHookEntry[];
103
126
  sessionEnd?: SessionEndHook;
104
127
  stop?: StopHook;
105
128
  subagentStart?: SubagentStartHook;
106
- subagentStop?: SubagentStopHook;
107
- userPromptSubmit?: UserPromptSubmitHook;
129
+ subagentStop?: SubagentStopHookEntry | SubagentStopHookEntry[];
130
+ userPromptSubmit?: UserPromptSubmitHookEntry | UserPromptSubmitHookEntry[];
108
131
  }
109
132
  /** @deprecated Use `AgentHooks` instead. Kept for backward compatibility. */
110
133
  export type ToolHooks = AgentHooks;
@@ -6,7 +6,7 @@ export type { ToCheckpointOptions } from '../session/handlers/CheckpointManager'
6
6
  export { Agent } from './agent';
7
7
  export { AgentAbortError, AgentMaxIterationsError, AgentPauseError, ensureNotAborted } from './errors';
8
8
  export { HookManager } from './hooks';
9
- export type { AgentHooks, BaseHookContext, HookContext, PermissionRequestHook, PermissionRequestResult, PostToolUseFailureHook, PostToolUseHook, PreToolUseHook, PreToolUseResult, SessionEndContext, SessionEndHook, SessionStartContext, SessionStartHook, StopContext, StopHook, SubagentStartContext, SubagentStartHook, SubagentStopContext, SubagentStopHook, ToolHookContext, ToolHooks, UserPromptSubmitContext, UserPromptSubmitHook, UserPromptSubmitResult, } from './hooks';
9
+ export type { AgentHooks, BaseHookContext, PermissionRequestHook, PermissionRequestHookEntry, PermissionRequestResult, PostToolUseFailureHook, PostToolUseFailureHookEntry, PostToolUseHook, PostToolUseHookEntry, PreToolUseHook, PreToolUseHookEntry, PreToolUseResult, PromptHookEntry, SessionEndContext, SessionEndHook, SessionStartContext, SessionStartHook, StopContext, StopHook, SubagentStartContext, SubagentStartHook, SubagentStopContext, SubagentStopHook, SubagentStopHookEntry, ToolHookContext, ToolHooks, UserPromptSubmitContext, UserPromptSubmitHook, UserPromptSubmitHookEntry, UserPromptSubmitResult, } from './hooks';
10
10
  export { compose } from './middleware';
11
11
  export type { Middleware, NamedMiddleware, NextFunction } from './middleware';
12
12
  export { countContentTokens, countMessagesTokens, countMessageTokens, countTokens, createCachedTokenCounter, estimateMessagesTokens, estimateTokens, } from './tokenCounter';
@@ -49,9 +49,11 @@ export interface Middleware<State = AgentLoopState> {
49
49
  /**
50
50
  * Optional factory function that creates tools to be registered with this middleware.
51
51
  * When the middleware is registered via agent.use(), this function will be called
52
- * and the returned tools will be automatically registered with a namespace prefix.
52
+ * and the returned tools will be automatically registered with a namespace prefix
53
+ * by default.
53
54
  *
54
- * Tools will be namespaced as: `<middlewareName>_<toolName>`
55
+ * Tools will be namespaced as: `<middlewareName>_<toolName>`.
56
+ * If `__toolNamespacePrefix === false`, tools are registered with original `tool.name`.
55
57
  * When the middleware is removed, all associated tools are automatically unregistered.
56
58
  *
57
59
  * Can be synchronous or asynchronous to support dynamic tool creation.
@@ -70,6 +72,12 @@ export interface Middleware<State = AgentLoopState> {
70
72
  * ```
71
73
  */
72
74
  __createTools?: () => BaseTool[] | Promise<BaseTool[]>;
75
+ /**
76
+ * Optional flag to control middleware tool namespace prefixing.
77
+ * Defaults to true/undefined, which registers tools as `<middlewareName>_<toolName>`.
78
+ * Set to false to register tools with their original `tool.name` (no middleware prefix).
79
+ */
80
+ __toolNamespacePrefix?: boolean;
73
81
  /**
74
82
  * Optional function that returns a list of tool names to block for the given state.
75
83
  * This allows middleware to dynamically control which tools should be unavailable
@@ -1,6 +1,7 @@
1
1
  import type { McpServerConfig } from '../mcp-client';
2
2
  import type { ModelClient, ModelRef } from '../model';
3
3
  import type { ModelStopReason } from '../model/types';
4
+ import type { MessageQueueConfig } from '../session/types';
4
5
  import type { StateStore } from '../state';
5
6
  import type { ToolExecutionContextInput, ToolRegistry } from '../tool';
6
7
  import type { CheckpointRequestParams, Message, MessageContent, ToolCall, Usage } from '../types';
@@ -294,10 +295,21 @@ export interface CreateSessionOptions extends SessionHandleOptions {
294
295
  * This value is persisted in session snapshots and restored on resume.
295
296
  */
296
297
  cwd?: string;
298
+ /**
299
+ * Optional message queue configuration for this session.
300
+ */
301
+ messageQueueConfig?: Partial<MessageQueueConfig>;
297
302
  }
298
303
  export interface SendOptions {
299
304
  /**
300
305
  * Optional tool execution context input
301
306
  */
302
307
  toolContext?: ToolExecutionContextInput;
308
+ /**
309
+ * Controls how receive() handles existing checkpoints.
310
+ * - auto: preserve current behavior
311
+ * - explicit_only: do not auto-resume a pending checkpoint
312
+ * - force_resume: require resuming from checkpoint flow first
313
+ */
314
+ resumeMode?: 'auto' | 'explicit_only' | 'force_resume';
303
315
  }