@ai-devkit/agent-manager 0.35.0 → 0.36.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/__tests__/adapters/AntigravityCliAdapter.test.js +381 -0
- package/dist/__tests__/adapters/AntigravityCliAdapter.test.js.map +1 -0
- package/dist/__tests__/adapters/KiroAdapter.test.js +607 -0
- package/dist/__tests__/adapters/KiroAdapter.test.js.map +1 -0
- package/dist/__tests__/capacity/claude.test.js +485 -0
- package/dist/__tests__/capacity/claude.test.js.map +1 -0
- package/dist/__tests__/capacity/openai.test.js +672 -0
- package/dist/__tests__/capacity/openai.test.js.map +1 -0
- package/dist/__tests__/capacity/wham.test.js +144 -0
- package/dist/__tests__/capacity/wham.test.js.map +1 -0
- package/dist/__tests__/utils/agents.test.js +6 -0
- package/dist/__tests__/utils/agents.test.js.map +1 -1
- package/dist/adapters/AgentAdapter.d.ts +1 -1
- package/dist/adapters/AgentAdapter.d.ts.map +1 -1
- package/dist/adapters/AgentAdapter.js.map +1 -1
- package/dist/adapters/AntigravityCliAdapter.d.ts +57 -0
- package/dist/adapters/AntigravityCliAdapter.d.ts.map +1 -0
- package/dist/adapters/AntigravityCliAdapter.js +273 -0
- package/dist/adapters/AntigravityCliAdapter.js.map +1 -0
- package/dist/adapters/KiroAdapter.d.ts +46 -0
- package/dist/adapters/KiroAdapter.d.ts.map +1 -0
- package/dist/adapters/KiroAdapter.js +344 -0
- package/dist/adapters/KiroAdapter.js.map +1 -0
- package/dist/adapters/index.d.ts +2 -0
- package/dist/adapters/index.d.ts.map +1 -1
- package/dist/adapters/index.js +2 -0
- package/dist/adapters/index.js.map +1 -1
- package/dist/capacity/claude.d.ts +17 -0
- package/dist/capacity/claude.d.ts.map +1 -0
- package/dist/capacity/claude.js +271 -0
- package/dist/capacity/claude.js.map +1 -0
- package/dist/capacity/codex.d.ts +1 -2
- package/dist/capacity/codex.d.ts.map +1 -1
- package/dist/capacity/codex.js +5 -47
- package/dist/capacity/codex.js.map +1 -1
- package/dist/capacity/index.d.ts +11 -0
- package/dist/capacity/index.d.ts.map +1 -1
- package/dist/capacity/index.js +17 -0
- package/dist/capacity/index.js.map +1 -1
- package/dist/capacity/openai.d.ts +48 -0
- package/dist/capacity/openai.d.ts.map +1 -0
- package/dist/capacity/openai.js +312 -0
- package/dist/capacity/openai.js.map +1 -0
- package/dist/capacity/wham.d.ts +16 -0
- package/dist/capacity/wham.d.ts.map +1 -0
- package/dist/capacity/wham.js +66 -0
- package/dist/capacity/wham.js.map +1 -0
- package/dist/index.d.ts +4 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -1
- package/dist/index.js.map +1 -1
- package/dist/readiness/AgentReadiness.d.ts +1 -1
- package/dist/readiness/AgentReadiness.d.ts.map +1 -1
- package/dist/readiness/AgentReadiness.js.map +1 -1
- package/dist/runtime/ManagedAgentRuntime.js +3 -1
- package/dist/runtime/ManagedAgentRuntime.js.map +1 -1
- package/dist/runtime/herdr/HerdrAgentDiscovery.js +10 -0
- package/dist/runtime/herdr/HerdrAgentDiscovery.js.map +1 -1
- package/dist/utils/agents.d.ts +1 -1
- package/dist/utils/agents.d.ts.map +1 -1
- package/dist/utils/agents.js +11 -0
- package/dist/utils/agents.js.map +1 -1
- package/package.json +1 -1
- package/src/__tests__/adapters/AntigravityCliAdapter.test.ts +324 -0
- package/src/__tests__/adapters/KiroAdapter.test.ts +534 -0
- package/src/__tests__/capacity/claude.test.ts +467 -0
- package/src/__tests__/capacity/fixtures/claude-credentials.json +7 -0
- package/src/__tests__/capacity/fixtures/claude-usage-malformed.json +1 -0
- package/src/__tests__/capacity/fixtures/claude-usage-partial.json +15 -0
- package/src/__tests__/capacity/fixtures/claude-usage.json +63 -0
- package/src/__tests__/capacity/fixtures/openai-auth.json +6 -0
- package/src/__tests__/capacity/fixtures/openai-codex-auth.json +9 -0
- package/src/__tests__/capacity/fixtures/openai-usage-completions.json +67 -0
- package/src/__tests__/capacity/fixtures/openai-usage-responses.json +20 -0
- package/src/__tests__/capacity/fixtures/wham-usage.json +32 -0
- package/src/__tests__/capacity/openai.test.ts +570 -0
- package/src/__tests__/capacity/wham.test.ts +104 -0
- package/src/__tests__/utils/agents.test.ts +7 -0
- package/src/adapters/AgentAdapter.ts +2 -0
- package/src/adapters/AntigravityCliAdapter.ts +356 -0
- package/src/adapters/KiroAdapter.ts +456 -0
- package/src/adapters/index.ts +2 -0
- package/src/capacity/claude.ts +313 -0
- package/src/capacity/codex.ts +25 -134
- package/src/capacity/index.ts +33 -4
- package/src/capacity/openai.ts +361 -0
- package/src/capacity/wham.ts +84 -0
- package/src/index.ts +10 -1
- package/src/readiness/AgentReadiness.ts +4 -1
- package/src/runtime/ManagedAgentRuntime.ts +2 -0
- package/src/runtime/herdr/HerdrAgentDiscovery.ts +5 -1
- package/src/utils/agents.ts +11 -1
|
@@ -0,0 +1,381 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tests for AntigravityCliAdapter
|
|
3
|
+
*
|
|
4
|
+
* The adapter resolves a live `agy` process to its conversation via
|
|
5
|
+
* ~/.gemini/antigravity-cli/cache/last_conversations.json (cwd -> conversationId)
|
|
6
|
+
* and reads session details from brain/<id>/.system_generated/logs/transcript.jsonl.
|
|
7
|
+
*/ import * as fs from "fs";
|
|
8
|
+
import * as os from "os";
|
|
9
|
+
import * as path from "path";
|
|
10
|
+
import { AntigravityCliAdapter } from "../../adapters/AntigravityCliAdapter.js";
|
|
11
|
+
import { AgentStatus } from "../../adapters/AgentAdapter.js";
|
|
12
|
+
import { listAgentProcesses, enrichProcesses } from "../../utils/process.js";
|
|
13
|
+
import { generateAgentName } from "../../utils/matching.js";
|
|
14
|
+
vi.mock("../../utils/process.js", async (importOriginal)=>{
|
|
15
|
+
const actual = await importOriginal();
|
|
16
|
+
return {
|
|
17
|
+
...actual,
|
|
18
|
+
listAgentProcesses: vi.fn(),
|
|
19
|
+
enrichProcesses: vi.fn()
|
|
20
|
+
};
|
|
21
|
+
});
|
|
22
|
+
vi.mock("../../utils/matching.js", async (importOriginal)=>{
|
|
23
|
+
const actual = await importOriginal();
|
|
24
|
+
return {
|
|
25
|
+
...actual,
|
|
26
|
+
generateAgentName: vi.fn()
|
|
27
|
+
};
|
|
28
|
+
});
|
|
29
|
+
const mockedListAgentProcesses = listAgentProcesses;
|
|
30
|
+
const mockedEnrichProcesses = enrichProcesses;
|
|
31
|
+
const mockedGenerateAgentName = generateAgentName;
|
|
32
|
+
const CONVERSATION_ID = "10485e13-2742-4e9e-b286-ac0606f0cb1e";
|
|
33
|
+
const iso = (d)=>d.toISOString().replace(/\.\d+Z$/, "Z");
|
|
34
|
+
/** A user transcript record: real prompt wrapped in <USER_REQUEST> like agy writes it. */ const userRecord = (text, at)=>({
|
|
35
|
+
source: "USER_EXPLICIT",
|
|
36
|
+
type: "USER_INPUT",
|
|
37
|
+
created_at: iso(at ?? new Date()),
|
|
38
|
+
content: `<USER_REQUEST>\n${text}\n</USER_REQUEST>\n<ADDITIONAL_CONTEXT>ignored</ADDITIONAL_CONTEXT>`
|
|
39
|
+
});
|
|
40
|
+
const modelRecord = (text, at)=>({
|
|
41
|
+
source: "MODEL",
|
|
42
|
+
type: "PLANNER_RESPONSE",
|
|
43
|
+
created_at: iso(at ?? new Date()),
|
|
44
|
+
content: text
|
|
45
|
+
});
|
|
46
|
+
/** A MODEL tool-call record (e.g. RUN_COMMAND) — execution detail, not a reply. */ const toolRecord = (text, at)=>({
|
|
47
|
+
source: "MODEL",
|
|
48
|
+
type: "RUN_COMMAND",
|
|
49
|
+
created_at: iso(at ?? new Date()),
|
|
50
|
+
content: text
|
|
51
|
+
});
|
|
52
|
+
const systemRecord = (text, at)=>({
|
|
53
|
+
source: "SYSTEM",
|
|
54
|
+
type: "CHECKPOINT",
|
|
55
|
+
created_at: iso(at ?? new Date()),
|
|
56
|
+
content: text
|
|
57
|
+
});
|
|
58
|
+
describe("AntigravityCliAdapter", ()=>{
|
|
59
|
+
let adapter;
|
|
60
|
+
let base;
|
|
61
|
+
let cwd;
|
|
62
|
+
beforeEach(()=>{
|
|
63
|
+
base = fs.mkdtempSync(path.join(os.tmpdir(), "agy-adapter-test-"));
|
|
64
|
+
process.env.ANTIGRAVITY_CLI_HOME = base;
|
|
65
|
+
cwd = "/Users/dev/my-project";
|
|
66
|
+
adapter = new AntigravityCliAdapter();
|
|
67
|
+
mockedListAgentProcesses.mockReset();
|
|
68
|
+
mockedEnrichProcesses.mockReset();
|
|
69
|
+
mockedGenerateAgentName.mockReset();
|
|
70
|
+
mockedEnrichProcesses.mockImplementation((procs)=>procs);
|
|
71
|
+
mockedGenerateAgentName.mockImplementation((c, pid)=>`${path.basename(c) || "unknown"}-${pid}`);
|
|
72
|
+
});
|
|
73
|
+
afterEach(()=>{
|
|
74
|
+
delete process.env.ANTIGRAVITY_CLI_HOME;
|
|
75
|
+
fs.rmSync(base, {
|
|
76
|
+
recursive: true,
|
|
77
|
+
force: true
|
|
78
|
+
});
|
|
79
|
+
});
|
|
80
|
+
/** Write brain/<id>/.system_generated/logs/transcript.jsonl. */ function writeTranscript(opts) {
|
|
81
|
+
const id = opts.id ?? CONVERSATION_ID;
|
|
82
|
+
const dir = path.join(base, "brain", id, ".system_generated", "logs");
|
|
83
|
+
fs.mkdirSync(dir, {
|
|
84
|
+
recursive: true
|
|
85
|
+
});
|
|
86
|
+
if (opts.transcript !== false) {
|
|
87
|
+
const records = opts.records ?? [
|
|
88
|
+
userRecord("fix the bug")
|
|
89
|
+
];
|
|
90
|
+
fs.writeFileSync(path.join(dir, "transcript.jsonl"), records.map((r)=>JSON.stringify(r)).join("\n"));
|
|
91
|
+
}
|
|
92
|
+
return path.join(dir, "transcript.jsonl");
|
|
93
|
+
}
|
|
94
|
+
/** Write cache/last_conversations.json (cwd -> conversationId). */ function writeRegistry(map) {
|
|
95
|
+
const dir = path.join(base, "cache");
|
|
96
|
+
fs.mkdirSync(dir, {
|
|
97
|
+
recursive: true
|
|
98
|
+
});
|
|
99
|
+
fs.writeFileSync(path.join(dir, "last_conversations.json"), JSON.stringify(map));
|
|
100
|
+
}
|
|
101
|
+
function proc(overrides = {}) {
|
|
102
|
+
return {
|
|
103
|
+
pid: 4242,
|
|
104
|
+
ppid: 1,
|
|
105
|
+
command: "agy",
|
|
106
|
+
cwd,
|
|
107
|
+
tty: "ttys010",
|
|
108
|
+
startTime: new Date(),
|
|
109
|
+
...overrides
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
describe("initialization", ()=>{
|
|
113
|
+
it("exposes the antigravity_cli type", ()=>{
|
|
114
|
+
expect(adapter.type).toBe("antigravity_cli");
|
|
115
|
+
});
|
|
116
|
+
});
|
|
117
|
+
describe("canHandle", ()=>{
|
|
118
|
+
it("returns true for a plain agy command", ()=>{
|
|
119
|
+
expect(adapter.canHandle(proc({
|
|
120
|
+
command: "agy"
|
|
121
|
+
}))).toBe(true);
|
|
122
|
+
});
|
|
123
|
+
it("returns true for agy with a full path and args", ()=>{
|
|
124
|
+
expect(adapter.canHandle(proc({
|
|
125
|
+
command: "/Users/dev/.local/bin/agy --dangerously-skip-permissions"
|
|
126
|
+
}))).toBe(true);
|
|
127
|
+
});
|
|
128
|
+
it("returns false for non-agy processes", ()=>{
|
|
129
|
+
expect(adapter.canHandle(proc({
|
|
130
|
+
command: "node app.js"
|
|
131
|
+
}))).toBe(false);
|
|
132
|
+
});
|
|
133
|
+
it('returns false when "agy" appears only in an argument path', ()=>{
|
|
134
|
+
expect(adapter.canHandle(proc({
|
|
135
|
+
command: "node /path/to/agy-thing.js"
|
|
136
|
+
}))).toBe(false);
|
|
137
|
+
});
|
|
138
|
+
});
|
|
139
|
+
describe("detectAgents", ()=>{
|
|
140
|
+
it("returns [] when there are no agy processes", async ()=>{
|
|
141
|
+
mockedListAgentProcesses.mockReturnValue([]);
|
|
142
|
+
expect(await adapter.detectAgents()).toEqual([]);
|
|
143
|
+
});
|
|
144
|
+
it("resolves the conversation via last_conversations.json (cwd -> id)", async ()=>{
|
|
145
|
+
writeTranscript({});
|
|
146
|
+
writeRegistry({
|
|
147
|
+
[cwd]: CONVERSATION_ID
|
|
148
|
+
});
|
|
149
|
+
mockedListAgentProcesses.mockReturnValue([
|
|
150
|
+
proc()
|
|
151
|
+
]);
|
|
152
|
+
const agents = await adapter.detectAgents();
|
|
153
|
+
expect(agents).toHaveLength(1);
|
|
154
|
+
expect(agents[0]).toMatchObject({
|
|
155
|
+
type: "antigravity_cli",
|
|
156
|
+
pid: 4242,
|
|
157
|
+
projectPath: cwd,
|
|
158
|
+
sessionId: CONVERSATION_ID,
|
|
159
|
+
summary: "fix the bug"
|
|
160
|
+
});
|
|
161
|
+
expect(agents[0].sessionFilePath).toBe(path.join(base, "brain", CONVERSATION_ID, ".system_generated", "logs", "transcript.jsonl"));
|
|
162
|
+
});
|
|
163
|
+
it("falls back to a process-only RUNNING agent when the cwd is not in the registry", async ()=>{
|
|
164
|
+
writeTranscript({});
|
|
165
|
+
writeRegistry({
|
|
166
|
+
"/some/other/cwd": CONVERSATION_ID
|
|
167
|
+
});
|
|
168
|
+
mockedListAgentProcesses.mockReturnValue([
|
|
169
|
+
proc()
|
|
170
|
+
]);
|
|
171
|
+
const agents = await adapter.detectAgents();
|
|
172
|
+
expect(agents).toHaveLength(1);
|
|
173
|
+
expect(agents[0].status).toBe(AgentStatus.RUNNING);
|
|
174
|
+
expect(agents[0].sessionId).toBe("pid-4242");
|
|
175
|
+
expect(agents[0].sessionFilePath).toBeUndefined();
|
|
176
|
+
});
|
|
177
|
+
it("is process-only when the mapped conversation has no transcript", async ()=>{
|
|
178
|
+
writeTranscript({
|
|
179
|
+
transcript: false
|
|
180
|
+
});
|
|
181
|
+
writeRegistry({
|
|
182
|
+
[cwd]: CONVERSATION_ID
|
|
183
|
+
});
|
|
184
|
+
mockedListAgentProcesses.mockReturnValue([
|
|
185
|
+
proc()
|
|
186
|
+
]);
|
|
187
|
+
const agents = await adapter.detectAgents();
|
|
188
|
+
expect(agents[0].sessionId).toBe("pid-4242");
|
|
189
|
+
});
|
|
190
|
+
});
|
|
191
|
+
describe("getConversation", ()=>{
|
|
192
|
+
it("maps USER_INPUT (<USER_REQUEST>) and MODEL records to roles", ()=>{
|
|
193
|
+
const file = writeTranscript({
|
|
194
|
+
records: [
|
|
195
|
+
userRecord("hi"),
|
|
196
|
+
modelRecord("hello")
|
|
197
|
+
]
|
|
198
|
+
});
|
|
199
|
+
expect(adapter.getConversation(file)).toEqual([
|
|
200
|
+
{
|
|
201
|
+
role: "user",
|
|
202
|
+
content: "hi"
|
|
203
|
+
},
|
|
204
|
+
{
|
|
205
|
+
role: "assistant",
|
|
206
|
+
content: "hello"
|
|
207
|
+
}
|
|
208
|
+
]);
|
|
209
|
+
});
|
|
210
|
+
it("accepts a bare conversation id and skips malformed lines", ()=>{
|
|
211
|
+
const file = writeTranscript({
|
|
212
|
+
records: [
|
|
213
|
+
userRecord("hi")
|
|
214
|
+
]
|
|
215
|
+
});
|
|
216
|
+
fs.appendFileSync(file, "\n{bad json");
|
|
217
|
+
expect(adapter.getConversation(CONVERSATION_ID)).toEqual([
|
|
218
|
+
{
|
|
219
|
+
role: "user",
|
|
220
|
+
content: "hi"
|
|
221
|
+
}
|
|
222
|
+
]);
|
|
223
|
+
});
|
|
224
|
+
it("excludes SYSTEM records unless verbose", ()=>{
|
|
225
|
+
const file = writeTranscript({
|
|
226
|
+
records: [
|
|
227
|
+
systemRecord("checkpoint"),
|
|
228
|
+
userRecord("go")
|
|
229
|
+
]
|
|
230
|
+
});
|
|
231
|
+
expect(adapter.getConversation(file)).toEqual([
|
|
232
|
+
{
|
|
233
|
+
role: "user",
|
|
234
|
+
content: "go"
|
|
235
|
+
}
|
|
236
|
+
]);
|
|
237
|
+
expect(adapter.getConversation(file, {
|
|
238
|
+
verbose: true
|
|
239
|
+
}).map((m)=>m.role)).toEqual([
|
|
240
|
+
"system",
|
|
241
|
+
"user"
|
|
242
|
+
]);
|
|
243
|
+
});
|
|
244
|
+
it("excludes MODEL tool-call (RUN_COMMAND) records except in verbose", ()=>{
|
|
245
|
+
const file = writeTranscript({
|
|
246
|
+
records: [
|
|
247
|
+
userRecord("go"),
|
|
248
|
+
toolRecord("ran: echo hi"),
|
|
249
|
+
modelRecord("done")
|
|
250
|
+
]
|
|
251
|
+
});
|
|
252
|
+
// A tool call is not an assistant reply; only USER_INPUT + PLANNER_RESPONSE show.
|
|
253
|
+
expect(adapter.getConversation(file)).toEqual([
|
|
254
|
+
{
|
|
255
|
+
role: "user",
|
|
256
|
+
content: "go"
|
|
257
|
+
},
|
|
258
|
+
{
|
|
259
|
+
role: "assistant",
|
|
260
|
+
content: "done"
|
|
261
|
+
}
|
|
262
|
+
]);
|
|
263
|
+
expect(adapter.getConversation(file, {
|
|
264
|
+
verbose: true
|
|
265
|
+
}).map((m)=>m.role)).toEqual([
|
|
266
|
+
"user",
|
|
267
|
+
"system",
|
|
268
|
+
"assistant"
|
|
269
|
+
]);
|
|
270
|
+
});
|
|
271
|
+
});
|
|
272
|
+
describe("detectAgents status + summary mapping", ()=>{
|
|
273
|
+
const detectFirst = async ()=>(await adapter.detectAgents())[0];
|
|
274
|
+
it("marks WAITING when the last reply is a PLANNER_RESPONSE (after a tool call)", async ()=>{
|
|
275
|
+
writeTranscript({
|
|
276
|
+
records: [
|
|
277
|
+
userRecord("go"),
|
|
278
|
+
toolRecord("ran: echo hi"),
|
|
279
|
+
modelRecord("done")
|
|
280
|
+
]
|
|
281
|
+
});
|
|
282
|
+
writeRegistry({
|
|
283
|
+
[cwd]: CONVERSATION_ID
|
|
284
|
+
});
|
|
285
|
+
mockedListAgentProcesses.mockReturnValue([
|
|
286
|
+
proc()
|
|
287
|
+
]);
|
|
288
|
+
expect((await detectFirst()).status).toBe(AgentStatus.WAITING);
|
|
289
|
+
});
|
|
290
|
+
it("marks RUNNING when the last transcript turn is a USER_INPUT message", async ()=>{
|
|
291
|
+
writeTranscript({
|
|
292
|
+
records: [
|
|
293
|
+
userRecord("still there?")
|
|
294
|
+
]
|
|
295
|
+
});
|
|
296
|
+
writeRegistry({
|
|
297
|
+
[cwd]: CONVERSATION_ID
|
|
298
|
+
});
|
|
299
|
+
mockedListAgentProcesses.mockReturnValue([
|
|
300
|
+
proc()
|
|
301
|
+
]);
|
|
302
|
+
expect((await detectFirst()).status).toBe(AgentStatus.RUNNING);
|
|
303
|
+
});
|
|
304
|
+
it("marks IDLE when the last created_at is older than the threshold", async ()=>{
|
|
305
|
+
const old = new Date(Date.now() - 10 * 60 * 1000);
|
|
306
|
+
writeTranscript({
|
|
307
|
+
records: [
|
|
308
|
+
userRecord("go", old)
|
|
309
|
+
]
|
|
310
|
+
});
|
|
311
|
+
writeRegistry({
|
|
312
|
+
[cwd]: CONVERSATION_ID
|
|
313
|
+
});
|
|
314
|
+
mockedListAgentProcesses.mockReturnValue([
|
|
315
|
+
proc()
|
|
316
|
+
]);
|
|
317
|
+
expect((await detectFirst()).status).toBe(AgentStatus.IDLE);
|
|
318
|
+
});
|
|
319
|
+
it("uses the last user request as the agent summary", async ()=>{
|
|
320
|
+
writeTranscript({
|
|
321
|
+
records: [
|
|
322
|
+
userRecord("refactor the parser"),
|
|
323
|
+
modelRecord("on it")
|
|
324
|
+
]
|
|
325
|
+
});
|
|
326
|
+
writeRegistry({
|
|
327
|
+
[cwd]: CONVERSATION_ID
|
|
328
|
+
});
|
|
329
|
+
mockedListAgentProcesses.mockReturnValue([
|
|
330
|
+
proc()
|
|
331
|
+
]);
|
|
332
|
+
expect((await detectFirst()).summary).toBe("refactor the parser");
|
|
333
|
+
});
|
|
334
|
+
});
|
|
335
|
+
describe("listSessions", ()=>{
|
|
336
|
+
it("returns [] when there is no registry", async ()=>{
|
|
337
|
+
expect(await adapter.listSessions()).toEqual([]);
|
|
338
|
+
});
|
|
339
|
+
it("lists sessions from the registry with cwd + first user message", async ()=>{
|
|
340
|
+
writeTranscript({});
|
|
341
|
+
writeRegistry({
|
|
342
|
+
[cwd]: CONVERSATION_ID
|
|
343
|
+
});
|
|
344
|
+
const summaries = await adapter.listSessions();
|
|
345
|
+
expect(summaries).toHaveLength(1);
|
|
346
|
+
expect(summaries[0]).toMatchObject({
|
|
347
|
+
type: "antigravity_cli",
|
|
348
|
+
sessionId: CONVERSATION_ID,
|
|
349
|
+
cwd,
|
|
350
|
+
firstUserMessage: "fix the bug"
|
|
351
|
+
});
|
|
352
|
+
});
|
|
353
|
+
it("applies the cwd filter", async ()=>{
|
|
354
|
+
writeTranscript({
|
|
355
|
+
id: "aaa0000a-0000-4000-8000-00000000000a",
|
|
356
|
+
records: [
|
|
357
|
+
userRecord("a")
|
|
358
|
+
]
|
|
359
|
+
});
|
|
360
|
+
writeTranscript({
|
|
361
|
+
id: "bbb0000b-0000-4000-8000-00000000000b",
|
|
362
|
+
records: [
|
|
363
|
+
userRecord("b")
|
|
364
|
+
]
|
|
365
|
+
});
|
|
366
|
+
writeRegistry({
|
|
367
|
+
"/Users/dev/project-a": "aaa0000a-0000-4000-8000-00000000000a",
|
|
368
|
+
"/Users/dev/project-b": "bbb0000b-0000-4000-8000-00000000000b"
|
|
369
|
+
});
|
|
370
|
+
const all = await adapter.listSessions();
|
|
371
|
+
expect(all).toHaveLength(2);
|
|
372
|
+
const filtered = await adapter.listSessions({
|
|
373
|
+
cwd: "/Users/dev/project-a"
|
|
374
|
+
});
|
|
375
|
+
expect(filtered).toHaveLength(1);
|
|
376
|
+
expect(filtered[0].cwd).toBe("/Users/dev/project-a");
|
|
377
|
+
});
|
|
378
|
+
});
|
|
379
|
+
});
|
|
380
|
+
|
|
381
|
+
//# sourceMappingURL=AntigravityCliAdapter.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/__tests__/adapters/AntigravityCliAdapter.test.ts"],"sourcesContent":["/**\n * Tests for AntigravityCliAdapter\n *\n * The adapter resolves a live `agy` process to its conversation via\n * ~/.gemini/antigravity-cli/cache/last_conversations.json (cwd -> conversationId)\n * and reads session details from brain/<id>/.system_generated/logs/transcript.jsonl.\n */\n\nimport type { MockedFunction } from \"vitest\";\nimport * as fs from \"fs\";\nimport * as os from \"os\";\nimport * as path from \"path\";\n\nimport { AntigravityCliAdapter } from \"../../adapters/AntigravityCliAdapter.js\";\nimport type { ProcessInfo } from \"../../adapters/AgentAdapter.js\";\nimport { AgentStatus } from \"../../adapters/AgentAdapter.js\";\nimport { listAgentProcesses, enrichProcesses } from \"../../utils/process.js\";\nimport { generateAgentName } from \"../../utils/matching.js\";\n\nvi.mock(\"../../utils/process.js\", async (importOriginal) => {\n const actual = (await importOriginal()) as typeof import(\"../../utils/process.js\");\n return {\n ...actual,\n listAgentProcesses: vi.fn(),\n enrichProcesses: vi.fn(),\n };\n});\n\nvi.mock(\"../../utils/matching.js\", async (importOriginal) => {\n const actual = (await importOriginal()) as typeof import(\"../../utils/matching.js\");\n return {\n ...actual,\n generateAgentName: vi.fn(),\n };\n});\n\nconst mockedListAgentProcesses = listAgentProcesses as MockedFunction<typeof listAgentProcesses>;\nconst mockedEnrichProcesses = enrichProcesses as MockedFunction<typeof enrichProcesses>;\nconst mockedGenerateAgentName = generateAgentName as MockedFunction<typeof generateAgentName>;\n\nconst CONVERSATION_ID = \"10485e13-2742-4e9e-b286-ac0606f0cb1e\";\n\nconst iso = (d: Date) => d.toISOString().replace(/\\.\\d+Z$/, \"Z\");\n/** A user transcript record: real prompt wrapped in <USER_REQUEST> like agy writes it. */\nconst userRecord = (text: string, at?: Date) => ({\n source: \"USER_EXPLICIT\",\n type: \"USER_INPUT\",\n created_at: iso(at ?? new Date()),\n content: `<USER_REQUEST>\\n${text}\\n</USER_REQUEST>\\n<ADDITIONAL_CONTEXT>ignored</ADDITIONAL_CONTEXT>`,\n});\nconst modelRecord = (text: string, at?: Date) => ({\n source: \"MODEL\",\n type: \"PLANNER_RESPONSE\",\n created_at: iso(at ?? new Date()),\n content: text,\n});\n/** A MODEL tool-call record (e.g. RUN_COMMAND) — execution detail, not a reply. */\nconst toolRecord = (text: string, at?: Date) => ({\n source: \"MODEL\",\n type: \"RUN_COMMAND\",\n created_at: iso(at ?? new Date()),\n content: text,\n});\nconst systemRecord = (text: string, at?: Date) => ({\n source: \"SYSTEM\",\n type: \"CHECKPOINT\",\n created_at: iso(at ?? new Date()),\n content: text,\n});\n\ndescribe(\"AntigravityCliAdapter\", () => {\n let adapter: AntigravityCliAdapter;\n let base: string;\n let cwd: string;\n\n beforeEach(() => {\n base = fs.mkdtempSync(path.join(os.tmpdir(), \"agy-adapter-test-\"));\n process.env.ANTIGRAVITY_CLI_HOME = base;\n cwd = \"/Users/dev/my-project\";\n\n adapter = new AntigravityCliAdapter();\n\n mockedListAgentProcesses.mockReset();\n mockedEnrichProcesses.mockReset();\n mockedGenerateAgentName.mockReset();\n\n mockedEnrichProcesses.mockImplementation((procs) => procs);\n mockedGenerateAgentName.mockImplementation(\n (c: string, pid: number) => `${path.basename(c) || \"unknown\"}-${pid}`,\n );\n });\n\n afterEach(() => {\n delete process.env.ANTIGRAVITY_CLI_HOME;\n fs.rmSync(base, { recursive: true, force: true });\n });\n\n /** Write brain/<id>/.system_generated/logs/transcript.jsonl. */\n function writeTranscript(opts: {\n id?: string;\n records?: object[];\n transcript?: boolean;\n }): string {\n const id = opts.id ?? CONVERSATION_ID;\n const dir = path.join(base, \"brain\", id, \".system_generated\", \"logs\");\n fs.mkdirSync(dir, { recursive: true });\n if (opts.transcript !== false) {\n const records = opts.records ?? [userRecord(\"fix the bug\")];\n fs.writeFileSync(\n path.join(dir, \"transcript.jsonl\"),\n records.map((r) => JSON.stringify(r)).join(\"\\n\"),\n );\n }\n return path.join(dir, \"transcript.jsonl\");\n }\n\n /** Write cache/last_conversations.json (cwd -> conversationId). */\n function writeRegistry(map: Record<string, string>): void {\n const dir = path.join(base, \"cache\");\n fs.mkdirSync(dir, { recursive: true });\n fs.writeFileSync(path.join(dir, \"last_conversations.json\"), JSON.stringify(map));\n }\n\n function proc(overrides: Partial<ProcessInfo> = {}): ProcessInfo {\n return {\n pid: 4242,\n ppid: 1,\n command: \"agy\",\n cwd,\n tty: \"ttys010\",\n startTime: new Date(),\n ...overrides,\n };\n }\n\n describe(\"initialization\", () => {\n it(\"exposes the antigravity_cli type\", () => {\n expect(adapter.type).toBe(\"antigravity_cli\");\n });\n });\n\n describe(\"canHandle\", () => {\n it(\"returns true for a plain agy command\", () => {\n expect(adapter.canHandle(proc({ command: \"agy\" }))).toBe(true);\n });\n\n it(\"returns true for agy with a full path and args\", () => {\n expect(\n adapter.canHandle(\n proc({ command: \"/Users/dev/.local/bin/agy --dangerously-skip-permissions\" }),\n ),\n ).toBe(true);\n });\n\n it(\"returns false for non-agy processes\", () => {\n expect(adapter.canHandle(proc({ command: \"node app.js\" }))).toBe(false);\n });\n\n it('returns false when \"agy\" appears only in an argument path', () => {\n expect(adapter.canHandle(proc({ command: \"node /path/to/agy-thing.js\" }))).toBe(false);\n });\n });\n\n describe(\"detectAgents\", () => {\n it(\"returns [] when there are no agy processes\", async () => {\n mockedListAgentProcesses.mockReturnValue([]);\n expect(await adapter.detectAgents()).toEqual([]);\n });\n\n it(\"resolves the conversation via last_conversations.json (cwd -> id)\", async () => {\n writeTranscript({});\n writeRegistry({ [cwd]: CONVERSATION_ID });\n mockedListAgentProcesses.mockReturnValue([proc()]);\n\n const agents = await adapter.detectAgents();\n\n expect(agents).toHaveLength(1);\n expect(agents[0]).toMatchObject({\n type: \"antigravity_cli\",\n pid: 4242,\n projectPath: cwd,\n sessionId: CONVERSATION_ID,\n summary: \"fix the bug\",\n });\n expect(agents[0].sessionFilePath).toBe(\n path.join(base, \"brain\", CONVERSATION_ID, \".system_generated\", \"logs\", \"transcript.jsonl\"),\n );\n });\n\n it(\"falls back to a process-only RUNNING agent when the cwd is not in the registry\", async () => {\n writeTranscript({});\n writeRegistry({ \"/some/other/cwd\": CONVERSATION_ID });\n mockedListAgentProcesses.mockReturnValue([proc()]);\n\n const agents = await adapter.detectAgents();\n\n expect(agents).toHaveLength(1);\n expect(agents[0].status).toBe(AgentStatus.RUNNING);\n expect(agents[0].sessionId).toBe(\"pid-4242\");\n expect(agents[0].sessionFilePath).toBeUndefined();\n });\n\n it(\"is process-only when the mapped conversation has no transcript\", async () => {\n writeTranscript({ transcript: false });\n writeRegistry({ [cwd]: CONVERSATION_ID });\n mockedListAgentProcesses.mockReturnValue([proc()]);\n\n const agents = await adapter.detectAgents();\n\n expect(agents[0].sessionId).toBe(\"pid-4242\");\n });\n });\n\n describe(\"getConversation\", () => {\n it(\"maps USER_INPUT (<USER_REQUEST>) and MODEL records to roles\", () => {\n const file = writeTranscript({ records: [userRecord(\"hi\"), modelRecord(\"hello\")] });\n expect(adapter.getConversation(file)).toEqual([\n { role: \"user\", content: \"hi\" },\n { role: \"assistant\", content: \"hello\" },\n ]);\n });\n\n it(\"accepts a bare conversation id and skips malformed lines\", () => {\n const file = writeTranscript({ records: [userRecord(\"hi\")] });\n fs.appendFileSync(file, \"\\n{bad json\");\n expect(adapter.getConversation(CONVERSATION_ID)).toEqual([{ role: \"user\", content: \"hi\" }]);\n });\n\n it(\"excludes SYSTEM records unless verbose\", () => {\n const file = writeTranscript({ records: [systemRecord(\"checkpoint\"), userRecord(\"go\")] });\n expect(adapter.getConversation(file)).toEqual([{ role: \"user\", content: \"go\" }]);\n expect(adapter.getConversation(file, { verbose: true }).map((m) => m.role)).toEqual([\n \"system\",\n \"user\",\n ]);\n });\n\n it(\"excludes MODEL tool-call (RUN_COMMAND) records except in verbose\", () => {\n const file = writeTranscript({\n records: [userRecord(\"go\"), toolRecord(\"ran: echo hi\"), modelRecord(\"done\")],\n });\n // A tool call is not an assistant reply; only USER_INPUT + PLANNER_RESPONSE show.\n expect(adapter.getConversation(file)).toEqual([\n { role: \"user\", content: \"go\" },\n { role: \"assistant\", content: \"done\" },\n ]);\n expect(adapter.getConversation(file, { verbose: true }).map((m) => m.role)).toEqual([\n \"user\",\n \"system\",\n \"assistant\",\n ]);\n });\n });\n\n describe(\"detectAgents status + summary mapping\", () => {\n const detectFirst = async () => (await adapter.detectAgents())[0];\n\n it(\"marks WAITING when the last reply is a PLANNER_RESPONSE (after a tool call)\", async () => {\n writeTranscript({\n records: [userRecord(\"go\"), toolRecord(\"ran: echo hi\"), modelRecord(\"done\")],\n });\n writeRegistry({ [cwd]: CONVERSATION_ID });\n mockedListAgentProcesses.mockReturnValue([proc()]);\n expect((await detectFirst()).status).toBe(AgentStatus.WAITING);\n });\n\n it(\"marks RUNNING when the last transcript turn is a USER_INPUT message\", async () => {\n writeTranscript({ records: [userRecord(\"still there?\")] });\n writeRegistry({ [cwd]: CONVERSATION_ID });\n mockedListAgentProcesses.mockReturnValue([proc()]);\n expect((await detectFirst()).status).toBe(AgentStatus.RUNNING);\n });\n\n it(\"marks IDLE when the last created_at is older than the threshold\", async () => {\n const old = new Date(Date.now() - 10 * 60 * 1000);\n writeTranscript({ records: [userRecord(\"go\", old)] });\n writeRegistry({ [cwd]: CONVERSATION_ID });\n mockedListAgentProcesses.mockReturnValue([proc()]);\n expect((await detectFirst()).status).toBe(AgentStatus.IDLE);\n });\n\n it(\"uses the last user request as the agent summary\", async () => {\n writeTranscript({ records: [userRecord(\"refactor the parser\"), modelRecord(\"on it\")] });\n writeRegistry({ [cwd]: CONVERSATION_ID });\n mockedListAgentProcesses.mockReturnValue([proc()]);\n expect((await detectFirst()).summary).toBe(\"refactor the parser\");\n });\n });\n\n describe(\"listSessions\", () => {\n it(\"returns [] when there is no registry\", async () => {\n expect(await adapter.listSessions()).toEqual([]);\n });\n\n it(\"lists sessions from the registry with cwd + first user message\", async () => {\n writeTranscript({});\n writeRegistry({ [cwd]: CONVERSATION_ID });\n const summaries = await adapter.listSessions();\n expect(summaries).toHaveLength(1);\n expect(summaries[0]).toMatchObject({\n type: \"antigravity_cli\",\n sessionId: CONVERSATION_ID,\n cwd,\n firstUserMessage: \"fix the bug\",\n });\n });\n\n it(\"applies the cwd filter\", async () => {\n writeTranscript({ id: \"aaa0000a-0000-4000-8000-00000000000a\", records: [userRecord(\"a\")] });\n writeTranscript({ id: \"bbb0000b-0000-4000-8000-00000000000b\", records: [userRecord(\"b\")] });\n writeRegistry({\n \"/Users/dev/project-a\": \"aaa0000a-0000-4000-8000-00000000000a\",\n \"/Users/dev/project-b\": \"bbb0000b-0000-4000-8000-00000000000b\",\n });\n\n const all = await adapter.listSessions();\n expect(all).toHaveLength(2);\n\n const filtered = await adapter.listSessions({ cwd: \"/Users/dev/project-a\" });\n expect(filtered).toHaveLength(1);\n expect(filtered[0].cwd).toBe(\"/Users/dev/project-a\");\n });\n });\n});\n"],"names":["fs","os","path","AntigravityCliAdapter","AgentStatus","listAgentProcesses","enrichProcesses","generateAgentName","vi","mock","importOriginal","actual","fn","mockedListAgentProcesses","mockedEnrichProcesses","mockedGenerateAgentName","CONVERSATION_ID","iso","d","toISOString","replace","userRecord","text","at","source","type","created_at","Date","content","modelRecord","toolRecord","systemRecord","describe","adapter","base","cwd","beforeEach","mkdtempSync","join","tmpdir","process","env","ANTIGRAVITY_CLI_HOME","mockReset","mockImplementation","procs","c","pid","basename","afterEach","rmSync","recursive","force","writeTranscript","opts","id","dir","mkdirSync","transcript","records","writeFileSync","map","r","JSON","stringify","writeRegistry","proc","overrides","ppid","command","tty","startTime","it","expect","toBe","canHandle","mockReturnValue","detectAgents","toEqual","agents","toHaveLength","toMatchObject","projectPath","sessionId","summary","sessionFilePath","status","RUNNING","toBeUndefined","file","getConversation","role","appendFileSync","verbose","m","detectFirst","WAITING","old","now","IDLE","listSessions","summaries","firstUserMessage","all","filtered"],"mappings":"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"}
|