UNPKG

@sema-agent/core

Version:

Stateless, task-oriented AI agent core

41 lines (40 loc) • 2.21 kB
import { deliverEngineNotice } from "../engine-notice.js"; import { readMember } from "../thrown-value.js"; export function createFinishReasonSeat(onNotice, ids) { const announced = new Set(); const once = (key) => { if (announced.has(key)) return false; announced.add(key); return true; }; return { observe(message) { const word = readMember(message, "finishReasonUnknown"); if (typeof word === "string" && once(`unknown\u0000${word}`)) { deliverEngineNotice(onNotice, { code: "route.finish_reason_unknown", message: `The provider ended a response with "${word}", a finish reason this engine does not read. The turn was kept ` + `as the model left it, but the provider may have cut it short — the text above may be incomplete.`, detail: { finishReason: word, sessionId: ids.sessionId, runId: ids.runId }, }); } const late = readMember(message, "streamEndIgnored"); const statement = readMember(late, "statement"); const lateWord = readMember(late, "word"); const frames = readMember(late, "frames"); if ((statement === "ending" || statement === "error" || statement === "content") && typeof lateWord === "string" && typeof frames === "number" && once(`late\u0000${statement}\u0000${lateWord}`)) { const what = statement === "error" ? `an error "${lateWord}"` : statement === "ending" ? `the ending "${lateWord}"` : `${lateWord} content`; deliverEngineNotice(onNotice, { code: "route.stream_end_ignored", message: `After the provider had already ended a response, its stream sent more (first: ${what}; ${frames} frame${frames === 1 ? "" : "s"} in all). ` + `The first ending stands; nothing after it was added to the turn.`, detail: { statement, word: lateWord, frames, sessionId: ids.sessionId, runId: ids.runId }, }); } }, }; }