Archived
refactor: generate session names via agent.streamFn instead of pi-ai compat
Rewrite sessionNameGenerator.ts to consume a StreamFn-shaped dependency (sourced from PiAgentSession.agent.streamFn, wired in leg B) instead of ModelRegistry plus a dynamic @earendil-works/pi-ai/compat import. streamFn resolves auth/headers/retry internally, so the explicit modelRegistry.getApiKeyAndHeaders(model) call and apiKey/headers stream options are no longer needed. Deletes now-dead compat-loading machinery: getPiAiProviderRegistryModule, loadPiAiProviderRegistryModule, importOptionalPiAiModule, isModuleUnavailableError, hasGetApiProvider, PI_AI_COMPAT_MODULE, ModuleImporter, SessionNameApiProvider, PiAiProviderRegistryModule, and the module-level provider registry cache. Updates the maybeGenerateSessionName call site in piSessionService.ts to pass session.agent.streamFn instead of this.modelRegistry, and updates both test files: sessionNameGenerator.test.ts gains coverage for the new streamFn-driven generateShortSessionName signature (success and error paths), and piSessionService.test.ts gains an end-to-end test proving a first prompt generates a session name through the wired agent.streamFn fake. sessionNameGenerator.ts no longer imports @earendil-works/pi-ai/compat or references getApiProvider anywhere.
This commit is contained in:
@@ -1,6 +1,8 @@
|
||||
import { mkdtemp, rm, writeFile } from "node:fs/promises";
|
||||
import { tmpdir } from "node:os";
|
||||
import { join } from "node:path";
|
||||
import { createAssistantMessageEventStream, type AssistantMessage } from "@earendil-works/pi-ai";
|
||||
import type { StreamFn } from "@earendil-works/pi-agent-core";
|
||||
import { AuthStorage, ModelRegistry } from "@earendil-works/pi-coding-agent";
|
||||
import { describe, expect, it, vi } from "vitest";
|
||||
import type { GlobalSessionEvent, SessionUiEvent } from "../../shared/apiTypes.js";
|
||||
@@ -938,6 +940,42 @@ describe("PiSessionService", () => {
|
||||
await service.dispose();
|
||||
});
|
||||
|
||||
it("generates a session name for the first prompt via the session's agent.streamFn", async () => {
|
||||
const model = testModel();
|
||||
const streamCalls: unknown[] = [];
|
||||
const streamFn: StreamFn = (streamModel, context, options) => {
|
||||
streamCalls.push({ streamModel, context, options });
|
||||
const stream = createAssistantMessageEventStream();
|
||||
const message: AssistantMessage = {
|
||||
role: "assistant",
|
||||
content: [{ type: "text", text: "Fix login bug" }],
|
||||
api: "anthropic-messages",
|
||||
provider: "anthropic",
|
||||
model: model.id,
|
||||
usage: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, totalTokens: 0, cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 } },
|
||||
stopReason: "stop",
|
||||
timestamp: Date.now(),
|
||||
};
|
||||
stream.push({ type: "done", reason: "stop", message });
|
||||
stream.end(message);
|
||||
return stream;
|
||||
};
|
||||
const hub = new CapturingSessionEventHub();
|
||||
const fake = fakeRuntime("name-session", { model, agent: { streamFn } });
|
||||
const service = new PiSessionService(hub, {
|
||||
createAgentRuntime: runtimeCreator(fake.runtime),
|
||||
sessionManager: sessionGateway([sessionRecord("name-session")]),
|
||||
heartbeatIntervalMs: 60_000,
|
||||
});
|
||||
|
||||
await service.prompt(sessionRef("name-session"), "Please fix the login bug");
|
||||
await vi.waitFor(() => { expect(fake.session.sessionName).toBe("Fix login bug"); });
|
||||
|
||||
expect(streamCalls).toHaveLength(1);
|
||||
expect(hub.sessionEvents.some(({ event }) => event.type === "session.name" && event.name === "Fix login bug")).toBe(true);
|
||||
await service.dispose();
|
||||
});
|
||||
|
||||
it("includes queued message details in session status", async () => {
|
||||
const fake = fakeRuntime("status-session", {
|
||||
messages: [{ role: "user", content: "hello" }, { role: "assistant", content: "hi" }],
|
||||
|
||||
Reference in New Issue
Block a user