genbox 1.0.213 → 1.0.214
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.
|
@@ -97,6 +97,43 @@ async function fetchLiveState(sessionId) {
|
|
|
97
97
|
return null;
|
|
98
98
|
}
|
|
99
99
|
}
|
|
100
|
+
/**
|
|
101
|
+
* Fetch Claude sessions for a specific genbox from API
|
|
102
|
+
*/
|
|
103
|
+
async function fetchGenboxSessions(genboxId) {
|
|
104
|
+
try {
|
|
105
|
+
const response = await (0, api_1.fetchApi)(`/claude/sessions/genbox/${genboxId}`);
|
|
106
|
+
return Array.isArray(response) ? response : [];
|
|
107
|
+
}
|
|
108
|
+
catch {
|
|
109
|
+
return [];
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Match a remote session name to an API session
|
|
114
|
+
* Remote session names are like "claude-abc123" (from socket file)
|
|
115
|
+
* API sessions have dtachSocket paths like "/home/dev/.genbox/sockets/claude-abc123.sock"
|
|
116
|
+
*/
|
|
117
|
+
function matchRemoteSessionToApiSession(remoteName, apiSessions) {
|
|
118
|
+
for (const apiSession of apiSessions) {
|
|
119
|
+
// Match by socket path
|
|
120
|
+
if (apiSession.dtachSocket) {
|
|
121
|
+
const socketName = apiSession.dtachSocket.split('/').pop()?.replace('.sock', '');
|
|
122
|
+
if (socketName === remoteName) {
|
|
123
|
+
return apiSession;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
// Match by tmux session name (legacy)
|
|
127
|
+
if (apiSession.tmuxSession === remoteName) {
|
|
128
|
+
return apiSession;
|
|
129
|
+
}
|
|
130
|
+
// Match by session ID prefix
|
|
131
|
+
if (apiSession.sessionId?.startsWith(remoteName) || remoteName.includes(apiSession.sessionId?.substring(0, 8))) {
|
|
132
|
+
return apiSession;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
return null;
|
|
136
|
+
}
|
|
100
137
|
/**
|
|
101
138
|
* Collect session states from all sources
|
|
102
139
|
*/
|
|
@@ -158,6 +195,21 @@ async function collectSessionStates(options) {
|
|
|
158
195
|
});
|
|
159
196
|
}
|
|
160
197
|
// Process remote sessions from cloud genboxes
|
|
198
|
+
// Group remote sessions by genbox to batch API calls
|
|
199
|
+
const remoteByGenbox = new Map();
|
|
200
|
+
for (const remote of result.remoteSessions) {
|
|
201
|
+
const key = remote.genboxId;
|
|
202
|
+
if (!remoteByGenbox.has(key)) {
|
|
203
|
+
remoteByGenbox.set(key, []);
|
|
204
|
+
}
|
|
205
|
+
remoteByGenbox.get(key).push(remote);
|
|
206
|
+
}
|
|
207
|
+
// Fetch API sessions for each genbox in parallel
|
|
208
|
+
const genboxSessionsMap = new Map();
|
|
209
|
+
await Promise.all(Array.from(remoteByGenbox.keys()).map(async (genboxId) => {
|
|
210
|
+
const apiSessions = await fetchGenboxSessions(genboxId);
|
|
211
|
+
genboxSessionsMap.set(genboxId, apiSessions);
|
|
212
|
+
}));
|
|
161
213
|
for (const remote of result.remoteSessions) {
|
|
162
214
|
// Filter by genbox if specified
|
|
163
215
|
if (options.genbox && !remote.genboxName.toLowerCase().includes(options.genbox.toLowerCase()))
|
|
@@ -168,14 +220,58 @@ async function collectSessionStates(options) {
|
|
|
168
220
|
// Remote sessions are running by definition (we found their socket)
|
|
169
221
|
if (options.status === 'stopped')
|
|
170
222
|
continue;
|
|
223
|
+
// Try to match this remote session to an API session (ClaudeSession)
|
|
224
|
+
const apiSessions = genboxSessionsMap.get(remote.genboxId) || [];
|
|
225
|
+
const matchedApiSession = matchRemoteSessionToApiSession(remote.name, apiSessions);
|
|
226
|
+
// ClaudeSession has status: 'active', 'idle', 'waiting_input', 'error', 'ended'
|
|
227
|
+
// Map to our display states
|
|
228
|
+
const apiStatus = matchedApiSession?.status;
|
|
229
|
+
let displayStatus = 'running';
|
|
230
|
+
let displayState;
|
|
231
|
+
if (matchedApiSession) {
|
|
232
|
+
// We have API data - use it
|
|
233
|
+
switch (apiStatus) {
|
|
234
|
+
case 'active':
|
|
235
|
+
displayStatus = 'running';
|
|
236
|
+
displayState = 'thinking';
|
|
237
|
+
break;
|
|
238
|
+
case 'waiting_input':
|
|
239
|
+
displayStatus = 'idle';
|
|
240
|
+
displayState = 'waiting_for_input';
|
|
241
|
+
break;
|
|
242
|
+
case 'idle':
|
|
243
|
+
displayStatus = 'idle';
|
|
244
|
+
displayState = 'waiting_for_input';
|
|
245
|
+
break;
|
|
246
|
+
case 'error':
|
|
247
|
+
displayStatus = 'error';
|
|
248
|
+
break;
|
|
249
|
+
case 'ended':
|
|
250
|
+
displayStatus = 'stopped';
|
|
251
|
+
break;
|
|
252
|
+
default:
|
|
253
|
+
displayStatus = 'running';
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
else {
|
|
257
|
+
// No API data - session is running (we found socket) but state is unknown
|
|
258
|
+
displayStatus = 'running';
|
|
259
|
+
displayState = undefined; // Will show as "idle" indicator but no state text
|
|
260
|
+
}
|
|
171
261
|
states.push({
|
|
172
|
-
id: remote.name.substring(0, 8),
|
|
262
|
+
id: matchedApiSession?.sessionId?.substring(0, 8) || remote.name.substring(0, 8),
|
|
173
263
|
name: remote.name,
|
|
174
264
|
provider: remote.provider,
|
|
175
265
|
type: 'cloud',
|
|
176
266
|
genbox: remote.genboxName,
|
|
177
|
-
status:
|
|
178
|
-
|
|
267
|
+
status: displayStatus,
|
|
268
|
+
state: displayState,
|
|
269
|
+
currentTool: undefined, // ClaudeSession doesn't track current tool
|
|
270
|
+
lastMessage: matchedApiSession?.lastPrompt?.substring(0, 50),
|
|
271
|
+
duration: matchedApiSession?.createdAt ? formatDuration(matchedApiSession.createdAt) : '?',
|
|
272
|
+
createdAt: matchedApiSession?.createdAt,
|
|
273
|
+
toolCalls: matchedApiSession?.toolUseCount,
|
|
274
|
+
messagesCount: matchedApiSession?.promptCount,
|
|
179
275
|
});
|
|
180
276
|
}
|
|
181
277
|
// Also add cloud genboxes that might have sessions we didn't scan
|