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: 'running',
178
- duration: '?',
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
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "genbox",
3
- "version": "1.0.213",
3
+ "version": "1.0.214",
4
4
  "description": "Genbox CLI - AI-Powered Development Environments",
5
5
  "main": "dist/index.js",
6
6
  "bin": {