@axhub/genie 0.2.8 → 0.2.10
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/LICENSE +21 -675
- package/dist/api-docs.html +2 -2
- package/dist/assets/App-CYCCsgwf.js +264 -0
- package/dist/assets/ReviewApp-0srHIXwb.js +1 -0
- package/dist/assets/{_basePickBy-CqJbRZ9y.js → _basePickBy-DVVb07UV.js} +1 -1
- package/dist/assets/{_baseUniq-BS8YH8jO.js → _baseUniq-BtbziL5G.js} +1 -1
- package/dist/assets/{arc-BBmKEN-S.js → arc-BsCC8yBD.js} +1 -1
- package/dist/assets/{architectureDiagram-2XIMDMQ5-N5lcb82R.js → architectureDiagram-2XIMDMQ5-woFp6eNI.js} +1 -1
- package/dist/assets/{blockDiagram-WCTKOSBZ-DTMwHuLn.js → blockDiagram-WCTKOSBZ-ya8VAc2k.js} +1 -1
- package/dist/assets/{c4Diagram-IC4MRINW-BTKlkXI9.js → c4Diagram-IC4MRINW-CY1dZmIZ.js} +1 -1
- package/dist/assets/channel-BMhScXFe.js +1 -0
- package/dist/assets/{chunk-4BX2VUAB-DUdoTxAc.js → chunk-4BX2VUAB-CR1lAd74.js} +1 -1
- package/dist/assets/{chunk-55IACEB6-Bm_92xe4.js → chunk-55IACEB6-CP98WcFC.js} +1 -1
- package/dist/assets/{chunk-FMBD7UC4-CGW0g62g.js → chunk-FMBD7UC4-D9c7ijAB.js} +1 -1
- package/dist/assets/{chunk-JSJVCQXG-DYkTH3w1.js → chunk-JSJVCQXG-DQAGYOn-.js} +1 -1
- package/dist/assets/{chunk-KX2RTZJC-C9oTlISU.js → chunk-KX2RTZJC-BbTXiDq7.js} +1 -1
- package/dist/assets/{chunk-NQ4KR5QH-CM50ygWP.js → chunk-NQ4KR5QH-BI6AX0dr.js} +1 -1
- package/dist/assets/{chunk-QZHKN3VN-7dzpYeNJ.js → chunk-QZHKN3VN-DB3V2Ifo.js} +1 -1
- package/dist/assets/{chunk-WL4C6EOR-Cm9nQrsr.js → chunk-WL4C6EOR-DhzTthv6.js} +1 -1
- package/dist/assets/classDiagram-VBA2DB6C-CMIxlWcT.js +1 -0
- package/dist/assets/classDiagram-v2-RAHNMMFH-CMIxlWcT.js +1 -0
- package/dist/assets/clone-BPqOt4r3.js +1 -0
- package/dist/assets/{cose-bilkent-S5V4N54A-Ccp_p0JZ.js → cose-bilkent-S5V4N54A-BQ09ZE2j.js} +1 -1
- package/dist/assets/{dagre-KLK3FWXG-fBwTLUp9.js → dagre-KLK3FWXG-Dc2ueD_R.js} +1 -1
- package/dist/assets/{diagram-E7M64L7V-CeNVmFUp.js → diagram-E7M64L7V-DP-LsQoL.js} +1 -1
- package/dist/assets/{diagram-IFDJBPK2-CtavyLGa.js → diagram-IFDJBPK2-Cg6r42cB.js} +1 -1
- package/dist/assets/{diagram-P4PSJMXO-CpQTjQwc.js → diagram-P4PSJMXO-aHsfoUZE.js} +1 -1
- package/dist/assets/{erDiagram-INFDFZHY-B8R5vwhd.js → erDiagram-INFDFZHY-qBXJ4aAz.js} +1 -1
- package/dist/assets/{flowDiagram-PKNHOUZH-BvkVVwIQ.js → flowDiagram-PKNHOUZH-D_13emJM.js} +1 -1
- package/dist/assets/{ganttDiagram-A5KZAMGK-DOu3hSNa.js → ganttDiagram-A5KZAMGK-BvIcOLwz.js} +1 -1
- package/dist/assets/{gitGraphDiagram-K3NZZRJ6-C7zT67YE.js → gitGraphDiagram-K3NZZRJ6-ad0vvNcU.js} +1 -1
- package/dist/assets/{graph-D11wiwHo.js → graph-CeJCMjan.js} +1 -1
- package/dist/assets/{highlighted-body-TPN3WLV5-Babpthg-.js → highlighted-body-TPN3WLV5-B_novwSz.js} +1 -1
- package/dist/assets/index-C514cLyb.js +2 -0
- package/dist/assets/index-h1DBl_g3.css +1 -0
- package/dist/assets/{infoDiagram-LFFYTUFH-BmA7IpQG.js → infoDiagram-LFFYTUFH-lOxAqb3m.js} +1 -1
- package/dist/assets/{ishikawaDiagram-PHBUUO56-BEquZd3E.js → ishikawaDiagram-PHBUUO56-DIr-51gj.js} +1 -1
- package/dist/assets/{journeyDiagram-4ABVD52K-BfemGz7f.js → journeyDiagram-4ABVD52K-CYcIW0ZU.js} +1 -1
- package/dist/assets/{kanban-definition-K7BYSVSG-CWja3mln.js → kanban-definition-K7BYSVSG-C1ZK616a.js} +1 -1
- package/dist/assets/{layout-BLUNf-PJ.js → layout-CI2RM-v6.js} +1 -1
- package/dist/assets/{linear-DukIV_Xv.js → linear-DE7bISck.js} +1 -1
- package/dist/assets/{mermaid-O7DHMXV3-SgtM28qI.js → mermaid-O7DHMXV3-XxAJo8EK.js} +6 -6
- package/dist/assets/{mindmap-definition-YRQLILUH-4UjqXITU.js → mindmap-definition-YRQLILUH-Dz6EFjmn.js} +1 -1
- package/dist/assets/{pieDiagram-SKSYHLDU-8AxqJd0M.js → pieDiagram-SKSYHLDU-DPpEzUed.js} +1 -1
- package/dist/assets/{quadrantDiagram-337W2JSQ-D60m8V8r.js → quadrantDiagram-337W2JSQ-xdoXNet7.js} +1 -1
- package/dist/assets/{requirementDiagram-Z7DCOOCP-zqh9jBVf.js → requirementDiagram-Z7DCOOCP-DUq8H3CL.js} +1 -1
- package/dist/assets/{sankeyDiagram-WA2Y5GQK-CDZILTLI.js → sankeyDiagram-WA2Y5GQK-CmqEUxRu.js} +1 -1
- package/dist/assets/{sequenceDiagram-2WXFIKYE-7BReFd0L.js → sequenceDiagram-2WXFIKYE-DhtXRNiH.js} +1 -1
- package/dist/assets/{stateDiagram-RAJIS63D-HPTVdIG4.js → stateDiagram-RAJIS63D-Dj0HOlbN.js} +1 -1
- package/dist/assets/stateDiagram-v2-FVOUBMTO-C9utf5gv.js +1 -0
- package/dist/assets/{timeline-definition-YZTLITO2-CTVllFgr.js → timeline-definition-YZTLITO2-DUuJzZB5.js} +1 -1
- package/dist/assets/{treemap-KZPCXAKY-BtyxboJZ.js → treemap-KZPCXAKY-DpYBQ0qr.js} +1 -1
- package/dist/assets/vendor-codemirror-CMHSJ_9p.js +9 -0
- package/dist/assets/{vendor-react-Cpt6D04s.js → vendor-react-xmA_f8ig.js} +1 -1
- package/dist/assets/{vennDiagram-LZ73GAT5-D96ZI6Mg.js → vennDiagram-LZ73GAT5-DpePUyOd.js} +1 -1
- package/dist/assets/{xychartDiagram-JWTSCODW-eRk-39YO.js → xychartDiagram-JWTSCODW-Cfp1I4_U.js} +1 -1
- package/dist/index.html +5 -5
- package/package.json +8 -7
- package/server/acp-runtime/client.js +129 -16
- package/server/acp-runtime/index.js +54 -0
- package/server/acp-runtime/registry.js +2 -2
- package/server/acp-runtime/session-store.js +79 -5
- package/server/cli.js +55 -10
- package/server/database/db.js +20 -0
- package/server/external-agent/service.js +24 -6
- package/server/external-agent/ws.js +540 -27
- package/server/index.js +112 -151
- package/server/lan-access/core.js +79 -0
- package/server/lan-access/state.js +102 -0
- package/server/middleware/auth.js +57 -14
- package/server/projects.js +930 -667
- package/server/routes/auth.js +24 -4
- package/server/routes/cli-auth.js +21 -25
- package/server/routes/codex.js +84 -298
- package/server/routes/commands.js +322 -407
- package/server/routes/lan-access.js +231 -0
- package/server/routes/projects.js +154 -158
- package/server/routes/session-core.js +160 -91
- package/server/routes/settings.js +113 -99
- package/server/session-core/eventStore.js +60 -20
- package/server/session-core/providerAdapters.js +75 -38
- package/server/session-core/runtimeState.js +8 -0
- package/server/session-core/sessionListMerge.js +47 -0
- package/shared/conversationEvents.js +174 -15
- package/shared/modelConstants.js +79 -99
- package/dist/assets/App-CTKZtqB1.js +0 -460
- package/dist/assets/ReviewApp-DM6BNAzR.js +0 -1
- package/dist/assets/channel-1oJBvF-0.js +0 -1
- package/dist/assets/classDiagram-VBA2DB6C-d5TeKFM4.js +0 -1
- package/dist/assets/classDiagram-v2-RAHNMMFH-d5TeKFM4.js +0 -1
- package/dist/assets/clone-CinxIlEu.js +0 -1
- package/dist/assets/index-DFxzgWoO.js +0 -2
- package/dist/assets/index-YCFGDVKw.css +0 -1
- package/dist/assets/stateDiagram-v2-FVOUBMTO-DTUf5_gC.js +0 -1
- package/dist/assets/vendor-codemirror-Dz7_EqNA.js +0 -39
- package/server/_legacy-providers/README.md +0 -30
- package/server/_legacy-providers/claude-sdk.js +0 -956
- package/server/_legacy-providers/gemini-cli.js +0 -368
- package/server/_legacy-providers/openai-codex.js +0 -705
- package/server/_legacy-providers/opencode-cli.js +0 -674
- package/server/routes/git.js +0 -1110
- package/server/routes/mcp-utils.js +0 -48
- package/server/routes/mcp.js +0 -536
- package/server/routes/taskmaster.js +0 -1963
- package/server/utils/mcp-detector.js +0 -198
- package/server/utils/taskmaster-websocket.js +0 -129
|
@@ -1,368 +0,0 @@
|
|
|
1
|
-
import { spawn } from 'child_process';
|
|
2
|
-
import crossSpawn from 'cross-spawn';
|
|
3
|
-
import { resolveWorkingDirectory } from './utils/defaultWorkingDirectory.js';
|
|
4
|
-
|
|
5
|
-
const spawnFunction = process.platform === 'win32' ? crossSpawn : spawn;
|
|
6
|
-
|
|
7
|
-
const activeGeminiProcesses = new Map();
|
|
8
|
-
|
|
9
|
-
function collectTextChunks(payload) {
|
|
10
|
-
if (!payload) return [];
|
|
11
|
-
if (typeof payload === 'string') return payload.trim() ? [payload] : [];
|
|
12
|
-
|
|
13
|
-
const chunks = [];
|
|
14
|
-
|
|
15
|
-
if (Array.isArray(payload)) {
|
|
16
|
-
payload.forEach(item => {
|
|
17
|
-
chunks.push(...collectTextChunks(item));
|
|
18
|
-
});
|
|
19
|
-
return chunks;
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
if (typeof payload !== 'object') {
|
|
23
|
-
return chunks;
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
const directKeys = ['text', 'response', 'content', 'message', 'delta'];
|
|
27
|
-
for (const key of directKeys) {
|
|
28
|
-
if (payload[key] !== undefined) {
|
|
29
|
-
chunks.push(...collectTextChunks(payload[key]));
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
if (Array.isArray(payload.parts)) {
|
|
34
|
-
payload.parts.forEach(part => {
|
|
35
|
-
chunks.push(...collectTextChunks(part));
|
|
36
|
-
});
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
if (payload.data && typeof payload.data === 'object') {
|
|
40
|
-
chunks.push(...collectTextChunks(payload.data));
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
return chunks;
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
function getEventRole(event) {
|
|
47
|
-
return (
|
|
48
|
-
event?.role ||
|
|
49
|
-
event?.author ||
|
|
50
|
-
event?.sender ||
|
|
51
|
-
event?.message?.role ||
|
|
52
|
-
event?.data?.role ||
|
|
53
|
-
event?.content?.role ||
|
|
54
|
-
null
|
|
55
|
-
);
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
function extractAssistantTextChunks(event, command) {
|
|
59
|
-
const role = String(getEventRole(event) || '').toLowerCase();
|
|
60
|
-
if (role === 'user') return [];
|
|
61
|
-
|
|
62
|
-
const eventType = String(event?.type || event?.event || event?.kind || '').toLowerCase();
|
|
63
|
-
const hasAssistantPayload = !!(event?.response || event?.candidates || event?.delta || event?.text || event?.content || event?.message);
|
|
64
|
-
if (eventType.includes('prompt') && !hasAssistantPayload) {
|
|
65
|
-
return [];
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
const normalizedPrompt = String(command || '').trim();
|
|
69
|
-
return collectTextChunks(event).filter((text) => {
|
|
70
|
-
const trimmed = String(text || '').trim();
|
|
71
|
-
if (!trimmed) return false;
|
|
72
|
-
if (normalizedPrompt && trimmed === normalizedPrompt) return false;
|
|
73
|
-
return true;
|
|
74
|
-
});
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
function parseGeminiJsonLine(line) {
|
|
78
|
-
const trimmed = line.trim();
|
|
79
|
-
if (!trimmed) return null;
|
|
80
|
-
|
|
81
|
-
const payload = trimmed.startsWith('data:') ? trimmed.slice(5).trim() : trimmed;
|
|
82
|
-
if (!payload) return null;
|
|
83
|
-
|
|
84
|
-
return JSON.parse(payload);
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
function emitTextChunks(ws, sessionId, chunks) {
|
|
88
|
-
chunks.forEach((text) => {
|
|
89
|
-
if (!text) return;
|
|
90
|
-
ws.send({
|
|
91
|
-
type: 'claude-response',
|
|
92
|
-
data: {
|
|
93
|
-
type: 'content_block_delta',
|
|
94
|
-
delta: {
|
|
95
|
-
type: 'text_delta',
|
|
96
|
-
text
|
|
97
|
-
}
|
|
98
|
-
},
|
|
99
|
-
provider: 'gemini',
|
|
100
|
-
sessionId
|
|
101
|
-
});
|
|
102
|
-
});
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
function formatGeminiProcessError(code, stderrOutput) {
|
|
106
|
-
const normalizedStderr = String(stderrOutput || '').trim();
|
|
107
|
-
if (normalizedStderr) {
|
|
108
|
-
const apiMessageMatch =
|
|
109
|
-
normalizedStderr.match(/"message":"([^"]+)"/) ||
|
|
110
|
-
normalizedStderr.match(/message:\s*"([^"]+)"/i) ||
|
|
111
|
-
normalizedStderr.match(/ApiError:\s*\{.*?"message":"([^"]+)"/i) ||
|
|
112
|
-
normalizedStderr.match(/Error when talking to Gemini API[\s\S]*?message":"([^"]+)"/i);
|
|
113
|
-
|
|
114
|
-
if (apiMessageMatch?.[1]) {
|
|
115
|
-
return apiMessageMatch[1];
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
const firstMeaningfulLine = normalizedStderr
|
|
119
|
-
.split('\n')
|
|
120
|
-
.map((line) => line.trim())
|
|
121
|
-
.find((line) => line && !line.startsWith('at '));
|
|
122
|
-
|
|
123
|
-
if (firstMeaningfulLine) {
|
|
124
|
-
return firstMeaningfulLine;
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
return normalizedStderr;
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
return `Gemini CLI exited with code ${code}`;
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
function extractGeminiEventError(event) {
|
|
134
|
-
if (!event || typeof event !== 'object') {
|
|
135
|
-
return null;
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
const candidates = [
|
|
139
|
-
event?.error?.message,
|
|
140
|
-
event?.error?.details,
|
|
141
|
-
event?.result?.error?.message,
|
|
142
|
-
event?.result?.error,
|
|
143
|
-
event?.data?.error?.message,
|
|
144
|
-
event?.data?.error,
|
|
145
|
-
event?.message
|
|
146
|
-
];
|
|
147
|
-
|
|
148
|
-
for (const candidate of candidates) {
|
|
149
|
-
const normalized = String(candidate || '').trim();
|
|
150
|
-
if (normalized) {
|
|
151
|
-
return normalized;
|
|
152
|
-
}
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
return null;
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
async function queryGemini(command, options = {}, ws) {
|
|
159
|
-
return new Promise((resolve, reject) => {
|
|
160
|
-
const { sessionId, cwd, projectPath, resume, model, permissionMode } = options;
|
|
161
|
-
let capturedSessionId = sessionId;
|
|
162
|
-
let sentSessionCreated = false;
|
|
163
|
-
let stderrBuffer = '';
|
|
164
|
-
let fatalErrorSent = false;
|
|
165
|
-
let sawSuccessfulTerminalEvent = false;
|
|
166
|
-
let sawErroredTerminalEvent = false;
|
|
167
|
-
|
|
168
|
-
const args = ['-y', '@google/gemini-cli'];
|
|
169
|
-
|
|
170
|
-
if (sessionId && (resume || !command || !command.trim())) {
|
|
171
|
-
args.push('--resume', sessionId);
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
if (command && command.trim()) {
|
|
175
|
-
args.push('--prompt', command);
|
|
176
|
-
args.push('--output-format', 'stream-json');
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
if (model) {
|
|
180
|
-
args.push('--model', model);
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
if (permissionMode === 'bypassPermissions' || permissionMode === 'acceptEdits') {
|
|
184
|
-
args.push('--yolo');
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
const workingDir = resolveWorkingDirectory({ cwd, projectPath });
|
|
188
|
-
|
|
189
|
-
const geminiProcess = spawnFunction('npx', args, {
|
|
190
|
-
cwd: workingDir,
|
|
191
|
-
stdio: ['pipe', 'pipe', 'pipe'],
|
|
192
|
-
env: {
|
|
193
|
-
...process.env,
|
|
194
|
-
GEMINI_NONINTERACTIVE: '1'
|
|
195
|
-
}
|
|
196
|
-
});
|
|
197
|
-
|
|
198
|
-
const processKey = capturedSessionId || Date.now().toString();
|
|
199
|
-
let processRegistryKey = processKey;
|
|
200
|
-
activeGeminiProcesses.set(processRegistryKey, geminiProcess);
|
|
201
|
-
|
|
202
|
-
const finalizeSessionId = () => capturedSessionId || sessionId || null;
|
|
203
|
-
const emitFatalError = (errorMessage) => {
|
|
204
|
-
if (fatalErrorSent || !errorMessage) {
|
|
205
|
-
return;
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
fatalErrorSent = true;
|
|
209
|
-
ws.send({
|
|
210
|
-
type: 'claude-error',
|
|
211
|
-
error: errorMessage,
|
|
212
|
-
provider: 'gemini',
|
|
213
|
-
sessionId: finalizeSessionId()
|
|
214
|
-
});
|
|
215
|
-
};
|
|
216
|
-
|
|
217
|
-
const handleJsonEvent = (event) => {
|
|
218
|
-
const incomingSessionId = event?.session_id || event?.sessionId || event?.data?.session_id || event?.data?.sessionId;
|
|
219
|
-
if (incomingSessionId && !capturedSessionId) {
|
|
220
|
-
capturedSessionId = incomingSessionId;
|
|
221
|
-
if (ws.setSessionId && typeof ws.setSessionId === 'function') {
|
|
222
|
-
ws.setSessionId(capturedSessionId);
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
if (processRegistryKey !== capturedSessionId) {
|
|
226
|
-
activeGeminiProcesses.delete(processRegistryKey);
|
|
227
|
-
activeGeminiProcesses.set(capturedSessionId, geminiProcess);
|
|
228
|
-
processRegistryKey = capturedSessionId;
|
|
229
|
-
}
|
|
230
|
-
|
|
231
|
-
if (!sessionId && !sentSessionCreated) {
|
|
232
|
-
sentSessionCreated = true;
|
|
233
|
-
ws.send({
|
|
234
|
-
type: 'session-created',
|
|
235
|
-
sessionId: capturedSessionId,
|
|
236
|
-
provider: 'gemini'
|
|
237
|
-
});
|
|
238
|
-
}
|
|
239
|
-
}
|
|
240
|
-
|
|
241
|
-
const type = event?.type || event?.event || event?.kind;
|
|
242
|
-
if (type === 'result' || type === 'done' || type === 'complete') {
|
|
243
|
-
const eventStatus = String(event?.status || event?.result?.status || '').trim().toLowerCase();
|
|
244
|
-
const eventError = extractGeminiEventError(event);
|
|
245
|
-
if (eventStatus === 'error' || eventError) {
|
|
246
|
-
sawErroredTerminalEvent = true;
|
|
247
|
-
emitFatalError(eventError || 'Gemini CLI request failed');
|
|
248
|
-
return;
|
|
249
|
-
}
|
|
250
|
-
|
|
251
|
-
sawSuccessfulTerminalEvent = true;
|
|
252
|
-
ws.send({
|
|
253
|
-
type: 'claude-response',
|
|
254
|
-
data: { type: 'content_block_stop' },
|
|
255
|
-
provider: 'gemini',
|
|
256
|
-
sessionId: finalizeSessionId()
|
|
257
|
-
});
|
|
258
|
-
|
|
259
|
-
ws.send({
|
|
260
|
-
type: 'gemini-result',
|
|
261
|
-
data: event,
|
|
262
|
-
sessionId: finalizeSessionId()
|
|
263
|
-
});
|
|
264
|
-
return;
|
|
265
|
-
}
|
|
266
|
-
|
|
267
|
-
const textChunks = extractAssistantTextChunks(event, command);
|
|
268
|
-
emitTextChunks(ws, finalizeSessionId(), textChunks);
|
|
269
|
-
};
|
|
270
|
-
|
|
271
|
-
let stdoutBuffer = '';
|
|
272
|
-
geminiProcess.stdout.on('data', (data) => {
|
|
273
|
-
stdoutBuffer += data.toString();
|
|
274
|
-
const lines = stdoutBuffer.split('\n');
|
|
275
|
-
stdoutBuffer = lines.pop() || '';
|
|
276
|
-
|
|
277
|
-
for (const line of lines) {
|
|
278
|
-
try {
|
|
279
|
-
const event = parseGeminiJsonLine(line);
|
|
280
|
-
if (!event) continue;
|
|
281
|
-
handleJsonEvent(event);
|
|
282
|
-
} catch {}
|
|
283
|
-
}
|
|
284
|
-
});
|
|
285
|
-
|
|
286
|
-
geminiProcess.stderr.on('data', (data) => {
|
|
287
|
-
const chunk = data.toString();
|
|
288
|
-
stderrBuffer += chunk;
|
|
289
|
-
|
|
290
|
-
const normalizedChunk = chunk.trim();
|
|
291
|
-
if (normalizedChunk) {
|
|
292
|
-
console.warn('Gemini CLI stderr:', normalizedChunk);
|
|
293
|
-
}
|
|
294
|
-
});
|
|
295
|
-
|
|
296
|
-
geminiProcess.on('close', (code) => {
|
|
297
|
-
if (stdoutBuffer.trim()) {
|
|
298
|
-
try {
|
|
299
|
-
const finalEvent = parseGeminiJsonLine(stdoutBuffer);
|
|
300
|
-
if (finalEvent) {
|
|
301
|
-
handleJsonEvent(finalEvent);
|
|
302
|
-
}
|
|
303
|
-
} catch {}
|
|
304
|
-
}
|
|
305
|
-
|
|
306
|
-
activeGeminiProcesses.delete(processRegistryKey);
|
|
307
|
-
|
|
308
|
-
if (code === 0 && !sawErroredTerminalEvent) {
|
|
309
|
-
if (!sawSuccessfulTerminalEvent) {
|
|
310
|
-
ws.send({
|
|
311
|
-
type: 'claude-response',
|
|
312
|
-
data: { type: 'content_block_stop' },
|
|
313
|
-
provider: 'gemini',
|
|
314
|
-
sessionId: finalizeSessionId()
|
|
315
|
-
});
|
|
316
|
-
}
|
|
317
|
-
|
|
318
|
-
ws.send({
|
|
319
|
-
type: 'claude-complete',
|
|
320
|
-
sessionId: finalizeSessionId(),
|
|
321
|
-
provider: 'gemini',
|
|
322
|
-
exitCode: code,
|
|
323
|
-
isNewSession: !sessionId && !!command
|
|
324
|
-
});
|
|
325
|
-
resolve();
|
|
326
|
-
} else {
|
|
327
|
-
const errorMessage = formatGeminiProcessError(code, stderrBuffer);
|
|
328
|
-
emitFatalError(errorMessage);
|
|
329
|
-
reject(new Error(errorMessage));
|
|
330
|
-
}
|
|
331
|
-
});
|
|
332
|
-
|
|
333
|
-
geminiProcess.on('error', (error) => {
|
|
334
|
-
activeGeminiProcesses.delete(processRegistryKey);
|
|
335
|
-
|
|
336
|
-
emitFatalError(error.message);
|
|
337
|
-
|
|
338
|
-
reject(error);
|
|
339
|
-
});
|
|
340
|
-
|
|
341
|
-
geminiProcess.stdin.end();
|
|
342
|
-
});
|
|
343
|
-
}
|
|
344
|
-
|
|
345
|
-
function abortGeminiSession(sessionId) {
|
|
346
|
-
const process = activeGeminiProcesses.get(sessionId);
|
|
347
|
-
if (process) {
|
|
348
|
-
process.kill('SIGTERM');
|
|
349
|
-
activeGeminiProcesses.delete(sessionId);
|
|
350
|
-
return true;
|
|
351
|
-
}
|
|
352
|
-
return false;
|
|
353
|
-
}
|
|
354
|
-
|
|
355
|
-
function isGeminiSessionActive(sessionId) {
|
|
356
|
-
return activeGeminiProcesses.has(sessionId);
|
|
357
|
-
}
|
|
358
|
-
|
|
359
|
-
function getActiveGeminiSessions() {
|
|
360
|
-
return Array.from(activeGeminiProcesses.keys());
|
|
361
|
-
}
|
|
362
|
-
|
|
363
|
-
export {
|
|
364
|
-
queryGemini,
|
|
365
|
-
abortGeminiSession,
|
|
366
|
-
isGeminiSessionActive,
|
|
367
|
-
getActiveGeminiSessions
|
|
368
|
-
};
|