pi-mono/packages/coding-agent/test/interactive-mode-bug-report-hint.test.ts
Armin Ronacher 1965a80693 fix(coding-agent,durable): fix CI test stub and macOS watch startup race
The bug report hint test stubbed InteractiveMode without the new
maybeShowInstallChangeWarning method.

On macOS fs.watch returns before libuv's FSEvents stream is live, so
changes made right after starting a watch could be lost. Rescan once
after installing native watchers there.
2026-10-05 00:02:59 +02:00

71 lines
2.8 KiB
TypeScript

import { type AssistantMessage, fauxAssistantMessage } from "@earendil-works/pi-ai";
import { describe, expect, test, vi } from "vitest";
import { formatCrashExtensionHint, InteractiveMode } from "../src/modes/interactive/interactive-mode.ts";
type BugReportHintContext = {
suggestBugReport(): void;
maybeShowInstallChangeWarning(): boolean;
};
const maybeSuggestBugReport = Reflect.get(InteractiveMode.prototype, "maybeSuggestBugReport") as (
this: BugReportHintContext,
message: AssistantMessage,
) => void;
function errorMessage(errorMessage: string): AssistantMessage {
return fauxAssistantMessage("", { stopReason: "error", errorMessage });
}
describe("InteractiveMode bug report hints", () => {
test("identifies extensions with frames in a crash stack", () => {
expect(formatCrashExtensionHint(["npm:pi-observational-memory"])).toBe(
"A stack frame came from loaded extension `npm:pi-observational-memory`, which may be involved. Try disabling it with `pi config`, or run `pi -ne` to confirm.",
);
expect(formatCrashExtensionHint(undefined)).toBeUndefined();
});
test("does not suggest reports for retryable provider failures", () => {
const context = { suggestBugReport: vi.fn(), maybeShowInstallChangeWarning: vi.fn(() => false) };
const failures = [
"500 Internal Server Error",
"502 Bad Gateway",
"503 Service Unavailable",
"504 Gateway Timeout",
"429 Too Many Requests",
"Provider overloaded",
"Network connection lost",
"Request timed out",
];
for (const failure of failures) maybeSuggestBugReport.call(context, errorMessage(failure));
expect(context.suggestBugReport).not.toHaveBeenCalled();
});
test("does not suggest reports for cancellations", () => {
const context = { suggestBugReport: vi.fn(), maybeShowInstallChangeWarning: vi.fn(() => false) };
maybeSuggestBugReport.call(context, errorMessage("This operation was aborted"));
maybeSuggestBugReport.call(context, errorMessage("Request cancelled"));
maybeSuggestBugReport.call(context, fauxAssistantMessage("", { stopReason: "aborted" }));
expect(context.suggestBugReport).not.toHaveBeenCalled();
});
test("suggests reports for unexpected errors", () => {
const context = { suggestBugReport: vi.fn(), maybeShowInstallChangeWarning: vi.fn(() => false) };
maybeSuggestBugReport.call(context, errorMessage("Unexpected internal state"));
expect(context.suggestBugReport).toHaveBeenCalledOnce();
});
test("shows the install change warning instead of a bug report hint", () => {
const context = { suggestBugReport: vi.fn(), maybeShowInstallChangeWarning: vi.fn(() => true) };
maybeSuggestBugReport.call(context, errorMessage("Cannot find module './worker.js'"));
expect(context.maybeShowInstallChangeWarning).toHaveBeenCalledOnce();
expect(context.suggestBugReport).not.toHaveBeenCalled();
});
});