@slopus/happy-agent-base 0.0.1 → 0.0.3

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.
Files changed (90) hide show
  1. package/README.md +20 -235
  2. package/dist/Agent.d.ts +71 -9
  3. package/dist/Agent.d.ts.map +1 -1
  4. package/dist/Agent.js +258 -40
  5. package/dist/Agent.js.map +1 -1
  6. package/dist/AgentBase.d.ts +268 -23
  7. package/dist/AgentBase.d.ts.map +1 -1
  8. package/dist/AgentBase.js +1620 -333
  9. package/dist/AgentBase.js.map +1 -1
  10. package/dist/AgentBaseHooks.d.ts +108 -24
  11. package/dist/AgentBaseHooks.d.ts.map +1 -1
  12. package/dist/AgentBasePending.d.ts +44 -0
  13. package/dist/AgentBasePending.d.ts.map +1 -0
  14. package/dist/AgentBasePending.js +64 -0
  15. package/dist/AgentBasePending.js.map +1 -0
  16. package/dist/AgentBaseState.d.ts +2 -0
  17. package/dist/AgentBaseState.d.ts.map +1 -1
  18. package/dist/AgentConfig.d.ts +67 -0
  19. package/dist/AgentConfig.d.ts.map +1 -0
  20. package/dist/AgentConfig.js +81 -0
  21. package/dist/AgentConfig.js.map +1 -0
  22. package/dist/AgentContexts.d.ts +40 -0
  23. package/dist/AgentContexts.d.ts.map +1 -0
  24. package/dist/AgentContexts.js +70 -0
  25. package/dist/AgentContexts.js.map +1 -0
  26. package/dist/AgentFeature.d.ts +118 -15
  27. package/dist/AgentFeature.d.ts.map +1 -1
  28. package/dist/AgentKV.d.ts +58 -0
  29. package/dist/AgentKV.d.ts.map +1 -0
  30. package/dist/AgentKV.js +114 -0
  31. package/dist/AgentKV.js.map +1 -0
  32. package/dist/AgentModel.d.ts +17 -0
  33. package/dist/AgentModel.d.ts.map +1 -0
  34. package/dist/AgentModel.js +2 -0
  35. package/dist/AgentModel.js.map +1 -0
  36. package/dist/{AgentBasePersistence.d.ts → AgentPersistence.d.ts} +13 -8
  37. package/dist/AgentPersistence.d.ts.map +1 -0
  38. package/dist/AgentPersistence.js +2 -0
  39. package/dist/AgentPersistence.js.map +1 -0
  40. package/dist/AgentProviders.d.ts +22 -7
  41. package/dist/AgentProviders.d.ts.map +1 -1
  42. package/dist/AgentProviders.js +18 -9
  43. package/dist/AgentProviders.js.map +1 -1
  44. package/dist/AgentRef.d.ts +41 -0
  45. package/dist/AgentRef.d.ts.map +1 -0
  46. package/dist/AgentRef.js +60 -0
  47. package/dist/AgentRef.js.map +1 -0
  48. package/dist/AgentStorage.d.ts +39 -0
  49. package/dist/AgentStorage.d.ts.map +1 -0
  50. package/dist/AgentStorage.js +49 -0
  51. package/dist/AgentStorage.js.map +1 -0
  52. package/dist/AgentSystem.d.ts +52 -0
  53. package/dist/AgentSystem.d.ts.map +1 -0
  54. package/dist/AgentSystem.js +2 -0
  55. package/dist/AgentSystem.js.map +1 -0
  56. package/dist/AgentSystemContext.d.ts +15 -0
  57. package/dist/AgentSystemContext.d.ts.map +1 -0
  58. package/dist/AgentSystemContext.js +20 -0
  59. package/dist/AgentSystemContext.js.map +1 -0
  60. package/dist/AgentSystemLocal.d.ts +104 -0
  61. package/dist/AgentSystemLocal.d.ts.map +1 -0
  62. package/dist/AgentSystemLocal.js +401 -0
  63. package/dist/AgentSystemLocal.js.map +1 -0
  64. package/dist/AgentSystemRef.d.ts +56 -0
  65. package/dist/AgentSystemRef.d.ts.map +1 -0
  66. package/dist/AgentSystemRef.js +75 -0
  67. package/dist/AgentSystemRef.js.map +1 -0
  68. package/dist/AgentTaskContext.d.ts +17 -0
  69. package/dist/AgentTaskContext.d.ts.map +1 -0
  70. package/dist/AgentTaskContext.js +26 -0
  71. package/dist/AgentTaskContext.js.map +1 -0
  72. package/dist/AgentTool.d.ts +40 -0
  73. package/dist/AgentTool.d.ts.map +1 -1
  74. package/dist/AgentTool.js.map +1 -1
  75. package/dist/index.d.ts +21 -7
  76. package/dist/index.d.ts.map +1 -1
  77. package/dist/index.js +24 -3
  78. package/dist/index.js.map +1 -1
  79. package/dist/models.d.ts +62 -0
  80. package/dist/models.d.ts.map +1 -0
  81. package/dist/models.js +185 -0
  82. package/dist/models.js.map +1 -0
  83. package/package.json +6 -4
  84. package/dist/AgentBaseContext.d.ts +0 -22
  85. package/dist/AgentBaseContext.d.ts.map +0 -1
  86. package/dist/AgentBaseContext.js +0 -33
  87. package/dist/AgentBaseContext.js.map +0 -1
  88. package/dist/AgentBasePersistence.d.ts.map +0 -1
  89. package/dist/AgentBasePersistence.js +0 -2
  90. package/dist/AgentBasePersistence.js.map +0 -1
@@ -1,7 +1,7 @@
1
1
  import type { SessionReasoningEffort, SessionServiceTier, SessionUserMessage } from "@slopus/happy-providers";
2
2
  import { type Context } from "@steve.kite/stdlib";
3
3
  import type { AgentBaseHooks } from "./AgentBaseHooks.js";
4
- import type { AgentBasePersistence } from "./AgentBasePersistence.js";
4
+ import type { AgentPersistence } from "./AgentPersistence.js";
5
5
  import type { AgentBaseState } from "./AgentBaseState.js";
6
6
  import { AgentProviders } from "./AgentProviders.js";
7
7
  /** How a message queue drains: one message per model response, or every queued message at once. */
@@ -14,10 +14,33 @@ export type AgentBaseQueueMode = "one-at-a-time" | "all";
14
14
  export interface AgentBaseMessageOptions {
15
15
  /** The registry ID of the provider to switch to. */
16
16
  readonly provider?: string;
17
+ /** The model to switch to; an incompatible one resets the conversation. */
17
18
  readonly model?: string;
19
+ /** How hard the model should think about the request. */
18
20
  readonly effort?: SessionReasoningEffort;
21
+ /** Which of the provider's service tiers to bill and schedule the request on. */
19
22
  readonly serviceTier?: SessionServiceTier;
20
23
  }
24
+ /**
25
+ * Whether an operation resolves once the agent has taken the request on, or once the agent has
26
+ * carried it out. Every operation that asks something of an agent accepts this, and every one of
27
+ * them defaults to the first: asking is the operation, and waiting is opt-in.
28
+ *
29
+ * The reason is re-entrancy. An agent does its work in one run loop, and while a hook or a tool
30
+ * runs, that loop is waiting for it — so code in that position that waits for its own agent waits
31
+ * for itself. Rather than offer some operations in a waiting form and others not, every operation
32
+ * returns as soon as the request is registered, and `await: true` asks for the rest. That flag is
33
+ * refused, loudly, when the caller's context says it is running inside the loop of the very agent
34
+ * it is asking, which is the only case where the wait could never end.
35
+ */
36
+ export interface AgentBaseAwaitOptions {
37
+ /**
38
+ * Wait for the operation to finish rather than for it to be accepted. Refused from inside the
39
+ * agent's own run loop.
40
+ */
41
+ readonly await?: boolean;
42
+ }
43
+ /** Everything an agent session is constructed with; only the identity and store are required. */
21
44
  export interface AgentBaseOptions {
22
45
  /** Stable session identity supplied by the caller. */
23
46
  readonly id: string;
@@ -25,14 +48,21 @@ export interface AgentBaseOptions {
25
48
  readonly providers: AgentProviders;
26
49
  /** The registry ID of the provider to use; serializable alongside model and effort. */
27
50
  readonly provider: string;
28
- readonly persistence: AgentBasePersistence;
51
+ /** The append-only store the conversation, the queues, and the settings live in. */
52
+ readonly persistence: AgentPersistence;
53
+ /** Observers and correctness hooks the run is assembled from; `Agent` merges features here. */
29
54
  readonly hooks?: AgentBaseHooks;
30
55
  /** Copied into the agent's own mutable `state`. */
31
56
  readonly initialState?: Partial<AgentBaseState>;
57
+ /** The initial model, superseded by the first message that carries one. */
32
58
  readonly model?: string;
59
+ /** The initial reasoning effort, superseded by the first message that carries one. */
33
60
  readonly effort?: SessionReasoningEffort;
61
+ /** The initial service tier, superseded by the first message that carries one. */
34
62
  readonly serviceTier?: SessionServiceTier;
63
+ /** How the steering queue drains; one message per response by default. */
35
64
  readonly steeringMode?: AgentBaseQueueMode;
65
+ /** How the send queue drains; one message per response by default. */
36
66
  readonly sendMode?: AgentBaseQueueMode;
37
67
  }
38
68
  /**
@@ -40,54 +70,269 @@ export interface AgentBaseOptions {
40
70
  * messages inject as soon as the current assistant response and its tool batch finish, while
41
71
  * sent messages wait until the agent would otherwise stop — no tool calls or steering remain.
42
72
  * Each queue drains per its configured mode, and the conversation is durable through
43
- * append-only persistence loaded on the first inference attempt.
73
+ * append-only persistence reloaded at the start of every turn.
74
+ *
75
+ * The rest of this comment is the list of promises the implementation has to keep. They are
76
+ * written down because most of them are invisible in ordinary use and only show themselves when
77
+ * a process dies or a caller races the loop. Each has focused test coverage.
78
+ *
79
+ * ## Serialization
80
+ *
81
+ * One lock serializes every persistence operation together with its in-memory effect, so storage
82
+ * order always matches history order and a load never overlaps an append. Anything that decides
83
+ * from durable state resolves that state inside the lock rather than capturing it beforehand; a
84
+ * reference taken before a wait can belong to a history that has since been replaced.
85
+ *
86
+ * ## Accepting a message
87
+ *
88
+ * A message is accepted exactly once, or not at all. Its durable write and the writes of every
89
+ * other message in the same batch commit in one transaction under one hold of the lock. So:
90
+ *
91
+ * - `steer` and `send` with `await: true` resolve only once the message is durable; a failed
92
+ * write keeps it out of the conversation entirely. Without the flag they return early, but the
93
+ * acceptance is the same one, and a close still waits for it.
94
+ * - Messages a hook returns from one decision are accepted as one batch. A caller arriving while
95
+ * that batch is being written lands after all of it, never between two halves of one thought.
96
+ * - Queue keys order by what the store already holds, including when the clock moves backwards.
97
+ * - An agent holding a durable message never describes itself as settled.
98
+ *
99
+ * ## Consuming a message
100
+ *
101
+ * A consumption deletes each entry inside the transaction that appends it to the context. A
102
+ * message is never durable in both places, or in neither, and memory changes only after commit.
103
+ *
104
+ * ## Turns
105
+ *
106
+ * A turn reloads the durable conversation before it decides anything, keeping the store
107
+ * authoritative across restarts. A turn that consumes the last queued work clears the request it
108
+ * just answered rather than buying an extra empty turn with a full set of hooks.
109
+ *
110
+ * ## Tool calls
111
+ *
112
+ * A batch runs its calls at the same time, each in its own persistence scope, and commits their
113
+ * results in batch order. Results are matched back by call ID, so a response that used one ID
114
+ * twice has no answer the model could tell apart: that ID is kept once and refused before
115
+ * anything runs, since a refusal after the fact would not undo the side effect.
116
+ *
117
+ * The conversation never keeps a tool call the model will not get an answer for:
118
+ *
119
+ * - A batch is committed before any call in it runs, so a batch found uncommitted after a crash
120
+ * has certainly not run and is dispatched as the fresh batch it never became.
121
+ * - A response that emits a call but does not end in one, and a turn that fails while owing
122
+ * results, settle their own calls with error results before appending anything behind them.
123
+ * - A conversation loaded with a call stranded under later messages is repaired atomically at
124
+ * load, since the answer belongs beside its call rather than at the end.
125
+ * - A non-durable tool never runs twice; a durable one may.
126
+ *
127
+ * ## Compaction
128
+ *
129
+ * A compaction runs before a turn's first inference, so the model always receives a settled
130
+ * conversation. It replaces the history whole or not at all. A compaction nobody will carry out
131
+ * is rejected rather than left waiting.
132
+ *
133
+ * ## Model changes
134
+ *
135
+ * An incompatible provider or model change resets the conversation; a compatible one keeps it.
136
+ * Either way the change lands on one side or the other, never the old history under the new
137
+ * model. `modelChanged` runs inside the lock and is lent a store bound to that hold — a
138
+ * capability released when the hook returns, so it cannot be retained to bypass the lock later.
139
+ * A failing handoff rejects an incompatible switch outright rather than costing the history.
140
+ *
141
+ * ## Recovery
142
+ *
143
+ * Whether a restart owes a response is decided by the last durable record: a consumed message, a
144
+ * tool result, or a failure note is owed an answer, while a replacement written by a compaction
145
+ * is not a question and gets none.
146
+ *
147
+ * ## Abort
148
+ *
149
+ * An abort owns the whole turn. Its scope opens before any of the turn's work — its hooks and its
150
+ * loading as much as its inference — so a turn cancelled while it is still starting up never
151
+ * reaches the model at all, rather than being cancelled only once it was already talking.
152
+ *
153
+ * What a cancelled turn leaves behind is fixed:
154
+ *
155
+ * - Assistant blocks that finished stay in the history; a block still being streamed is dropped,
156
+ * because half a block is not something the model said.
157
+ * - Tool calls still running are settled in the conversation as aborted error results, so the
158
+ * history owes nothing, and the turn ends without waiting for the tools themselves. A tool that
159
+ * never notices cancellation therefore cannot hold the cancellation open — but it is still
160
+ * running, so the *next* provider request waits for it before reusing the stateful session.
161
+ * - Messages already queued stay durable and join the next requested turn. An abort cancels the
162
+ * turn, not the work waiting for one.
163
+ * - A compaction requested during the turn is rejected rather than left pending, because dropping
164
+ * the turn request drops the only thing that would have carried it out.
165
+ * - Exactly one terminal event is reported. A cancellation seen after a response already reported
166
+ * its own outcome adds nothing, since that response is over.
167
+ *
168
+ * `abort` signals and returns, because the cancellation is complete once it is signalled.
169
+ * `abort(ctx, { await: true })` additionally waits for the loop to stop, which is what an owner
170
+ * outside the agent usually wants and what code inside it must not ask for — see below.
171
+ *
172
+ * ## Close
173
+ *
174
+ * Close is a barrier, published before any of the shutdown runs. Nothing new is admitted from
175
+ * the moment it is called; everything already admitted is written and answered, and only then is
176
+ * the provider session destroyed. Every caller shares that one shutdown, including one
177
+ * reentering from inside session destruction, so a session is never destroyed twice.
178
+ *
179
+ * ## Hooks
180
+ *
181
+ * Hooks observe the run and never fail it. Neither a throwing hook nor a failing hook-driven
182
+ * action ends a turn.
183
+ *
184
+ * ## Re-entrancy
185
+ *
186
+ * A hook or a tool runs while the loop is waiting for it, so anything it asks of its own agent
187
+ * that only the loop can deliver would wait for itself. Rather than leave that to be remembered
188
+ * per operation, asking and waiting are separated everywhere:
189
+ *
190
+ * - `steer`, `send`, `abort` and `compact` are safe from anywhere in their asking form, which is
191
+ * the default. Each registers what it registers and returns; the loop acts on it afterwards.
192
+ * - `await: true` asks for the part only the loop can give. Contexts handed to hooks and tools
193
+ * record which agents' loops the execution is inside, so the flag is refused with an error that
194
+ * names the problem instead of hanging. The check is per agent: work inside one agent's loop
195
+ * may still wait on another's, which is what makes a subagent's report to its parent safe.
196
+ * - The refusal is uniform even where a particular wait would have happened to work. A tool that
197
+ * waits for its own abort, for instance, does unwind — the batch races each execution against
198
+ * cancellation — but that is a property of tool batches rather than of abort, and a rule that
199
+ * holds only in one position is worse than no rule.
200
+ * - A hook that wants a compaction has a better option than requesting one: the
201
+ * `{ type: "compact" }` action it returns lands exactly where the loop can act on it, in order
202
+ * with the rest of that decision.
203
+ * - `close` and `waitForIdle` take no context, so they cannot be checked and will simply hang.
204
+ * Both are nothing but a wait for the run to finish. Close the agent from the caller that owns
205
+ * its lifetime.
206
+ *
207
+ * `AgentRef` and `AgentSystemRef` drop the two unguarded waits, and are what code running inside
208
+ * an agent should be handed.
44
209
  */
45
210
  export declare class AgentBase {
46
211
  #private;
212
+ /** The caller-supplied session identity: the name of this agent's store and of its loop. */
47
213
  readonly id: string;
48
214
  /**
49
215
  * The agent's own copy of the initial state, mutable directly; every inference reads the
50
216
  * current values.
51
217
  */
52
218
  readonly state: AgentBaseState;
53
- constructor(ctx: Context, options: AgentBaseOptions);
219
+ /**
220
+ * A new agent, wired to its options and touching no storage at all. Use this for an identity
221
+ * with no durable state yet; whatever the agent needs from the store is read by its first
222
+ * turn.
223
+ */
224
+ static create(ctx: Context, options: AgentBaseOptions): Promise<AgentBase>;
225
+ /**
226
+ * An agent for an identity that may already have durable state, with the one externally
227
+ * meaningful fact about that state — whether it has work left — read before it is handed
228
+ * back, so `active` is answerable straight away.
229
+ *
230
+ * Only the flag is read. The conversation, the queues and the settings are deliberately not:
231
+ * they are needed by the first turn and by nothing before it, so an owner resuming a hundred
232
+ * identities at startup pays for a hundred small reads rather than a hundred transcripts.
233
+ * The rest loads on the way into the turn that actually needs it.
234
+ */
235
+ static load(ctx: Context, options: AgentBaseOptions): Promise<AgentBase>;
236
+ /**
237
+ * Load the agent and set it going again if it has work left, or answer with nothing when it
238
+ * has none. This is how an owner coming up carries on whatever an earlier process was in the
239
+ * middle of: the whole question is one key, and an agent told to go picks its own work back
240
+ * up, so the caller has only to bring it into existence.
241
+ *
242
+ * An agent owing nothing is not handed back, because there is nothing to do with it that
243
+ * resolving it when something is actually wanted of it would not do better.
244
+ */
245
+ static loadActive(ctx: Context, options: AgentBaseOptions): Promise<AgentBase | undefined>;
246
+ /**
247
+ * Build the agent from its options, without touching the store. Nothing is loaded here: the
248
+ * durable state is read by the first turn, so constructing one stays cheap even for a session
249
+ * nobody goes on to run. Private, because an agent is made by `create` or by `load`, and
250
+ * which of the two the caller means is worth saying.
251
+ */
252
+ private constructor();
253
+ /**
254
+ * Whether the agent has anything left to do. This is the only thing about an agent's state
255
+ * anyone outside it may read: the queues and the stage behind this answer are the run's own
256
+ * business, and can be cleared but never inspected. Even this is rarely wanted — it is here
257
+ * for the owner deciding which agents a restarted process has to resume.
258
+ */
259
+ get active(): boolean;
54
260
  /**
55
261
  * Queue a user message that injects as soon as the current assistant response and its tool
56
- * batch finish; steering always takes precedence over sent messages. The returned promise
57
- * resolves once the durable write lands; it waits neither for the history load nor for the
58
- * turn, and a failed write keeps the message out of the conversation entirely.
262
+ * batch finish; steering always takes precedence over sent messages. Returns once the message
263
+ * has been handed to the agent, which never waits for the turn that answers it; with
264
+ * `await: true` it returns once the durable write has landed instead, and a failed write both
265
+ * rejects and keeps the message out of the conversation entirely.
59
266
  */
60
- steer(ctx: Context, message: SessionUserMessage, options?: AgentBaseMessageOptions): Promise<void>;
267
+ steer(ctx: Context, message: SessionUserMessage, options?: AgentBaseMessageOptions & AgentBaseAwaitOptions): Promise<void>;
61
268
  /**
62
269
  * Queue a user message that waits until the agent would otherwise stop — no tool calls or
63
- * steering remain — before injecting. The returned promise resolves once the durable write
64
- * lands; it waits neither for the history load nor for the turn, and a failed write keeps
65
- * the message out of the conversation entirely.
270
+ * steering remain — before injecting. Returns once the message has been handed to the agent,
271
+ * which never waits for the turn that answers it; with `await: true` it returns once the
272
+ * durable write has landed instead, and a failed write both rejects and keeps the message out
273
+ * of the conversation entirely.
66
274
  */
67
- send(ctx: Context, message: SessionUserMessage, options?: AgentBaseMessageOptions): Promise<void>;
275
+ send(ctx: Context, message: SessionUserMessage, options?: AgentBaseMessageOptions & AgentBaseAwaitOptions): Promise<void>;
68
276
  /**
69
277
  * Start the loop without a new message: load the durable state and, if a turn was cut off —
70
278
  * queued messages, a dispatched tool batch without results, or an unanswered user or tool
71
279
  * message — continue it to completion. On an idle history this loads and does nothing more.
72
280
  */
73
281
  start(): void;
282
+ /**
283
+ * Wait until the agent has nothing left to do. That includes work it has taken on but not yet
284
+ * started: an operation whose caller did not wait for it is registered from the moment it is
285
+ * called, so a message asked for and abandoned is still something this waits for, rather than
286
+ * a race between the caller's next line and the agent's own lock.
287
+ */
74
288
  waitForIdle(): Promise<void>;
75
289
  /**
76
290
  * Compact the conversation. The compaction waits for the active turn to end — or runs right
77
- * away when idle — and replaces the compacted history with the provider's replacement
78
- * context while keeping every message that joined the history after the snapshot. Calls made
79
- * while a compaction is pending or running await that same compaction; the shared promise
80
- * resolves when it completes and rejects when the provider reports failure.
291
+ * away when idle — and replaces the compacted history with the provider's replacement context
292
+ * while keeping every message that joined the history after the snapshot.
293
+ *
294
+ * Returns once the compaction has been asked for; with `await: true` it returns once the
295
+ * compaction has run, rejecting when the provider reports failure or when nothing will carry
296
+ * it out. Callers that wait while a compaction is pending or running all wait for that same
297
+ * compaction rather than queueing another.
298
+ */
299
+ compact(ctx: Context, options?: AgentBaseAwaitOptions): Promise<void>;
300
+ /**
301
+ * Cancel the active turn: stop consuming the inference stream, settle still-running tool calls
302
+ * as aborted error results, and drop the queued turn request. Blocks that already finished
303
+ * stay in the history; an unfinished block is dropped. Messages still waiting in the steering
304
+ * and send queues stay durable and join the next requested turn. A no-op when the agent is
305
+ * idle.
306
+ *
307
+ * Returns once the cancellation has been signalled, which is the point from which nothing
308
+ * more of that turn happens; with `await: true` it returns once the loop has actually
309
+ * unwound. The cancellation is identical either way — waiting only buys the answer about
310
+ * when it finished.
81
311
  */
82
- compact(ctx: Context): Promise<void>;
312
+ abort(ctx: Context, options?: AgentBaseAwaitOptions): Promise<void>;
83
313
  /**
84
- * Cancel the active turn: stop consuming the inference stream, settle still-running tool
85
- * calls as aborted error results, and drop the queued turn request. Blocks that already
86
- * finished stay in the history; an unfinished block is dropped. Messages still waiting in
87
- * the steering and send queues stay durable and join the next requested turn. Resolves
88
- * once the loop has stopped; a no-op when the agent is idle.
314
+ * Stop the agent, without abandoning anything it had already taken on. Nothing new is
315
+ * admitted from the moment close is called, but a message accepted just before it is still
316
+ * written, still answered, and only then is the provider session destroyed so a caller
317
+ * whose send resolved never has to wonder whether the close raced it. Closing twice awaits
318
+ * the same shutdown.
319
+ *
320
+ * A close is nothing but a wait, so it is refused from inside the agent's own run loop, where
321
+ * the wait could never end. It is the one operation with no context to check, so it asks the
322
+ * runtime instead.
323
+ *
324
+ * Running tool calls are the exception to finishing what was accepted. From the moment close
325
+ * begins, the batch stops waiting for them and settles them in the conversation as error
326
+ * results. A tool can perfectly well be blocked on this very close — that is how two agents
327
+ * closing each other through their tools would otherwise wedge — and no tool is worth
328
+ * letting the shutdown never finish.
89
329
  */
90
- abort(): Promise<void>;
91
330
  close(): Promise<void>;
331
+ /**
332
+ * Wait for a close that has already been requested to finish. Unlike `close`, this never
333
+ * initiates shutdown, so owners can separate the caller-facing reentrancy report from the
334
+ * underlying lifetime barrier.
335
+ */
336
+ waitForClosed(): Promise<void>;
92
337
  }
93
338
  //# sourceMappingURL=AgentBase.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"AgentBase.d.ts","sourceRoot":"","sources":["../sources/AgentBase.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAMR,sBAAsB,EACtB,kBAAkB,EAIlB,kBAAkB,EACrB,MAAM,yBAAyB,CAAC;AAGjC,OAAO,EAA2C,KAAK,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAG3F,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAC1D,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAC;AACtE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAC1D,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAOrD,mGAAmG;AACnG,MAAM,MAAM,kBAAkB,GAAG,eAAe,GAAG,KAAK,CAAC;AAEzD;;;;GAIG;AACH,MAAM,WAAW,uBAAuB;IACpC,oDAAoD;IACpD,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,MAAM,CAAC,EAAE,sBAAsB,CAAC;IACzC,QAAQ,CAAC,WAAW,CAAC,EAAE,kBAAkB,CAAC;CAC7C;AASD,MAAM,WAAW,gBAAgB;IAC7B,sDAAsD;IACtD,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,0EAA0E;IAC1E,QAAQ,CAAC,SAAS,EAAE,cAAc,CAAC;IACnC,uFAAuF;IACvF,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,WAAW,EAAE,oBAAoB,CAAC;IAC3C,QAAQ,CAAC,KAAK,CAAC,EAAE,cAAc,CAAC;IAChC,mDAAmD;IACnD,QAAQ,CAAC,YAAY,CAAC,EAAE,OAAO,CAAC,cAAc,CAAC,CAAC;IAChD,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,MAAM,CAAC,EAAE,sBAAsB,CAAC;IACzC,QAAQ,CAAC,WAAW,CAAC,EAAE,kBAAkB,CAAC;IAC1C,QAAQ,CAAC,YAAY,CAAC,EAAE,kBAAkB,CAAC;IAC3C,QAAQ,CAAC,QAAQ,CAAC,EAAE,kBAAkB,CAAC;CAC1C;AAED;;;;;;GAMG;AACH,qBAAa,SAAS;;IAClB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB;;;OAGG;IACH,QAAQ,CAAC,KAAK,EAAE,cAAc,CAAC;IAwC/B,YAAY,GAAG,EAAE,OAAO,EAAE,OAAO,EAAE,gBAAgB,EAmBlD;IAWD;;;;;OAKG;IACG,KAAK,CACP,GAAG,EAAE,OAAO,EACZ,OAAO,EAAE,kBAAkB,EAC3B,OAAO,CAAC,EAAE,uBAAuB,GAClC,OAAO,CAAC,IAAI,CAAC,CAEf;IAED;;;;;OAKG;IACG,IAAI,CACN,GAAG,EAAE,OAAO,EACZ,OAAO,EAAE,kBAAkB,EAC3B,OAAO,CAAC,EAAE,uBAAuB,GAClC,OAAO,CAAC,IAAI,CAAC,CAEf;IAmBD;;;;OAIG;IACH,KAAK,IAAI,IAAI,CAGZ;IAEK,WAAW,IAAI,OAAO,CAAC,IAAI,CAAC,CAIjC;IAED;;;;;;OAMG;IACG,OAAO,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAGzC;IAyCD;;;;;;OAMG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAM3B;IAEK,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAM3B;CAqvBJ"}
1
+ {"version":3,"file":"AgentBase.d.ts","sourceRoot":"","sources":["../sources/AgentBase.ts"],"names":[],"mappings":"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"}