life-pulse 2.4.1 → 2.4.2
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/dist/cli.js +88 -12
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -28,7 +28,7 @@ import { findHandlesForName } from './contacts.js';
|
|
|
28
28
|
import { ensurePromptLayerFiles } from './prompt-layers.js';
|
|
29
29
|
import { hasTailscale, startFunnel, getHostname as getTailscaleHostname } from './tunnel.js';
|
|
30
30
|
import chalk from 'chalk';
|
|
31
|
-
import { readFileSync, existsSync, mkdirSync, writeFileSync } from 'fs';
|
|
31
|
+
import { readFileSync, existsSync, mkdirSync, writeFileSync, cpSync, rmSync } from 'fs';
|
|
32
32
|
import { join, dirname } from 'path';
|
|
33
33
|
import { fileURLToPath } from 'url';
|
|
34
34
|
import { homedir } from 'os';
|
|
@@ -96,6 +96,31 @@ function normalizeHostOrIp(raw) {
|
|
|
96
96
|
t = t.replace(/:\d+$/, '');
|
|
97
97
|
return t.trim();
|
|
98
98
|
}
|
|
99
|
+
function resolveTailscaleBin() {
|
|
100
|
+
try {
|
|
101
|
+
const out = execSync('command -v tailscale', {
|
|
102
|
+
stdio: 'pipe',
|
|
103
|
+
timeout: 3000,
|
|
104
|
+
encoding: 'utf-8',
|
|
105
|
+
shell: '/bin/zsh',
|
|
106
|
+
}).trim();
|
|
107
|
+
if (out)
|
|
108
|
+
return out;
|
|
109
|
+
}
|
|
110
|
+
catch { }
|
|
111
|
+
const candidates = [
|
|
112
|
+
'/Applications/Tailscale.app/Contents/MacOS/Tailscale',
|
|
113
|
+
join(homedir(), 'Applications', 'Tailscale.app', 'Contents', 'MacOS', 'Tailscale'),
|
|
114
|
+
];
|
|
115
|
+
for (const c of candidates) {
|
|
116
|
+
if (existsSync(c))
|
|
117
|
+
return c;
|
|
118
|
+
}
|
|
119
|
+
return '';
|
|
120
|
+
}
|
|
121
|
+
function hasUsableTailscale() {
|
|
122
|
+
return !!resolveTailscaleBin();
|
|
123
|
+
}
|
|
99
124
|
function extractExecOutput(error) {
|
|
100
125
|
const e = error;
|
|
101
126
|
const stdout = typeof e?.stdout === 'string' ? e.stdout : Buffer.isBuffer(e?.stdout) ? e.stdout.toString('utf-8') : '';
|
|
@@ -137,11 +162,27 @@ function detectOpenClawToken() {
|
|
|
137
162
|
return '';
|
|
138
163
|
}
|
|
139
164
|
function detectTailscaleHostOrIp() {
|
|
140
|
-
const
|
|
141
|
-
if (
|
|
142
|
-
return
|
|
165
|
+
const bin = resolveTailscaleBin();
|
|
166
|
+
if (!bin)
|
|
167
|
+
return '';
|
|
168
|
+
try {
|
|
169
|
+
const out = execFileSync(bin, ['status', '--json'], {
|
|
170
|
+
stdio: 'pipe',
|
|
171
|
+
timeout: 5000,
|
|
172
|
+
encoding: 'utf-8',
|
|
173
|
+
});
|
|
174
|
+
const status = JSON.parse(out);
|
|
175
|
+
const dns = normalizeHostOrIp(String(status?.Self?.DNSName || '').replace(/\.$/, ''));
|
|
176
|
+
if (dns)
|
|
177
|
+
return dns;
|
|
178
|
+
const ips = Array.isArray(status?.Self?.TailscaleIPs) ? status.Self.TailscaleIPs : [];
|
|
179
|
+
const ip = ips.find((x) => typeof x === 'string' && /^100\.\d+\.\d+\.\d+$/.test(x));
|
|
180
|
+
if (ip)
|
|
181
|
+
return String(ip);
|
|
182
|
+
}
|
|
183
|
+
catch { }
|
|
143
184
|
try {
|
|
144
|
-
const out =
|
|
185
|
+
const out = execFileSync(bin, ['ip', '-4'], {
|
|
145
186
|
stdio: 'pipe',
|
|
146
187
|
timeout: 5000,
|
|
147
188
|
encoding: 'utf-8',
|
|
@@ -166,32 +207,67 @@ function hasHomebrew() {
|
|
|
166
207
|
}
|
|
167
208
|
}
|
|
168
209
|
function installTailscaleIfMissing() {
|
|
169
|
-
if (
|
|
210
|
+
if (hasUsableTailscale())
|
|
170
211
|
return true;
|
|
171
|
-
if (
|
|
172
|
-
|
|
212
|
+
if (hasHomebrew()) {
|
|
213
|
+
try {
|
|
214
|
+
execSync('brew list --cask tailscale >/dev/null 2>&1 || brew install --cask tailscale', {
|
|
215
|
+
stdio: 'pipe',
|
|
216
|
+
timeout: 8 * 60 * 1000,
|
|
217
|
+
shell: '/bin/zsh',
|
|
218
|
+
});
|
|
219
|
+
}
|
|
220
|
+
catch { }
|
|
221
|
+
if (hasUsableTailscale())
|
|
222
|
+
return true;
|
|
223
|
+
}
|
|
224
|
+
// Homebrew-less fallback: install official app bundle from Tailscale zip.
|
|
173
225
|
try {
|
|
174
|
-
|
|
226
|
+
const tmpDir = join('/tmp', `life-pulse-ts-${Date.now()}`);
|
|
227
|
+
mkdirSync(tmpDir, { recursive: true });
|
|
228
|
+
const zipPath = join(tmpDir, 'tailscale.zip');
|
|
229
|
+
execSync(`curl -L --fail -o ${JSON.stringify(zipPath)} https://pkgs.tailscale.com/stable/Tailscale-latest-macos.zip`, {
|
|
175
230
|
stdio: 'pipe',
|
|
176
|
-
timeout:
|
|
231
|
+
timeout: 3 * 60 * 1000,
|
|
177
232
|
shell: '/bin/zsh',
|
|
178
233
|
});
|
|
234
|
+
execSync(`unzip -oq ${JSON.stringify(zipPath)} -d ${JSON.stringify(tmpDir)}`, {
|
|
235
|
+
stdio: 'pipe',
|
|
236
|
+
timeout: 60_000,
|
|
237
|
+
shell: '/bin/zsh',
|
|
238
|
+
});
|
|
239
|
+
const appSrc = join(tmpDir, 'Tailscale.app');
|
|
240
|
+
if (existsSync(appSrc)) {
|
|
241
|
+
const appDestSystem = '/Applications/Tailscale.app';
|
|
242
|
+
const appDestUser = join(homedir(), 'Applications', 'Tailscale.app');
|
|
243
|
+
try {
|
|
244
|
+
cpSync(appSrc, appDestSystem, { recursive: true, force: true });
|
|
245
|
+
}
|
|
246
|
+
catch {
|
|
247
|
+
mkdirSync(join(homedir(), 'Applications'), { recursive: true });
|
|
248
|
+
cpSync(appSrc, appDestUser, { recursive: true, force: true });
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
rmSync(tmpDir, { recursive: true, force: true });
|
|
179
252
|
}
|
|
180
253
|
catch { }
|
|
181
|
-
return
|
|
254
|
+
return hasUsableTailscale();
|
|
182
255
|
}
|
|
183
256
|
function extractTailscaleAuthUrl(output) {
|
|
184
257
|
const m = output.match(/https:\/\/login\.tailscale\.com\/[^\s"']+/i);
|
|
185
258
|
return m ? m[0] : '';
|
|
186
259
|
}
|
|
187
260
|
function kickOffTailscaleAuth() {
|
|
261
|
+
const bin = resolveTailscaleBin();
|
|
262
|
+
if (!bin)
|
|
263
|
+
return;
|
|
188
264
|
try {
|
|
189
265
|
execSync('open -g -a Tailscale', { stdio: 'pipe', timeout: 5000 });
|
|
190
266
|
}
|
|
191
267
|
catch { }
|
|
192
268
|
let output = '';
|
|
193
269
|
try {
|
|
194
|
-
output =
|
|
270
|
+
output = execFileSync(bin, ['up', '--accept-dns=false'], {
|
|
195
271
|
stdio: 'pipe',
|
|
196
272
|
timeout: 15_000,
|
|
197
273
|
encoding: 'utf-8',
|