@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.
- package/README.md +20 -235
- package/dist/Agent.d.ts +71 -9
- package/dist/Agent.d.ts.map +1 -1
- package/dist/Agent.js +258 -40
- package/dist/Agent.js.map +1 -1
- package/dist/AgentBase.d.ts +268 -23
- package/dist/AgentBase.d.ts.map +1 -1
- package/dist/AgentBase.js +1620 -333
- package/dist/AgentBase.js.map +1 -1
- package/dist/AgentBaseHooks.d.ts +108 -24
- package/dist/AgentBaseHooks.d.ts.map +1 -1
- package/dist/AgentBasePending.d.ts +44 -0
- package/dist/AgentBasePending.d.ts.map +1 -0
- package/dist/AgentBasePending.js +64 -0
- package/dist/AgentBasePending.js.map +1 -0
- package/dist/AgentBaseState.d.ts +2 -0
- package/dist/AgentBaseState.d.ts.map +1 -1
- package/dist/AgentConfig.d.ts +67 -0
- package/dist/AgentConfig.d.ts.map +1 -0
- package/dist/AgentConfig.js +81 -0
- package/dist/AgentConfig.js.map +1 -0
- package/dist/AgentContexts.d.ts +40 -0
- package/dist/AgentContexts.d.ts.map +1 -0
- package/dist/AgentContexts.js +70 -0
- package/dist/AgentContexts.js.map +1 -0
- package/dist/AgentFeature.d.ts +118 -15
- package/dist/AgentFeature.d.ts.map +1 -1
- package/dist/AgentKV.d.ts +58 -0
- package/dist/AgentKV.d.ts.map +1 -0
- package/dist/AgentKV.js +114 -0
- package/dist/AgentKV.js.map +1 -0
- package/dist/AgentModel.d.ts +17 -0
- package/dist/AgentModel.d.ts.map +1 -0
- package/dist/AgentModel.js +2 -0
- package/dist/AgentModel.js.map +1 -0
- package/dist/{AgentBasePersistence.d.ts → AgentPersistence.d.ts} +13 -8
- package/dist/AgentPersistence.d.ts.map +1 -0
- package/dist/AgentPersistence.js +2 -0
- package/dist/AgentPersistence.js.map +1 -0
- package/dist/AgentProviders.d.ts +22 -7
- package/dist/AgentProviders.d.ts.map +1 -1
- package/dist/AgentProviders.js +18 -9
- package/dist/AgentProviders.js.map +1 -1
- package/dist/AgentRef.d.ts +41 -0
- package/dist/AgentRef.d.ts.map +1 -0
- package/dist/AgentRef.js +60 -0
- package/dist/AgentRef.js.map +1 -0
- package/dist/AgentStorage.d.ts +39 -0
- package/dist/AgentStorage.d.ts.map +1 -0
- package/dist/AgentStorage.js +49 -0
- package/dist/AgentStorage.js.map +1 -0
- package/dist/AgentSystem.d.ts +52 -0
- package/dist/AgentSystem.d.ts.map +1 -0
- package/dist/AgentSystem.js +2 -0
- package/dist/AgentSystem.js.map +1 -0
- package/dist/AgentSystemContext.d.ts +15 -0
- package/dist/AgentSystemContext.d.ts.map +1 -0
- package/dist/AgentSystemContext.js +20 -0
- package/dist/AgentSystemContext.js.map +1 -0
- package/dist/AgentSystemLocal.d.ts +104 -0
- package/dist/AgentSystemLocal.d.ts.map +1 -0
- package/dist/AgentSystemLocal.js +401 -0
- package/dist/AgentSystemLocal.js.map +1 -0
- package/dist/AgentSystemRef.d.ts +56 -0
- package/dist/AgentSystemRef.d.ts.map +1 -0
- package/dist/AgentSystemRef.js +75 -0
- package/dist/AgentSystemRef.js.map +1 -0
- package/dist/AgentTaskContext.d.ts +17 -0
- package/dist/AgentTaskContext.d.ts.map +1 -0
- package/dist/AgentTaskContext.js +26 -0
- package/dist/AgentTaskContext.js.map +1 -0
- package/dist/AgentTool.d.ts +40 -0
- package/dist/AgentTool.d.ts.map +1 -1
- package/dist/AgentTool.js.map +1 -1
- package/dist/index.d.ts +21 -7
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +24 -3
- package/dist/index.js.map +1 -1
- package/dist/models.d.ts +62 -0
- package/dist/models.d.ts.map +1 -0
- package/dist/models.js +185 -0
- package/dist/models.js.map +1 -0
- package/package.json +6 -4
- package/dist/AgentBaseContext.d.ts +0 -22
- package/dist/AgentBaseContext.d.ts.map +0 -1
- package/dist/AgentBaseContext.js +0 -33
- package/dist/AgentBaseContext.js.map +0 -1
- package/dist/AgentBasePersistence.d.ts.map +0 -1
- package/dist/AgentBasePersistence.js +0 -2
- package/dist/AgentBasePersistence.js.map +0 -1
|
@@ -0,0 +1,401 @@
|
|
|
1
|
+
import { createId } from "@paralleldrive/cuid2";
|
|
2
|
+
import { Value } from "@sinclair/typebox/value";
|
|
3
|
+
import { asyncLock } from "@steve.kite/stdlib";
|
|
4
|
+
import { Agent } from "./Agent.js";
|
|
5
|
+
import {} from "./AgentBase.js";
|
|
6
|
+
import { agentId as agentIdOf } from "./AgentContexts.js";
|
|
7
|
+
import { agentConfigSchema, withAgentConfig } from "./AgentConfig.js";
|
|
8
|
+
import { withAgentSystem } from "./AgentSystemContext.js";
|
|
9
|
+
import { AgentSystemRef } from "./AgentSystemRef.js";
|
|
10
|
+
/**
|
|
11
|
+
* The `AgentSystem` backed by this process: it lazily builds and owns the `Agent` instances for
|
|
12
|
+
* the identities its storage holds. Concurrent resolutions of the same ID share one load, while a
|
|
13
|
+
* failed load is forgotten so a later resolution can retry.
|
|
14
|
+
*
|
|
15
|
+
* Work serializes per agent rather than per collection: a collection-wide lock would make one
|
|
16
|
+
* agent's feature load block every other agent, including one that load itself resolves.
|
|
17
|
+
*
|
|
18
|
+
* This is the owner's handle, and some of what it offers waits for an agent to reach a point only
|
|
19
|
+
* that agent's run loop can bring it to. Hand an `AgentSystemRef` to anything running inside an
|
|
20
|
+
* agent instead.
|
|
21
|
+
*/
|
|
22
|
+
export class AgentSystemLocal {
|
|
23
|
+
/** The models this collection offers its agents. */
|
|
24
|
+
models;
|
|
25
|
+
/** The lifetime context retained by this system and its storage lock. */
|
|
26
|
+
#ctx;
|
|
27
|
+
/**
|
|
28
|
+
* What this collection looks like from inside one of its agents, and the only form of it a
|
|
29
|
+
* derived context ever carries.
|
|
30
|
+
*/
|
|
31
|
+
#ref = new AgentSystemRef(this);
|
|
32
|
+
/** The collection's feature instances, every one of them serving every agent it builds. */
|
|
33
|
+
#features;
|
|
34
|
+
/** Where the collection's identities, configuration, and per-agent state are durable. */
|
|
35
|
+
#storage;
|
|
36
|
+
/** The registry providers are resolved from when an agent is built. */
|
|
37
|
+
#providers;
|
|
38
|
+
/** The registry ID of the provider new agents are created with. */
|
|
39
|
+
#provider;
|
|
40
|
+
/** Exclusive database-backed ownership of this collection's whole durable store. */
|
|
41
|
+
#storageLock;
|
|
42
|
+
/** The configuration each identity was created with. */
|
|
43
|
+
#configs;
|
|
44
|
+
/**
|
|
45
|
+
* The root of the store features share across the collection. Each feature works under its
|
|
46
|
+
* own scope of it, which is where anything outliving one agent's conversation belongs.
|
|
47
|
+
*/
|
|
48
|
+
#sharedFeatureKV;
|
|
49
|
+
/** The live `Agent` instances this process has built, keyed by identity. */
|
|
50
|
+
#agents = new Map();
|
|
51
|
+
// One agent has one store for the life of the collection, so inspecting an agent's durable
|
|
52
|
+
// work and running that agent never end up looking at two different stores.
|
|
53
|
+
#persistences = new Map();
|
|
54
|
+
/** Per-agent locks handed out by `#lockFor`, created lazily the first time an ID is touched. */
|
|
55
|
+
#locks = new Map();
|
|
56
|
+
/** Public operations admitted before shutdown and therefore allowed to finish. */
|
|
57
|
+
#admitted = new Set();
|
|
58
|
+
/** No agent operation is admitted until every feature has finished its beforeStart hook. */
|
|
59
|
+
#lifecycle = "initializing";
|
|
60
|
+
/** The shared shutdown, including release of the hard storage lock. */
|
|
61
|
+
#closePromise;
|
|
62
|
+
/**
|
|
63
|
+
* Bring up a collection over one storage and carry on where the last process left off.
|
|
64
|
+
*
|
|
65
|
+
* A collection is not a passive registry that happens to be asked for agents later: whatever
|
|
66
|
+
* was running when the previous process ended is still owed an answer, and this is what
|
|
67
|
+
* makes it happen. Every identity the storage holds is examined, and each one that owes work
|
|
68
|
+
* is resolved and resumed, so by the time this returns the collection is not merely built
|
|
69
|
+
* but running.
|
|
70
|
+
*/
|
|
71
|
+
static async create(ctx, storage, config) {
|
|
72
|
+
const systemCtx = ctx;
|
|
73
|
+
const storageLock = await storage.acquireLock(systemCtx);
|
|
74
|
+
const system = new AgentSystemLocal(systemCtx, storage, storageLock, config);
|
|
75
|
+
try {
|
|
76
|
+
await system.#beforeStart(systemCtx);
|
|
77
|
+
const active = await system.#start(systemCtx);
|
|
78
|
+
system.#lifecycle = "open";
|
|
79
|
+
for (const agent of active)
|
|
80
|
+
agent.start();
|
|
81
|
+
await system.#afterStart(systemCtx);
|
|
82
|
+
return system;
|
|
83
|
+
}
|
|
84
|
+
catch (error) {
|
|
85
|
+
await system.close(systemCtx).catch(() => undefined);
|
|
86
|
+
throw error;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Wire this collection to its storage, providers, and feature configuration, without reading
|
|
91
|
+
* any of it. Private: a collection is brought up by `create`, which also resumes the work
|
|
92
|
+
* the storage was left holding — building one without that is building half of it.
|
|
93
|
+
*/
|
|
94
|
+
constructor(ctx, storage, storageLock, options) {
|
|
95
|
+
this.#ctx = ctx;
|
|
96
|
+
this.#features = options.features ?? [];
|
|
97
|
+
this.#storage = storage;
|
|
98
|
+
this.#storageLock = storageLock;
|
|
99
|
+
this.#providers = options.providers;
|
|
100
|
+
this.#provider = options.provider;
|
|
101
|
+
this.models = [...options.models];
|
|
102
|
+
this.#configs = storage.kv.scoped("config");
|
|
103
|
+
this.#sharedFeatureKV = storage.kv.scoped("features");
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Stop every live agent, wait for operations already admitted by this owner, and only then
|
|
107
|
+
* release the database lock. Repeated callers join the same shutdown.
|
|
108
|
+
*/
|
|
109
|
+
async close(ctx) {
|
|
110
|
+
if (this.#closePromise === undefined) {
|
|
111
|
+
this.#lifecycle = "closing";
|
|
112
|
+
this.#closePromise = this.#shutdown();
|
|
113
|
+
}
|
|
114
|
+
const closing = this.#closePromise;
|
|
115
|
+
const caller = agentIdOf(ctx);
|
|
116
|
+
if (caller !== undefined && this.#agents.has(caller)) {
|
|
117
|
+
void closing.catch(() => undefined);
|
|
118
|
+
throw new Error("Closing the agent system from inside one of its own agents would wait for " +
|
|
119
|
+
"that agent's turn. Shutdown will finish and release the store after this " +
|
|
120
|
+
"caller returns.");
|
|
121
|
+
}
|
|
122
|
+
await closing;
|
|
123
|
+
}
|
|
124
|
+
/** The real shutdown barrier, which keeps the hard store lock until every agent is closed. */
|
|
125
|
+
async #shutdown() {
|
|
126
|
+
try {
|
|
127
|
+
while (this.#admitted.size > 0) {
|
|
128
|
+
await Promise.allSettled(this.#admitted);
|
|
129
|
+
}
|
|
130
|
+
const closed = [...this.#agents.values()].map((agent) => {
|
|
131
|
+
void agent.close().catch(() => undefined);
|
|
132
|
+
return agent.waitForClosed();
|
|
133
|
+
});
|
|
134
|
+
await Promise.allSettled(closed);
|
|
135
|
+
this.#agents.clear();
|
|
136
|
+
this.#persistences.clear();
|
|
137
|
+
this.#locks.clear();
|
|
138
|
+
}
|
|
139
|
+
finally {
|
|
140
|
+
try {
|
|
141
|
+
await this.#storageLock.release(this.#ctx);
|
|
142
|
+
}
|
|
143
|
+
finally {
|
|
144
|
+
this.#lifecycle = "closed";
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* Admit one public operation while this system still owns the store. Shutdown rejects new
|
|
150
|
+
* admissions and waits for every earlier one before releasing the hard lock.
|
|
151
|
+
*/
|
|
152
|
+
#admit(operation) {
|
|
153
|
+
if (this.#lifecycle !== "open") {
|
|
154
|
+
return Promise.reject(new Error(this.#lifecycle === "initializing"
|
|
155
|
+
? "The agent system is not ready."
|
|
156
|
+
: "The agent system is closed."));
|
|
157
|
+
}
|
|
158
|
+
let running;
|
|
159
|
+
try {
|
|
160
|
+
// Begin synchronously so ownership-transfer boundaries such as create(config) copy
|
|
161
|
+
// caller-owned input before the caller can mutate it after receiving the promise.
|
|
162
|
+
running = operation();
|
|
163
|
+
}
|
|
164
|
+
catch (error) {
|
|
165
|
+
return Promise.reject(error);
|
|
166
|
+
}
|
|
167
|
+
const settled = running.then(() => undefined, () => undefined);
|
|
168
|
+
this.#admitted.add(settled);
|
|
169
|
+
void settled.finally(() => this.#admitted.delete(settled));
|
|
170
|
+
return running;
|
|
171
|
+
}
|
|
172
|
+
/**
|
|
173
|
+
* Create an agent with the configuration it keeps for its whole life, and resolve it. The
|
|
174
|
+
* identity is allocated here and nowhere else: it is a cuid2, globally unique, so a new
|
|
175
|
+
* agent never lands on an identity that already exists or on a store something else wrote.
|
|
176
|
+
* The configuration is persisted before the agent runs, so every later process resolves the
|
|
177
|
+
* agent exactly as it was created.
|
|
178
|
+
*
|
|
179
|
+
* Nothing here is undone: an agent whose features refuse to load leaves an identity that
|
|
180
|
+
* exists, is resolvable, and will be built the next time something wants it. Taking a
|
|
181
|
+
* provisional identity back after a failed build would add a compensation that can itself
|
|
182
|
+
* fail.
|
|
183
|
+
*/
|
|
184
|
+
async create(ctx, config, initialContext) {
|
|
185
|
+
return await this.#admit(async () => {
|
|
186
|
+
const agentId = createId();
|
|
187
|
+
if (!Value.Check(agentConfigSchema, config)) {
|
|
188
|
+
throw new Error(`The configuration for agent "${agentId}" is not valid.`);
|
|
189
|
+
}
|
|
190
|
+
// The caller keeps its own object, and may go on editing it. What was created is what
|
|
191
|
+
// was passed at this moment, so storage and this agent's context both get a copy.
|
|
192
|
+
const owned = structuredClone(config);
|
|
193
|
+
return await this.#lockFor(agentId).runInLock(ctx, async (lockCtx) => {
|
|
194
|
+
await this.#configs.write(lockCtx, agentId, owned);
|
|
195
|
+
if (initialContext !== undefined) {
|
|
196
|
+
await this.#seedInitialContext(lockCtx, agentId, initialContext.messages);
|
|
197
|
+
}
|
|
198
|
+
const agent = await this.#instantiate(lockCtx, agentId, owned);
|
|
199
|
+
if (agent === undefined)
|
|
200
|
+
throw new Error(`Agent "${agentId}" could not be built.`);
|
|
201
|
+
return agent;
|
|
202
|
+
});
|
|
203
|
+
});
|
|
204
|
+
}
|
|
205
|
+
/**
|
|
206
|
+
* Close an agent and release its identity, so the same ID can be created again. Used to undo
|
|
207
|
+
* a creation whose follow-up work failed; an ID that was never created is left alone.
|
|
208
|
+
*
|
|
209
|
+
* What the agent wrote is left where it is. The close finishes first, so the store holds a
|
|
210
|
+
* whole conversation rather than a truncated one, and that record is worth more here than the
|
|
211
|
+
* space it takes: whoever deleted the agent may still want to know what it did. The next
|
|
212
|
+
* identity created under this ID starts from an empty store all the same, because creation is
|
|
213
|
+
* what clears it.
|
|
214
|
+
*/
|
|
215
|
+
async delete(ctx, agentId) {
|
|
216
|
+
await this.#admit(async () => {
|
|
217
|
+
await this.#lockFor(agentId).runInLock(ctx, async (lockCtx) => {
|
|
218
|
+
const agent = this.#agents.get(agentId);
|
|
219
|
+
this.#agents.delete(agentId);
|
|
220
|
+
await agent?.close();
|
|
221
|
+
await this.#configs.delete(lockCtx, agentId);
|
|
222
|
+
this.#persistences.delete(agentId);
|
|
223
|
+
});
|
|
224
|
+
});
|
|
225
|
+
}
|
|
226
|
+
/** Install a projected conversation before the new agent is started. */
|
|
227
|
+
async #seedInitialContext(ctx, agentId, messages) {
|
|
228
|
+
if (messages.length === 0)
|
|
229
|
+
return;
|
|
230
|
+
const persistence = this.#persistenceFor(agentId);
|
|
231
|
+
await persistence.transaction(ctx, async (txCtx) => {
|
|
232
|
+
await persistence.append(txCtx, {
|
|
233
|
+
type: "compaction",
|
|
234
|
+
messages: structuredClone(messages),
|
|
235
|
+
});
|
|
236
|
+
});
|
|
237
|
+
}
|
|
238
|
+
/** The configuration an agent was created with, or undefined when there is no such agent. */
|
|
239
|
+
async config(ctx, agentId) {
|
|
240
|
+
return await this.#admit(async () => await this.#config(ctx, agentId));
|
|
241
|
+
}
|
|
242
|
+
/** Read one stored configuration while its owning operation is already admitted. */
|
|
243
|
+
async #config(ctx, agentId) {
|
|
244
|
+
const stored = await this.#configs.read(ctx, agentId);
|
|
245
|
+
if (stored === undefined)
|
|
246
|
+
return undefined;
|
|
247
|
+
if (!Value.Check(agentConfigSchema, stored)) {
|
|
248
|
+
throw new Error(`The stored configuration of agent "${agentId}" is not valid.`);
|
|
249
|
+
}
|
|
250
|
+
return stored;
|
|
251
|
+
}
|
|
252
|
+
/**
|
|
253
|
+
* The live agent for an ID, loading and starting it if this process has not seen it yet.
|
|
254
|
+
* Concurrent resolutions of the same ID share one load.
|
|
255
|
+
*/
|
|
256
|
+
async resolve(ctx, agentId) {
|
|
257
|
+
return await this.#admit(async () => await this.#resolve(ctx, agentId));
|
|
258
|
+
}
|
|
259
|
+
/** Resolve one agent while its owning public operation is already admitted. */
|
|
260
|
+
async #resolve(ctx, agentId) {
|
|
261
|
+
const existing = this.#agents.get(agentId);
|
|
262
|
+
if (existing !== undefined)
|
|
263
|
+
return existing;
|
|
264
|
+
return await this.#lockFor(agentId).runInLock(ctx, async (lockCtx) => {
|
|
265
|
+
const resolved = this.#agents.get(agentId);
|
|
266
|
+
if (resolved !== undefined)
|
|
267
|
+
return resolved;
|
|
268
|
+
const config = await this.#config(lockCtx, agentId);
|
|
269
|
+
if (config === undefined) {
|
|
270
|
+
throw new Error(`Agent "${agentId}" has not been created.`);
|
|
271
|
+
}
|
|
272
|
+
const agent = await this.#instantiate(lockCtx, agentId, config);
|
|
273
|
+
if (agent === undefined)
|
|
274
|
+
throw new Error(`Agent "${agentId}" could not be built.`);
|
|
275
|
+
return agent;
|
|
276
|
+
});
|
|
277
|
+
}
|
|
278
|
+
/**
|
|
279
|
+
* Build one agent and put it to work. Called with the agent's lock held, and only for an ID
|
|
280
|
+
* that has no live instance yet.
|
|
281
|
+
*/
|
|
282
|
+
async #instantiate(ctx, agentId, config, onlyIfActive = false, start = true) {
|
|
283
|
+
const agentCtx = withAgentConfig(withAgentSystem(ctx, this.#ref), config);
|
|
284
|
+
const options = {
|
|
285
|
+
id: agentId,
|
|
286
|
+
providers: this.#providers,
|
|
287
|
+
provider: this.#provider,
|
|
288
|
+
persistence: this.#persistenceFor(agentId),
|
|
289
|
+
sharedKV: this.#sharedFeatureKV,
|
|
290
|
+
// The collection's features come first, so the instructions they contribute — the
|
|
291
|
+
// system prompt above all — open every agent's prompt.
|
|
292
|
+
features: this.#features,
|
|
293
|
+
};
|
|
294
|
+
// An identity built here may already have durable state — this is the path a restart
|
|
295
|
+
// resolves through — so the agent is loaded rather than created, and knows whether it
|
|
296
|
+
// has work left before anything asks it. Bringing a collection up asks only for the
|
|
297
|
+
// agents that do; anything else resolving an agent wants it whether it owes work or not.
|
|
298
|
+
const agent = await Agent.load(agentCtx, options);
|
|
299
|
+
if (onlyIfActive && !agent.active) {
|
|
300
|
+
await agent.close();
|
|
301
|
+
return undefined;
|
|
302
|
+
}
|
|
303
|
+
this.#agents.set(agentId, agent);
|
|
304
|
+
if (start)
|
|
305
|
+
agent.start();
|
|
306
|
+
return agent;
|
|
307
|
+
}
|
|
308
|
+
/**
|
|
309
|
+
* Resolve and resume every agent that has work left from before this process started.
|
|
310
|
+
*
|
|
311
|
+
* The active index is a fast answer, not the authority. It is written by a live run and can
|
|
312
|
+
* Every identity the storage holds is asked whether it has work left, and the ones that do
|
|
313
|
+
* are built and set going. The question is one key in the agent's own store, and only the
|
|
314
|
+
* agent answers it: the collection keeps no index of its own to go stale, and an identity is
|
|
315
|
+
* never dismissed on the strength of something written about it elsewhere.
|
|
316
|
+
*
|
|
317
|
+
* Building the agent is all this does. An agent picks its own work back up when it is
|
|
318
|
+
* loaded, so the collection has only to bring the right ones into existence.
|
|
319
|
+
*/
|
|
320
|
+
async #start(ctx) {
|
|
321
|
+
const created = await this.#configs.list(ctx);
|
|
322
|
+
const results = await Promise.allSettled(created.map(async ({ key: agentId, value }) => {
|
|
323
|
+
if (!Value.Check(agentConfigSchema, value))
|
|
324
|
+
return undefined;
|
|
325
|
+
return await this.#lockFor(agentId).runInLock(ctx, async (lockCtx) => {
|
|
326
|
+
if (this.#agents.has(agentId))
|
|
327
|
+
return undefined;
|
|
328
|
+
return await this.#instantiate(lockCtx, agentId, value, true, false);
|
|
329
|
+
});
|
|
330
|
+
}));
|
|
331
|
+
throwFirstStartFailure(results);
|
|
332
|
+
return results.flatMap((result) => result.status === "fulfilled" && result.value !== undefined ? [result.value] : []);
|
|
333
|
+
}
|
|
334
|
+
/** Initialize every feature before any active agent is restored or started. */
|
|
335
|
+
async #beforeStart(ctx) {
|
|
336
|
+
const startCtx = withAgentSystem(ctx, this.#ref);
|
|
337
|
+
const results = await Promise.allSettled(this.#features.map(async (feature) => await feature.beforeStart?.(startCtx, this.#ref)));
|
|
338
|
+
throwFirstStartFailure(results);
|
|
339
|
+
}
|
|
340
|
+
/** Notify every feature after all active agents have been restored and started. */
|
|
341
|
+
async #afterStart(ctx) {
|
|
342
|
+
const startCtx = withAgentSystem(ctx, this.#ref);
|
|
343
|
+
const results = await Promise.allSettled(this.#features.map(async (feature) => await feature.afterStart?.(startCtx, this.#ref)));
|
|
344
|
+
throwFirstStartFailure(results);
|
|
345
|
+
}
|
|
346
|
+
/** The durable store for one agent, created once and reused for the life of the collection. */
|
|
347
|
+
#persistenceFor(agentId) {
|
|
348
|
+
const existing = this.#persistences.get(agentId);
|
|
349
|
+
if (existing !== undefined)
|
|
350
|
+
return existing;
|
|
351
|
+
const created = this.#storage.persistence(agentId);
|
|
352
|
+
this.#persistences.set(agentId, created);
|
|
353
|
+
return created;
|
|
354
|
+
}
|
|
355
|
+
/**
|
|
356
|
+
* The lock serializing this collection's work on one identity. It is per agent because the
|
|
357
|
+
* work it guards — building an agent, which loads every feature — may itself resolve another
|
|
358
|
+
* agent from this same collection, and a collection-wide lock would deadlock on it.
|
|
359
|
+
*/
|
|
360
|
+
#lockFor(agentId) {
|
|
361
|
+
const existing = this.#locks.get(agentId);
|
|
362
|
+
if (existing !== undefined)
|
|
363
|
+
return existing;
|
|
364
|
+
const created = asyncLock({ reentry: "block" });
|
|
365
|
+
this.#locks.set(agentId, created);
|
|
366
|
+
return created;
|
|
367
|
+
}
|
|
368
|
+
/** Queue a steered message for an agent. */
|
|
369
|
+
async steer(ctx, agentId, message, options) {
|
|
370
|
+
await this.#admit(async () => {
|
|
371
|
+
const agent = await this.#resolve(ctx, agentId);
|
|
372
|
+
await agent.steer(ctx, message, options);
|
|
373
|
+
});
|
|
374
|
+
}
|
|
375
|
+
/** Queue a message for an agent. */
|
|
376
|
+
async send(ctx, agentId, message, options) {
|
|
377
|
+
await this.#admit(async () => {
|
|
378
|
+
const agent = await this.#resolve(ctx, agentId);
|
|
379
|
+
await agent.send(ctx, message, options);
|
|
380
|
+
});
|
|
381
|
+
}
|
|
382
|
+
/** Cancel an agent's active turn, leaving its queued messages durable for the next one. */
|
|
383
|
+
async abort(ctx, agentId, options) {
|
|
384
|
+
await this.#admit(async () => {
|
|
385
|
+
await (await this.#resolve(ctx, agentId)).abort(ctx, options);
|
|
386
|
+
});
|
|
387
|
+
}
|
|
388
|
+
/** Ask an agent for its conversation to be replaced by the provider's summary of it. */
|
|
389
|
+
async compact(ctx, agentId, options) {
|
|
390
|
+
await this.#admit(async () => {
|
|
391
|
+
await (await this.#resolve(ctx, agentId)).compact(ctx, options);
|
|
392
|
+
});
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
/** Start every feature even when one fails, then surface the first failure in feature order. */
|
|
396
|
+
function throwFirstStartFailure(results) {
|
|
397
|
+
const failure = results.find((result) => result.status === "rejected");
|
|
398
|
+
if (failure !== undefined)
|
|
399
|
+
throw failure.reason;
|
|
400
|
+
}
|
|
401
|
+
//# sourceMappingURL=AgentSystemLocal.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AgentSystemLocal.js","sourceRoot":"","sources":["../sources/AgentSystemLocal.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import type { SessionUserMessage } from "@slopus/happy-providers";
|
|
2
|
+
import type { Context } from "@steve.kite/stdlib";
|
|
3
|
+
import type { AgentBaseMessageOptions } from "./AgentBase.js";
|
|
4
|
+
import type { AgentConfig } from "./AgentConfig.js";
|
|
5
|
+
import type { AgentModel } from "./AgentModel.js";
|
|
6
|
+
import { AgentRef } from "./AgentRef.js";
|
|
7
|
+
import type { AgentInitialContext, AgentSystem } from "./AgentSystem.js";
|
|
8
|
+
/**
|
|
9
|
+
* A reference to a collection of agents that cannot deadlock, for code that runs inside an agent
|
|
10
|
+
* — a feature hook, or a tool the run loop is waiting on. Every operation returns without
|
|
11
|
+
* waiting for any agent's loop to reach a particular point.
|
|
12
|
+
*
|
|
13
|
+
* What is missing is missing on purpose. `delete` closes an agent and `start` resumes whole
|
|
14
|
+
* agents; both are the owning caller's business, and both would wait for a loop that may be
|
|
15
|
+
* waiting for the very code asking. Agents come back as `AgentRef` for the same reason — handing
|
|
16
|
+
* out the real `Agent` would hand back `close` and `waitForIdle` along with the `await: true`
|
|
17
|
+
* that waits for a compaction or an unwound turn.
|
|
18
|
+
*
|
|
19
|
+
* A message is the one thing a caller here may be told about, because accepting one is a durable
|
|
20
|
+
* queue write rather than a turn: `steer` and `send` resolve once the message is safely part of
|
|
21
|
+
* the target agent's conversation, and reject when that write fails, so a caller routing work to
|
|
22
|
+
* another agent knows whether it arrived. The exception is the caller's own agent, whose loop is
|
|
23
|
+
* what would have to perform that write — asked for itself, the message is queued and not waited
|
|
24
|
+
* for. That is decided from the context, which names the agent the caller is running inside; a
|
|
25
|
+
* context that names none proves nothing, so nothing is waited for there either.
|
|
26
|
+
*/
|
|
27
|
+
export declare class AgentSystemRef {
|
|
28
|
+
#private;
|
|
29
|
+
/** Wrap a collection as the deadlock-free reference given to code running inside it. */
|
|
30
|
+
constructor(system: AgentSystem);
|
|
31
|
+
/** The models this collection offers its agents. */
|
|
32
|
+
get models(): readonly AgentModel[];
|
|
33
|
+
/** Create an agent with a new system-generated cuid2 identity. */
|
|
34
|
+
create(ctx: Context, config: AgentConfig, initialContext?: AgentInitialContext): Promise<AgentRef>;
|
|
35
|
+
/** A reference to an existing agent; resolving one that was never created is an error. */
|
|
36
|
+
resolve(ctx: Context, agentId: string): Promise<AgentRef>;
|
|
37
|
+
/** The configuration an agent was created with, or undefined when there is no such agent. */
|
|
38
|
+
config(ctx: Context, agentId: string): Promise<AgentConfig | undefined>;
|
|
39
|
+
/**
|
|
40
|
+
* Queue a steered message. For another agent this resolves once the message is durably
|
|
41
|
+
* accepted and rejects when that write fails; for the caller's own agent it resolves as soon
|
|
42
|
+
* as the agent has taken the request on.
|
|
43
|
+
*/
|
|
44
|
+
steer(ctx: Context, agentId: string, message: SessionUserMessage, options?: AgentBaseMessageOptions): Promise<void>;
|
|
45
|
+
/**
|
|
46
|
+
* Queue a sent message. For another agent this resolves once the message is durably accepted
|
|
47
|
+
* and rejects when that write fails; for the caller's own agent it resolves as soon as the
|
|
48
|
+
* agent has taken the request on.
|
|
49
|
+
*/
|
|
50
|
+
send(ctx: Context, agentId: string, message: SessionUserMessage, options?: AgentBaseMessageOptions): Promise<void>;
|
|
51
|
+
/** Ask an agent to compact, and resolve once it has been asked. */
|
|
52
|
+
compact(ctx: Context, agentId: string): Promise<void>;
|
|
53
|
+
/** Cancel an agent's active turn, and resolve once the cancellation has been signalled. */
|
|
54
|
+
abort(ctx: Context, agentId: string): Promise<void>;
|
|
55
|
+
}
|
|
56
|
+
//# sourceMappingURL=AgentSystemRef.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AgentSystemRef.d.ts","sourceRoot":"","sources":["../sources/AgentSystemRef.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAClE,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAElD,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,gBAAgB,CAAC;AAC9D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AACpD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAClD,OAAO,EAAwB,QAAQ,EAAE,MAAM,eAAe,CAAC;AAC/D,OAAO,KAAK,EAAE,mBAAmB,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAEzE;;;;;;;;;;;;;;;;;;GAkBG;AACH,qBAAa,cAAc;;IAIvB,wFAAwF;IACxF,YAAY,MAAM,EAAE,WAAW,EAE9B;IAED,oDAAoD;IACpD,IAAI,MAAM,IAAI,SAAS,UAAU,EAAE,CAElC;IAED,kEAAkE;IAC5D,MAAM,CACR,GAAG,EAAE,OAAO,EACZ,MAAM,EAAE,WAAW,EACnB,cAAc,CAAC,EAAE,mBAAmB,GACrC,OAAO,CAAC,QAAQ,CAAC,CAEnB;IAED,0FAA0F;IACpF,OAAO,CAAC,GAAG,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,CAAC,CAE9D;IAED,6FAA6F;IACvF,MAAM,CAAC,GAAG,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,GAAG,SAAS,CAAC,CAE5E;IAED;;;;OAIG;IACG,KAAK,CACP,GAAG,EAAE,OAAO,EACZ,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,kBAAkB,EAC3B,OAAO,CAAC,EAAE,uBAAuB,GAClC,OAAO,CAAC,IAAI,CAAC,CAKf;IAED;;;;OAIG;IACG,IAAI,CACN,GAAG,EAAE,OAAO,EACZ,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,kBAAkB,EAC3B,OAAO,CAAC,EAAE,uBAAuB,GAClC,OAAO,CAAC,IAAI,CAAC,CAKf;IAED,mEAAmE;IAC7D,OAAO,CAAC,GAAG,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAE1D;IAED,2FAA2F;IACrF,KAAK,CAAC,GAAG,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAExD;CACJ"}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { acceptanceIsWaitable, AgentRef } from "./AgentRef.js";
|
|
2
|
+
/**
|
|
3
|
+
* A reference to a collection of agents that cannot deadlock, for code that runs inside an agent
|
|
4
|
+
* — a feature hook, or a tool the run loop is waiting on. Every operation returns without
|
|
5
|
+
* waiting for any agent's loop to reach a particular point.
|
|
6
|
+
*
|
|
7
|
+
* What is missing is missing on purpose. `delete` closes an agent and `start` resumes whole
|
|
8
|
+
* agents; both are the owning caller's business, and both would wait for a loop that may be
|
|
9
|
+
* waiting for the very code asking. Agents come back as `AgentRef` for the same reason — handing
|
|
10
|
+
* out the real `Agent` would hand back `close` and `waitForIdle` along with the `await: true`
|
|
11
|
+
* that waits for a compaction or an unwound turn.
|
|
12
|
+
*
|
|
13
|
+
* A message is the one thing a caller here may be told about, because accepting one is a durable
|
|
14
|
+
* queue write rather than a turn: `steer` and `send` resolve once the message is safely part of
|
|
15
|
+
* the target agent's conversation, and reject when that write fails, so a caller routing work to
|
|
16
|
+
* another agent knows whether it arrived. The exception is the caller's own agent, whose loop is
|
|
17
|
+
* what would have to perform that write — asked for itself, the message is queued and not waited
|
|
18
|
+
* for. That is decided from the context, which names the agent the caller is running inside; a
|
|
19
|
+
* context that names none proves nothing, so nothing is waited for there either.
|
|
20
|
+
*/
|
|
21
|
+
export class AgentSystemRef {
|
|
22
|
+
/** The collection this reference forwards every operation to without waiting on its loops. */
|
|
23
|
+
#system;
|
|
24
|
+
/** Wrap a collection as the deadlock-free reference given to code running inside it. */
|
|
25
|
+
constructor(system) {
|
|
26
|
+
this.#system = system;
|
|
27
|
+
}
|
|
28
|
+
/** The models this collection offers its agents. */
|
|
29
|
+
get models() {
|
|
30
|
+
return this.#system.models;
|
|
31
|
+
}
|
|
32
|
+
/** Create an agent with a new system-generated cuid2 identity. */
|
|
33
|
+
async create(ctx, config, initialContext) {
|
|
34
|
+
return new AgentRef(await this.#system.create(ctx, config, initialContext));
|
|
35
|
+
}
|
|
36
|
+
/** A reference to an existing agent; resolving one that was never created is an error. */
|
|
37
|
+
async resolve(ctx, agentId) {
|
|
38
|
+
return new AgentRef(await this.#system.resolve(ctx, agentId));
|
|
39
|
+
}
|
|
40
|
+
/** The configuration an agent was created with, or undefined when there is no such agent. */
|
|
41
|
+
async config(ctx, agentId) {
|
|
42
|
+
return await this.#system.config(ctx, agentId);
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Queue a steered message. For another agent this resolves once the message is durably
|
|
46
|
+
* accepted and rejects when that write fails; for the caller's own agent it resolves as soon
|
|
47
|
+
* as the agent has taken the request on.
|
|
48
|
+
*/
|
|
49
|
+
async steer(ctx, agentId, message, options) {
|
|
50
|
+
await this.#system.steer(ctx, agentId, message, {
|
|
51
|
+
...options,
|
|
52
|
+
await: acceptanceIsWaitable(ctx, agentId),
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Queue a sent message. For another agent this resolves once the message is durably accepted
|
|
57
|
+
* and rejects when that write fails; for the caller's own agent it resolves as soon as the
|
|
58
|
+
* agent has taken the request on.
|
|
59
|
+
*/
|
|
60
|
+
async send(ctx, agentId, message, options) {
|
|
61
|
+
await this.#system.send(ctx, agentId, message, {
|
|
62
|
+
...options,
|
|
63
|
+
await: acceptanceIsWaitable(ctx, agentId),
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
/** Ask an agent to compact, and resolve once it has been asked. */
|
|
67
|
+
async compact(ctx, agentId) {
|
|
68
|
+
await (await this.resolve(ctx, agentId)).compact(ctx);
|
|
69
|
+
}
|
|
70
|
+
/** Cancel an agent's active turn, and resolve once the cancellation has been signalled. */
|
|
71
|
+
async abort(ctx, agentId) {
|
|
72
|
+
await (await this.resolve(ctx, agentId)).abort(ctx);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
//# sourceMappingURL=AgentSystemRef.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AgentSystemRef.js","sourceRoot":"","sources":["../sources/AgentSystemRef.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,oBAAoB,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAG/D;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,OAAO,cAAc;IACvB,8FAA8F;IACrF,OAAO,CAAc;IAE9B,wFAAwF;IACxF,YAAY,MAAmB;QAC3B,IAAI,CAAC,OAAO,GAAG,MAAM,CAAC;IAC1B,CAAC;IAED,oDAAoD;IACpD,IAAI,MAAM;QACN,OAAO,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC;IAC/B,CAAC;IAED,kEAAkE;IAClE,KAAK,CAAC,MAAM,CACR,GAAY,EACZ,MAAmB,EACnB,cAAoC;QAEpC,OAAO,IAAI,QAAQ,CAAC,MAAM,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,GAAG,EAAE,MAAM,EAAE,cAAc,CAAC,CAAC,CAAC;IAChF,CAAC;IAED,0FAA0F;IAC1F,KAAK,CAAC,OAAO,CAAC,GAAY,EAAE,OAAe;QACvC,OAAO,IAAI,QAAQ,CAAC,MAAM,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC,CAAC;IAClE,CAAC;IAED,6FAA6F;IAC7F,KAAK,CAAC,MAAM,CAAC,GAAY,EAAE,OAAe;QACtC,OAAO,MAAM,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;IACnD,CAAC;IAED;;;;OAIG;IACH,KAAK,CAAC,KAAK,CACP,GAAY,EACZ,OAAe,EACf,OAA2B,EAC3B,OAAiC;QAEjC,MAAM,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,GAAG,EAAE,OAAO,EAAE,OAAO,EAAE;YAC5C,GAAG,OAAO;YACV,KAAK,EAAE,oBAAoB,CAAC,GAAG,EAAE,OAAO,CAAC;SAC5C,CAAC,CAAC;IACP,CAAC;IAED;;;;OAIG;IACH,KAAK,CAAC,IAAI,CACN,GAAY,EACZ,OAAe,EACf,OAA2B,EAC3B,OAAiC;QAEjC,MAAM,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,EAAE,OAAO,EAAE,OAAO,EAAE;YAC3C,GAAG,OAAO;YACV,KAAK,EAAE,oBAAoB,CAAC,GAAG,EAAE,OAAO,CAAC;SAC5C,CAAC,CAAC;IACP,CAAC;IAED,mEAAmE;IACnE,KAAK,CAAC,OAAO,CAAC,GAAY,EAAE,OAAe;QACvC,MAAM,CAAC,MAAM,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IAC1D,CAAC;IAED,2FAA2F;IAC3F,KAAK,CAAC,KAAK,CAAC,GAAY,EAAE,OAAe;QACrC,MAAM,CAAC,MAAM,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IACxD,CAAC;CACJ"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { SessionMessage } from "@slopus/happy-providers";
|
|
2
|
+
import { type Context } from "@steve.kite/stdlib";
|
|
3
|
+
/**
|
|
4
|
+
* Carry the parent conversation that existed before the assistant response containing the
|
|
5
|
+
* current tool call. The snapshot is immutable caller context: collaboration can fork it without
|
|
6
|
+
* gaining a general-purpose history-reading capability.
|
|
7
|
+
*/
|
|
8
|
+
export declare function withAgentTaskContext(ctx: Context, messages: readonly SessionMessage[]): Context;
|
|
9
|
+
/** The pre-tool-call parent conversation available to the current tool execution. */
|
|
10
|
+
export declare function agentTaskContext(ctx: Context): readonly SessionMessage[];
|
|
11
|
+
/**
|
|
12
|
+
* Select everything before the assistant response that issued `callId`. Removing the complete
|
|
13
|
+
* response follows Codex's fork boundary and prevents sibling calls, reasoning, or prefatory
|
|
14
|
+
* assistant text from leaking into a child while that response is still being settled.
|
|
15
|
+
*/
|
|
16
|
+
export declare function taskContextBeforeToolCall(messages: readonly SessionMessage[], callId: string): readonly SessionMessage[];
|
|
17
|
+
//# sourceMappingURL=AgentTaskContext.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AgentTaskContext.d.ts","sourceRoot":"","sources":["../sources/AgentTaskContext.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AAC9D,OAAO,EAA0B,KAAK,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAQ1E;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,OAAO,EAAE,QAAQ,EAAE,SAAS,cAAc,EAAE,GAAG,OAAO,CAE/F;AAED,qFAAqF;AACrF,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,OAAO,GAAG,SAAS,cAAc,EAAE,CAExE;AAED;;;;GAIG;AACH,wBAAgB,yBAAyB,CACrC,QAAQ,EAAE,SAAS,cAAc,EAAE,EACnC,MAAM,EAAE,MAAM,GACf,SAAS,cAAc,EAAE,CAO3B"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { createContextNamespace } from "@steve.kite/stdlib";
|
|
2
|
+
/** Backing storage for `agentTaskContext`: the parent conversation before a tool call. */
|
|
3
|
+
const taskContextNamespace = createContextNamespace("happyAgent.taskContext", undefined);
|
|
4
|
+
/**
|
|
5
|
+
* Carry the parent conversation that existed before the assistant response containing the
|
|
6
|
+
* current tool call. The snapshot is immutable caller context: collaboration can fork it without
|
|
7
|
+
* gaining a general-purpose history-reading capability.
|
|
8
|
+
*/
|
|
9
|
+
export function withAgentTaskContext(ctx, messages) {
|
|
10
|
+
return taskContextNamespace.set(ctx, structuredClone(messages));
|
|
11
|
+
}
|
|
12
|
+
/** The pre-tool-call parent conversation available to the current tool execution. */
|
|
13
|
+
export function agentTaskContext(ctx) {
|
|
14
|
+
return structuredClone(taskContextNamespace.get(ctx) ?? []);
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Select everything before the assistant response that issued `callId`. Removing the complete
|
|
18
|
+
* response follows Codex's fork boundary and prevents sibling calls, reasoning, or prefatory
|
|
19
|
+
* assistant text from leaking into a child while that response is still being settled.
|
|
20
|
+
*/
|
|
21
|
+
export function taskContextBeforeToolCall(messages, callId) {
|
|
22
|
+
const boundary = messages.findIndex((message) => message.role === "assistant" &&
|
|
23
|
+
message.content.some((block) => block.type === "tool_call" && block.callId === callId));
|
|
24
|
+
return structuredClone(boundary < 0 ? messages : messages.slice(0, boundary));
|
|
25
|
+
}
|
|
26
|
+
//# sourceMappingURL=AgentTaskContext.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AgentTaskContext.js","sourceRoot":"","sources":["../sources/AgentTaskContext.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,sBAAsB,EAAgB,MAAM,oBAAoB,CAAC;AAE1E,0FAA0F;AAC1F,MAAM,oBAAoB,GAAG,sBAAsB,CAC/C,wBAAwB,EACxB,SAAS,CACZ,CAAC;AAEF;;;;GAIG;AACH,MAAM,UAAU,oBAAoB,CAAC,GAAY,EAAE,QAAmC;IAClF,OAAO,oBAAoB,CAAC,GAAG,CAAC,GAAG,EAAE,eAAe,CAAC,QAAQ,CAAC,CAAC,CAAC;AACpE,CAAC;AAED,qFAAqF;AACrF,MAAM,UAAU,gBAAgB,CAAC,GAAY;IACzC,OAAO,eAAe,CAAC,oBAAoB,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC;AAChE,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,yBAAyB,CACrC,QAAmC,EACnC,MAAc;IAEd,MAAM,QAAQ,GAAG,QAAQ,CAAC,SAAS,CAC/B,CAAC,OAAO,EAAE,EAAE,CACR,OAAO,CAAC,IAAI,KAAK,WAAW;QAC5B,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,KAAK,WAAW,IAAI,KAAK,CAAC,MAAM,KAAK,MAAM,CAAC,CAC7F,CAAC;IACF,OAAO,eAAe,CAAC,QAAQ,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC,CAAC;AAClF,CAAC"}
|