feat: add ephemeral /btw side-question panel (#399)
* feat: add ephemeral /btw side-question panel * fix: preserve /btw live context and payload hooks * fix: send /btw question through session pipeline
This commit is contained in:
@@ -0,0 +1,93 @@
|
||||
import { afterEach, describe, expect, it, vi } from "bun:test";
|
||||
import { Agent, type AgentMessage } from "@oh-my-pi/pi-agent-core";
|
||||
import type { Message, SimpleStreamOptions } from "@oh-my-pi/pi-ai";
|
||||
import { Settings } from "@oh-my-pi/pi-coding-agent/config/settings";
|
||||
import { AgentSession } from "@oh-my-pi/pi-coding-agent/session/agent-session";
|
||||
import { SessionManager } from "@oh-my-pi/pi-coding-agent/session/session-manager";
|
||||
|
||||
function createAgent(): Agent {
|
||||
return new Agent({
|
||||
initialState: {
|
||||
systemPrompt: "system prompt",
|
||||
messages: [],
|
||||
tools: [],
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
describe("AgentSession message pipeline", () => {
|
||||
const sessions: AgentSession[] = [];
|
||||
|
||||
afterEach(async () => {
|
||||
vi.restoreAllMocks();
|
||||
for (const session of sessions.splice(0)) {
|
||||
await session.dispose();
|
||||
}
|
||||
});
|
||||
|
||||
it("applies transformContext before convertToLlm", async () => {
|
||||
const inputMessages: AgentMessage[] = [{ role: "user", content: "hello", timestamp: Date.now() }];
|
||||
const transformedMessages: AgentMessage[] = [
|
||||
...inputMessages,
|
||||
{ role: "user", content: "injected context", timestamp: Date.now() },
|
||||
];
|
||||
const convertedMessages: Message[] = [
|
||||
{
|
||||
role: "user",
|
||||
content: [{ type: "text", text: "converted" }],
|
||||
attribution: "user",
|
||||
timestamp: Date.now(),
|
||||
},
|
||||
];
|
||||
const transformContext = vi.fn(async (messages: AgentMessage[], signal?: AbortSignal) => {
|
||||
expect(signal).toBe(abortController.signal);
|
||||
return [...messages, ...transformedMessages.slice(messages.length)];
|
||||
});
|
||||
const convertToLlm = vi.fn(async (_messages: AgentMessage[]) => {
|
||||
return convertedMessages;
|
||||
});
|
||||
const abortController = new AbortController();
|
||||
const session = new AgentSession({
|
||||
agent: createAgent(),
|
||||
sessionManager: SessionManager.inMemory(),
|
||||
settings: Settings.isolated({ "compaction.enabled": false }),
|
||||
modelRegistry: {} as never,
|
||||
transformContext,
|
||||
convertToLlm,
|
||||
});
|
||||
sessions.push(session);
|
||||
|
||||
const result = await session.convertMessagesToLlm(inputMessages, abortController.signal);
|
||||
|
||||
expect(transformContext).toHaveBeenCalledWith(inputMessages, abortController.signal);
|
||||
expect(convertToLlm).toHaveBeenCalledWith(transformedMessages);
|
||||
expect(result).toEqual(convertedMessages);
|
||||
});
|
||||
|
||||
it("composes session payload hooks into direct side-request options", async () => {
|
||||
const sessionOnPayload = vi.fn(async (payload: unknown) => ({
|
||||
...(payload as Record<string, unknown>),
|
||||
session: true,
|
||||
}));
|
||||
const requestOnPayload = vi.fn(async () => undefined);
|
||||
const session = new AgentSession({
|
||||
agent: createAgent(),
|
||||
sessionManager: SessionManager.inMemory(),
|
||||
settings: Settings.isolated({ "compaction.enabled": false }),
|
||||
modelRegistry: {} as never,
|
||||
onPayload: sessionOnPayload,
|
||||
});
|
||||
sessions.push(session);
|
||||
const options: SimpleStreamOptions = {
|
||||
apiKey: "key",
|
||||
onPayload: requestOnPayload,
|
||||
};
|
||||
|
||||
const prepared = session.prepareSimpleStreamOptions(options);
|
||||
const result = await prepared.onPayload?.({ original: true });
|
||||
|
||||
expect(sessionOnPayload).toHaveBeenCalledWith({ original: true }, undefined);
|
||||
expect(requestOnPayload).toHaveBeenCalledWith({ original: true, session: true }, undefined);
|
||||
expect(result).toEqual({ original: true, session: true });
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user