mirror of
https://github.com/getpaseo/paseo.git
synced 2026-10-30 21:23:04 +00:00
* fix(plugin): continue one timeline item across ACP chunks without messageId The plugin ACP reducer minted a new fallback id for every agent_message_chunk / agent_thought_chunk that carried no messageId, so a streamed reply rendered as one block per chunk, splitting words and Markdown delimiters (#4699). Keep one fallback id per chunk kind and end it on a chunk of the other kind, a tool call, a plan, a user message, or a turn boundary, matching the server-side ACP provider. * fix(plugin): end the other chunk kind's item on any chunk A chunk of one kind now ends the other kind's fallback item before the content or id is looked at, so an explicit-id text chunk between two id-less thoughts yields three items instead of merging the thoughts. The test declares the streamed updates through the connector harness instead of handling protocol frames itself. * test(plugin): verify ACP message boundaries and rendered Markdown * test(app): synchronize rewind setup and menu selection --------- Co-authored-by: Mohamed Boudra <boudra.moha@gmail.com>
47 lines
1.6 KiB
TypeScript
47 lines
1.6 KiB
TypeScript
import type { PluginServerContext } from "@getpaseo/plugin/server";
|
|
import { runAcpProvider, type AcpStreamMessage } from "@getpaseo/plugin/server/acp";
|
|
|
|
function connect() {
|
|
let controller: ReadableStreamDefaultController<AcpStreamMessage>;
|
|
return {
|
|
readable: new ReadableStream<AcpStreamMessage>({
|
|
start(value) {
|
|
controller = value;
|
|
},
|
|
}),
|
|
writable: new WritableStream<AcpStreamMessage>({
|
|
write(message) {
|
|
if (!("method" in message) || !("id" in message)) return;
|
|
let result: unknown = {};
|
|
if (message.method === "initialize") result = { protocolVersion: 1, agentCapabilities: {} };
|
|
if (message.method === "session/new") result = { sessionId: "chunks" };
|
|
if (message.method === "session/prompt") {
|
|
for (const text of [
|
|
"- **Current tem",
|
|
"perature**: 25°C. Read [Paseo ",
|
|
"docs](https://example.com/docs).",
|
|
]) {
|
|
controller.enqueue({
|
|
jsonrpc: "2.0",
|
|
method: "session/update",
|
|
params: {
|
|
sessionId: "chunks",
|
|
update: { sessionUpdate: "agent_message_chunk", content: { type: "text", text } },
|
|
},
|
|
});
|
|
}
|
|
result = { stopReason: "end_turn" };
|
|
}
|
|
controller.enqueue({ jsonrpc: "2.0", id: message.id, result });
|
|
},
|
|
}),
|
|
};
|
|
}
|
|
|
|
export default function contribute(server: PluginServerContext) {
|
|
server.registerProvider(
|
|
runAcpProvider({ id: "acp-chunks", label: "ACP chunks", connector: connect }),
|
|
);
|
|
return () => {};
|
|
}
|