@usagefleet/cli 1.2.160 → 1.2.162
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/README.md +7 -0
- package/dist/index.js +18 -5
- package/dist/release.js +1 -1
- package/dist/service.js +13 -3
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -211,6 +211,9 @@ until you re-run `usagefleet login` under the new one.
|
|
|
211
211
|
it holds your token.
|
|
212
212
|
- **Linux** — a `systemd --user` unit, plus `loginctl enable-linger $USER` so it
|
|
213
213
|
survives logout. If `systemctl` can't be driven it prints the manual steps.
|
|
214
|
+
- **Linux without systemd** (a Docker container, WSL without it) — no service.
|
|
215
|
+
Run `usagefleet watch` as the container's command or under your own
|
|
216
|
+
supervisor, with a restart policy such as `restart: unless-stopped`.
|
|
214
217
|
- **Windows** — a Scheduled Task (`usagefleet`) starting at logon, restarting on
|
|
215
218
|
failure, running hidden through a `wscript` launcher in
|
|
216
219
|
`%LOCALAPPDATA%\usagefleet` (which carries the env values set at install
|
|
@@ -231,6 +234,10 @@ restart the service on it. `usagefleet update` does the same on demand. npm is
|
|
|
231
234
|
called through the absolute path next to the running `node`, because a
|
|
232
235
|
launchd/systemd service gets a minimal PATH.
|
|
233
236
|
|
|
237
|
+
A `watch` that is not the installed service (a container's command, a
|
|
238
|
+
terminal) exits with code 75 after an update, so whatever runs it starts the
|
|
239
|
+
new version.
|
|
240
|
+
|
|
234
241
|
Every failure is a no-op — registry unreachable, non-semver version, npm
|
|
235
242
|
missing or exiting non-zero, local `dev` builds — and the service is only
|
|
236
243
|
restarted after npm reports success.
|
package/dist/index.js
CHANGED
|
@@ -9,7 +9,7 @@ import { loadNotifyConfig } from './notifier.js';
|
|
|
9
9
|
import { sendNotification } from './notify.js';
|
|
10
10
|
import { detectOs } from './os.js';
|
|
11
11
|
import { RELEASE_VERSION } from './release.js';
|
|
12
|
-
import { serviceStatus } from './service.js';
|
|
12
|
+
import { isServiceProcess, serviceStatus } from './service.js';
|
|
13
13
|
import { readStore, storePath, updateStore } from './store.js';
|
|
14
14
|
import { ago, bar, blue, dim, fail, green, header, hint, host, line, note, pct, row, state as stateLine, step, tilde, warn, yellow, } from './ui.js';
|
|
15
15
|
import { checkForUpdate } from './update.js';
|
|
@@ -112,7 +112,13 @@ async function cmdWatch() {
|
|
|
112
112
|
const nowMs = Date.now();
|
|
113
113
|
if (nowMs - lastUpdateAt >= updateInterval) {
|
|
114
114
|
lastUpdateAt = nowMs;
|
|
115
|
-
await checkForUpdate((level, m) => line(level === 'ok' ? blue('↻') : yellow('!'), m));
|
|
115
|
+
const updated = await checkForUpdate((level, m) => line(level === 'ok' ? blue('↻') : yellow('!'), m));
|
|
116
|
+
// `login` restarts only the installed service. Any other watch (a container's command, a terminal)
|
|
117
|
+
// exits so its supervisor starts the new version; non-zero because `restart: on-failure` ignores 0.
|
|
118
|
+
if (updated && !isServiceProcess()) {
|
|
119
|
+
line(blue('↻'), `exiting to restart on ${updated}`);
|
|
120
|
+
process.exit(75);
|
|
121
|
+
}
|
|
116
122
|
}
|
|
117
123
|
if (nowMs - lastLimitsAt >= limitsInterval) {
|
|
118
124
|
lastLimitsAt = nowMs;
|
|
@@ -176,9 +182,7 @@ async function cmdStatus() {
|
|
|
176
182
|
const creds = await detectClaudeCreds();
|
|
177
183
|
console.log(header());
|
|
178
184
|
console.log('');
|
|
179
|
-
console.log(svc
|
|
180
|
-
? stateLine('ok', 'service', `running${svc.pid ? dim(` · pid ${svc.pid}`) : ''}`)
|
|
181
|
-
: stateLine('bad', 'service', `${svc.state} ${dim(svc.state === 'stopped' ? '· check the log' : '· run `usagefleet login`')}`));
|
|
185
|
+
console.log(serviceLine(svc));
|
|
182
186
|
console.log(creds
|
|
183
187
|
? stateLine('ok', 'claude', `${creds.source}${dim(creds.subscriptionType ? ` · ${creds.subscriptionType}` : '')}`)
|
|
184
188
|
: stateLine('warn', 'claude', `no login ${dim('· sign in with `claude` or set ANTHROPIC_API_KEY')}`));
|
|
@@ -195,6 +199,15 @@ async function cmdStatus() {
|
|
|
195
199
|
console.log(row('tracked', `${tracked} file${tracked === 1 ? '' : 's'} · ${mb} MB read · synced ${ago(state.updatedAt)}`));
|
|
196
200
|
console.log(row('config', tilde(cfg.storePath)));
|
|
197
201
|
}
|
|
202
|
+
function serviceLine(svc) {
|
|
203
|
+
if (svc.state === 'running') {
|
|
204
|
+
return stateLine('ok', 'service', `running${svc.pid ? dim(` · pid ${svc.pid}`) : ''}`);
|
|
205
|
+
}
|
|
206
|
+
if (svc.state === 'no autostart') {
|
|
207
|
+
return stateLine('warn', 'service', `no autostart here ${dim('· keep `usagefleet watch` running yourself')}`);
|
|
208
|
+
}
|
|
209
|
+
return stateLine('bad', 'service', `${svc.state} ${dim(svc.state === 'stopped' ? '· check the log' : '· run `usagefleet login`')}`);
|
|
210
|
+
}
|
|
198
211
|
/** Worst of the two windows decides the dot colour. */
|
|
199
212
|
function limitHealth(fiveHour, sevenDay) {
|
|
200
213
|
const worst = Math.max(fiveHour ?? 0, sevenDay ?? 0);
|
package/dist/release.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
// Generated by .github/workflows/release.yml.
|
|
2
|
-
export const RELEASE_VERSION = "1.2.
|
|
2
|
+
export const RELEASE_VERSION = "1.2.162";
|
package/dist/service.js
CHANGED
|
@@ -129,6 +129,10 @@ function macPlistPath() {
|
|
|
129
129
|
function systemdUnitPath() {
|
|
130
130
|
return join(homedir(), '.config', 'systemd', 'user', 'usagefleet.service');
|
|
131
131
|
}
|
|
132
|
+
/** sd_booted(3): without systemd as init (a Docker container, WSL without it) a unit would never start. */
|
|
133
|
+
function systemdBooted() {
|
|
134
|
+
return existsSync('/run/systemd/system');
|
|
135
|
+
}
|
|
132
136
|
/** Env vars that are actually set, for baking into the unit so the service
|
|
133
137
|
* behaves like the install shell. Derived from the USAGEFLEET_ prefix rather
|
|
134
138
|
* than a hand-kept allowlist: that list had already drifted, silently dropping
|
|
@@ -373,7 +377,7 @@ ${envXml}
|
|
|
373
377
|
console.log(row('logs', tilde(macLogDir())));
|
|
374
378
|
return collectingNow();
|
|
375
379
|
}
|
|
376
|
-
if (process.platform === 'linux') {
|
|
380
|
+
if (process.platform === 'linux' && systemdBooted()) {
|
|
377
381
|
// systemd: quote values, escape backslash/quote, reject newlines.
|
|
378
382
|
const envLines = env
|
|
379
383
|
.filter(([, v]) => !/[\r\n]/.test(v))
|
|
@@ -505,7 +509,7 @@ export function serviceStatus() {
|
|
|
505
509
|
const pid = out?.match(/\bpid = (\d+)/)?.[1];
|
|
506
510
|
return pid ? { pid: Number(pid), state: 'running' } : { state: 'stopped' };
|
|
507
511
|
}
|
|
508
|
-
if (process.platform === 'linux') {
|
|
512
|
+
if (process.platform === 'linux' && systemdBooted()) {
|
|
509
513
|
if (!existsSync(systemdUnitPath())) {
|
|
510
514
|
return { state: 'not installed' };
|
|
511
515
|
}
|
|
@@ -523,7 +527,13 @@ export function serviceStatus() {
|
|
|
523
527
|
}
|
|
524
528
|
return { state: /Status:\s*Running/i.test(out) ? 'running' : 'stopped' };
|
|
525
529
|
}
|
|
526
|
-
return { state: '
|
|
530
|
+
return { state: 'no autostart' };
|
|
531
|
+
}
|
|
532
|
+
/** Whether this process is the one the installed service runs, i.e. the one `login` restarts.
|
|
533
|
+
* Windows reports no pid, so a running task counts as this process, as it did before. */
|
|
534
|
+
export function isServiceProcess() {
|
|
535
|
+
const svc = serviceStatus();
|
|
536
|
+
return svc.state === 'running' && (svc.pid === undefined || svc.pid === process.pid);
|
|
527
537
|
}
|
|
528
538
|
/** Best-effort removal of the ~60 MB binary copy that pre-npm releases parked in
|
|
529
539
|
* the app-support dir (plus the `.old` file a Windows in-place update left).
|