1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
//! `beforeToolCall` and `afterToolCall` config hooks.
//!
//! Faithful port of pi's hook surface at agent-loop.ts:578-708.
//!
//! Pi's hooks are JavaScript callbacks that receive a context
//! object and may MUTATE the args in place (test pi:310). Rust
//! can't compose `&mut` cleanly with `Pin<Box<dyn Future>>`, so
//! we pass `args` by value and return the (possibly mutated)
//! args alongside the hook result. The dispatcher threads the
//! returned args forward — semantically identical to pi's
//! mutate-in-place but with explicit data flow.
use Pin;
use Arc;
use Value;
use ;
use ;
use ;
/// Context passed to `beforeToolCall`. Port of pi
/// `BeforeToolCallContext` (types.ts:84).
///
/// Fields are owned values (clones) so the hook closure can be
/// `Fn(Ctx) -> Future` rather than `Fn(&Ctx) -> Future` — the
/// latter is hairy with `Pin<Box<dyn Future>>` lifetimes. Pi's
/// hooks receive references to mutable JS objects; we trade a
/// small clone overhead for a clean async-fn shape.
/// Return value of `beforeToolCall`. Pi returns
/// `Promise<BeforeToolCallResult | undefined>` AND mutates the
/// context's `args` in place. Since Rust can't elegantly mutate
/// through a moved value, the closure returns BOTH the result
/// (possibly None) and the (possibly mutated) args.
/// `beforeToolCall` hook signature. Pi (types.ts:262):
/// `(context: BeforeToolCallContext, signal?) => Promise<BeforeToolCallResult | undefined>`
pub type BeforeToolCallFn = ;
/// Context passed to `afterToolCall`. Port of pi
/// `AfterToolCallContext` (types.ts:96).
/// `afterToolCall` hook signature. Pi (types.ts:276):
/// `(context: AfterToolCallContext, signal?) => Promise<AfterToolCallResult | undefined>`
///
/// Returning `None` keeps the executed result verbatim; returning
/// `Some(AfterToolCallResult { … })` overrides any of the four
/// fields per pi's merge semantics (content/details/isError/
/// terminate replace in full when Some).
pub type AfterToolCallFn = ;
// ---------------------------------------------------------------
// Phase 4 hooks: prepareNextTurn, shouldStopAfterTurn,
// getSteeringMessages, getFollowupMessages.
// ---------------------------------------------------------------
/// Context passed to `prepareNextTurn` AND `shouldStopAfterTurn`.
/// Pi has `PrepareNextTurnContext extends ShouldStopAfterTurnContext`
/// (types.ts:133) — same shape, two aliases. We define one struct.
///
/// Port of pi `ShouldStopAfterTurnContext` (types.ts:112):
/// `{ message, toolResults, context, newMessages }`
/// `prepareNextTurn` hook signature. Port of pi
/// `prepareNextTurn?` (types.ts:215):
/// `(context) => AgentLoopTurnUpdate | undefined | Promise<...>`
///
/// `None` means "no changes — continue with current state". The
/// returned `TurnUpdate`'s `Some` fields replace the
/// corresponding loop config / context for the next turn.
pub type PrepareNextTurnFn = ;
/// `shouldStopAfterTurn` hook signature. Port of pi
/// `shouldStopAfterTurn?` (types.ts:208):
/// `(context) => boolean | Promise<boolean>`
///
/// Returning `true` requests a graceful stop after the current
/// turn — the loop emits `agent_end` and exits without polling
/// steering or follow-up queues.
pub type ShouldStopAfterTurnFn =
;
/// `getSteeringMessages` hook signature. Port of pi
/// `getSteeringMessages?` (types.ts:230):
/// `() => Promise<AgentMessage[]>`
///
/// Polled at: (a) loop entry, (b) after each `turn_end` /
/// `prepareNextTurn` / `shouldStopAfterTurn` cycle. Returned
/// messages inject BEFORE the next assistant response.
pub type GetSteeringMessagesFn =
;
/// `getFollowupMessages` hook signature. Port of pi
/// `getFollowUpMessages?` (types.ts:243):
/// `() => Promise<AgentMessage[]>`
///
/// Polled at the OUTER-loop boundary — when the inner loop has
/// no more tool calls AND no pending steering. Non-empty return
/// triggers the outer loop to re-enter the inner loop with these
/// messages as pending.
pub type GetFollowupMessagesFn =
;
/// Polled at the finalization boundary. Returns `true` when the run should
/// defer finalization — e.g. coordinated subagent work is still running, so the
/// parent turn should end WITHOUT the critic (and lower gates) firing and be
/// re-woken when the batch becomes deliverable.
pub type ShouldDeferFinalizationFn = ;