replit-tools 1.1.6 → 1.1.8

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "replit-tools",
3
- "version": "1.1.6",
3
+ "version": "1.1.8",
4
4
  "description": "DATA Tools - One command to set up Claude Code and Codex CLI on Replit with full persistence",
5
5
  "main": "index.js",
6
6
  "bin": {
@@ -240,85 +240,100 @@ if [[ ":$PATH:" != *":${LOCAL_BIN}:"* ]]; then
240
240
  fi
241
241
 
242
242
  # =============================================================================
243
- # Step 6: Auto-refresh OAuth token if needed
243
+ # Step 6: Auto-refresh OAuth token if needed (with loop prevention)
244
244
  # =============================================================================
245
245
  CREDENTIALS_FILE="${CLAUDE_PERSISTENT}/.credentials.json"
246
- if [ -f "${CREDENTIALS_FILE}" ] && [ -f "${AUTH_REFRESH_SCRIPT}" ]; then
247
- # Source the auth refresh script to get the function
248
- source "${AUTH_REFRESH_SCRIPT}"
249
-
250
- # Check and refresh if needed (this handles all the logic)
251
- if command -v node &> /dev/null; then
252
- AUTH_INFO=$(node -e "
253
- try {
254
- const creds = require('${CREDENTIALS_FILE}');
255
- const oauth = creds.claudeAiOauth;
256
- const apiKey = creds.primaryApiKey;
257
- if (apiKey) {
258
- console.log('apikey:permanent');
259
- } else if (oauth && oauth.expiresAt) {
260
- const now = Date.now();
261
- const remaining = Math.floor((oauth.expiresAt - now) / 1000 / 60 / 60);
262
- const hasRefresh = oauth.refreshToken ? 'yes' : 'no';
263
- console.log('oauth:' + remaining + ':' + hasRefresh);
264
- }
265
- } catch(e) { console.log('error'); }
266
- " 2>/dev/null)
267
-
268
- IFS=':' read -r auth_type remaining has_refresh <<< "${AUTH_INFO}"
269
-
270
- if [ "${auth_type}" = "apikey" ]; then
271
- log "✅ Claude authentication: API key (permanent)"
272
- elif [ "${auth_type}" = "oauth" ]; then
273
- if [ "${remaining}" -le 0 ]; then
274
- # Token expired - try to refresh
275
- if [ "${has_refresh}" = "yes" ]; then
276
- log "⚠️ Token expired, attempting refresh..."
277
- if refresh_token 2>/dev/null; then
278
- # Re-check the new expiry
279
- NEW_REMAINING=$(node -e "
280
- try {
281
- const creds = require('${CREDENTIALS_FILE}');
282
- const remaining = Math.floor((creds.claudeAiOauth.expiresAt - Date.now()) / 1000 / 60 / 60);
283
- console.log(remaining);
284
- } catch(e) { console.log('0'); }
285
- " 2>/dev/null)
286
- log " Claude authentication: refreshed (${NEW_REMAINING}h remaining)"
246
+ AUTH_FAILED_MARKER="${REPLIT_TOOLS}/.auth-refresh-failed"
247
+
248
+ # Clear failed marker if it's more than 1 hour old (allow retry after cooldown)
249
+ if [ -f "${AUTH_FAILED_MARKER}" ]; then
250
+ marker_age=$(( $(date +%s) - $(stat -c %Y "${AUTH_FAILED_MARKER}" 2>/dev/null || echo "0") ))
251
+ if [ "${marker_age}" -gt 3600 ]; then
252
+ rm -f "${AUTH_FAILED_MARKER}" 2>/dev/null
253
+ fi
254
+ fi
255
+
256
+ # Skip auth refresh if we already failed recently (file-based lock prevents loops)
257
+ if [ ! -f "${AUTH_FAILED_MARKER}" ] && [ -f "${CREDENTIALS_FILE}" ] && [ -f "${AUTH_REFRESH_SCRIPT}" ]; then
258
+ # Source the auth refresh script to get the function
259
+ source "${AUTH_REFRESH_SCRIPT}"
260
+
261
+ # Check and refresh if needed (this handles all the logic)
262
+ if command -v node &> /dev/null; then
263
+ AUTH_INFO=$(node -e "
264
+ try {
265
+ const creds = require('${CREDENTIALS_FILE}');
266
+ const oauth = creds.claudeAiOauth;
267
+ const apiKey = creds.primaryApiKey;
268
+ if (apiKey) {
269
+ console.log('apikey:permanent');
270
+ } else if (oauth && oauth.expiresAt) {
271
+ const now = Date.now();
272
+ const remaining = Math.floor((oauth.expiresAt - now) / 1000 / 60 / 60);
273
+ const hasRefresh = oauth.refreshToken ? 'yes' : 'no';
274
+ console.log('oauth:' + remaining + ':' + hasRefresh);
275
+ } else {
276
+ console.log('none');
277
+ }
278
+ } catch(e) { console.log('error'); }
279
+ " 2>/dev/null)
280
+
281
+ IFS=':' read -r auth_type remaining has_refresh <<< "${AUTH_INFO}"
282
+
283
+ if [ "${auth_type}" = "apikey" ]; then
284
+ log "✅ Claude authentication: API key (permanent)"
285
+ elif [ "${auth_type}" = "oauth" ]; then
286
+ if [ "${remaining}" -le 0 ]; then
287
+ # Token expired - try to refresh once
288
+ if [ "${has_refresh}" = "yes" ]; then
289
+ log "⚠️ Token expired, attempting refresh..."
290
+ if refresh_token 2>/dev/null; then
291
+ NEW_REMAINING=$(node -e "
292
+ try {
293
+ const creds = require('${CREDENTIALS_FILE}');
294
+ const remaining = Math.floor((creds.claudeAiOauth.expiresAt - Date.now()) / 1000 / 60 / 60);
295
+ console.log(remaining);
296
+ } catch(e) { console.log('0'); }
297
+ " 2>/dev/null)
298
+ log "✅ Claude authentication: refreshed (${NEW_REMAINING}h remaining)"
299
+ else
300
+ log "❌ Token refresh failed - run 'claude login' when ready"
301
+ touch "${AUTH_FAILED_MARKER}"
302
+ fi
287
303
  else
288
- log "❌ Token refresh failed - run: claude login"
304
+ log "❌ Token expired (no refresh token) - run 'claude login' when ready"
305
+ touch "${AUTH_FAILED_MARKER}"
289
306
  fi
290
- else
291
- log "❌ Token expired (no refresh token) - run: claude login"
292
- fi
293
- elif [ "${remaining}" -lt 2 ]; then
294
- # Less than 2 hours - refresh proactively
295
- if [ "${has_refresh}" = "yes" ]; then
296
- log "🔄 Token expires in ${remaining}h, refreshing..."
297
- if refresh_token 2>/dev/null; then
298
- NEW_REMAINING=$(node -e "
299
- try {
300
- const creds = require('${CREDENTIALS_FILE}');
301
- const remaining = Math.floor((creds.claudeAiOauth.expiresAt - Date.now()) / 1000 / 60 / 60);
302
- console.log(remaining);
303
- } catch(e) { console.log('0'); }
304
- " 2>/dev/null)
305
- log "✅ Claude authentication: refreshed (${NEW_REMAINING}h remaining)"
307
+ elif [ "${remaining}" -lt 2 ]; then
308
+ # Less than 2 hours - refresh proactively
309
+ if [ "${has_refresh}" = "yes" ]; then
310
+ log "🔄 Token expires in ${remaining}h, refreshing..."
311
+ if refresh_token 2>/dev/null; then
312
+ NEW_REMAINING=$(node -e "
313
+ try {
314
+ const creds = require('${CREDENTIALS_FILE}');
315
+ const remaining = Math.floor((creds.claudeAiOauth.expiresAt - Date.now()) / 1000 / 60 / 60);
316
+ console.log(remaining);
317
+ } catch(e) { console.log('0'); }
318
+ " 2>/dev/null)
319
+ log "✅ Claude authentication: refreshed (${NEW_REMAINING}h remaining)"
320
+ else
321
+ log "⚠️ Refresh failed, ${remaining}h remaining"
322
+ fi
306
323
  else
307
- log "⚠️ Refresh failed, ${remaining}h remaining"
324
+ log "⚠️ Claude authentication: ${remaining}h remaining (no refresh token)"
308
325
  fi
309
326
  else
310
- log "⚠️ Claude authentication: ${remaining}h remaining (no refresh token)"
327
+ log "Claude authentication: valid (${remaining}h remaining)"
311
328
  fi
312
- else
313
- log " Claude authentication: valid (${remaining}h remaining)"
329
+ elif [ "${auth_type}" = "none" ] || [ "${auth_type}" = "error" ]; then
330
+ log "⚠️ No valid auth - run 'claude login' when ready"
314
331
  fi
315
- elif [ "${auth_type}" = "error" ]; then
316
- log "⚠️ Could not read credentials"
317
332
  fi
318
- fi
333
+ elif [ -f "${AUTH_FAILED_MARKER}" ]; then
334
+ log "⏭️ Skipping auth check (refresh failed recently, retry in 1h or run 'claude login')"
319
335
  elif [ ! -f "${CREDENTIALS_FILE}" ]; then
320
- log "⚠️ No Claude credentials found. Run 'claude login' to authenticate"
321
- log " 💡 Tip: Run 'claude setup-token' for a long-lived token"
336
+ log "⚠️ No credentials - run 'claude login' when ready"
322
337
  fi
323
338
 
324
339
  # =============================================================================