-
Notifications
You must be signed in to change notification settings - Fork 48
Expand file tree
/
Copy pathCodexAcpClient.test.ts
More file actions
109 lines (87 loc) · 4.93 KB
/
Copy pathCodexAcpClient.test.ts
File metadata and controls
109 lines (87 loc) · 4.93 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
import {describe, expect, it, vi, beforeEach} from 'vitest';
import type {CodexAuthRequest} from "../../CodexAuthMethod";
import {createTestFixture, type TestFixture} from "../acp-test-utils";
import type {ServerNotification} from "../../app-server";
import type {SessionState} from "../../CodexAcpServer";
describe('ACP server test', () => {
let fixture: TestFixture;
beforeEach(() => {
fixture = createTestFixture();
vi.clearAllMocks();
});
const ignoredFields = ["thread", "cwd", "id", "createdAt", "path", "threadId", "userAgent", "sandbox", "reasoningEffort", "conversationId"];
it('should start conversation', async () => {
const codexAcpAgent = fixture.getCodexAcpAgent();
await codexAcpAgent.initialize({protocolVersion: 1});
fixture.getCodexAcpClient().authRequired = vi.fn().mockResolvedValue(false);
const newSessionResponse = await codexAcpAgent.newSession({cwd: "", mcpServers: []});
codexAcpAgent.prompt({ sessionId: newSessionResponse.sessionId, prompt: [{type: "text", text: "Hi!"}] });
const transportDump = fixture.getCodexConnectionDump(ignoredFields);
await expect(transportDump).toMatchFileSnapshot("data/start-conversation.json");
});
it('should throw error without authentication', async () => {
const codexAcpAgent = fixture.getCodexAcpAgent();
await codexAcpAgent.initialize({protocolVersion: 1});
await fixture.getCodexAcpClient().logout();
fixture.clearCodexConnectionDump();
await expect(
codexAcpAgent.newSession({cwd: "", mcpServers: []})
).rejects.toThrow("Authentication required");
const transportDump = fixture.getCodexConnectionDump(ignoredFields);
await expect(transportDump).toMatchFileSnapshot("data/auth-failed.json");
});
it('should authenticate with key', async () => {
const codexAcpAgent = fixture.getCodexAcpAgent();
await codexAcpAgent.initialize({protocolVersion: 1});
await fixture.getCodexAcpClient().logout();
fixture.clearCodexConnectionDump();
const authRequest: CodexAuthRequest = { methodId: "api-key", _meta: {apiKey: "TOKEN"} }
await codexAcpAgent.authenticate(authRequest);
const newSessionResponse = await codexAcpAgent.newSession({cwd: "", mcpServers: []});
expect(newSessionResponse.sessionId).toBeDefined()
const transportDump = fixture.getCodexConnectionDump(ignoredFields);
await expect(transportDump).toMatchFileSnapshot("data/auth-with-key.json");
});
function loadNotifications(){
//TODO collect logs form dev run and then load them from file to speedup
const serverNotifications: ServerNotification[] = [
{ method: "item/agentMessage/delta", params: { threadId: "string", turnId: "string", itemId: "string", delta: "He", }},
{ method: "item/agentMessage/delta", params: { threadId: "string", turnId: "string", itemId: "string", delta: "ll", }},
{ method: "item/agentMessage/delta", params: { threadId: "string", turnId: "string", itemId: "string", delta: "o!", }},
];
function onServerNotification(callback: (event: ServerNotification) => void){
for (const notification of serverNotifications) {
callback(notification);
}
}
return onServerNotification;
}
it('should map events from dump', async () => {
fixture.getCodexAppServerClient().onServerNotification = loadNotifications();
const codexAcpAgent = fixture.getCodexAcpAgent();
fixture.getCodexAppServerClient().turnStart = vi.fn().mockResolvedValue(undefined);
fixture.getCodexAppServerClient().awaitTurnCompleted = vi.fn().mockResolvedValue(undefined);
const sessionState: SessionState = {
pendingPrompt: null,
sessionMetadata: {
sessionId: "id",
currentModelId: "model-id",
models: [],
}
};
vi.spyOn(codexAcpAgent, "getSessionState").mockReturnValue(sessionState);
await codexAcpAgent.prompt({ sessionId: "id", prompt: [{type: "text", text: ""}] });
expect(fixture.getAcpConnectionDump([])).toMatchFileSnapshot("data/output-acp-events.json");
}, 90_000);
//dev-time test
it.skip('should convert session notification to acp events', async () => {
fixture.onCodexConnectionEvent((event) => {
console.log(JSON.stringify(event, null, 2));
});
const codexAcpAgent = fixture.getCodexAcpAgent();
await codexAcpAgent.initialize({protocolVersion: 1});
const newSessionResponse = await codexAcpAgent.newSession({cwd: "/home/alex/work/spring-petclinic/", mcpServers: []});
fixture.clearCodexConnectionDump();
await codexAcpAgent.prompt({ sessionId: newSessionResponse.sessionId, prompt: [{type: "text", text: "Add method `minus` to Math Utils."}] });
}, 90_000);
});