@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,273 @@
|
|
|
1
|
+
import * as path from "path";
|
|
2
|
+
import { AgentStatus } from "./AgentAdapter.js";
|
|
3
|
+
import { listAgentProcesses, enrichProcesses } from "../utils/process.js";
|
|
4
|
+
import { safeReadFile, safeStat } from "../utils/session.js";
|
|
5
|
+
import { generateAgentName } from "../utils/matching.js";
|
|
6
|
+
/**
|
|
7
|
+
* Antigravity CLI Adapter
|
|
8
|
+
*
|
|
9
|
+
* Detects running Antigravity CLI agents (Google's Gemini-family `agy` CLI) by:
|
|
10
|
+
* 1. Finding running `agy` processes via shared listAgentProcesses() — Antigravity
|
|
11
|
+
* ships a native binary (argv[0] basename `agy`).
|
|
12
|
+
* 2. Resolving each live process to its conversation via
|
|
13
|
+
* ~/.gemini/antigravity-cli/cache/last_conversations.json, which the CLI
|
|
14
|
+
* maintains as a `{ <cwd>: <conversationId> }` map of the current conversation
|
|
15
|
+
* per workspace. The process cwd is the join key.
|
|
16
|
+
* 3. Reading the transcript from
|
|
17
|
+
* brain/<conversationId>/.system_generated/logs/transcript.jsonl. User turns are
|
|
18
|
+
* USER_INPUT records (prompt inside <USER_REQUEST>...</USER_REQUEST>) and the
|
|
19
|
+
* model's reply is a PLANNER_RESPONSE record; tool calls (RUN_COMMAND, ...) are
|
|
20
|
+
* skipped. The last user turn is the summary; each record's created_at gives the
|
|
21
|
+
* last-activity time.
|
|
22
|
+
*
|
|
23
|
+
* This is the runtime/agent side of Antigravity; it is independent of the
|
|
24
|
+
* `antigravity` environment (which configures the Antigravity IDE), the same way
|
|
25
|
+
* GeminiCliAdapter is independent of the `gemini` environment.
|
|
26
|
+
*/ const REGISTRY_FILE = path.join("cache", "last_conversations.json");
|
|
27
|
+
const BRAIN_DIR = "brain";
|
|
28
|
+
const TRANSCRIPT_REL = path.join(".system_generated", "logs", "transcript.jsonl");
|
|
29
|
+
const IDLE_THRESHOLD_MINUTES = 5;
|
|
30
|
+
export class AntigravityCliAdapter {
|
|
31
|
+
type = "antigravity_cli";
|
|
32
|
+
base;
|
|
33
|
+
constructor(){
|
|
34
|
+
// ANTIGRAVITY_CLI_HOME overrides the ~/.gemini/antigravity-cli base dir.
|
|
35
|
+
const homeDir = process.env.HOME || process.env.USERPROFILE || "";
|
|
36
|
+
this.base = process.env.ANTIGRAVITY_CLI_HOME || path.join(homeDir, ".gemini", "antigravity-cli");
|
|
37
|
+
}
|
|
38
|
+
canHandle(processInfo) {
|
|
39
|
+
return this.isAgyExecutable(processInfo.command);
|
|
40
|
+
}
|
|
41
|
+
isAgyExecutable(command) {
|
|
42
|
+
const executable = command.trim().split(/\s+/)[0] || "";
|
|
43
|
+
const base = path.basename(executable).toLowerCase();
|
|
44
|
+
return base === "agy" || base === "agy.exe";
|
|
45
|
+
}
|
|
46
|
+
async detectAgents() {
|
|
47
|
+
const processes = enrichProcesses(listAgentProcesses("agy"));
|
|
48
|
+
if (processes.length === 0) {
|
|
49
|
+
return [];
|
|
50
|
+
}
|
|
51
|
+
// last_conversations.json maps a workspace cwd to its current
|
|
52
|
+
// conversation id; the live process cwd is the join key.
|
|
53
|
+
const cwdToConversation = this.readRegistry();
|
|
54
|
+
const agents = [];
|
|
55
|
+
for (const proc of processes){
|
|
56
|
+
const cwd = proc.cwd || "";
|
|
57
|
+
const conversationId = cwd ? cwdToConversation.get(cwd) : undefined;
|
|
58
|
+
const session = conversationId ? this.readSession(conversationId, cwd) : null;
|
|
59
|
+
if (session) {
|
|
60
|
+
agents.push(this.mapSessionToAgent(session, proc));
|
|
61
|
+
} else {
|
|
62
|
+
agents.push(this.mapProcessOnlyAgent(proc, cwd));
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
return agents;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Read cache/last_conversations.json into a cwd -> conversationId map. The
|
|
69
|
+
* CLI rewrites this as the current conversation per workspace changes.
|
|
70
|
+
*/ readRegistry() {
|
|
71
|
+
const map = new Map();
|
|
72
|
+
const content = safeReadFile(path.join(this.base, REGISTRY_FILE));
|
|
73
|
+
if (content === undefined) return map;
|
|
74
|
+
let parsed;
|
|
75
|
+
try {
|
|
76
|
+
parsed = JSON.parse(content);
|
|
77
|
+
} catch {
|
|
78
|
+
return map;
|
|
79
|
+
}
|
|
80
|
+
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) return map;
|
|
81
|
+
for (const [cwd, conversationId] of Object.entries(parsed)){
|
|
82
|
+
if (cwd && typeof conversationId === "string" && conversationId) {
|
|
83
|
+
map.set(cwd, conversationId);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
return map;
|
|
87
|
+
}
|
|
88
|
+
transcriptPath(conversationId) {
|
|
89
|
+
return path.join(this.base, BRAIN_DIR, conversationId, TRANSCRIPT_REL);
|
|
90
|
+
}
|
|
91
|
+
mapSessionToAgent(session, processInfo) {
|
|
92
|
+
const projectPath = session.projectPath || processInfo.cwd || "";
|
|
93
|
+
return {
|
|
94
|
+
name: generateAgentName(projectPath, processInfo.pid),
|
|
95
|
+
type: this.type,
|
|
96
|
+
status: this.determineStatus(session),
|
|
97
|
+
summary: session.summary || "Antigravity CLI session active",
|
|
98
|
+
pid: processInfo.pid,
|
|
99
|
+
projectPath,
|
|
100
|
+
sessionId: session.sessionId,
|
|
101
|
+
lastActive: session.lastActive,
|
|
102
|
+
sessionFilePath: this.transcriptPath(session.sessionId)
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
mapProcessOnlyAgent(processInfo, cwd) {
|
|
106
|
+
const projectPath = cwd || processInfo.cwd || "";
|
|
107
|
+
return {
|
|
108
|
+
name: generateAgentName(projectPath, processInfo.pid),
|
|
109
|
+
type: this.type,
|
|
110
|
+
status: AgentStatus.RUNNING,
|
|
111
|
+
summary: "Antigravity CLI process running",
|
|
112
|
+
pid: processInfo.pid,
|
|
113
|
+
projectPath,
|
|
114
|
+
sessionId: `pid-${processInfo.pid}`,
|
|
115
|
+
lastActive: new Date()
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
getConversation(sessionFilePath, options) {
|
|
119
|
+
return this.parseTranscript(this.resolveTranscriptPath(sessionFilePath), options?.verbose ?? false).messages;
|
|
120
|
+
}
|
|
121
|
+
async listSessions(opts) {
|
|
122
|
+
const filterCwd = opts?.cwd;
|
|
123
|
+
const summaries = [];
|
|
124
|
+
for (const [cwd, conversationId] of this.readRegistry()){
|
|
125
|
+
if (filterCwd !== undefined && cwd !== filterCwd) continue;
|
|
126
|
+
const session = this.readSession(conversationId, cwd);
|
|
127
|
+
if (!session) continue;
|
|
128
|
+
summaries.push({
|
|
129
|
+
type: this.type,
|
|
130
|
+
sessionId: session.sessionId,
|
|
131
|
+
cwd: session.projectPath || cwd,
|
|
132
|
+
firstUserMessage: session.firstUserMessage || "",
|
|
133
|
+
lastActive: session.lastActive,
|
|
134
|
+
startedAt: session.sessionStart,
|
|
135
|
+
sessionFilePath: this.transcriptPath(conversationId)
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
return summaries;
|
|
139
|
+
}
|
|
140
|
+
// --- Session parsing (transcript.jsonl) ---
|
|
141
|
+
/**
|
|
142
|
+
* Parse a conversation into an {@link AntigravitySession} from its
|
|
143
|
+
* transcript.jsonl. Returns null when the transcript is missing — i.e. there
|
|
144
|
+
* is no real session to surface.
|
|
145
|
+
*/ readSession(conversationId, defaultCwd) {
|
|
146
|
+
const transcriptPath = this.transcriptPath(conversationId);
|
|
147
|
+
const stat = safeStat(transcriptPath);
|
|
148
|
+
if (!stat) return null;
|
|
149
|
+
const scan = this.parseTranscript(transcriptPath, false);
|
|
150
|
+
const lastActive = scan.lastActive || stat.mtime;
|
|
151
|
+
return {
|
|
152
|
+
sessionId: conversationId,
|
|
153
|
+
projectPath: defaultCwd || "",
|
|
154
|
+
summary: scan.lastUserMessage || "Antigravity CLI session active",
|
|
155
|
+
sessionStart: stat.birthtime || lastActive,
|
|
156
|
+
lastActive,
|
|
157
|
+
firstUserMessage: scan.firstUserMessage,
|
|
158
|
+
lastUserMessage: scan.lastUserMessage,
|
|
159
|
+
lastRole: scan.lastRole
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
/**
|
|
163
|
+
* Determine agent status from parsed session state.
|
|
164
|
+
*
|
|
165
|
+
* - past the idle threshold → IDLE
|
|
166
|
+
* - last transcript turn is an assistant message → WAITING (awaiting user)
|
|
167
|
+
* - otherwise (last turn was a user message, or unknown) → RUNNING
|
|
168
|
+
*/ determineStatus(session) {
|
|
169
|
+
const diffMinutes = (Date.now() - session.lastActive.getTime()) / 60000;
|
|
170
|
+
if (diffMinutes > IDLE_THRESHOLD_MINUTES) {
|
|
171
|
+
return AgentStatus.IDLE;
|
|
172
|
+
}
|
|
173
|
+
if (session.lastRole === "assistant") {
|
|
174
|
+
return AgentStatus.WAITING;
|
|
175
|
+
}
|
|
176
|
+
return AgentStatus.RUNNING;
|
|
177
|
+
}
|
|
178
|
+
/**
|
|
179
|
+
* Single pass over transcript.jsonl. Each line is a
|
|
180
|
+
* { source, type, created_at, content } record. User turns are
|
|
181
|
+
* `type: 'USER_INPUT'` with the real prompt wrapped in
|
|
182
|
+
* <USER_REQUEST>...</USER_REQUEST>; the model's reply is `type:
|
|
183
|
+
* 'PLANNER_RESPONSE'`. Other MODEL records (tool calls like RUN_COMMAND) and
|
|
184
|
+
* SYSTEM records (conversation history, checkpoints) are execution detail and
|
|
185
|
+
* are skipped unless verbose.
|
|
186
|
+
*/ parseTranscript(transcriptPath, verbose) {
|
|
187
|
+
const empty = {
|
|
188
|
+
messages: []
|
|
189
|
+
};
|
|
190
|
+
const content = safeReadFile(transcriptPath);
|
|
191
|
+
if (content === undefined) return empty;
|
|
192
|
+
const messages = [];
|
|
193
|
+
let lastRole;
|
|
194
|
+
let lastActive;
|
|
195
|
+
for (const line of content.trim().split("\n")){
|
|
196
|
+
if (!line.trim()) continue;
|
|
197
|
+
let record;
|
|
198
|
+
try {
|
|
199
|
+
record = JSON.parse(line);
|
|
200
|
+
} catch {
|
|
201
|
+
continue;
|
|
202
|
+
}
|
|
203
|
+
const at = this.parseTimestamp(record.created_at);
|
|
204
|
+
if (at && (!lastActive || at.getTime() > lastActive.getTime())) lastActive = at;
|
|
205
|
+
const text = this.extractText(record.content);
|
|
206
|
+
if (record.type === "USER_INPUT") {
|
|
207
|
+
const request = this.extractUserRequest(text);
|
|
208
|
+
if (request === null) continue; // not a real prompt
|
|
209
|
+
messages.push({
|
|
210
|
+
role: "user",
|
|
211
|
+
content: request
|
|
212
|
+
});
|
|
213
|
+
lastRole = "user";
|
|
214
|
+
} else if (record.type === "PLANNER_RESPONSE") {
|
|
215
|
+
// The model's user-facing reply. Other MODEL records (tool calls
|
|
216
|
+
// such as RUN_COMMAND, empty planning steps) are execution detail,
|
|
217
|
+
// not conversation, so they are excluded from the normal view.
|
|
218
|
+
if (!text) continue;
|
|
219
|
+
messages.push({
|
|
220
|
+
role: "assistant",
|
|
221
|
+
content: text
|
|
222
|
+
});
|
|
223
|
+
lastRole = "assistant";
|
|
224
|
+
} else if (verbose) {
|
|
225
|
+
// Tool calls (MODEL/RUN_COMMAND, ...) and SYSTEM records surface
|
|
226
|
+
// only in verbose mode.
|
|
227
|
+
if (!text) continue;
|
|
228
|
+
messages.push({
|
|
229
|
+
role: "system",
|
|
230
|
+
content: text
|
|
231
|
+
});
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
const userTurns = messages.filter((m)=>m.role === "user");
|
|
235
|
+
return {
|
|
236
|
+
messages,
|
|
237
|
+
firstUserMessage: userTurns[0]?.content,
|
|
238
|
+
lastUserMessage: userTurns[userTurns.length - 1]?.content,
|
|
239
|
+
lastRole,
|
|
240
|
+
lastActive
|
|
241
|
+
};
|
|
242
|
+
}
|
|
243
|
+
/** Flatten a transcript record's content (string or text-block array) to text. */ extractText(content) {
|
|
244
|
+
if (typeof content === "string") return content;
|
|
245
|
+
if (Array.isArray(content)) {
|
|
246
|
+
return content.map((block)=>block && typeof block === "object" && typeof block.text === "string" ? block.text : "").join("");
|
|
247
|
+
}
|
|
248
|
+
return "";
|
|
249
|
+
}
|
|
250
|
+
/**
|
|
251
|
+
* Extract the prompt inside <USER_REQUEST>...</USER_REQUEST>. Returns null when
|
|
252
|
+
* the record has no such tag (context injection rather than a prompt). Falls
|
|
253
|
+
* back to the trimmed text when a USER_INPUT record has no wrapper.
|
|
254
|
+
*/ extractUserRequest(text) {
|
|
255
|
+
const match = text.match(/<USER_REQUEST>\s*([\s\S]*?)\s*<\/USER_REQUEST>/);
|
|
256
|
+
if (match) return match[1].trim();
|
|
257
|
+
const trimmed = text.trim();
|
|
258
|
+
return trimmed ? trimmed : null;
|
|
259
|
+
}
|
|
260
|
+
/** Resolve a conversation dir, transcript path, or bare id to the transcript file. */ resolveTranscriptPath(sessionPath) {
|
|
261
|
+
if (sessionPath.endsWith(".jsonl")) return sessionPath;
|
|
262
|
+
// A bare conversation id (no separator) resolves under the brain dir.
|
|
263
|
+
if (!sessionPath.includes(path.sep)) return this.transcriptPath(sessionPath);
|
|
264
|
+
return path.join(sessionPath, TRANSCRIPT_REL);
|
|
265
|
+
}
|
|
266
|
+
parseTimestamp(value) {
|
|
267
|
+
if (!value) return null;
|
|
268
|
+
const ts = new Date(value);
|
|
269
|
+
return Number.isNaN(ts.getTime()) ? null : ts;
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
//# sourceMappingURL=AntigravityCliAdapter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/adapters/AntigravityCliAdapter.ts"],"sourcesContent":["import * as path from \"path\";\nimport type {\n AgentAdapter,\n AgentInfo,\n ProcessInfo,\n ConversationMessage,\n SessionSummary,\n ListSessionsOptions,\n} from \"./AgentAdapter.js\";\nimport { AgentStatus } from \"./AgentAdapter.js\";\nimport { listAgentProcesses, enrichProcesses } from \"../utils/process.js\";\nimport { safeReadFile, safeStat } from \"../utils/session.js\";\nimport { generateAgentName } from \"../utils/matching.js\";\n\n/**\n * Antigravity CLI Adapter\n *\n * Detects running Antigravity CLI agents (Google's Gemini-family `agy` CLI) by:\n * 1. Finding running `agy` processes via shared listAgentProcesses() — Antigravity\n * ships a native binary (argv[0] basename `agy`).\n * 2. Resolving each live process to its conversation via\n * ~/.gemini/antigravity-cli/cache/last_conversations.json, which the CLI\n * maintains as a `{ <cwd>: <conversationId> }` map of the current conversation\n * per workspace. The process cwd is the join key.\n * 3. Reading the transcript from\n * brain/<conversationId>/.system_generated/logs/transcript.jsonl. User turns are\n * USER_INPUT records (prompt inside <USER_REQUEST>...</USER_REQUEST>) and the\n * model's reply is a PLANNER_RESPONSE record; tool calls (RUN_COMMAND, ...) are\n * skipped. The last user turn is the summary; each record's created_at gives the\n * last-activity time.\n *\n * This is the runtime/agent side of Antigravity; it is independent of the\n * `antigravity` environment (which configures the Antigravity IDE), the same way\n * GeminiCliAdapter is independent of the `gemini` environment.\n */\n\nconst REGISTRY_FILE = path.join(\"cache\", \"last_conversations.json\");\nconst BRAIN_DIR = \"brain\";\nconst TRANSCRIPT_REL = path.join(\".system_generated\", \"logs\", \"transcript.jsonl\");\nconst IDLE_THRESHOLD_MINUTES = 5;\n\n/** One line of transcript.jsonl. */\ninterface TranscriptRecord {\n source?: string;\n type?: string;\n created_at?: string;\n content?: unknown;\n}\n\ninterface TranscriptScan {\n messages: ConversationMessage[];\n firstUserMessage?: string;\n lastUserMessage?: string;\n lastRole?: ConversationMessage[\"role\"];\n lastActive?: Date;\n}\n\n/** Parsed state for a single conversation. */\ninterface AntigravitySession {\n sessionId: string;\n projectPath: string;\n summary: string;\n sessionStart: Date;\n lastActive: Date;\n firstUserMessage?: string;\n lastUserMessage?: string;\n lastRole?: ConversationMessage[\"role\"];\n}\n\nexport class AntigravityCliAdapter implements AgentAdapter {\n readonly type = \"antigravity_cli\" as const;\n\n private base: string;\n\n constructor() {\n // ANTIGRAVITY_CLI_HOME overrides the ~/.gemini/antigravity-cli base dir.\n const homeDir = process.env.HOME || process.env.USERPROFILE || \"\";\n this.base =\n process.env.ANTIGRAVITY_CLI_HOME || path.join(homeDir, \".gemini\", \"antigravity-cli\");\n }\n\n canHandle(processInfo: ProcessInfo): boolean {\n return this.isAgyExecutable(processInfo.command);\n }\n\n private isAgyExecutable(command: string): boolean {\n const executable = command.trim().split(/\\s+/)[0] || \"\";\n const base = path.basename(executable).toLowerCase();\n return base === \"agy\" || base === \"agy.exe\";\n }\n\n async detectAgents(): Promise<AgentInfo[]> {\n const processes = enrichProcesses(listAgentProcesses(\"agy\"));\n if (processes.length === 0) {\n return [];\n }\n\n // last_conversations.json maps a workspace cwd to its current\n // conversation id; the live process cwd is the join key.\n const cwdToConversation = this.readRegistry();\n\n const agents: AgentInfo[] = [];\n for (const proc of processes) {\n const cwd = proc.cwd || \"\";\n const conversationId = cwd ? cwdToConversation.get(cwd) : undefined;\n const session = conversationId ? this.readSession(conversationId, cwd) : null;\n\n if (session) {\n agents.push(this.mapSessionToAgent(session, proc));\n } else {\n agents.push(this.mapProcessOnlyAgent(proc, cwd));\n }\n }\n\n return agents;\n }\n\n /**\n * Read cache/last_conversations.json into a cwd -> conversationId map. The\n * CLI rewrites this as the current conversation per workspace changes.\n */\n private readRegistry(): Map<string, string> {\n const map = new Map<string, string>();\n const content = safeReadFile(path.join(this.base, REGISTRY_FILE));\n if (content === undefined) return map;\n\n let parsed: unknown;\n try {\n parsed = JSON.parse(content);\n } catch {\n return map;\n }\n if (!parsed || typeof parsed !== \"object\" || Array.isArray(parsed)) return map;\n\n for (const [cwd, conversationId] of Object.entries(parsed as Record<string, unknown>)) {\n if (cwd && typeof conversationId === \"string\" && conversationId) {\n map.set(cwd, conversationId);\n }\n }\n return map;\n }\n\n private transcriptPath(conversationId: string): string {\n return path.join(this.base, BRAIN_DIR, conversationId, TRANSCRIPT_REL);\n }\n\n private mapSessionToAgent(session: AntigravitySession, processInfo: ProcessInfo): AgentInfo {\n const projectPath = session.projectPath || processInfo.cwd || \"\";\n return {\n name: generateAgentName(projectPath, processInfo.pid),\n type: this.type,\n status: this.determineStatus(session),\n summary: session.summary || \"Antigravity CLI session active\",\n pid: processInfo.pid,\n projectPath,\n sessionId: session.sessionId,\n lastActive: session.lastActive,\n sessionFilePath: this.transcriptPath(session.sessionId),\n };\n }\n\n private mapProcessOnlyAgent(processInfo: ProcessInfo, cwd: string): AgentInfo {\n const projectPath = cwd || processInfo.cwd || \"\";\n return {\n name: generateAgentName(projectPath, processInfo.pid),\n type: this.type,\n status: AgentStatus.RUNNING,\n summary: \"Antigravity CLI process running\",\n pid: processInfo.pid,\n projectPath,\n sessionId: `pid-${processInfo.pid}`,\n lastActive: new Date(),\n };\n }\n\n getConversation(sessionFilePath: string, options?: { verbose?: boolean }): ConversationMessage[] {\n return this.parseTranscript(\n this.resolveTranscriptPath(sessionFilePath),\n options?.verbose ?? false,\n ).messages;\n }\n\n async listSessions(opts?: ListSessionsOptions): Promise<SessionSummary[]> {\n const filterCwd = opts?.cwd;\n const summaries: SessionSummary[] = [];\n\n for (const [cwd, conversationId] of this.readRegistry()) {\n if (filterCwd !== undefined && cwd !== filterCwd) continue;\n\n const session = this.readSession(conversationId, cwd);\n if (!session) continue;\n\n summaries.push({\n type: this.type,\n sessionId: session.sessionId,\n cwd: session.projectPath || cwd,\n firstUserMessage: session.firstUserMessage || \"\",\n lastActive: session.lastActive,\n startedAt: session.sessionStart,\n sessionFilePath: this.transcriptPath(conversationId),\n });\n }\n\n return summaries;\n }\n\n // --- Session parsing (transcript.jsonl) ---\n\n /**\n * Parse a conversation into an {@link AntigravitySession} from its\n * transcript.jsonl. Returns null when the transcript is missing — i.e. there\n * is no real session to surface.\n */\n private readSession(conversationId: string, defaultCwd: string): AntigravitySession | null {\n const transcriptPath = this.transcriptPath(conversationId);\n const stat = safeStat(transcriptPath);\n if (!stat) return null;\n\n const scan = this.parseTranscript(transcriptPath, false);\n const lastActive = scan.lastActive || stat.mtime;\n\n return {\n sessionId: conversationId,\n projectPath: defaultCwd || \"\",\n summary: scan.lastUserMessage || \"Antigravity CLI session active\",\n sessionStart: stat.birthtime || lastActive,\n lastActive,\n firstUserMessage: scan.firstUserMessage,\n lastUserMessage: scan.lastUserMessage,\n lastRole: scan.lastRole,\n };\n }\n\n /**\n * Determine agent status from parsed session state.\n *\n * - past the idle threshold → IDLE\n * - last transcript turn is an assistant message → WAITING (awaiting user)\n * - otherwise (last turn was a user message, or unknown) → RUNNING\n */\n private determineStatus(session: AntigravitySession): AgentStatus {\n const diffMinutes = (Date.now() - session.lastActive.getTime()) / 60000;\n if (diffMinutes > IDLE_THRESHOLD_MINUTES) {\n return AgentStatus.IDLE;\n }\n if (session.lastRole === \"assistant\") {\n return AgentStatus.WAITING;\n }\n return AgentStatus.RUNNING;\n }\n\n /**\n * Single pass over transcript.jsonl. Each line is a\n * { source, type, created_at, content } record. User turns are\n * `type: 'USER_INPUT'` with the real prompt wrapped in\n * <USER_REQUEST>...</USER_REQUEST>; the model's reply is `type:\n * 'PLANNER_RESPONSE'`. Other MODEL records (tool calls like RUN_COMMAND) and\n * SYSTEM records (conversation history, checkpoints) are execution detail and\n * are skipped unless verbose.\n */\n private parseTranscript(transcriptPath: string, verbose: boolean): TranscriptScan {\n const empty: TranscriptScan = { messages: [] };\n const content = safeReadFile(transcriptPath);\n if (content === undefined) return empty;\n\n const messages: ConversationMessage[] = [];\n let lastRole: ConversationMessage[\"role\"] | undefined;\n let lastActive: Date | undefined;\n\n for (const line of content.trim().split(\"\\n\")) {\n if (!line.trim()) continue;\n\n let record: TranscriptRecord;\n try {\n record = JSON.parse(line);\n } catch {\n continue;\n }\n\n const at = this.parseTimestamp(record.created_at);\n if (at && (!lastActive || at.getTime() > lastActive.getTime())) lastActive = at;\n\n const text = this.extractText(record.content);\n if (record.type === \"USER_INPUT\") {\n const request = this.extractUserRequest(text);\n if (request === null) continue; // not a real prompt\n messages.push({ role: \"user\", content: request });\n lastRole = \"user\";\n } else if (record.type === \"PLANNER_RESPONSE\") {\n // The model's user-facing reply. Other MODEL records (tool calls\n // such as RUN_COMMAND, empty planning steps) are execution detail,\n // not conversation, so they are excluded from the normal view.\n if (!text) continue;\n messages.push({ role: \"assistant\", content: text });\n lastRole = \"assistant\";\n } else if (verbose) {\n // Tool calls (MODEL/RUN_COMMAND, ...) and SYSTEM records surface\n // only in verbose mode.\n if (!text) continue;\n messages.push({ role: \"system\", content: text });\n }\n }\n\n const userTurns = messages.filter((m) => m.role === \"user\");\n return {\n messages,\n firstUserMessage: userTurns[0]?.content,\n lastUserMessage: userTurns[userTurns.length - 1]?.content,\n lastRole,\n lastActive,\n };\n }\n\n /** Flatten a transcript record's content (string or text-block array) to text. */\n private extractText(content: unknown): string {\n if (typeof content === \"string\") return content;\n if (Array.isArray(content)) {\n return content\n .map((block) =>\n block &&\n typeof block === \"object\" &&\n typeof (block as { text?: unknown }).text === \"string\"\n ? (block as { text: string }).text\n : \"\",\n )\n .join(\"\");\n }\n return \"\";\n }\n\n /**\n * Extract the prompt inside <USER_REQUEST>...</USER_REQUEST>. Returns null when\n * the record has no such tag (context injection rather than a prompt). Falls\n * back to the trimmed text when a USER_INPUT record has no wrapper.\n */\n private extractUserRequest(text: string): string | null {\n const match = text.match(/<USER_REQUEST>\\s*([\\s\\S]*?)\\s*<\\/USER_REQUEST>/);\n if (match) return match[1].trim();\n const trimmed = text.trim();\n return trimmed ? trimmed : null;\n }\n\n /** Resolve a conversation dir, transcript path, or bare id to the transcript file. */\n private resolveTranscriptPath(sessionPath: string): string {\n if (sessionPath.endsWith(\".jsonl\")) return sessionPath;\n // A bare conversation id (no separator) resolves under the brain dir.\n if (!sessionPath.includes(path.sep)) return this.transcriptPath(sessionPath);\n return path.join(sessionPath, TRANSCRIPT_REL);\n }\n\n private parseTimestamp(value?: string): Date | null {\n if (!value) return null;\n const ts = new Date(value);\n return Number.isNaN(ts.getTime()) ? null : ts;\n }\n}\n"],"names":["path","AgentStatus","listAgentProcesses","enrichProcesses","safeReadFile","safeStat","generateAgentName","REGISTRY_FILE","join","BRAIN_DIR","TRANSCRIPT_REL","IDLE_THRESHOLD_MINUTES","AntigravityCliAdapter","type","base","homeDir","process","env","HOME","USERPROFILE","ANTIGRAVITY_CLI_HOME","canHandle","processInfo","isAgyExecutable","command","executable","trim","split","basename","toLowerCase","detectAgents","processes","length","cwdToConversation","readRegistry","agents","proc","cwd","conversationId","get","undefined","session","readSession","push","mapSessionToAgent","mapProcessOnlyAgent","map","Map","content","parsed","JSON","parse","Array","isArray","Object","entries","set","transcriptPath","projectPath","name","pid","status","determineStatus","summary","sessionId","lastActive","sessionFilePath","RUNNING","Date","getConversation","options","parseTranscript","resolveTranscriptPath","verbose","messages","listSessions","opts","filterCwd","summaries","firstUserMessage","startedAt","sessionStart","defaultCwd","stat","scan","mtime","lastUserMessage","birthtime","lastRole","diffMinutes","now","getTime","IDLE","WAITING","empty","line","record","at","parseTimestamp","created_at","text","extractText","request","extractUserRequest","role","userTurns","filter","m","block","match","trimmed","sessionPath","endsWith","includes","sep","value","ts","Number","isNaN"],"mappings":"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"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Kiro Adapter
|
|
3
|
+
*
|
|
4
|
+
* Detects running Kiro agents by matching process IDs from
|
|
5
|
+
* ~/.kiro/sessions/cli/<session-id>.lock to the sibling metadata and transcript files.
|
|
6
|
+
*/
|
|
7
|
+
import type { AgentAdapter, AgentInfo, ProcessInfo, ConversationMessage, SessionSummary, ListSessionsOptions, AgentDetectionContext } from "./AgentAdapter.js";
|
|
8
|
+
export declare class KiroAdapter implements AgentAdapter {
|
|
9
|
+
readonly type: "kiro";
|
|
10
|
+
readonly processNames: readonly ["kiro-cli", "kiro", "kiro-cli-chat", "node"];
|
|
11
|
+
private kiroSessionsDir;
|
|
12
|
+
constructor();
|
|
13
|
+
canHandle(processInfo: ProcessInfo): boolean;
|
|
14
|
+
detectAgents(context?: AgentDetectionContext): Promise<AgentInfo[]>;
|
|
15
|
+
getConversation(sessionFilePath: string, options?: {
|
|
16
|
+
verbose?: boolean;
|
|
17
|
+
}): ConversationMessage[];
|
|
18
|
+
listSessions(opts?: ListSessionsOptions): Promise<SessionSummary[]>;
|
|
19
|
+
private discoverActiveLocks;
|
|
20
|
+
private readSession;
|
|
21
|
+
private readMetadata;
|
|
22
|
+
private readJsonl;
|
|
23
|
+
private entriesToMessages;
|
|
24
|
+
private entryToMessage;
|
|
25
|
+
private textContent;
|
|
26
|
+
private toolUseContent;
|
|
27
|
+
private toolResultContent;
|
|
28
|
+
private contentBlocks;
|
|
29
|
+
private hasContentKind;
|
|
30
|
+
private entryTimestamp;
|
|
31
|
+
private entryDate;
|
|
32
|
+
private mapSessionToAgent;
|
|
33
|
+
private mapProcessOnlyAgent;
|
|
34
|
+
private determineStatus;
|
|
35
|
+
private resolveLockProcess;
|
|
36
|
+
private matchSoleTopLevelOnTty;
|
|
37
|
+
private isKiroExecutable;
|
|
38
|
+
private kiroBasename;
|
|
39
|
+
private toPid;
|
|
40
|
+
private parseDate;
|
|
41
|
+
private firstString;
|
|
42
|
+
private asRecord;
|
|
43
|
+
private formatValue;
|
|
44
|
+
private truncate;
|
|
45
|
+
}
|
|
46
|
+
//# sourceMappingURL=KiroAdapter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"KiroAdapter.d.ts","sourceRoot":"","sources":["../../src/adapters/KiroAdapter.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,KAAK,EACV,YAAY,EACZ,SAAS,EACT,WAAW,EACX,mBAAmB,EACnB,cAAc,EACd,mBAAmB,EACnB,qBAAqB,EACtB,MAAM,mBAAmB,CAAC;AA+C3B,qBAAa,WAAY,YAAW,YAAY;IAC9C,QAAQ,CAAC,IAAI,EAAG,MAAM,CAAU;IAChC,QAAQ,CAAC,YAAY,yDAA0D;IAE/E,OAAO,CAAC,eAAe,CAAS;;IAOhC,SAAS,CAAC,WAAW,EAAE,WAAW,GAAG,OAAO;IAItC,YAAY,CAAC,OAAO,CAAC,EAAE,qBAAqB,GAAG,OAAO,CAAC,SAAS,EAAE,CAAC;IA8BzE,eAAe,CAAC,eAAe,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;QAAE,OAAO,CAAC,EAAE,OAAO,CAAA;KAAE,GAAG,mBAAmB,EAAE;IAI1F,YAAY,CAAC,IAAI,CAAC,EAAE,mBAAmB,GAAG,OAAO,CAAC,cAAc,EAAE,CAAC;IAyBzE,OAAO,CAAC,mBAAmB;IA2B3B,OAAO,CAAC,WAAW;IAiCnB,OAAO,CAAC,YAAY;IA0BpB,OAAO,CAAC,SAAS;IAkBjB,OAAO,CAAC,iBAAiB;IASzB,OAAO,CAAC,cAAc;IA2BtB,OAAO,CAAC,WAAW;IAQnB,OAAO,CAAC,cAAc;IAWtB,OAAO,CAAC,iBAAiB;IAWzB,OAAO,CAAC,aAAa;IAQrB,OAAO,CAAC,cAAc;IAItB,OAAO,CAAC,cAAc;IAStB,OAAO,CAAC,SAAS;IAIjB,OAAO,CAAC,iBAAiB;IAezB,OAAO,CAAC,mBAAmB;IAa3B,OAAO,CAAC,eAAe;IASvB,OAAO,CAAC,kBAAkB;IAqB1B,OAAO,CAAC,sBAAsB;IAS9B,OAAO,CAAC,gBAAgB;IAYxB,OAAO,CAAC,YAAY;IAIpB,OAAO,CAAC,KAAK;IAOb,OAAO,CAAC,SAAS;IAUjB,OAAO,CAAC,WAAW;IAInB,OAAO,CAAC,QAAQ;IAKhB,OAAO,CAAC,WAAW;IAUnB,OAAO,CAAC,QAAQ;CAIjB"}
|