thrust-cli 1.0.7 → 1.0.9

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 (3) hide show
  1. package/index.js +9 -12
  2. package/package.json +1 -1
  3. package/utils/daemon.js +21 -17
package/index.js CHANGED
@@ -4,7 +4,6 @@ import { Command } from 'commander';
4
4
  import fs from 'fs';
5
5
  import path from 'path';
6
6
  import os from 'os';
7
- import { exec } from 'child_process';
8
7
  import { fileURLToPath } from 'url';
9
8
  import { startDaemon } from './utils/daemon.js';
10
9
  import { getConfig, saveConfig } from './utils/config.js';
@@ -67,15 +66,14 @@ async function setupNativeStartup() {
67
66
  return;
68
67
  }
69
68
 
70
- // 2. Windows
69
+ // 2. Windows - Clean, direct global execution
71
70
  if (process.platform === 'win32') {
72
71
  try {
73
- // Cleanup ghost registry key from old auto-launch package
74
- exec('reg delete "HKCU\\Software\\Microsoft\\Windows\\CurrentVersion\\Run" /v "ThrustAgent" /f', () => {});
75
-
76
72
  const startupFolder = path.join(os.homedir(), 'AppData', 'Roaming', 'Microsoft', 'Windows', 'Start Menu', 'Programs', 'Startup');
77
73
  const batFilePath = path.join(startupFolder, 'thrust-agent.bat');
78
- const batContent = `@echo off\ntitle Thrust Local Agent\necho Starting Thrust...\ntimeout /t 3 /nobreak > NUL\n"${process.execPath}" "${__filename}"\npause`;
74
+
75
+ // Clean batch script that simply calls the global `thrust` command
76
+ const batContent = `@echo off\ntitle Thrust Local Agent\necho Starting Thrust...\ntimeout /t 2 /nobreak > NUL\nthrust\npause`;
79
77
 
80
78
  if (!fs.existsSync(startupFolder)) fs.mkdirSync(startupFolder, { recursive: true });
81
79
  fs.writeFileSync(batFilePath, batContent, 'utf8');
@@ -85,13 +83,12 @@ async function setupNativeStartup() {
85
83
  }
86
84
  }
87
85
 
88
- // 3. macOS
86
+ // 3. macOS - Requires absolute paths due to empty launchd $PATH
89
87
  else if (process.platform === 'darwin') {
90
88
  try {
91
89
  const launchAgentsDir = path.join(os.homedir(), 'Library', 'LaunchAgents');
92
90
  const plistPath = path.join(launchAgentsDir, 'com.thrust.agent.plist');
93
91
 
94
- // Native Mac LaunchDaemon XML Configuration
95
92
  const plistContent = `<?xml version="1.0" encoding="UTF-8"?>
96
93
  <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
97
94
  <plist version="1.0">
@@ -113,15 +110,16 @@ async function setupNativeStartup() {
113
110
  if (!fs.existsSync(launchAgentsDir)) fs.mkdirSync(launchAgentsDir, { recursive: true });
114
111
  fs.writeFileSync(plistPath, plistContent, 'utf8');
115
112
 
116
- // Register it quietly with the Mac OS
117
- exec(`launchctl load -w "${plistPath}"`, () => {});
113
+ import('child_process').then(({ exec }) => {
114
+ exec(`launchctl load -w "${plistPath}"`, () => {});
115
+ });
118
116
  console.log('⚙️ macOS LaunchAgent active (Will run silently in background on boot).');
119
117
  } catch (err) {
120
118
  console.log(`⚠️ Failed to create macOS LaunchAgent: ${err.message}`);
121
119
  }
122
120
  }
123
121
 
124
- // 4. Linux (Ubuntu, Debian, Fedora, Mint, etc.)
122
+ // 4. Linux - Requires absolute paths for FreeDesktop compliance
125
123
  else if (process.platform === 'linux') {
126
124
  try {
127
125
  if (!process.env.DISPLAY) {
@@ -132,7 +130,6 @@ async function setupNativeStartup() {
132
130
  const autostartDir = path.join(os.homedir(), '.config', 'autostart');
133
131
  const desktopPath = path.join(autostartDir, 'thrust-agent.desktop');
134
132
 
135
- // Native Linux XDG Autostart File
136
133
  const desktopContent = `[Desktop Entry]
137
134
  Type=Application
138
135
  Exec="${process.execPath}" "${__filename}"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "thrust-cli",
3
- "version": "1.0.7",
3
+ "version": "1.0.9",
4
4
  "description": "The local agent for Thrust AI Director",
5
5
  "type": "module",
6
6
  "homepage": "https://thrust.web.app",
package/utils/daemon.js CHANGED
@@ -151,33 +151,37 @@ export async function startDaemon(preferredPort) {
151
151
  }
152
152
  }
153
153
 
154
- // --- BULLETPROOF BROWSER OPENER WITH LOGGING ---
154
+ // --- INTELLIGENT BROWSER OPENER ---
155
155
  async function safeOpenBrowser(url) {
156
156
  try {
157
157
  if (process.env.TERMUX_VERSION) {
158
- exec(`termux-open-url ${url}`, (err) => {
159
- if (err) console.log("👉 Please open the URL manually.");
158
+ exec(`termux-open-url ${url}`, () => {
159
+ console.log("👉 Please open the URL manually in your mobile browser.");
160
160
  });
161
161
  } else if (!process.env.DISPLAY && process.platform === 'linux') {
162
162
  console.log("👉 [Headless] Please open the URL manually in a browser.");
163
163
  } else {
164
- console.log("🌐 Attempting to launch browser window...");
164
+ const chromeName = process.platform === 'darwin' ? 'google chrome' :
165
+ process.platform === 'win32' ? 'chrome' : 'google-chrome';
166
+
167
+ console.log("🌐 Attempting to launch dashboard in App Mode...");
168
+
165
169
  try {
166
- // Try Chrome App Mode First
167
- const chromeName = process.platform === 'darwin' ? 'google chrome' :
168
- process.platform === 'win32' ? 'chrome' : 'google-chrome';
169
-
170
- await open(url, {
170
+ // ATTEMPT 1: Try Chrome App Mode
171
+ const browserProcess = await open(url, {
171
172
  app: { name: chromeName, arguments: [`--app=${url}`, '--window-size=1000,800'] }
172
173
  });
173
- } catch (err) {
174
- // If Chrome fails (e.g., Windows Server EC2 often doesn't have Chrome in path),
175
- // just use the absolute default system opener.
176
- try {
177
- await open(url);
178
- } catch (fallbackErr) {
179
- console.log("\n👉 OS security prevented auto-launching the browser. Please open the URL above manually.\n");
180
- }
174
+
175
+ // Catch asynchronous spawn failures (e.g., Windows when Chrome isn't in PATH)
176
+ browserProcess.on('error', async () => {
177
+ console.log("👉 Chrome App Mode failed. Falling back to default browser...");
178
+ await open(url).catch(()=>{});
179
+ });
180
+
181
+ } catch (chromeErr) {
182
+ // Catch synchronous promise rejections (e.g., Mac/Linux when Chrome is missing)
183
+ console.log("👉 Chrome App Mode unavailable. Falling back to default browser...");
184
+ await open(url);
181
185
  }
182
186
  }
183
187
  } catch (e) {