Auto-reply: smarter chunking breaks
This commit is contained in:
@@ -62,7 +62,7 @@ describe("agent buildArgs + parseOutput helpers", () => {
|
||||
'{"type":"message_end","message":{"role":"assistant","content":[{"type":"text","text":"hello world"}],"usage":{"input":10,"output":5},"model":"pi-1","provider":"inflection","stopReason":"end"}}',
|
||||
].join("\n");
|
||||
const parsed = piSpec.parseOutput(stdout);
|
||||
expect(parsed.text).toBe("hello world");
|
||||
expect(parsed.texts?.[0]).toBe("hello world");
|
||||
expect(parsed.meta?.provider).toBe("inflection");
|
||||
expect((parsed.meta?.usage as { output?: number })?.output).toBe(5);
|
||||
});
|
||||
@@ -73,7 +73,7 @@ describe("agent buildArgs + parseOutput helpers", () => {
|
||||
'{"type":"turn.completed","usage":{"input_tokens":50,"output_tokens":10,"cached_input_tokens":5}}',
|
||||
].join("\n");
|
||||
const parsed = codexSpec.parseOutput(stdout);
|
||||
expect(parsed.text).toBe("hi there");
|
||||
expect(parsed.texts?.[0]).toBe("hi there");
|
||||
const usage = parsed.meta?.usage as {
|
||||
input?: number;
|
||||
output?: number;
|
||||
@@ -93,7 +93,7 @@ describe("agent buildArgs + parseOutput helpers", () => {
|
||||
'{"type":"step_finish","timestamp":1200,"part":{"cost":0.002,"tokens":{"input":100,"output":20}}}',
|
||||
].join("\n");
|
||||
const parsed = opencodeSpec.parseOutput(stdout);
|
||||
expect(parsed.text).toBe("hi");
|
||||
expect(parsed.texts?.[0]).toBe("hi");
|
||||
expect(parsed.meta?.extra?.summary).toContain("duration=1200ms");
|
||||
expect(parsed.meta?.extra?.summary).toContain("cost=$0.0020");
|
||||
expect(parsed.meta?.extra?.summary).toContain("tokens=100+20");
|
||||
|
||||
@@ -14,11 +14,10 @@ type PiAssistantMessage = {
|
||||
function parsePiJson(raw: string): AgentParseResult {
|
||||
const lines = raw.split(/\n+/).filter((l) => l.trim().startsWith("{"));
|
||||
|
||||
// Collect every assistant message we see; Tau in RPC mode can emit multiple
|
||||
// assistant payloads in one run (e.g., queued turns, heartbeats). We concatenate
|
||||
// all text blocks so users see everything instead of only the last message_end.
|
||||
// Collect only completed assistant messages (skip streaming updates/toolcalls).
|
||||
const texts: string[] = [];
|
||||
let lastAssistant: PiAssistantMessage | undefined;
|
||||
let lastPushed: string | undefined;
|
||||
|
||||
for (const line of lines) {
|
||||
try {
|
||||
@@ -26,15 +25,24 @@ function parsePiJson(raw: string): AgentParseResult {
|
||||
type?: string;
|
||||
message?: PiAssistantMessage;
|
||||
};
|
||||
const msg = ev.message;
|
||||
if (msg?.role === "assistant" && Array.isArray(msg.content)) {
|
||||
const msgText = msg.content
|
||||
.filter((c) => c?.type === "text" && typeof c.text === "string")
|
||||
.map((c) => c.text)
|
||||
.join("\n")
|
||||
.trim();
|
||||
if (msgText) texts.push(msgText);
|
||||
// keep meta from the most recent assistant message
|
||||
|
||||
const isAssistantMessage =
|
||||
(ev.type === "message" || ev.type === "message_end") &&
|
||||
ev.message?.role === "assistant" &&
|
||||
Array.isArray(ev.message.content);
|
||||
|
||||
if (!isAssistantMessage) continue;
|
||||
|
||||
const msg = ev.message as PiAssistantMessage;
|
||||
const msgText = msg.content
|
||||
?.filter((c) => c?.type === "text" && typeof c.text === "string")
|
||||
.map((c) => c.text)
|
||||
.join("\n")
|
||||
.trim();
|
||||
|
||||
if (msgText && msgText !== lastPushed) {
|
||||
texts.push(msgText);
|
||||
lastPushed = msgText;
|
||||
lastAssistant = msg;
|
||||
}
|
||||
} catch {
|
||||
@@ -42,12 +50,8 @@ function parsePiJson(raw: string): AgentParseResult {
|
||||
}
|
||||
}
|
||||
|
||||
// Combine all assistant text messages (ignore tool calls/partials). This keeps
|
||||
// multi-message replies intact while dropping non-text events.
|
||||
const text = texts.length ? texts.join("\n\n").trim() : undefined;
|
||||
|
||||
const meta: AgentMeta | undefined =
|
||||
text && lastAssistant
|
||||
lastAssistant && texts.length
|
||||
? {
|
||||
model: lastAssistant.model,
|
||||
provider: lastAssistant.provider,
|
||||
|
||||
@@ -16,6 +16,7 @@ export type AgentMeta = {
|
||||
};
|
||||
|
||||
export type AgentParseResult = {
|
||||
// Plural to support agents that emit multiple assistant turns per prompt.
|
||||
texts?: string[];
|
||||
mediaUrls?: string[];
|
||||
meta?: AgentMeta;
|
||||
|
||||
Reference in New Issue
Block a user