tnega 0.3.0 → 0.4.1
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 +3 -3
- package/dist/agent.js +2207 -513
- package/dist/agent.js.map +4 -4
- package/dist/bin.js +942 -469
- package/dist/bin.js.map +3 -3
- package/dist/cli-runtime.js +943 -469
- package/dist/cli-runtime.js.map +3 -3
- package/dist/coding-agent.js +1623 -162
- package/dist/coding-agent.js.map +4 -4
- package/dist/eval.js +422 -158
- package/dist/eval.js.map +3 -3
- package/dist/evolve.js +512 -326
- package/dist/evolve.js.map +4 -4
- package/dist/index.js +951 -469
- package/dist/index.js.map +3 -3
- package/dist/llm.js +47 -3
- package/dist/llm.js.map +3 -3
- package/dist/session.js +91 -5
- package/dist/session.js.map +2 -2
- package/dist/types/packages/agent/src/inbox-durable.d.ts +5 -0
- package/dist/types/packages/agent/src/live.d.ts +24 -8
- package/dist/types/packages/agent/src/service.d.ts +8 -2
- package/dist/types/packages/agent/src/types.d.ts +40 -2
- package/dist/types/packages/cli/src/config.d.ts +2 -0
- package/dist/types/packages/cli/src/index.d.ts +1 -0
- package/dist/types/packages/llm/src/types.d.ts +2 -0
- package/dist/types/packages/session/src/index.d.ts +68 -7
- package/dist/types/packages/session/src/invariant.d.ts +2 -0
- package/dist/types/src/index.d.ts +2 -2
- package/dist/web/assets/{index-45pokiBH.js → index-Bq0i29_u.js} +30 -30
- package/dist/web/index.html +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -9096,6 +9096,8 @@ __export(src_exports2, {
|
|
|
9096
9096
|
SESSION_FORMAT_VERSION: () => SESSION_FORMAT_VERSION,
|
|
9097
9097
|
SessionFormatError: () => SessionFormatError,
|
|
9098
9098
|
SessionLog: () => SessionLog,
|
|
9099
|
+
assistantStreams: () => assistantStreams,
|
|
9100
|
+
checkAssistantAttempts: () => checkAssistantAttempts,
|
|
9099
9101
|
checkBalancedSteps: () => checkBalancedSteps,
|
|
9100
9102
|
checkBalancedToolCalls: () => checkBalancedToolCalls,
|
|
9101
9103
|
checkBalancedTurns: () => checkBalancedTurns,
|
|
@@ -9226,17 +9228,88 @@ function checkMonotonicSeq(events) {
|
|
|
9226
9228
|
}
|
|
9227
9229
|
return failures;
|
|
9228
9230
|
}
|
|
9231
|
+
function isRecord(value) {
|
|
9232
|
+
return typeof value === "object" && value !== null && (Object.getPrototypeOf(value) === Object.prototype || Object.getPrototypeOf(value) === null);
|
|
9233
|
+
}
|
|
9234
|
+
function isNonNegativeInteger(value) {
|
|
9235
|
+
return typeof value === "number" && Number.isSafeInteger(value) && value >= 0;
|
|
9236
|
+
}
|
|
9237
|
+
function isJsonValue(value, ancestors = /* @__PURE__ */ new Set()) {
|
|
9238
|
+
if (value === null || typeof value === "string" || typeof value === "boolean") return true;
|
|
9239
|
+
if (typeof value === "number") return Number.isFinite(value);
|
|
9240
|
+
if (typeof value !== "object" || ancestors.has(value)) return false;
|
|
9241
|
+
if (!Array.isArray(value) && Object.getPrototypeOf(value) !== Object.prototype && Object.getPrototypeOf(value) !== null) return false;
|
|
9242
|
+
ancestors.add(value);
|
|
9243
|
+
const valid = (Array.isArray(value) ? Array.from(value) : Object.values(value)).every((member) => isJsonValue(member, ancestors));
|
|
9244
|
+
ancestors.delete(value);
|
|
9245
|
+
return valid;
|
|
9246
|
+
}
|
|
9247
|
+
function isStreamRecord(value) {
|
|
9248
|
+
if (!isRecord(value) || !isNonNegativeInteger(value.time) || !isRecord(value.chunk)) return false;
|
|
9249
|
+
const chunk = value.chunk;
|
|
9250
|
+
if (chunk.type === "stream_error") {
|
|
9251
|
+
return isRecord(chunk.error) && typeof chunk.error.message === "string" && (chunk.error.name === void 0 || typeof chunk.error.name === "string") && (chunk.error.stack === void 0 || typeof chunk.error.stack === "string");
|
|
9252
|
+
}
|
|
9253
|
+
if (typeof chunk.id !== "string") return false;
|
|
9254
|
+
switch (chunk.type) {
|
|
9255
|
+
case "message_start":
|
|
9256
|
+
return chunk.model === void 0 || typeof chunk.model === "string";
|
|
9257
|
+
case "message_delta":
|
|
9258
|
+
return typeof chunk.delta === "string";
|
|
9259
|
+
case "toolcall_start":
|
|
9260
|
+
case "toolcall_end":
|
|
9261
|
+
return isNonNegativeInteger(chunk.index) && typeof chunk.name === "string" && (chunk.type === "toolcall_start" || isJsonValue(chunk.arguments));
|
|
9262
|
+
case "message_stop":
|
|
9263
|
+
return chunk.finishReason === "stop" || chunk.finishReason === "tool_calls" || chunk.finishReason === "length" || chunk.finishReason === "max_turns" || chunk.finishReason === "max_steps" || chunk.finishReason === "error" || chunk.finishReason === "cancelled";
|
|
9264
|
+
default:
|
|
9265
|
+
return false;
|
|
9266
|
+
}
|
|
9267
|
+
}
|
|
9268
|
+
function checkAssistantAttempts(events) {
|
|
9269
|
+
const turns = /* @__PURE__ */ new Set();
|
|
9270
|
+
const steps = /* @__PURE__ */ new Map();
|
|
9271
|
+
const failures = [];
|
|
9272
|
+
for (const event of events) {
|
|
9273
|
+
if (event.type === "turn/start") turns.add(event.payload.turn);
|
|
9274
|
+
if (event.type === "turn/end") {
|
|
9275
|
+
turns.delete(event.payload.turn);
|
|
9276
|
+
for (const [key, turn] of steps) {
|
|
9277
|
+
if (turn === event.payload.turn) steps.delete(key);
|
|
9278
|
+
}
|
|
9279
|
+
}
|
|
9280
|
+
if (event.type === "step/start" && turns.has(event.payload.turn)) {
|
|
9281
|
+
steps.set(`${event.payload.turn}:${event.payload.step}`, event.payload.turn);
|
|
9282
|
+
}
|
|
9283
|
+
if (event.type === "step/end") steps.delete(`${event.payload.turn}:${event.payload.step}`);
|
|
9284
|
+
if (event.type !== "assistant/attempt") continue;
|
|
9285
|
+
const payload = event.payload;
|
|
9286
|
+
if (!isRecord(payload) || !isNonNegativeInteger(payload.turn) || !isNonNegativeInteger(payload.step) || !turns.has(payload.turn) || !steps.has(`${payload.turn}:${payload.step}`)) {
|
|
9287
|
+
failures.push({
|
|
9288
|
+
name: "assistant/attempt-without-open-step",
|
|
9289
|
+
detail: `assistant/attempt at seq ${event.seq} has no matching open turn and step`
|
|
9290
|
+
});
|
|
9291
|
+
}
|
|
9292
|
+
if (!isRecord(payload) || !Array.isArray(payload.stream) || !payload.stream.every(isStreamRecord)) {
|
|
9293
|
+
failures.push({
|
|
9294
|
+
name: "assistant/attempt-invalid-stream",
|
|
9295
|
+
detail: `assistant/attempt at seq ${event.seq} must contain an ordered array of normalized stream records`
|
|
9296
|
+
});
|
|
9297
|
+
}
|
|
9298
|
+
}
|
|
9299
|
+
return failures;
|
|
9300
|
+
}
|
|
9229
9301
|
function checkSessionInvariants(events) {
|
|
9230
9302
|
return [
|
|
9231
9303
|
...checkBalancedTurns(events),
|
|
9232
9304
|
...checkBalancedSteps(events),
|
|
9233
9305
|
...checkBalancedToolCalls(events),
|
|
9234
|
-
...checkMonotonicSeq(events)
|
|
9306
|
+
...checkMonotonicSeq(events),
|
|
9307
|
+
...checkAssistantAttempts(events)
|
|
9235
9308
|
];
|
|
9236
9309
|
}
|
|
9237
9310
|
|
|
9238
9311
|
// packages/session/src/index.ts
|
|
9239
|
-
var SESSION_FORMAT_VERSION =
|
|
9312
|
+
var SESSION_FORMAT_VERSION = 10;
|
|
9240
9313
|
var SessionFormatError = class extends Error {
|
|
9241
9314
|
name = "SessionFormatError";
|
|
9242
9315
|
};
|
|
@@ -9256,6 +9329,12 @@ function isSessionEvent(value) {
|
|
|
9256
9329
|
const record3 = value;
|
|
9257
9330
|
return typeof record3.id === "string" && typeof record3.seq === "number" && typeof record3.ts === "number" && typeof record3.type === "string" && "payload" in record3;
|
|
9258
9331
|
}
|
|
9332
|
+
function assistantStreams(events) {
|
|
9333
|
+
return events.flatMap((event) => {
|
|
9334
|
+
if (event.type !== "assistant/message" && event.type !== "assistant/attempt") return [];
|
|
9335
|
+
return event.payload.stream === void 0 ? [] : [clone(event.payload.stream)];
|
|
9336
|
+
});
|
|
9337
|
+
}
|
|
9259
9338
|
function clone(value) {
|
|
9260
9339
|
return structuredClone(value);
|
|
9261
9340
|
}
|
|
@@ -9411,7 +9490,7 @@ function transcriptEvents(events) {
|
|
|
9411
9490
|
const structure = events.filter((event) => !inSkeleton.has(event.id)).filter((event) => event.type !== "compaction/start" && event.type !== "compaction/end").filter((event) => event.type !== "checkpoint").filter((event) => !(event.type === "tool/call" && declaredCalls.has(event.payload.id)));
|
|
9412
9491
|
const ordered = [...skeleton];
|
|
9413
9492
|
for (const event of structure) {
|
|
9414
|
-
let index =
|
|
9493
|
+
let index = 0;
|
|
9415
9494
|
for (let cursor = ordered.length - 1; cursor >= 0; cursor -= 1) {
|
|
9416
9495
|
if (ordered[cursor].seq <= event.seq) {
|
|
9417
9496
|
index = cursor + 1;
|
|
@@ -9511,6 +9590,7 @@ function estimateEventTokens(event) {
|
|
|
9511
9590
|
return Math.ceil(raw.length / 4);
|
|
9512
9591
|
}
|
|
9513
9592
|
case "plan":
|
|
9593
|
+
case "assistant/attempt":
|
|
9514
9594
|
return 0;
|
|
9515
9595
|
case "checkpoint":
|
|
9516
9596
|
return estimateMessageTokens(event.payload.messages);
|
|
@@ -9667,9 +9747,15 @@ function estimateContextUsage(messages, limit = DEFAULT_CONTEXT_LIMIT) {
|
|
|
9667
9747
|
};
|
|
9668
9748
|
}
|
|
9669
9749
|
var SessionLog = class {
|
|
9670
|
-
constructor(file, _broadcast) {
|
|
9750
|
+
constructor(file, _broadcast, publicationContext) {
|
|
9671
9751
|
this.file = file;
|
|
9672
9752
|
this._broadcast = _broadcast;
|
|
9753
|
+
if (!this._broadcast && publicationContext) {
|
|
9754
|
+
this._broadcast = (type, payload) => {
|
|
9755
|
+
if (type === "event") publicationContext.emit("session/event", payload);
|
|
9756
|
+
else publicationContext.emit("session/flush", payload);
|
|
9757
|
+
};
|
|
9758
|
+
}
|
|
9673
9759
|
}
|
|
9674
9760
|
file;
|
|
9675
9761
|
_broadcast;
|
|
@@ -9838,7 +9924,7 @@ var SessionLog = class {
|
|
|
9838
9924
|
selected.push(clone(event));
|
|
9839
9925
|
continue;
|
|
9840
9926
|
}
|
|
9841
|
-
if (event.type === "meta" || event.type === "llm/retry" || event.type === "llm/retry-started" || event.type.startsWith("turn/") || event.type.startsWith("step/")) {
|
|
9927
|
+
if (event.type === "meta" || event.type === "llm/retry" || event.type === "llm/retry-started" || event.type === "assistant/attempt" || event.type.startsWith("turn/") || event.type.startsWith("step/")) {
|
|
9842
9928
|
continue;
|
|
9843
9929
|
}
|
|
9844
9930
|
if (event.type === "checkpoint") {
|
|
@@ -11511,7 +11597,7 @@ function copyMessages(messages) {
|
|
|
11511
11597
|
copy.tool_calls = message3.tool_calls.map((call) => ({
|
|
11512
11598
|
id: call.id,
|
|
11513
11599
|
name: call.name,
|
|
11514
|
-
arguments: call.arguments
|
|
11600
|
+
arguments: structuredClone(call.arguments)
|
|
11515
11601
|
}));
|
|
11516
11602
|
}
|
|
11517
11603
|
return copy;
|
|
@@ -11542,6 +11628,75 @@ function copyCompletion(completion) {
|
|
|
11542
11628
|
}
|
|
11543
11629
|
return copy;
|
|
11544
11630
|
}
|
|
11631
|
+
function canonicalMessages(messages) {
|
|
11632
|
+
return JSON.stringify(messages.map((message3) => ({
|
|
11633
|
+
role: message3.role,
|
|
11634
|
+
content: message3.content,
|
|
11635
|
+
...message3.name ? { name: message3.name } : {},
|
|
11636
|
+
...message3.tool_call_id ? { tool_call_id: message3.tool_call_id } : {},
|
|
11637
|
+
...message3.tool_calls?.length ? { tool_calls: message3.tool_calls } : {},
|
|
11638
|
+
...message3.toolOk !== void 0 ? { toolOk: message3.toolOk } : {},
|
|
11639
|
+
...message3.toolError ? {
|
|
11640
|
+
toolError: { name: message3.toolError.name, message: message3.toolError.message }
|
|
11641
|
+
} : {}
|
|
11642
|
+
})));
|
|
11643
|
+
}
|
|
11644
|
+
function freezeRequestData(data) {
|
|
11645
|
+
const visited = /* @__PURE__ */ new Set();
|
|
11646
|
+
const freeze = (value) => {
|
|
11647
|
+
if (typeof value !== "object" || value === null || visited.has(value)) return;
|
|
11648
|
+
visited.add(value);
|
|
11649
|
+
for (const child of Object.values(value)) freeze(child);
|
|
11650
|
+
Object.freeze(value);
|
|
11651
|
+
};
|
|
11652
|
+
freeze(data);
|
|
11653
|
+
}
|
|
11654
|
+
function lockStreamRequest(request) {
|
|
11655
|
+
freezeRequestData(request.messages);
|
|
11656
|
+
request.tools = Object.freeze(request.tools.map((tool) => {
|
|
11657
|
+
const schema = structuredClone(tool.schema);
|
|
11658
|
+
freezeRequestData(schema);
|
|
11659
|
+
return Object.freeze({ ...tool, schema });
|
|
11660
|
+
}));
|
|
11661
|
+
Object.freeze(request.options);
|
|
11662
|
+
Object.freeze(request);
|
|
11663
|
+
}
|
|
11664
|
+
function requestHeaderFor(request, input) {
|
|
11665
|
+
const system = input.find((message3) => message3.role === "system")?.content;
|
|
11666
|
+
const tools2 = request.tools.map((tool) => ({
|
|
11667
|
+
name: tool.schema.name,
|
|
11668
|
+
description: tool.schema.description,
|
|
11669
|
+
...tool.schema.parameters ? { parameters: tool.schema.parameters } : {}
|
|
11670
|
+
}));
|
|
11671
|
+
const config2 = {
|
|
11672
|
+
...request.options.provider ? { provider: request.options.provider } : {},
|
|
11673
|
+
...request.options.model ? { model: request.options.model } : {},
|
|
11674
|
+
...request.options.temperature !== void 0 ? { temperature: request.options.temperature } : {}
|
|
11675
|
+
};
|
|
11676
|
+
return {
|
|
11677
|
+
...Object.keys(config2).length ? { config: config2 } : {},
|
|
11678
|
+
...system !== void 0 ? { system } : {},
|
|
11679
|
+
...tools2.length ? { tools: tools2 } : {}
|
|
11680
|
+
};
|
|
11681
|
+
}
|
|
11682
|
+
async function* completeAsStream(llm, messages, tools2, options) {
|
|
11683
|
+
const id = randomUUID2();
|
|
11684
|
+
yield { type: "message_start", id };
|
|
11685
|
+
const completion = await llm.complete(messages, tools2, options);
|
|
11686
|
+
if (completion.content) yield { type: "message_delta", id, delta: completion.content };
|
|
11687
|
+
for (let index = 0; index < (completion.toolCalls?.length ?? 0); index += 1) {
|
|
11688
|
+
const call = completion.toolCalls[index];
|
|
11689
|
+
yield { type: "toolcall_start", id: call.id, index, name: call.name };
|
|
11690
|
+
yield {
|
|
11691
|
+
type: "toolcall_end",
|
|
11692
|
+
id: call.id,
|
|
11693
|
+
index,
|
|
11694
|
+
name: call.name,
|
|
11695
|
+
arguments: call.arguments
|
|
11696
|
+
};
|
|
11697
|
+
}
|
|
11698
|
+
yield { type: "message_stop", id, finishReason: completion.finishReason };
|
|
11699
|
+
}
|
|
11545
11700
|
function isCancelCause(value) {
|
|
11546
11701
|
if (typeof value !== "object" || value === null) return false;
|
|
11547
11702
|
const record3 = value;
|
|
@@ -11562,6 +11717,13 @@ function cancelCauseFromSignal(signal) {
|
|
|
11562
11717
|
if (isCancelCause(reason)) return reason;
|
|
11563
11718
|
return { type: "abort" };
|
|
11564
11719
|
}
|
|
11720
|
+
function abortedToolError(signal) {
|
|
11721
|
+
const cause = cancelCauseFromSignal(signal);
|
|
11722
|
+
return {
|
|
11723
|
+
name: "AbortError",
|
|
11724
|
+
message: `tool call aborted: ${cause?.type ?? "abort"}`
|
|
11725
|
+
};
|
|
11726
|
+
}
|
|
11565
11727
|
function toTurnEndReason(fields) {
|
|
11566
11728
|
const { cancelled, turnError, finishReason, cancelCause } = fields;
|
|
11567
11729
|
if (cancelled || finishReason === "cancelled") {
|
|
@@ -11606,6 +11768,78 @@ async function cancellableDelay(ms, signal) {
|
|
|
11606
11768
|
signal?.addEventListener("abort", onAbort, { once: true });
|
|
11607
11769
|
});
|
|
11608
11770
|
}
|
|
11771
|
+
var AssistantStreamAttempt = class {
|
|
11772
|
+
constructor(session2, turn, step, nextRevision) {
|
|
11773
|
+
this.session = session2;
|
|
11774
|
+
this.turn = turn;
|
|
11775
|
+
this.step = step;
|
|
11776
|
+
this.nextRevision = nextRevision;
|
|
11777
|
+
}
|
|
11778
|
+
session;
|
|
11779
|
+
turn;
|
|
11780
|
+
step;
|
|
11781
|
+
nextRevision;
|
|
11782
|
+
attemptId = randomUUID2();
|
|
11783
|
+
records = [];
|
|
11784
|
+
ended = false;
|
|
11785
|
+
start() {
|
|
11786
|
+
return { type: "assistant/stream", frame: {
|
|
11787
|
+
type: "start",
|
|
11788
|
+
attemptId: this.attemptId,
|
|
11789
|
+
revision: this.nextRevision(),
|
|
11790
|
+
turn: this.turn,
|
|
11791
|
+
step: this.step
|
|
11792
|
+
} };
|
|
11793
|
+
}
|
|
11794
|
+
push(chunk) {
|
|
11795
|
+
if (this.ended) throw new AgentError("assistant attempt is already settled");
|
|
11796
|
+
const record3 = { time: Date.now(), chunk: structuredClone(chunk) };
|
|
11797
|
+
const index = this.records.length;
|
|
11798
|
+
this.records.push(record3);
|
|
11799
|
+
return { type: "assistant/stream", frame: {
|
|
11800
|
+
type: "chunk",
|
|
11801
|
+
attemptId: this.attemptId,
|
|
11802
|
+
revision: this.nextRevision(),
|
|
11803
|
+
index,
|
|
11804
|
+
...structuredClone(record3)
|
|
11805
|
+
} };
|
|
11806
|
+
}
|
|
11807
|
+
async settle(message3) {
|
|
11808
|
+
if (this.ended) throw new AgentError("assistant attempt is already settled");
|
|
11809
|
+
const eventType = message3 ? "assistant/message" : "assistant/attempt";
|
|
11810
|
+
let event;
|
|
11811
|
+
try {
|
|
11812
|
+
event = message3 ? await this.session.append("assistant/message", { ...message3, stream: this.records }) : await this.session.append("assistant/attempt", { turn: this.turn, step: this.step, stream: this.records });
|
|
11813
|
+
} catch (cause) {
|
|
11814
|
+
this.ended = true;
|
|
11815
|
+
const frame = { type: "assistant/stream", frame: {
|
|
11816
|
+
type: "end",
|
|
11817
|
+
attemptId: this.attemptId,
|
|
11818
|
+
revision: this.nextRevision(),
|
|
11819
|
+
index: this.records.length,
|
|
11820
|
+
outcome: { kind: "abandoned" }
|
|
11821
|
+
} };
|
|
11822
|
+
throw new AttemptSettlementError(cause, frame);
|
|
11823
|
+
}
|
|
11824
|
+
this.ended = true;
|
|
11825
|
+
return { type: "assistant/stream", frame: {
|
|
11826
|
+
type: "end",
|
|
11827
|
+
attemptId: this.attemptId,
|
|
11828
|
+
revision: this.nextRevision(),
|
|
11829
|
+
index: this.records.length,
|
|
11830
|
+
outcome: { kind: "committed", eventType, seq: event.seq }
|
|
11831
|
+
} };
|
|
11832
|
+
}
|
|
11833
|
+
};
|
|
11834
|
+
var AttemptSettlementError = class extends Error {
|
|
11835
|
+
constructor(cause, frame) {
|
|
11836
|
+
super("assistant attempt settlement failed");
|
|
11837
|
+
this.cause = cause;
|
|
11838
|
+
this.frame = frame;
|
|
11839
|
+
}
|
|
11840
|
+
cause;
|
|
11841
|
+
frame;
|
|
11842
|
+
};
|
|
11609
11843
|
var AgentService = class {
|
|
11610
11844
|
constructor(ctx, config2 = {}) {
|
|
11611
11845
|
this.ctx = ctx;
|
|
@@ -11614,9 +11848,24 @@ var AgentService = class {
|
|
|
11614
11848
|
}
|
|
11615
11849
|
ctx;
|
|
11616
11850
|
config;
|
|
11851
|
+
async *settleAttempt(attempt, message3) {
|
|
11852
|
+
try {
|
|
11853
|
+
yield await attempt.settle(message3);
|
|
11854
|
+
} catch (error2) {
|
|
11855
|
+
if (error2 instanceof AttemptSettlementError) {
|
|
11856
|
+
yield error2.frame;
|
|
11857
|
+
throw error2.cause;
|
|
11858
|
+
}
|
|
11859
|
+
throw error2;
|
|
11860
|
+
}
|
|
11861
|
+
}
|
|
11617
11862
|
inbox;
|
|
11618
11863
|
_seriesStarted = false;
|
|
11619
11864
|
_persistedRequest = false;
|
|
11865
|
+
_streamRevision = 0;
|
|
11866
|
+
_attempt(session2, turn, step) {
|
|
11867
|
+
return new AssistantStreamAttempt(session2, turn, step, () => ++this._streamRevision);
|
|
11868
|
+
}
|
|
11620
11869
|
/** Call when a request begins an explicit new model-message series. */
|
|
11621
11870
|
startSeries() {
|
|
11622
11871
|
this._seriesStarted = true;
|
|
@@ -11630,7 +11879,7 @@ var AgentService = class {
|
|
|
11630
11879
|
return this._persistedRequest;
|
|
11631
11880
|
}
|
|
11632
11881
|
async run(input, options = {}) {
|
|
11633
|
-
return consumeAgentStream(this._stream(input, options
|
|
11882
|
+
return consumeAgentStream(this._stream(input, options));
|
|
11634
11883
|
}
|
|
11635
11884
|
async *runStream(input, options = {}) {
|
|
11636
11885
|
const iterator = this._stream(input, options)[Symbol.asyncIterator]();
|
|
@@ -11640,7 +11889,7 @@ var AgentService = class {
|
|
|
11640
11889
|
yield next.value;
|
|
11641
11890
|
}
|
|
11642
11891
|
}
|
|
11643
|
-
async *_stream(input, options = {}
|
|
11892
|
+
async *_stream(input, options = {}) {
|
|
11644
11893
|
const claimed = input ?? this.inbox.claim();
|
|
11645
11894
|
if (!claimed) throw new AgentError("no agent input available");
|
|
11646
11895
|
await this.config.hooks?.beforeRun?.(claimed, options);
|
|
@@ -11648,26 +11897,32 @@ var AgentService = class {
|
|
|
11648
11897
|
const tools2 = this._tools();
|
|
11649
11898
|
const llm = this._llm();
|
|
11650
11899
|
if (!llm) throw new AgentError("no LLM adapter available");
|
|
11900
|
+
const streamAdapter = llm.stream;
|
|
11901
|
+
const persistChunks = streamAdapter !== void 0;
|
|
11651
11902
|
const maxTurns = options.maxTurns ?? this.config.maxTurns ?? 64;
|
|
11652
11903
|
const maxSteps = options.maxSteps ?? this.config.maxSteps ?? 64;
|
|
11653
11904
|
const contextBudget = options.contextBudget ?? this.config.contextBudget;
|
|
11654
11905
|
const injected = this.inbox.injected();
|
|
11655
11906
|
this.ctx.emit("agent/start", { input: claimed, options, injected });
|
|
11656
11907
|
let messages = await this._initialMessages(claimed);
|
|
11908
|
+
let claimedMessages = messages.filter((message3) => message3.role === "user");
|
|
11657
11909
|
const steps = [];
|
|
11658
11910
|
let output = "";
|
|
11659
11911
|
let finishReason = "stop";
|
|
11912
|
+
let lengthReached = false;
|
|
11660
11913
|
this.ctx.emit("agent/turn-start", {
|
|
11661
11914
|
input: claimed,
|
|
11662
11915
|
messages: copyMessages(messages),
|
|
11663
11916
|
injected
|
|
11664
11917
|
});
|
|
11665
|
-
const turn = await session2.nextTurn();
|
|
11666
|
-
|
|
11667
|
-
turn,
|
|
11668
|
-
|
|
11669
|
-
|
|
11670
|
-
|
|
11918
|
+
const turn = options.turn ?? await session2.nextTurn();
|
|
11919
|
+
if (options.turn === void 0) {
|
|
11920
|
+
await session2.append("turn/start", {
|
|
11921
|
+
turn,
|
|
11922
|
+
input: claimed.text ?? claimed,
|
|
11923
|
+
reason: "user"
|
|
11924
|
+
});
|
|
11925
|
+
}
|
|
11671
11926
|
let index = 0;
|
|
11672
11927
|
let finalTurnGranted = false;
|
|
11673
11928
|
let currentStepIndex;
|
|
@@ -11686,20 +11941,22 @@ var AgentService = class {
|
|
|
11686
11941
|
messages = await this._enforceContextBudget(session2, contextBudget, messages);
|
|
11687
11942
|
}
|
|
11688
11943
|
const stepInput = copyMessages(messages);
|
|
11689
|
-
const preStep = this.ctx.
|
|
11944
|
+
const preStep = await this.ctx.waterfallAsync("agent/pre-step", {
|
|
11690
11945
|
index,
|
|
11691
11946
|
turn,
|
|
11692
11947
|
step: index,
|
|
11693
11948
|
messages: stepInput,
|
|
11949
|
+
claimedMessages: copyMessages(claimedMessages),
|
|
11694
11950
|
...options.signal ? { signal: options.signal } : {}
|
|
11695
11951
|
}, (payload) => payload);
|
|
11696
|
-
if (!preStep || !Array.isArray(preStep.messages) || !preStep.messages.length) {
|
|
11952
|
+
if (!preStep || preStep.admission === "reject" || !Array.isArray(preStep.messages) || !preStep.messages.length) {
|
|
11697
11953
|
break;
|
|
11698
11954
|
}
|
|
11699
11955
|
if (preStep.startsRequestSeries) this._seriesStarted = true;
|
|
11700
11956
|
await session2.append("step/start", { turn, step: index });
|
|
11701
11957
|
currentStepIndex = index;
|
|
11702
11958
|
const requestedInput = copyMessages(preStep.messages);
|
|
11959
|
+
const admittedHistory = await session2.deriveMessages();
|
|
11703
11960
|
this.ctx.emit("agent/step", {
|
|
11704
11961
|
index,
|
|
11705
11962
|
turn,
|
|
@@ -11711,93 +11968,85 @@ var AgentService = class {
|
|
|
11711
11968
|
maxSteps: maxSteps - steps.length
|
|
11712
11969
|
};
|
|
11713
11970
|
if (options.signal) completeOptions.signal = options.signal;
|
|
11714
|
-
const request = this.ctx.waterfall("agent/request", {
|
|
11715
|
-
index,
|
|
11716
|
-
messages: requestedInput,
|
|
11717
|
-
tools: availableTools,
|
|
11718
|
-
options: completeOptions
|
|
11719
|
-
}, (payload) => payload);
|
|
11720
|
-
if (!request || !request.options || !request.tools) {
|
|
11721
|
-
throw new AgentError("agent/request must return a request payload");
|
|
11722
|
-
}
|
|
11723
11971
|
let llmMessages = copyMessages(requestedInput);
|
|
11724
11972
|
let completion;
|
|
11725
|
-
|
|
11973
|
+
let activeAttempt;
|
|
11726
11974
|
let attempt = 0;
|
|
11727
|
-
let persistedStepInput = false;
|
|
11728
11975
|
while (true) {
|
|
11729
11976
|
if (options.signal?.aborted) {
|
|
11730
11977
|
finishReason = "cancelled";
|
|
11731
11978
|
break;
|
|
11732
11979
|
}
|
|
11733
11980
|
const streamEvents = [];
|
|
11981
|
+
activeAttempt = this._attempt(session2, turn, index);
|
|
11982
|
+
yield activeAttempt.start();
|
|
11983
|
+
const streamRequest = {
|
|
11984
|
+
index,
|
|
11985
|
+
messages: copyMessages(requestedInput),
|
|
11986
|
+
tools: [...availableTools],
|
|
11987
|
+
options: { ...completeOptions }
|
|
11988
|
+
};
|
|
11734
11989
|
try {
|
|
11735
|
-
|
|
11736
|
-
|
|
11737
|
-
|
|
11738
|
-
|
|
11739
|
-
|
|
11740
|
-
|
|
11741
|
-
|
|
11742
|
-
|
|
11743
|
-
|
|
11744
|
-
|
|
11745
|
-
|
|
11746
|
-
|
|
11747
|
-
|
|
11748
|
-
|
|
11749
|
-
return streamMethod(payload.messages, payload.tools, payload.options);
|
|
11750
|
-
}
|
|
11751
|
-
);
|
|
11752
|
-
if (!stream || typeof stream[Symbol.asyncIterator] !== "function") {
|
|
11753
|
-
throw new AgentError("llm/stream must return an async iterable stream");
|
|
11754
|
-
}
|
|
11990
|
+
const request = await this.ctx.waterfallAsync("agent/request", {
|
|
11991
|
+
index,
|
|
11992
|
+
messages: copyMessages(requestedInput),
|
|
11993
|
+
tools: streamRequest.tools,
|
|
11994
|
+
options: streamRequest.options
|
|
11995
|
+
}, (payload) => payload);
|
|
11996
|
+
if (!request || !request.options || !request.tools) {
|
|
11997
|
+
throw new AgentError("agent/request must return a request payload");
|
|
11998
|
+
}
|
|
11999
|
+
streamRequest.tools = request.tools;
|
|
12000
|
+
streamRequest.options = request.options;
|
|
12001
|
+
let preparation;
|
|
12002
|
+
const prepareRequest = () => preparation ??= (async () => {
|
|
12003
|
+
lockStreamRequest(streamRequest);
|
|
11755
12004
|
llmMessages = copyMessages(streamRequest.messages);
|
|
11756
|
-
|
|
11757
|
-
|
|
11758
|
-
|
|
11759
|
-
|
|
11760
|
-
|
|
11761
|
-
|
|
11762
|
-
|
|
11763
|
-
|
|
11764
|
-
|
|
11765
|
-
|
|
11766
|
-
|
|
11767
|
-
|
|
11768
|
-
|
|
11769
|
-
|
|
11770
|
-
|
|
11771
|
-
|
|
11772
|
-
|
|
11773
|
-
|
|
11774
|
-
|
|
11775
|
-
|
|
11776
|
-
|
|
11777
|
-
|
|
11778
|
-
|
|
11779
|
-
|
|
11780
|
-
|
|
11781
|
-
|
|
11782
|
-
}
|
|
11783
|
-
persistedStepInput = true;
|
|
12005
|
+
await this._persistStepInput(session2, streamRequest, llmMessages, admittedHistory);
|
|
12006
|
+
await this._assertReplayable(session2, streamRequest, llmMessages);
|
|
12007
|
+
})();
|
|
12008
|
+
const stream = await this.ctx.waterfallAsync(
|
|
12009
|
+
"llm/stream",
|
|
12010
|
+
streamRequest,
|
|
12011
|
+
(payload) => (async function* () {
|
|
12012
|
+
await prepareRequest();
|
|
12013
|
+
yield* streamAdapter ? streamAdapter.call(llm, payload.messages, payload.tools, payload.options) : completeAsStream(llm, payload.messages, payload.tools, payload.options);
|
|
12014
|
+
})()
|
|
12015
|
+
);
|
|
12016
|
+
if (!stream || typeof stream[Symbol.asyncIterator] !== "function") {
|
|
12017
|
+
throw new AgentError("llm/stream must return an async iterable stream");
|
|
12018
|
+
}
|
|
12019
|
+
await prepareRequest();
|
|
12020
|
+
let chunkIndex = 0;
|
|
12021
|
+
for await (const event of stream) {
|
|
12022
|
+
streamEvents.push(structuredClone(event));
|
|
12023
|
+
yield activeAttempt.push(event);
|
|
12024
|
+
if (persistChunks && event.type === "message_delta") {
|
|
12025
|
+
await session2.append("assistant/chunk", {
|
|
12026
|
+
id: event.id,
|
|
12027
|
+
content: event.delta,
|
|
12028
|
+
index: chunkIndex
|
|
12029
|
+
});
|
|
12030
|
+
chunkIndex += 1;
|
|
11784
12031
|
}
|
|
11785
|
-
|
|
12032
|
+
yield event;
|
|
12033
|
+
}
|
|
12034
|
+
completion = completionFromStreamEvents(streamEvents);
|
|
12035
|
+
if (completion.finishReason === "error" || completion.finishReason === "cancelled") {
|
|
12036
|
+
const terminalReason = completion.finishReason;
|
|
12037
|
+
completion = void 0;
|
|
12038
|
+
throw new AgentError(`LLM stream finished with ${terminalReason}`);
|
|
11786
12039
|
}
|
|
11787
12040
|
break;
|
|
11788
12041
|
} catch (error2) {
|
|
11789
|
-
|
|
11790
|
-
if (content) {
|
|
11791
|
-
await session2.append("assistant/message", {
|
|
11792
|
-
content,
|
|
11793
|
-
interrupted: true
|
|
11794
|
-
});
|
|
11795
|
-
llmMessages = await session2.deriveMessages();
|
|
11796
|
-
}
|
|
12042
|
+
yield activeAttempt.push({ type: "stream_error", error: toToolError2(error2) });
|
|
11797
12043
|
if (options.signal?.aborted) {
|
|
12044
|
+
const content = partialStreamContent(streamEvents);
|
|
12045
|
+
yield* this.settleAttempt(activeAttempt, content ? { content, interrupted: true } : void 0);
|
|
11798
12046
|
finishReason = "cancelled";
|
|
11799
12047
|
break;
|
|
11800
12048
|
}
|
|
12049
|
+
yield* this.settleAttempt(activeAttempt);
|
|
11801
12050
|
attempt += 1;
|
|
11802
12051
|
const failure = toToolError2(error2);
|
|
11803
12052
|
const decision = await this.ctx.waterfallAsync(
|
|
@@ -11806,14 +12055,14 @@ var AgentService = class {
|
|
|
11806
12055
|
index,
|
|
11807
12056
|
turn,
|
|
11808
12057
|
step: index,
|
|
11809
|
-
messages: copyMessages(
|
|
11810
|
-
tools:
|
|
11811
|
-
options:
|
|
12058
|
+
messages: copyMessages(streamRequest.messages),
|
|
12059
|
+
tools: [...streamRequest.tools],
|
|
12060
|
+
options: { ...streamRequest.options },
|
|
11812
12061
|
attempt,
|
|
11813
12062
|
error: error2,
|
|
11814
12063
|
failure,
|
|
11815
|
-
...
|
|
11816
|
-
...
|
|
12064
|
+
...streamRequest.options.provider ? { provider: streamRequest.options.provider } : {},
|
|
12065
|
+
...streamRequest.options.model ? { model: streamRequest.options.model } : {},
|
|
11817
12066
|
...options.signal ? { signal: options.signal } : {}
|
|
11818
12067
|
},
|
|
11819
12068
|
() => void 0
|
|
@@ -11838,16 +12087,30 @@ var AgentService = class {
|
|
|
11838
12087
|
await session2.append("llm/retry-started", { retryId, retry: attempt });
|
|
11839
12088
|
}
|
|
11840
12089
|
}
|
|
11841
|
-
if (
|
|
11842
|
-
|
|
12090
|
+
if (!completion || !activeAttempt) {
|
|
12091
|
+
if (options.signal?.aborted) {
|
|
12092
|
+
finishReason = "cancelled";
|
|
12093
|
+
break;
|
|
12094
|
+
}
|
|
12095
|
+
throw new AgentError("LLM adapter did not produce a completion");
|
|
12096
|
+
}
|
|
11843
12097
|
const toolCalls = completion.toolCalls ?? [];
|
|
11844
|
-
if (
|
|
12098
|
+
if (completion.finishReason === "length") lengthReached = true;
|
|
12099
|
+
if (options.signal?.aborted && toolCalls.length === 0) {
|
|
12100
|
+
yield activeAttempt.push({ type: "stream_error", error: { name: "AbortError", message: "stream aborted" } });
|
|
12101
|
+
yield* this.settleAttempt(activeAttempt);
|
|
12102
|
+
finishReason = "cancelled";
|
|
12103
|
+
break;
|
|
12104
|
+
}
|
|
12105
|
+
if (finalTurnGranted && toolCalls.length && !options.signal?.aborted) {
|
|
12106
|
+
yield activeAttempt.push({ type: "stream_error", error: { name: "AgentError", message: "maximum turns reached" } });
|
|
12107
|
+
yield* this.settleAttempt(activeAttempt);
|
|
11845
12108
|
finishReason = "max_turns";
|
|
11846
12109
|
break;
|
|
11847
12110
|
}
|
|
11848
12111
|
const toolResults = [];
|
|
11849
12112
|
if (toolCalls.length) {
|
|
11850
|
-
|
|
12113
|
+
yield* this.settleAttempt(activeAttempt, {
|
|
11851
12114
|
content: completion.content ?? "",
|
|
11852
12115
|
toolCalls: toolCalls.map((call) => ({
|
|
11853
12116
|
id: call.id,
|
|
@@ -11868,18 +12131,30 @@ var AgentService = class {
|
|
|
11868
12131
|
if (options.signal) toolOptions.signal = options.signal;
|
|
11869
12132
|
const startedAt = Date.now();
|
|
11870
12133
|
let result;
|
|
11871
|
-
|
|
11872
|
-
result = await tools2.execute(call.name, call.arguments, toolOptions);
|
|
11873
|
-
} catch (error2) {
|
|
12134
|
+
if (options.signal?.aborted) {
|
|
11874
12135
|
result = {
|
|
11875
12136
|
ok: false,
|
|
11876
12137
|
name: call.name,
|
|
11877
12138
|
callId: call.id,
|
|
11878
12139
|
input: call.arguments,
|
|
11879
|
-
error:
|
|
12140
|
+
error: abortedToolError(options.signal),
|
|
11880
12141
|
startedAt,
|
|
11881
12142
|
durationMs: Date.now() - startedAt
|
|
11882
12143
|
};
|
|
12144
|
+
} else {
|
|
12145
|
+
try {
|
|
12146
|
+
result = await tools2.execute(call.name, call.arguments, toolOptions);
|
|
12147
|
+
} catch (error2) {
|
|
12148
|
+
result = {
|
|
12149
|
+
ok: false,
|
|
12150
|
+
name: call.name,
|
|
12151
|
+
callId: call.id,
|
|
12152
|
+
input: call.arguments,
|
|
12153
|
+
error: toToolError2(error2),
|
|
12154
|
+
startedAt,
|
|
12155
|
+
durationMs: Date.now() - startedAt
|
|
12156
|
+
};
|
|
12157
|
+
}
|
|
11883
12158
|
}
|
|
11884
12159
|
toolResults.push(result);
|
|
11885
12160
|
const toolResultPayload = {
|
|
@@ -11921,7 +12196,7 @@ var AgentService = class {
|
|
|
11921
12196
|
output = completion.content;
|
|
11922
12197
|
}
|
|
11923
12198
|
if (!toolCalls.length) {
|
|
11924
|
-
|
|
12199
|
+
yield* this.settleAttempt(activeAttempt, { content: completion.content ?? "" });
|
|
11925
12200
|
}
|
|
11926
12201
|
await session2.append("step/end", {
|
|
11927
12202
|
turn,
|
|
@@ -11932,19 +12207,19 @@ var AgentService = class {
|
|
|
11932
12207
|
currentStepIndex = void 0;
|
|
11933
12208
|
const nextMessages = this._extendMessages(llmMessages, completion, toolResults);
|
|
11934
12209
|
const concludesTurn = toolResults.some((result) => result.concludesTurn === true);
|
|
11935
|
-
|
|
11936
|
-
|
|
11937
|
-
|
|
11938
|
-
}
|
|
11939
|
-
if (toolCalls.length === 0) {
|
|
11940
|
-
finishReason = completion.finishReason === "length" ? "length" : completion.finishReason === "error" ? "error" : "stop";
|
|
12210
|
+
let nextStepMessages = await this._claimNextStepMessages();
|
|
12211
|
+
if ((toolCalls.length === 0 || concludesTurn) && nextStepMessages.length === 0) {
|
|
12212
|
+
finishReason = lengthReached ? "length" : completion.finishReason === "error" ? "error" : "stop";
|
|
11941
12213
|
const keepGoing = await this.ctx.serial("agent/turn-stopping", {
|
|
11942
12214
|
index,
|
|
11943
12215
|
turn,
|
|
11944
12216
|
steps: copySteps(steps),
|
|
11945
12217
|
finishReason
|
|
11946
12218
|
});
|
|
11947
|
-
if (!keepGoing)
|
|
12219
|
+
if (!keepGoing) {
|
|
12220
|
+
nextStepMessages = await this._claimNextStepMessages();
|
|
12221
|
+
if (nextStepMessages.length === 0) break;
|
|
12222
|
+
}
|
|
11948
12223
|
}
|
|
11949
12224
|
if (index + 1 >= maxTurns && !finalTurnGranted) {
|
|
11950
12225
|
finalTurnGranted = true;
|
|
@@ -11954,7 +12229,8 @@ var AgentService = class {
|
|
|
11954
12229
|
}
|
|
11955
12230
|
if (toolCalls.length) finishReason = "tool_calls";
|
|
11956
12231
|
index += 1;
|
|
11957
|
-
messages = nextMessages;
|
|
12232
|
+
messages = [...nextMessages, ...nextStepMessages];
|
|
12233
|
+
claimedMessages = nextStepMessages.filter((message3) => message3.role === "user");
|
|
11958
12234
|
}
|
|
11959
12235
|
} catch (error2) {
|
|
11960
12236
|
turnError = error2;
|
|
@@ -12040,23 +12316,22 @@ var AgentService = class {
|
|
|
12040
12316
|
});
|
|
12041
12317
|
return compactMessages.map((message3) => copyMessages([message3])[0]);
|
|
12042
12318
|
}
|
|
12043
|
-
async _persistStepInput(session2, request, input) {
|
|
12044
|
-
const
|
|
12045
|
-
const
|
|
12046
|
-
|
|
12047
|
-
|
|
12048
|
-
|
|
12049
|
-
|
|
12050
|
-
|
|
12051
|
-
|
|
12052
|
-
|
|
12053
|
-
|
|
12054
|
-
|
|
12055
|
-
|
|
12056
|
-
|
|
12057
|
-
|
|
12058
|
-
|
|
12059
|
-
};
|
|
12319
|
+
async _persistStepInput(session2, request, input, admittedHistory) {
|
|
12320
|
+
const surface = await session2.deriveMessages();
|
|
12321
|
+
const owned = admittedHistory.filter((message3) => !isUserOrSystemMessage(message3));
|
|
12322
|
+
let ownerIndex = 0;
|
|
12323
|
+
for (const message3 of input) {
|
|
12324
|
+
if (isUserOrSystemMessage(message3)) continue;
|
|
12325
|
+
const actual = canonicalMessages([message3]);
|
|
12326
|
+
while (ownerIndex < owned.length && canonicalMessages([owned[ownerIndex]]) !== actual) {
|
|
12327
|
+
ownerIndex += 1;
|
|
12328
|
+
}
|
|
12329
|
+
if (ownerIndex === owned.length) {
|
|
12330
|
+
throw new AgentError("request is not reconstructable from session log: unowned or reordered assistant/tool message");
|
|
12331
|
+
}
|
|
12332
|
+
ownerIndex += 1;
|
|
12333
|
+
}
|
|
12334
|
+
const nextHeader = requestHeaderFor(request, input);
|
|
12060
12335
|
const previousHeader = session2.requestHeader();
|
|
12061
12336
|
const isFirstRequest = !this._persistedRequest;
|
|
12062
12337
|
const isResume = isFirstRequest && previousHeader !== void 0;
|
|
@@ -12086,19 +12361,23 @@ var AgentService = class {
|
|
|
12086
12361
|
...request.options.provider ? { provider: request.options.provider } : {},
|
|
12087
12362
|
...request.options.model ? { model: request.options.model } : {}
|
|
12088
12363
|
};
|
|
12364
|
+
if (request.options.contextWindow !== void 0) {
|
|
12365
|
+
nextContext.contextWindow = request.options.contextWindow;
|
|
12366
|
+
}
|
|
12089
12367
|
const llmService2 = this.ctx.reflect.get("llm", false);
|
|
12090
12368
|
const routeCapacity = llmService2?.routeCapacity?.();
|
|
12091
|
-
if (routeCapacity?.contextWindow !== void 0) {
|
|
12369
|
+
if (nextContext.contextWindow === void 0 && routeCapacity?.contextWindow !== void 0) {
|
|
12092
12370
|
nextContext.contextWindow = routeCapacity.contextWindow;
|
|
12093
12371
|
}
|
|
12094
12372
|
const previousContext = session2.requestContext();
|
|
12095
12373
|
if (previousContext?.provider !== nextContext.provider || previousContext?.model !== nextContext.model || previousContext?.contextWindow !== nextContext.contextWindow || previousContext === void 0) {
|
|
12096
12374
|
await session2.append("request/context", nextContext);
|
|
12097
12375
|
}
|
|
12098
|
-
const
|
|
12099
|
-
const
|
|
12100
|
-
const
|
|
12101
|
-
|
|
12376
|
+
const isSurfacePrefix = (messages) => canonicalMessages(messages.slice(0, surface.length)) === canonicalMessages(surface);
|
|
12377
|
+
const requested = surface.length > 0 && input[0]?.role === "system" && input[0].content === nextHeader.system && isSurfacePrefix(input.slice(1)) ? input.slice(1) : input;
|
|
12378
|
+
const tail = requested.slice(surface.length);
|
|
12379
|
+
if (isSurfacePrefix(requested) && tail.every(isUserOrSystemMessage)) {
|
|
12380
|
+
for (const message3 of tail) {
|
|
12102
12381
|
if (message3.role === "user") {
|
|
12103
12382
|
await session2.append("user/message", {
|
|
12104
12383
|
content: message3.content,
|
|
@@ -12111,45 +12390,37 @@ var AgentService = class {
|
|
|
12111
12390
|
});
|
|
12112
12391
|
}
|
|
12113
12392
|
}
|
|
12114
|
-
};
|
|
12115
|
-
if (surface.length === 0) {
|
|
12116
|
-
await appendDurable(requested);
|
|
12117
12393
|
return;
|
|
12118
12394
|
}
|
|
12119
|
-
const
|
|
12120
|
-
|
|
12121
|
-
|
|
12122
|
-
|
|
12123
|
-
|
|
12124
|
-
if (seenUsers <= durableUsers) continue;
|
|
12125
|
-
newTail.push(message3);
|
|
12126
|
-
}
|
|
12127
|
-
await appendDurable(newTail);
|
|
12395
|
+
const nodes = await session2.surfaceEvents();
|
|
12396
|
+
await session2.append("checkpoint", {
|
|
12397
|
+
messages: copyMessages(requested),
|
|
12398
|
+
surfaceOp: { op: "replace", start: nodes[0].seq, end: nodes.at(-1).seq }
|
|
12399
|
+
});
|
|
12128
12400
|
}
|
|
12129
|
-
async _assertReplayable(session2, input) {
|
|
12401
|
+
async _assertReplayable(session2, request, input) {
|
|
12130
12402
|
const reconstructed = await session2.deriveMessages();
|
|
12131
|
-
const
|
|
12132
|
-
|
|
12133
|
-
|
|
12134
|
-
|
|
12135
|
-
|
|
12136
|
-
...message3.tool_calls?.length ? { tool_calls: message3.tool_calls.map((call) => ({
|
|
12137
|
-
id: call.id,
|
|
12138
|
-
name: call.name,
|
|
12139
|
-
args: JSON.stringify(call.arguments ?? {})
|
|
12140
|
-
})) } : {}
|
|
12141
|
-
}));
|
|
12142
|
-
const actual = canonical(input);
|
|
12143
|
-
const replay = canonical(reconstructed);
|
|
12144
|
-
if (JSON.stringify(actual) !== JSON.stringify(replay)) {
|
|
12403
|
+
const actual = canonicalMessages(input);
|
|
12404
|
+
const replay = canonicalMessages(reconstructed);
|
|
12405
|
+
const header = session2.requestHeader();
|
|
12406
|
+
const headerOwnsPrefix = input[0]?.role === "system" && input[0].content === header?.system && canonicalMessages(input.slice(1)) === replay;
|
|
12407
|
+
if (actual !== replay && !headerOwnsPrefix) {
|
|
12145
12408
|
throw new AgentError(
|
|
12146
|
-
`request is not reconstructable from session log: actual=${
|
|
12409
|
+
`request is not reconstructable from session log: actual=${actual} replay=${replay}`
|
|
12147
12410
|
);
|
|
12148
12411
|
}
|
|
12412
|
+
const expected = requestHeaderFor(request, input);
|
|
12413
|
+
if (header?.system !== expected.system || JSON.stringify(header?.tools ?? []) !== JSON.stringify(expected.tools ?? []) || JSON.stringify(header?.config ?? {}) !== JSON.stringify(expected.config ?? {})) {
|
|
12414
|
+
throw new AgentError("request envelope is not reconstructable from session log");
|
|
12415
|
+
}
|
|
12416
|
+
}
|
|
12417
|
+
async _claimNextStepMessages() {
|
|
12418
|
+
const inputs = await this.config.claimNextStep?.() ?? [];
|
|
12419
|
+
return inputs.flatMap((input) => input.messages?.length ? copyMessages(input.messages) : input.text ? [{ role: "user", content: input.text }] : input.context !== void 0 ? [{ role: "user", content: stringify2(input.context) }] : []);
|
|
12149
12420
|
}
|
|
12150
12421
|
async _initialMessages(input) {
|
|
12151
12422
|
const promptService = this.ctx.reflect.get("systemPrompt", false);
|
|
12152
|
-
const assembled = promptService ? (await promptService.assemble()).text.trim() : void 0;
|
|
12423
|
+
const assembled = promptService ? (await promptService.assemble({}, this.ctx)).text.trim() : void 0;
|
|
12153
12424
|
const systemPrompt3 = assembled || this.inbox.injected().get("agentSystem");
|
|
12154
12425
|
const systemMessage = typeof systemPrompt3 === "string" && systemPrompt3 ? [{ role: "system", content: systemPrompt3 }] : [];
|
|
12155
12426
|
if (input.messages?.length) {
|
|
@@ -12174,7 +12445,7 @@ var AgentService = class {
|
|
|
12174
12445
|
arguments: call.arguments
|
|
12175
12446
|
}));
|
|
12176
12447
|
}
|
|
12177
|
-
next.push(assistant);
|
|
12448
|
+
if (assistant.content || toolCalls.length) next.push(assistant);
|
|
12178
12449
|
for (const call of toolCalls) {
|
|
12179
12450
|
const result = toolResults.find((candidate) => candidate.callId === call.id);
|
|
12180
12451
|
const content = result ? result.ok ? stringify2(result.output) : `error: ${result.error?.message ?? "unknown"}` : "error: missing tool result";
|
|
@@ -12204,7 +12475,8 @@ var AgentService = class {
|
|
|
12204
12475
|
return session2;
|
|
12205
12476
|
}
|
|
12206
12477
|
_tools() {
|
|
12207
|
-
const
|
|
12478
|
+
const scoped = this.ctx.reflect.get("tools", false);
|
|
12479
|
+
const tools2 = scoped ?? this.ctx.tools;
|
|
12208
12480
|
if (!tools2) throw new AgentError("tools service is required");
|
|
12209
12481
|
return tools2;
|
|
12210
12482
|
}
|
|
@@ -12388,67 +12660,77 @@ var DurableInbox = class _DurableInbox {
|
|
|
12388
12660
|
_session;
|
|
12389
12661
|
_nextTurn = [];
|
|
12390
12662
|
_nextStep = [];
|
|
12663
|
+
_operationTail = Promise.resolve();
|
|
12391
12664
|
get size() {
|
|
12392
12665
|
return this._nextTurn.length + this._nextStep.length;
|
|
12393
12666
|
}
|
|
12394
12667
|
async insert(input, target = "next-turn") {
|
|
12395
|
-
|
|
12396
|
-
|
|
12397
|
-
|
|
12398
|
-
|
|
12399
|
-
|
|
12400
|
-
|
|
12401
|
-
|
|
12402
|
-
|
|
12403
|
-
|
|
12404
|
-
|
|
12405
|
-
|
|
12406
|
-
|
|
12407
|
-
|
|
12408
|
-
|
|
12409
|
-
|
|
12668
|
+
return this._run(async () => {
|
|
12669
|
+
const message3 = {
|
|
12670
|
+
id: randomUUID3(),
|
|
12671
|
+
...input.text !== void 0 ? { text: input.text } : {},
|
|
12672
|
+
...input.content !== void 0 ? { content: input.content } : {}
|
|
12673
|
+
};
|
|
12674
|
+
const list = target === "next-step" ? this._nextStep : this._nextTurn;
|
|
12675
|
+
const index = list.length;
|
|
12676
|
+
await this._session.append("agent/inbox/spliced", {
|
|
12677
|
+
target,
|
|
12678
|
+
index,
|
|
12679
|
+
inserted: [{
|
|
12680
|
+
id: message3.id,
|
|
12681
|
+
content: contentOf(message3),
|
|
12682
|
+
...payloadOf(message3) !== void 0 ? { payload: payloadOf(message3) } : {}
|
|
12683
|
+
}]
|
|
12684
|
+
});
|
|
12685
|
+
list.push(message3);
|
|
12686
|
+
return message3;
|
|
12410
12687
|
});
|
|
12411
|
-
return message3;
|
|
12412
12688
|
}
|
|
12413
12689
|
async steer(input) {
|
|
12414
|
-
|
|
12415
|
-
|
|
12416
|
-
|
|
12417
|
-
|
|
12418
|
-
|
|
12419
|
-
|
|
12420
|
-
await this._session.append("agent/inbox/spliced", {
|
|
12421
|
-
target: "next-step",
|
|
12422
|
-
index: 0,
|
|
12423
|
-
inserted: [{
|
|
12424
|
-
id: message3.id,
|
|
12425
|
-
content: contentOf(message3),
|
|
12426
|
-
...payloadOf(message3) !== void 0 ? { payload: payloadOf(message3) } : {},
|
|
12427
|
-
mode: "steer"
|
|
12428
|
-
}]
|
|
12429
|
-
});
|
|
12430
|
-
return message3;
|
|
12431
|
-
}
|
|
12432
|
-
async claim() {
|
|
12433
|
-
const steered = this._nextStep.shift();
|
|
12434
|
-
if (steered) {
|
|
12690
|
+
return this._run(async () => {
|
|
12691
|
+
const message3 = {
|
|
12692
|
+
id: randomUUID3(),
|
|
12693
|
+
...input.text !== void 0 ? { text: input.text } : {},
|
|
12694
|
+
...input.content !== void 0 ? { content: input.content } : {}
|
|
12695
|
+
};
|
|
12435
12696
|
await this._session.append("agent/inbox/spliced", {
|
|
12436
12697
|
target: "next-step",
|
|
12437
|
-
index:
|
|
12438
|
-
|
|
12698
|
+
index: this._nextStep.length,
|
|
12699
|
+
inserted: [{
|
|
12700
|
+
id: message3.id,
|
|
12701
|
+
content: contentOf(message3),
|
|
12702
|
+
...payloadOf(message3) !== void 0 ? { payload: payloadOf(message3) } : {},
|
|
12703
|
+
mode: "steer"
|
|
12704
|
+
}]
|
|
12439
12705
|
});
|
|
12440
|
-
|
|
12441
|
-
|
|
12442
|
-
|
|
12443
|
-
|
|
12444
|
-
|
|
12445
|
-
|
|
12446
|
-
|
|
12447
|
-
|
|
12448
|
-
|
|
12449
|
-
|
|
12450
|
-
|
|
12451
|
-
|
|
12706
|
+
this._nextStep.push(message3);
|
|
12707
|
+
return message3;
|
|
12708
|
+
});
|
|
12709
|
+
}
|
|
12710
|
+
async claim() {
|
|
12711
|
+
return this._run(async () => {
|
|
12712
|
+
const steered = this._nextStep[0];
|
|
12713
|
+
if (steered) {
|
|
12714
|
+
await this._session.append("agent/inbox/spliced", {
|
|
12715
|
+
target: "next-step",
|
|
12716
|
+
index: 0,
|
|
12717
|
+
deleteCount: 1
|
|
12718
|
+
});
|
|
12719
|
+
this._nextStep.shift();
|
|
12720
|
+
return steered;
|
|
12721
|
+
}
|
|
12722
|
+
const next = this._nextTurn[0];
|
|
12723
|
+
if (next) {
|
|
12724
|
+
await this._session.append("agent/inbox/spliced", {
|
|
12725
|
+
target: "next-turn",
|
|
12726
|
+
index: 0,
|
|
12727
|
+
deleteCount: 1
|
|
12728
|
+
});
|
|
12729
|
+
this._nextTurn.shift();
|
|
12730
|
+
return next;
|
|
12731
|
+
}
|
|
12732
|
+
return void 0;
|
|
12733
|
+
});
|
|
12452
12734
|
}
|
|
12453
12735
|
/**
|
|
12454
12736
|
* Claim the complete proposed step batch: every pending next-step input plus
|
|
@@ -12456,105 +12738,108 @@ var DurableInbox = class _DurableInbox {
|
|
|
12456
12738
|
* nothing is pending.
|
|
12457
12739
|
*/
|
|
12458
12740
|
async claimBatch() {
|
|
12459
|
-
|
|
12460
|
-
|
|
12461
|
-
const
|
|
12462
|
-
claimed.push(
|
|
12741
|
+
return this._run(async () => {
|
|
12742
|
+
const claimed = [...this._nextStep];
|
|
12743
|
+
const nextTurn = this._nextTurn[0];
|
|
12744
|
+
if (nextTurn) claimed.push(nextTurn);
|
|
12745
|
+
if (!claimed.length) return [];
|
|
12746
|
+
const deleteCounts = { nextStep: this._nextStep.length, nextTurn: nextTurn ? 1 : 0 };
|
|
12747
|
+
await this._session.append("agent/inbox/spliced", { target: "all", deleteCounts });
|
|
12748
|
+
this._nextStep.splice(0, deleteCounts.nextStep);
|
|
12749
|
+
this._nextTurn.splice(0, deleteCounts.nextTurn);
|
|
12750
|
+
return claimed;
|
|
12751
|
+
});
|
|
12752
|
+
}
|
|
12753
|
+
/** Claim every input waiting for the next step, without consuming a turn. */
|
|
12754
|
+
async claimNextStep() {
|
|
12755
|
+
return this._run(async () => {
|
|
12756
|
+
if (!this._nextStep.length) return [];
|
|
12757
|
+
const claimed = [...this._nextStep];
|
|
12463
12758
|
await this._session.append("agent/inbox/spliced", {
|
|
12464
12759
|
target: "next-step",
|
|
12465
12760
|
index: 0,
|
|
12466
|
-
deleteCount:
|
|
12761
|
+
deleteCount: claimed.length
|
|
12467
12762
|
});
|
|
12468
|
-
|
|
12469
|
-
|
|
12470
|
-
|
|
12471
|
-
claimed.push(nextTurn);
|
|
12472
|
-
await this._session.append("agent/inbox/spliced", {
|
|
12473
|
-
target: "next-turn",
|
|
12474
|
-
index: 0,
|
|
12475
|
-
deleteCount: 1
|
|
12476
|
-
});
|
|
12477
|
-
}
|
|
12478
|
-
return claimed;
|
|
12763
|
+
this._nextStep.splice(0, claimed.length);
|
|
12764
|
+
return claimed;
|
|
12765
|
+
});
|
|
12479
12766
|
}
|
|
12480
12767
|
async clear() {
|
|
12481
|
-
|
|
12482
|
-
this._nextTurn
|
|
12768
|
+
return this._run(async () => {
|
|
12769
|
+
if (!this._nextTurn.length && !this._nextStep.length) return;
|
|
12483
12770
|
await this._session.append("agent/inbox/spliced", {
|
|
12484
|
-
target: "
|
|
12485
|
-
index: 0,
|
|
12486
|
-
deleteCount: Number.POSITIVE_INFINITY
|
|
12771
|
+
target: "all"
|
|
12487
12772
|
});
|
|
12488
|
-
|
|
12489
|
-
if (this._nextStep.length) {
|
|
12773
|
+
this._nextTurn = [];
|
|
12490
12774
|
this._nextStep = [];
|
|
12491
|
-
|
|
12492
|
-
target: "next-step",
|
|
12493
|
-
index: 0,
|
|
12494
|
-
deleteCount: Number.POSITIVE_INFINITY
|
|
12495
|
-
});
|
|
12496
|
-
}
|
|
12775
|
+
});
|
|
12497
12776
|
}
|
|
12498
12777
|
/** Insert a message at an explicit target/index boundary. */
|
|
12499
12778
|
async insertAt(input, target, index, mode = "followup") {
|
|
12500
|
-
|
|
12501
|
-
|
|
12502
|
-
|
|
12503
|
-
|
|
12504
|
-
|
|
12505
|
-
|
|
12506
|
-
|
|
12507
|
-
|
|
12508
|
-
|
|
12509
|
-
|
|
12510
|
-
|
|
12511
|
-
|
|
12512
|
-
|
|
12513
|
-
|
|
12514
|
-
|
|
12515
|
-
|
|
12516
|
-
|
|
12779
|
+
return this._run(async () => {
|
|
12780
|
+
const message3 = {
|
|
12781
|
+
id: randomUUID3(),
|
|
12782
|
+
...input.text !== void 0 ? { text: input.text } : {},
|
|
12783
|
+
...input.content !== void 0 ? { content: input.content } : {}
|
|
12784
|
+
};
|
|
12785
|
+
const list = target === "next-step" ? this._nextStep : this._nextTurn;
|
|
12786
|
+
const safeIndex = Math.max(0, Math.min(index, list.length));
|
|
12787
|
+
await this._session.append("agent/inbox/spliced", {
|
|
12788
|
+
target,
|
|
12789
|
+
index: safeIndex,
|
|
12790
|
+
inserted: [{
|
|
12791
|
+
id: message3.id,
|
|
12792
|
+
content: contentOf(message3),
|
|
12793
|
+
...payloadOf(message3) !== void 0 ? { payload: payloadOf(message3) } : {},
|
|
12794
|
+
mode
|
|
12795
|
+
}]
|
|
12796
|
+
});
|
|
12797
|
+
list.splice(safeIndex, 0, message3);
|
|
12798
|
+
return message3;
|
|
12517
12799
|
});
|
|
12518
|
-
return message3;
|
|
12519
12800
|
}
|
|
12520
12801
|
/**
|
|
12521
12802
|
* Replace one pending message by id. The old message is emitted as
|
|
12522
12803
|
* discarded and the new one as inserted, matching the DSH inbox contract.
|
|
12523
12804
|
*/
|
|
12524
12805
|
async replace(messageId, input) {
|
|
12525
|
-
|
|
12526
|
-
|
|
12527
|
-
|
|
12528
|
-
|
|
12529
|
-
|
|
12530
|
-
|
|
12531
|
-
|
|
12532
|
-
|
|
12533
|
-
|
|
12534
|
-
|
|
12535
|
-
|
|
12536
|
-
|
|
12537
|
-
|
|
12538
|
-
|
|
12539
|
-
|
|
12540
|
-
|
|
12541
|
-
|
|
12542
|
-
|
|
12543
|
-
|
|
12806
|
+
return this._run(async () => {
|
|
12807
|
+
const entry = this._find(messageId);
|
|
12808
|
+
if (!entry) return void 0;
|
|
12809
|
+
const replacement = {
|
|
12810
|
+
id: randomUUID3(),
|
|
12811
|
+
...input.text !== void 0 ? { text: input.text } : {},
|
|
12812
|
+
...input.content !== void 0 ? { content: input.content } : {}
|
|
12813
|
+
};
|
|
12814
|
+
const target = entry.target;
|
|
12815
|
+
const index = entry.index;
|
|
12816
|
+
await this._session.append("agent/inbox/spliced", {
|
|
12817
|
+
target,
|
|
12818
|
+
index,
|
|
12819
|
+
deleteCount: 1,
|
|
12820
|
+
inserted: [{
|
|
12821
|
+
id: replacement.id,
|
|
12822
|
+
content: contentOf(replacement),
|
|
12823
|
+
...payloadOf(replacement) !== void 0 ? { payload: payloadOf(replacement) } : {}
|
|
12824
|
+
}]
|
|
12825
|
+
});
|
|
12826
|
+
entry.list.splice(index, 1, replacement);
|
|
12827
|
+
return replacement;
|
|
12544
12828
|
});
|
|
12545
|
-
return replacement;
|
|
12546
12829
|
}
|
|
12547
12830
|
/** Remove one pending message by id. */
|
|
12548
12831
|
async remove(messageId) {
|
|
12549
|
-
|
|
12550
|
-
|
|
12551
|
-
|
|
12552
|
-
|
|
12553
|
-
|
|
12554
|
-
|
|
12555
|
-
|
|
12832
|
+
return this._run(async () => {
|
|
12833
|
+
const entry = this._find(messageId);
|
|
12834
|
+
if (!entry) return void 0;
|
|
12835
|
+
await this._session.append("agent/inbox/spliced", {
|
|
12836
|
+
target: entry.target,
|
|
12837
|
+
index: entry.index,
|
|
12838
|
+
deleteCount: 1
|
|
12839
|
+
});
|
|
12840
|
+
entry.list.splice(entry.index, 1);
|
|
12841
|
+
return entry.message;
|
|
12556
12842
|
});
|
|
12557
|
-
return entry.message;
|
|
12558
12843
|
}
|
|
12559
12844
|
/** Return the first pending message by id across both queues. */
|
|
12560
12845
|
get(messageId) {
|
|
@@ -12566,6 +12851,12 @@ var DurableInbox = class _DurableInbox {
|
|
|
12566
12851
|
nextStep: [...this._nextStep]
|
|
12567
12852
|
};
|
|
12568
12853
|
}
|
|
12854
|
+
/** Keep the entire read → append → apply transition ordered, including claims. */
|
|
12855
|
+
_run(operation) {
|
|
12856
|
+
const result = this._operationTail.then(operation);
|
|
12857
|
+
this._operationTail = result.then(() => void 0, () => void 0);
|
|
12858
|
+
return result;
|
|
12859
|
+
}
|
|
12569
12860
|
_find(messageId) {
|
|
12570
12861
|
for (const target of ["next-step", "next-turn"]) {
|
|
12571
12862
|
const list = target === "next-step" ? this._nextStep : this._nextTurn;
|
|
@@ -12583,6 +12874,11 @@ var DurableInbox = class _DurableInbox {
|
|
|
12583
12874
|
for (const event of events) {
|
|
12584
12875
|
if (event.type !== "agent/inbox/spliced") continue;
|
|
12585
12876
|
const payload = event.payload;
|
|
12877
|
+
if (payload.target === "all") {
|
|
12878
|
+
this._nextTurn.splice(0, payload.deleteCounts?.nextTurn ?? this._nextTurn.length);
|
|
12879
|
+
this._nextStep.splice(0, payload.deleteCounts?.nextStep ?? this._nextStep.length);
|
|
12880
|
+
continue;
|
|
12881
|
+
}
|
|
12586
12882
|
const list = payload.target === "next-step" ? this._nextStep : this._nextTurn;
|
|
12587
12883
|
const count = payload.deleteCount ?? 0;
|
|
12588
12884
|
if (count === Number.POSITIVE_INFINITY) {
|
|
@@ -12612,8 +12908,29 @@ var DurableInbox = class _DurableInbox {
|
|
|
12612
12908
|
};
|
|
12613
12909
|
|
|
12614
12910
|
// packages/agent/src/live.ts
|
|
12911
|
+
function createAgentRuntimeContext(agentCtx) {
|
|
12912
|
+
const runtimeCtx = agentCtx.extend();
|
|
12913
|
+
Object.defineProperty(runtimeCtx, Context.filter, {
|
|
12914
|
+
value: (target) => {
|
|
12915
|
+
const targetScope = target[symbols.isolate].agentScope;
|
|
12916
|
+
let ancestor = agentCtx;
|
|
12917
|
+
while (true) {
|
|
12918
|
+
if (targetScope === ancestor[symbols.isolate].agentScope) return true;
|
|
12919
|
+
if (ancestor.fiber.parent.fiber === ancestor.fiber) return false;
|
|
12920
|
+
ancestor = ancestor.fiber.parent;
|
|
12921
|
+
}
|
|
12922
|
+
}
|
|
12923
|
+
});
|
|
12924
|
+
const events = agentCtx.events;
|
|
12925
|
+
for (const method of ["emit", "parallel", "serial", "bail", "waterfall", "waterfallAsync"]) {
|
|
12926
|
+
Object.defineProperty(runtimeCtx, method, {
|
|
12927
|
+
value: (...args) => events[method](runtimeCtx, ...args)
|
|
12928
|
+
});
|
|
12929
|
+
}
|
|
12930
|
+
return runtimeCtx;
|
|
12931
|
+
}
|
|
12615
12932
|
var LiveAgentImpl = class {
|
|
12616
|
-
constructor(_ctx, _agentCtx, _service, id, inbox, session2, durable, meta2, manualStreaming = false) {
|
|
12933
|
+
constructor(_ctx, _agentCtx, _service, id, inbox, session2, durable, meta2, manualStreaming = false, wakeReserved = false) {
|
|
12617
12934
|
this._ctx = _ctx;
|
|
12618
12935
|
this._agentCtx = _agentCtx;
|
|
12619
12936
|
this._service = _service;
|
|
@@ -12623,6 +12940,7 @@ var LiveAgentImpl = class {
|
|
|
12623
12940
|
this.meta = meta2;
|
|
12624
12941
|
this._durable = durable;
|
|
12625
12942
|
this._manualStreaming = manualStreaming;
|
|
12943
|
+
this._wakeReserved = wakeReserved;
|
|
12626
12944
|
}
|
|
12627
12945
|
_ctx;
|
|
12628
12946
|
_agentCtx;
|
|
@@ -12644,8 +12962,9 @@ var LiveAgentImpl = class {
|
|
|
12644
12962
|
_setupDisposers = [];
|
|
12645
12963
|
_scopeClosed = false;
|
|
12646
12964
|
_durable;
|
|
12647
|
-
_agentSystem;
|
|
12648
12965
|
_manualStreaming = false;
|
|
12966
|
+
_wakeReserved = false;
|
|
12967
|
+
_loop;
|
|
12649
12968
|
get agentType() {
|
|
12650
12969
|
return this.meta.agentType;
|
|
12651
12970
|
}
|
|
@@ -12672,13 +12991,41 @@ var LiveAgentImpl = class {
|
|
|
12672
12991
|
return this._ctx;
|
|
12673
12992
|
}
|
|
12674
12993
|
followup(input) {
|
|
12675
|
-
this._send(input, "followup");
|
|
12994
|
+
return this._send(input, "followup");
|
|
12995
|
+
}
|
|
12996
|
+
setLoop(loop) {
|
|
12997
|
+
this._loop = loop;
|
|
12998
|
+
}
|
|
12999
|
+
async _closeCustomTurn(turn, run) {
|
|
13000
|
+
const events = await this.session.read();
|
|
13001
|
+
if (events.some((event) => event.type === "turn/end" && event.payload.turn === turn)) return;
|
|
13002
|
+
const reason = run.finishReason === "length" ? { kind: "max-tokens" } : run.finishReason === "max_steps" ? { kind: "max-steps" } : run.finishReason === "max_turns" ? { kind: "max-turns" } : run.finishReason === "cancelled" ? { kind: "interrupted" } : run.finishReason === "error" ? { kind: "interrupted" } : { kind: "completed" };
|
|
13003
|
+
await this.session.append("turn/end", {
|
|
13004
|
+
turn,
|
|
13005
|
+
finishReason: run.finishReason,
|
|
13006
|
+
reason,
|
|
13007
|
+
...run.output ? { output: run.output } : {},
|
|
13008
|
+
...run.steps.length ? { steps: run.steps.length } : {}
|
|
13009
|
+
});
|
|
13010
|
+
}
|
|
13011
|
+
async _closeFailedCustomTurn(turn, error2) {
|
|
13012
|
+
const events = await this.session.read();
|
|
13013
|
+
if (events.some((event) => event.type === "turn/end" && event.payload.turn === turn)) return;
|
|
13014
|
+
const failure = error2 instanceof Error ? { name: error2.name, message: error2.message, ...error2.stack ? { stack: error2.stack } : {} } : { name: "Error", message: String(error2) };
|
|
13015
|
+
await this.session.append("turn/end", {
|
|
13016
|
+
turn,
|
|
13017
|
+
finishReason: "error",
|
|
13018
|
+
reason: { kind: "error", error: failure },
|
|
13019
|
+
interrupted: true,
|
|
13020
|
+
error: failure
|
|
13021
|
+
});
|
|
12676
13022
|
}
|
|
12677
13023
|
/** Replace one pending inbox message by durable message id. */
|
|
12678
13024
|
replaceMessage(messageId, input) {
|
|
12679
|
-
this._mutatePending(async () => {
|
|
13025
|
+
return this._mutatePending(async () => {
|
|
12680
13026
|
const previous = this._durable.get(messageId);
|
|
12681
|
-
|
|
13027
|
+
const target = this._findTarget(messageId);
|
|
13028
|
+
if (!previous || !target) return;
|
|
12682
13029
|
const replacement = await this._durable.replace(messageId, {
|
|
12683
13030
|
text: input.text ?? "",
|
|
12684
13031
|
...input.messages !== void 0 || input.context !== void 0 ? { content: input.messages ?? input.context } : {}
|
|
@@ -12689,18 +13036,19 @@ var LiveAgentImpl = class {
|
|
|
12689
13036
|
agent: this,
|
|
12690
13037
|
message: previous
|
|
12691
13038
|
});
|
|
12692
|
-
|
|
13039
|
+
const event = {
|
|
12693
13040
|
id: this.id,
|
|
12694
13041
|
agent: this,
|
|
12695
|
-
target
|
|
13042
|
+
target,
|
|
12696
13043
|
input: replacement,
|
|
12697
13044
|
inboxSeq: this._durable.size
|
|
12698
|
-
}
|
|
13045
|
+
};
|
|
13046
|
+
this._ctx.emit("agent/inbox/inserted", event);
|
|
12699
13047
|
});
|
|
12700
13048
|
}
|
|
12701
13049
|
/** Remove one pending inbox message by durable message id. */
|
|
12702
13050
|
removeMessage(messageId) {
|
|
12703
|
-
this._mutatePending(async () => {
|
|
13051
|
+
return this._mutatePending(async () => {
|
|
12704
13052
|
const removed = await this._durable.remove(messageId);
|
|
12705
13053
|
if (!removed) return;
|
|
12706
13054
|
this._ctx.emit("agent/inbox/discarded", {
|
|
@@ -12711,48 +13059,54 @@ var LiveAgentImpl = class {
|
|
|
12711
13059
|
});
|
|
12712
13060
|
}
|
|
12713
13061
|
steer(input) {
|
|
12714
|
-
this._send(input, "steer");
|
|
13062
|
+
return this._send(input, "steer");
|
|
12715
13063
|
}
|
|
12716
|
-
inject(
|
|
12717
|
-
|
|
12718
|
-
this._agentSystem = value;
|
|
12719
|
-
}
|
|
13064
|
+
inject(input) {
|
|
13065
|
+
return this._send(input, "inject");
|
|
12720
13066
|
}
|
|
12721
13067
|
send(input, options = {}) {
|
|
12722
|
-
this._send(input, options.mode === "steer" ? "steer" : "followup");
|
|
13068
|
+
return this._send(input, options.mode === "steer" ? "steer" : "followup");
|
|
12723
13069
|
}
|
|
12724
13070
|
_send(input, target) {
|
|
12725
|
-
if (this._disposed) throw new Error(`agent disposed: ${this.id}`);
|
|
12726
13071
|
const text = input.text ?? "";
|
|
12727
13072
|
const content = input.messages ?? input.context;
|
|
12728
|
-
const
|
|
12729
|
-
|
|
12730
|
-
this.
|
|
13073
|
+
const steeredAfterAbort = target === "steer" && this._controller?.signal.aborted === true;
|
|
13074
|
+
return this._mutatePending(async () => {
|
|
13075
|
+
const message3 = target === "followup" ? await this._durable.insert({ text, ...content !== void 0 ? { content } : {} }) : target === "steer" ? steeredAfterAbort ? await this._durable.insert({ text, ...content !== void 0 ? { content } : {} }) : await this._durable.steer({ text, ...content !== void 0 ? { content } : {} }) : await this._durable.insert({ text, ...content !== void 0 ? { content } : {} }, "next-step");
|
|
13076
|
+
if (target !== "inject") this._wakeReserved = true;
|
|
13077
|
+
const event = {
|
|
12731
13078
|
id: this.id,
|
|
13079
|
+
agent: this,
|
|
12732
13080
|
target,
|
|
12733
13081
|
input: message3,
|
|
12734
13082
|
inboxSeq: this._durable.size
|
|
12735
|
-
}
|
|
12736
|
-
|
|
12737
|
-
|
|
12738
|
-
});
|
|
12739
|
-
this._writeTail = task;
|
|
12740
|
-
this._pendingWrite = task;
|
|
12741
|
-
task.finally(() => {
|
|
12742
|
-
if (this._pendingWrite === task) this._pendingWrite = void 0;
|
|
12743
|
-
queueMicrotask(() => this._wake());
|
|
12744
|
-
});
|
|
13083
|
+
};
|
|
13084
|
+
this._ctx.emit("agent/inbox/inserted", event);
|
|
13085
|
+
}, target !== "inject");
|
|
12745
13086
|
}
|
|
12746
|
-
_mutatePending(task) {
|
|
12747
|
-
if (this._disposed
|
|
12748
|
-
|
|
12749
|
-
|
|
12750
|
-
|
|
12751
|
-
|
|
12752
|
-
|
|
12753
|
-
|
|
12754
|
-
|
|
13087
|
+
_mutatePending(task, wakes = false, allowDisposed = false) {
|
|
13088
|
+
if (this._disposed && !allowDisposed) {
|
|
13089
|
+
return Promise.reject(new Error(`agent disposed: ${this.id}`));
|
|
13090
|
+
}
|
|
13091
|
+
const result = this._writeTail.then(task);
|
|
13092
|
+
const recovered = result.catch((error2) => {
|
|
13093
|
+
try {
|
|
13094
|
+
this._ctx.emit("agent/error", { id: this.id, error: error2 });
|
|
13095
|
+
} catch {
|
|
13096
|
+
}
|
|
12755
13097
|
});
|
|
13098
|
+
this._writeTail = recovered;
|
|
13099
|
+
this._pendingWrite = recovered;
|
|
13100
|
+
void result.then(
|
|
13101
|
+
() => {
|
|
13102
|
+
if (this._pendingWrite === recovered) this._pendingWrite = void 0;
|
|
13103
|
+
if (wakes) queueMicrotask(() => this._wake());
|
|
13104
|
+
},
|
|
13105
|
+
() => {
|
|
13106
|
+
if (this._pendingWrite === recovered) this._pendingWrite = void 0;
|
|
13107
|
+
}
|
|
13108
|
+
);
|
|
13109
|
+
return result;
|
|
12756
13110
|
}
|
|
12757
13111
|
_findTarget(messageId) {
|
|
12758
13112
|
const snapshot = this._durable.snapshot();
|
|
@@ -12762,27 +13116,21 @@ var LiveAgentImpl = class {
|
|
|
12762
13116
|
}
|
|
12763
13117
|
cancel(cause, options = {}) {
|
|
12764
13118
|
if (!options.keepInbox) {
|
|
12765
|
-
|
|
13119
|
+
void this._mutatePending(async () => {
|
|
12766
13120
|
const before = this._durable.snapshot();
|
|
13121
|
+
await this._durable.clear();
|
|
12767
13122
|
for (const message3 of [...before.nextStep, ...before.nextTurn]) {
|
|
12768
13123
|
this._ctx.emit("agent/inbox/discarded", { id: this.id, message: message3 });
|
|
12769
13124
|
}
|
|
12770
|
-
|
|
12771
|
-
}
|
|
12772
|
-
this._ctx.emit("agent/error", { id: this.id, error: error2 });
|
|
12773
|
-
});
|
|
12774
|
-
this._writeTail = task;
|
|
12775
|
-
this._pendingWrite = task;
|
|
12776
|
-
task.finally(() => {
|
|
12777
|
-
if (this._pendingWrite === task) this._pendingWrite = void 0;
|
|
12778
|
-
});
|
|
13125
|
+
this._wakeReserved = false;
|
|
13126
|
+
}, false, true);
|
|
12779
13127
|
}
|
|
12780
13128
|
this._controller?.abort(cause);
|
|
12781
13129
|
this._maintenance?.controller.abort(cause);
|
|
12782
13130
|
}
|
|
12783
13131
|
async whenIdle() {
|
|
12784
|
-
while (this._pendingWrite) await this._pendingWrite;
|
|
12785
13132
|
while (true) {
|
|
13133
|
+
while (this._pendingWrite) await this._pendingWrite;
|
|
12786
13134
|
const maintenance = this._maintenance;
|
|
12787
13135
|
if (maintenance) {
|
|
12788
13136
|
await maintenance.promise.catch(() => void 0);
|
|
@@ -12793,7 +13141,7 @@ var LiveAgentImpl = class {
|
|
|
12793
13141
|
await drain.catch(() => void 0);
|
|
12794
13142
|
continue;
|
|
12795
13143
|
}
|
|
12796
|
-
if (!this.
|
|
13144
|
+
if (!this._hasQueuedWork()) break;
|
|
12797
13145
|
await new Promise((resolve12) => setTimeout(resolve12, 0));
|
|
12798
13146
|
}
|
|
12799
13147
|
}
|
|
@@ -12835,6 +13183,7 @@ var LiveAgentImpl = class {
|
|
|
12835
13183
|
this._pendingWrite = void 0;
|
|
12836
13184
|
await writeTail.catch(() => void 0);
|
|
12837
13185
|
}
|
|
13186
|
+
await this.session.close();
|
|
12838
13187
|
this._setStatus("idle");
|
|
12839
13188
|
}
|
|
12840
13189
|
/** Publish the agent lifecycle session-start notification once. */
|
|
@@ -12864,13 +13213,23 @@ var LiveAgentImpl = class {
|
|
|
12864
13213
|
if (this._disposed || this._manualStreaming || this._drainPromise || this._busy || this._maintenanceBusy) return;
|
|
12865
13214
|
const task = this._drainAll();
|
|
12866
13215
|
this._drainPromise = task;
|
|
12867
|
-
task.
|
|
12868
|
-
|
|
12869
|
-
|
|
13216
|
+
void task.then(
|
|
13217
|
+
() => {
|
|
13218
|
+
if (this._drainPromise === task) this._drainPromise = void 0;
|
|
13219
|
+
if (this._hasQueuedWork()) queueMicrotask(() => this._wake());
|
|
13220
|
+
},
|
|
13221
|
+
(error2) => {
|
|
13222
|
+
if (this._drainPromise === task) this._drainPromise = void 0;
|
|
13223
|
+
try {
|
|
13224
|
+
this._ctx.emit("agent/error", { id: this.id, agent: this, error: error2 });
|
|
13225
|
+
} catch {
|
|
13226
|
+
}
|
|
13227
|
+
}
|
|
13228
|
+
);
|
|
12870
13229
|
}
|
|
12871
13230
|
async _drainAll() {
|
|
12872
13231
|
await this._writeTail.catch(() => void 0);
|
|
12873
|
-
if (this.
|
|
13232
|
+
if (this._hasQueuedWork()) {
|
|
12874
13233
|
for await (const _ of this._streamTurns()) void _;
|
|
12875
13234
|
}
|
|
12876
13235
|
}
|
|
@@ -12886,10 +13245,13 @@ var LiveAgentImpl = class {
|
|
|
12886
13245
|
this._setStatus("running");
|
|
12887
13246
|
try {
|
|
12888
13247
|
while (!this._disposed) {
|
|
12889
|
-
const
|
|
12890
|
-
if (!
|
|
12891
|
-
const input = await this._inputForBatch(batch);
|
|
13248
|
+
const snapshot = this._durable.snapshot();
|
|
13249
|
+
if (!snapshot.nextTurn.length && !this._wakeReserved) break;
|
|
12892
13250
|
const turn = await this._nextTurnNumber();
|
|
13251
|
+
await this.session.append("turn/start", { turn, reason: "user" });
|
|
13252
|
+
const batch = await this._durable.claimBatch();
|
|
13253
|
+
this._wakeReserved = false;
|
|
13254
|
+
const input = batch.length ? await this._inputForBatch(batch, true) : { text: "" };
|
|
12893
13255
|
for (const message3 of batch) {
|
|
12894
13256
|
this._ctx.emit("agent/inbox/claimed", {
|
|
12895
13257
|
id: this.id,
|
|
@@ -12906,11 +13268,21 @@ var LiveAgentImpl = class {
|
|
|
12906
13268
|
else signal?.addEventListener("abort", forward, { once: true });
|
|
12907
13269
|
try {
|
|
12908
13270
|
if (this._manualStreaming) {
|
|
12909
|
-
|
|
13271
|
+
if (this._loop) {
|
|
13272
|
+
const run = await this._loop(input, { signal: controller.signal, turn });
|
|
13273
|
+
await this._closeCustomTurn(turn, run);
|
|
13274
|
+
yield { type: "run/end", run };
|
|
13275
|
+
} else {
|
|
13276
|
+
yield* this._service.runStream(input, { signal: controller.signal, turn });
|
|
13277
|
+
}
|
|
12910
13278
|
} else {
|
|
12911
|
-
|
|
13279
|
+
if (this._loop) {
|
|
13280
|
+
const run = await this._loop(input, { signal: controller.signal, turn });
|
|
13281
|
+
await this._closeCustomTurn(turn, run);
|
|
13282
|
+
} else await this._service.run(input, { signal: controller.signal, turn });
|
|
12912
13283
|
}
|
|
12913
13284
|
} catch (error2) {
|
|
13285
|
+
if (this._loop) await this._closeFailedCustomTurn(turn, error2);
|
|
12914
13286
|
if (!controller.signal.aborted) {
|
|
12915
13287
|
const step = await this._failedStep();
|
|
12916
13288
|
this._ctx.emit("agent/error", {
|
|
@@ -12928,26 +13300,37 @@ var LiveAgentImpl = class {
|
|
|
12928
13300
|
}
|
|
12929
13301
|
} finally {
|
|
12930
13302
|
this._busy = false;
|
|
13303
|
+
if (!this._durable.size) this._wakeReserved = false;
|
|
12931
13304
|
this._setStatus("idle");
|
|
12932
13305
|
}
|
|
12933
13306
|
}
|
|
12934
|
-
|
|
12935
|
-
const
|
|
12936
|
-
|
|
12937
|
-
|
|
12938
|
-
|
|
12939
|
-
|
|
12940
|
-
|
|
12941
|
-
|
|
12942
|
-
|
|
12943
|
-
|
|
12944
|
-
|
|
12945
|
-
|
|
12946
|
-
|
|
12947
|
-
|
|
12948
|
-
|
|
13307
|
+
_hasQueuedWork() {
|
|
13308
|
+
const snapshot = this._durable.snapshot();
|
|
13309
|
+
return snapshot.nextTurn.length > 0 || this._wakeReserved && snapshot.nextStep.length > 0;
|
|
13310
|
+
}
|
|
13311
|
+
async _inputForBatch(batch, includeHistory) {
|
|
13312
|
+
const history = includeHistory ? await this.session.deriveMessages() : [];
|
|
13313
|
+
const messages = batch.flatMap((message3) => message3.content !== void 0 ? Array.isArray(message3.content) ? message3.content : [{ role: "user", content: String(message3.content ?? "") }] : message3.text !== void 0 ? [{ role: "user", content: message3.text }] : []);
|
|
13314
|
+
if (history.length || messages.length > 1) return { messages: [...history, ...messages] };
|
|
13315
|
+
return { text: messages[0]?.content ?? "" };
|
|
13316
|
+
}
|
|
13317
|
+
async claimNextStepInputs() {
|
|
13318
|
+
await this._writeTail;
|
|
13319
|
+
const batch = await this._durable.claimNextStep();
|
|
13320
|
+
this._wakeReserved = false;
|
|
13321
|
+
if (batch.length) {
|
|
13322
|
+
const turn = await this._nextTurnNumber() - 1;
|
|
13323
|
+
for (const message3 of batch) {
|
|
13324
|
+
this._ctx.emit("agent/inbox/claimed", {
|
|
13325
|
+
id: this.id,
|
|
13326
|
+
agent: this,
|
|
13327
|
+
message: message3,
|
|
13328
|
+
input: { text: message3.text ?? "" },
|
|
13329
|
+
turn
|
|
13330
|
+
});
|
|
13331
|
+
}
|
|
12949
13332
|
}
|
|
12950
|
-
return
|
|
13333
|
+
return batch.length ? [await this._inputForBatch(batch, false)] : [];
|
|
12951
13334
|
}
|
|
12952
13335
|
_setStatus(status) {
|
|
12953
13336
|
const previous = this._status;
|
|
@@ -13043,112 +13426,156 @@ async function buildHandle(ctx, options, resume = false) {
|
|
|
13043
13426
|
}
|
|
13044
13427
|
const agentId = fileMeta?.agentId ?? requestedId;
|
|
13045
13428
|
if (!agentId) throw new AgentError("agent requires a stable identity");
|
|
13046
|
-
|
|
13047
|
-
options.file,
|
|
13048
|
-
(type, payload) => {
|
|
13049
|
-
if (type === "event") ctx.emit("session/event", payload);
|
|
13050
|
-
else ctx.emit("session/flush", payload);
|
|
13051
|
-
}
|
|
13052
|
-
);
|
|
13053
|
-
await log.init();
|
|
13054
|
-
const fileEvents = await log.read();
|
|
13055
|
-
const durableMeta = readDurableAgentMeta(fileEvents);
|
|
13056
|
-
if (durableMeta) {
|
|
13057
|
-
if (durableMeta.agentId !== agentId) {
|
|
13058
|
-
throw new AgentError(
|
|
13059
|
-
`agent id mismatch: session belongs to ${durableMeta.agentId}, requested ${agentId}`
|
|
13060
|
-
);
|
|
13061
|
-
}
|
|
13062
|
-
if (options.agentType && durableMeta.agentType !== options.agentType) {
|
|
13063
|
-
throw new AgentError(
|
|
13064
|
-
`agent type mismatch: session is ${durableMeta.agentType ?? "untyped"}, requested ${options.agentType}`
|
|
13065
|
-
);
|
|
13066
|
-
}
|
|
13067
|
-
if (options.mode && durableMeta.mode !== options.mode) {
|
|
13068
|
-
throw new AgentError(
|
|
13069
|
-
`agent mode mismatch: session is ${durableMeta.mode ?? "unset"}, requested ${options.mode}`
|
|
13070
|
-
);
|
|
13071
|
-
}
|
|
13072
|
-
}
|
|
13073
|
-
const boundMeta = {
|
|
13074
|
-
...fileMeta,
|
|
13075
|
-
...durableMeta ?? {},
|
|
13076
|
-
...options.title ? { title: options.title } : {},
|
|
13077
|
-
...options.owner ? { owner: options.owner } : {},
|
|
13078
|
-
...options.parentSessionId ? { parentSessionId: options.parentSessionId } : {},
|
|
13079
|
-
...options.forkedAtMessageId ? { forkedAtMessageId: options.forkedAtMessageId } : {},
|
|
13080
|
-
agentId
|
|
13081
|
-
};
|
|
13082
|
-
const resolvedAgentType = options.agentType ?? durableMeta?.agentType;
|
|
13083
|
-
if (resolvedAgentType) boundMeta.agentType = resolvedAgentType;
|
|
13084
|
-
const resolvedMode = options.mode ?? durableMeta?.mode;
|
|
13085
|
-
if (resolvedMode) boundMeta.mode = resolvedMode;
|
|
13086
|
-
if (!durableMeta) {
|
|
13087
|
-
await log.append("meta", {
|
|
13088
|
-
kind: "agent",
|
|
13089
|
-
agentId,
|
|
13090
|
-
...boundMeta.agentType ? { agentType: boundMeta.agentType } : {},
|
|
13091
|
-
...boundMeta.mode ? { mode: boundMeta.mode } : {},
|
|
13092
|
-
...boundMeta.title ? { title: boundMeta.title } : {},
|
|
13093
|
-
...boundMeta.owner ? { owner: boundMeta.owner } : {},
|
|
13094
|
-
...boundMeta.parentSessionId ? { parentSessionId: boundMeta.parentSessionId } : {},
|
|
13095
|
-
...boundMeta.forkedAtMessageId ? { forkedAtMessageId: boundMeta.forkedAtMessageId } : {},
|
|
13096
|
-
...boundMeta.createdAt !== void 0 ? { createdAt: boundMeta.createdAt } : {}
|
|
13097
|
-
});
|
|
13098
|
-
}
|
|
13099
|
-
const durable = resume ? await DurableInbox.restore(log) : new DurableInbox(log);
|
|
13100
|
-
const injected = new AgentInbox();
|
|
13101
|
-
const inboxView = {
|
|
13102
|
-
get size() {
|
|
13103
|
-
return durable.size;
|
|
13104
|
-
},
|
|
13105
|
-
snapshot: () => durable.snapshot()
|
|
13106
|
-
};
|
|
13107
|
-
const service = new AgentService(ctx, {
|
|
13108
|
-
session: log,
|
|
13109
|
-
inbox: injected,
|
|
13110
|
-
...options.llm ? { llm: options.llm } : {},
|
|
13111
|
-
...options.maxTurns !== void 0 ? { maxTurns: options.maxTurns } : {},
|
|
13112
|
-
...options.maxSteps !== void 0 ? { maxSteps: options.maxSteps } : {},
|
|
13113
|
-
...options.contextBudget ? { contextBudget: options.contextBudget } : {},
|
|
13114
|
-
...options.hooks ? { hooks: options.hooks } : {}
|
|
13115
|
-
});
|
|
13116
|
-
if (options.system) injected.inject("agentSystem", options.system);
|
|
13429
|
+
let agentCtx;
|
|
13117
13430
|
const agentScope = await ctx.inject([], (scopeCtx) => {
|
|
13118
|
-
scopeCtx.isolate("agentScope").
|
|
13431
|
+
agentCtx = scopeCtx.isolate("agentScope").isolate("llm").isolate("tools").isolate("systemPrompt");
|
|
13432
|
+
agentCtx.provide("agentScope", agentCtx);
|
|
13119
13433
|
});
|
|
13120
13434
|
await agentScope;
|
|
13121
|
-
const
|
|
13122
|
-
const
|
|
13123
|
-
ctx,
|
|
13124
|
-
agentCtx,
|
|
13125
|
-
service,
|
|
13126
|
-
agentId,
|
|
13127
|
-
inboxView,
|
|
13128
|
-
log,
|
|
13129
|
-
durable,
|
|
13130
|
-
boundMeta,
|
|
13131
|
-
options.manualStreaming === true
|
|
13132
|
-
);
|
|
13133
|
-
agent2.trackSetupDispose(() => agentScope.dispose());
|
|
13134
|
-
if (options.system) agent2.inject("agentSystem", options.system);
|
|
13135
|
-
let setupResult;
|
|
13435
|
+
const runtimeCtx = createAgentRuntimeContext(agentCtx);
|
|
13436
|
+
const log = new SessionLog(options.file, void 0, runtimeCtx);
|
|
13136
13437
|
try {
|
|
13137
|
-
|
|
13138
|
-
|
|
13438
|
+
await log.init();
|
|
13439
|
+
const fileEvents = await log.read();
|
|
13440
|
+
const durableMeta = readDurableAgentMeta(fileEvents);
|
|
13441
|
+
if (durableMeta) {
|
|
13442
|
+
if (durableMeta.agentId !== agentId) {
|
|
13443
|
+
throw new AgentError(
|
|
13444
|
+
`agent id mismatch: session belongs to ${durableMeta.agentId}, requested ${agentId}`
|
|
13445
|
+
);
|
|
13446
|
+
}
|
|
13447
|
+
if (options.agentType && durableMeta.agentType !== options.agentType) {
|
|
13448
|
+
throw new AgentError(
|
|
13449
|
+
`agent type mismatch: session is ${durableMeta.agentType ?? "untyped"}, requested ${options.agentType}`
|
|
13450
|
+
);
|
|
13451
|
+
}
|
|
13452
|
+
if (options.mode && durableMeta.mode !== options.mode) {
|
|
13453
|
+
throw new AgentError(
|
|
13454
|
+
`agent mode mismatch: session is ${durableMeta.mode ?? "unset"}, requested ${options.mode}`
|
|
13455
|
+
);
|
|
13456
|
+
}
|
|
13457
|
+
}
|
|
13458
|
+
const boundMeta = {
|
|
13459
|
+
...fileMeta,
|
|
13460
|
+
...durableMeta ?? {},
|
|
13461
|
+
...options.title ? { title: options.title } : {},
|
|
13462
|
+
...options.owner ? { owner: options.owner } : {},
|
|
13463
|
+
...options.parentSessionId ? { parentSessionId: options.parentSessionId } : {},
|
|
13464
|
+
...options.forkedAtMessageId ? { forkedAtMessageId: options.forkedAtMessageId } : {},
|
|
13465
|
+
agentId
|
|
13466
|
+
};
|
|
13467
|
+
const resolvedAgentType = options.agentType ?? durableMeta?.agentType;
|
|
13468
|
+
if (resolvedAgentType) boundMeta.agentType = resolvedAgentType;
|
|
13469
|
+
const resolvedMode = options.mode ?? durableMeta?.mode;
|
|
13470
|
+
if (resolvedMode) boundMeta.mode = resolvedMode;
|
|
13471
|
+
if (!durableMeta) {
|
|
13472
|
+
await log.append("meta", {
|
|
13473
|
+
kind: "agent",
|
|
13474
|
+
agentId,
|
|
13475
|
+
...boundMeta.agentType ? { agentType: boundMeta.agentType } : {},
|
|
13476
|
+
...boundMeta.mode ? { mode: boundMeta.mode } : {},
|
|
13477
|
+
...boundMeta.title ? { title: boundMeta.title } : {},
|
|
13478
|
+
...boundMeta.owner ? { owner: boundMeta.owner } : {},
|
|
13479
|
+
...boundMeta.parentSessionId ? { parentSessionId: boundMeta.parentSessionId } : {},
|
|
13480
|
+
...boundMeta.forkedAtMessageId ? { forkedAtMessageId: boundMeta.forkedAtMessageId } : {},
|
|
13481
|
+
...boundMeta.createdAt !== void 0 ? { createdAt: boundMeta.createdAt } : {}
|
|
13482
|
+
});
|
|
13483
|
+
}
|
|
13484
|
+
const durable = resume ? await DurableInbox.restore(log) : new DurableInbox(log);
|
|
13485
|
+
const restoredWakeReservation = resume && hasRestoredWakeReservation(fileEvents);
|
|
13486
|
+
const injected = new AgentInbox();
|
|
13487
|
+
const inboxView = {
|
|
13488
|
+
get size() {
|
|
13489
|
+
return durable.size;
|
|
13490
|
+
},
|
|
13491
|
+
snapshot: () => durable.snapshot()
|
|
13492
|
+
};
|
|
13493
|
+
let claimNextStep = async () => [];
|
|
13494
|
+
const service = new AgentService(runtimeCtx, {
|
|
13495
|
+
session: log,
|
|
13496
|
+
inbox: injected,
|
|
13497
|
+
...options.llm ? { llm: options.llm } : {},
|
|
13498
|
+
...options.maxTurns !== void 0 ? { maxTurns: options.maxTurns } : {},
|
|
13499
|
+
...options.maxSteps !== void 0 ? { maxSteps: options.maxSteps } : {},
|
|
13500
|
+
...options.contextBudget ? { contextBudget: options.contextBudget } : {},
|
|
13501
|
+
...options.hooks ? { hooks: options.hooks } : {},
|
|
13502
|
+
claimNextStep: () => claimNextStep()
|
|
13503
|
+
});
|
|
13504
|
+
if (options.system) injected.inject("agentSystem", options.system);
|
|
13505
|
+
const agent2 = new LiveAgentImpl(
|
|
13506
|
+
runtimeCtx,
|
|
13507
|
+
agentCtx,
|
|
13508
|
+
service,
|
|
13509
|
+
agentId,
|
|
13510
|
+
inboxView,
|
|
13511
|
+
log,
|
|
13512
|
+
durable,
|
|
13513
|
+
boundMeta,
|
|
13514
|
+
options.manualStreaming === true,
|
|
13515
|
+
restoredWakeReservation
|
|
13516
|
+
);
|
|
13517
|
+
claimNextStep = () => agent2.claimNextStepInputs();
|
|
13518
|
+
agent2.trackSetupDispose(() => agentScope.dispose());
|
|
13519
|
+
let setupResult;
|
|
13520
|
+
try {
|
|
13521
|
+
setupResult = await options.setup?.(agentCtx);
|
|
13522
|
+
for (const name7 of ["llm", "systemPrompt"]) {
|
|
13523
|
+
if (agentCtx.reflect.get(name7, false) !== void 0) continue;
|
|
13524
|
+
const inherited = ctx.reflect.get(name7, false);
|
|
13525
|
+
if (inherited !== void 0) agentCtx.provide(name7, inherited);
|
|
13526
|
+
}
|
|
13527
|
+
const loop = agentCtx.reflect.get("agentLoop", false);
|
|
13528
|
+
agent2.setLoop(loop);
|
|
13529
|
+
setupResult?.commit();
|
|
13530
|
+
} catch (error2) {
|
|
13531
|
+
await agent2.dispose().catch(() => void 0);
|
|
13532
|
+
await log.close().catch(() => void 0);
|
|
13533
|
+
throw error2;
|
|
13534
|
+
}
|
|
13535
|
+
await agent2.publishSessionStart(resume ? "resume" : "startup");
|
|
13536
|
+
for (const input of options.initial ?? []) {
|
|
13537
|
+
if (!resume) await durable.insert({ text: input.text ?? "" });
|
|
13538
|
+
}
|
|
13539
|
+
if (resume && (durable.snapshot().nextTurn.length || restoredWakeReservation) && options.manualStreaming !== true) {
|
|
13540
|
+
setTimeout(() => agent2.wakeNow(), 0);
|
|
13541
|
+
}
|
|
13542
|
+
return { agent: agent2, dispose: () => agent2.dispose() };
|
|
13139
13543
|
} catch (error2) {
|
|
13140
|
-
await
|
|
13141
|
-
await log.close().catch(() => void 0);
|
|
13544
|
+
await Promise.resolve().then(() => agentScope.dispose()).catch(() => void 0);
|
|
13142
13545
|
throw error2;
|
|
13143
13546
|
}
|
|
13144
|
-
|
|
13145
|
-
|
|
13146
|
-
|
|
13147
|
-
|
|
13148
|
-
|
|
13149
|
-
|
|
13547
|
+
}
|
|
13548
|
+
function hasRestoredWakeReservation(events) {
|
|
13549
|
+
const nextTurn = [];
|
|
13550
|
+
const nextStep = [];
|
|
13551
|
+
for (const event of events) {
|
|
13552
|
+
if (event.type !== "agent/inbox/spliced") continue;
|
|
13553
|
+
const payload = event.payload;
|
|
13554
|
+
if (payload.target === "all") {
|
|
13555
|
+
nextTurn.splice(0, payload.deleteCounts?.nextTurn ?? nextTurn.length);
|
|
13556
|
+
nextStep.splice(0, payload.deleteCounts?.nextStep ?? nextStep.length);
|
|
13557
|
+
continue;
|
|
13558
|
+
}
|
|
13559
|
+
const list = payload.target === "next-step" ? nextStep : nextTurn;
|
|
13560
|
+
const count = payload.deleteCount ?? 0;
|
|
13561
|
+
if (count === Number.POSITIVE_INFINITY) {
|
|
13562
|
+
list.length = 0;
|
|
13563
|
+
} else if (count > 0 && payload.index !== void 0) {
|
|
13564
|
+
list.splice(payload.index, count);
|
|
13565
|
+
}
|
|
13566
|
+
let insertedOffset = 0;
|
|
13567
|
+
for (const inserted of payload.inserted ?? []) {
|
|
13568
|
+
const entry = { wakes: payload.target === "next-step" && inserted.mode === "steer" };
|
|
13569
|
+
if (inserted.mode === "steer") {
|
|
13570
|
+
list.unshift(entry);
|
|
13571
|
+
} else {
|
|
13572
|
+
const index = payload.index === void 0 ? list.length : Math.min(list.length, payload.index + insertedOffset);
|
|
13573
|
+
list.splice(index, 0, entry);
|
|
13574
|
+
insertedOffset += 1;
|
|
13575
|
+
}
|
|
13576
|
+
}
|
|
13150
13577
|
}
|
|
13151
|
-
return
|
|
13578
|
+
return nextStep.some((entry) => entry.wakes);
|
|
13152
13579
|
}
|
|
13153
13580
|
async function readAgentMeta(file) {
|
|
13154
13581
|
const lines = await import("node:fs/promises").then((fs2) => fs2.readFile(file, "utf8")).catch((error2) => {
|
|
@@ -26283,7 +26710,9 @@ function anthropicMessagesAdapter(config2 = {}) {
|
|
|
26283
26710
|
}
|
|
26284
26711
|
let sawEvent = false;
|
|
26285
26712
|
try {
|
|
26286
|
-
|
|
26713
|
+
const contentType2 = response.headers.get("content-type")?.split(";")[0]?.trim().toLowerCase();
|
|
26714
|
+
const events = contentType2 === "application/json" ? parseJSONCompletionStream(response) : parseAnthropicStream(response.body);
|
|
26715
|
+
for await (const event of events) {
|
|
26287
26716
|
sawEvent = true;
|
|
26288
26717
|
yield event;
|
|
26289
26718
|
}
|
|
@@ -26324,7 +26753,7 @@ function buildRequest(messages, tools2, config2, signal, stream = false) {
|
|
|
26324
26753
|
headers: {
|
|
26325
26754
|
"content-type": "application/json",
|
|
26326
26755
|
"anthropic-version": ANTHROPIC_VERSION,
|
|
26327
|
-
...config2.apiKey ? { "x-api-key": config2.apiKey } : {}
|
|
26756
|
+
...config2.apiKey ? { [config2.apiKeyHeader ?? "x-api-key"]: config2.apiKey } : {}
|
|
26328
26757
|
},
|
|
26329
26758
|
body: JSON.stringify(body),
|
|
26330
26759
|
...signal ? { signal } : {}
|
|
@@ -26616,6 +27045,26 @@ async function* parseAnthropicStream(body) {
|
|
|
26616
27045
|
function toIndex(block) {
|
|
26617
27046
|
return typeof block.index === "number" ? block.index : 0;
|
|
26618
27047
|
}
|
|
27048
|
+
async function* parseJSONCompletionStream(response) {
|
|
27049
|
+
const payload = await parseJson(response);
|
|
27050
|
+
const completion = parseCompletion(payload);
|
|
27051
|
+
const record3 = payload;
|
|
27052
|
+
const id = typeof record3?.id === "string" && record3.id ? record3.id : randomUUID8();
|
|
27053
|
+
const model = typeof record3?.model === "string" && record3.model ? record3.model : void 0;
|
|
27054
|
+
yield { type: "message_start", id, ...model ? { model } : {} };
|
|
27055
|
+
if (completion.content) yield { type: "message_delta", id, delta: completion.content };
|
|
27056
|
+
for (const [index, call] of (completion.toolCalls ?? []).entries()) {
|
|
27057
|
+
yield { type: "toolcall_start", id: call.id, index, name: call.name };
|
|
27058
|
+
yield {
|
|
27059
|
+
type: "toolcall_end",
|
|
27060
|
+
id: call.id,
|
|
27061
|
+
index,
|
|
27062
|
+
name: call.name,
|
|
27063
|
+
arguments: call.arguments
|
|
27064
|
+
};
|
|
27065
|
+
}
|
|
27066
|
+
yield { type: "message_stop", id, finishReason: completion.finishReason };
|
|
27067
|
+
}
|
|
26619
27068
|
function toStreamError(error2, timeoutMs) {
|
|
26620
27069
|
if (isAbortLike(error2)) {
|
|
26621
27070
|
return new OpenAICompatibleError(
|
|
@@ -26704,7 +27153,9 @@ function openaiCompatAdapter(config2 = {}) {
|
|
|
26704
27153
|
}
|
|
26705
27154
|
let sawEvent = false;
|
|
26706
27155
|
try {
|
|
26707
|
-
|
|
27156
|
+
const contentType2 = response.headers.get("content-type")?.split(";")[0]?.trim().toLowerCase();
|
|
27157
|
+
const events = contentType2 === "application/json" ? parseJSONCompletionStream2(response) : parseOpenAIStream(response.body);
|
|
27158
|
+
for await (const event of events) {
|
|
26708
27159
|
sawEvent = true;
|
|
26709
27160
|
yield event;
|
|
26710
27161
|
}
|
|
@@ -26922,6 +27373,26 @@ async function* parseOpenAIStream(body) {
|
|
|
26922
27373
|
}
|
|
26923
27374
|
yield* finalizeStreamEvents(messageId, content, calls, finishReason);
|
|
26924
27375
|
}
|
|
27376
|
+
async function* parseJSONCompletionStream2(response) {
|
|
27377
|
+
const payload = await parseJson(response);
|
|
27378
|
+
const completion = parseCompletion2(payload);
|
|
27379
|
+
const record3 = payload;
|
|
27380
|
+
const id = typeof record3?.id === "string" && record3.id ? record3.id : randomUUID9();
|
|
27381
|
+
const model = typeof record3?.model === "string" && record3.model ? record3.model : void 0;
|
|
27382
|
+
yield { type: "message_start", id, ...model ? { model } : {} };
|
|
27383
|
+
if (completion.content) yield { type: "message_delta", id, delta: completion.content };
|
|
27384
|
+
for (const [index, call] of (completion.toolCalls ?? []).entries()) {
|
|
27385
|
+
yield { type: "toolcall_start", id: call.id, index, name: call.name };
|
|
27386
|
+
yield {
|
|
27387
|
+
type: "toolcall_end",
|
|
27388
|
+
id: call.id,
|
|
27389
|
+
index,
|
|
27390
|
+
name: call.name,
|
|
27391
|
+
arguments: call.arguments
|
|
27392
|
+
};
|
|
27393
|
+
}
|
|
27394
|
+
yield { type: "message_stop", id, finishReason: completion.finishReason };
|
|
27395
|
+
}
|
|
26925
27396
|
function processStreamChunk(payload, state, progress, calls) {
|
|
26926
27397
|
const record3 = payload;
|
|
26927
27398
|
const events = [];
|
|
@@ -31186,7 +31657,7 @@ async function updateSystemConfig(patch, file = systemConfigPath()) {
|
|
|
31186
31657
|
}
|
|
31187
31658
|
function effectiveLlmConfig(config2, env = process.env) {
|
|
31188
31659
|
const envConfig = resolveLlmEnv(env);
|
|
31189
|
-
const apiKey =
|
|
31660
|
+
const apiKey = effectiveApiKey(config2, env);
|
|
31190
31661
|
const baseUrl = envConfig.baseUrl ?? config2.baseUrl ?? DEFAULT_OPENCODE_GO_BASE_URL;
|
|
31191
31662
|
const model = envConfig.model ?? config2.model ?? DEFAULT_MODEL;
|
|
31192
31663
|
const result = {
|
|
@@ -31195,15 +31666,18 @@ function effectiveLlmConfig(config2, env = process.env) {
|
|
|
31195
31666
|
model
|
|
31196
31667
|
};
|
|
31197
31668
|
if (config2.protocol) result.protocol = config2.protocol;
|
|
31669
|
+
if (config2.apiKeyHeader) result.apiKeyHeader = config2.apiKeyHeader;
|
|
31198
31670
|
if (config2.temperature !== void 0) result.temperature = config2.temperature;
|
|
31199
31671
|
return result;
|
|
31200
31672
|
}
|
|
31201
31673
|
function effectiveApiKey(config2, env = process.env) {
|
|
31674
|
+
if (env.TNEGA_API_KEY) return env.TNEGA_API_KEY;
|
|
31675
|
+
if (config2.protocol && config2.apiKey) return config2.apiKey;
|
|
31202
31676
|
return resolveLlmEnv(env).apiKey ?? config2.apiKey;
|
|
31203
31677
|
}
|
|
31204
31678
|
function resolveLlmEnv(env = process.env) {
|
|
31205
31679
|
const config2 = {};
|
|
31206
|
-
const apiKey = env.OPENCODE_GO_API_KEY || env.OPENAI_API_KEY || env.DEEPSEEK_API_KEY;
|
|
31680
|
+
const apiKey = env.TNEGA_API_KEY || env.OPENCODE_GO_API_KEY || env.OPENAI_API_KEY || env.DEEPSEEK_API_KEY;
|
|
31207
31681
|
if (apiKey) config2.apiKey = apiKey;
|
|
31208
31682
|
if (env.OPENCODE_GO_BASE_URL) config2.baseUrl = env.OPENCODE_GO_BASE_URL;
|
|
31209
31683
|
if (env.OPENCODE_GO_MODEL) config2.model = env.OPENCODE_GO_MODEL;
|
|
@@ -31219,6 +31693,9 @@ function normalizeConfig2(value) {
|
|
|
31219
31693
|
if (record3.protocol === "anthropic" || record3.protocol === "openai") {
|
|
31220
31694
|
config2.protocol = record3.protocol;
|
|
31221
31695
|
}
|
|
31696
|
+
if (record3.apiKeyHeader === "x-api-key" || record3.apiKeyHeader === "api-key") {
|
|
31697
|
+
config2.apiKeyHeader = record3.apiKeyHeader;
|
|
31698
|
+
}
|
|
31222
31699
|
if (typeof record3.temperature === "number" && Number.isFinite(record3.temperature)) {
|
|
31223
31700
|
config2.temperature = record3.temperature;
|
|
31224
31701
|
}
|
|
@@ -31542,10 +32019,10 @@ async function runCommand3(options) {
|
|
|
31542
32019
|
if (candidate.coding) {
|
|
31543
32020
|
const systemConfig = await readSystemConfig();
|
|
31544
32021
|
const envConfig = resolveLlmEnv(process.env);
|
|
31545
|
-
const apiKey =
|
|
32022
|
+
const apiKey = effectiveApiKey(systemConfig);
|
|
31546
32023
|
if (!apiKey) {
|
|
31547
32024
|
throw new CliError(
|
|
31548
|
-
"missing LLM API key for coding eval; set
|
|
32025
|
+
"missing LLM API key for coding eval; set TNEGA_API_KEY (or OPENCODE_GO_API_KEY / OPENAI_API_KEY / DEEPSEEK_API_KEY) or configure it in the tnega config file"
|
|
31549
32026
|
);
|
|
31550
32027
|
}
|
|
31551
32028
|
const model = options.model ?? envConfig.model ?? systemConfig.model ?? candidate.coding.model;
|
|
@@ -31555,6 +32032,7 @@ async function runCommand3(options) {
|
|
|
31555
32032
|
...model ? { model } : {},
|
|
31556
32033
|
...baseUrl ? { baseUrl } : {},
|
|
31557
32034
|
...systemConfig.protocol ? { protocol: systemConfig.protocol } : {},
|
|
32035
|
+
...systemConfig.apiKeyHeader ? { apiKeyHeader: systemConfig.apiKeyHeader } : {},
|
|
31558
32036
|
...options.maxTokens !== void 0 ? { maxTokens: options.maxTokens } : {},
|
|
31559
32037
|
...options.temperature !== void 0 ? { temperature: options.temperature } : {},
|
|
31560
32038
|
...systemConfig.temperature !== void 0 && options.temperature === void 0 ? { temperature: systemConfig.temperature } : {},
|
|
@@ -31622,10 +32100,10 @@ async function runAgentCommand(options) {
|
|
|
31622
32100
|
const profileOptions = profile?.options ?? {};
|
|
31623
32101
|
const systemConfig = await readSystemConfig(configFile);
|
|
31624
32102
|
const envConfig = resolveLlmEnv(process.env);
|
|
31625
|
-
const apiKey =
|
|
32103
|
+
const apiKey = effectiveApiKey(systemConfig);
|
|
31626
32104
|
if (!apiKey) {
|
|
31627
32105
|
throw new CliError(
|
|
31628
|
-
"missing LLM API key; set
|
|
32106
|
+
"missing LLM API key; set TNEGA_API_KEY (or OPENCODE_GO_API_KEY / OPENAI_API_KEY / DEEPSEEK_API_KEY) or configure it in the tnega config file"
|
|
31629
32107
|
);
|
|
31630
32108
|
}
|
|
31631
32109
|
const model = options.model ?? profileOptions.model ?? envConfig.model ?? systemConfig.model;
|
|
@@ -31636,6 +32114,7 @@ async function runAgentCommand(options) {
|
|
|
31636
32114
|
...typeof model === "string" && model ? { model } : {},
|
|
31637
32115
|
...baseUrl ? { baseUrl } : {},
|
|
31638
32116
|
...protocolFrom(profileOptions) ?? systemConfig.protocol ? { protocol: protocolFrom(profileOptions) ?? systemConfig.protocol } : {},
|
|
32117
|
+
...systemConfig.apiKeyHeader ? { apiKeyHeader: systemConfig.apiKeyHeader } : {},
|
|
31639
32118
|
...options.maxTokens !== void 0 ? { maxTokens: options.maxTokens } : {},
|
|
31640
32119
|
...options.maxTokens === void 0 && typeof profileOptions.maxTokens === "number" ? { maxTokens: profileOptions.maxTokens } : {},
|
|
31641
32120
|
...options.temperature !== void 0 ? { temperature: options.temperature } : {},
|
|
@@ -31766,10 +32245,10 @@ async function runEvolveCommand(options) {
|
|
|
31766
32245
|
const configFile = options.configFile ?? systemConfigPath();
|
|
31767
32246
|
const systemConfig = await readSystemConfig(configFile);
|
|
31768
32247
|
const envConfig = resolveLlmEnv(process.env);
|
|
31769
|
-
const apiKey =
|
|
32248
|
+
const apiKey = effectiveApiKey(systemConfig);
|
|
31770
32249
|
if (!apiKey) {
|
|
31771
32250
|
throw new CliError(
|
|
31772
|
-
"missing LLM API key; set
|
|
32251
|
+
"missing LLM API key; set TNEGA_API_KEY (or OPENCODE_GO_API_KEY / OPENAI_API_KEY / DEEPSEEK_API_KEY) or configure it in the tnega config file"
|
|
31773
32252
|
);
|
|
31774
32253
|
}
|
|
31775
32254
|
const model = options.model ?? envConfig.model ?? systemConfig.model;
|
|
@@ -31779,6 +32258,7 @@ async function runEvolveCommand(options) {
|
|
|
31779
32258
|
...model ? { model } : {},
|
|
31780
32259
|
...baseUrl ? { baseUrl } : {},
|
|
31781
32260
|
...systemConfig.protocol ? { protocol: systemConfig.protocol } : {},
|
|
32261
|
+
...systemConfig.apiKeyHeader ? { apiKeyHeader: systemConfig.apiKeyHeader } : {},
|
|
31782
32262
|
...options.maxTokens !== void 0 ? { maxTokens: options.maxTokens } : {},
|
|
31783
32263
|
...options.temperature !== void 0 ? { temperature: options.temperature } : {},
|
|
31784
32264
|
...systemConfig.temperature !== void 0 && options.temperature === void 0 ? { temperature: systemConfig.temperature } : {},
|
|
@@ -33145,6 +33625,7 @@ function adapterFromConfig(effective, apiKey) {
|
|
|
33145
33625
|
model: effective.model
|
|
33146
33626
|
};
|
|
33147
33627
|
if (effective.protocol) options.protocol = effective.protocol;
|
|
33628
|
+
if (effective.apiKeyHeader) options.apiKeyHeader = effective.apiKeyHeader;
|
|
33148
33629
|
if (effective.temperature !== void 0) options.temperature = effective.temperature;
|
|
33149
33630
|
return createLlmAdapter(options);
|
|
33150
33631
|
}
|
|
@@ -33827,6 +34308,7 @@ export {
|
|
|
33827
34308
|
anthropicMessagesAdapter,
|
|
33828
34309
|
assertInvariants,
|
|
33829
34310
|
assertStrategy,
|
|
34311
|
+
assistantStreams,
|
|
33830
34312
|
bootAgentRuntime,
|
|
33831
34313
|
builtinTools,
|
|
33832
34314
|
candidateKey,
|