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/eval.js
CHANGED
|
@@ -8190,17 +8190,88 @@ function checkMonotonicSeq(events) {
|
|
|
8190
8190
|
}
|
|
8191
8191
|
return failures;
|
|
8192
8192
|
}
|
|
8193
|
+
function isRecord(value) {
|
|
8194
|
+
return typeof value === "object" && value !== null && (Object.getPrototypeOf(value) === Object.prototype || Object.getPrototypeOf(value) === null);
|
|
8195
|
+
}
|
|
8196
|
+
function isNonNegativeInteger(value) {
|
|
8197
|
+
return typeof value === "number" && Number.isSafeInteger(value) && value >= 0;
|
|
8198
|
+
}
|
|
8199
|
+
function isJsonValue(value, ancestors = /* @__PURE__ */ new Set()) {
|
|
8200
|
+
if (value === null || typeof value === "string" || typeof value === "boolean") return true;
|
|
8201
|
+
if (typeof value === "number") return Number.isFinite(value);
|
|
8202
|
+
if (typeof value !== "object" || ancestors.has(value)) return false;
|
|
8203
|
+
if (!Array.isArray(value) && Object.getPrototypeOf(value) !== Object.prototype && Object.getPrototypeOf(value) !== null) return false;
|
|
8204
|
+
ancestors.add(value);
|
|
8205
|
+
const valid = (Array.isArray(value) ? Array.from(value) : Object.values(value)).every((member) => isJsonValue(member, ancestors));
|
|
8206
|
+
ancestors.delete(value);
|
|
8207
|
+
return valid;
|
|
8208
|
+
}
|
|
8209
|
+
function isStreamRecord(value) {
|
|
8210
|
+
if (!isRecord(value) || !isNonNegativeInteger(value.time) || !isRecord(value.chunk)) return false;
|
|
8211
|
+
const chunk = value.chunk;
|
|
8212
|
+
if (chunk.type === "stream_error") {
|
|
8213
|
+
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");
|
|
8214
|
+
}
|
|
8215
|
+
if (typeof chunk.id !== "string") return false;
|
|
8216
|
+
switch (chunk.type) {
|
|
8217
|
+
case "message_start":
|
|
8218
|
+
return chunk.model === void 0 || typeof chunk.model === "string";
|
|
8219
|
+
case "message_delta":
|
|
8220
|
+
return typeof chunk.delta === "string";
|
|
8221
|
+
case "toolcall_start":
|
|
8222
|
+
case "toolcall_end":
|
|
8223
|
+
return isNonNegativeInteger(chunk.index) && typeof chunk.name === "string" && (chunk.type === "toolcall_start" || isJsonValue(chunk.arguments));
|
|
8224
|
+
case "message_stop":
|
|
8225
|
+
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";
|
|
8226
|
+
default:
|
|
8227
|
+
return false;
|
|
8228
|
+
}
|
|
8229
|
+
}
|
|
8230
|
+
function checkAssistantAttempts(events) {
|
|
8231
|
+
const turns = /* @__PURE__ */ new Set();
|
|
8232
|
+
const steps = /* @__PURE__ */ new Map();
|
|
8233
|
+
const failures = [];
|
|
8234
|
+
for (const event of events) {
|
|
8235
|
+
if (event.type === "turn/start") turns.add(event.payload.turn);
|
|
8236
|
+
if (event.type === "turn/end") {
|
|
8237
|
+
turns.delete(event.payload.turn);
|
|
8238
|
+
for (const [key, turn] of steps) {
|
|
8239
|
+
if (turn === event.payload.turn) steps.delete(key);
|
|
8240
|
+
}
|
|
8241
|
+
}
|
|
8242
|
+
if (event.type === "step/start" && turns.has(event.payload.turn)) {
|
|
8243
|
+
steps.set(`${event.payload.turn}:${event.payload.step}`, event.payload.turn);
|
|
8244
|
+
}
|
|
8245
|
+
if (event.type === "step/end") steps.delete(`${event.payload.turn}:${event.payload.step}`);
|
|
8246
|
+
if (event.type !== "assistant/attempt") continue;
|
|
8247
|
+
const payload = event.payload;
|
|
8248
|
+
if (!isRecord(payload) || !isNonNegativeInteger(payload.turn) || !isNonNegativeInteger(payload.step) || !turns.has(payload.turn) || !steps.has(`${payload.turn}:${payload.step}`)) {
|
|
8249
|
+
failures.push({
|
|
8250
|
+
name: "assistant/attempt-without-open-step",
|
|
8251
|
+
detail: `assistant/attempt at seq ${event.seq} has no matching open turn and step`
|
|
8252
|
+
});
|
|
8253
|
+
}
|
|
8254
|
+
if (!isRecord(payload) || !Array.isArray(payload.stream) || !payload.stream.every(isStreamRecord)) {
|
|
8255
|
+
failures.push({
|
|
8256
|
+
name: "assistant/attempt-invalid-stream",
|
|
8257
|
+
detail: `assistant/attempt at seq ${event.seq} must contain an ordered array of normalized stream records`
|
|
8258
|
+
});
|
|
8259
|
+
}
|
|
8260
|
+
}
|
|
8261
|
+
return failures;
|
|
8262
|
+
}
|
|
8193
8263
|
function checkSessionInvariants(events) {
|
|
8194
8264
|
return [
|
|
8195
8265
|
...checkBalancedTurns(events),
|
|
8196
8266
|
...checkBalancedSteps(events),
|
|
8197
8267
|
...checkBalancedToolCalls(events),
|
|
8198
|
-
...checkMonotonicSeq(events)
|
|
8268
|
+
...checkMonotonicSeq(events),
|
|
8269
|
+
...checkAssistantAttempts(events)
|
|
8199
8270
|
];
|
|
8200
8271
|
}
|
|
8201
8272
|
|
|
8202
8273
|
// packages/session/src/index.ts
|
|
8203
|
-
var SESSION_FORMAT_VERSION =
|
|
8274
|
+
var SESSION_FORMAT_VERSION = 10;
|
|
8204
8275
|
var SessionFormatError = class extends Error {
|
|
8205
8276
|
name = "SessionFormatError";
|
|
8206
8277
|
};
|
|
@@ -8415,6 +8486,7 @@ function estimateEventTokens(event) {
|
|
|
8415
8486
|
return Math.ceil(raw.length / 4);
|
|
8416
8487
|
}
|
|
8417
8488
|
case "plan":
|
|
8489
|
+
case "assistant/attempt":
|
|
8418
8490
|
return 0;
|
|
8419
8491
|
case "checkpoint":
|
|
8420
8492
|
return estimateMessageTokens(event.payload.messages);
|
|
@@ -8549,9 +8621,15 @@ function estimateContextUsage(messages, limit = DEFAULT_CONTEXT_LIMIT) {
|
|
|
8549
8621
|
};
|
|
8550
8622
|
}
|
|
8551
8623
|
var SessionLog = class {
|
|
8552
|
-
constructor(file, _broadcast) {
|
|
8624
|
+
constructor(file, _broadcast, publicationContext) {
|
|
8553
8625
|
this.file = file;
|
|
8554
8626
|
this._broadcast = _broadcast;
|
|
8627
|
+
if (!this._broadcast && publicationContext) {
|
|
8628
|
+
this._broadcast = (type, payload) => {
|
|
8629
|
+
if (type === "event") publicationContext.emit("session/event", payload);
|
|
8630
|
+
else publicationContext.emit("session/flush", payload);
|
|
8631
|
+
};
|
|
8632
|
+
}
|
|
8555
8633
|
}
|
|
8556
8634
|
file;
|
|
8557
8635
|
_broadcast;
|
|
@@ -8720,7 +8798,7 @@ var SessionLog = class {
|
|
|
8720
8798
|
selected.push(clone(event));
|
|
8721
8799
|
continue;
|
|
8722
8800
|
}
|
|
8723
|
-
if (event.type === "meta" || event.type === "llm/retry" || event.type === "llm/retry-started" || event.type.startsWith("turn/") || event.type.startsWith("step/")) {
|
|
8801
|
+
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/")) {
|
|
8724
8802
|
continue;
|
|
8725
8803
|
}
|
|
8726
8804
|
if (event.type === "checkpoint") {
|
|
@@ -11614,7 +11692,7 @@ function copyMessages(messages) {
|
|
|
11614
11692
|
copy.tool_calls = message2.tool_calls.map((call) => ({
|
|
11615
11693
|
id: call.id,
|
|
11616
11694
|
name: call.name,
|
|
11617
|
-
arguments: call.arguments
|
|
11695
|
+
arguments: structuredClone(call.arguments)
|
|
11618
11696
|
}));
|
|
11619
11697
|
}
|
|
11620
11698
|
return copy;
|
|
@@ -11645,6 +11723,75 @@ function copyCompletion(completion) {
|
|
|
11645
11723
|
}
|
|
11646
11724
|
return copy;
|
|
11647
11725
|
}
|
|
11726
|
+
function canonicalMessages(messages) {
|
|
11727
|
+
return JSON.stringify(messages.map((message2) => ({
|
|
11728
|
+
role: message2.role,
|
|
11729
|
+
content: message2.content,
|
|
11730
|
+
...message2.name ? { name: message2.name } : {},
|
|
11731
|
+
...message2.tool_call_id ? { tool_call_id: message2.tool_call_id } : {},
|
|
11732
|
+
...message2.tool_calls?.length ? { tool_calls: message2.tool_calls } : {},
|
|
11733
|
+
...message2.toolOk !== void 0 ? { toolOk: message2.toolOk } : {},
|
|
11734
|
+
...message2.toolError ? {
|
|
11735
|
+
toolError: { name: message2.toolError.name, message: message2.toolError.message }
|
|
11736
|
+
} : {}
|
|
11737
|
+
})));
|
|
11738
|
+
}
|
|
11739
|
+
function freezeRequestData(data) {
|
|
11740
|
+
const visited = /* @__PURE__ */ new Set();
|
|
11741
|
+
const freeze = (value) => {
|
|
11742
|
+
if (typeof value !== "object" || value === null || visited.has(value)) return;
|
|
11743
|
+
visited.add(value);
|
|
11744
|
+
for (const child of Object.values(value)) freeze(child);
|
|
11745
|
+
Object.freeze(value);
|
|
11746
|
+
};
|
|
11747
|
+
freeze(data);
|
|
11748
|
+
}
|
|
11749
|
+
function lockStreamRequest(request) {
|
|
11750
|
+
freezeRequestData(request.messages);
|
|
11751
|
+
request.tools = Object.freeze(request.tools.map((tool) => {
|
|
11752
|
+
const schema = structuredClone(tool.schema);
|
|
11753
|
+
freezeRequestData(schema);
|
|
11754
|
+
return Object.freeze({ ...tool, schema });
|
|
11755
|
+
}));
|
|
11756
|
+
Object.freeze(request.options);
|
|
11757
|
+
Object.freeze(request);
|
|
11758
|
+
}
|
|
11759
|
+
function requestHeaderFor(request, input) {
|
|
11760
|
+
const system = input.find((message2) => message2.role === "system")?.content;
|
|
11761
|
+
const tools2 = request.tools.map((tool) => ({
|
|
11762
|
+
name: tool.schema.name,
|
|
11763
|
+
description: tool.schema.description,
|
|
11764
|
+
...tool.schema.parameters ? { parameters: tool.schema.parameters } : {}
|
|
11765
|
+
}));
|
|
11766
|
+
const config2 = {
|
|
11767
|
+
...request.options.provider ? { provider: request.options.provider } : {},
|
|
11768
|
+
...request.options.model ? { model: request.options.model } : {},
|
|
11769
|
+
...request.options.temperature !== void 0 ? { temperature: request.options.temperature } : {}
|
|
11770
|
+
};
|
|
11771
|
+
return {
|
|
11772
|
+
...Object.keys(config2).length ? { config: config2 } : {},
|
|
11773
|
+
...system !== void 0 ? { system } : {},
|
|
11774
|
+
...tools2.length ? { tools: tools2 } : {}
|
|
11775
|
+
};
|
|
11776
|
+
}
|
|
11777
|
+
async function* completeAsStream(llm, messages, tools2, options) {
|
|
11778
|
+
const id = randomUUID2();
|
|
11779
|
+
yield { type: "message_start", id };
|
|
11780
|
+
const completion = await llm.complete(messages, tools2, options);
|
|
11781
|
+
if (completion.content) yield { type: "message_delta", id, delta: completion.content };
|
|
11782
|
+
for (let index = 0; index < (completion.toolCalls?.length ?? 0); index += 1) {
|
|
11783
|
+
const call = completion.toolCalls[index];
|
|
11784
|
+
yield { type: "toolcall_start", id: call.id, index, name: call.name };
|
|
11785
|
+
yield {
|
|
11786
|
+
type: "toolcall_end",
|
|
11787
|
+
id: call.id,
|
|
11788
|
+
index,
|
|
11789
|
+
name: call.name,
|
|
11790
|
+
arguments: call.arguments
|
|
11791
|
+
};
|
|
11792
|
+
}
|
|
11793
|
+
yield { type: "message_stop", id, finishReason: completion.finishReason };
|
|
11794
|
+
}
|
|
11648
11795
|
function isCancelCause(value) {
|
|
11649
11796
|
if (typeof value !== "object" || value === null) return false;
|
|
11650
11797
|
const record3 = value;
|
|
@@ -11665,6 +11812,13 @@ function cancelCauseFromSignal(signal) {
|
|
|
11665
11812
|
if (isCancelCause(reason)) return reason;
|
|
11666
11813
|
return { type: "abort" };
|
|
11667
11814
|
}
|
|
11815
|
+
function abortedToolError(signal) {
|
|
11816
|
+
const cause = cancelCauseFromSignal(signal);
|
|
11817
|
+
return {
|
|
11818
|
+
name: "AbortError",
|
|
11819
|
+
message: `tool call aborted: ${cause?.type ?? "abort"}`
|
|
11820
|
+
};
|
|
11821
|
+
}
|
|
11668
11822
|
function toTurnEndReason(fields) {
|
|
11669
11823
|
const { cancelled, turnError, finishReason, cancelCause } = fields;
|
|
11670
11824
|
if (cancelled || finishReason === "cancelled") {
|
|
@@ -11709,6 +11863,78 @@ async function cancellableDelay(ms, signal) {
|
|
|
11709
11863
|
signal?.addEventListener("abort", onAbort, { once: true });
|
|
11710
11864
|
});
|
|
11711
11865
|
}
|
|
11866
|
+
var AssistantStreamAttempt = class {
|
|
11867
|
+
constructor(session2, turn, step, nextRevision) {
|
|
11868
|
+
this.session = session2;
|
|
11869
|
+
this.turn = turn;
|
|
11870
|
+
this.step = step;
|
|
11871
|
+
this.nextRevision = nextRevision;
|
|
11872
|
+
}
|
|
11873
|
+
session;
|
|
11874
|
+
turn;
|
|
11875
|
+
step;
|
|
11876
|
+
nextRevision;
|
|
11877
|
+
attemptId = randomUUID2();
|
|
11878
|
+
records = [];
|
|
11879
|
+
ended = false;
|
|
11880
|
+
start() {
|
|
11881
|
+
return { type: "assistant/stream", frame: {
|
|
11882
|
+
type: "start",
|
|
11883
|
+
attemptId: this.attemptId,
|
|
11884
|
+
revision: this.nextRevision(),
|
|
11885
|
+
turn: this.turn,
|
|
11886
|
+
step: this.step
|
|
11887
|
+
} };
|
|
11888
|
+
}
|
|
11889
|
+
push(chunk) {
|
|
11890
|
+
if (this.ended) throw new AgentError("assistant attempt is already settled");
|
|
11891
|
+
const record3 = { time: Date.now(), chunk: structuredClone(chunk) };
|
|
11892
|
+
const index = this.records.length;
|
|
11893
|
+
this.records.push(record3);
|
|
11894
|
+
return { type: "assistant/stream", frame: {
|
|
11895
|
+
type: "chunk",
|
|
11896
|
+
attemptId: this.attemptId,
|
|
11897
|
+
revision: this.nextRevision(),
|
|
11898
|
+
index,
|
|
11899
|
+
...structuredClone(record3)
|
|
11900
|
+
} };
|
|
11901
|
+
}
|
|
11902
|
+
async settle(message2) {
|
|
11903
|
+
if (this.ended) throw new AgentError("assistant attempt is already settled");
|
|
11904
|
+
const eventType = message2 ? "assistant/message" : "assistant/attempt";
|
|
11905
|
+
let event;
|
|
11906
|
+
try {
|
|
11907
|
+
event = message2 ? await this.session.append("assistant/message", { ...message2, stream: this.records }) : await this.session.append("assistant/attempt", { turn: this.turn, step: this.step, stream: this.records });
|
|
11908
|
+
} catch (cause) {
|
|
11909
|
+
this.ended = true;
|
|
11910
|
+
const frame = { type: "assistant/stream", frame: {
|
|
11911
|
+
type: "end",
|
|
11912
|
+
attemptId: this.attemptId,
|
|
11913
|
+
revision: this.nextRevision(),
|
|
11914
|
+
index: this.records.length,
|
|
11915
|
+
outcome: { kind: "abandoned" }
|
|
11916
|
+
} };
|
|
11917
|
+
throw new AttemptSettlementError(cause, frame);
|
|
11918
|
+
}
|
|
11919
|
+
this.ended = true;
|
|
11920
|
+
return { type: "assistant/stream", frame: {
|
|
11921
|
+
type: "end",
|
|
11922
|
+
attemptId: this.attemptId,
|
|
11923
|
+
revision: this.nextRevision(),
|
|
11924
|
+
index: this.records.length,
|
|
11925
|
+
outcome: { kind: "committed", eventType, seq: event.seq }
|
|
11926
|
+
} };
|
|
11927
|
+
}
|
|
11928
|
+
};
|
|
11929
|
+
var AttemptSettlementError = class extends Error {
|
|
11930
|
+
constructor(cause, frame) {
|
|
11931
|
+
super("assistant attempt settlement failed");
|
|
11932
|
+
this.cause = cause;
|
|
11933
|
+
this.frame = frame;
|
|
11934
|
+
}
|
|
11935
|
+
cause;
|
|
11936
|
+
frame;
|
|
11937
|
+
};
|
|
11712
11938
|
var AgentService = class {
|
|
11713
11939
|
constructor(ctx, config2 = {}) {
|
|
11714
11940
|
this.ctx = ctx;
|
|
@@ -11717,9 +11943,24 @@ var AgentService = class {
|
|
|
11717
11943
|
}
|
|
11718
11944
|
ctx;
|
|
11719
11945
|
config;
|
|
11946
|
+
async *settleAttempt(attempt, message2) {
|
|
11947
|
+
try {
|
|
11948
|
+
yield await attempt.settle(message2);
|
|
11949
|
+
} catch (error2) {
|
|
11950
|
+
if (error2 instanceof AttemptSettlementError) {
|
|
11951
|
+
yield error2.frame;
|
|
11952
|
+
throw error2.cause;
|
|
11953
|
+
}
|
|
11954
|
+
throw error2;
|
|
11955
|
+
}
|
|
11956
|
+
}
|
|
11720
11957
|
inbox;
|
|
11721
11958
|
_seriesStarted = false;
|
|
11722
11959
|
_persistedRequest = false;
|
|
11960
|
+
_streamRevision = 0;
|
|
11961
|
+
_attempt(session2, turn, step) {
|
|
11962
|
+
return new AssistantStreamAttempt(session2, turn, step, () => ++this._streamRevision);
|
|
11963
|
+
}
|
|
11723
11964
|
/** Call when a request begins an explicit new model-message series. */
|
|
11724
11965
|
startSeries() {
|
|
11725
11966
|
this._seriesStarted = true;
|
|
@@ -11733,7 +11974,7 @@ var AgentService = class {
|
|
|
11733
11974
|
return this._persistedRequest;
|
|
11734
11975
|
}
|
|
11735
11976
|
async run(input, options = {}) {
|
|
11736
|
-
return consumeAgentStream(this._stream(input, options
|
|
11977
|
+
return consumeAgentStream(this._stream(input, options));
|
|
11737
11978
|
}
|
|
11738
11979
|
async *runStream(input, options = {}) {
|
|
11739
11980
|
const iterator = this._stream(input, options)[Symbol.asyncIterator]();
|
|
@@ -11743,7 +11984,7 @@ var AgentService = class {
|
|
|
11743
11984
|
yield next.value;
|
|
11744
11985
|
}
|
|
11745
11986
|
}
|
|
11746
|
-
async *_stream(input, options = {}
|
|
11987
|
+
async *_stream(input, options = {}) {
|
|
11747
11988
|
const claimed = input ?? this.inbox.claim();
|
|
11748
11989
|
if (!claimed) throw new AgentError("no agent input available");
|
|
11749
11990
|
await this.config.hooks?.beforeRun?.(claimed, options);
|
|
@@ -11751,26 +11992,32 @@ var AgentService = class {
|
|
|
11751
11992
|
const tools2 = this._tools();
|
|
11752
11993
|
const llm = this._llm();
|
|
11753
11994
|
if (!llm) throw new AgentError("no LLM adapter available");
|
|
11995
|
+
const streamAdapter = llm.stream;
|
|
11996
|
+
const persistChunks = streamAdapter !== void 0;
|
|
11754
11997
|
const maxTurns = options.maxTurns ?? this.config.maxTurns ?? 64;
|
|
11755
11998
|
const maxSteps = options.maxSteps ?? this.config.maxSteps ?? 64;
|
|
11756
11999
|
const contextBudget = options.contextBudget ?? this.config.contextBudget;
|
|
11757
12000
|
const injected = this.inbox.injected();
|
|
11758
12001
|
this.ctx.emit("agent/start", { input: claimed, options, injected });
|
|
11759
12002
|
let messages = await this._initialMessages(claimed);
|
|
12003
|
+
let claimedMessages = messages.filter((message2) => message2.role === "user");
|
|
11760
12004
|
const steps = [];
|
|
11761
12005
|
let output = "";
|
|
11762
12006
|
let finishReason = "stop";
|
|
12007
|
+
let lengthReached = false;
|
|
11763
12008
|
this.ctx.emit("agent/turn-start", {
|
|
11764
12009
|
input: claimed,
|
|
11765
12010
|
messages: copyMessages(messages),
|
|
11766
12011
|
injected
|
|
11767
12012
|
});
|
|
11768
|
-
const turn = await session2.nextTurn();
|
|
11769
|
-
|
|
11770
|
-
turn,
|
|
11771
|
-
|
|
11772
|
-
|
|
11773
|
-
|
|
12013
|
+
const turn = options.turn ?? await session2.nextTurn();
|
|
12014
|
+
if (options.turn === void 0) {
|
|
12015
|
+
await session2.append("turn/start", {
|
|
12016
|
+
turn,
|
|
12017
|
+
input: claimed.text ?? claimed,
|
|
12018
|
+
reason: "user"
|
|
12019
|
+
});
|
|
12020
|
+
}
|
|
11774
12021
|
let index = 0;
|
|
11775
12022
|
let finalTurnGranted = false;
|
|
11776
12023
|
let currentStepIndex;
|
|
@@ -11789,20 +12036,22 @@ var AgentService = class {
|
|
|
11789
12036
|
messages = await this._enforceContextBudget(session2, contextBudget, messages);
|
|
11790
12037
|
}
|
|
11791
12038
|
const stepInput = copyMessages(messages);
|
|
11792
|
-
const preStep = this.ctx.
|
|
12039
|
+
const preStep = await this.ctx.waterfallAsync("agent/pre-step", {
|
|
11793
12040
|
index,
|
|
11794
12041
|
turn,
|
|
11795
12042
|
step: index,
|
|
11796
12043
|
messages: stepInput,
|
|
12044
|
+
claimedMessages: copyMessages(claimedMessages),
|
|
11797
12045
|
...options.signal ? { signal: options.signal } : {}
|
|
11798
12046
|
}, (payload) => payload);
|
|
11799
|
-
if (!preStep || !Array.isArray(preStep.messages) || !preStep.messages.length) {
|
|
12047
|
+
if (!preStep || preStep.admission === "reject" || !Array.isArray(preStep.messages) || !preStep.messages.length) {
|
|
11800
12048
|
break;
|
|
11801
12049
|
}
|
|
11802
12050
|
if (preStep.startsRequestSeries) this._seriesStarted = true;
|
|
11803
12051
|
await session2.append("step/start", { turn, step: index });
|
|
11804
12052
|
currentStepIndex = index;
|
|
11805
12053
|
const requestedInput = copyMessages(preStep.messages);
|
|
12054
|
+
const admittedHistory = await session2.deriveMessages();
|
|
11806
12055
|
this.ctx.emit("agent/step", {
|
|
11807
12056
|
index,
|
|
11808
12057
|
turn,
|
|
@@ -11814,93 +12063,85 @@ var AgentService = class {
|
|
|
11814
12063
|
maxSteps: maxSteps - steps.length
|
|
11815
12064
|
};
|
|
11816
12065
|
if (options.signal) completeOptions.signal = options.signal;
|
|
11817
|
-
const request = this.ctx.waterfall("agent/request", {
|
|
11818
|
-
index,
|
|
11819
|
-
messages: requestedInput,
|
|
11820
|
-
tools: availableTools,
|
|
11821
|
-
options: completeOptions
|
|
11822
|
-
}, (payload) => payload);
|
|
11823
|
-
if (!request || !request.options || !request.tools) {
|
|
11824
|
-
throw new AgentError("agent/request must return a request payload");
|
|
11825
|
-
}
|
|
11826
12066
|
let llmMessages = copyMessages(requestedInput);
|
|
11827
12067
|
let completion;
|
|
11828
|
-
|
|
12068
|
+
let activeAttempt;
|
|
11829
12069
|
let attempt = 0;
|
|
11830
|
-
let persistedStepInput = false;
|
|
11831
12070
|
while (true) {
|
|
11832
12071
|
if (options.signal?.aborted) {
|
|
11833
12072
|
finishReason = "cancelled";
|
|
11834
12073
|
break;
|
|
11835
12074
|
}
|
|
11836
12075
|
const streamEvents = [];
|
|
12076
|
+
activeAttempt = this._attempt(session2, turn, index);
|
|
12077
|
+
yield activeAttempt.start();
|
|
12078
|
+
const streamRequest = {
|
|
12079
|
+
index,
|
|
12080
|
+
messages: copyMessages(requestedInput),
|
|
12081
|
+
tools: [...availableTools],
|
|
12082
|
+
options: { ...completeOptions }
|
|
12083
|
+
};
|
|
11837
12084
|
try {
|
|
11838
|
-
|
|
11839
|
-
|
|
11840
|
-
|
|
11841
|
-
|
|
11842
|
-
|
|
11843
|
-
|
|
11844
|
-
|
|
11845
|
-
|
|
11846
|
-
|
|
11847
|
-
|
|
11848
|
-
|
|
11849
|
-
|
|
11850
|
-
|
|
11851
|
-
|
|
11852
|
-
return streamMethod(payload.messages, payload.tools, payload.options);
|
|
11853
|
-
}
|
|
11854
|
-
);
|
|
11855
|
-
if (!stream || typeof stream[Symbol.asyncIterator] !== "function") {
|
|
11856
|
-
throw new AgentError("llm/stream must return an async iterable stream");
|
|
11857
|
-
}
|
|
12085
|
+
const request = await this.ctx.waterfallAsync("agent/request", {
|
|
12086
|
+
index,
|
|
12087
|
+
messages: copyMessages(requestedInput),
|
|
12088
|
+
tools: streamRequest.tools,
|
|
12089
|
+
options: streamRequest.options
|
|
12090
|
+
}, (payload) => payload);
|
|
12091
|
+
if (!request || !request.options || !request.tools) {
|
|
12092
|
+
throw new AgentError("agent/request must return a request payload");
|
|
12093
|
+
}
|
|
12094
|
+
streamRequest.tools = request.tools;
|
|
12095
|
+
streamRequest.options = request.options;
|
|
12096
|
+
let preparation;
|
|
12097
|
+
const prepareRequest = () => preparation ??= (async () => {
|
|
12098
|
+
lockStreamRequest(streamRequest);
|
|
11858
12099
|
llmMessages = copyMessages(streamRequest.messages);
|
|
11859
|
-
|
|
11860
|
-
|
|
11861
|
-
|
|
11862
|
-
|
|
11863
|
-
|
|
11864
|
-
|
|
11865
|
-
|
|
11866
|
-
|
|
11867
|
-
|
|
11868
|
-
|
|
11869
|
-
|
|
11870
|
-
|
|
11871
|
-
|
|
11872
|
-
|
|
11873
|
-
|
|
11874
|
-
|
|
11875
|
-
|
|
11876
|
-
|
|
11877
|
-
|
|
11878
|
-
|
|
11879
|
-
|
|
11880
|
-
|
|
11881
|
-
|
|
11882
|
-
|
|
11883
|
-
|
|
11884
|
-
|
|
11885
|
-
}
|
|
11886
|
-
persistedStepInput = true;
|
|
12100
|
+
await this._persistStepInput(session2, streamRequest, llmMessages, admittedHistory);
|
|
12101
|
+
await this._assertReplayable(session2, streamRequest, llmMessages);
|
|
12102
|
+
})();
|
|
12103
|
+
const stream = await this.ctx.waterfallAsync(
|
|
12104
|
+
"llm/stream",
|
|
12105
|
+
streamRequest,
|
|
12106
|
+
(payload) => (async function* () {
|
|
12107
|
+
await prepareRequest();
|
|
12108
|
+
yield* streamAdapter ? streamAdapter.call(llm, payload.messages, payload.tools, payload.options) : completeAsStream(llm, payload.messages, payload.tools, payload.options);
|
|
12109
|
+
})()
|
|
12110
|
+
);
|
|
12111
|
+
if (!stream || typeof stream[Symbol.asyncIterator] !== "function") {
|
|
12112
|
+
throw new AgentError("llm/stream must return an async iterable stream");
|
|
12113
|
+
}
|
|
12114
|
+
await prepareRequest();
|
|
12115
|
+
let chunkIndex = 0;
|
|
12116
|
+
for await (const event of stream) {
|
|
12117
|
+
streamEvents.push(structuredClone(event));
|
|
12118
|
+
yield activeAttempt.push(event);
|
|
12119
|
+
if (persistChunks && event.type === "message_delta") {
|
|
12120
|
+
await session2.append("assistant/chunk", {
|
|
12121
|
+
id: event.id,
|
|
12122
|
+
content: event.delta,
|
|
12123
|
+
index: chunkIndex
|
|
12124
|
+
});
|
|
12125
|
+
chunkIndex += 1;
|
|
11887
12126
|
}
|
|
11888
|
-
|
|
12127
|
+
yield event;
|
|
12128
|
+
}
|
|
12129
|
+
completion = completionFromStreamEvents(streamEvents);
|
|
12130
|
+
if (completion.finishReason === "error" || completion.finishReason === "cancelled") {
|
|
12131
|
+
const terminalReason = completion.finishReason;
|
|
12132
|
+
completion = void 0;
|
|
12133
|
+
throw new AgentError(`LLM stream finished with ${terminalReason}`);
|
|
11889
12134
|
}
|
|
11890
12135
|
break;
|
|
11891
12136
|
} catch (error2) {
|
|
11892
|
-
|
|
11893
|
-
if (content) {
|
|
11894
|
-
await session2.append("assistant/message", {
|
|
11895
|
-
content,
|
|
11896
|
-
interrupted: true
|
|
11897
|
-
});
|
|
11898
|
-
llmMessages = await session2.deriveMessages();
|
|
11899
|
-
}
|
|
12137
|
+
yield activeAttempt.push({ type: "stream_error", error: toToolError2(error2) });
|
|
11900
12138
|
if (options.signal?.aborted) {
|
|
12139
|
+
const content = partialStreamContent(streamEvents);
|
|
12140
|
+
yield* this.settleAttempt(activeAttempt, content ? { content, interrupted: true } : void 0);
|
|
11901
12141
|
finishReason = "cancelled";
|
|
11902
12142
|
break;
|
|
11903
12143
|
}
|
|
12144
|
+
yield* this.settleAttempt(activeAttempt);
|
|
11904
12145
|
attempt += 1;
|
|
11905
12146
|
const failure = toToolError2(error2);
|
|
11906
12147
|
const decision = await this.ctx.waterfallAsync(
|
|
@@ -11909,14 +12150,14 @@ var AgentService = class {
|
|
|
11909
12150
|
index,
|
|
11910
12151
|
turn,
|
|
11911
12152
|
step: index,
|
|
11912
|
-
messages: copyMessages(
|
|
11913
|
-
tools:
|
|
11914
|
-
options:
|
|
12153
|
+
messages: copyMessages(streamRequest.messages),
|
|
12154
|
+
tools: [...streamRequest.tools],
|
|
12155
|
+
options: { ...streamRequest.options },
|
|
11915
12156
|
attempt,
|
|
11916
12157
|
error: error2,
|
|
11917
12158
|
failure,
|
|
11918
|
-
...
|
|
11919
|
-
...
|
|
12159
|
+
...streamRequest.options.provider ? { provider: streamRequest.options.provider } : {},
|
|
12160
|
+
...streamRequest.options.model ? { model: streamRequest.options.model } : {},
|
|
11920
12161
|
...options.signal ? { signal: options.signal } : {}
|
|
11921
12162
|
},
|
|
11922
12163
|
() => void 0
|
|
@@ -11941,16 +12182,30 @@ var AgentService = class {
|
|
|
11941
12182
|
await session2.append("llm/retry-started", { retryId, retry: attempt });
|
|
11942
12183
|
}
|
|
11943
12184
|
}
|
|
11944
|
-
if (
|
|
11945
|
-
|
|
12185
|
+
if (!completion || !activeAttempt) {
|
|
12186
|
+
if (options.signal?.aborted) {
|
|
12187
|
+
finishReason = "cancelled";
|
|
12188
|
+
break;
|
|
12189
|
+
}
|
|
12190
|
+
throw new AgentError("LLM adapter did not produce a completion");
|
|
12191
|
+
}
|
|
11946
12192
|
const toolCalls = completion.toolCalls ?? [];
|
|
11947
|
-
if (
|
|
12193
|
+
if (completion.finishReason === "length") lengthReached = true;
|
|
12194
|
+
if (options.signal?.aborted && toolCalls.length === 0) {
|
|
12195
|
+
yield activeAttempt.push({ type: "stream_error", error: { name: "AbortError", message: "stream aborted" } });
|
|
12196
|
+
yield* this.settleAttempt(activeAttempt);
|
|
12197
|
+
finishReason = "cancelled";
|
|
12198
|
+
break;
|
|
12199
|
+
}
|
|
12200
|
+
if (finalTurnGranted && toolCalls.length && !options.signal?.aborted) {
|
|
12201
|
+
yield activeAttempt.push({ type: "stream_error", error: { name: "AgentError", message: "maximum turns reached" } });
|
|
12202
|
+
yield* this.settleAttempt(activeAttempt);
|
|
11948
12203
|
finishReason = "max_turns";
|
|
11949
12204
|
break;
|
|
11950
12205
|
}
|
|
11951
12206
|
const toolResults = [];
|
|
11952
12207
|
if (toolCalls.length) {
|
|
11953
|
-
|
|
12208
|
+
yield* this.settleAttempt(activeAttempt, {
|
|
11954
12209
|
content: completion.content ?? "",
|
|
11955
12210
|
toolCalls: toolCalls.map((call) => ({
|
|
11956
12211
|
id: call.id,
|
|
@@ -11971,18 +12226,30 @@ var AgentService = class {
|
|
|
11971
12226
|
if (options.signal) toolOptions.signal = options.signal;
|
|
11972
12227
|
const startedAt = Date.now();
|
|
11973
12228
|
let result;
|
|
11974
|
-
|
|
11975
|
-
result = await tools2.execute(call.name, call.arguments, toolOptions);
|
|
11976
|
-
} catch (error2) {
|
|
12229
|
+
if (options.signal?.aborted) {
|
|
11977
12230
|
result = {
|
|
11978
12231
|
ok: false,
|
|
11979
12232
|
name: call.name,
|
|
11980
12233
|
callId: call.id,
|
|
11981
12234
|
input: call.arguments,
|
|
11982
|
-
error:
|
|
12235
|
+
error: abortedToolError(options.signal),
|
|
11983
12236
|
startedAt,
|
|
11984
12237
|
durationMs: Date.now() - startedAt
|
|
11985
12238
|
};
|
|
12239
|
+
} else {
|
|
12240
|
+
try {
|
|
12241
|
+
result = await tools2.execute(call.name, call.arguments, toolOptions);
|
|
12242
|
+
} catch (error2) {
|
|
12243
|
+
result = {
|
|
12244
|
+
ok: false,
|
|
12245
|
+
name: call.name,
|
|
12246
|
+
callId: call.id,
|
|
12247
|
+
input: call.arguments,
|
|
12248
|
+
error: toToolError2(error2),
|
|
12249
|
+
startedAt,
|
|
12250
|
+
durationMs: Date.now() - startedAt
|
|
12251
|
+
};
|
|
12252
|
+
}
|
|
11986
12253
|
}
|
|
11987
12254
|
toolResults.push(result);
|
|
11988
12255
|
const toolResultPayload = {
|
|
@@ -12024,7 +12291,7 @@ var AgentService = class {
|
|
|
12024
12291
|
output = completion.content;
|
|
12025
12292
|
}
|
|
12026
12293
|
if (!toolCalls.length) {
|
|
12027
|
-
|
|
12294
|
+
yield* this.settleAttempt(activeAttempt, { content: completion.content ?? "" });
|
|
12028
12295
|
}
|
|
12029
12296
|
await session2.append("step/end", {
|
|
12030
12297
|
turn,
|
|
@@ -12035,19 +12302,19 @@ var AgentService = class {
|
|
|
12035
12302
|
currentStepIndex = void 0;
|
|
12036
12303
|
const nextMessages = this._extendMessages(llmMessages, completion, toolResults);
|
|
12037
12304
|
const concludesTurn = toolResults.some((result) => result.concludesTurn === true);
|
|
12038
|
-
|
|
12039
|
-
|
|
12040
|
-
|
|
12041
|
-
}
|
|
12042
|
-
if (toolCalls.length === 0) {
|
|
12043
|
-
finishReason = completion.finishReason === "length" ? "length" : completion.finishReason === "error" ? "error" : "stop";
|
|
12305
|
+
let nextStepMessages = await this._claimNextStepMessages();
|
|
12306
|
+
if ((toolCalls.length === 0 || concludesTurn) && nextStepMessages.length === 0) {
|
|
12307
|
+
finishReason = lengthReached ? "length" : completion.finishReason === "error" ? "error" : "stop";
|
|
12044
12308
|
const keepGoing = await this.ctx.serial("agent/turn-stopping", {
|
|
12045
12309
|
index,
|
|
12046
12310
|
turn,
|
|
12047
12311
|
steps: copySteps(steps),
|
|
12048
12312
|
finishReason
|
|
12049
12313
|
});
|
|
12050
|
-
if (!keepGoing)
|
|
12314
|
+
if (!keepGoing) {
|
|
12315
|
+
nextStepMessages = await this._claimNextStepMessages();
|
|
12316
|
+
if (nextStepMessages.length === 0) break;
|
|
12317
|
+
}
|
|
12051
12318
|
}
|
|
12052
12319
|
if (index + 1 >= maxTurns && !finalTurnGranted) {
|
|
12053
12320
|
finalTurnGranted = true;
|
|
@@ -12057,7 +12324,8 @@ var AgentService = class {
|
|
|
12057
12324
|
}
|
|
12058
12325
|
if (toolCalls.length) finishReason = "tool_calls";
|
|
12059
12326
|
index += 1;
|
|
12060
|
-
messages = nextMessages;
|
|
12327
|
+
messages = [...nextMessages, ...nextStepMessages];
|
|
12328
|
+
claimedMessages = nextStepMessages.filter((message2) => message2.role === "user");
|
|
12061
12329
|
}
|
|
12062
12330
|
} catch (error2) {
|
|
12063
12331
|
turnError = error2;
|
|
@@ -12143,23 +12411,22 @@ var AgentService = class {
|
|
|
12143
12411
|
});
|
|
12144
12412
|
return compactMessages.map((message2) => copyMessages([message2])[0]);
|
|
12145
12413
|
}
|
|
12146
|
-
async _persistStepInput(session2, request, input) {
|
|
12147
|
-
const
|
|
12148
|
-
const
|
|
12149
|
-
|
|
12150
|
-
|
|
12151
|
-
|
|
12152
|
-
|
|
12153
|
-
|
|
12154
|
-
|
|
12155
|
-
|
|
12156
|
-
|
|
12157
|
-
|
|
12158
|
-
|
|
12159
|
-
|
|
12160
|
-
|
|
12161
|
-
|
|
12162
|
-
};
|
|
12414
|
+
async _persistStepInput(session2, request, input, admittedHistory) {
|
|
12415
|
+
const surface = await session2.deriveMessages();
|
|
12416
|
+
const owned = admittedHistory.filter((message2) => !isUserOrSystemMessage(message2));
|
|
12417
|
+
let ownerIndex = 0;
|
|
12418
|
+
for (const message2 of input) {
|
|
12419
|
+
if (isUserOrSystemMessage(message2)) continue;
|
|
12420
|
+
const actual = canonicalMessages([message2]);
|
|
12421
|
+
while (ownerIndex < owned.length && canonicalMessages([owned[ownerIndex]]) !== actual) {
|
|
12422
|
+
ownerIndex += 1;
|
|
12423
|
+
}
|
|
12424
|
+
if (ownerIndex === owned.length) {
|
|
12425
|
+
throw new AgentError("request is not reconstructable from session log: unowned or reordered assistant/tool message");
|
|
12426
|
+
}
|
|
12427
|
+
ownerIndex += 1;
|
|
12428
|
+
}
|
|
12429
|
+
const nextHeader = requestHeaderFor(request, input);
|
|
12163
12430
|
const previousHeader = session2.requestHeader();
|
|
12164
12431
|
const isFirstRequest = !this._persistedRequest;
|
|
12165
12432
|
const isResume = isFirstRequest && previousHeader !== void 0;
|
|
@@ -12189,19 +12456,23 @@ var AgentService = class {
|
|
|
12189
12456
|
...request.options.provider ? { provider: request.options.provider } : {},
|
|
12190
12457
|
...request.options.model ? { model: request.options.model } : {}
|
|
12191
12458
|
};
|
|
12459
|
+
if (request.options.contextWindow !== void 0) {
|
|
12460
|
+
nextContext.contextWindow = request.options.contextWindow;
|
|
12461
|
+
}
|
|
12192
12462
|
const llmService = this.ctx.reflect.get("llm", false);
|
|
12193
12463
|
const routeCapacity = llmService?.routeCapacity?.();
|
|
12194
|
-
if (routeCapacity?.contextWindow !== void 0) {
|
|
12464
|
+
if (nextContext.contextWindow === void 0 && routeCapacity?.contextWindow !== void 0) {
|
|
12195
12465
|
nextContext.contextWindow = routeCapacity.contextWindow;
|
|
12196
12466
|
}
|
|
12197
12467
|
const previousContext = session2.requestContext();
|
|
12198
12468
|
if (previousContext?.provider !== nextContext.provider || previousContext?.model !== nextContext.model || previousContext?.contextWindow !== nextContext.contextWindow || previousContext === void 0) {
|
|
12199
12469
|
await session2.append("request/context", nextContext);
|
|
12200
12470
|
}
|
|
12201
|
-
const
|
|
12202
|
-
const
|
|
12203
|
-
const
|
|
12204
|
-
|
|
12471
|
+
const isSurfacePrefix = (messages) => canonicalMessages(messages.slice(0, surface.length)) === canonicalMessages(surface);
|
|
12472
|
+
const requested = surface.length > 0 && input[0]?.role === "system" && input[0].content === nextHeader.system && isSurfacePrefix(input.slice(1)) ? input.slice(1) : input;
|
|
12473
|
+
const tail = requested.slice(surface.length);
|
|
12474
|
+
if (isSurfacePrefix(requested) && tail.every(isUserOrSystemMessage)) {
|
|
12475
|
+
for (const message2 of tail) {
|
|
12205
12476
|
if (message2.role === "user") {
|
|
12206
12477
|
await session2.append("user/message", {
|
|
12207
12478
|
content: message2.content,
|
|
@@ -12214,45 +12485,37 @@ var AgentService = class {
|
|
|
12214
12485
|
});
|
|
12215
12486
|
}
|
|
12216
12487
|
}
|
|
12217
|
-
};
|
|
12218
|
-
if (surface.length === 0) {
|
|
12219
|
-
await appendDurable(requested);
|
|
12220
12488
|
return;
|
|
12221
12489
|
}
|
|
12222
|
-
const
|
|
12223
|
-
|
|
12224
|
-
|
|
12225
|
-
|
|
12226
|
-
|
|
12227
|
-
if (seenUsers <= durableUsers) continue;
|
|
12228
|
-
newTail.push(message2);
|
|
12229
|
-
}
|
|
12230
|
-
await appendDurable(newTail);
|
|
12490
|
+
const nodes = await session2.surfaceEvents();
|
|
12491
|
+
await session2.append("checkpoint", {
|
|
12492
|
+
messages: copyMessages(requested),
|
|
12493
|
+
surfaceOp: { op: "replace", start: nodes[0].seq, end: nodes.at(-1).seq }
|
|
12494
|
+
});
|
|
12231
12495
|
}
|
|
12232
|
-
async _assertReplayable(session2, input) {
|
|
12496
|
+
async _assertReplayable(session2, request, input) {
|
|
12233
12497
|
const reconstructed = await session2.deriveMessages();
|
|
12234
|
-
const
|
|
12235
|
-
|
|
12236
|
-
|
|
12237
|
-
|
|
12238
|
-
|
|
12239
|
-
...message2.tool_calls?.length ? { tool_calls: message2.tool_calls.map((call) => ({
|
|
12240
|
-
id: call.id,
|
|
12241
|
-
name: call.name,
|
|
12242
|
-
args: JSON.stringify(call.arguments ?? {})
|
|
12243
|
-
})) } : {}
|
|
12244
|
-
}));
|
|
12245
|
-
const actual = canonical(input);
|
|
12246
|
-
const replay = canonical(reconstructed);
|
|
12247
|
-
if (JSON.stringify(actual) !== JSON.stringify(replay)) {
|
|
12498
|
+
const actual = canonicalMessages(input);
|
|
12499
|
+
const replay = canonicalMessages(reconstructed);
|
|
12500
|
+
const header = session2.requestHeader();
|
|
12501
|
+
const headerOwnsPrefix = input[0]?.role === "system" && input[0].content === header?.system && canonicalMessages(input.slice(1)) === replay;
|
|
12502
|
+
if (actual !== replay && !headerOwnsPrefix) {
|
|
12248
12503
|
throw new AgentError(
|
|
12249
|
-
`request is not reconstructable from session log: actual=${
|
|
12504
|
+
`request is not reconstructable from session log: actual=${actual} replay=${replay}`
|
|
12250
12505
|
);
|
|
12251
12506
|
}
|
|
12507
|
+
const expected = requestHeaderFor(request, input);
|
|
12508
|
+
if (header?.system !== expected.system || JSON.stringify(header?.tools ?? []) !== JSON.stringify(expected.tools ?? []) || JSON.stringify(header?.config ?? {}) !== JSON.stringify(expected.config ?? {})) {
|
|
12509
|
+
throw new AgentError("request envelope is not reconstructable from session log");
|
|
12510
|
+
}
|
|
12511
|
+
}
|
|
12512
|
+
async _claimNextStepMessages() {
|
|
12513
|
+
const inputs = await this.config.claimNextStep?.() ?? [];
|
|
12514
|
+
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) }] : []);
|
|
12252
12515
|
}
|
|
12253
12516
|
async _initialMessages(input) {
|
|
12254
12517
|
const promptService = this.ctx.reflect.get("systemPrompt", false);
|
|
12255
|
-
const assembled = promptService ? (await promptService.assemble()).text.trim() : void 0;
|
|
12518
|
+
const assembled = promptService ? (await promptService.assemble({}, this.ctx)).text.trim() : void 0;
|
|
12256
12519
|
const systemPrompt = assembled || this.inbox.injected().get("agentSystem");
|
|
12257
12520
|
const systemMessage = typeof systemPrompt === "string" && systemPrompt ? [{ role: "system", content: systemPrompt }] : [];
|
|
12258
12521
|
if (input.messages?.length) {
|
|
@@ -12277,7 +12540,7 @@ var AgentService = class {
|
|
|
12277
12540
|
arguments: call.arguments
|
|
12278
12541
|
}));
|
|
12279
12542
|
}
|
|
12280
|
-
next.push(assistant);
|
|
12543
|
+
if (assistant.content || toolCalls.length) next.push(assistant);
|
|
12281
12544
|
for (const call of toolCalls) {
|
|
12282
12545
|
const result = toolResults.find((candidate) => candidate.callId === call.id);
|
|
12283
12546
|
const content = result ? result.ok ? stringify2(result.output) : `error: ${result.error?.message ?? "unknown"}` : "error: missing tool result";
|
|
@@ -12307,7 +12570,8 @@ var AgentService = class {
|
|
|
12307
12570
|
return session2;
|
|
12308
12571
|
}
|
|
12309
12572
|
_tools() {
|
|
12310
|
-
const
|
|
12573
|
+
const scoped = this.ctx.reflect.get("tools", false);
|
|
12574
|
+
const tools2 = scoped ?? this.ctx.tools;
|
|
12311
12575
|
if (!tools2) throw new AgentError("tools service is required");
|
|
12312
12576
|
return tools2;
|
|
12313
12577
|
}
|