paseo-acp-agy 1.2.10 → 1.2.12
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/acp-server.js +23 -3
- package/dist/antigravity-process.js +29 -3
- package/dist/native-sessions.js +106 -80
- package/package.json +1 -1
package/dist/acp-server.js
CHANGED
|
@@ -610,7 +610,25 @@ export class ACPServer extends EventEmitter {
|
|
|
610
610
|
}
|
|
611
611
|
};
|
|
612
612
|
try {
|
|
613
|
-
|
|
613
|
+
let resultEvent;
|
|
614
|
+
try {
|
|
615
|
+
resultEvent = await session.process.sendPrompt(promptText, onStepUpdate);
|
|
616
|
+
}
|
|
617
|
+
catch (firstErr) {
|
|
618
|
+
const firstMsg = firstErr.message || "";
|
|
619
|
+
if (stepCount === 0 &&
|
|
620
|
+
!session.isCancelled &&
|
|
621
|
+
firstMsg.includes("agy process exited prematurely")) {
|
|
622
|
+
logger.warn("agy process exited before streaming any steps; retrying prompt with fresh process", {
|
|
623
|
+
sessionId,
|
|
624
|
+
error: firstMsg,
|
|
625
|
+
});
|
|
626
|
+
resultEvent = await session.process.sendPrompt(promptText, onStepUpdate);
|
|
627
|
+
}
|
|
628
|
+
else {
|
|
629
|
+
throw firstErr;
|
|
630
|
+
}
|
|
631
|
+
}
|
|
614
632
|
const turnUsage = resultEvent.result?.usage;
|
|
615
633
|
const numTurns = resultEvent.result?.num_turns || stepCount || 1;
|
|
616
634
|
// Usage is billable even when the turn terminates with ERROR
|
|
@@ -642,12 +660,14 @@ export class ACPServer extends EventEmitter {
|
|
|
642
660
|
}
|
|
643
661
|
}
|
|
644
662
|
catch (promptErr) {
|
|
645
|
-
|
|
663
|
+
const errorMsg = promptErr.message || "Turn execution failed";
|
|
664
|
+
if (session.isCancelled ||
|
|
665
|
+
errorMsg.includes("cancelled") ||
|
|
666
|
+
errorMsg.includes("Turn was cancelled")) {
|
|
646
667
|
if (!isNotification)
|
|
647
668
|
this.sendSuccess(id, { stopReason: "cancelled" });
|
|
648
669
|
}
|
|
649
670
|
else {
|
|
650
|
-
const errorMsg = promptErr.message || "Turn execution failed";
|
|
651
671
|
logger.error("Error executing prompt turn", { error: errorMsg, sessionId });
|
|
652
672
|
this.sendNotification(ACP_METHODS.SESSION_UPDATE, {
|
|
653
673
|
sessionId: session.id,
|
|
@@ -399,6 +399,7 @@ export class AntigravityProcess extends EventEmitter {
|
|
|
399
399
|
child.stderr.setEncoding("utf-8");
|
|
400
400
|
let stdoutBuffer = "";
|
|
401
401
|
let stderrBuffer = "";
|
|
402
|
+
const recentStderrLines = [];
|
|
402
403
|
child.stdout.on("data", (chunk) => {
|
|
403
404
|
this.emit("activity");
|
|
404
405
|
stdoutBuffer += chunk;
|
|
@@ -424,8 +425,13 @@ export class AntigravityProcess extends EventEmitter {
|
|
|
424
425
|
const lines = stderrBuffer.split("\n");
|
|
425
426
|
stderrBuffer = lines.pop() || "";
|
|
426
427
|
for (const line of lines) {
|
|
427
|
-
|
|
428
|
-
|
|
428
|
+
const trimmed = line.trim();
|
|
429
|
+
if (trimmed) {
|
|
430
|
+
logger.warn("agy stderr: " + trimmed);
|
|
431
|
+
recentStderrLines.push(trimmed);
|
|
432
|
+
if (recentStderrLines.length > 20)
|
|
433
|
+
recentStderrLines.shift();
|
|
434
|
+
}
|
|
429
435
|
}
|
|
430
436
|
});
|
|
431
437
|
child.on("error", (err) => {
|
|
@@ -438,9 +444,24 @@ export class AntigravityProcess extends EventEmitter {
|
|
|
438
444
|
});
|
|
439
445
|
child.on("close", (code, signal) => {
|
|
440
446
|
logger.info("agy process exited", { code, signal, pid: child.pid });
|
|
447
|
+
if (stderrBuffer.trim()) {
|
|
448
|
+
recentStderrLines.push(stderrBuffer.trim());
|
|
449
|
+
if (recentStderrLines.length > 20)
|
|
450
|
+
recentStderrLines.shift();
|
|
451
|
+
}
|
|
452
|
+
const stderrDiagnostic = recentStderrLines.join(" ").trim();
|
|
453
|
+
const exitDiagnostic = stderrDiagnostic
|
|
454
|
+
? `agy process exited prematurely with code ${code} signal ${signal}: ${stderrDiagnostic}`
|
|
455
|
+
: `agy process exited prematurely with code ${code} signal ${signal}`;
|
|
441
456
|
if (this.currentTurnPromise?.child === child) {
|
|
442
|
-
this.currentTurnPromise
|
|
457
|
+
const turn = this.currentTurnPromise;
|
|
443
458
|
this.currentTurnPromise = null;
|
|
459
|
+
if (turn.cancelled) {
|
|
460
|
+
turn.reject(new Error("Turn was cancelled"));
|
|
461
|
+
}
|
|
462
|
+
else {
|
|
463
|
+
turn.reject(new Error(exitDiagnostic));
|
|
464
|
+
}
|
|
444
465
|
}
|
|
445
466
|
// The leader can die while a tool subprocess remains in its process
|
|
446
467
|
// group. Keep the group identity long enough to reap those descendants.
|
|
@@ -742,6 +763,11 @@ export class AntigravityProcess extends EventEmitter {
|
|
|
742
763
|
logger.info("Cancelling active agy turn", { hasChild: Boolean(active.child) });
|
|
743
764
|
if (active.child) {
|
|
744
765
|
const child = active.child;
|
|
766
|
+
// Immediately detach this.child so subsequent turns will NOT attach to this dying process!
|
|
767
|
+
if (this.child === child) {
|
|
768
|
+
this.child = null;
|
|
769
|
+
this.initialInfo = null;
|
|
770
|
+
}
|
|
745
771
|
this.signalProcessTree(child, "SIGINT");
|
|
746
772
|
setTimeout(() => {
|
|
747
773
|
if (this.isProcessTreeAlive(child)) {
|
package/dist/native-sessions.js
CHANGED
|
@@ -13,69 +13,100 @@ export function getAgyAppDataDir() {
|
|
|
13
13
|
}
|
|
14
14
|
return path.join(os.homedir(), ".gemini", "antigravity-cli");
|
|
15
15
|
}
|
|
16
|
+
function querySummariesDb(dbPath, query, params = []) {
|
|
17
|
+
// 1. Try node:sqlite DatabaseSync (Node 22+)
|
|
18
|
+
try {
|
|
19
|
+
const DatabaseSync = require("node:sqlite")?.DatabaseSync;
|
|
20
|
+
if (DatabaseSync) {
|
|
21
|
+
const db = new DatabaseSync(dbPath, { readOnly: true });
|
|
22
|
+
return db.prepare(query).all(...params) || [];
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
catch { }
|
|
26
|
+
// 2. Try sqlite3 CLI fallback (macOS, Linux with Node < 22)
|
|
27
|
+
try {
|
|
28
|
+
const { execFileSync } = require("node:child_process");
|
|
29
|
+
let finalQuery = query;
|
|
30
|
+
if (params.length === 1 && typeof params[0] === "string") {
|
|
31
|
+
finalQuery = query.replace("?", `'${params[0].replace(/'/g, "''")}'`);
|
|
32
|
+
}
|
|
33
|
+
const stdout = execFileSync("sqlite3", ["-json", dbPath, finalQuery], {
|
|
34
|
+
encoding: "utf-8",
|
|
35
|
+
timeout: 5000,
|
|
36
|
+
stdio: ["pipe", "pipe", "ignore"],
|
|
37
|
+
});
|
|
38
|
+
if (stdout && stdout.trim()) {
|
|
39
|
+
return JSON.parse(stdout) || [];
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
catch (err) {
|
|
43
|
+
logger.debug("Failed to query conversation summaries via sqlite3 CLI", {
|
|
44
|
+
error: err.message,
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
return [];
|
|
48
|
+
}
|
|
16
49
|
export function loadNativeAntigravitySessions(cwd) {
|
|
17
50
|
const results = [];
|
|
18
51
|
const appDataDir = getAgyAppDataDir();
|
|
19
52
|
const dbPath = path.join(appDataDir, "conversation_summaries.db");
|
|
20
53
|
const normalizedTargetCwd = cwd ? path.resolve(cwd).toLowerCase() : undefined;
|
|
21
54
|
if (fs.existsSync(dbPath)) {
|
|
22
|
-
let DatabaseSync = null;
|
|
23
55
|
try {
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
try {
|
|
43
|
-
const uris = JSON.parse(row.workspace_uris);
|
|
44
|
-
if (Array.isArray(uris) && uris.length > 0) {
|
|
45
|
-
const filePaths = uris
|
|
46
|
-
.map((u) => u.replace(/^file:\/\//i, ""))
|
|
47
|
-
.filter(Boolean);
|
|
48
|
-
if (filePaths.length > 0) {
|
|
49
|
-
primaryCwd = filePaths[0];
|
|
56
|
+
const rows = querySummariesDb(dbPath, `SELECT conversation_id, title, preview, last_modified_time, workspace_uris
|
|
57
|
+
FROM conversation_summaries
|
|
58
|
+
ORDER BY last_modified_time DESC
|
|
59
|
+
LIMIT 100`);
|
|
60
|
+
for (const row of rows) {
|
|
61
|
+
if (!row.conversation_id)
|
|
62
|
+
continue;
|
|
63
|
+
let primaryCwd = process.cwd();
|
|
64
|
+
let matchesCwd = false;
|
|
65
|
+
if (row.workspace_uris) {
|
|
66
|
+
try {
|
|
67
|
+
const uris = JSON.parse(row.workspace_uris);
|
|
68
|
+
if (Array.isArray(uris) && uris.length > 0) {
|
|
69
|
+
const filePaths = uris
|
|
70
|
+
.map((u) => {
|
|
71
|
+
const cleaned = u.replace(/^file:\/\//i, "");
|
|
72
|
+
try {
|
|
73
|
+
return path.resolve(decodeURIComponent(cleaned));
|
|
50
74
|
}
|
|
51
|
-
|
|
52
|
-
|
|
75
|
+
catch {
|
|
76
|
+
return path.resolve(cleaned);
|
|
53
77
|
}
|
|
78
|
+
})
|
|
79
|
+
.filter(Boolean);
|
|
80
|
+
if (filePaths.length > 0) {
|
|
81
|
+
primaryCwd = filePaths[0];
|
|
82
|
+
}
|
|
83
|
+
if (normalizedTargetCwd) {
|
|
84
|
+
matchesCwd = filePaths.some((p) => p.toLowerCase() === normalizedTargetCwd);
|
|
54
85
|
}
|
|
55
86
|
}
|
|
56
|
-
catch { }
|
|
57
|
-
}
|
|
58
|
-
if (normalizedTargetCwd && !matchesCwd) {
|
|
59
|
-
continue;
|
|
60
87
|
}
|
|
61
|
-
|
|
62
|
-
const dateIso = rawDate ? new Date(rawDate).toISOString() : undefined;
|
|
63
|
-
results.push({
|
|
64
|
-
sessionId: row.conversation_id,
|
|
65
|
-
cwd: primaryCwd,
|
|
66
|
-
title: (row.title && row.title.trim()) ||
|
|
67
|
-
(row.preview && row.preview.trim()) ||
|
|
68
|
-
"Antigravity Session",
|
|
69
|
-
updatedAt: dateIso,
|
|
70
|
-
});
|
|
88
|
+
catch { }
|
|
71
89
|
}
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
90
|
+
if (normalizedTargetCwd && !matchesCwd) {
|
|
91
|
+
continue;
|
|
92
|
+
}
|
|
93
|
+
const rawDate = row.last_modified_time;
|
|
94
|
+
const dateIso = rawDate ? new Date(rawDate).toISOString() : undefined;
|
|
95
|
+
results.push({
|
|
96
|
+
sessionId: row.conversation_id,
|
|
97
|
+
cwd: primaryCwd,
|
|
98
|
+
title: (row.title && row.title.trim()) ||
|
|
99
|
+
(row.preview && row.preview.trim()) ||
|
|
100
|
+
"Antigravity Session",
|
|
101
|
+
updatedAt: dateIso,
|
|
76
102
|
});
|
|
77
103
|
}
|
|
78
104
|
}
|
|
105
|
+
catch (err) {
|
|
106
|
+
logger.debug("Failed to read native conversation summaries from sqlite", {
|
|
107
|
+
error: err.message,
|
|
108
|
+
});
|
|
109
|
+
}
|
|
79
110
|
}
|
|
80
111
|
// Fallback: Only scan brainDir if no conversations were found in DB
|
|
81
112
|
if (results.length === 0) {
|
|
@@ -119,46 +150,41 @@ export function getNativeAntigravitySession(conversationId) {
|
|
|
119
150
|
const appDataDir = getAgyAppDataDir();
|
|
120
151
|
const dbPath = path.join(appDataDir, "conversation_summaries.db");
|
|
121
152
|
if (fs.existsSync(dbPath)) {
|
|
122
|
-
let DatabaseSync = null;
|
|
123
153
|
try {
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
if (Array.isArray(uris) && uris.length > 0) {
|
|
141
|
-
const p = uris[0].replace(/^file:\/\//i, "");
|
|
142
|
-
if (p)
|
|
143
|
-
primaryCwd = p;
|
|
154
|
+
const rows = querySummariesDb(dbPath, `SELECT conversation_id, title, preview, last_modified_time, workspace_uris
|
|
155
|
+
FROM conversation_summaries
|
|
156
|
+
WHERE conversation_id = ?`, [conversationId]);
|
|
157
|
+
const row = rows[0];
|
|
158
|
+
if (row) {
|
|
159
|
+
let primaryCwd = process.cwd();
|
|
160
|
+
if (row.workspace_uris) {
|
|
161
|
+
try {
|
|
162
|
+
const uris = JSON.parse(row.workspace_uris);
|
|
163
|
+
if (Array.isArray(uris) && uris.length > 0) {
|
|
164
|
+
const cleaned = uris[0].replace(/^file:\/\//i, "");
|
|
165
|
+
try {
|
|
166
|
+
primaryCwd = path.resolve(decodeURIComponent(cleaned));
|
|
167
|
+
}
|
|
168
|
+
catch {
|
|
169
|
+
primaryCwd = path.resolve(cleaned);
|
|
144
170
|
}
|
|
145
171
|
}
|
|
146
|
-
catch { }
|
|
147
172
|
}
|
|
148
|
-
|
|
149
|
-
sessionId: row.conversation_id,
|
|
150
|
-
cwd: primaryCwd,
|
|
151
|
-
title: (row.title && row.title.trim()) ||
|
|
152
|
-
(row.preview && row.preview.trim()) ||
|
|
153
|
-
"Antigravity Session",
|
|
154
|
-
updatedAt: row.last_modified_time
|
|
155
|
-
? new Date(row.last_modified_time).toISOString()
|
|
156
|
-
: undefined,
|
|
157
|
-
};
|
|
173
|
+
catch { }
|
|
158
174
|
}
|
|
175
|
+
return {
|
|
176
|
+
sessionId: row.conversation_id,
|
|
177
|
+
cwd: primaryCwd,
|
|
178
|
+
title: (row.title && row.title.trim()) ||
|
|
179
|
+
(row.preview && row.preview.trim()) ||
|
|
180
|
+
"Antigravity Session",
|
|
181
|
+
updatedAt: row.last_modified_time
|
|
182
|
+
? new Date(row.last_modified_time).toISOString()
|
|
183
|
+
: undefined,
|
|
184
|
+
};
|
|
159
185
|
}
|
|
160
|
-
catch { }
|
|
161
186
|
}
|
|
187
|
+
catch { }
|
|
162
188
|
}
|
|
163
189
|
// Fallback check transcript file
|
|
164
190
|
const brainDir = path.join(appDataDir, "brain", conversationId);
|