thrust-cli 1.0.5 → 1.0.7

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/index.js CHANGED
@@ -3,8 +3,9 @@
3
3
  import { Command } from 'commander';
4
4
  import fs from 'fs';
5
5
  import path from 'path';
6
+ import os from 'os';
7
+ import { exec } from 'child_process';
6
8
  import { fileURLToPath } from 'url';
7
- import AutoLaunch from 'auto-launch';
8
9
  import { startDaemon } from './utils/daemon.js';
9
10
  import { getConfig, saveConfig } from './utils/config.js';
10
11
 
@@ -28,7 +29,7 @@ program
28
29
  .action(async (options) => {
29
30
  console.log('šŸš€ Booting Thrust Agent...');
30
31
 
31
- await enableAutoLaunchSafe();
32
+ await setupNativeStartup();
32
33
 
33
34
  startDaemon(parseInt(options.port, 10));
34
35
  });
@@ -58,37 +59,95 @@ program
58
59
 
59
60
  program.parse(process.argv);
60
61
 
61
- async function enableAutoLaunchSafe() {
62
+ // --- NATIVE, CROSS-PLATFORM OS STARTUP LOGIC ---
63
+ async function setupNativeStartup() {
64
+ // 1. Termux (Android)
62
65
  if (process.env.TERMUX_VERSION) {
63
- console.log('šŸ“± Termux detected: Skipping desktop AutoLaunch. (Tip: Use termux-boot to run on startup)');
66
+ console.log('šŸ“± Termux detected: (Tip: Use the `termux-boot` app for OS startup).');
64
67
  return;
65
68
  }
69
+
70
+ // 2. Windows
71
+ if (process.platform === 'win32') {
72
+ 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
+ const startupFolder = path.join(os.homedir(), 'AppData', 'Roaming', 'Microsoft', 'Windows', 'Start Menu', 'Programs', 'Startup');
77
+ 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`;
79
+
80
+ if (!fs.existsSync(startupFolder)) fs.mkdirSync(startupFolder, { recursive: true });
81
+ fs.writeFileSync(batFilePath, batContent, 'utf8');
82
+ console.log('āš™ļø Windows Startup Script active.');
83
+ } catch (err) {
84
+ console.log(`āš ļø Failed to create Windows startup script: ${err.message}`);
85
+ }
86
+ }
66
87
 
67
- if (process.platform === 'linux' && !process.env.DISPLAY) {
68
- console.log('šŸ–„ļø Headless Linux detected: Skipping GUI AutoLaunch. (Tip: Set up a systemd service)');
69
- return;
70
- }
88
+ // 3. macOS
89
+ else if (process.platform === 'darwin') {
90
+ try {
91
+ const launchAgentsDir = path.join(os.homedir(), 'Library', 'LaunchAgents');
92
+ const plistPath = path.join(launchAgentsDir, 'com.thrust.agent.plist');
93
+
94
+ // Native Mac LaunchDaemon XML Configuration
95
+ const plistContent = `<?xml version="1.0" encoding="UTF-8"?>
96
+ <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
97
+ <plist version="1.0">
98
+ <dict>
99
+ <key>Label</key>
100
+ <string>com.thrust.agent</string>
101
+ <key>ProgramArguments</key>
102
+ <array>
103
+ <string>${process.execPath}</string>
104
+ <string>${__filename}</string>
105
+ </array>
106
+ <key>RunAtLoad</key>
107
+ <true/>
108
+ <key>KeepAlive</key>
109
+ <true/>
110
+ </dict>
111
+ </plist>`;
112
+
113
+ if (!fs.existsSync(launchAgentsDir)) fs.mkdirSync(launchAgentsDir, { recursive: true });
114
+ fs.writeFileSync(plistPath, plistContent, 'utf8');
115
+
116
+ // Register it quietly with the Mac OS
117
+ exec(`launchctl load -w "${plistPath}"`, () => {});
118
+ console.log('āš™ļø macOS LaunchAgent active (Will run silently in background on boot).');
119
+ } catch (err) {
120
+ console.log(`āš ļø Failed to create macOS LaunchAgent: ${err.message}`);
121
+ }
122
+ }
123
+
124
+ // 4. Linux (Ubuntu, Debian, Fedora, Mint, etc.)
125
+ else if (process.platform === 'linux') {
126
+ try {
127
+ if (!process.env.DISPLAY) {
128
+ console.log('šŸ–„ļø Headless Linux detected: Skipping GUI Autostart.');
129
+ return;
130
+ }
131
+
132
+ const autostartDir = path.join(os.homedir(), '.config', 'autostart');
133
+ const desktopPath = path.join(autostartDir, 'thrust-agent.desktop');
134
+
135
+ // Native Linux XDG Autostart File
136
+ const desktopContent = `[Desktop Entry]
137
+ Type=Application
138
+ Exec="${process.execPath}" "${__filename}"
139
+ Hidden=false
140
+ NoDisplay=false
141
+ X-GNOME-Autostart-enabled=true
142
+ Name=Thrust Local Agent
143
+ Comment=Proactive AI Project Director
144
+ Terminal=true`;
71
145
 
72
- try {
73
- // FIX: Combine Node executable and script path into a single safely-quoted string
74
- // This ensures Windows registry executes exactly: "C:\Program Files\nodejs\node.exe" "C:\path\to\index.js"
75
- const launchPath = `"${process.execPath}" "${__filename}"`;
76
-
77
- const thrustAutoLauncher = new AutoLaunch({
78
- name: 'ThrustAgent',
79
- path: launchPath
80
- });
81
-
82
- const isEnabled = await thrustAutoLauncher.isEnabled();
83
- if (!isEnabled) {
84
- await thrustAutoLauncher.enable();
85
- console.log('āš™ļø Added to OS Startup programs.');
86
- } else {
87
- // Because we changed the path format, we should overwrite the broken registry key
88
- await thrustAutoLauncher.enable();
89
- console.log('āš™ļø OS Startup auto-launch is active (Registry updated).');
146
+ if (!fs.existsSync(autostartDir)) fs.mkdirSync(autostartDir, { recursive: true });
147
+ fs.writeFileSync(desktopPath, desktopContent, 'utf8');
148
+ console.log('āš™ļø Linux Autostart active (A terminal will open automatically on next reboot).');
149
+ } catch (err) {
150
+ console.log(`āš ļø Failed to create Linux startup script: ${err.message}`);
90
151
  }
91
- } catch (err) {
92
- console.log(`āš ļø Auto-launch setup skipped (not supported on this setup).`);
93
152
  }
94
153
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "thrust-cli",
3
- "version": "1.0.5",
3
+ "version": "1.0.7",
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,7 +151,7 @@ export async function startDaemon(preferredPort) {
151
151
  }
152
152
  }
153
153
 
154
- // --- BULLETPROOF BROWSER OPENER ---
154
+ // --- BULLETPROOF BROWSER OPENER WITH LOGGING ---
155
155
  async function safeOpenBrowser(url) {
156
156
  try {
157
157
  if (process.env.TERMUX_VERSION) {
@@ -161,24 +161,22 @@ async function safeOpenBrowser(url) {
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
165
  try {
165
- // OS-Specific Chrome Executable Names to force App Mode
166
+ // Try Chrome App Mode First
166
167
  const chromeName = process.platform === 'darwin' ? 'google chrome' :
167
168
  process.platform === 'win32' ? 'chrome' : 'google-chrome';
168
169
 
169
- // Force a small, docked 800x600 native app window without toolbars
170
170
  await open(url, {
171
- app: {
172
- name: chromeName,
173
- arguments: [`--app=${url}`, '--window-size=800,600']
174
- }
171
+ app: { name: chromeName, arguments: [`--app=${url}`, '--window-size=1000,800'] }
175
172
  });
176
173
  } catch (err) {
177
- // If Chrome isn't installed, fail gracefully to the default normal browser
174
+ // If Chrome fails (e.g., Windows Server EC2 often doesn't have Chrome in path),
175
+ // just use the absolute default system opener.
178
176
  try {
179
177
  await open(url);
180
178
  } catch (fallbackErr) {
181
- console.log("\nšŸ‘‰ OS prevented launching the browser automatically. Please open the URL above manually.\n");
179
+ console.log("\nšŸ‘‰ OS security prevented auto-launching the browser. Please open the URL above manually.\n");
182
180
  }
183
181
  }
184
182
  }