diff --git a/apps/cli/src/commands/context.command.ts b/apps/cli/src/commands/context.command.ts index 13e86c60..dc2f0fc7 100644 --- a/apps/cli/src/commands/context.command.ts +++ b/apps/cli/src/commands/context.command.ts @@ -501,7 +501,7 @@ export class ContextCommand extends Command { if (!briefId) { spinner.fail('Could not extract a brief ID from the provided input'); ui.displayError( - `Provide a valid brief ID or a Hamster brief URL, e.g. https://${process.env.TM_PUBLIC_BASE_DOMAIN}/home/hamster/briefs/` + `Provide a valid brief ID or a Hamster brief URL, e.g. https://${process.env.TM_BASE_DOMAIN || process.env.TM_PUBLIC_BASE_DOMAIN}/home/hamster/briefs/` ); process.exit(1); } diff --git a/packages/tm-core/src/auth/credential-store.ts b/packages/tm-core/src/auth/credential-store.ts index 1d4b2776..fa33ee37 100644 --- a/packages/tm-core/src/auth/credential-store.ts +++ b/packages/tm-core/src/auth/credential-store.ts @@ -24,6 +24,8 @@ export class CredentialStore { private config: AuthConfig; // Clock skew tolerance for expiry checks (30 seconds) private readonly CLOCK_SKEW_MS = 30_000; + // Track if we've already warned about missing expiration to avoid spam + private hasWarnedAboutMissingExpiration = false; private constructor(config?: Partial) { this.config = getAuthConfig(config); @@ -84,7 +86,11 @@ export class CredentialStore { // Validate expiration time for tokens if (expiresAtMs === undefined) { - this.logger.warn('No valid expiration time provided for token'); + // Only log this warning once to avoid spam during auth flows + if (!this.hasWarnedAboutMissingExpiration) { + this.logger.warn('No valid expiration time provided for token'); + this.hasWarnedAboutMissingExpiration = true; + } return null; } @@ -174,6 +180,9 @@ export class CredentialStore { mode: 0o600 }); fs.renameSync(tempFile, this.config.configFile); + + // Reset the warning flag so it can be shown again for future invalid tokens + this.hasWarnedAboutMissingExpiration = false; } catch (error) { throw new AuthenticationError( `Failed to save auth credentials: ${(error as Error).message}`, diff --git a/packages/tm-core/src/services/export.service.ts b/packages/tm-core/src/services/export.service.ts index 90630ef1..94e3bfe6 100644 --- a/packages/tm-core/src/services/export.service.ts +++ b/packages/tm-core/src/services/export.service.ts @@ -358,11 +358,12 @@ export class ExportService { tasks: any[] ): Promise { // Check if we should use the API endpoint or direct Supabase - const useAPIEndpoint = process.env.TM_PUBLIC_BASE_DOMAIN; + const apiEndpoint = + process.env.TM_BASE_DOMAIN || process.env.TM_PUBLIC_BASE_DOMAIN; - if (useAPIEndpoint) { + if (apiEndpoint) { // Use the new bulk import API endpoint - const apiUrl = `${process.env.TM_PUBLIC_BASE_DOMAIN}/ai/api/v1/briefs/${briefId}/tasks`; + const apiUrl = `${apiEndpoint}/ai/api/v1/briefs/${briefId}/tasks`; // Transform tasks to flat structure for API const flatTasks = this.transformTasksForBulkImport(tasks); diff --git a/scripts/dev.js b/scripts/dev.js index dbf1895a..8902d390 100755 --- a/scripts/dev.js +++ b/scripts/dev.js @@ -9,6 +9,8 @@ */ import dotenv from 'dotenv'; + +// Load .env BEFORE any other imports to ensure env vars are available dotenv.config(); // Add at the very beginning of the file @@ -16,7 +18,8 @@ if (process.env.DEBUG === '1') { console.error('DEBUG - dev.js received args:', process.argv.slice(2)); } -import { runCLI } from './modules/commands.js'; +// Use dynamic import to ensure dotenv.config() runs before module-level code executes +const { runCLI } = await import('./modules/commands.js'); // Run the CLI with the process arguments runCLI(process.argv);