@livedesk/client 0.1.23 → 0.1.24

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.
@@ -6,7 +6,7 @@ import path from 'path';
6
6
  import crypto from 'crypto';
7
7
  import { promises as fs, statfsSync } from 'fs';
8
8
 
9
- const AGENT_VERSION = '0.1.23-livedesk.1';
9
+ const AGENT_VERSION = '0.1.24-livedesk.1';
10
10
  const DEFAULT_MANAGER = '127.0.0.1:5197';
11
11
  const DEFAULT_HEARTBEAT_MS = 5000;
12
12
  const DEFAULT_RECONNECT_MS = 5000;
@@ -17,6 +17,7 @@ const DEFAULT_AUTH_CALLBACK_HOST = '127.0.0.1';
17
17
  const DEFAULT_AUTH_CALLBACK_PORT = 5198;
18
18
  const DISCOVERY_RETRY_MS = 5000;
19
19
  const EXIT_INVALID_PAIR_TOKEN = 23;
20
+ const SESSION_REFRESH_SKEW_SECONDS = 60;
20
21
  const SUPABASE_URL = process.env.LIVEDESK_SUPABASE_URL || 'https://otbyfkjxrkngvjziawki.supabase.co';
21
22
  const SUPABASE_PUBLISHABLE_KEY = process.env.LIVEDESK_SUPABASE_PUBLISHABLE_KEY || 'sb_publishable_NpUs0RDJH2YnllsqTKO6TQ_1jTdSsNQ';
22
23
  const CLIENT_STATE_DIR = join(os.homedir(), '.livedesk-client');
@@ -278,7 +279,7 @@ async function createSupabaseClient() {
278
279
  const { createClient } = await import('@supabase/supabase-js');
279
280
  return createClient(SUPABASE_URL, SUPABASE_PUBLISHABLE_KEY, {
280
281
  auth: {
281
- autoRefreshToken: true,
282
+ autoRefreshToken: false,
282
283
  persistSession: true,
283
284
  detectSessionInUrl: false,
284
285
  flowType: 'pkce',
@@ -288,6 +289,62 @@ async function createSupabaseClient() {
288
289
  });
289
290
  }
290
291
 
292
+ function getNestedErrorCode(error) {
293
+ let cursor = error;
294
+ for (let i = 0; i < 5 && cursor; i++) {
295
+ if (typeof cursor.code === 'string' && cursor.code.trim()) {
296
+ return cursor.code.trim();
297
+ }
298
+ cursor = cursor.cause;
299
+ }
300
+ return '';
301
+ }
302
+
303
+ function getNestedErrorMessage(error) {
304
+ const messages = [];
305
+ let cursor = error;
306
+ for (let i = 0; i < 5 && cursor; i++) {
307
+ if (typeof cursor.message === 'string' && cursor.message.trim()) {
308
+ messages.push(cursor.message.trim());
309
+ }
310
+ cursor = cursor.cause;
311
+ }
312
+ return messages.join(' ');
313
+ }
314
+
315
+ function isTransientNetworkError(error) {
316
+ const code = getNestedErrorCode(error).toUpperCase();
317
+ if (['ENOTFOUND', 'EAI_AGAIN', 'ECONNRESET', 'ECONNREFUSED', 'ETIMEDOUT', 'ENETUNREACH', 'EHOSTUNREACH'].includes(code)) {
318
+ return true;
319
+ }
320
+ return /fetch failed|network|dns|socket|connection|timeout|getaddrinfo/i.test(getNestedErrorMessage(error));
321
+ }
322
+
323
+ function formatDiscoveryError(error) {
324
+ if (isTransientNetworkError(error)) {
325
+ const code = getNestedErrorCode(error);
326
+ return `Network is not ready yet${code ? ` (${code})` : ''}. Waiting for DNS/Wi-Fi after sleep.`;
327
+ }
328
+ return error instanceof Error ? error.message : String(error);
329
+ }
330
+
331
+ async function refreshSessionIfNeeded(supabase) {
332
+ const { data: existing } = await supabase.auth.getSession();
333
+ const session = existing?.session;
334
+ if (!session?.access_token) {
335
+ return null;
336
+ }
337
+ const expiresAt = Number(session.expires_at || 0);
338
+ if (expiresAt <= 0 || expiresAt - Math.floor(Date.now() / 1000) > SESSION_REFRESH_SKEW_SECONDS) {
339
+ return session;
340
+ }
341
+ const { data, error } = await supabase.auth.refreshSession(session);
342
+ if (error) {
343
+ throw error;
344
+ }
345
+ return data?.session || session;
346
+ }
347
+
291
348
  function openBrowser(url) {
292
349
  if (os.platform() === 'win32') {
293
350
  spawn('rundll32.exe', ['url.dll,FileProtocolHandler', url], { detached: true, stdio: 'ignore', windowsHide: true }).unref();
@@ -533,6 +590,7 @@ function normalizeEndpointCandidates(target) {
533
590
  }
534
591
 
535
592
  async function resolveManagerFromSupabase(supabase, options = {}) {
593
+ await refreshSessionIfNeeded(supabase);
536
594
  const { data, error } = await supabase
537
595
  .from('livedesk_remote_host_targets')
538
596
  .select('endpoint, endpoint_candidates, pair_token, active, expires_at, updated_at, manager_version')
@@ -576,7 +634,7 @@ async function waitForManagerFromSupabase(supabase, options = {}) {
576
634
  try {
577
635
  return await resolveManagerFromSupabase(supabase, { requireReachable: true });
578
636
  } catch (err) {
579
- const message = err instanceof Error ? err.message : String(err);
637
+ const message = formatDiscoveryError(err);
580
638
  if (message !== lastMessage || attempts === 1 || attempts % 6 === 0) {
581
639
  const suffix = attempts === 1 ? '' : ` attempt ${attempts}`;
582
640
  console.log(`Still waiting for LiveDesk Hub${suffix}: ${message}`);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@livedesk/client",
3
- "version": "0.1.23",
3
+ "version": "0.1.24",
4
4
  "description": "LiveDesk local remote client",
5
5
  "type": "module",
6
6
  "bin": {