@demlik/tea 0.17.0 → 0.19.0
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 +4 -3
- package/dist/agent/index.d.ts +182 -35
- package/dist/agent/index.js +11 -11
- package/dist/{chunk-KWNCM6XM.js → chunk-AHW2CLPT.js} +65 -18
- package/dist/chunk-AHW2CLPT.js.map +1 -0
- package/dist/{chunk-K4ETBNKS.js → chunk-AIIXV4XB.js} +38 -9
- package/dist/chunk-AIIXV4XB.js.map +1 -0
- package/dist/{chunk-LYVOGOBC.js → chunk-BRX3243I.js} +3 -3
- package/dist/{chunk-LYVOGOBC.js.map → chunk-BRX3243I.js.map} +1 -1
- package/dist/{chunk-GWWCCSDH.js → chunk-C3G2QFEZ.js} +4 -4
- package/dist/{chunk-GWWCCSDH.js.map → chunk-C3G2QFEZ.js.map} +1 -1
- package/dist/{chunk-C4U5D5HP.js → chunk-FNGZMVIT.js} +3 -3
- package/dist/chunk-FNGZMVIT.js.map +1 -0
- package/dist/{chunk-QWIPH4YH.js → chunk-H2ELKHI6.js} +16 -6
- package/dist/chunk-H2ELKHI6.js.map +1 -0
- package/dist/chunk-H3MWNH7A.js +119 -0
- package/dist/chunk-H3MWNH7A.js.map +1 -0
- package/dist/chunk-I7E7AD2S.js +213 -0
- package/dist/chunk-I7E7AD2S.js.map +1 -0
- package/dist/{chunk-OYR7ENKU.js → chunk-IHUNKHDX.js} +3 -3
- package/dist/{chunk-OYR7ENKU.js.map → chunk-IHUNKHDX.js.map} +1 -1
- package/dist/chunk-JVE2LBFJ.js +21 -0
- package/dist/chunk-JVE2LBFJ.js.map +1 -0
- package/dist/chunk-JVKU2UQC.js +34 -0
- package/dist/chunk-JVKU2UQC.js.map +1 -0
- package/dist/{chunk-OPH6Y4UT.js → chunk-JYNYG5SF.js} +4 -4
- package/dist/{chunk-OPH6Y4UT.js.map → chunk-JYNYG5SF.js.map} +1 -1
- package/dist/{chunk-XBZQT2TD.js → chunk-PCJA2HTZ.js} +437 -162
- package/dist/chunk-PCJA2HTZ.js.map +1 -0
- package/dist/{chunk-DFUEAA6L.js → chunk-PQSDUX6B.js} +3 -3
- package/dist/{chunk-DFUEAA6L.js.map → chunk-PQSDUX6B.js.map} +1 -1
- package/dist/{chunk-6XBEYZME.js → chunk-WTSOW2MD.js} +5 -5
- package/dist/{chunk-6XBEYZME.js.map → chunk-WTSOW2MD.js.map} +1 -1
- package/dist/{chunk-4PXNZ5UY.js → chunk-XVIKSRCK.js} +4 -4
- package/dist/{chunk-4PXNZ5UY.js.map → chunk-XVIKSRCK.js.map} +1 -1
- package/dist/{chunk-4NTCPTNQ.js → chunk-YIMOFXST.js} +3 -3
- package/dist/{chunk-4NTCPTNQ.js.map → chunk-YIMOFXST.js.map} +1 -1
- package/dist/{core-rDbOaJTN.d.ts → core-Ce9ncpuv.d.ts} +5 -4
- package/dist/do/index.d.ts +140 -64
- package/dist/do/index.js +17 -18
- package/dist/do/index.js.map +1 -1
- package/dist/drive-loop-CsUsW3Wo.d.ts +127 -0
- package/dist/{durable-effects-CNaw97Be.d.ts → durable-effects-BmUrRA-h.d.ts} +1 -1
- package/dist/effect/index.d.ts +6 -150
- package/dist/effect/index.js +4 -96
- package/dist/effect/index.js.map +1 -1
- package/dist/extension/index.d.ts +7 -5
- package/dist/extension/index.js +2 -3
- package/dist/extension/index.js.map +1 -1
- package/dist/flow/index.d.ts +13 -13
- package/dist/flow/index.js +13 -12
- package/dist/flow/index.js.map +1 -1
- package/dist/idempotency/index.d.ts +3 -3
- package/dist/idempotency/index.js +4 -4
- package/dist/{index-q1PoukOZ.d.ts → index-2kNxy6az.d.ts} +2 -2
- package/dist/{index-B_BxplWi.d.ts → index-B1Wzarkl.d.ts} +1 -1
- package/dist/{index-Cberb5Rr.d.ts → index-Bf9_bNql.d.ts} +2 -2
- package/dist/index-BnsAqn0-.d.ts +286 -0
- package/dist/{index-Cx0F2M34.d.ts → index-Ce5GYAuI.d.ts} +2 -2
- package/dist/{index-CWmsXNdX.d.ts → index-D8sYVzCI.d.ts} +1 -1
- package/dist/{index-CcrKLtse.d.ts → index-DWdg7R1l.d.ts} +1 -1
- package/dist/{index-BOrsbdAf.d.ts → index-Dy3379ve.d.ts} +5 -5
- package/dist/{index-DaX_P35Q.d.ts → index-e36uEyl4.d.ts} +3 -3
- package/dist/index.d.ts +109 -36
- package/dist/index.js +2 -2
- package/dist/jev/index.d.ts +8 -8
- package/dist/jev/index.js +6 -7
- package/dist/jev/index.js.map +1 -1
- package/dist/{machine-BcfCFMYF.d.ts → machine-CuojfZup.d.ts} +353 -57
- package/dist/machine-viz/index.d.ts +1 -1
- package/dist/machine-viz/index.js +2 -2
- package/dist/mem/index.d.ts +6 -6
- package/dist/mem/index.js +6 -2
- package/dist/mem/index.js.map +1 -1
- package/dist/node/index.d.ts +16 -10
- package/dist/node/index.js +22 -3
- package/dist/node/index.js.map +1 -1
- package/dist/otel/index.d.ts +161 -0
- package/dist/otel/index.js +403 -0
- package/dist/otel/index.js.map +1 -0
- package/dist/paginate/index.d.ts +4 -4
- package/dist/paginate/index.js +5 -5
- package/dist/parity/index.d.ts +3 -3
- package/dist/parity/index.js +3 -3
- package/dist/pbt/index.d.ts +166 -53
- package/dist/pbt/index.js +2 -2
- package/dist/pbt/index.js.map +1 -1
- package/dist/persistence/index.d.ts +5 -5
- package/dist/persistence/index.js +5 -5
- package/dist/promise/index.d.ts +2 -2
- package/dist/promise/index.js +4 -3
- package/dist/react/index.d.ts +2 -2
- package/dist/resilience/index.d.ts +13 -9
- package/dist/resilience/index.js +5 -5
- package/dist/resilience/index.js.map +1 -1
- package/dist/{runtime-types-B62Ucnxr.d.ts → runtime-types-BKg2CGMx.d.ts} +88 -14
- package/dist/testing/effect/index.d.ts +65 -0
- package/dist/testing/effect/index.js +148 -0
- package/dist/testing/effect/index.js.map +1 -0
- package/dist/testing/index.d.ts +12 -158
- package/dist/testing/index.js +4 -130
- package/dist/testing/index.js.map +1 -1
- package/dist/testing/promise/index.d.ts +41 -0
- package/dist/testing/promise/index.js +37 -0
- package/dist/testing/promise/index.js.map +1 -0
- package/dist/timing/index.d.ts +4 -4
- package/dist/timing/index.js +4 -4
- package/dist/{types-DPm5YCDQ.d.ts → types-SzNSHKlV.d.ts} +1 -1
- package/dist/work-queue/index.d.ts +4 -4
- package/dist/work-queue/index.js +4 -3
- package/dist/work-queue/index.js.map +1 -1
- package/package.json +26 -14
- package/dist/chunk-C4U5D5HP.js.map +0 -1
- package/dist/chunk-G5E74IJB.js +0 -8
- package/dist/chunk-G5E74IJB.js.map +0 -1
- package/dist/chunk-K4ETBNKS.js.map +0 -1
- package/dist/chunk-KWNCM6XM.js.map +0 -1
- package/dist/chunk-QWIPH4YH.js.map +0 -1
- package/dist/chunk-XBZQT2TD.js.map +0 -1
|
@@ -1,11 +1,10 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { createMonitoredRun } from './chunk-4PXNZ5UY.js';
|
|
1
|
+
import { createMonitoredRun } from './chunk-XVIKSRCK.js';
|
|
3
2
|
import { createFanOut, initFanOut } from './chunk-QNGYQMZB.js';
|
|
4
|
-
import { createResilientCall } from './chunk-
|
|
3
|
+
import { createResilientCall } from './chunk-WTSOW2MD.js';
|
|
4
|
+
import { deadlinesSub, subscribeDeadline } from './chunk-C3G2QFEZ.js';
|
|
5
5
|
import { rejectAll, unchecked } from './chunk-4LPY67E4.js';
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import { Cmd, Outcome, cmdEdgeOf, detachWorkOf, absurd, defineMachine, validateSync, malformedResult } from './chunk-K4ETBNKS.js';
|
|
6
|
+
import { run, driveToDone } from './chunk-H2ELKHI6.js';
|
|
7
|
+
import { Cmd, absurd, Outcome, cmdEdgeOf, detachWorkOf, defineMachine, validateSync, malformedResult, describeError, DriveFailedError } from './chunk-AIIXV4XB.js';
|
|
9
8
|
|
|
10
9
|
// src/internal/llm-call/index.ts
|
|
11
10
|
function createLlmCall(config, rng = Math.random) {
|
|
@@ -145,12 +144,47 @@ function isCompactionSummary(value) {
|
|
|
145
144
|
var compactionSummarySchema = schemaFromGuard(isCompactionSummary, "a CompactionSummary");
|
|
146
145
|
|
|
147
146
|
// src/agent/internal.ts
|
|
147
|
+
var NO_USAGE = { inputTokens: 0, outputTokens: 0 };
|
|
148
148
|
function freshConversation() {
|
|
149
149
|
return {
|
|
150
150
|
turns: [],
|
|
151
151
|
toolRecords: [],
|
|
152
152
|
turnCount: 0,
|
|
153
|
-
awaiting: { kind: "llm" }
|
|
153
|
+
awaiting: { kind: "llm" },
|
|
154
|
+
contextTokens: null
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
function addUsage(total, turn) {
|
|
158
|
+
const optional = (key) => total[key] === void 0 && turn[key] === void 0 ? {} : { [key]: (total[key] ?? 0) + (turn[key] ?? 0) };
|
|
159
|
+
return {
|
|
160
|
+
inputTokens: total.inputTokens + turn.inputTokens,
|
|
161
|
+
outputTokens: total.outputTokens + turn.outputTokens,
|
|
162
|
+
...optional("reasoningTokens"),
|
|
163
|
+
...optional("cachedInputTokens")
|
|
164
|
+
};
|
|
165
|
+
}
|
|
166
|
+
function withTurnUsage(s, conv, turn) {
|
|
167
|
+
const { usage } = turn;
|
|
168
|
+
if (usage === void 0) return [s.usage, { ...conv, contextTokens: null }];
|
|
169
|
+
return [
|
|
170
|
+
addUsage(s.usage, usage),
|
|
171
|
+
{ ...conv, contextTokens: usage.inputTokens + usage.outputTokens }
|
|
172
|
+
];
|
|
173
|
+
}
|
|
174
|
+
function withUsageDefaults(s) {
|
|
175
|
+
const persisted = s;
|
|
176
|
+
const conv = s.conversation;
|
|
177
|
+
const current = persisted.usage !== void 0 && (conv === null || conv.usage === void 0 && conv.contextTokens !== void 0);
|
|
178
|
+
if (current) return s;
|
|
179
|
+
let conversation = null;
|
|
180
|
+
if (conv !== null) {
|
|
181
|
+
const { usage: _lifted, ...rest } = conv;
|
|
182
|
+
conversation = { ...rest, contextTokens: rest.contextTokens ?? null };
|
|
183
|
+
}
|
|
184
|
+
return {
|
|
185
|
+
...s,
|
|
186
|
+
usage: persisted.usage ?? conv?.usage ?? NO_USAGE,
|
|
187
|
+
conversation
|
|
154
188
|
};
|
|
155
189
|
}
|
|
156
190
|
function dedupeByCallId(calls) {
|
|
@@ -171,7 +205,8 @@ function foldSummary(conv, folding, summaryTurn) {
|
|
|
171
205
|
...conv,
|
|
172
206
|
turns: [summaryTurn, ...survivingTurns],
|
|
173
207
|
toolRecords: survivingRecords,
|
|
174
|
-
awaiting: { kind: "llm" }
|
|
208
|
+
awaiting: { kind: "llm" },
|
|
209
|
+
contextTokens: null
|
|
175
210
|
};
|
|
176
211
|
}
|
|
177
212
|
function currentStage(s) {
|
|
@@ -194,6 +229,70 @@ function toCompactRunCmd(cmd) {
|
|
|
194
229
|
};
|
|
195
230
|
}
|
|
196
231
|
|
|
232
|
+
// src/agent/types.ts
|
|
233
|
+
function isTokenCount(value) {
|
|
234
|
+
return typeof value === "number" && Number.isSafeInteger(value) && value >= 0;
|
|
235
|
+
}
|
|
236
|
+
function isTurnUsage(value) {
|
|
237
|
+
if (value === null || typeof value !== "object") return false;
|
|
238
|
+
const u = value;
|
|
239
|
+
return isTokenCount(u.inputTokens) && isTokenCount(u.outputTokens) && (u.reasoningTokens === void 0 || isTokenCount(u.reasoningTokens)) && (u.cachedInputTokens === void 0 || isTokenCount(u.cachedInputTokens));
|
|
240
|
+
}
|
|
241
|
+
function isStreamingModel(model) {
|
|
242
|
+
return model.length >= 2;
|
|
243
|
+
}
|
|
244
|
+
function isToolCall(value) {
|
|
245
|
+
if (value === null || typeof value !== "object") return false;
|
|
246
|
+
const t = value;
|
|
247
|
+
return typeof t.callId === "string" && typeof t.name === "string" && t.args !== null && typeof t.args === "object";
|
|
248
|
+
}
|
|
249
|
+
function isAgentTurn(value) {
|
|
250
|
+
if (value === null || typeof value !== "object") return false;
|
|
251
|
+
const t = value;
|
|
252
|
+
return typeof t.content === "string" && Array.isArray(t.toolCalls) && t.toolCalls.every(isToolCall) && (t.usage === void 0 || isTurnUsage(t.usage));
|
|
253
|
+
}
|
|
254
|
+
var agentTurnSchema = schemaFromGuard(
|
|
255
|
+
isAgentTurn,
|
|
256
|
+
"an AgentTurn"
|
|
257
|
+
);
|
|
258
|
+
var TOOL_TIMEOUT_TAG = "timeout";
|
|
259
|
+
var TOOL_RETRY_EXHAUSTED_TAG = "retry_exhausted";
|
|
260
|
+
function status(s) {
|
|
261
|
+
if (s.failure !== null) {
|
|
262
|
+
return { kind: "failed", failure: s.failure };
|
|
263
|
+
}
|
|
264
|
+
const run2 = s.run;
|
|
265
|
+
switch (run2.phase) {
|
|
266
|
+
// 2) Never started — monitored-run's `idle` phase is exactly the "has this
|
|
267
|
+
// actually started?" guard, and the status channel keeps that distinction.
|
|
268
|
+
case "idle":
|
|
269
|
+
return { kind: "idle" };
|
|
270
|
+
// 3) The monitored-run terminal failure (deadline / stage). `run.failure`
|
|
271
|
+
// rides ONLY the `failed` arm of the discriminated union, so narrowing on
|
|
272
|
+
// `phase === "failed"` surfaces it with no nullable side field and no
|
|
273
|
+
// fabricated fallback — the old "failed-yet-failure-null" state is
|
|
274
|
+
// unrepresentable.
|
|
275
|
+
case "failed":
|
|
276
|
+
return { kind: "failed", failure: run2.failure };
|
|
277
|
+
// 4) The pipeline finished — the terminal output landed on `state.output`.
|
|
278
|
+
case "done":
|
|
279
|
+
return { kind: "done", output: s.output, usage: s.usage ?? NO_USAGE };
|
|
280
|
+
// 5) Stopped from outside. Terminal, and deliberately NOT folded into
|
|
281
|
+
// `failed`: the unified failure channel answers "what went wrong", and
|
|
282
|
+
// nothing did.
|
|
283
|
+
case "cancelled":
|
|
284
|
+
return { kind: "cancelled", at: run2.at };
|
|
285
|
+
// 6) Live. Awaiting tools is the resumable shape — the outstanding calls are
|
|
286
|
+
// the in-flight fan-out batch (`tools.running`); anything else is plain
|
|
287
|
+
// `running`, which is also where `stale` reads (a soft mark the next
|
|
288
|
+
// progress clears, not an outcome).
|
|
289
|
+
case "running":
|
|
290
|
+
case "stale":
|
|
291
|
+
return s.conversation !== null && s.conversation.awaiting.kind === "tools" ? { kind: "suspended", pending: s.tools.running } : { kind: "running" };
|
|
292
|
+
}
|
|
293
|
+
return absurd(run2);
|
|
294
|
+
}
|
|
295
|
+
|
|
197
296
|
// src/agent/machine.ts
|
|
198
297
|
function agentBootMsg(at) {
|
|
199
298
|
return { type: MsgType.AgentBoot, at };
|
|
@@ -201,39 +300,108 @@ function agentBootMsg(at) {
|
|
|
201
300
|
function agentCancelMsg(at) {
|
|
202
301
|
return { type: MsgType.AgentCancel, at };
|
|
203
302
|
}
|
|
303
|
+
var AGENT_EVENT_TYPES = [
|
|
304
|
+
"BrainStarted",
|
|
305
|
+
"TurnSettled",
|
|
306
|
+
"ToolStarted",
|
|
307
|
+
"ToolSettled",
|
|
308
|
+
"ToolFailed",
|
|
309
|
+
"RunDone"
|
|
310
|
+
];
|
|
204
311
|
function agentEvents(opts) {
|
|
205
312
|
const tools = opts?.tools;
|
|
313
|
+
const projected = /* @__PURE__ */ new WeakSet();
|
|
206
314
|
return (msg, state) => {
|
|
207
315
|
const events = [];
|
|
208
|
-
|
|
209
|
-
const
|
|
210
|
-
|
|
211
|
-
if (
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
316
|
+
const run2 = state.run;
|
|
317
|
+
const runId = run2.phase === "idle" ? null : run2.runId;
|
|
318
|
+
if (runId === null) return events;
|
|
319
|
+
if (run2.phase !== "cancelled") {
|
|
320
|
+
const refused = new Set(state.refusedCalls ?? []);
|
|
321
|
+
const routed = tools === void 0 ? null : tools.outcomeOf(msg);
|
|
322
|
+
if (routed !== null) {
|
|
323
|
+
if (routed.outcome.kind === "ok" && !refused.has(routed.callId)) {
|
|
324
|
+
events.push({
|
|
325
|
+
type: "ToolSettled",
|
|
326
|
+
runId,
|
|
327
|
+
// The router claimed it, so it is one of its settled Msgs.
|
|
328
|
+
at: msg.at,
|
|
329
|
+
callId: routed.callId,
|
|
330
|
+
result: routed.outcome.result
|
|
331
|
+
});
|
|
332
|
+
}
|
|
333
|
+
} else {
|
|
334
|
+
projectOwn(msg, runId, events, refused);
|
|
218
335
|
}
|
|
219
|
-
} else {
|
|
220
|
-
projectOwn(msg, events, refused);
|
|
221
336
|
}
|
|
222
|
-
|
|
223
|
-
|
|
337
|
+
const outbox = state.lifecycle ?? [];
|
|
338
|
+
if (outbox.length === 0 || projected.has(outbox)) return events;
|
|
339
|
+
projected.add(outbox);
|
|
340
|
+
for (const note of outbox) {
|
|
341
|
+
const event = projectNote(note, runId, state);
|
|
342
|
+
if (event !== null) events.push(event);
|
|
224
343
|
}
|
|
225
344
|
return events;
|
|
226
345
|
};
|
|
227
346
|
}
|
|
228
|
-
function
|
|
347
|
+
function turnSettled(turn, runId, at) {
|
|
348
|
+
return turn.usage === void 0 ? { type: "TurnSettled", runId, at, turn } : { type: "TurnSettled", runId, at, turn, usage: turn.usage };
|
|
349
|
+
}
|
|
350
|
+
function projectNote(note, runId, state) {
|
|
351
|
+
switch (note.kind) {
|
|
352
|
+
case "brain_started":
|
|
353
|
+
return {
|
|
354
|
+
type: "BrainStarted",
|
|
355
|
+
runId,
|
|
356
|
+
at: note.at,
|
|
357
|
+
turn: note.turn,
|
|
358
|
+
purpose: note.purpose,
|
|
359
|
+
model: note.model,
|
|
360
|
+
payload: inFlightPayload(state, note.purpose)
|
|
361
|
+
};
|
|
362
|
+
case "tool_started":
|
|
363
|
+
return {
|
|
364
|
+
type: "ToolStarted",
|
|
365
|
+
runId,
|
|
366
|
+
at: note.at,
|
|
367
|
+
callId: note.call.callId,
|
|
368
|
+
name: note.call.name,
|
|
369
|
+
args: note.call.args
|
|
370
|
+
};
|
|
371
|
+
case "tool_failed":
|
|
372
|
+
return {
|
|
373
|
+
type: "ToolFailed",
|
|
374
|
+
runId,
|
|
375
|
+
at: note.at,
|
|
376
|
+
callId: note.call.callId,
|
|
377
|
+
name: note.call.name,
|
|
378
|
+
failure: note.failure
|
|
379
|
+
};
|
|
380
|
+
case "run_ended": {
|
|
381
|
+
const status2 = ended(state);
|
|
382
|
+
return status2 === null ? null : { type: "RunDone", runId, at: note.at, status: status2 };
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
function inFlightPayload(state, key) {
|
|
387
|
+
const call = state.resilience.calls[key];
|
|
388
|
+
return call?.phase === "running" || call?.phase === "waiting_retry" ? call.input.payload : null;
|
|
389
|
+
}
|
|
390
|
+
function ended(state) {
|
|
391
|
+
const s = status(state);
|
|
392
|
+
return s.kind === "done" || s.kind === "failed" || s.kind === "cancelled" ? s : null;
|
|
393
|
+
}
|
|
394
|
+
function projectOwn(msg, runId, events, refused) {
|
|
229
395
|
switch (msg.type) {
|
|
230
396
|
case MsgType.ResilientOk:
|
|
231
|
-
events.push(
|
|
397
|
+
events.push(turnSettled(msg.value.output, runId, msg.at));
|
|
232
398
|
break;
|
|
233
399
|
case MsgType.AgentToolOk:
|
|
234
400
|
if (!refused.has(msg.callId)) {
|
|
235
401
|
events.push({
|
|
236
402
|
type: "ToolSettled",
|
|
403
|
+
runId,
|
|
404
|
+
at: msg.at,
|
|
237
405
|
callId: msg.callId,
|
|
238
406
|
result: msg.result
|
|
239
407
|
});
|
|
@@ -290,7 +458,7 @@ function brainHandler(llm, ports) {
|
|
|
290
458
|
};
|
|
291
459
|
}
|
|
292
460
|
|
|
293
|
-
// src/agent/tool.ts
|
|
461
|
+
// src/agent/tool-cell.ts
|
|
294
462
|
var REJECTED_TYPE = "tool_rejected";
|
|
295
463
|
var SNAPSHOT_WRITE_TYPE = "snapshot_write";
|
|
296
464
|
var SETTLE_SUFFIX = /_(?:ok|err|run)$/;
|
|
@@ -306,31 +474,22 @@ var reservedToolNames = /* @__PURE__ */ new Set([
|
|
|
306
474
|
function isReservedToolName(name) {
|
|
307
475
|
return reservedToolNames.has(name);
|
|
308
476
|
}
|
|
309
|
-
function
|
|
477
|
+
function definedTool(door, name, spec, declaredTags, cell) {
|
|
310
478
|
if (isReservedToolName(name)) {
|
|
311
479
|
throw new Error(
|
|
312
|
-
|
|
480
|
+
`${door}: "${name}" is reserved \u2014 it is an agent-owned Msg prefix`
|
|
313
481
|
);
|
|
314
482
|
}
|
|
315
483
|
const def = Cmd.define(name, {
|
|
316
|
-
// The router parses `args` against `spec.input` before it builds the Cmd,
|
|
317
|
-
// so the Cmd's own input schema only names the type.
|
|
318
484
|
input: unchecked(),
|
|
319
485
|
ok: spec.ok,
|
|
320
|
-
err: [...
|
|
486
|
+
err: [...declaredTags, "thrown"]
|
|
321
487
|
});
|
|
322
|
-
const declared = new Set(
|
|
323
|
-
const
|
|
324
|
-
ok: Outcome.ok,
|
|
325
|
-
fail: Outcome.err
|
|
326
|
-
};
|
|
327
|
-
const asDeclared = (thrown) => {
|
|
328
|
-
if (isTagged(thrown) && declared.has(thrown._tag)) return thrown;
|
|
329
|
-
return { _tag: "thrown", message: describeError(thrown) };
|
|
330
|
-
};
|
|
488
|
+
const declared = new Set(declaredTags);
|
|
489
|
+
const asDeclared = (thrown) => isTagged(thrown) && declared.has(thrown._tag) ? thrown : { _tag: "thrown", message: describeError(thrown) };
|
|
331
490
|
const interpret = async (cmd, ctx) => {
|
|
332
491
|
try {
|
|
333
|
-
return await
|
|
492
|
+
return await cell(cmd, ctx);
|
|
334
493
|
} catch (thrown) {
|
|
335
494
|
return Outcome.err(asDeclared(thrown));
|
|
336
495
|
}
|
|
@@ -339,6 +498,7 @@ function tool(name, spec, handler) {
|
|
|
339
498
|
description: spec.description,
|
|
340
499
|
args: spec.input,
|
|
341
500
|
resilience: resilienceOf(spec),
|
|
501
|
+
content: spec.content ?? null,
|
|
342
502
|
interpret
|
|
343
503
|
});
|
|
344
504
|
}
|
|
@@ -352,6 +512,21 @@ function resilienceOf(spec) {
|
|
|
352
512
|
function isTagged(value) {
|
|
353
513
|
return typeof value === "object" && value !== null && typeof value._tag === "string";
|
|
354
514
|
}
|
|
515
|
+
|
|
516
|
+
// src/agent/tool.ts
|
|
517
|
+
function tool(name, spec, handler) {
|
|
518
|
+
const settle = {
|
|
519
|
+
ok: Outcome.ok,
|
|
520
|
+
fail: Outcome.err
|
|
521
|
+
};
|
|
522
|
+
return definedTool(
|
|
523
|
+
"tool",
|
|
524
|
+
name,
|
|
525
|
+
spec,
|
|
526
|
+
spec.err,
|
|
527
|
+
(cmd, ctx) => handler(cmd.args, ctx, settle)
|
|
528
|
+
);
|
|
529
|
+
}
|
|
355
530
|
var rejected = Cmd.define(REJECTED_TYPE, {
|
|
356
531
|
input: unchecked(),
|
|
357
532
|
ok: rejectAll,
|
|
@@ -426,7 +601,14 @@ function toolRouter(tools) {
|
|
|
426
601
|
return null;
|
|
427
602
|
};
|
|
428
603
|
const resilienceOf2 = (call) => byName.get(call.name)?.resilience ?? null;
|
|
429
|
-
|
|
604
|
+
const partsOf = (call, outcome) => {
|
|
605
|
+
const content = byName.get(call.name)?.content ?? null;
|
|
606
|
+
if (content === null || outcome.kind !== "ok") return null;
|
|
607
|
+
return content(
|
|
608
|
+
outcome.result
|
|
609
|
+
);
|
|
610
|
+
};
|
|
611
|
+
return { defs, toolOf, interpret, outcomeOf, resilienceOf: resilienceOf2, partsOf };
|
|
430
612
|
}
|
|
431
613
|
function fanOutInterpret(interpret) {
|
|
432
614
|
let release = Promise.resolve();
|
|
@@ -459,62 +641,6 @@ function toolErrorReason(error) {
|
|
|
459
641
|
return Object.keys(detail).length === 0 ? _tag : `${_tag} ${JSON.stringify(detail)}`;
|
|
460
642
|
}
|
|
461
643
|
|
|
462
|
-
// src/agent/types.ts
|
|
463
|
-
function isStreamingModel(model) {
|
|
464
|
-
return model.length >= 2;
|
|
465
|
-
}
|
|
466
|
-
function isToolCall(value) {
|
|
467
|
-
if (value === null || typeof value !== "object") return false;
|
|
468
|
-
const t = value;
|
|
469
|
-
return typeof t.callId === "string" && typeof t.name === "string" && t.args !== null && typeof t.args === "object";
|
|
470
|
-
}
|
|
471
|
-
function isAgentTurn(value) {
|
|
472
|
-
if (value === null || typeof value !== "object") return false;
|
|
473
|
-
const t = value;
|
|
474
|
-
return typeof t.content === "string" && Array.isArray(t.toolCalls) && t.toolCalls.every(isToolCall);
|
|
475
|
-
}
|
|
476
|
-
var agentTurnSchema = schemaFromGuard(
|
|
477
|
-
isAgentTurn,
|
|
478
|
-
"an AgentTurn"
|
|
479
|
-
);
|
|
480
|
-
var TOOL_TIMEOUT_TAG = "timeout";
|
|
481
|
-
var TOOL_RETRY_EXHAUSTED_TAG = "retry_exhausted";
|
|
482
|
-
function status(s) {
|
|
483
|
-
if (s.failure !== null) {
|
|
484
|
-
return { kind: "failed", failure: s.failure };
|
|
485
|
-
}
|
|
486
|
-
const run2 = s.run;
|
|
487
|
-
switch (run2.phase) {
|
|
488
|
-
// 2) Never started — monitored-run's `idle` phase is exactly the "has this
|
|
489
|
-
// actually started?" guard, and the status channel keeps that distinction.
|
|
490
|
-
case "idle":
|
|
491
|
-
return { kind: "idle" };
|
|
492
|
-
// 3) The monitored-run terminal failure (deadline / stage). `run.failure`
|
|
493
|
-
// rides ONLY the `failed` arm of the discriminated union, so narrowing on
|
|
494
|
-
// `phase === "failed"` surfaces it with no nullable side field and no
|
|
495
|
-
// fabricated fallback — the old "failed-yet-failure-null" state is
|
|
496
|
-
// unrepresentable.
|
|
497
|
-
case "failed":
|
|
498
|
-
return { kind: "failed", failure: run2.failure };
|
|
499
|
-
// 4) The pipeline finished — the terminal output landed on `state.output`.
|
|
500
|
-
case "done":
|
|
501
|
-
return { kind: "done", output: s.output };
|
|
502
|
-
// 5) Stopped from outside. Terminal, and deliberately NOT folded into
|
|
503
|
-
// `failed`: the unified failure channel answers "what went wrong", and
|
|
504
|
-
// nothing did.
|
|
505
|
-
case "cancelled":
|
|
506
|
-
return { kind: "cancelled", at: run2.at };
|
|
507
|
-
// 6) Live. Awaiting tools is the resumable shape — the outstanding calls are
|
|
508
|
-
// the in-flight fan-out batch (`tools.running`); anything else is plain
|
|
509
|
-
// `running`, which is also where `stale` reads (a soft mark the next
|
|
510
|
-
// progress clears, not an outcome).
|
|
511
|
-
case "running":
|
|
512
|
-
case "stale":
|
|
513
|
-
return s.conversation !== null && s.conversation.awaiting.kind === "tools" ? { kind: "suspended", pending: s.tools.running } : { kind: "running" };
|
|
514
|
-
}
|
|
515
|
-
return absurd(run2);
|
|
516
|
-
}
|
|
517
|
-
|
|
518
644
|
// src/agent/tool-resilience.ts
|
|
519
645
|
var TOOL_KEY_PREFIX = "$tool:";
|
|
520
646
|
var NAME_CALL_SEP = "#";
|
|
@@ -718,6 +844,75 @@ function taggedFailure(tagged) {
|
|
|
718
844
|
return { ...tagged, reason: toolErrorReason(tagged), kind: "error" };
|
|
719
845
|
}
|
|
720
846
|
|
|
847
|
+
// src/agent/agent-tool.ts
|
|
848
|
+
var AGENT_TOOL_TAGS = [
|
|
849
|
+
"child_failed",
|
|
850
|
+
"child_cancelled"
|
|
851
|
+
];
|
|
852
|
+
function agentTool(name, spec) {
|
|
853
|
+
const runChild = spec.agent.run;
|
|
854
|
+
const childCtx = spec.childCtx;
|
|
855
|
+
return definedTool(
|
|
856
|
+
"agentTool",
|
|
857
|
+
name,
|
|
858
|
+
{ description: spec.description, input: spec.input, ok: spec.ok },
|
|
859
|
+
AGENT_TOOL_TAGS,
|
|
860
|
+
async (cmd, ctx) => {
|
|
861
|
+
const childRunId = `${spec.namespace(ctx)}/${cmd.callId}`;
|
|
862
|
+
const opts = {
|
|
863
|
+
store: spec.store(childRunId, ctx),
|
|
864
|
+
runId: childRunId,
|
|
865
|
+
...childCtx === void 0 ? {} : { ctx: childCtx(ctx) }
|
|
866
|
+
};
|
|
867
|
+
let final;
|
|
868
|
+
try {
|
|
869
|
+
final = await runChild(spec.prompt(cmd.args), opts);
|
|
870
|
+
} catch (error) {
|
|
871
|
+
if (!(error instanceof DriveFailedError)) throw error;
|
|
872
|
+
return Outcome.err(childFailed(childRunId, error.state));
|
|
873
|
+
}
|
|
874
|
+
if (final.run.phase === "cancelled") {
|
|
875
|
+
return Outcome.err({ _tag: "child_cancelled", childRunId });
|
|
876
|
+
}
|
|
877
|
+
if (final.output === null) {
|
|
878
|
+
throw new Error(
|
|
879
|
+
`agentTool: child run "${childRunId}" ended done with no output`
|
|
880
|
+
);
|
|
881
|
+
}
|
|
882
|
+
return Outcome.ok(spec.result(final.output));
|
|
883
|
+
}
|
|
884
|
+
);
|
|
885
|
+
}
|
|
886
|
+
function childFailed(childRunId, state) {
|
|
887
|
+
const s = status(state);
|
|
888
|
+
if (s.kind !== "failed") {
|
|
889
|
+
throw new Error(
|
|
890
|
+
`agentTool: child run "${childRunId}" rejected on a ${s.kind} Model`
|
|
891
|
+
);
|
|
892
|
+
}
|
|
893
|
+
return { _tag: "child_failed", childRunId, failure: s.failure.reason };
|
|
894
|
+
}
|
|
895
|
+
|
|
896
|
+
// src/agent/content.ts
|
|
897
|
+
function contentParts(content) {
|
|
898
|
+
return typeof content === "string" ? [{ type: "text", text: content }] : content;
|
|
899
|
+
}
|
|
900
|
+
var IMAGE_OMITTED = "[image omitted]";
|
|
901
|
+
var FILE_OMITTED = "[file omitted]";
|
|
902
|
+
function omitMedia(parts) {
|
|
903
|
+
return parts.map(placeholderOf);
|
|
904
|
+
}
|
|
905
|
+
function placeholderOf(part) {
|
|
906
|
+
switch (part.type) {
|
|
907
|
+
case "text":
|
|
908
|
+
return part;
|
|
909
|
+
case "image":
|
|
910
|
+
return { type: "text", text: IMAGE_OMITTED };
|
|
911
|
+
case "file":
|
|
912
|
+
return { type: "text", text: FILE_OMITTED };
|
|
913
|
+
}
|
|
914
|
+
}
|
|
915
|
+
|
|
721
916
|
// src/agent/define-agent.ts
|
|
722
917
|
function defineAgent(config) {
|
|
723
918
|
const router = toolRouter(config.tools);
|
|
@@ -737,7 +932,7 @@ function definedAgent(config, wiring, overlays) {
|
|
|
737
932
|
model: brain,
|
|
738
933
|
instructions: config.instructions,
|
|
739
934
|
payloadOf: promptOf,
|
|
740
|
-
loadMessages: messagesOf,
|
|
935
|
+
loadMessages: messagesOf(tools.partsOf),
|
|
741
936
|
toolOf: tools.toolOf,
|
|
742
937
|
// The per-tool timeout / retry knob (#117). The lid grows no option for
|
|
743
938
|
// it: the policy is declared on the `tool()` that needs it, and the
|
|
@@ -797,9 +992,9 @@ function definedAgent(config, wiring, overlays) {
|
|
|
797
992
|
};
|
|
798
993
|
const signal = opts.signal;
|
|
799
994
|
if (signal === void 0) {
|
|
800
|
-
return
|
|
995
|
+
return ended2(driveToDone(handle, begin, isEnded, { failed: isFailed }));
|
|
801
996
|
}
|
|
802
|
-
return
|
|
997
|
+
return ended2(
|
|
803
998
|
driveToDone(handle, begin, isEnded, {
|
|
804
999
|
failed: isFailed,
|
|
805
1000
|
signal,
|
|
@@ -855,7 +1050,7 @@ function compactingMachine(core, knob, brain, tools) {
|
|
|
855
1050
|
const agent = createAgent({ ...core, compaction: compactionPolicyOf(knob) });
|
|
856
1051
|
const wiring = {
|
|
857
1052
|
tools,
|
|
858
|
-
toolInterpret: { compact_run: summarizeWith(brain) }
|
|
1053
|
+
toolInterpret: { compact_run: summarizeWith(brain, tools.partsOf) }
|
|
859
1054
|
};
|
|
860
1055
|
return agent.toMachine(
|
|
861
1056
|
wiring
|
|
@@ -865,7 +1060,7 @@ var SUMMARIZE_INSTRUCTION = "Summarize the conversation so far. Preserve the fac
|
|
|
865
1060
|
function compactionPolicyOf(knob) {
|
|
866
1061
|
const keep = knob.keepTurns ?? 0;
|
|
867
1062
|
return {
|
|
868
|
-
planCompaction: (conversation) => conversation
|
|
1063
|
+
planCompaction: (conversation) => isCompactionDue(knob, conversation) ? Math.max(0, conversation.turns.length - keep) : 0,
|
|
869
1064
|
payloadOf: (conversation, folding) => ({
|
|
870
1065
|
instructions: SUMMARIZE_INSTRUCTION,
|
|
871
1066
|
input: null,
|
|
@@ -877,10 +1072,15 @@ function compactionPolicyOf(knob) {
|
|
|
877
1072
|
})
|
|
878
1073
|
};
|
|
879
1074
|
}
|
|
880
|
-
function
|
|
1075
|
+
function isCompactionDue(knob, conversation) {
|
|
1076
|
+
const { afterTurns, afterContextTokens } = knob;
|
|
1077
|
+
const { contextTokens } = conversation;
|
|
1078
|
+
return afterTurns !== void 0 && conversation.turns.length >= afterTurns || afterContextTokens !== void 0 && contextTokens !== null && contextTokens >= afterContextTokens;
|
|
1079
|
+
}
|
|
1080
|
+
function summarizeWith(model, partsOf) {
|
|
881
1081
|
return async (cmd) => {
|
|
882
1082
|
const payload = cmd.input.payload;
|
|
883
|
-
const turn = await model(renderPrompt(payload));
|
|
1083
|
+
const turn = await model(renderPrompt(payload, partsOf).map(withoutMedia));
|
|
884
1084
|
return {
|
|
885
1085
|
type: MsgType.CompactOk,
|
|
886
1086
|
key: COMPACTION_PURPOSE,
|
|
@@ -896,8 +1096,10 @@ function summarizeWith(model) {
|
|
|
896
1096
|
function promptOf(stage, conversation, instructions) {
|
|
897
1097
|
return { instructions, input: stage ?? null, conversation };
|
|
898
1098
|
}
|
|
899
|
-
|
|
900
|
-
|
|
1099
|
+
function messagesOf(partsOf) {
|
|
1100
|
+
return async (call) => renderPrompt(call.payload, partsOf);
|
|
1101
|
+
}
|
|
1102
|
+
function renderPrompt(prompt, partsOf = noParts) {
|
|
901
1103
|
const head = [];
|
|
902
1104
|
if (prompt.instructions !== null) {
|
|
903
1105
|
head.push({ role: "system", content: prompt.instructions });
|
|
@@ -908,15 +1110,32 @@ function renderPrompt(prompt) {
|
|
|
908
1110
|
const { turns, toolRecords } = prompt.conversation;
|
|
909
1111
|
const transcript2 = turns.flatMap((turn, i) => [
|
|
910
1112
|
assistantOf(turn),
|
|
911
|
-
...toolRecords.filter((r) => r.turn === i).map((r) =>
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
1113
|
+
...toolRecords.filter((r) => r.turn === i).map((r) => {
|
|
1114
|
+
const message = {
|
|
1115
|
+
role: "tool",
|
|
1116
|
+
callId: r.call.callId,
|
|
1117
|
+
name: r.call.name,
|
|
1118
|
+
outcome: r.outcome
|
|
1119
|
+
};
|
|
1120
|
+
const parts = partsOf(r.call, r.outcome);
|
|
1121
|
+
return parts === null ? message : { ...message, parts };
|
|
1122
|
+
})
|
|
917
1123
|
]);
|
|
918
1124
|
return [...head, ...transcript2];
|
|
919
1125
|
}
|
|
1126
|
+
function noParts() {
|
|
1127
|
+
return null;
|
|
1128
|
+
}
|
|
1129
|
+
function withoutMedia(message) {
|
|
1130
|
+
switch (message.role) {
|
|
1131
|
+
case "user":
|
|
1132
|
+
return typeof message.content === "string" ? message : { ...message, content: omitMedia(message.content) };
|
|
1133
|
+
case "tool":
|
|
1134
|
+
return message.parts === void 0 ? message : { ...message, parts: omitMedia(message.parts) };
|
|
1135
|
+
default:
|
|
1136
|
+
return message;
|
|
1137
|
+
}
|
|
1138
|
+
}
|
|
920
1139
|
function assistantOf(turn) {
|
|
921
1140
|
const { content, toolCalls } = turn;
|
|
922
1141
|
return "provider" in turn ? { role: "assistant", content, toolCalls, provider: turn.provider } : { role: "assistant", content, toolCalls };
|
|
@@ -924,7 +1143,6 @@ function assistantOf(turn) {
|
|
|
924
1143
|
function noHost() {
|
|
925
1144
|
return {};
|
|
926
1145
|
}
|
|
927
|
-
var AGENT_EVENT_TYPES = ["TurnSettled", "ToolSettled", "RunDone"];
|
|
928
1146
|
function forwardEvents(handle, onEvent) {
|
|
929
1147
|
const deliver = contained("onEvent", onEvent);
|
|
930
1148
|
for (const type of AGENT_EVENT_TYPES) {
|
|
@@ -997,7 +1215,7 @@ function isMidRun(s) {
|
|
|
997
1215
|
function isEnded(s) {
|
|
998
1216
|
return s.run.phase === "done" || s.run.phase === "cancelled";
|
|
999
1217
|
}
|
|
1000
|
-
function
|
|
1218
|
+
function ended2(drive) {
|
|
1001
1219
|
return drive;
|
|
1002
1220
|
}
|
|
1003
1221
|
function isFailed(s) {
|
|
@@ -1021,7 +1239,13 @@ function transcript(seed) {
|
|
|
1021
1239
|
tools.push({ callId: event.callId, result: event.result });
|
|
1022
1240
|
return;
|
|
1023
1241
|
case "RunDone":
|
|
1024
|
-
outcome =
|
|
1242
|
+
outcome = event.status;
|
|
1243
|
+
return;
|
|
1244
|
+
// The started and failed events add nothing a transcript keeps: a
|
|
1245
|
+
// turn is kept once it settles, and a failed call is `onToolError`'s.
|
|
1246
|
+
case "BrainStarted":
|
|
1247
|
+
case "ToolStarted":
|
|
1248
|
+
case "ToolFailed":
|
|
1025
1249
|
return;
|
|
1026
1250
|
}
|
|
1027
1251
|
},
|
|
@@ -1065,9 +1289,11 @@ function createAgent(config) {
|
|
|
1065
1289
|
resilience: llm.init(),
|
|
1066
1290
|
tools: initFanOut(),
|
|
1067
1291
|
conversation: null,
|
|
1292
|
+
usage: NO_USAGE,
|
|
1068
1293
|
compaction: compactRc.init(),
|
|
1069
1294
|
toolResilience: ladder.init(),
|
|
1070
1295
|
refusedCalls: [],
|
|
1296
|
+
lifecycle: [],
|
|
1071
1297
|
failure: null,
|
|
1072
1298
|
output: null,
|
|
1073
1299
|
instructions: config.instructions ?? null
|
|
@@ -1086,7 +1312,21 @@ function createAgent(config) {
|
|
|
1086
1312
|
function fireBrainCall(s, at) {
|
|
1087
1313
|
const call = brainCall(s);
|
|
1088
1314
|
const [resilience, cmds] = llm.attempt(s.resilience, call, at);
|
|
1089
|
-
|
|
1315
|
+
const started = noted(s, {
|
|
1316
|
+
kind: "brain_started",
|
|
1317
|
+
turn: s.conversation?.turnCount ?? 0,
|
|
1318
|
+
purpose: call.purpose,
|
|
1319
|
+
model: call.model,
|
|
1320
|
+
at
|
|
1321
|
+
});
|
|
1322
|
+
return [{ ...started, resilience }, cmds];
|
|
1323
|
+
}
|
|
1324
|
+
function noted(s, ...notes) {
|
|
1325
|
+
if (notes.length === 0) return s;
|
|
1326
|
+
return { ...s, lifecycle: [...s.lifecycle ?? [], ...notes] };
|
|
1327
|
+
}
|
|
1328
|
+
function toolsStarted(calls, at) {
|
|
1329
|
+
return calls.map((call) => ({ kind: "tool_started", call, at }));
|
|
1090
1330
|
}
|
|
1091
1331
|
function compactionCall(conv, folding) {
|
|
1092
1332
|
const payloadOf = config.compaction?.payloadOf;
|
|
@@ -1115,6 +1355,8 @@ function createAgent(config) {
|
|
|
1115
1355
|
...s,
|
|
1116
1356
|
run: runSlice,
|
|
1117
1357
|
conversation,
|
|
1358
|
+
// A new run has cost nothing yet (#332).
|
|
1359
|
+
usage: NO_USAGE,
|
|
1118
1360
|
failure: null,
|
|
1119
1361
|
// A restart clears the prior run's terminal output — `result()` reads
|
|
1120
1362
|
// `undefined` again until THIS run finishes (#46).
|
|
@@ -1132,12 +1374,14 @@ function createAgent(config) {
|
|
|
1132
1374
|
function turn(s, result, at) {
|
|
1133
1375
|
const conv = requireAwaiting(s, "llm");
|
|
1134
1376
|
if (conv === null) return [s, []];
|
|
1377
|
+
const [usage, measured] = withTurnUsage(s, conv, result);
|
|
1135
1378
|
const withTurn = {
|
|
1136
|
-
...
|
|
1379
|
+
...measured,
|
|
1137
1380
|
turns: [...conv.turns, result]
|
|
1138
1381
|
};
|
|
1382
|
+
const counted = { ...s, usage };
|
|
1139
1383
|
if (result.toolCalls.length === 0) {
|
|
1140
|
-
return advanceStage({ ...
|
|
1384
|
+
return advanceStage({ ...counted, conversation: withTurn }, result, at);
|
|
1141
1385
|
}
|
|
1142
1386
|
const batch = dedupeByCallId(result.toolCalls);
|
|
1143
1387
|
const [tools] = fan.scatter(initFanOut(), batch);
|
|
@@ -1146,9 +1390,23 @@ function createAgent(config) {
|
|
|
1146
1390
|
awaiting: { kind: "tools", batchTurn: withTurn.turnCount }
|
|
1147
1391
|
};
|
|
1148
1392
|
const [runSlice] = run2.progress(s.run, void 0, at);
|
|
1149
|
-
const [toolResilience, launchCmds] = armLaunch(
|
|
1393
|
+
const [toolResilience, launchCmds, launched] = armLaunch(
|
|
1394
|
+
s,
|
|
1395
|
+
[],
|
|
1396
|
+
tools.running,
|
|
1397
|
+
at
|
|
1398
|
+
);
|
|
1150
1399
|
return [
|
|
1151
|
-
|
|
1400
|
+
noted(
|
|
1401
|
+
{
|
|
1402
|
+
...counted,
|
|
1403
|
+
run: runSlice,
|
|
1404
|
+
tools,
|
|
1405
|
+
toolResilience,
|
|
1406
|
+
conversation: nextConv
|
|
1407
|
+
},
|
|
1408
|
+
...toolsStarted(launched, at)
|
|
1409
|
+
),
|
|
1152
1410
|
launchCmds
|
|
1153
1411
|
];
|
|
1154
1412
|
}
|
|
@@ -1205,11 +1463,9 @@ function createAgent(config) {
|
|
|
1205
1463
|
}
|
|
1206
1464
|
function armLaunch(s, before, after, at) {
|
|
1207
1465
|
const known = new Set(before.map((c) => c.callId));
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
at
|
|
1212
|
-
);
|
|
1466
|
+
const launched = after.filter((c) => !known.has(c.callId));
|
|
1467
|
+
const [slice, cmds] = ladder.launch(toolSlice(s), launched, at);
|
|
1468
|
+
return [slice, cmds, launched];
|
|
1213
1469
|
}
|
|
1214
1470
|
function settleTool(prev, callId, outcome, at) {
|
|
1215
1471
|
const conv = requireAwaiting(prev, "tools");
|
|
@@ -1217,14 +1473,18 @@ function createAgent(config) {
|
|
|
1217
1473
|
const call = prev.tools.running.find((c) => c.callId === callId);
|
|
1218
1474
|
if (call === void 0) return [prev, []];
|
|
1219
1475
|
const [tools] = outcome.kind === "ok" ? fan.itemOk(prev.tools, callId, outcome) : fan.itemErr(prev.tools, callId, outcome);
|
|
1220
|
-
const [toolResilience, launchCmds] = armLaunch(
|
|
1476
|
+
const [toolResilience, launchCmds, launched] = armLaunch(
|
|
1221
1477
|
prev,
|
|
1222
1478
|
prev.tools.running,
|
|
1223
1479
|
tools.running,
|
|
1224
1480
|
at
|
|
1225
1481
|
);
|
|
1226
1482
|
const refusedCalls = outcome.kind === "ok" ? refusedOf(prev) : [...refusedOf(prev), callId];
|
|
1227
|
-
const s =
|
|
1483
|
+
const s = noted(
|
|
1484
|
+
{ ...prev, toolResilience, refusedCalls },
|
|
1485
|
+
...outcome.kind === "ok" ? [] : [{ kind: "tool_failed", call, failure: outcome, at }],
|
|
1486
|
+
...toolsStarted(launched, at)
|
|
1487
|
+
);
|
|
1228
1488
|
const foldedConv = {
|
|
1229
1489
|
...conv,
|
|
1230
1490
|
// Stamp the producing-turn index on the record (#85, A1). At settle time
|
|
@@ -1383,29 +1643,34 @@ function createAgent(config) {
|
|
|
1383
1643
|
}
|
|
1384
1644
|
function boot(s, at) {
|
|
1385
1645
|
const [runSlice] = run2.boot(s.run, at);
|
|
1386
|
-
const
|
|
1387
|
-
if (isSettled(
|
|
1388
|
-
const conv =
|
|
1389
|
-
if (conv === null) return [
|
|
1646
|
+
const resumed = { ...s, run: runSlice };
|
|
1647
|
+
if (isSettled(resumed)) return [resumed, []];
|
|
1648
|
+
const conv = resumed.conversation;
|
|
1649
|
+
if (conv === null) return [resumed, []];
|
|
1390
1650
|
if (conv.awaiting.kind === "llm") {
|
|
1391
|
-
return fireBrainCall(
|
|
1651
|
+
return fireBrainCall(resumed, at);
|
|
1392
1652
|
}
|
|
1393
1653
|
if (conv.awaiting.kind === "compacting") {
|
|
1394
1654
|
const input = compactionCall(conv, conv.awaiting.folding);
|
|
1395
1655
|
const [compaction, cmds] = compact.attempt(
|
|
1396
|
-
|
|
1656
|
+
resumed.compaction,
|
|
1397
1657
|
COMPACTION_PURPOSE,
|
|
1398
1658
|
input,
|
|
1399
1659
|
at
|
|
1400
1660
|
);
|
|
1401
|
-
return [{ ...
|
|
1661
|
+
return [{ ...resumed, compaction }, cmds];
|
|
1402
1662
|
}
|
|
1403
1663
|
const [toolResilience, outcome] = ladder.boot(
|
|
1404
|
-
toolSlice(
|
|
1405
|
-
|
|
1664
|
+
toolSlice(resumed),
|
|
1665
|
+
resumed.tools.running,
|
|
1666
|
+
at
|
|
1667
|
+
);
|
|
1668
|
+
return applyLadder(
|
|
1669
|
+
noted(resumed, ...toolsStarted(resumed.tools.running, at)),
|
|
1670
|
+
toolResilience,
|
|
1671
|
+
outcome,
|
|
1406
1672
|
at
|
|
1407
1673
|
);
|
|
1408
|
-
return applyLadder(rebooted, toolResilience, outcome, at);
|
|
1409
1674
|
}
|
|
1410
1675
|
function cancel(s, at) {
|
|
1411
1676
|
const [runSlice] = run2.cancel(s.run, at);
|
|
@@ -1435,31 +1700,32 @@ function createAgent(config) {
|
|
|
1435
1700
|
if (settled === void 0 || settled === null) return [s, []];
|
|
1436
1701
|
return settled.outcome.kind === "ok" ? toolOk(s, settled.callId, settled.outcome.result, m.at) : toolErr(s, settled.callId, settled.outcome, m.at);
|
|
1437
1702
|
};
|
|
1703
|
+
const toolCell = (s, m) => transition(s, m.at, (entered) => foldTool(entered, m));
|
|
1438
1704
|
const toolCells = {};
|
|
1439
1705
|
for (const def of tools?.defs ?? []) {
|
|
1440
|
-
toolCells[def.okType] =
|
|
1441
|
-
toolCells[def.errType] =
|
|
1706
|
+
toolCells[def.okType] = toolCell;
|
|
1707
|
+
toolCells[def.errType] = toolCell;
|
|
1442
1708
|
}
|
|
1443
1709
|
const ownUpdate = {
|
|
1444
|
-
[MsgType.AgentStart]: (s, m) => start(s, m.runId, m.at),
|
|
1445
|
-
[MsgType.AgentToolOk]: (s, m) => toolOk(s, m.callId, m.result, m.at),
|
|
1710
|
+
[MsgType.AgentStart]: (s, m) => door.start(s, m.runId, m.at),
|
|
1711
|
+
[MsgType.AgentToolOk]: (s, m) => door.toolOk(s, m.callId, m.result, m.at),
|
|
1446
1712
|
// `agent_tool_err` is `createAgent`'s own raw settle Msg and its wire
|
|
1447
1713
|
// shape is a bare `reason` string — a consumer routing their own interpret
|
|
1448
1714
|
// through it never declared a tag, so the failure it mints carries none.
|
|
1449
|
-
[MsgType.AgentToolErr]: (s, m) => toolErr(s, m.callId, m.reason, m.at),
|
|
1715
|
+
[MsgType.AgentToolErr]: (s, m) => door.toolErr(s, m.callId, m.reason, m.at),
|
|
1450
1716
|
// The engine-minted brain-call settle Msgs (from `brainHandlers`' outcome):
|
|
1451
1717
|
// success runs `succeed` (reset retry + fold the turn), failure runs `fail`.
|
|
1452
|
-
[MsgType.ResilientOk]: (s, m) => succeed(s, m, m.at),
|
|
1453
|
-
[MsgType.ResilientErr]: (s, m) => fail(s, m, m.at),
|
|
1718
|
+
[MsgType.ResilientOk]: (s, m) => door.succeed(s, m, m.at),
|
|
1719
|
+
[MsgType.ResilientErr]: (s, m) => door.fail(s, m, m.at),
|
|
1454
1720
|
// The re-entered compaction settle Msgs (from the consumer's `compact_run`
|
|
1455
1721
|
// cell, #85): `compact_ok` folds the summary back (drop oldest turns +
|
|
1456
1722
|
// their records, fire the next brain call), `compact_err` backs off via the
|
|
1457
1723
|
// compaction retry or proceeds without compacting.
|
|
1458
|
-
[MsgType.CompactOk]: (s, m) => compactOk(s, m.key, m, m.at),
|
|
1459
|
-
[MsgType.CompactErr]: (s, m) => compactErr(s, m.key, m, m.at),
|
|
1460
|
-
deadline_exceeded: (s, m) => onTimer(s, m),
|
|
1461
|
-
[MsgType.AgentBoot]: (s, m) => boot(s, m.at),
|
|
1462
|
-
[MsgType.AgentCancel]: (s, m) =>
|
|
1724
|
+
[MsgType.CompactOk]: (s, m) => door.compactOk(s, m.key, m, m.at),
|
|
1725
|
+
[MsgType.CompactErr]: (s, m) => door.compactErr(s, m.key, m, m.at),
|
|
1726
|
+
deadline_exceeded: (s, m) => door.onTimer(s, m),
|
|
1727
|
+
[MsgType.AgentBoot]: (s, m) => door.boot(s, m.at),
|
|
1728
|
+
[MsgType.AgentCancel]: (s, m) => transition(s, m.at, (entered) => cancel(entered, m.at))
|
|
1463
1729
|
};
|
|
1464
1730
|
const update = { ...ownUpdate, ...toolCells };
|
|
1465
1731
|
const machine = {
|
|
@@ -1477,18 +1743,27 @@ function createAgent(config) {
|
|
|
1477
1743
|
subscribe: { deadline: subscribeDeadline }
|
|
1478
1744
|
};
|
|
1479
1745
|
}
|
|
1746
|
+
function transition(s, at, verb) {
|
|
1747
|
+
const current = withUsageDefaults(s);
|
|
1748
|
+
const entered = (current.lifecycle ?? []).length === 0 ? current : { ...current, lifecycle: [] };
|
|
1749
|
+
const [next, cmds] = verb(entered);
|
|
1750
|
+
return !isSettled(entered) && isSettled(next) ? [noted(next, { kind: "run_ended", at }), cmds] : [next, cmds];
|
|
1751
|
+
}
|
|
1752
|
+
const door = {
|
|
1753
|
+
start: (s, runId, at) => transition(s, at, (e) => start(e, runId, at)),
|
|
1754
|
+
turn: (s, result, at) => transition(s, at, (e) => turn(e, result, at)),
|
|
1755
|
+
toolOk: (s, callId, result, at) => transition(s, at, (e) => toolOk(e, callId, result, at)),
|
|
1756
|
+
toolErr: (s, callId, failure, at) => transition(s, at, (e) => toolErr(e, callId, failure, at)),
|
|
1757
|
+
succeed: (s, msg, at) => transition(s, at, (e) => succeed(e, msg, at)),
|
|
1758
|
+
fail: (s, msg, at) => transition(s, at, (e) => fail(e, msg, at)),
|
|
1759
|
+
compactOk: (s, key, msg, at) => transition(s, at, (e) => compactOk(e, key, msg, at)),
|
|
1760
|
+
compactErr: (s, key, msg, at) => transition(s, at, (e) => compactErr(e, key, msg, at)),
|
|
1761
|
+
onTimer: (s, msg) => transition(s, msg.atMs, (e) => onTimer(e, msg)),
|
|
1762
|
+
boot: (s, at) => transition(s, at, (e) => boot(e, at))
|
|
1763
|
+
};
|
|
1480
1764
|
return {
|
|
1481
1765
|
init,
|
|
1482
|
-
|
|
1483
|
-
turn,
|
|
1484
|
-
toolOk,
|
|
1485
|
-
toolErr,
|
|
1486
|
-
succeed,
|
|
1487
|
-
fail,
|
|
1488
|
-
compactOk,
|
|
1489
|
-
compactErr,
|
|
1490
|
-
onTimer,
|
|
1491
|
-
boot,
|
|
1766
|
+
...door,
|
|
1492
1767
|
isSettled,
|
|
1493
1768
|
currentStage,
|
|
1494
1769
|
brainCall,
|
|
@@ -1501,6 +1776,6 @@ function createAgent(config) {
|
|
|
1501
1776
|
};
|
|
1502
1777
|
}
|
|
1503
1778
|
|
|
1504
|
-
export { COMPACTION_PURPOSE, PLAIN_MODEL_MISROUTE_REASON, TOOL_RETRY_EXHAUSTED_TAG, TOOL_TIMEOUT_TAG, agentBootMsg, agentCancelMsg, agentEvents, agentTurnSchema, compactionSummarySchema, createAgent, defineAgent, fanOutInterpret, isAgentTurn, isCompactionSummary, isReservedToolName, isStreamingModel, liftAgent, mergeInterpret, plainModel, renderPrompt, status, tool, toolErrorReason, toolRouter, transcript };
|
|
1505
|
-
//# sourceMappingURL=chunk-
|
|
1506
|
-
//# sourceMappingURL=chunk-
|
|
1779
|
+
export { AGENT_EVENT_TYPES, COMPACTION_PURPOSE, FILE_OMITTED, IMAGE_OMITTED, PLAIN_MODEL_MISROUTE_REASON, TOOL_RETRY_EXHAUSTED_TAG, TOOL_TIMEOUT_TAG, agentBootMsg, agentCancelMsg, agentEvents, agentTool, agentTurnSchema, compactionSummarySchema, contentParts, createAgent, defineAgent, fanOutInterpret, isAgentTurn, isCompactionSummary, isReservedToolName, isStreamingModel, isTurnUsage, liftAgent, mergeInterpret, omitMedia, plainModel, renderPrompt, status, tool, toolErrorReason, toolRouter, transcript };
|
|
1780
|
+
//# sourceMappingURL=chunk-PCJA2HTZ.js.map
|
|
1781
|
+
//# sourceMappingURL=chunk-PCJA2HTZ.js.map
|