modelstat 0.0.47 → 0.0.49
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.mjs +314 -203
- package/dist/cli.mjs.map +1 -1
- package/package.json +3 -3
package/dist/cli.mjs
CHANGED
|
@@ -44914,6 +44914,116 @@ var init_api = __esm({
|
|
|
44914
44914
|
}
|
|
44915
44915
|
});
|
|
44916
44916
|
|
|
44917
|
+
// src/machine-key.ts
|
|
44918
|
+
import { spawnSync } from "child_process";
|
|
44919
|
+
import { createHash as createHash3 } from "crypto";
|
|
44920
|
+
import { chmodSync as chmodSync2, existsSync as existsSync6, mkdirSync as mkdirSync2, readFileSync as readFileSync3, writeFileSync as writeFileSync3 } from "fs";
|
|
44921
|
+
import { homedir as homedir4, platform as platform2 } from "os";
|
|
44922
|
+
import { join as join4 } from "path";
|
|
44923
|
+
function macosPlatformUuid() {
|
|
44924
|
+
try {
|
|
44925
|
+
const r = spawnSync("ioreg", ["-rd1", "-c", "IOPlatformExpertDevice"], {
|
|
44926
|
+
encoding: "utf8",
|
|
44927
|
+
timeout: 4e3
|
|
44928
|
+
});
|
|
44929
|
+
if (r.status !== 0 || !r.stdout) return null;
|
|
44930
|
+
const m = /"IOPlatformUUID"\s*=\s*"([^"]+)"/.exec(r.stdout);
|
|
44931
|
+
return m?.[1]?.trim() || null;
|
|
44932
|
+
} catch {
|
|
44933
|
+
return null;
|
|
44934
|
+
}
|
|
44935
|
+
}
|
|
44936
|
+
function linuxMachineId() {
|
|
44937
|
+
for (const p of ["/etc/machine-id", "/var/lib/dbus/machine-id"]) {
|
|
44938
|
+
try {
|
|
44939
|
+
const v = readFileSync3(p, "utf8").trim();
|
|
44940
|
+
if (v) return v;
|
|
44941
|
+
} catch {
|
|
44942
|
+
}
|
|
44943
|
+
}
|
|
44944
|
+
return null;
|
|
44945
|
+
}
|
|
44946
|
+
function windowsMachineGuid() {
|
|
44947
|
+
try {
|
|
44948
|
+
const r = spawnSync(
|
|
44949
|
+
"reg",
|
|
44950
|
+
["query", "HKLM\\SOFTWARE\\Microsoft\\Cryptography", "/v", "MachineGuid"],
|
|
44951
|
+
{ encoding: "utf8", timeout: 4e3 }
|
|
44952
|
+
);
|
|
44953
|
+
if (r.status !== 0 || !r.stdout) return null;
|
|
44954
|
+
const m = /MachineGuid\s+REG_SZ\s+([0-9a-fA-F-]+)/.exec(r.stdout);
|
|
44955
|
+
return m?.[1]?.trim() || null;
|
|
44956
|
+
} catch {
|
|
44957
|
+
return null;
|
|
44958
|
+
}
|
|
44959
|
+
}
|
|
44960
|
+
function fallbackKey() {
|
|
44961
|
+
try {
|
|
44962
|
+
if (existsSync6(FALLBACK_KEY_FILE)) {
|
|
44963
|
+
const v = readFileSync3(FALLBACK_KEY_FILE, "utf8").trim();
|
|
44964
|
+
if (v) return v;
|
|
44965
|
+
}
|
|
44966
|
+
} catch {
|
|
44967
|
+
}
|
|
44968
|
+
const fresh = createHash3("sha256").update(`${MACHINE_KEY_SALT}:fallback:${Date.now()}:${Math.random()}`).digest("hex");
|
|
44969
|
+
try {
|
|
44970
|
+
mkdirSync2(ROOT2, { recursive: true, mode: 448 });
|
|
44971
|
+
writeFileSync3(FALLBACK_KEY_FILE, fresh, { mode: 384 });
|
|
44972
|
+
chmodSync2(FALLBACK_KEY_FILE, 384);
|
|
44973
|
+
} catch {
|
|
44974
|
+
}
|
|
44975
|
+
return fresh;
|
|
44976
|
+
}
|
|
44977
|
+
function resolveRaw() {
|
|
44978
|
+
const p = platform2();
|
|
44979
|
+
if (p === "darwin") {
|
|
44980
|
+
const v = macosPlatformUuid();
|
|
44981
|
+
if (v) return { raw: v, source: "macos-ioplatform" };
|
|
44982
|
+
} else if (p === "win32") {
|
|
44983
|
+
const v = windowsMachineGuid();
|
|
44984
|
+
if (v) return { raw: v, source: "windows-guid" };
|
|
44985
|
+
} else {
|
|
44986
|
+
const v = linuxMachineId();
|
|
44987
|
+
if (v) return { raw: v, source: "linux-machine-id" };
|
|
44988
|
+
}
|
|
44989
|
+
return { raw: fallbackKey(), source: "fallback-file" };
|
|
44990
|
+
}
|
|
44991
|
+
function machineKey() {
|
|
44992
|
+
if (cachedKey) return cachedKey;
|
|
44993
|
+
const { raw, source } = resolveRaw();
|
|
44994
|
+
cachedSource = source;
|
|
44995
|
+
cachedKey = createHash3("sha256").update(`${MACHINE_KEY_SALT}:${raw}`).digest("hex");
|
|
44996
|
+
return cachedKey;
|
|
44997
|
+
}
|
|
44998
|
+
function machineKeySource() {
|
|
44999
|
+
if (!cachedSource) machineKey();
|
|
45000
|
+
return cachedSource;
|
|
45001
|
+
}
|
|
45002
|
+
function deviceUuidFromMachineKey(key = machineKey()) {
|
|
45003
|
+
const nsHex = DEVICE_UUID_NAMESPACE.replace(/-/g, "");
|
|
45004
|
+
const nsBytes = Buffer.from(nsHex, "hex");
|
|
45005
|
+
const hash = createHash3("sha1").update(nsBytes).update(key).digest();
|
|
45006
|
+
const b = Buffer.from(hash.subarray(0, 16));
|
|
45007
|
+
b[6] = b[6] & 15 | 80;
|
|
45008
|
+
b[8] = b[8] & 63 | 128;
|
|
45009
|
+
const h = b.toString("hex");
|
|
45010
|
+
return [h.slice(0, 8), h.slice(8, 12), h.slice(12, 16), h.slice(16, 20), h.slice(20, 32)].join(
|
|
45011
|
+
"-"
|
|
45012
|
+
);
|
|
45013
|
+
}
|
|
45014
|
+
var MACHINE_KEY_SALT, DEVICE_UUID_NAMESPACE, ROOT2, FALLBACK_KEY_FILE, cachedKey, cachedSource;
|
|
45015
|
+
var init_machine_key = __esm({
|
|
45016
|
+
"src/machine-key.ts"() {
|
|
45017
|
+
"use strict";
|
|
45018
|
+
MACHINE_KEY_SALT = "modelstat.device.machine-key.v1";
|
|
45019
|
+
DEVICE_UUID_NAMESPACE = "6f1d2c9a-8b3e-4a7f-9c2d-0e5a1b6c7d8e";
|
|
45020
|
+
ROOT2 = join4(homedir4(), ".modelstat");
|
|
45021
|
+
FALLBACK_KEY_FILE = join4(ROOT2, "machine-key");
|
|
45022
|
+
cachedKey = null;
|
|
45023
|
+
cachedSource = null;
|
|
45024
|
+
}
|
|
45025
|
+
});
|
|
45026
|
+
|
|
44917
45027
|
// ../../packages/companion-core/src/contracts/index.ts
|
|
44918
45028
|
var init_contracts = __esm({
|
|
44919
45029
|
"../../packages/companion-core/src/contracts/index.ts"() {
|
|
@@ -44932,11 +45042,7 @@ var init_ids2 = __esm({
|
|
|
44932
45042
|
});
|
|
44933
45043
|
|
|
44934
45044
|
// ../../packages/companion-core/src/queue/index.ts
|
|
44935
|
-
function
|
|
44936
|
-
const segmentByEvent = /* @__PURE__ */ new Map();
|
|
44937
|
-
for (const seg of segments) {
|
|
44938
|
-
for (const id of seg.source_event_ids) segmentByEvent.set(id, seg.segment_id);
|
|
44939
|
-
}
|
|
45045
|
+
function attachSegmentIdsByMap(calls, segmentByEvent) {
|
|
44940
45046
|
return calls.map((c) => ({
|
|
44941
45047
|
...c,
|
|
44942
45048
|
segment_id: segmentByEvent.get(c.source_event_id) ?? null
|
|
@@ -45700,14 +45806,14 @@ var init_ollama = __esm({
|
|
|
45700
45806
|
|
|
45701
45807
|
// ../../packages/companion-core/src/node/llama.ts
|
|
45702
45808
|
import { mkdir } from "fs/promises";
|
|
45703
|
-
import { existsSync as
|
|
45704
|
-
import { homedir as
|
|
45705
|
-
import { dirname as dirname5, join as
|
|
45809
|
+
import { existsSync as existsSync7 } from "fs";
|
|
45810
|
+
import { homedir as homedir5 } from "os";
|
|
45811
|
+
import { dirname as dirname5, join as join5 } from "path";
|
|
45706
45812
|
function defaultLlamaConfig() {
|
|
45707
45813
|
const env2 = globalThis.process?.env ?? {};
|
|
45708
|
-
const modelsDir = env2.MODELSTAT_MODELS_DIR ??
|
|
45814
|
+
const modelsDir = env2.MODELSTAT_MODELS_DIR ?? join5(homedir5(), ".modelstat", "models");
|
|
45709
45815
|
const modelUrl = env2.MODELSTAT_LLAMA_MODEL_URL ?? DEFAULT_LLAMA_MODEL_URL;
|
|
45710
|
-
const modelPath = env2.MODELSTAT_LLAMA_MODEL_PATH ??
|
|
45816
|
+
const modelPath = env2.MODELSTAT_LLAMA_MODEL_PATH ?? join5(modelsDir, basenameFromUrl(modelUrl));
|
|
45711
45817
|
return {
|
|
45712
45818
|
modelPath,
|
|
45713
45819
|
modelUrl,
|
|
@@ -45728,7 +45834,7 @@ function basenameFromUrl(url) {
|
|
|
45728
45834
|
return parts[parts.length - 1] || "model.gguf";
|
|
45729
45835
|
}
|
|
45730
45836
|
async function ensureLlamaModel(cfg = defaultLlamaConfig()) {
|
|
45731
|
-
if (
|
|
45837
|
+
if (existsSync7(cfg.modelPath)) return cfg.modelPath;
|
|
45732
45838
|
await mkdir(dirname5(cfg.modelPath), { recursive: true });
|
|
45733
45839
|
const res = await fetch(cfg.modelUrl);
|
|
45734
45840
|
if (!res.ok || !res.body) {
|
|
@@ -46241,8 +46347,8 @@ var init_pipeline2 = __esm({
|
|
|
46241
46347
|
|
|
46242
46348
|
// src/scan.ts
|
|
46243
46349
|
import { readdir, stat as stat2 } from "fs/promises";
|
|
46244
|
-
import { homedir as
|
|
46245
|
-
import { join as
|
|
46350
|
+
import { homedir as homedir6 } from "os";
|
|
46351
|
+
import { join as join6 } from "path";
|
|
46246
46352
|
function withNonNullTokens(e) {
|
|
46247
46353
|
return e.tokens ? e : { ...e, tokens: { ...ZERO_TOKENS } };
|
|
46248
46354
|
}
|
|
@@ -46251,16 +46357,16 @@ async function scanAll(cb = {}) {
|
|
|
46251
46357
|
if (!deviceId) throw new Error("agent not enrolled \u2014 run `register` first");
|
|
46252
46358
|
const jobs = [];
|
|
46253
46359
|
try {
|
|
46254
|
-
const base =
|
|
46360
|
+
const base = join6(homedir6(), ".claude/projects");
|
|
46255
46361
|
const projects = await readdir(base).catch(() => []);
|
|
46256
46362
|
for (const p of projects) {
|
|
46257
|
-
const dir =
|
|
46363
|
+
const dir = join6(base, p);
|
|
46258
46364
|
const ds = await stat2(dir).catch(() => null);
|
|
46259
46365
|
if (!ds?.isDirectory()) continue;
|
|
46260
46366
|
const files = await readdir(dir);
|
|
46261
46367
|
for (const f of files) {
|
|
46262
46368
|
if (!f.endsWith(".jsonl")) continue;
|
|
46263
|
-
const full =
|
|
46369
|
+
const full = join6(dir, f);
|
|
46264
46370
|
jobs.push({
|
|
46265
46371
|
path: full,
|
|
46266
46372
|
parse: async (sink2) => {
|
|
@@ -46274,17 +46380,17 @@ async function scanAll(cb = {}) {
|
|
|
46274
46380
|
console.warn("claude scan skipped:", e.message);
|
|
46275
46381
|
}
|
|
46276
46382
|
try {
|
|
46277
|
-
const base =
|
|
46383
|
+
const base = join6(homedir6(), ".codex/sessions");
|
|
46278
46384
|
const years = await readdir(base).catch(() => []);
|
|
46279
46385
|
for (const y of years) {
|
|
46280
|
-
const months = await readdir(
|
|
46386
|
+
const months = await readdir(join6(base, y)).catch(() => []);
|
|
46281
46387
|
for (const m of months) {
|
|
46282
|
-
const days = await readdir(
|
|
46388
|
+
const days = await readdir(join6(base, y, m)).catch(() => []);
|
|
46283
46389
|
for (const d of days) {
|
|
46284
|
-
const files = await readdir(
|
|
46390
|
+
const files = await readdir(join6(base, y, m, d)).catch(() => []);
|
|
46285
46391
|
for (const f of files) {
|
|
46286
46392
|
if (!f.startsWith("rollout-") || !f.endsWith(".jsonl")) continue;
|
|
46287
|
-
const full =
|
|
46393
|
+
const full = join6(base, y, m, d, f);
|
|
46288
46394
|
jobs.push({
|
|
46289
46395
|
path: full,
|
|
46290
46396
|
parse: async (sink2) => {
|
|
@@ -46327,16 +46433,19 @@ async function scanAll(cb = {}) {
|
|
|
46327
46433
|
} catch (e) {
|
|
46328
46434
|
console.warn("session titling failed \u2014 shipping batch untitled:", e.message);
|
|
46329
46435
|
}
|
|
46436
|
+
const callSegmentByEvent = /* @__PURE__ */ new Map();
|
|
46437
|
+
for (const sessionId of new Set(toolCallBuffer.map((c) => c.session_id))) {
|
|
46438
|
+
for (const seg of runSegmentsBySession.get(sessionId) ?? []) {
|
|
46439
|
+
for (const id of seg.source_event_ids) callSegmentByEvent.set(id, seg.segment_id);
|
|
46440
|
+
}
|
|
46441
|
+
}
|
|
46330
46442
|
const batch = {
|
|
46331
46443
|
batch_id: batchId(),
|
|
46332
46444
|
device_id: deviceId,
|
|
46333
46445
|
agent_version: AGENT_VERSION,
|
|
46334
46446
|
events,
|
|
46335
46447
|
segments,
|
|
46336
|
-
|
|
46337
|
-
// each call to the segment covering its source event (null when
|
|
46338
|
-
// no segment covers it — e.g. codex response_item anchors).
|
|
46339
|
-
tool_calls: attachSegmentIds(toolCallBuffer, segments),
|
|
46448
|
+
tool_calls: attachSegmentIdsByMap(toolCallBuffer, callSegmentByEvent),
|
|
46340
46449
|
...Object.keys(sessionTitles).length ? { session_titles: sessionTitles } : {}
|
|
46341
46450
|
};
|
|
46342
46451
|
cb.onUpload?.({ events: events.length, segments: segments.length });
|
|
@@ -46398,7 +46507,7 @@ var init_scan = __esm({
|
|
|
46398
46507
|
init_api();
|
|
46399
46508
|
init_config2();
|
|
46400
46509
|
init_pipeline2();
|
|
46401
|
-
AGENT_VERSION = true ? "agent-0.0.
|
|
46510
|
+
AGENT_VERSION = true ? "agent-0.0.49" : "agent-dev";
|
|
46402
46511
|
BATCH_MAX_EVENTS = 2e3;
|
|
46403
46512
|
BATCH_MAX_TOOL_CALLS = 2e4;
|
|
46404
46513
|
BATCH_BUFFER_HARD_CAP = BATCH_MAX_EVENTS * 2;
|
|
@@ -46415,17 +46524,17 @@ var init_scan = __esm({
|
|
|
46415
46524
|
// src/lock.ts
|
|
46416
46525
|
import {
|
|
46417
46526
|
closeSync,
|
|
46418
|
-
existsSync as
|
|
46419
|
-
mkdirSync as
|
|
46527
|
+
existsSync as existsSync9,
|
|
46528
|
+
mkdirSync as mkdirSync4,
|
|
46420
46529
|
openSync,
|
|
46421
|
-
readFileSync as
|
|
46530
|
+
readFileSync as readFileSync5,
|
|
46422
46531
|
renameSync as renameSync2,
|
|
46423
46532
|
unlinkSync as unlinkSync2,
|
|
46424
|
-
writeFileSync as
|
|
46533
|
+
writeFileSync as writeFileSync5,
|
|
46425
46534
|
writeSync
|
|
46426
46535
|
} from "fs";
|
|
46427
|
-
import { homedir as
|
|
46428
|
-
import { join as
|
|
46536
|
+
import { homedir as homedir8 } from "os";
|
|
46537
|
+
import { join as join8 } from "path";
|
|
46429
46538
|
function isProcessAlive(pid) {
|
|
46430
46539
|
if (!pid || pid <= 0) return false;
|
|
46431
46540
|
try {
|
|
@@ -46439,7 +46548,7 @@ function isProcessAlive(pid) {
|
|
|
46439
46548
|
}
|
|
46440
46549
|
function readDaemonLock(lockFile = LOCK_FILE) {
|
|
46441
46550
|
try {
|
|
46442
|
-
const raw =
|
|
46551
|
+
const raw = readFileSync5(lockFile, "utf8");
|
|
46443
46552
|
const obj = JSON.parse(raw);
|
|
46444
46553
|
if (typeof obj.pid !== "number") return null;
|
|
46445
46554
|
return {
|
|
@@ -46453,7 +46562,7 @@ function readDaemonLock(lockFile = LOCK_FILE) {
|
|
|
46453
46562
|
}
|
|
46454
46563
|
}
|
|
46455
46564
|
function writeLockAtomic(meta) {
|
|
46456
|
-
|
|
46565
|
+
mkdirSync4(LOCK_DIR, { recursive: true });
|
|
46457
46566
|
const tmp = `${LOCK_FILE}.${meta.pid}.${Date.now()}.tmp`;
|
|
46458
46567
|
const fd = openSync(tmp, "wx");
|
|
46459
46568
|
try {
|
|
@@ -46545,8 +46654,8 @@ var LOCK_DIR, LOCK_FILE, LOCK_RECHECK_MS;
|
|
|
46545
46654
|
var init_lock = __esm({
|
|
46546
46655
|
"src/lock.ts"() {
|
|
46547
46656
|
"use strict";
|
|
46548
|
-
LOCK_DIR =
|
|
46549
|
-
LOCK_FILE =
|
|
46657
|
+
LOCK_DIR = join8(homedir8(), ".modelstat");
|
|
46658
|
+
LOCK_FILE = join8(LOCK_DIR, "daemon.lock");
|
|
46550
46659
|
LOCK_RECHECK_MS = 5e3;
|
|
46551
46660
|
}
|
|
46552
46661
|
});
|
|
@@ -48343,7 +48452,7 @@ __export(daemon_exports, {
|
|
|
48343
48452
|
setQueue: () => setQueue,
|
|
48344
48453
|
setStat: () => setStat
|
|
48345
48454
|
});
|
|
48346
|
-
import { existsSync as
|
|
48455
|
+
import { existsSync as existsSync10, statSync as statSync2 } from "fs";
|
|
48347
48456
|
function setPhase(phase, message) {
|
|
48348
48457
|
status.phase = phase;
|
|
48349
48458
|
status.message = message ?? null;
|
|
@@ -48385,7 +48494,8 @@ function snapshotBody() {
|
|
|
48385
48494
|
queue_size: status.queueSize,
|
|
48386
48495
|
stats: status.stats,
|
|
48387
48496
|
last_event_at: status.lastEventAt,
|
|
48388
|
-
agent_version: AGENT_VERSION2
|
|
48497
|
+
agent_version: AGENT_VERSION2,
|
|
48498
|
+
machine_id: machineKey()
|
|
48389
48499
|
};
|
|
48390
48500
|
}
|
|
48391
48501
|
function scheduleLocalFlush() {
|
|
@@ -48422,12 +48532,12 @@ async function sendHeartbeat() {
|
|
|
48422
48532
|
writeLocalStatus(body).catch(() => void 0);
|
|
48423
48533
|
}
|
|
48424
48534
|
async function rotateRunawayLogs() {
|
|
48425
|
-
const { homedir:
|
|
48426
|
-
const { join:
|
|
48535
|
+
const { homedir: homedir11 } = await import("os");
|
|
48536
|
+
const { join: join13 } = await import("path");
|
|
48427
48537
|
const { open: open2, stat: stat6, truncate, writeFile } = await import("fs/promises");
|
|
48428
|
-
const dir =
|
|
48538
|
+
const dir = join13(homedir11(), ".modelstat", "logs");
|
|
48429
48539
|
for (const name of ["out.log", "err.log"]) {
|
|
48430
|
-
const p =
|
|
48540
|
+
const p = join13(dir, name);
|
|
48431
48541
|
try {
|
|
48432
48542
|
const st = await stat6(p);
|
|
48433
48543
|
if (st.size <= LOG_MAX_BYTES) continue;
|
|
@@ -48449,16 +48559,16 @@ async function rotateRunawayLogs() {
|
|
|
48449
48559
|
}
|
|
48450
48560
|
}
|
|
48451
48561
|
async function writeLocalStatus(snapshot) {
|
|
48452
|
-
const { homedir:
|
|
48453
|
-
const { join:
|
|
48562
|
+
const { homedir: homedir11 } = await import("os");
|
|
48563
|
+
const { join: join13 } = await import("path");
|
|
48454
48564
|
const { writeFile, mkdir: mkdir2, rename } = await import("fs/promises");
|
|
48455
48565
|
if (!lastStatusPath) {
|
|
48456
|
-
const dir =
|
|
48566
|
+
const dir = join13(homedir11(), ".modelstat");
|
|
48457
48567
|
try {
|
|
48458
48568
|
await mkdir2(dir, { recursive: true });
|
|
48459
48569
|
} catch {
|
|
48460
48570
|
}
|
|
48461
|
-
lastStatusPath =
|
|
48571
|
+
lastStatusPath = join13(dir, "last-status.json");
|
|
48462
48572
|
}
|
|
48463
48573
|
const tmp = `${lastStatusPath}.tmp`;
|
|
48464
48574
|
try {
|
|
@@ -48500,10 +48610,7 @@ async function runScanCycle(reason) {
|
|
|
48500
48610
|
if (p.segment === 0) {
|
|
48501
48611
|
setPhase("processing", `Analyzing${sess}`);
|
|
48502
48612
|
} else {
|
|
48503
|
-
setPhase(
|
|
48504
|
-
"processing",
|
|
48505
|
-
`Summarising segment ${p.segment}/${p.segmentTotal}${sess}`
|
|
48506
|
-
);
|
|
48613
|
+
setPhase("processing", `Summarising segment ${p.segment}/${p.segmentTotal}${sess}`);
|
|
48507
48614
|
}
|
|
48508
48615
|
},
|
|
48509
48616
|
onUpload({ segments }) {
|
|
@@ -48558,12 +48665,8 @@ async function runDaemon(opts = {}) {
|
|
|
48558
48665
|
lock.ageSec
|
|
48559
48666
|
)} ago, agent ${lock.owner.agentVersion}.`
|
|
48560
48667
|
);
|
|
48561
|
-
console.log(
|
|
48562
|
-
|
|
48563
|
-
);
|
|
48564
|
-
console.log(
|
|
48565
|
-
" \u2192 to force-replace it: modelstat start --force"
|
|
48566
|
-
);
|
|
48668
|
+
console.log(" \u2192 to stop it: kill " + lock.owner.pid);
|
|
48669
|
+
console.log(" \u2192 to force-replace it: modelstat start --force");
|
|
48567
48670
|
return;
|
|
48568
48671
|
}
|
|
48569
48672
|
setPhase("starting", "Booting");
|
|
@@ -48591,21 +48694,19 @@ async function runDaemon(opts = {}) {
|
|
|
48591
48694
|
await runDiscovery();
|
|
48592
48695
|
await requestScan("startup");
|
|
48593
48696
|
const chokidar = (await Promise.resolve().then(() => (init_esm2(), esm_exports))).default;
|
|
48594
|
-
const { homedir:
|
|
48595
|
-
const { join:
|
|
48596
|
-
const home2 =
|
|
48697
|
+
const { homedir: homedir11, platform: platform6 } = await import("os");
|
|
48698
|
+
const { join: join13 } = await import("path");
|
|
48699
|
+
const home2 = homedir11();
|
|
48597
48700
|
const dirs = [
|
|
48598
|
-
|
|
48599
|
-
|
|
48600
|
-
|
|
48601
|
-
|
|
48602
|
-
...
|
|
48603
|
-
|
|
48604
|
-
|
|
48605
|
-
] : [
|
|
48606
|
-
|
|
48607
|
-
]
|
|
48608
|
-
].filter((p) => existsSync9(p) && statSync2(p).isDirectory());
|
|
48701
|
+
join13(home2, ".claude/projects"),
|
|
48702
|
+
join13(home2, ".codex/sessions"),
|
|
48703
|
+
join13(home2, ".cursor/ai-tracking"),
|
|
48704
|
+
join13(home2, ".gemini"),
|
|
48705
|
+
...platform6() === "darwin" ? [
|
|
48706
|
+
join13(home2, "Library/Application Support/Cursor/User/workspaceStorage"),
|
|
48707
|
+
join13(home2, "Library/Application Support/Claude")
|
|
48708
|
+
] : [join13(home2, ".config/Cursor/User/workspaceStorage")]
|
|
48709
|
+
].filter((p) => existsSync10(p) && statSync2(p).isDirectory());
|
|
48609
48710
|
setPhase("watching", `Watching ${dirs.length} directories`);
|
|
48610
48711
|
const watcher = chokidar.watch(dirs, {
|
|
48611
48712
|
persistent: true,
|
|
@@ -48630,10 +48731,7 @@ async function runDaemon(opts = {}) {
|
|
|
48630
48731
|
});
|
|
48631
48732
|
const backstop = setInterval(() => void requestScan("interval"), SCAN_INTERVAL_MS);
|
|
48632
48733
|
backstop.unref();
|
|
48633
|
-
const discoveryTimer = setInterval(
|
|
48634
|
-
() => void runDiscovery(),
|
|
48635
|
-
DISCOVERY_INTERVAL_MS
|
|
48636
|
-
);
|
|
48734
|
+
const discoveryTimer = setInterval(() => void runDiscovery(), DISCOVERY_INTERVAL_MS);
|
|
48637
48735
|
discoveryTimer.unref();
|
|
48638
48736
|
const shutdown = async () => {
|
|
48639
48737
|
setPhase("offline", "Shutting down");
|
|
@@ -48650,15 +48748,16 @@ var import_undici2, AGENT_VERSION2, HEARTBEAT_INTERVAL_MS, SCAN_INTERVAL_MS, DIS
|
|
|
48650
48748
|
var init_daemon = __esm({
|
|
48651
48749
|
"src/daemon.ts"() {
|
|
48652
48750
|
"use strict";
|
|
48653
|
-
import_undici2 = __toESM(require_undici(), 1);
|
|
48654
48751
|
init_logger();
|
|
48655
48752
|
init_src2();
|
|
48753
|
+
import_undici2 = __toESM(require_undici(), 1);
|
|
48656
48754
|
init_api();
|
|
48657
48755
|
init_config2();
|
|
48658
48756
|
init_lock();
|
|
48757
|
+
init_machine_key();
|
|
48659
48758
|
init_scan();
|
|
48660
48759
|
init_single_flight();
|
|
48661
|
-
AGENT_VERSION2 = true ? "agent-0.0.
|
|
48760
|
+
AGENT_VERSION2 = true ? "agent-0.0.49" : "agent-dev";
|
|
48662
48761
|
HEARTBEAT_INTERVAL_MS = 1e4;
|
|
48663
48762
|
SCAN_INTERVAL_MS = 5 * 60 * 1e3;
|
|
48664
48763
|
DISCOVERY_INTERVAL_MS = 6e4;
|
|
@@ -48686,37 +48785,37 @@ var watch_exports = {};
|
|
|
48686
48785
|
__export(watch_exports, {
|
|
48687
48786
|
watchForever: () => watchForever
|
|
48688
48787
|
});
|
|
48689
|
-
import { existsSync as
|
|
48690
|
-
import { homedir as
|
|
48691
|
-
import { join as
|
|
48788
|
+
import { existsSync as existsSync11 } from "fs";
|
|
48789
|
+
import { homedir as homedir10, platform as platform4 } from "os";
|
|
48790
|
+
import { join as join12 } from "path";
|
|
48692
48791
|
function resolveWatchDirs() {
|
|
48693
|
-
const home2 =
|
|
48694
|
-
const xdgConfig = process.env.XDG_CONFIG_HOME ??
|
|
48695
|
-
const xdgData = process.env.XDG_DATA_HOME ??
|
|
48792
|
+
const home2 = homedir10();
|
|
48793
|
+
const xdgConfig = process.env.XDG_CONFIG_HOME ?? join12(home2, ".config");
|
|
48794
|
+
const xdgData = process.env.XDG_DATA_HOME ?? join12(home2, ".local/share");
|
|
48696
48795
|
const candidates = [
|
|
48697
48796
|
// universal (default HOME-rooted CLI data dirs)
|
|
48698
|
-
|
|
48699
|
-
|
|
48700
|
-
|
|
48701
|
-
|
|
48702
|
-
|
|
48797
|
+
join12(home2, ".claude/projects"),
|
|
48798
|
+
join12(home2, ".codex/sessions"),
|
|
48799
|
+
join12(home2, ".cursor/ai-tracking"),
|
|
48800
|
+
join12(home2, ".gemini"),
|
|
48801
|
+
join12(home2, ".aider"),
|
|
48703
48802
|
// XDG / Linux
|
|
48704
|
-
|
|
48705
|
-
|
|
48706
|
-
|
|
48707
|
-
|
|
48708
|
-
|
|
48709
|
-
|
|
48803
|
+
join12(xdgConfig, "claude/projects"),
|
|
48804
|
+
join12(xdgConfig, "codex/sessions"),
|
|
48805
|
+
join12(xdgConfig, "Cursor/User/workspaceStorage"),
|
|
48806
|
+
join12(xdgConfig, "Code/User/workspaceStorage"),
|
|
48807
|
+
join12(xdgConfig, "Code - Insiders/User/workspaceStorage"),
|
|
48808
|
+
join12(xdgData, "claude/projects"),
|
|
48710
48809
|
// macOS
|
|
48711
|
-
...
|
|
48712
|
-
|
|
48713
|
-
|
|
48714
|
-
|
|
48715
|
-
|
|
48716
|
-
|
|
48810
|
+
...platform4() === "darwin" ? [
|
|
48811
|
+
join12(home2, "Library/Application Support/Cursor/User/workspaceStorage"),
|
|
48812
|
+
join12(home2, "Library/Application Support/Claude"),
|
|
48813
|
+
join12(home2, "Library/Application Support/Code/User/workspaceStorage"),
|
|
48814
|
+
join12(home2, "Library/Application Support/Windsurf/User/workspaceStorage"),
|
|
48815
|
+
join12(home2, "Library/Application Support/Zed")
|
|
48717
48816
|
] : []
|
|
48718
48817
|
];
|
|
48719
|
-
return Array.from(new Set(candidates)).filter((p) =>
|
|
48818
|
+
return Array.from(new Set(candidates)).filter((p) => existsSync11(p));
|
|
48720
48819
|
}
|
|
48721
48820
|
async function safeScan(reason) {
|
|
48722
48821
|
if (scanning) {
|
|
@@ -48781,53 +48880,53 @@ init_src2();
|
|
|
48781
48880
|
init_api();
|
|
48782
48881
|
init_config2();
|
|
48783
48882
|
init_identity();
|
|
48883
|
+
init_machine_key();
|
|
48784
48884
|
init_scan();
|
|
48785
48885
|
import { spawn } from "child_process";
|
|
48786
|
-
import {
|
|
48787
|
-
import { arch as cpuArch, hostname as hostname2, platform as platform4, release } from "os";
|
|
48886
|
+
import { arch as cpuArch, hostname as hostname2, platform as platform5, release } from "os";
|
|
48788
48887
|
import { createInterface as createInterface3 } from "readline";
|
|
48789
48888
|
|
|
48790
48889
|
// src/service.ts
|
|
48791
|
-
import { spawnSync } from "child_process";
|
|
48890
|
+
import { spawnSync as spawnSync2 } from "child_process";
|
|
48792
48891
|
import {
|
|
48793
48892
|
copyFileSync,
|
|
48794
|
-
existsSync as
|
|
48795
|
-
mkdirSync as
|
|
48796
|
-
readFileSync as
|
|
48893
|
+
existsSync as existsSync8,
|
|
48894
|
+
mkdirSync as mkdirSync3,
|
|
48895
|
+
readFileSync as readFileSync4,
|
|
48797
48896
|
realpathSync,
|
|
48798
48897
|
unlinkSync,
|
|
48799
|
-
writeFileSync as
|
|
48898
|
+
writeFileSync as writeFileSync4
|
|
48800
48899
|
} from "fs";
|
|
48801
48900
|
import { createRequire } from "module";
|
|
48802
|
-
import { homedir as
|
|
48803
|
-
import { dirname as dirname6, join as
|
|
48901
|
+
import { homedir as homedir7, platform as platform3, userInfo } from "os";
|
|
48902
|
+
import { dirname as dirname6, join as join7 } from "path";
|
|
48804
48903
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
48805
48904
|
var SERVICE_LABEL = "ai.modelstat.agent";
|
|
48806
48905
|
var SYSTEMD_UNIT = "modelstat";
|
|
48807
48906
|
function home() {
|
|
48808
|
-
return
|
|
48907
|
+
return homedir7();
|
|
48809
48908
|
}
|
|
48810
48909
|
function stateDir() {
|
|
48811
|
-
return
|
|
48910
|
+
return join7(home(), ".modelstat");
|
|
48812
48911
|
}
|
|
48813
48912
|
function binDir() {
|
|
48814
|
-
return
|
|
48913
|
+
return join7(stateDir(), "bin");
|
|
48815
48914
|
}
|
|
48816
48915
|
function logDir() {
|
|
48817
|
-
return
|
|
48916
|
+
return join7(stateDir(), "logs");
|
|
48818
48917
|
}
|
|
48819
48918
|
function installedCliPath() {
|
|
48820
|
-
return
|
|
48919
|
+
return join7(binDir(), "modelstat.mjs");
|
|
48821
48920
|
}
|
|
48822
48921
|
function runningCliPath() {
|
|
48823
48922
|
return fileURLToPath2(import.meta.url).replace(/service\.(mjs|js|ts)$/, "cli.mjs");
|
|
48824
48923
|
}
|
|
48825
48924
|
function installBundle() {
|
|
48826
|
-
|
|
48827
|
-
|
|
48925
|
+
mkdirSync3(binDir(), { recursive: true });
|
|
48926
|
+
mkdirSync3(logDir(), { recursive: true });
|
|
48828
48927
|
const src = runningCliPath();
|
|
48829
48928
|
const dest = installedCliPath();
|
|
48830
|
-
if (!
|
|
48929
|
+
if (!existsSync8(src)) {
|
|
48831
48930
|
throw new Error(
|
|
48832
48931
|
`Can't find the CLI bundle to install from (${src}). Are you running a local dev build?`
|
|
48833
48932
|
);
|
|
@@ -48845,9 +48944,9 @@ function sourceLlamaVersion(sourceCli) {
|
|
|
48845
48944
|
const req = createRequire(sourceCli);
|
|
48846
48945
|
let d = dirname6(realpathSync(req.resolve("node-llama-cpp")));
|
|
48847
48946
|
for (let i = 0; i < 10; i++) {
|
|
48848
|
-
const pj =
|
|
48849
|
-
if (
|
|
48850
|
-
const p = JSON.parse(
|
|
48947
|
+
const pj = join7(d, "package.json");
|
|
48948
|
+
if (existsSync8(pj)) {
|
|
48949
|
+
const p = JSON.parse(readFileSync4(pj, "utf8"));
|
|
48851
48950
|
if (p.name === "node-llama-cpp" && p.version) return p.version;
|
|
48852
48951
|
}
|
|
48853
48952
|
const up = dirname6(d);
|
|
@@ -48863,19 +48962,19 @@ function installNativeRuntime(sourceCli) {
|
|
|
48863
48962
|
const dest = binDir();
|
|
48864
48963
|
try {
|
|
48865
48964
|
const have = JSON.parse(
|
|
48866
|
-
|
|
48867
|
-
|
|
48965
|
+
readFileSync4(
|
|
48966
|
+
join7(dest, "node_modules", "node-llama-cpp", "package.json"),
|
|
48868
48967
|
"utf8"
|
|
48869
48968
|
)
|
|
48870
48969
|
);
|
|
48871
48970
|
if (have.version === version) return [`node-llama-cpp@${version} (cached)`];
|
|
48872
48971
|
} catch {
|
|
48873
48972
|
}
|
|
48874
|
-
|
|
48973
|
+
mkdirSync3(dest, { recursive: true });
|
|
48875
48974
|
const childEnv = { ...process.env };
|
|
48876
48975
|
delete childEnv.npm_config_global;
|
|
48877
48976
|
delete childEnv.npm_config_prefix;
|
|
48878
|
-
const r =
|
|
48977
|
+
const r = spawnSync2(
|
|
48879
48978
|
"npm",
|
|
48880
48979
|
[
|
|
48881
48980
|
"install",
|
|
@@ -48905,21 +49004,21 @@ function nodeBinary() {
|
|
|
48905
49004
|
return process.execPath;
|
|
48906
49005
|
}
|
|
48907
49006
|
function plistPath() {
|
|
48908
|
-
return
|
|
49007
|
+
return join7(home(), "Library", "LaunchAgents", `${SERVICE_LABEL}.plist`);
|
|
48909
49008
|
}
|
|
48910
49009
|
function locateTrayExecutable() {
|
|
48911
49010
|
const candidates = [
|
|
48912
|
-
|
|
49011
|
+
join7(home(), "Applications", "ModelstatTray.app", "Contents", "MacOS", "modelstat-tray"),
|
|
48913
49012
|
"/Applications/ModelstatTray.app/Contents/MacOS/modelstat-tray"
|
|
48914
49013
|
];
|
|
48915
49014
|
for (const p of candidates) {
|
|
48916
|
-
if (
|
|
49015
|
+
if (existsSync8(p)) return p;
|
|
48917
49016
|
}
|
|
48918
49017
|
return null;
|
|
48919
49018
|
}
|
|
48920
49019
|
function writePlist(cliPath) {
|
|
48921
49020
|
const p = plistPath();
|
|
48922
|
-
|
|
49021
|
+
mkdirSync3(dirname6(p), { recursive: true });
|
|
48923
49022
|
const tray = locateTrayExecutable();
|
|
48924
49023
|
const programArgs = tray ? ` <string>${tray}</string>` : [
|
|
48925
49024
|
` <string>${nodeBinary()}</string>`,
|
|
@@ -48939,8 +49038,8 @@ ${programArgs}
|
|
|
48939
49038
|
<key>KeepAlive</key>
|
|
48940
49039
|
<dict><key>SuccessfulExit</key><false/></dict>
|
|
48941
49040
|
<key>ThrottleInterval</key><integer>30</integer>
|
|
48942
|
-
<key>StandardOutPath</key><string>${
|
|
48943
|
-
<key>StandardErrorPath</key><string>${
|
|
49041
|
+
<key>StandardOutPath</key><string>${join7(logDir(), "out.log")}</string>
|
|
49042
|
+
<key>StandardErrorPath</key><string>${join7(logDir(), "err.log")}</string>
|
|
48944
49043
|
<key>EnvironmentVariables</key>
|
|
48945
49044
|
<dict>
|
|
48946
49045
|
<key>PATH</key><string>/usr/local/bin:/opt/homebrew/bin:/usr/bin:/bin</string>
|
|
@@ -48954,11 +49053,11 @@ ${programArgs}
|
|
|
48954
49053
|
</dict>
|
|
48955
49054
|
</plist>
|
|
48956
49055
|
`;
|
|
48957
|
-
|
|
49056
|
+
writeFileSync4(p, plist, { mode: 420 });
|
|
48958
49057
|
return p;
|
|
48959
49058
|
}
|
|
48960
49059
|
function launchctl(args) {
|
|
48961
|
-
const r =
|
|
49060
|
+
const r = spawnSync2("launchctl", args, { encoding: "utf8" });
|
|
48962
49061
|
return { ok: r.status === 0, out: r.stdout ?? "", err: r.stderr ?? "" };
|
|
48963
49062
|
}
|
|
48964
49063
|
function macInstall() {
|
|
@@ -48985,7 +49084,7 @@ function macUninstall() {
|
|
|
48985
49084
|
const target = `gui/${uid}/${SERVICE_LABEL}`;
|
|
48986
49085
|
launchctl(["bootout", target]);
|
|
48987
49086
|
const plist = plistPath();
|
|
48988
|
-
if (
|
|
49087
|
+
if (existsSync8(plist)) {
|
|
48989
49088
|
try {
|
|
48990
49089
|
unlinkSync(plist);
|
|
48991
49090
|
} catch {
|
|
@@ -48998,12 +49097,12 @@ function macStatus() {
|
|
|
48998
49097
|
return { running: r.ok, hint: r.ok ? "launchd managed" : "not installed" };
|
|
48999
49098
|
}
|
|
49000
49099
|
function systemdUnitPath() {
|
|
49001
|
-
const xdg = process.env.XDG_CONFIG_HOME ??
|
|
49002
|
-
return
|
|
49100
|
+
const xdg = process.env.XDG_CONFIG_HOME ?? join7(home(), ".config");
|
|
49101
|
+
return join7(xdg, "systemd", "user", `${SYSTEMD_UNIT}.service`);
|
|
49003
49102
|
}
|
|
49004
49103
|
function writeSystemdUnit(cliPath) {
|
|
49005
49104
|
const unitPath = systemdUnitPath();
|
|
49006
|
-
|
|
49105
|
+
mkdirSync3(dirname6(unitPath), { recursive: true });
|
|
49007
49106
|
const unit = `[Unit]
|
|
49008
49107
|
Description=modelstat agent
|
|
49009
49108
|
Documentation=https://modelstat.ai
|
|
@@ -49022,17 +49121,17 @@ RestartSec=10
|
|
|
49022
49121
|
# Don't restart-storm if the service is persistently unreachable.
|
|
49023
49122
|
StartLimitIntervalSec=300
|
|
49024
49123
|
StartLimitBurst=10
|
|
49025
|
-
StandardOutput=append:${
|
|
49026
|
-
StandardError=append:${
|
|
49124
|
+
StandardOutput=append:${join7(logDir(), "out.log")}
|
|
49125
|
+
StandardError=append:${join7(logDir(), "err.log")}
|
|
49027
49126
|
|
|
49028
49127
|
[Install]
|
|
49029
49128
|
WantedBy=default.target
|
|
49030
49129
|
`;
|
|
49031
|
-
|
|
49130
|
+
writeFileSync4(unitPath, unit, { mode: 420 });
|
|
49032
49131
|
return unitPath;
|
|
49033
49132
|
}
|
|
49034
49133
|
function systemctl(args) {
|
|
49035
|
-
const r =
|
|
49134
|
+
const r = spawnSync2("systemctl", ["--user", ...args], { encoding: "utf8" });
|
|
49036
49135
|
return { ok: r.status === 0, out: r.stdout ?? "", err: r.stderr ?? "" };
|
|
49037
49136
|
}
|
|
49038
49137
|
function linuxInstall() {
|
|
@@ -49048,7 +49147,7 @@ function linuxInstall() {
|
|
|
49048
49147
|
function linuxUninstall() {
|
|
49049
49148
|
systemctl(["disable", "--now", `${SYSTEMD_UNIT}.service`]);
|
|
49050
49149
|
const unit = systemdUnitPath();
|
|
49051
|
-
if (
|
|
49150
|
+
if (existsSync8(unit)) {
|
|
49052
49151
|
try {
|
|
49053
49152
|
unlinkSync(unit);
|
|
49054
49153
|
} catch {
|
|
@@ -49062,7 +49161,7 @@ function linuxStatus() {
|
|
|
49062
49161
|
return { running: active, hint: active ? "systemd managed" : "not running" };
|
|
49063
49162
|
}
|
|
49064
49163
|
function installService() {
|
|
49065
|
-
const p =
|
|
49164
|
+
const p = platform3();
|
|
49066
49165
|
if (p === "darwin") {
|
|
49067
49166
|
macInstall();
|
|
49068
49167
|
return { path: plistPath(), logs: logDir() };
|
|
@@ -49076,13 +49175,13 @@ function installService() {
|
|
|
49076
49175
|
);
|
|
49077
49176
|
}
|
|
49078
49177
|
function uninstallService() {
|
|
49079
|
-
const p =
|
|
49178
|
+
const p = platform3();
|
|
49080
49179
|
if (p === "darwin") return macUninstall();
|
|
49081
49180
|
if (p === "linux") return linuxUninstall();
|
|
49082
49181
|
throw new Error(`Service uninstall isn't supported on ${p}.`);
|
|
49083
49182
|
}
|
|
49084
49183
|
function serviceStatus() {
|
|
49085
|
-
const p =
|
|
49184
|
+
const p = platform3();
|
|
49086
49185
|
if (p === "darwin") return macStatus();
|
|
49087
49186
|
if (p === "linux") return linuxStatus();
|
|
49088
49187
|
return { running: false, hint: `unsupported platform (${p})` };
|
|
@@ -49091,60 +49190,60 @@ function logsDir() {
|
|
|
49091
49190
|
return logDir();
|
|
49092
49191
|
}
|
|
49093
49192
|
function installTrayApp(sourceAppPath) {
|
|
49094
|
-
if (
|
|
49095
|
-
if (!
|
|
49096
|
-
const dest =
|
|
49097
|
-
|
|
49098
|
-
|
|
49099
|
-
const r =
|
|
49193
|
+
if (platform3() !== "darwin") return null;
|
|
49194
|
+
if (!existsSync8(sourceAppPath)) return null;
|
|
49195
|
+
const dest = join7(home(), "Applications", "ModelstatTray.app");
|
|
49196
|
+
mkdirSync3(dirname6(dest), { recursive: true });
|
|
49197
|
+
spawnSync2("rm", ["-rf", dest]);
|
|
49198
|
+
const r = spawnSync2("cp", ["-R", sourceAppPath, dest], { encoding: "utf8" });
|
|
49100
49199
|
if (r.status !== 0) {
|
|
49101
49200
|
throw new Error(`cp ModelstatTray.app failed: ${r.stderr?.trim() || `exit ${r.status}`}`);
|
|
49102
49201
|
}
|
|
49103
49202
|
return { installedAt: dest };
|
|
49104
49203
|
}
|
|
49105
49204
|
function bundledTrayAppPath() {
|
|
49106
|
-
if (
|
|
49205
|
+
if (platform3() !== "darwin") return null;
|
|
49107
49206
|
const here2 = dirname6(fileURLToPath2(import.meta.url));
|
|
49108
49207
|
const candidates = [
|
|
49109
49208
|
// Pre-built .app — CI with codesigning drops one here.
|
|
49110
|
-
|
|
49209
|
+
join7(here2, "..", "vendor", "ModelstatTray.app"),
|
|
49111
49210
|
// Local dev layout: apps/agent-dev/src/service.ts → ../../tray-mac/build/ModelstatTray.app
|
|
49112
|
-
|
|
49211
|
+
join7(here2, "..", "..", "tray-mac", "build", "ModelstatTray.app")
|
|
49113
49212
|
];
|
|
49114
49213
|
for (const c of candidates) {
|
|
49115
|
-
if (
|
|
49214
|
+
if (existsSync8(c)) return c;
|
|
49116
49215
|
}
|
|
49117
49216
|
const sourceDirs = [
|
|
49118
|
-
|
|
49119
|
-
|
|
49217
|
+
join7(here2, "..", "vendor", "tray-mac"),
|
|
49218
|
+
join7(here2, "..", "..", "tray-mac")
|
|
49120
49219
|
];
|
|
49121
49220
|
for (const src of sourceDirs) {
|
|
49122
|
-
const build =
|
|
49123
|
-
if (!
|
|
49221
|
+
const build = join7(src, "build-app.sh");
|
|
49222
|
+
if (!existsSync8(build)) continue;
|
|
49124
49223
|
if (!hasSwift()) return null;
|
|
49125
|
-
const r =
|
|
49224
|
+
const r = spawnSync2("bash", [build], { cwd: src, encoding: "utf8" });
|
|
49126
49225
|
if (r.status === 0) {
|
|
49127
|
-
const app =
|
|
49128
|
-
if (
|
|
49226
|
+
const app = join7(src, "build", "ModelstatTray.app");
|
|
49227
|
+
if (existsSync8(app)) return app;
|
|
49129
49228
|
}
|
|
49130
49229
|
}
|
|
49131
49230
|
return null;
|
|
49132
49231
|
}
|
|
49133
49232
|
function hasSwift() {
|
|
49134
|
-
const r =
|
|
49233
|
+
const r = spawnSync2("swift", ["--version"], { encoding: "utf8" });
|
|
49135
49234
|
return r.status === 0;
|
|
49136
49235
|
}
|
|
49137
49236
|
function trayStatus() {
|
|
49138
|
-
if (
|
|
49237
|
+
if (platform3() !== "darwin") return { installed: false, path: null };
|
|
49139
49238
|
const exe = locateTrayExecutable();
|
|
49140
49239
|
return exe ? { installed: true, path: exe.replace(/\/Contents\/MacOS\/modelstat-tray$/, "") } : { installed: false, path: null };
|
|
49141
49240
|
}
|
|
49142
49241
|
|
|
49143
49242
|
// src/supervise.ts
|
|
49144
49243
|
init_lock();
|
|
49145
|
-
import { readFileSync as
|
|
49146
|
-
import { homedir as
|
|
49147
|
-
import { join as
|
|
49244
|
+
import { readFileSync as readFileSync6 } from "fs";
|
|
49245
|
+
import { homedir as homedir9 } from "os";
|
|
49246
|
+
import { join as join9 } from "path";
|
|
49148
49247
|
var STATUS_FRESH_MS = 12e4;
|
|
49149
49248
|
var BOOT_GRACE_MS = 9e4;
|
|
49150
49249
|
function decideSupervision(input) {
|
|
@@ -49161,13 +49260,13 @@ function decideSupervision(input) {
|
|
|
49161
49260
|
function daemonHealth(opts = {}) {
|
|
49162
49261
|
const now = opts.now ?? Date.now();
|
|
49163
49262
|
const pidAlive = opts.pidAlive ?? isProcessAlive;
|
|
49164
|
-
const statusPath = opts.statusPath ??
|
|
49263
|
+
const statusPath = opts.statusPath ?? join9(homedir9(), ".modelstat", "last-status.json");
|
|
49165
49264
|
const lock = opts.lockPath === void 0 ? readDaemonLock() : readDaemonLock(opts.lockPath);
|
|
49166
49265
|
const ownerAlive = lock !== null && pidAlive(lock.pid);
|
|
49167
49266
|
const lockAgeMs = lock ? ageMs(lock.startedAt, now) : null;
|
|
49168
49267
|
let statusAgeMs = null;
|
|
49169
49268
|
try {
|
|
49170
|
-
const raw =
|
|
49269
|
+
const raw = readFileSync6(statusPath, "utf8");
|
|
49171
49270
|
const writtenAt = JSON.parse(raw).written_at;
|
|
49172
49271
|
statusAgeMs = writtenAt ? ageMs(writtenAt, now) : null;
|
|
49173
49272
|
} catch {
|
|
@@ -49209,7 +49308,7 @@ async function confirmPrompt(question, defaultYes) {
|
|
|
49209
49308
|
}
|
|
49210
49309
|
}
|
|
49211
49310
|
function tryOpenBrowser(url) {
|
|
49212
|
-
const p =
|
|
49311
|
+
const p = platform5();
|
|
49213
49312
|
const cmd = p === "darwin" ? "open" : p === "win32" ? "cmd" : "xdg-open";
|
|
49214
49313
|
const args = p === "win32" ? ["/c", "start", "", url] : [url];
|
|
49215
49314
|
try {
|
|
@@ -49223,9 +49322,9 @@ function tryOpenBrowser(url) {
|
|
|
49223
49322
|
return false;
|
|
49224
49323
|
}
|
|
49225
49324
|
}
|
|
49226
|
-
var AGENT_VERSION3 = true ? "agent-0.0.
|
|
49325
|
+
var AGENT_VERSION3 = true ? "agent-0.0.49" : "agent-dev";
|
|
49227
49326
|
function osFamily() {
|
|
49228
|
-
const p =
|
|
49327
|
+
const p = platform5();
|
|
49229
49328
|
if (p === "darwin") return "macos";
|
|
49230
49329
|
if (p === "linux") return "linux";
|
|
49231
49330
|
return "other";
|
|
@@ -49236,35 +49335,33 @@ function osArch() {
|
|
|
49236
49335
|
if (a === "arm64") return "arm64";
|
|
49237
49336
|
return "other";
|
|
49238
49337
|
}
|
|
49239
|
-
function
|
|
49240
|
-
const
|
|
49241
|
-
const
|
|
49242
|
-
|
|
49243
|
-
rand[0] = rand[0] & 15 | 112;
|
|
49244
|
-
rand[2] = rand[2] & 63 | 128;
|
|
49245
|
-
const hex = tsHex + rand.toString("hex");
|
|
49246
|
-
return [
|
|
49247
|
-
hex.slice(0, 8),
|
|
49248
|
-
hex.slice(8, 12),
|
|
49249
|
-
hex.slice(12, 16),
|
|
49250
|
-
hex.slice(16, 20),
|
|
49251
|
-
hex.slice(20, 32)
|
|
49252
|
-
].join("-");
|
|
49338
|
+
function intendedDeviceUuid() {
|
|
49339
|
+
const salt = process.env.MODELSTAT_DEVICE_SALT?.trim();
|
|
49340
|
+
const key = salt ? `${machineKey()}:${salt}` : machineKey();
|
|
49341
|
+
return deviceUuidFromMachineKey(key);
|
|
49253
49342
|
}
|
|
49254
49343
|
async function cmdSelfRegister() {
|
|
49255
|
-
const deviceUuid = state.deviceUuid ??
|
|
49256
|
-
const
|
|
49344
|
+
const deviceUuid = state.deviceUuid ?? intendedDeviceUuid();
|
|
49345
|
+
const derived = !state.deviceUuid;
|
|
49346
|
+
const mid = machineKey();
|
|
49257
49347
|
const fingerprint = {
|
|
49258
49348
|
hostname: hostname2(),
|
|
49259
49349
|
os_family: osFamily(),
|
|
49260
49350
|
os_version: release(),
|
|
49261
49351
|
arch: osArch(),
|
|
49262
49352
|
agent: "modelstat-agent-dev",
|
|
49263
|
-
agent_version: AGENT_VERSION3
|
|
49353
|
+
agent_version: AGENT_VERSION3,
|
|
49354
|
+
// Stable, install-method-independent machine key. The server
|
|
49355
|
+
// dedupes self-register on this so the same physical machine can
|
|
49356
|
+
// never become two device rows, even if the UUID somehow differs
|
|
49357
|
+
// (legacy random UUID → deterministic UUID transition).
|
|
49358
|
+
machine_id: mid
|
|
49264
49359
|
};
|
|
49265
|
-
if (
|
|
49266
|
-
process.stdout.write(
|
|
49267
|
-
`)
|
|
49360
|
+
if (derived) {
|
|
49361
|
+
process.stdout.write(
|
|
49362
|
+
` \x1B[2mdevice id derived from machine key (${machineKeySource()}): ${deviceUuid.slice(0, 8)}\u2026\x1B[0m
|
|
49363
|
+
`
|
|
49364
|
+
);
|
|
49268
49365
|
}
|
|
49269
49366
|
process.stdout.write(` \x1B[2m\u2192 POST ${state.apiUrl}/v1/devices/self-register\x1B[0m
|
|
49270
49367
|
`);
|
|
@@ -49344,7 +49441,7 @@ async function cmdConnect(opts) {
|
|
|
49344
49441
|
await cmdSelfRegister();
|
|
49345
49442
|
};
|
|
49346
49443
|
if (opts.fresh && hasIdentityFile()) {
|
|
49347
|
-
step("`--fresh` passed \u2014
|
|
49444
|
+
step("`--fresh` passed \u2014 re-registering this device");
|
|
49348
49445
|
await wipeAndSelfRegister("forced fresh start");
|
|
49349
49446
|
} else if (!state.deviceUuid || !state.bearer || !state.deviceId) {
|
|
49350
49447
|
step("Registering this device with modelstat.ai");
|
|
@@ -49389,7 +49486,7 @@ async function cmdConnect(opts) {
|
|
|
49389
49486
|
claim_url: claimUrl,
|
|
49390
49487
|
agent_url: agentUrl
|
|
49391
49488
|
});
|
|
49392
|
-
if (
|
|
49489
|
+
if (platform5() === "darwin") {
|
|
49393
49490
|
step("Installing menu-bar tray (macOS)");
|
|
49394
49491
|
try {
|
|
49395
49492
|
const src = bundledTrayAppPath();
|
|
@@ -49433,7 +49530,7 @@ async function cmdConnect(opts) {
|
|
|
49433
49530
|
logs: svc.logs,
|
|
49434
49531
|
summariser_ready: modelReady
|
|
49435
49532
|
});
|
|
49436
|
-
ok(`${
|
|
49533
|
+
ok(`${platform5() === "darwin" ? "launchd" : "systemd --user"}: ${svc.path}`);
|
|
49437
49534
|
} catch (e) {
|
|
49438
49535
|
emitEvent(opts, "service_install_failed", { error: e.message });
|
|
49439
49536
|
warn(`couldn't install service: ${e.message}`);
|
|
@@ -49476,7 +49573,7 @@ async function cmdConnect(opts) {
|
|
|
49476
49573
|
` detected: \x1B[32m${discovered.installations} installs \xB7 ${discovered.identities} accounts\x1B[0m`
|
|
49477
49574
|
);
|
|
49478
49575
|
}
|
|
49479
|
-
if (
|
|
49576
|
+
if (platform5() === "darwin") {
|
|
49480
49577
|
console.log(
|
|
49481
49578
|
` tray : \x1B[${tray.installed ? "32" : "2"}m${tray.installed ? "menu-bar icon ready" : "not installed"}\x1B[0m`
|
|
49482
49579
|
);
|
|
@@ -49607,10 +49704,10 @@ function fmtTokens(v) {
|
|
|
49607
49704
|
}
|
|
49608
49705
|
async function readLocalStatus() {
|
|
49609
49706
|
try {
|
|
49610
|
-
const { homedir:
|
|
49611
|
-
const { join:
|
|
49707
|
+
const { homedir: homedir11 } = await import("os");
|
|
49708
|
+
const { join: join13 } = await import("path");
|
|
49612
49709
|
const { readFile } = await import("fs/promises");
|
|
49613
|
-
const p =
|
|
49710
|
+
const p = join13(homedir11(), ".modelstat", "last-status.json");
|
|
49614
49711
|
const txt = await readFile(p, "utf8");
|
|
49615
49712
|
return JSON.parse(txt);
|
|
49616
49713
|
} catch {
|
|
@@ -49730,11 +49827,17 @@ async function cmdJobs(args) {
|
|
|
49730
49827
|
}
|
|
49731
49828
|
}
|
|
49732
49829
|
function cmdPaths(args) {
|
|
49830
|
+
const intended = intendedDeviceUuid();
|
|
49733
49831
|
const data = {
|
|
49734
49832
|
state: state.storePath,
|
|
49833
|
+
identity: identityPath(),
|
|
49735
49834
|
logs: logsDir(),
|
|
49736
49835
|
api: state.apiUrl,
|
|
49737
|
-
paired: !!state.bearer && !!state.deviceId
|
|
49836
|
+
paired: !!state.bearer && !!state.deviceId,
|
|
49837
|
+
device_id: state.deviceId ?? "(none)",
|
|
49838
|
+
device_uuid: state.deviceUuid ?? "(none)",
|
|
49839
|
+
intended_uuid: intended,
|
|
49840
|
+
machine_key_source: machineKeySource()
|
|
49738
49841
|
};
|
|
49739
49842
|
if (args.includes("--json")) {
|
|
49740
49843
|
process.stdout.write(`${JSON.stringify(data)}
|
|
@@ -49841,10 +49944,18 @@ async function main() {
|
|
|
49841
49944
|
console.log();
|
|
49842
49945
|
console.log("Diagnostics:");
|
|
49843
49946
|
console.log(" npx modelstat@latest status \u2014 show pairing + service state");
|
|
49844
|
-
console.log(
|
|
49845
|
-
|
|
49846
|
-
|
|
49847
|
-
console.log(
|
|
49947
|
+
console.log(
|
|
49948
|
+
" npx modelstat@latest stats \u2014 live device summary: sessions \xB7 tokens \xB7 cost (--json)"
|
|
49949
|
+
);
|
|
49950
|
+
console.log(
|
|
49951
|
+
" npx modelstat@latest jobs \u2014 pipeline queue + recent processing ledger (--json)"
|
|
49952
|
+
);
|
|
49953
|
+
console.log(
|
|
49954
|
+
" npx modelstat@latest paths \u2014 print state file + log dir + api URL (--json)"
|
|
49955
|
+
);
|
|
49956
|
+
console.log(
|
|
49957
|
+
" npx modelstat@latest token \u2014 print the device token for hosted MCP / API access (--json)"
|
|
49958
|
+
);
|
|
49848
49959
|
console.log();
|
|
49849
49960
|
console.log("Dev / one-shots:");
|
|
49850
49961
|
console.log(" npx modelstat@latest scan \u2014 one-shot parse + upload of local JSONL");
|