@geekbeer/minion 2.16.2 → 2.16.4

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.
Files changed (2) hide show
  1. package/package.json +1 -1
  2. package/routes/auth.js +62 -3
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@geekbeer/minion",
3
- "version": "2.16.2",
3
+ "version": "2.16.4",
4
4
  "description": "AI Agent runtime for Minion - manages status and skill deployment on VPS",
5
5
  "main": "server.js",
6
6
  "bin": {
package/routes/auth.js CHANGED
@@ -112,12 +112,15 @@ function startClaudeAuth() {
112
112
 
113
113
  try {
114
114
  // Start claude auth login in a new tmux session
115
- // -e flags pass environment variables to the tmux session
115
+ // Use inline env vars in the shell command for compatibility with all tmux versions
116
+ // (tmux -e flag requires tmux 3.2+)
116
117
  // CLAUDECODE='' prevents the nesting check
117
118
  execSync(
118
- `tmux new-session -d -s ${TMUX_SESSION} -x 500 -y 40 -e "HOME=${config.HOME_DIR}" -e "PATH=${extendedPath}" -e "CLAUDECODE=" 'claude auth login'`,
119
+ `tmux new-session -d -s ${TMUX_SESSION} -x 500 -y 40 'export HOME="${config.HOME_DIR}" PATH="${extendedPath}"; CLAUDECODE="" claude auth login'`,
119
120
  { timeout: 5000 }
120
121
  )
122
+ // Keep pane alive after command exits so we can capture error output
123
+ execSync(`tmux set-option -t ${TMUX_SESSION} remain-on-exit on`)
121
124
  } catch (err) {
122
125
  reject(new Error(`Failed to create tmux session: ${err.message}`))
123
126
  return
@@ -136,7 +139,16 @@ function startClaudeAuth() {
136
139
  const pollInterval = setInterval(() => {
137
140
  if (resolved) return
138
141
 
139
- if (!tmuxSessionExists()) {
142
+ // Check if the process inside the pane has exited (remain-on-exit keeps pane alive)
143
+ let paneDead = false
144
+ try {
145
+ const deadFlag = execSync(
146
+ `tmux list-panes -t ${TMUX_SESSION} -F '#{pane_dead}'`,
147
+ { encoding: 'utf-8', timeout: 3000 }
148
+ ).trim()
149
+ paneDead = deadFlag === '1'
150
+ } catch {
151
+ // Session itself is gone
140
152
  resolved = true
141
153
  clearInterval(pollInterval)
142
154
  reject(new Error('Auth session ended unexpectedly'))
@@ -146,6 +158,16 @@ function startClaudeAuth() {
146
158
  const content = captureTmuxPane()
147
159
  const clean = stripAnsi(content)
148
160
 
161
+ // If process exited, capture output for diagnostics and report error
162
+ if (paneDead) {
163
+ resolved = true
164
+ clearInterval(pollInterval)
165
+ console.error(`[Auth] Process exited. Pane output:\n${clean.slice(0, 1000)}`)
166
+ try { execSync(`tmux kill-session -t ${TMUX_SESSION} 2>/dev/null`) } catch {}
167
+ reject(new Error(`Auth process exited. Output: ${clean.slice(0, 300) || '(none)'}`))
168
+ return
169
+ }
170
+
149
171
  // Check for URL at any stage
150
172
  const url = extractUrlFromPane(content)
151
173
  if (url) {
@@ -206,11 +228,39 @@ function submitAuthCode(code) {
206
228
  return { success: false, error: 'No auth session running' }
207
229
  }
208
230
 
231
+ // Check if the process inside the pane is still alive
232
+ // (remain-on-exit keeps the session but the process may have exited)
233
+ try {
234
+ const deadFlag = execSync(
235
+ `tmux list-panes -t ${TMUX_SESSION} -F '#{pane_dead}'`,
236
+ { encoding: 'utf-8', timeout: 3000 }
237
+ ).trim()
238
+ if (deadFlag === '1') {
239
+ const content = captureTmuxPane()
240
+ const clean = stripAnsi(content).trim()
241
+ console.error(`[Auth] Cannot submit code: auth process already exited. Pane output:\n${clean.slice(0, 500)}`)
242
+ try { execSync(`tmux kill-session -t ${TMUX_SESSION} 2>/dev/null`) } catch {}
243
+ return { success: false, error: `Auth process already exited. Output: ${clean.slice(0, 200) || '(none)'}` }
244
+ }
245
+ } catch {
246
+ return { success: false, error: 'No auth session running' }
247
+ }
248
+
209
249
  try {
210
250
  console.log('[Auth] Submitting auth code to tmux session')
211
251
  // Use send-keys with -l (literal) to avoid interpreting special chars
212
252
  execSync(`tmux send-keys -t ${TMUX_SESSION} -l '${code.replace(/'/g, "'\\''")}'`)
213
253
  execSync(`tmux send-keys -t ${TMUX_SESSION} Enter`)
254
+
255
+ // Log pane content after submission for diagnostics
256
+ setTimeout(() => {
257
+ try {
258
+ const content = captureTmuxPane()
259
+ const clean = stripAnsi(content).trim()
260
+ console.log(`[Auth] Pane content after code submission:\n${clean.slice(0, 500)}`)
261
+ } catch {}
262
+ }, 3000)
263
+
214
264
  return { success: true }
215
265
  } catch (err) {
216
266
  console.error(`[Auth] Failed to send code: ${err.message}`)
@@ -344,6 +394,15 @@ async function authRoutes(fastify) {
344
394
  // During active auth flow, bypass cache so credential changes are detected immediately
345
395
  if (authInProgress) {
346
396
  clearLlmCache()
397
+
398
+ // Log credential file check for diagnostics
399
+ const credPaths = [
400
+ path.join(config.HOME_DIR, '.claude', '.credentials.json'),
401
+ path.join(config.HOME_DIR, '.claude', 'credentials.json'),
402
+ ]
403
+ for (const p of credPaths) {
404
+ console.log(`[Auth] Checking ${p}: ${fs.existsSync(p) ? 'EXISTS' : 'not found'}`)
405
+ }
347
406
  }
348
407
 
349
408
  const services = getLlmServices()