14252e71cb
Fix all Windows-specific test failures caused by path handling problems
and EBUSY errors from unclosed SQLite database handles.
Root causes fixed:
1. POSIX path assumptions: replaced hard-coded file:///tmp, /repo, etc.
with pathToFileURL/path.resolve/path.join computed expectations
2. shortenPath() now normalizes backslashes to forward slashes after ~
and respects home directory boundaries
3. HistoryStorage.resetInstance() leaked its Database — added #close()
that finalizes all prepared statements and closes the DB
4. AgentStorage gained the same resetInstance()/#close() pattern
5. SqliteAuthCredentialStore.close() leaked one-off prepared statements
from inline this.#db.prepare() calls — wrapped each in try/finally
6. model-cache.ts used a process-global DB even for custom dbPath —
now opens/closes per-call via withModelCacheDb
7. createAgentSession leaked AuthStorage on construction failure —
added ownsAuthStorage cleanup in catch block
8. MnemopiBackend.removeDbFiles() now truly best-effort (catches errors)
9. TempDir retry window expanded from 4x10ms to 40x25ms
10. TempDir prefix convention: non-@ prefixes created dirs relative to
cwd instead of os.tmpdir() — all test temp dirs now use @ prefix
11. Shell-escaped interpolated paths in bash tool tests
12. git core.autocrlf false in autoresearch test repo init
All 522 previously-failing Windows tests now pass.
78 lines
2.9 KiB
TypeScript
78 lines
2.9 KiB
TypeScript
/**
|
|
* Regression test for issue #1234.
|
|
*
|
|
* `omp acp` must not auto-discover host `.mcp.json` servers when creating a
|
|
* session for an ACP client. MCP server ownership belongs entirely to the ACP
|
|
* client (`session/new.mcpServers` → `AcpAgent#configureMcpServers`); letting
|
|
* `createAgentSession` run on-disk discovery in parallel registers host MCP
|
|
* tools that shadow the client-supplied ones in the session tool registry.
|
|
*
|
|
* The contract enforced here is narrow on purpose: every call routed through
|
|
* the ACP session factory must reach `createAgentSession` with
|
|
* `enableMCP: false`, regardless of what `baseOptions` carries.
|
|
*/
|
|
|
|
import { describe, expect, it } from "bun:test";
|
|
import { ModelRegistry } from "@oh-my-pi/pi-coding-agent/config/model-registry";
|
|
import { Settings } from "@oh-my-pi/pi-coding-agent/config/settings";
|
|
import { createAcpSessionFactory } from "@oh-my-pi/pi-coding-agent/main";
|
|
import type { CreateAgentSessionOptions, CreateAgentSessionResult } from "@oh-my-pi/pi-coding-agent/sdk";
|
|
import type { AgentSession } from "@oh-my-pi/pi-coding-agent/session/agent-session";
|
|
import { AuthStorage } from "@oh-my-pi/pi-coding-agent/session/auth-storage";
|
|
import { TempDir } from "@oh-my-pi/pi-utils";
|
|
|
|
describe("createAcpSessionFactory MCP isolation (issue #1234)", () => {
|
|
it("forces enableMCP=false even when baseOptions opts in", async () => {
|
|
const tempDir = TempDir.createSync("@pi-acp-mcp-isolation-");
|
|
let authStorage: AuthStorage | undefined;
|
|
try {
|
|
authStorage = await AuthStorage.create(tempDir.join("auth.db"));
|
|
const modelRegistry = new ModelRegistry(authStorage);
|
|
const settings = Settings.isolated({});
|
|
const fakeSession = {} as AgentSession;
|
|
const captured: CreateAgentSessionOptions[] = [];
|
|
const createSession = async (options: CreateAgentSessionOptions): Promise<CreateAgentSessionResult> => {
|
|
captured.push(options);
|
|
return {
|
|
session: fakeSession,
|
|
extensionsResult: {
|
|
extensions: [],
|
|
errors: [],
|
|
runner: undefined,
|
|
} as unknown as CreateAgentSessionResult["extensionsResult"],
|
|
setToolUIContext: () => {},
|
|
eventBus: {
|
|
emit: () => {},
|
|
on: () => () => {},
|
|
off: () => {},
|
|
} as unknown as CreateAgentSessionResult["eventBus"],
|
|
};
|
|
};
|
|
|
|
// baseOptions deliberately sets enableMCP=true to prove the factory ignores it.
|
|
const factory = createAcpSessionFactory({
|
|
baseOptions: { enableMCP: true } as CreateAgentSessionOptions,
|
|
settings,
|
|
sessionDir: tempDir.join("sessions"),
|
|
authStorage,
|
|
modelRegistry,
|
|
parsedArgs: {},
|
|
rawArgs: [],
|
|
createSession,
|
|
});
|
|
|
|
const result = await factory(tempDir.path());
|
|
expect(result).toBe(fakeSession);
|
|
expect(captured).toHaveLength(1);
|
|
expect(captured[0].enableMCP).toBe(false);
|
|
} finally {
|
|
try {
|
|
authStorage?.close();
|
|
} finally {
|
|
await Bun.sleep(0);
|
|
await tempDir.remove();
|
|
}
|
|
}
|
|
});
|
|
});
|