genbox 1.0.213 → 1.0.215
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/commands/session/watch.js +117 -3
- package/package.json +1 -1
|
@@ -97,6 +97,61 @@ async function fetchLiveState(sessionId) {
|
|
|
97
97
|
return null;
|
|
98
98
|
}
|
|
99
99
|
}
|
|
100
|
+
/**
|
|
101
|
+
* Fetch sessions for a specific genbox from API
|
|
102
|
+
* Queries both ClaudeSession (monitoring) and Session (sync) collections
|
|
103
|
+
*/
|
|
104
|
+
async function fetchGenboxSessions(genboxId) {
|
|
105
|
+
const allSessions = [];
|
|
106
|
+
try {
|
|
107
|
+
// Try ClaudeSession (monitoring) first
|
|
108
|
+
const claudeSessions = await (0, api_1.fetchApi)(`/claude/sessions/genbox/${genboxId}`);
|
|
109
|
+
if (Array.isArray(claudeSessions)) {
|
|
110
|
+
allSessions.push(...claudeSessions);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
catch {
|
|
114
|
+
// Ignore errors
|
|
115
|
+
}
|
|
116
|
+
try {
|
|
117
|
+
// Also query Session (sync) collection
|
|
118
|
+
const sessions = await (0, api_1.fetchApi)(`/sessions/v2?limit=50`);
|
|
119
|
+
if (sessions && Array.isArray(sessions.sessions)) {
|
|
120
|
+
// Filter to cloud type sessions that might belong to this genbox
|
|
121
|
+
const cloudSessions = sessions.sessions.filter((s) => s.type === 'cloud');
|
|
122
|
+
allSessions.push(...cloudSessions);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
catch {
|
|
126
|
+
// Ignore errors
|
|
127
|
+
}
|
|
128
|
+
return allSessions;
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Match a remote session name to an API session
|
|
132
|
+
* Remote session names are like "claude-abc123" (from socket file)
|
|
133
|
+
* API sessions have dtachSocket paths like "/home/dev/.genbox/sockets/claude-abc123.sock"
|
|
134
|
+
*/
|
|
135
|
+
function matchRemoteSessionToApiSession(remoteName, apiSessions) {
|
|
136
|
+
for (const apiSession of apiSessions) {
|
|
137
|
+
// Match by socket path
|
|
138
|
+
if (apiSession.dtachSocket) {
|
|
139
|
+
const socketName = apiSession.dtachSocket.split('/').pop()?.replace('.sock', '');
|
|
140
|
+
if (socketName === remoteName) {
|
|
141
|
+
return apiSession;
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
// Match by tmux session name (legacy)
|
|
145
|
+
if (apiSession.tmuxSession === remoteName) {
|
|
146
|
+
return apiSession;
|
|
147
|
+
}
|
|
148
|
+
// Match by session ID prefix
|
|
149
|
+
if (apiSession.sessionId?.startsWith(remoteName) || remoteName.includes(apiSession.sessionId?.substring(0, 8))) {
|
|
150
|
+
return apiSession;
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
return null;
|
|
154
|
+
}
|
|
100
155
|
/**
|
|
101
156
|
* Collect session states from all sources
|
|
102
157
|
*/
|
|
@@ -158,6 +213,21 @@ async function collectSessionStates(options) {
|
|
|
158
213
|
});
|
|
159
214
|
}
|
|
160
215
|
// Process remote sessions from cloud genboxes
|
|
216
|
+
// Group remote sessions by genbox to batch API calls
|
|
217
|
+
const remoteByGenbox = new Map();
|
|
218
|
+
for (const remote of result.remoteSessions) {
|
|
219
|
+
const key = remote.genboxId;
|
|
220
|
+
if (!remoteByGenbox.has(key)) {
|
|
221
|
+
remoteByGenbox.set(key, []);
|
|
222
|
+
}
|
|
223
|
+
remoteByGenbox.get(key).push(remote);
|
|
224
|
+
}
|
|
225
|
+
// Fetch API sessions for each genbox in parallel
|
|
226
|
+
const genboxSessionsMap = new Map();
|
|
227
|
+
await Promise.all(Array.from(remoteByGenbox.keys()).map(async (genboxId) => {
|
|
228
|
+
const apiSessions = await fetchGenboxSessions(genboxId);
|
|
229
|
+
genboxSessionsMap.set(genboxId, apiSessions);
|
|
230
|
+
}));
|
|
161
231
|
for (const remote of result.remoteSessions) {
|
|
162
232
|
// Filter by genbox if specified
|
|
163
233
|
if (options.genbox && !remote.genboxName.toLowerCase().includes(options.genbox.toLowerCase()))
|
|
@@ -168,14 +238,58 @@ async function collectSessionStates(options) {
|
|
|
168
238
|
// Remote sessions are running by definition (we found their socket)
|
|
169
239
|
if (options.status === 'stopped')
|
|
170
240
|
continue;
|
|
241
|
+
// Try to match this remote session to an API session (ClaudeSession)
|
|
242
|
+
const apiSessions = genboxSessionsMap.get(remote.genboxId) || [];
|
|
243
|
+
const matchedApiSession = matchRemoteSessionToApiSession(remote.name, apiSessions);
|
|
244
|
+
// ClaudeSession has status: 'active', 'idle', 'waiting_input', 'error', 'ended'
|
|
245
|
+
// Map to our display states
|
|
246
|
+
const apiStatus = matchedApiSession?.status;
|
|
247
|
+
let displayStatus = 'running';
|
|
248
|
+
let displayState;
|
|
249
|
+
if (matchedApiSession) {
|
|
250
|
+
// We have API data - use it
|
|
251
|
+
switch (apiStatus) {
|
|
252
|
+
case 'active':
|
|
253
|
+
displayStatus = 'running';
|
|
254
|
+
displayState = 'thinking';
|
|
255
|
+
break;
|
|
256
|
+
case 'waiting_input':
|
|
257
|
+
displayStatus = 'idle';
|
|
258
|
+
displayState = 'waiting_for_input';
|
|
259
|
+
break;
|
|
260
|
+
case 'idle':
|
|
261
|
+
displayStatus = 'idle';
|
|
262
|
+
displayState = 'waiting_for_input';
|
|
263
|
+
break;
|
|
264
|
+
case 'error':
|
|
265
|
+
displayStatus = 'error';
|
|
266
|
+
break;
|
|
267
|
+
case 'ended':
|
|
268
|
+
displayStatus = 'stopped';
|
|
269
|
+
break;
|
|
270
|
+
default:
|
|
271
|
+
displayStatus = 'running';
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
else {
|
|
275
|
+
// No API data - session is running (we found socket) but state is unknown
|
|
276
|
+
displayStatus = 'running';
|
|
277
|
+
displayState = undefined; // Will show as "idle" indicator but no state text
|
|
278
|
+
}
|
|
171
279
|
states.push({
|
|
172
|
-
id: remote.name.substring(0, 8),
|
|
280
|
+
id: matchedApiSession?.sessionId?.substring(0, 8) || remote.name.substring(0, 8),
|
|
173
281
|
name: remote.name,
|
|
174
282
|
provider: remote.provider,
|
|
175
283
|
type: 'cloud',
|
|
176
284
|
genbox: remote.genboxName,
|
|
177
|
-
status:
|
|
178
|
-
|
|
285
|
+
status: displayStatus,
|
|
286
|
+
state: displayState,
|
|
287
|
+
currentTool: undefined, // ClaudeSession doesn't track current tool
|
|
288
|
+
lastMessage: matchedApiSession?.lastPrompt?.substring(0, 50),
|
|
289
|
+
duration: matchedApiSession?.createdAt ? formatDuration(matchedApiSession.createdAt) : '?',
|
|
290
|
+
createdAt: matchedApiSession?.createdAt,
|
|
291
|
+
toolCalls: matchedApiSession?.toolUseCount,
|
|
292
|
+
messagesCount: matchedApiSession?.promptCount,
|
|
179
293
|
});
|
|
180
294
|
}
|
|
181
295
|
// Also add cloud genboxes that might have sessions we didn't scan
|