modelstat 0.0.22 → 0.0.23
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 +342 -146
- package/dist/cli.mjs.map +1 -1
- package/package.json +1 -1
package/dist/cli.mjs
CHANGED
|
@@ -7487,6 +7487,107 @@ var init_src2 = __esm({
|
|
|
7487
7487
|
}
|
|
7488
7488
|
});
|
|
7489
7489
|
|
|
7490
|
+
// src/identity.ts
|
|
7491
|
+
import {
|
|
7492
|
+
chmodSync,
|
|
7493
|
+
mkdirSync,
|
|
7494
|
+
readFileSync as readFileSync2,
|
|
7495
|
+
renameSync,
|
|
7496
|
+
writeFileSync,
|
|
7497
|
+
existsSync as existsSync3
|
|
7498
|
+
} from "fs";
|
|
7499
|
+
import { homedir as homedir2, hostname as osHostname } from "os";
|
|
7500
|
+
import { join as join2 } from "path";
|
|
7501
|
+
function ensureRoot() {
|
|
7502
|
+
mkdirSync(ROOT, { recursive: true, mode: 448 });
|
|
7503
|
+
}
|
|
7504
|
+
function writeAtomic(meta) {
|
|
7505
|
+
ensureRoot();
|
|
7506
|
+
const tmp = `${IDENTITY_FILE}.${process.pid}.tmp`;
|
|
7507
|
+
writeFileSync(tmp, JSON.stringify(meta, null, 2), { mode: 384 });
|
|
7508
|
+
renameSync(tmp, IDENTITY_FILE);
|
|
7509
|
+
try {
|
|
7510
|
+
chmodSync(IDENTITY_FILE, 384);
|
|
7511
|
+
} catch {
|
|
7512
|
+
}
|
|
7513
|
+
}
|
|
7514
|
+
function identityPath() {
|
|
7515
|
+
return IDENTITY_FILE;
|
|
7516
|
+
}
|
|
7517
|
+
function hasIdentityFile() {
|
|
7518
|
+
return existsSync3(IDENTITY_FILE);
|
|
7519
|
+
}
|
|
7520
|
+
function parseFile() {
|
|
7521
|
+
try {
|
|
7522
|
+
const raw = readFileSync2(IDENTITY_FILE, "utf8");
|
|
7523
|
+
const obj = JSON.parse(raw);
|
|
7524
|
+
if (!obj.deviceUuid || !obj.deviceId || !obj.bearerToken) {
|
|
7525
|
+
return null;
|
|
7526
|
+
}
|
|
7527
|
+
return {
|
|
7528
|
+
deviceUuid: obj.deviceUuid,
|
|
7529
|
+
deviceId: obj.deviceId,
|
|
7530
|
+
bearerToken: obj.bearerToken,
|
|
7531
|
+
claimCode: obj.claimCode ?? null,
|
|
7532
|
+
claimUrl: obj.claimUrl ?? null,
|
|
7533
|
+
hostname: obj.hostname ?? osHostname(),
|
|
7534
|
+
createdAt: obj.createdAt ?? (/* @__PURE__ */ new Date()).toISOString(),
|
|
7535
|
+
userEmail: obj.userEmail ?? null,
|
|
7536
|
+
defaultOrgId: obj.defaultOrgId ?? null
|
|
7537
|
+
};
|
|
7538
|
+
} catch {
|
|
7539
|
+
return null;
|
|
7540
|
+
}
|
|
7541
|
+
}
|
|
7542
|
+
function loadIdentity(migrateFromConf2) {
|
|
7543
|
+
const fromFile = parseFile();
|
|
7544
|
+
if (fromFile) return fromFile;
|
|
7545
|
+
if (!migrateFromConf2) return null;
|
|
7546
|
+
const legacy = migrateFromConf2();
|
|
7547
|
+
if (!legacy) return null;
|
|
7548
|
+
if (!legacy.deviceUuid || !legacy.deviceId || !legacy.bearerToken) {
|
|
7549
|
+
return null;
|
|
7550
|
+
}
|
|
7551
|
+
const migrated = {
|
|
7552
|
+
deviceUuid: legacy.deviceUuid,
|
|
7553
|
+
deviceId: legacy.deviceId,
|
|
7554
|
+
bearerToken: legacy.bearerToken,
|
|
7555
|
+
claimCode: legacy.claimCode ?? null,
|
|
7556
|
+
claimUrl: legacy.claimUrl ?? null,
|
|
7557
|
+
hostname: osHostname(),
|
|
7558
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
7559
|
+
userEmail: legacy.userEmail ?? null,
|
|
7560
|
+
defaultOrgId: legacy.defaultOrgId ?? null
|
|
7561
|
+
};
|
|
7562
|
+
writeAtomic(migrated);
|
|
7563
|
+
return migrated;
|
|
7564
|
+
}
|
|
7565
|
+
function saveIdentity(meta) {
|
|
7566
|
+
writeAtomic(meta);
|
|
7567
|
+
}
|
|
7568
|
+
function backupIdentity() {
|
|
7569
|
+
if (!existsSync3(IDENTITY_FILE)) return null;
|
|
7570
|
+
const stamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
7571
|
+
const dest = `${IDENTITY_FILE}.bak-${stamp}`;
|
|
7572
|
+
renameSync(IDENTITY_FILE, dest);
|
|
7573
|
+
return dest;
|
|
7574
|
+
}
|
|
7575
|
+
function updateIdentity(patch) {
|
|
7576
|
+
const current = parseFile();
|
|
7577
|
+
if (!current) return null;
|
|
7578
|
+
const merged = { ...current, ...patch };
|
|
7579
|
+
writeAtomic(merged);
|
|
7580
|
+
return merged;
|
|
7581
|
+
}
|
|
7582
|
+
var ROOT, IDENTITY_FILE;
|
|
7583
|
+
var init_identity = __esm({
|
|
7584
|
+
"src/identity.ts"() {
|
|
7585
|
+
"use strict";
|
|
7586
|
+
ROOT = join2(homedir2(), ".modelstat");
|
|
7587
|
+
IDENTITY_FILE = join2(ROOT, "identity.json");
|
|
7588
|
+
}
|
|
7589
|
+
});
|
|
7590
|
+
|
|
7490
7591
|
// ../../node_modules/.pnpm/undici@7.25.0/node_modules/undici/lib/core/symbols.js
|
|
7491
7592
|
var require_symbols = __commonJS({
|
|
7492
7593
|
"../../node_modules/.pnpm/undici@7.25.0/node_modules/undici/lib/core/symbols.js"(exports, module) {
|
|
@@ -33061,15 +33162,15 @@ function envPaths(name, { suffix = "nodejs" } = {}) {
|
|
|
33061
33162
|
}
|
|
33062
33163
|
return linux(name);
|
|
33063
33164
|
}
|
|
33064
|
-
var
|
|
33165
|
+
var homedir3, tmpdir, env, macos, windows, linux;
|
|
33065
33166
|
var init_env_paths = __esm({
|
|
33066
33167
|
"../../node_modules/.pnpm/env-paths@3.0.0/node_modules/env-paths/index.js"() {
|
|
33067
33168
|
"use strict";
|
|
33068
|
-
|
|
33169
|
+
homedir3 = os.homedir();
|
|
33069
33170
|
tmpdir = os.tmpdir();
|
|
33070
33171
|
({ env } = process2);
|
|
33071
33172
|
macos = (name) => {
|
|
33072
|
-
const library = path.join(
|
|
33173
|
+
const library = path.join(homedir3, "Library");
|
|
33073
33174
|
return {
|
|
33074
33175
|
data: path.join(library, "Application Support", name),
|
|
33075
33176
|
config: path.join(library, "Preferences", name),
|
|
@@ -33079,8 +33180,8 @@ var init_env_paths = __esm({
|
|
|
33079
33180
|
};
|
|
33080
33181
|
};
|
|
33081
33182
|
windows = (name) => {
|
|
33082
|
-
const appData = env.APPDATA || path.join(
|
|
33083
|
-
const localAppData = env.LOCALAPPDATA || path.join(
|
|
33183
|
+
const appData = env.APPDATA || path.join(homedir3, "AppData", "Roaming");
|
|
33184
|
+
const localAppData = env.LOCALAPPDATA || path.join(homedir3, "AppData", "Local");
|
|
33084
33185
|
return {
|
|
33085
33186
|
// Data/config/cache/log are invented by me as Windows isn't opinionated about this
|
|
33086
33187
|
data: path.join(localAppData, name, "Data"),
|
|
@@ -33091,13 +33192,13 @@ var init_env_paths = __esm({
|
|
|
33091
33192
|
};
|
|
33092
33193
|
};
|
|
33093
33194
|
linux = (name) => {
|
|
33094
|
-
const username = path.basename(
|
|
33195
|
+
const username = path.basename(homedir3);
|
|
33095
33196
|
return {
|
|
33096
|
-
data: path.join(env.XDG_DATA_HOME || path.join(
|
|
33097
|
-
config: path.join(env.XDG_CONFIG_HOME || path.join(
|
|
33098
|
-
cache: path.join(env.XDG_CACHE_HOME || path.join(
|
|
33197
|
+
data: path.join(env.XDG_DATA_HOME || path.join(homedir3, ".local", "share"), name),
|
|
33198
|
+
config: path.join(env.XDG_CONFIG_HOME || path.join(homedir3, ".config"), name),
|
|
33199
|
+
cache: path.join(env.XDG_CACHE_HOME || path.join(homedir3, ".cache"), name),
|
|
33099
33200
|
// https://wiki.debian.org/XDGBaseDirectorySpecification#state
|
|
33100
|
-
log: path.join(env.XDG_STATE_HOME || path.join(
|
|
33201
|
+
log: path.join(env.XDG_STATE_HOME || path.join(homedir3, ".local", "state"), name),
|
|
33101
33202
|
temp: path.join(tmpdir, username, name)
|
|
33102
33203
|
};
|
|
33103
33204
|
};
|
|
@@ -33538,9 +33639,9 @@ import { once } from "events";
|
|
|
33538
33639
|
import { createWriteStream } from "fs";
|
|
33539
33640
|
import path3 from "path";
|
|
33540
33641
|
import { Readable } from "stream";
|
|
33541
|
-
function
|
|
33642
|
+
function writeFileSync2(filePath, data, options = DEFAULT_WRITE_OPTIONS) {
|
|
33542
33643
|
if (isString(options))
|
|
33543
|
-
return
|
|
33644
|
+
return writeFileSync2(filePath, data, { encoding: options });
|
|
33544
33645
|
const timeout = options.timeout ?? DEFAULT_TIMEOUT_SYNC;
|
|
33545
33646
|
const retryOptions = { timeout };
|
|
33546
33647
|
let tempDisposer = null;
|
|
@@ -43663,7 +43764,7 @@ var init_source = __esm({
|
|
|
43663
43764
|
fs2.writeFileSync(this.path, data, { mode: this.#options.configFileMode });
|
|
43664
43765
|
} else {
|
|
43665
43766
|
try {
|
|
43666
|
-
|
|
43767
|
+
writeFileSync2(this.path, data, { mode: this.#options.configFileMode });
|
|
43667
43768
|
} catch (error) {
|
|
43668
43769
|
if (error?.code === "EXDEV") {
|
|
43669
43770
|
fs2.writeFileSync(this.path, data, { mode: this.#options.configFileMode });
|
|
@@ -43765,20 +43866,52 @@ var init_source = __esm({
|
|
|
43765
43866
|
});
|
|
43766
43867
|
|
|
43767
43868
|
// src/config.ts
|
|
43768
|
-
import { existsSync as
|
|
43869
|
+
import { existsSync as existsSync4 } from "fs";
|
|
43769
43870
|
import { hostname } from "os";
|
|
43770
43871
|
import { dirname as dirname2, resolve as resolve3 } from "path";
|
|
43771
43872
|
import { fileURLToPath } from "url";
|
|
43772
|
-
|
|
43873
|
+
function migrateFromConf() {
|
|
43874
|
+
const bearer = store.get("bearerToken");
|
|
43875
|
+
const deviceUuid = store.get("deviceUuid");
|
|
43876
|
+
const deviceId = store.get("deviceId");
|
|
43877
|
+
if (!bearer || !deviceUuid || !deviceId) return null;
|
|
43878
|
+
return {
|
|
43879
|
+
bearerToken: bearer,
|
|
43880
|
+
deviceId,
|
|
43881
|
+
deviceUuid,
|
|
43882
|
+
claimCode: store.get("claimCode"),
|
|
43883
|
+
claimUrl: store.get("claimUrl"),
|
|
43884
|
+
userEmail: store.get("userEmail"),
|
|
43885
|
+
defaultOrgId: store.get("defaultOrgId")
|
|
43886
|
+
};
|
|
43887
|
+
}
|
|
43888
|
+
function clearConfIdentity() {
|
|
43889
|
+
store.set("bearerToken", null);
|
|
43890
|
+
store.set("deviceId", null);
|
|
43891
|
+
store.set("deviceUuid", null);
|
|
43892
|
+
store.set("claimCode", null);
|
|
43893
|
+
store.set("claimUrl", null);
|
|
43894
|
+
}
|
|
43895
|
+
function writeThrough(patch) {
|
|
43896
|
+
if (!cachedIdentity) {
|
|
43897
|
+
throw new Error(
|
|
43898
|
+
"config: no identity yet \u2014 call state.saveFreshIdentity() first"
|
|
43899
|
+
);
|
|
43900
|
+
}
|
|
43901
|
+
cachedIdentity = { ...cachedIdentity, ...patch };
|
|
43902
|
+
updateIdentity(patch);
|
|
43903
|
+
}
|
|
43904
|
+
var import_dotenv, here, DEFAULT_API_URL, LEGACY_LOCALHOST_API, store, cachedIdentity, state;
|
|
43773
43905
|
var init_config2 = __esm({
|
|
43774
43906
|
"src/config.ts"() {
|
|
43775
43907
|
"use strict";
|
|
43776
43908
|
import_dotenv = __toESM(require_main(), 1);
|
|
43777
43909
|
init_source();
|
|
43910
|
+
init_identity();
|
|
43778
43911
|
here = dirname2(fileURLToPath(import.meta.url));
|
|
43779
43912
|
for (let d = here, i = 0; i < 8; i++, d = resolve3(d, "..")) {
|
|
43780
43913
|
const candidate = resolve3(d, ".env");
|
|
43781
|
-
if (
|
|
43914
|
+
if (existsSync4(candidate)) {
|
|
43782
43915
|
(0, import_dotenv.config)({ path: candidate });
|
|
43783
43916
|
break;
|
|
43784
43917
|
}
|
|
@@ -43804,6 +43937,14 @@ var init_config2 = __esm({
|
|
|
43804
43937
|
cursor: {}
|
|
43805
43938
|
}
|
|
43806
43939
|
});
|
|
43940
|
+
cachedIdentity = (() => {
|
|
43941
|
+
const had = store.get("bearerToken") !== null;
|
|
43942
|
+
const id = loadIdentity(migrateFromConf);
|
|
43943
|
+
if (id && had && !store.path.includes("fallback")) {
|
|
43944
|
+
clearConfIdentity();
|
|
43945
|
+
}
|
|
43946
|
+
return id;
|
|
43947
|
+
})();
|
|
43807
43948
|
state = {
|
|
43808
43949
|
/** Resolution order: env var → stored value (if user ran `setApiUrl`
|
|
43809
43950
|
* or paired pre-0.0.8) → production default. The legacy localhost
|
|
@@ -43817,42 +43958,66 @@ var init_config2 = __esm({
|
|
|
43817
43958
|
setApiUrl(v) {
|
|
43818
43959
|
store.set("apiUrl", v);
|
|
43819
43960
|
},
|
|
43961
|
+
// ── Identity: backed by ~/.modelstat/identity.json ─────────────
|
|
43962
|
+
/** Seed a fresh identity after a successful self-register. Writes
|
|
43963
|
+
* the file atomically; use `state.backupAndReset()` first if
|
|
43964
|
+
* overwriting an existing identity. */
|
|
43965
|
+
saveFreshIdentity(meta) {
|
|
43966
|
+
const id = {
|
|
43967
|
+
deviceUuid: meta.deviceUuid,
|
|
43968
|
+
deviceId: meta.deviceId,
|
|
43969
|
+
bearerToken: meta.bearerToken,
|
|
43970
|
+
claimCode: meta.claimCode,
|
|
43971
|
+
claimUrl: meta.claimUrl,
|
|
43972
|
+
hostname: hostname(),
|
|
43973
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
43974
|
+
userEmail: null,
|
|
43975
|
+
defaultOrgId: null
|
|
43976
|
+
};
|
|
43977
|
+
saveIdentity(id);
|
|
43978
|
+
cachedIdentity = id;
|
|
43979
|
+
},
|
|
43980
|
+
get identity() {
|
|
43981
|
+
return cachedIdentity;
|
|
43982
|
+
},
|
|
43820
43983
|
get bearer() {
|
|
43821
|
-
return
|
|
43984
|
+
return cachedIdentity?.bearerToken ?? null;
|
|
43822
43985
|
},
|
|
43823
43986
|
setBearer(v) {
|
|
43824
|
-
|
|
43987
|
+
if (v === null) {
|
|
43988
|
+
cachedIdentity = null;
|
|
43989
|
+
return;
|
|
43990
|
+
}
|
|
43991
|
+
writeThrough({ bearerToken: v });
|
|
43825
43992
|
},
|
|
43826
43993
|
get deviceId() {
|
|
43827
|
-
return
|
|
43828
|
-
},
|
|
43829
|
-
setDeviceId(v) {
|
|
43830
|
-
store.set("deviceId", v);
|
|
43831
|
-
},
|
|
43832
|
-
get userEmail() {
|
|
43833
|
-
return store.get("userEmail");
|
|
43834
|
-
},
|
|
43835
|
-
setUserEmail(v) {
|
|
43836
|
-
store.set("userEmail", v);
|
|
43994
|
+
return cachedIdentity?.deviceId ?? null;
|
|
43837
43995
|
},
|
|
43838
43996
|
get deviceUuid() {
|
|
43839
|
-
return
|
|
43840
|
-
},
|
|
43841
|
-
setDeviceUuid(v) {
|
|
43842
|
-
store.set("deviceUuid", v);
|
|
43997
|
+
return cachedIdentity?.deviceUuid ?? null;
|
|
43843
43998
|
},
|
|
43844
43999
|
get claimCode() {
|
|
43845
|
-
return
|
|
44000
|
+
return cachedIdentity?.claimCode ?? null;
|
|
43846
44001
|
},
|
|
43847
44002
|
setClaimCode(v) {
|
|
43848
|
-
|
|
44003
|
+
if (!cachedIdentity) return;
|
|
44004
|
+
writeThrough({ claimCode: v });
|
|
43849
44005
|
},
|
|
43850
44006
|
get claimUrl() {
|
|
43851
|
-
return
|
|
44007
|
+
return cachedIdentity?.claimUrl ?? null;
|
|
43852
44008
|
},
|
|
43853
44009
|
setClaimUrl(v) {
|
|
43854
|
-
|
|
44010
|
+
if (!cachedIdentity) return;
|
|
44011
|
+
writeThrough({ claimUrl: v });
|
|
44012
|
+
},
|
|
44013
|
+
get userEmail() {
|
|
44014
|
+
return cachedIdentity?.userEmail ?? null;
|
|
43855
44015
|
},
|
|
44016
|
+
setUserEmail(v) {
|
|
44017
|
+
if (!cachedIdentity) return;
|
|
44018
|
+
writeThrough({ userEmail: v });
|
|
44019
|
+
},
|
|
44020
|
+
// ── Runtime state: stays in conf ───────────────────────────────
|
|
43856
44021
|
getCursor(path5) {
|
|
43857
44022
|
return store.get("cursor")[path5];
|
|
43858
44023
|
},
|
|
@@ -44402,23 +44567,23 @@ var init_pipeline2 = __esm({
|
|
|
44402
44567
|
|
|
44403
44568
|
// src/scan.ts
|
|
44404
44569
|
import { readdir, stat as stat2 } from "fs/promises";
|
|
44405
|
-
import { homedir as
|
|
44406
|
-
import { join as
|
|
44570
|
+
import { homedir as homedir4 } from "os";
|
|
44571
|
+
import { join as join3 } from "path";
|
|
44407
44572
|
async function scanAll(cb = {}) {
|
|
44408
44573
|
const deviceId = state.deviceId;
|
|
44409
44574
|
if (!deviceId) throw new Error("agent not enrolled \u2014 run `register` first");
|
|
44410
44575
|
const jobs = [];
|
|
44411
44576
|
try {
|
|
44412
|
-
const base =
|
|
44577
|
+
const base = join3(homedir4(), ".claude/projects");
|
|
44413
44578
|
const projects = await readdir(base).catch(() => []);
|
|
44414
44579
|
for (const p of projects) {
|
|
44415
|
-
const dir =
|
|
44580
|
+
const dir = join3(base, p);
|
|
44416
44581
|
const ds = await stat2(dir).catch(() => null);
|
|
44417
44582
|
if (!ds?.isDirectory()) continue;
|
|
44418
44583
|
const files = await readdir(dir);
|
|
44419
44584
|
for (const f of files) {
|
|
44420
44585
|
if (!f.endsWith(".jsonl")) continue;
|
|
44421
|
-
const full =
|
|
44586
|
+
const full = join3(dir, f);
|
|
44422
44587
|
jobs.push({
|
|
44423
44588
|
path: full,
|
|
44424
44589
|
parse: async () => {
|
|
@@ -44432,17 +44597,17 @@ async function scanAll(cb = {}) {
|
|
|
44432
44597
|
console.warn("claude scan skipped:", e.message);
|
|
44433
44598
|
}
|
|
44434
44599
|
try {
|
|
44435
|
-
const base =
|
|
44600
|
+
const base = join3(homedir4(), ".codex/sessions");
|
|
44436
44601
|
const years = await readdir(base).catch(() => []);
|
|
44437
44602
|
for (const y of years) {
|
|
44438
|
-
const months = await readdir(
|
|
44603
|
+
const months = await readdir(join3(base, y)).catch(() => []);
|
|
44439
44604
|
for (const m of months) {
|
|
44440
|
-
const days = await readdir(
|
|
44605
|
+
const days = await readdir(join3(base, y, m)).catch(() => []);
|
|
44441
44606
|
for (const d of days) {
|
|
44442
|
-
const files = await readdir(
|
|
44607
|
+
const files = await readdir(join3(base, y, m, d)).catch(() => []);
|
|
44443
44608
|
for (const f of files) {
|
|
44444
44609
|
if (!f.startsWith("rollout-") || !f.endsWith(".jsonl")) continue;
|
|
44445
|
-
const full =
|
|
44610
|
+
const full = join3(base, y, m, d, f);
|
|
44446
44611
|
jobs.push({
|
|
44447
44612
|
path: full,
|
|
44448
44613
|
parse: async () => {
|
|
@@ -44516,7 +44681,7 @@ var init_scan = __esm({
|
|
|
44516
44681
|
init_pipeline2();
|
|
44517
44682
|
init_config2();
|
|
44518
44683
|
init_api();
|
|
44519
|
-
AGENT_VERSION = "agent-dev-0.0.
|
|
44684
|
+
AGENT_VERSION = "agent-dev-0.0.23";
|
|
44520
44685
|
BATCH_MAX_EVENTS = 2e3;
|
|
44521
44686
|
}
|
|
44522
44687
|
});
|
|
@@ -44524,17 +44689,17 @@ var init_scan = __esm({
|
|
|
44524
44689
|
// src/lock.ts
|
|
44525
44690
|
import {
|
|
44526
44691
|
closeSync,
|
|
44527
|
-
existsSync as
|
|
44528
|
-
mkdirSync as
|
|
44692
|
+
existsSync as existsSync6,
|
|
44693
|
+
mkdirSync as mkdirSync3,
|
|
44529
44694
|
openSync,
|
|
44530
|
-
readFileSync as
|
|
44531
|
-
renameSync,
|
|
44695
|
+
readFileSync as readFileSync3,
|
|
44696
|
+
renameSync as renameSync2,
|
|
44532
44697
|
unlinkSync as unlinkSync2,
|
|
44533
|
-
writeFileSync as
|
|
44698
|
+
writeFileSync as writeFileSync4,
|
|
44534
44699
|
writeSync
|
|
44535
44700
|
} from "fs";
|
|
44536
|
-
import { homedir as
|
|
44537
|
-
import { join as
|
|
44701
|
+
import { homedir as homedir6 } from "os";
|
|
44702
|
+
import { join as join5 } from "path";
|
|
44538
44703
|
function isProcessAlive(pid) {
|
|
44539
44704
|
if (!pid || pid <= 0) return false;
|
|
44540
44705
|
try {
|
|
@@ -44548,7 +44713,7 @@ function isProcessAlive(pid) {
|
|
|
44548
44713
|
}
|
|
44549
44714
|
function readLock() {
|
|
44550
44715
|
try {
|
|
44551
|
-
const raw =
|
|
44716
|
+
const raw = readFileSync3(LOCK_FILE, "utf8");
|
|
44552
44717
|
const obj = JSON.parse(raw);
|
|
44553
44718
|
if (typeof obj.pid !== "number") return null;
|
|
44554
44719
|
return {
|
|
@@ -44562,7 +44727,7 @@ function readLock() {
|
|
|
44562
44727
|
}
|
|
44563
44728
|
}
|
|
44564
44729
|
function writeLockAtomic(meta) {
|
|
44565
|
-
|
|
44730
|
+
mkdirSync3(LOCK_DIR, { recursive: true });
|
|
44566
44731
|
const tmp = `${LOCK_FILE}.${meta.pid}.${Date.now()}.tmp`;
|
|
44567
44732
|
const fd = openSync(tmp, "wx");
|
|
44568
44733
|
try {
|
|
@@ -44570,7 +44735,7 @@ function writeLockAtomic(meta) {
|
|
|
44570
44735
|
} finally {
|
|
44571
44736
|
closeSync(fd);
|
|
44572
44737
|
}
|
|
44573
|
-
|
|
44738
|
+
renameSync2(tmp, LOCK_FILE);
|
|
44574
44739
|
}
|
|
44575
44740
|
function removeLockIfOwned(ownerPid) {
|
|
44576
44741
|
const lock = readLock();
|
|
@@ -44635,8 +44800,8 @@ var LOCK_DIR, LOCK_FILE;
|
|
|
44635
44800
|
var init_lock = __esm({
|
|
44636
44801
|
"src/lock.ts"() {
|
|
44637
44802
|
"use strict";
|
|
44638
|
-
LOCK_DIR =
|
|
44639
|
-
LOCK_FILE =
|
|
44803
|
+
LOCK_DIR = join5(homedir6(), ".modelstat");
|
|
44804
|
+
LOCK_FILE = join5(LOCK_DIR, "daemon.lock");
|
|
44640
44805
|
}
|
|
44641
44806
|
});
|
|
44642
44807
|
|
|
@@ -46366,7 +46531,7 @@ __export(daemon_exports, {
|
|
|
46366
46531
|
setProgress: () => setProgress,
|
|
46367
46532
|
setQueue: () => setQueue
|
|
46368
46533
|
});
|
|
46369
|
-
import { existsSync as
|
|
46534
|
+
import { existsSync as existsSync7, statSync as statSync2 } from "fs";
|
|
46370
46535
|
function setPhase(phase, message) {
|
|
46371
46536
|
status.phase = phase;
|
|
46372
46537
|
status.message = message ?? null;
|
|
@@ -46488,21 +46653,21 @@ async function runDaemon(opts = {}) {
|
|
|
46488
46653
|
await runDiscovery();
|
|
46489
46654
|
await runScanCycle("startup");
|
|
46490
46655
|
const chokidar = (await Promise.resolve().then(() => (init_esm2(), esm_exports))).default;
|
|
46491
|
-
const { homedir:
|
|
46492
|
-
const { join:
|
|
46493
|
-
const home2 =
|
|
46656
|
+
const { homedir: homedir8, platform: platform5 } = await import("os");
|
|
46657
|
+
const { join: join9 } = await import("path");
|
|
46658
|
+
const home2 = homedir8();
|
|
46494
46659
|
const dirs = [
|
|
46495
|
-
|
|
46496
|
-
|
|
46497
|
-
|
|
46498
|
-
|
|
46660
|
+
join9(home2, ".claude/projects"),
|
|
46661
|
+
join9(home2, ".codex/sessions"),
|
|
46662
|
+
join9(home2, ".cursor/ai-tracking"),
|
|
46663
|
+
join9(home2, ".gemini"),
|
|
46499
46664
|
...platform5() === "darwin" ? [
|
|
46500
|
-
|
|
46501
|
-
|
|
46665
|
+
join9(home2, "Library/Application Support/Cursor/User/workspaceStorage"),
|
|
46666
|
+
join9(home2, "Library/Application Support/Claude")
|
|
46502
46667
|
] : [
|
|
46503
|
-
|
|
46668
|
+
join9(home2, ".config/Cursor/User/workspaceStorage")
|
|
46504
46669
|
]
|
|
46505
|
-
].filter((p) =>
|
|
46670
|
+
].filter((p) => existsSync7(p) && statSync2(p).isDirectory());
|
|
46506
46671
|
setPhase("watching", `Watching ${dirs.length} directories`);
|
|
46507
46672
|
const watcher = chokidar.watch(dirs, {
|
|
46508
46673
|
persistent: true,
|
|
@@ -46549,7 +46714,7 @@ var init_daemon = __esm({
|
|
|
46549
46714
|
init_config2();
|
|
46550
46715
|
init_lock();
|
|
46551
46716
|
init_scan();
|
|
46552
|
-
AGENT_VERSION2 = "agent-dev-0.0.
|
|
46717
|
+
AGENT_VERSION2 = "agent-dev-0.0.23";
|
|
46553
46718
|
HEARTBEAT_INTERVAL_MS = 1e4;
|
|
46554
46719
|
SCAN_INTERVAL_MS = 5 * 60 * 1e3;
|
|
46555
46720
|
status = {
|
|
@@ -46569,37 +46734,37 @@ var watch_exports = {};
|
|
|
46569
46734
|
__export(watch_exports, {
|
|
46570
46735
|
watchForever: () => watchForever
|
|
46571
46736
|
});
|
|
46572
|
-
import { existsSync as
|
|
46573
|
-
import { homedir as
|
|
46574
|
-
import { join as
|
|
46737
|
+
import { existsSync as existsSync8 } from "fs";
|
|
46738
|
+
import { homedir as homedir7, platform as platform3 } from "os";
|
|
46739
|
+
import { join as join8 } from "path";
|
|
46575
46740
|
function resolveWatchDirs() {
|
|
46576
|
-
const home2 =
|
|
46577
|
-
const xdgConfig = process.env.XDG_CONFIG_HOME ??
|
|
46578
|
-
const xdgData = process.env.XDG_DATA_HOME ??
|
|
46741
|
+
const home2 = homedir7();
|
|
46742
|
+
const xdgConfig = process.env.XDG_CONFIG_HOME ?? join8(home2, ".config");
|
|
46743
|
+
const xdgData = process.env.XDG_DATA_HOME ?? join8(home2, ".local/share");
|
|
46579
46744
|
const candidates = [
|
|
46580
46745
|
// universal (default HOME-rooted CLI data dirs)
|
|
46581
|
-
|
|
46582
|
-
|
|
46583
|
-
|
|
46584
|
-
|
|
46585
|
-
|
|
46746
|
+
join8(home2, ".claude/projects"),
|
|
46747
|
+
join8(home2, ".codex/sessions"),
|
|
46748
|
+
join8(home2, ".cursor/ai-tracking"),
|
|
46749
|
+
join8(home2, ".gemini"),
|
|
46750
|
+
join8(home2, ".aider"),
|
|
46586
46751
|
// XDG / Linux
|
|
46587
|
-
|
|
46588
|
-
|
|
46589
|
-
|
|
46590
|
-
|
|
46591
|
-
|
|
46592
|
-
|
|
46752
|
+
join8(xdgConfig, "claude/projects"),
|
|
46753
|
+
join8(xdgConfig, "codex/sessions"),
|
|
46754
|
+
join8(xdgConfig, "Cursor/User/workspaceStorage"),
|
|
46755
|
+
join8(xdgConfig, "Code/User/workspaceStorage"),
|
|
46756
|
+
join8(xdgConfig, "Code - Insiders/User/workspaceStorage"),
|
|
46757
|
+
join8(xdgData, "claude/projects"),
|
|
46593
46758
|
// macOS
|
|
46594
46759
|
...platform3() === "darwin" ? [
|
|
46595
|
-
|
|
46596
|
-
|
|
46597
|
-
|
|
46598
|
-
|
|
46599
|
-
|
|
46760
|
+
join8(home2, "Library/Application Support/Cursor/User/workspaceStorage"),
|
|
46761
|
+
join8(home2, "Library/Application Support/Claude"),
|
|
46762
|
+
join8(home2, "Library/Application Support/Code/User/workspaceStorage"),
|
|
46763
|
+
join8(home2, "Library/Application Support/Windsurf/User/workspaceStorage"),
|
|
46764
|
+
join8(home2, "Library/Application Support/Zed")
|
|
46600
46765
|
] : []
|
|
46601
46766
|
];
|
|
46602
|
-
return Array.from(new Set(candidates)).filter((p) =>
|
|
46767
|
+
return Array.from(new Set(candidates)).filter((p) => existsSync8(p));
|
|
46603
46768
|
}
|
|
46604
46769
|
async function safeScan(reason) {
|
|
46605
46770
|
if (scanning) {
|
|
@@ -46659,51 +46824,53 @@ var init_watch = __esm({
|
|
|
46659
46824
|
|
|
46660
46825
|
// src/cli.ts
|
|
46661
46826
|
init_src2();
|
|
46827
|
+
init_identity();
|
|
46662
46828
|
init_api();
|
|
46663
46829
|
init_config2();
|
|
46664
46830
|
init_scan();
|
|
46665
46831
|
import { spawn } from "child_process";
|
|
46666
46832
|
import { randomBytes } from "crypto";
|
|
46667
46833
|
import { platform as platform4, release, arch as cpuArch, hostname as hostname2 } from "os";
|
|
46834
|
+
import { createInterface as createInterface3 } from "readline";
|
|
46668
46835
|
|
|
46669
46836
|
// src/service.ts
|
|
46670
46837
|
import { spawnSync } from "child_process";
|
|
46671
46838
|
import {
|
|
46672
46839
|
copyFileSync,
|
|
46673
|
-
existsSync as
|
|
46674
|
-
mkdirSync,
|
|
46840
|
+
existsSync as existsSync5,
|
|
46841
|
+
mkdirSync as mkdirSync2,
|
|
46675
46842
|
unlinkSync,
|
|
46676
|
-
writeFileSync as
|
|
46843
|
+
writeFileSync as writeFileSync3
|
|
46677
46844
|
} from "fs";
|
|
46678
|
-
import { homedir as
|
|
46679
|
-
import { dirname as dirname4, join as
|
|
46845
|
+
import { homedir as homedir5, platform as platform2, userInfo } from "os";
|
|
46846
|
+
import { dirname as dirname4, join as join4 } from "path";
|
|
46680
46847
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
46681
46848
|
var SERVICE_LABEL = "ai.modelstat.agent";
|
|
46682
46849
|
var SYSTEMD_UNIT = "modelstat";
|
|
46683
46850
|
function home() {
|
|
46684
|
-
return
|
|
46851
|
+
return homedir5();
|
|
46685
46852
|
}
|
|
46686
46853
|
function stateDir() {
|
|
46687
|
-
return
|
|
46854
|
+
return join4(home(), ".modelstat");
|
|
46688
46855
|
}
|
|
46689
46856
|
function binDir() {
|
|
46690
|
-
return
|
|
46857
|
+
return join4(stateDir(), "bin");
|
|
46691
46858
|
}
|
|
46692
46859
|
function logDir() {
|
|
46693
|
-
return
|
|
46860
|
+
return join4(stateDir(), "logs");
|
|
46694
46861
|
}
|
|
46695
46862
|
function installedCliPath() {
|
|
46696
|
-
return
|
|
46863
|
+
return join4(binDir(), "modelstat.mjs");
|
|
46697
46864
|
}
|
|
46698
46865
|
function runningCliPath() {
|
|
46699
46866
|
return fileURLToPath2(import.meta.url).replace(/service\.(mjs|js|ts)$/, "cli.mjs");
|
|
46700
46867
|
}
|
|
46701
46868
|
function installBundle() {
|
|
46702
|
-
|
|
46703
|
-
|
|
46869
|
+
mkdirSync2(binDir(), { recursive: true });
|
|
46870
|
+
mkdirSync2(logDir(), { recursive: true });
|
|
46704
46871
|
const src = runningCliPath();
|
|
46705
46872
|
const dest = installedCliPath();
|
|
46706
|
-
if (!
|
|
46873
|
+
if (!existsSync5(src)) {
|
|
46707
46874
|
throw new Error(
|
|
46708
46875
|
`Can't find the CLI bundle to install from (${src}). Are you running a local dev build?`
|
|
46709
46876
|
);
|
|
@@ -46715,21 +46882,21 @@ function nodeBinary() {
|
|
|
46715
46882
|
return process.execPath;
|
|
46716
46883
|
}
|
|
46717
46884
|
function plistPath() {
|
|
46718
|
-
return
|
|
46885
|
+
return join4(home(), "Library", "LaunchAgents", `${SERVICE_LABEL}.plist`);
|
|
46719
46886
|
}
|
|
46720
46887
|
function locateTrayExecutable() {
|
|
46721
46888
|
const candidates = [
|
|
46722
|
-
|
|
46889
|
+
join4(home(), "Applications", "ModelstatTray.app", "Contents", "MacOS", "modelstat-tray"),
|
|
46723
46890
|
"/Applications/ModelstatTray.app/Contents/MacOS/modelstat-tray"
|
|
46724
46891
|
];
|
|
46725
46892
|
for (const p of candidates) {
|
|
46726
|
-
if (
|
|
46893
|
+
if (existsSync5(p)) return p;
|
|
46727
46894
|
}
|
|
46728
46895
|
return null;
|
|
46729
46896
|
}
|
|
46730
46897
|
function writePlist(cliPath) {
|
|
46731
46898
|
const p = plistPath();
|
|
46732
|
-
|
|
46899
|
+
mkdirSync2(dirname4(p), { recursive: true });
|
|
46733
46900
|
const tray = locateTrayExecutable();
|
|
46734
46901
|
const programArgs = tray ? ` <string>${tray}</string>` : [
|
|
46735
46902
|
` <string>${nodeBinary()}</string>`,
|
|
@@ -46749,8 +46916,8 @@ ${programArgs}
|
|
|
46749
46916
|
<key>KeepAlive</key>
|
|
46750
46917
|
<dict><key>SuccessfulExit</key><false/></dict>
|
|
46751
46918
|
<key>ThrottleInterval</key><integer>30</integer>
|
|
46752
|
-
<key>StandardOutPath</key><string>${
|
|
46753
|
-
<key>StandardErrorPath</key><string>${
|
|
46919
|
+
<key>StandardOutPath</key><string>${join4(logDir(), "out.log")}</string>
|
|
46920
|
+
<key>StandardErrorPath</key><string>${join4(logDir(), "err.log")}</string>
|
|
46754
46921
|
<key>EnvironmentVariables</key>
|
|
46755
46922
|
<dict>
|
|
46756
46923
|
<key>PATH</key><string>/usr/local/bin:/opt/homebrew/bin:/usr/bin:/bin</string>
|
|
@@ -46759,7 +46926,7 @@ ${programArgs}
|
|
|
46759
46926
|
</dict>
|
|
46760
46927
|
</plist>
|
|
46761
46928
|
`;
|
|
46762
|
-
|
|
46929
|
+
writeFileSync3(p, plist, { mode: 420 });
|
|
46763
46930
|
return p;
|
|
46764
46931
|
}
|
|
46765
46932
|
function launchctl(args) {
|
|
@@ -46790,7 +46957,7 @@ function macUninstall() {
|
|
|
46790
46957
|
const target = `gui/${uid}/${SERVICE_LABEL}`;
|
|
46791
46958
|
launchctl(["bootout", target]);
|
|
46792
46959
|
const plist = plistPath();
|
|
46793
|
-
if (
|
|
46960
|
+
if (existsSync5(plist)) {
|
|
46794
46961
|
try {
|
|
46795
46962
|
unlinkSync(plist);
|
|
46796
46963
|
} catch {
|
|
@@ -46803,12 +46970,12 @@ function macStatus() {
|
|
|
46803
46970
|
return { running: r.ok, hint: r.ok ? "launchd managed" : "not installed" };
|
|
46804
46971
|
}
|
|
46805
46972
|
function systemdUnitPath() {
|
|
46806
|
-
const xdg = process.env.XDG_CONFIG_HOME ??
|
|
46807
|
-
return
|
|
46973
|
+
const xdg = process.env.XDG_CONFIG_HOME ?? join4(home(), ".config");
|
|
46974
|
+
return join4(xdg, "systemd", "user", `${SYSTEMD_UNIT}.service`);
|
|
46808
46975
|
}
|
|
46809
46976
|
function writeSystemdUnit(cliPath) {
|
|
46810
46977
|
const unitPath = systemdUnitPath();
|
|
46811
|
-
|
|
46978
|
+
mkdirSync2(dirname4(unitPath), { recursive: true });
|
|
46812
46979
|
const unit = `[Unit]
|
|
46813
46980
|
Description=modelstat agent
|
|
46814
46981
|
Documentation=https://modelstat.ai
|
|
@@ -46823,13 +46990,13 @@ RestartSec=10
|
|
|
46823
46990
|
# Don't restart-storm if the service is persistently unreachable.
|
|
46824
46991
|
StartLimitIntervalSec=300
|
|
46825
46992
|
StartLimitBurst=10
|
|
46826
|
-
StandardOutput=append:${
|
|
46827
|
-
StandardError=append:${
|
|
46993
|
+
StandardOutput=append:${join4(logDir(), "out.log")}
|
|
46994
|
+
StandardError=append:${join4(logDir(), "err.log")}
|
|
46828
46995
|
|
|
46829
46996
|
[Install]
|
|
46830
46997
|
WantedBy=default.target
|
|
46831
46998
|
`;
|
|
46832
|
-
|
|
46999
|
+
writeFileSync3(unitPath, unit, { mode: 420 });
|
|
46833
47000
|
return unitPath;
|
|
46834
47001
|
}
|
|
46835
47002
|
function systemctl(args) {
|
|
@@ -46849,7 +47016,7 @@ function linuxInstall() {
|
|
|
46849
47016
|
function linuxUninstall() {
|
|
46850
47017
|
systemctl(["disable", "--now", `${SYSTEMD_UNIT}.service`]);
|
|
46851
47018
|
const unit = systemdUnitPath();
|
|
46852
|
-
if (
|
|
47019
|
+
if (existsSync5(unit)) {
|
|
46853
47020
|
try {
|
|
46854
47021
|
unlinkSync(unit);
|
|
46855
47022
|
} catch {
|
|
@@ -46893,9 +47060,9 @@ function logsDir() {
|
|
|
46893
47060
|
}
|
|
46894
47061
|
function installTrayApp(sourceAppPath) {
|
|
46895
47062
|
if (platform2() !== "darwin") return null;
|
|
46896
|
-
if (!
|
|
46897
|
-
const dest =
|
|
46898
|
-
|
|
47063
|
+
if (!existsSync5(sourceAppPath)) return null;
|
|
47064
|
+
const dest = join4(home(), "Applications", "ModelstatTray.app");
|
|
47065
|
+
mkdirSync2(dirname4(dest), { recursive: true });
|
|
46899
47066
|
spawnSync("rm", ["-rf", dest]);
|
|
46900
47067
|
const r = spawnSync("cp", ["-R", sourceAppPath, dest], { encoding: "utf8" });
|
|
46901
47068
|
if (r.status !== 0) {
|
|
@@ -46908,25 +47075,25 @@ function bundledTrayAppPath() {
|
|
|
46908
47075
|
const here2 = dirname4(fileURLToPath2(import.meta.url));
|
|
46909
47076
|
const candidates = [
|
|
46910
47077
|
// Pre-built .app — CI with codesigning drops one here.
|
|
46911
|
-
|
|
47078
|
+
join4(here2, "..", "vendor", "ModelstatTray.app"),
|
|
46912
47079
|
// Local dev layout: apps/agent-dev/src/service.ts → ../../tray-mac/build/ModelstatTray.app
|
|
46913
|
-
|
|
47080
|
+
join4(here2, "..", "..", "tray-mac", "build", "ModelstatTray.app")
|
|
46914
47081
|
];
|
|
46915
47082
|
for (const c of candidates) {
|
|
46916
|
-
if (
|
|
47083
|
+
if (existsSync5(c)) return c;
|
|
46917
47084
|
}
|
|
46918
47085
|
const sourceDirs = [
|
|
46919
|
-
|
|
46920
|
-
|
|
47086
|
+
join4(here2, "..", "vendor", "tray-mac"),
|
|
47087
|
+
join4(here2, "..", "..", "tray-mac")
|
|
46921
47088
|
];
|
|
46922
47089
|
for (const src of sourceDirs) {
|
|
46923
|
-
const build =
|
|
46924
|
-
if (!
|
|
47090
|
+
const build = join4(src, "build-app.sh");
|
|
47091
|
+
if (!existsSync5(build)) continue;
|
|
46925
47092
|
if (!hasSwift()) return null;
|
|
46926
47093
|
const r = spawnSync("bash", [build], { cwd: src, encoding: "utf8" });
|
|
46927
47094
|
if (r.status === 0) {
|
|
46928
|
-
const app =
|
|
46929
|
-
if (
|
|
47095
|
+
const app = join4(src, "build", "ModelstatTray.app");
|
|
47096
|
+
if (existsSync5(app)) return app;
|
|
46930
47097
|
}
|
|
46931
47098
|
}
|
|
46932
47099
|
return null;
|
|
@@ -46942,6 +47109,20 @@ function trayStatus() {
|
|
|
46942
47109
|
}
|
|
46943
47110
|
|
|
46944
47111
|
// src/cli.ts
|
|
47112
|
+
async function confirmPrompt(question, defaultYes) {
|
|
47113
|
+
if (process.stdin.isTTY !== true) return defaultYes;
|
|
47114
|
+
const rl = createInterface3({ input: process.stdin, output: process.stdout });
|
|
47115
|
+
try {
|
|
47116
|
+
const raw = await new Promise((resolve6) => rl.question(question, resolve6));
|
|
47117
|
+
const ans = raw.trim().toLowerCase();
|
|
47118
|
+
if (ans === "") return defaultYes;
|
|
47119
|
+
if (ans === "y" || ans === "yes") return true;
|
|
47120
|
+
if (ans === "n" || ans === "no") return false;
|
|
47121
|
+
return defaultYes;
|
|
47122
|
+
} finally {
|
|
47123
|
+
rl.close();
|
|
47124
|
+
}
|
|
47125
|
+
}
|
|
46945
47126
|
function tryOpenBrowser(url) {
|
|
46946
47127
|
const p = platform4();
|
|
46947
47128
|
const cmd = p === "darwin" ? "open" : p === "win32" ? "cmd" : "xdg-open";
|
|
@@ -47008,11 +47189,13 @@ async function cmdSelfRegister() {
|
|
|
47008
47189
|
device_uuid: deviceUuid,
|
|
47009
47190
|
fingerprint
|
|
47010
47191
|
});
|
|
47011
|
-
state.
|
|
47012
|
-
|
|
47013
|
-
|
|
47014
|
-
|
|
47015
|
-
|
|
47192
|
+
state.saveFreshIdentity({
|
|
47193
|
+
deviceUuid: res.device_uuid,
|
|
47194
|
+
deviceId: res.device_id,
|
|
47195
|
+
bearerToken: res.device_secret,
|
|
47196
|
+
claimCode: res.claim_code,
|
|
47197
|
+
claimUrl: res.claim_url
|
|
47198
|
+
});
|
|
47016
47199
|
process.stdout.write(` \x1B[32m\u2713\x1B[0m registered device_id=${res.device_id}
|
|
47017
47200
|
`);
|
|
47018
47201
|
process.stdout.write(` \x1B[32m\u2713\x1B[0m secret ${res.secret_prefix}\u2026 (hashed on server, never re-sent)
|
|
@@ -47072,19 +47255,21 @@ async function cmdConnect(opts) {
|
|
|
47072
47255
|
};
|
|
47073
47256
|
const wipeAndSelfRegister = async (reason) => {
|
|
47074
47257
|
warn(`${reason} \u2014 re-registering this device`);
|
|
47258
|
+
const bak = backupIdentity();
|
|
47259
|
+
if (bak) warn(`old identity moved to ${bak}`);
|
|
47075
47260
|
state.setBearer(null);
|
|
47076
|
-
state.setDeviceId(null);
|
|
47077
|
-
state.setDeviceUuid(null);
|
|
47078
|
-
state.setClaimCode(null);
|
|
47079
|
-
state.setClaimUrl(null);
|
|
47080
47261
|
await cmdSelfRegister();
|
|
47081
47262
|
};
|
|
47082
|
-
if (
|
|
47263
|
+
if (opts.fresh && hasIdentityFile()) {
|
|
47264
|
+
step("`--fresh` passed \u2014 minting a new device identity");
|
|
47265
|
+
await wipeAndSelfRegister("forced fresh start");
|
|
47266
|
+
} else if (!state.deviceUuid || !state.bearer || !state.deviceId) {
|
|
47083
47267
|
step("Registering this device with modelstat.ai");
|
|
47084
47268
|
await cmdSelfRegister();
|
|
47085
47269
|
} else {
|
|
47086
47270
|
step("Re-using existing device identity");
|
|
47087
47271
|
ok(`device ${state.deviceId}`);
|
|
47272
|
+
ok(`identity file ${identityPath()}`);
|
|
47088
47273
|
try {
|
|
47089
47274
|
const me = await fetchDeviceMe(state.bearer);
|
|
47090
47275
|
if (me.claim_code && me.claim_code !== state.claimCode) {
|
|
@@ -47096,6 +47281,15 @@ async function cmdConnect(opts) {
|
|
|
47096
47281
|
}
|
|
47097
47282
|
} catch (e) {
|
|
47098
47283
|
if (e instanceof DeviceMeUnauthorized) {
|
|
47284
|
+
const interactive = !opts.yes && process.stdin.isTTY === true;
|
|
47285
|
+
if (interactive) {
|
|
47286
|
+
const prompt = "cached credentials no longer accepted by the server. Re-register this device? [Y/n] ";
|
|
47287
|
+
const answer = await confirmPrompt(prompt, true);
|
|
47288
|
+
if (!answer) {
|
|
47289
|
+
warn("keeping existing identity; connect aborted");
|
|
47290
|
+
return;
|
|
47291
|
+
}
|
|
47292
|
+
}
|
|
47099
47293
|
await wipeAndSelfRegister("cached credentials no longer valid");
|
|
47100
47294
|
} else {
|
|
47101
47295
|
warn(`couldn't refresh device state: ${e.message}`);
|
|
@@ -47375,7 +47569,9 @@ function cmdPaths(args) {
|
|
|
47375
47569
|
function parseConnectOpts(argv) {
|
|
47376
47570
|
return {
|
|
47377
47571
|
json: argv.includes("--json"),
|
|
47378
|
-
noBrowser: argv.includes("--no-browser")
|
|
47572
|
+
noBrowser: argv.includes("--no-browser"),
|
|
47573
|
+
fresh: argv.includes("--fresh"),
|
|
47574
|
+
yes: argv.includes("--yes") || argv.includes("-y")
|
|
47379
47575
|
};
|
|
47380
47576
|
}
|
|
47381
47577
|
async function main() {
|