modelstat 0.0.48 → 0.0.50
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 +362 -249
- package/dist/cli.mjs.map +1 -1
- package/package.json +1 -1
- package/vendor/tray-mac/Sources/ModelstatTray/main.swift +5 -5
package/dist/cli.mjs
CHANGED
|
@@ -78,11 +78,11 @@ var init_git = __esm({
|
|
|
78
78
|
});
|
|
79
79
|
|
|
80
80
|
// ../../packages/core/src/enums.ts
|
|
81
|
-
var
|
|
81
|
+
var AGENTS, PROVIDERS, IDENTITY_OWNER_SCOPES, INSTALL_METHODS, OS_FAMILIES, EVENT_KINDS, TOOL_CALL_STATUSES, COMPANION_PHASES, CLASSIFICATION_CONFIDENCE;
|
|
82
82
|
var init_enums = __esm({
|
|
83
83
|
"../../packages/core/src/enums.ts"() {
|
|
84
84
|
"use strict";
|
|
85
|
-
|
|
85
|
+
AGENTS = [
|
|
86
86
|
"claude_code",
|
|
87
87
|
"claude_desktop",
|
|
88
88
|
"codex_cli",
|
|
@@ -105,12 +105,13 @@ var init_enums = __esm({
|
|
|
105
105
|
"crush",
|
|
106
106
|
"kimi",
|
|
107
107
|
"openclaw",
|
|
108
|
+
"hermes",
|
|
108
109
|
"ollama",
|
|
109
110
|
"raw_sdk_anthropic",
|
|
110
111
|
"raw_sdk_openai",
|
|
111
112
|
"raw_sdk_google",
|
|
112
113
|
// Web chat UIs (Chrome-extension companion). Categorically distinct
|
|
113
|
-
// from *_cli / *_desktop
|
|
114
|
+
// from *_cli / *_desktop agents — same provider, different surface.
|
|
114
115
|
"chatgpt_web",
|
|
115
116
|
"claude_web",
|
|
116
117
|
"gemini_web",
|
|
@@ -4339,11 +4340,11 @@ var init_schemas = __esm({
|
|
|
4339
4340
|
ts: external_exports.string().datetime({ offset: true }),
|
|
4340
4341
|
kind: external_exports.enum(EVENT_KINDS),
|
|
4341
4342
|
// Attribution
|
|
4342
|
-
|
|
4343
|
+
agent: external_exports.enum(AGENTS),
|
|
4343
4344
|
provider: external_exports.enum(PROVIDERS),
|
|
4344
4345
|
model: external_exports.string().max(120).nullable(),
|
|
4345
4346
|
session_id: external_exports.string().max(120),
|
|
4346
|
-
//
|
|
4347
|
+
// agent-local session id (UUID in most cases)
|
|
4347
4348
|
turn_index: external_exports.number().int().nonnegative().nullable(),
|
|
4348
4349
|
parent_event_id: external_exports.string().nullable(),
|
|
4349
4350
|
// for subagent turns
|
|
@@ -4372,7 +4373,7 @@ var init_schemas = __esm({
|
|
|
4372
4373
|
// Reference to originating file for reparsing
|
|
4373
4374
|
source_file: external_exports.string().max(1024).nullable(),
|
|
4374
4375
|
source_byte_offset: external_exports.number().int().nonnegative().nullable(),
|
|
4375
|
-
// Billing mode.
|
|
4376
|
+
// Billing mode. Agents with a flat-fee subscription tier (Claude
|
|
4376
4377
|
// Code, Cursor Pro, GitHub Copilot, etc) emit events tagged
|
|
4377
4378
|
// `billing: "subscription"` — the server short-circuits cost to $0
|
|
4378
4379
|
// for those, since token-level pricing doesn't apply once the user
|
|
@@ -4397,7 +4398,7 @@ var init_schemas = __esm({
|
|
|
4397
4398
|
/** sha256-based deterministic id — see @modelstat/core/ids.ts segmentId(). */
|
|
4398
4399
|
segment_id: external_exports.string().max(64),
|
|
4399
4400
|
session_id: external_exports.string().max(120),
|
|
4400
|
-
|
|
4401
|
+
agent: external_exports.enum(AGENTS),
|
|
4401
4402
|
started_at: external_exports.string().datetime({ offset: true }),
|
|
4402
4403
|
ended_at: external_exports.string().datetime({ offset: true }),
|
|
4403
4404
|
/** Pre-redacted abstract, ≤ 512 chars. Never contains PII. */
|
|
@@ -4421,15 +4422,15 @@ var init_schemas = __esm({
|
|
|
4421
4422
|
* deterministic `tc_<djb2-base36>` of `${source_event_id}|${call_index}`
|
|
4422
4423
|
* when the source line carries no id. */
|
|
4423
4424
|
external_call_id: external_exports.string().max(120),
|
|
4424
|
-
/**
|
|
4425
|
+
/** Agent-local session id — same id space as RawEvent.session_id. */
|
|
4425
4426
|
session_id: external_exports.string().max(120),
|
|
4426
4427
|
/** The RawEvent that contained the tool_use (dedupe/replay anchor). */
|
|
4427
4428
|
source_event_id: external_exports.string(),
|
|
4428
4429
|
/** Segment containing source_event_id — filled by the companion at
|
|
4429
4430
|
* batch-build time when known, else null. */
|
|
4430
4431
|
segment_id: external_exports.string().max(64).nullable().default(null),
|
|
4431
|
-
/** The agent that made the call (
|
|
4432
|
-
agent: external_exports.enum(
|
|
4432
|
+
/** The agent that made the call (AGENTS enum). */
|
|
4433
|
+
agent: external_exports.enum(AGENTS),
|
|
4433
4434
|
/** `builtin` or `mcp:<server>`. */
|
|
4434
4435
|
server: external_exports.string().max(120),
|
|
4435
4436
|
/** Bare tool name (`Bash`, `create_pr`) — normalised vendor identifier. */
|
|
@@ -4463,7 +4464,7 @@ var init_schemas = __esm({
|
|
|
4463
4464
|
batch_id: external_exports.string(),
|
|
4464
4465
|
// ULID
|
|
4465
4466
|
device_id: external_exports.string(),
|
|
4466
|
-
|
|
4467
|
+
companion_version: external_exports.string().max(40),
|
|
4467
4468
|
events: external_exports.array(RawEvent).max(1e4),
|
|
4468
4469
|
segments: external_exports.array(Segment).max(2e3).default([]),
|
|
4469
4470
|
/** Per-call tool invocations (additive — old agents omit it, old
|
|
@@ -4496,7 +4497,7 @@ var init_schemas = __esm({
|
|
|
4496
4497
|
queue_size: external_exports.number().int().nonnegative().default(0),
|
|
4497
4498
|
stats: external_exports.record(external_exports.string(), external_exports.unknown()).default({}),
|
|
4498
4499
|
last_event_at: external_exports.string().datetime({ offset: true }).nullable(),
|
|
4499
|
-
|
|
4500
|
+
companion_version: external_exports.string().max(40)
|
|
4500
4501
|
});
|
|
4501
4502
|
DeviceEnrollment = external_exports.object({
|
|
4502
4503
|
machine_id: external_exports.string(),
|
|
@@ -4505,7 +4506,7 @@ var init_schemas = __esm({
|
|
|
4505
4506
|
os_family: external_exports.enum(OS_FAMILIES),
|
|
4506
4507
|
os_version: external_exports.string().max(60),
|
|
4507
4508
|
arch: external_exports.enum(["x86_64", "arm64", "other"]),
|
|
4508
|
-
|
|
4509
|
+
companion_version: external_exports.string().max(40)
|
|
4509
4510
|
});
|
|
4510
4511
|
DeviceSelfRegister = external_exports.object({
|
|
4511
4512
|
/** Agent-generated UUIDv7 — must pass shape + recent-timestamp checks. */
|
|
@@ -4521,8 +4522,8 @@ var init_schemas = __esm({
|
|
|
4521
4522
|
os_family: external_exports.enum(OS_FAMILIES).optional(),
|
|
4522
4523
|
os_version: external_exports.string().max(60).optional(),
|
|
4523
4524
|
arch: external_exports.enum(["x86_64", "arm64", "other"]).optional(),
|
|
4524
|
-
|
|
4525
|
-
|
|
4525
|
+
companion: external_exports.string().max(80).optional(),
|
|
4526
|
+
companion_version: external_exports.string().max(40).optional()
|
|
4526
4527
|
// Allow extra fields for forward-compat without breaking old agents.
|
|
4527
4528
|
}).catchall(external_exports.union([external_exports.string(), external_exports.number(), external_exports.boolean()])).default({})
|
|
4528
4529
|
});
|
|
@@ -4553,7 +4554,7 @@ var init_schemas = __esm({
|
|
|
4553
4554
|
recommended_for: external_exports.string().max(160).optional()
|
|
4554
4555
|
});
|
|
4555
4556
|
DetectedInstallation = external_exports.object({
|
|
4556
|
-
|
|
4557
|
+
agent: external_exports.enum(AGENTS),
|
|
4557
4558
|
install_method: external_exports.enum(INSTALL_METHODS),
|
|
4558
4559
|
binary_path: external_exports.string().nullable(),
|
|
4559
4560
|
data_dir: external_exports.string().nullable(),
|
|
@@ -5143,7 +5144,7 @@ async function parseClaudeCodeJsonl(ctx) {
|
|
|
5143
5144
|
source_event_id: eventId,
|
|
5144
5145
|
ts: a.timestamp,
|
|
5145
5146
|
kind: "assistant_message",
|
|
5146
|
-
|
|
5147
|
+
agent: "claude_code",
|
|
5147
5148
|
provider: "anthropic",
|
|
5148
5149
|
model: a.message?.model ?? null,
|
|
5149
5150
|
session_id: sessionId,
|
|
@@ -5206,7 +5207,7 @@ async function parseClaudeCodeJsonl(ctx) {
|
|
|
5206
5207
|
source_event_id: eventId,
|
|
5207
5208
|
ts: u.timestamp,
|
|
5208
5209
|
kind: "user_message",
|
|
5209
|
-
|
|
5210
|
+
agent: "claude_code",
|
|
5210
5211
|
provider: "anthropic",
|
|
5211
5212
|
model: lastModel,
|
|
5212
5213
|
session_id: sessionId,
|
|
@@ -5531,7 +5532,7 @@ async function parseCodexRollout(ctx) {
|
|
|
5531
5532
|
source_event_id: sourceEventId(ctx.deviceId, ctx.sourceFile, offsetAtLineStart),
|
|
5532
5533
|
ts,
|
|
5533
5534
|
kind: "assistant_message",
|
|
5534
|
-
|
|
5535
|
+
agent: "codex_cli",
|
|
5535
5536
|
provider: "openai",
|
|
5536
5537
|
model,
|
|
5537
5538
|
session_id: sessionId,
|
|
@@ -5571,7 +5572,7 @@ async function parseCodexRollout(ctx) {
|
|
|
5571
5572
|
source_event_id: sourceEventId(ctx.deviceId, ctx.sourceFile, offsetAtLineStart),
|
|
5572
5573
|
ts,
|
|
5573
5574
|
kind: "user_message",
|
|
5574
|
-
|
|
5575
|
+
agent: "codex_cli",
|
|
5575
5576
|
provider: "openai",
|
|
5576
5577
|
model,
|
|
5577
5578
|
session_id: sessionId,
|
|
@@ -7805,11 +7806,11 @@ async function discover(options = {}) {
|
|
|
7805
7806
|
const v = process.env[env2];
|
|
7806
7807
|
if (v) candidates.add(v);
|
|
7807
7808
|
}
|
|
7808
|
-
for (const extra of options.extraDataDirs?.[spec.
|
|
7809
|
+
for (const extra of options.extraDataDirs?.[spec.agent] ?? []) candidates.add(expandPath(extra));
|
|
7809
7810
|
for (const p of candidates) {
|
|
7810
7811
|
if (existsSync3(p) && statSync(p).isDirectory()) {
|
|
7811
7812
|
installations.push({
|
|
7812
|
-
|
|
7813
|
+
agent: spec.agent,
|
|
7813
7814
|
install_method: "manual",
|
|
7814
7815
|
binary_path: null,
|
|
7815
7816
|
data_dir: p,
|
|
@@ -7828,7 +7829,7 @@ async function discover(options = {}) {
|
|
|
7828
7829
|
if (existsSync3(p)) {
|
|
7829
7830
|
const version = await safeVersionProbe(p);
|
|
7830
7831
|
installations.push({
|
|
7831
|
-
|
|
7832
|
+
agent: spec.agent,
|
|
7832
7833
|
install_method: classifyInstallMethod(p, os2),
|
|
7833
7834
|
binary_path: p,
|
|
7834
7835
|
data_dir: null,
|
|
@@ -7848,7 +7849,7 @@ async function discover(options = {}) {
|
|
|
7848
7849
|
const hit = apps.find((a) => a.bundleId === bid);
|
|
7849
7850
|
if (hit) {
|
|
7850
7851
|
installations.push({
|
|
7851
|
-
|
|
7852
|
+
agent: spec.agent,
|
|
7852
7853
|
install_method: "app_bundle",
|
|
7853
7854
|
binary_path: hit.path,
|
|
7854
7855
|
data_dir: null,
|
|
@@ -8076,7 +8077,7 @@ async function probeIdentities(os2) {
|
|
|
8076
8077
|
function dedupeInstalls(list) {
|
|
8077
8078
|
const seen = /* @__PURE__ */ new Map();
|
|
8078
8079
|
for (const i of list) {
|
|
8079
|
-
const k = `${i.
|
|
8080
|
+
const k = `${i.agent}|${i.binary_path ?? ""}|${i.data_dir ?? ""}`;
|
|
8080
8081
|
const prev = seen.get(k);
|
|
8081
8082
|
if (!prev) {
|
|
8082
8083
|
seen.set(k, i);
|
|
@@ -8103,7 +8104,7 @@ var init_discovery = __esm({
|
|
|
8103
8104
|
H = (p) => p.startsWith("~") ? p.replace("~", homedir()) : p;
|
|
8104
8105
|
SOURCES = [
|
|
8105
8106
|
{
|
|
8106
|
-
|
|
8107
|
+
agent: "claude_code",
|
|
8107
8108
|
dataDirs: {
|
|
8108
8109
|
macos: ["~/.claude"],
|
|
8109
8110
|
linux: ["$XDG_CONFIG_HOME/claude", "~/.claude", "~/.config/claude"]
|
|
@@ -8115,7 +8116,7 @@ var init_discovery = __esm({
|
|
|
8115
8116
|
]
|
|
8116
8117
|
},
|
|
8117
8118
|
{
|
|
8118
|
-
|
|
8119
|
+
agent: "codex_cli",
|
|
8119
8120
|
dataDirs: {
|
|
8120
8121
|
macos: ["~/.codex"],
|
|
8121
8122
|
linux: ["$XDG_CONFIG_HOME/codex", "~/.codex"]
|
|
@@ -8125,7 +8126,7 @@ var init_discovery = __esm({
|
|
|
8125
8126
|
fileSignatures: [{ filenameGlob: "sessions/**/rollout-*.jsonl" }]
|
|
8126
8127
|
},
|
|
8127
8128
|
{
|
|
8128
|
-
|
|
8129
|
+
agent: "claude_desktop",
|
|
8129
8130
|
dataDirs: {
|
|
8130
8131
|
macos: ["~/Library/Application Support/Claude"],
|
|
8131
8132
|
linux: ["~/.config/Claude"]
|
|
@@ -8133,7 +8134,7 @@ var init_discovery = __esm({
|
|
|
8133
8134
|
bundleIds: ["com.anthropic.claudeforbrowser", "com.anthropic.claudeelectron"]
|
|
8134
8135
|
},
|
|
8135
8136
|
{
|
|
8136
|
-
|
|
8137
|
+
agent: "cursor",
|
|
8137
8138
|
dataDirs: {
|
|
8138
8139
|
macos: ["~/Library/Application Support/Cursor"],
|
|
8139
8140
|
linux: ["~/.config/Cursor"]
|
|
@@ -8141,7 +8142,7 @@ var init_discovery = __esm({
|
|
|
8141
8142
|
bundleIds: ["co.anysphere.cursor", "com.todesktop.230313mzl4w4u92"]
|
|
8142
8143
|
},
|
|
8143
8144
|
{
|
|
8144
|
-
|
|
8145
|
+
agent: "windsurf",
|
|
8145
8146
|
dataDirs: {
|
|
8146
8147
|
macos: ["~/Library/Application Support/Windsurf"],
|
|
8147
8148
|
linux: ["~/.config/Windsurf"]
|
|
@@ -8149,7 +8150,7 @@ var init_discovery = __esm({
|
|
|
8149
8150
|
bundleIds: ["com.codeium.windsurf"]
|
|
8150
8151
|
},
|
|
8151
8152
|
{
|
|
8152
|
-
|
|
8153
|
+
agent: "zed",
|
|
8153
8154
|
dataDirs: {
|
|
8154
8155
|
macos: ["~/Library/Application Support/Zed", "~/.config/zed"],
|
|
8155
8156
|
linux: ["~/.config/zed"]
|
|
@@ -8158,7 +8159,7 @@ var init_discovery = __esm({
|
|
|
8158
8159
|
bundleIds: ["dev.zed.Zed"]
|
|
8159
8160
|
},
|
|
8160
8161
|
{
|
|
8161
|
-
|
|
8162
|
+
agent: "gemini_cli",
|
|
8162
8163
|
dataDirs: {
|
|
8163
8164
|
macos: ["~/.gemini"],
|
|
8164
8165
|
linux: ["~/.gemini"]
|
|
@@ -8166,18 +8167,18 @@ var init_discovery = __esm({
|
|
|
8166
8167
|
binaries: ["gemini"]
|
|
8167
8168
|
},
|
|
8168
8169
|
{
|
|
8169
|
-
|
|
8170
|
+
agent: "aider",
|
|
8170
8171
|
dataDirs: { macos: ["~/.aider"], linux: ["~/.aider"] },
|
|
8171
8172
|
binaries: ["aider"]
|
|
8172
8173
|
},
|
|
8173
8174
|
{
|
|
8174
|
-
|
|
8175
|
+
agent: "ollama",
|
|
8175
8176
|
dataDirs: { macos: ["~/.ollama"], linux: ["~/.ollama"] },
|
|
8176
8177
|
binaries: ["ollama"],
|
|
8177
8178
|
bundleIds: ["com.electron.ollama"]
|
|
8178
8179
|
},
|
|
8179
8180
|
{
|
|
8180
|
-
|
|
8181
|
+
agent: "openclaw",
|
|
8181
8182
|
dataDirs: { macos: ["~/.openclaw", "~/.claw"], linux: ["~/.openclaw", "~/.claw"] },
|
|
8182
8183
|
binaries: ["openclaw", "claw", "clawdbot", "moltbot"]
|
|
8183
8184
|
}
|
|
@@ -44914,6 +44915,116 @@ var init_api = __esm({
|
|
|
44914
44915
|
}
|
|
44915
44916
|
});
|
|
44916
44917
|
|
|
44918
|
+
// src/machine-key.ts
|
|
44919
|
+
import { spawnSync } from "child_process";
|
|
44920
|
+
import { createHash as createHash3 } from "crypto";
|
|
44921
|
+
import { chmodSync as chmodSync2, existsSync as existsSync6, mkdirSync as mkdirSync2, readFileSync as readFileSync3, writeFileSync as writeFileSync3 } from "fs";
|
|
44922
|
+
import { homedir as homedir4, platform as platform2 } from "os";
|
|
44923
|
+
import { join as join4 } from "path";
|
|
44924
|
+
function macosPlatformUuid() {
|
|
44925
|
+
try {
|
|
44926
|
+
const r = spawnSync("ioreg", ["-rd1", "-c", "IOPlatformExpertDevice"], {
|
|
44927
|
+
encoding: "utf8",
|
|
44928
|
+
timeout: 4e3
|
|
44929
|
+
});
|
|
44930
|
+
if (r.status !== 0 || !r.stdout) return null;
|
|
44931
|
+
const m = /"IOPlatformUUID"\s*=\s*"([^"]+)"/.exec(r.stdout);
|
|
44932
|
+
return m?.[1]?.trim() || null;
|
|
44933
|
+
} catch {
|
|
44934
|
+
return null;
|
|
44935
|
+
}
|
|
44936
|
+
}
|
|
44937
|
+
function linuxMachineId() {
|
|
44938
|
+
for (const p of ["/etc/machine-id", "/var/lib/dbus/machine-id"]) {
|
|
44939
|
+
try {
|
|
44940
|
+
const v = readFileSync3(p, "utf8").trim();
|
|
44941
|
+
if (v) return v;
|
|
44942
|
+
} catch {
|
|
44943
|
+
}
|
|
44944
|
+
}
|
|
44945
|
+
return null;
|
|
44946
|
+
}
|
|
44947
|
+
function windowsMachineGuid() {
|
|
44948
|
+
try {
|
|
44949
|
+
const r = spawnSync(
|
|
44950
|
+
"reg",
|
|
44951
|
+
["query", "HKLM\\SOFTWARE\\Microsoft\\Cryptography", "/v", "MachineGuid"],
|
|
44952
|
+
{ encoding: "utf8", timeout: 4e3 }
|
|
44953
|
+
);
|
|
44954
|
+
if (r.status !== 0 || !r.stdout) return null;
|
|
44955
|
+
const m = /MachineGuid\s+REG_SZ\s+([0-9a-fA-F-]+)/.exec(r.stdout);
|
|
44956
|
+
return m?.[1]?.trim() || null;
|
|
44957
|
+
} catch {
|
|
44958
|
+
return null;
|
|
44959
|
+
}
|
|
44960
|
+
}
|
|
44961
|
+
function fallbackKey() {
|
|
44962
|
+
try {
|
|
44963
|
+
if (existsSync6(FALLBACK_KEY_FILE)) {
|
|
44964
|
+
const v = readFileSync3(FALLBACK_KEY_FILE, "utf8").trim();
|
|
44965
|
+
if (v) return v;
|
|
44966
|
+
}
|
|
44967
|
+
} catch {
|
|
44968
|
+
}
|
|
44969
|
+
const fresh = createHash3("sha256").update(`${MACHINE_KEY_SALT}:fallback:${Date.now()}:${Math.random()}`).digest("hex");
|
|
44970
|
+
try {
|
|
44971
|
+
mkdirSync2(ROOT2, { recursive: true, mode: 448 });
|
|
44972
|
+
writeFileSync3(FALLBACK_KEY_FILE, fresh, { mode: 384 });
|
|
44973
|
+
chmodSync2(FALLBACK_KEY_FILE, 384);
|
|
44974
|
+
} catch {
|
|
44975
|
+
}
|
|
44976
|
+
return fresh;
|
|
44977
|
+
}
|
|
44978
|
+
function resolveRaw() {
|
|
44979
|
+
const p = platform2();
|
|
44980
|
+
if (p === "darwin") {
|
|
44981
|
+
const v = macosPlatformUuid();
|
|
44982
|
+
if (v) return { raw: v, source: "macos-ioplatform" };
|
|
44983
|
+
} else if (p === "win32") {
|
|
44984
|
+
const v = windowsMachineGuid();
|
|
44985
|
+
if (v) return { raw: v, source: "windows-guid" };
|
|
44986
|
+
} else {
|
|
44987
|
+
const v = linuxMachineId();
|
|
44988
|
+
if (v) return { raw: v, source: "linux-machine-id" };
|
|
44989
|
+
}
|
|
44990
|
+
return { raw: fallbackKey(), source: "fallback-file" };
|
|
44991
|
+
}
|
|
44992
|
+
function machineKey() {
|
|
44993
|
+
if (cachedKey) return cachedKey;
|
|
44994
|
+
const { raw, source } = resolveRaw();
|
|
44995
|
+
cachedSource = source;
|
|
44996
|
+
cachedKey = createHash3("sha256").update(`${MACHINE_KEY_SALT}:${raw}`).digest("hex");
|
|
44997
|
+
return cachedKey;
|
|
44998
|
+
}
|
|
44999
|
+
function machineKeySource() {
|
|
45000
|
+
if (!cachedSource) machineKey();
|
|
45001
|
+
return cachedSource;
|
|
45002
|
+
}
|
|
45003
|
+
function deviceUuidFromMachineKey(key = machineKey()) {
|
|
45004
|
+
const nsHex = DEVICE_UUID_NAMESPACE.replace(/-/g, "");
|
|
45005
|
+
const nsBytes = Buffer.from(nsHex, "hex");
|
|
45006
|
+
const hash = createHash3("sha1").update(nsBytes).update(key).digest();
|
|
45007
|
+
const b = Buffer.from(hash.subarray(0, 16));
|
|
45008
|
+
b[6] = b[6] & 15 | 80;
|
|
45009
|
+
b[8] = b[8] & 63 | 128;
|
|
45010
|
+
const h = b.toString("hex");
|
|
45011
|
+
return [h.slice(0, 8), h.slice(8, 12), h.slice(12, 16), h.slice(16, 20), h.slice(20, 32)].join(
|
|
45012
|
+
"-"
|
|
45013
|
+
);
|
|
45014
|
+
}
|
|
45015
|
+
var MACHINE_KEY_SALT, DEVICE_UUID_NAMESPACE, ROOT2, FALLBACK_KEY_FILE, cachedKey, cachedSource;
|
|
45016
|
+
var init_machine_key = __esm({
|
|
45017
|
+
"src/machine-key.ts"() {
|
|
45018
|
+
"use strict";
|
|
45019
|
+
MACHINE_KEY_SALT = "modelstat.device.machine-key.v1";
|
|
45020
|
+
DEVICE_UUID_NAMESPACE = "6f1d2c9a-8b3e-4a7f-9c2d-0e5a1b6c7d8e";
|
|
45021
|
+
ROOT2 = join4(homedir4(), ".modelstat");
|
|
45022
|
+
FALLBACK_KEY_FILE = join4(ROOT2, "machine-key");
|
|
45023
|
+
cachedKey = null;
|
|
45024
|
+
cachedSource = null;
|
|
45025
|
+
}
|
|
45026
|
+
});
|
|
45027
|
+
|
|
44917
45028
|
// ../../packages/companion-core/src/contracts/index.ts
|
|
44918
45029
|
var init_contracts = __esm({
|
|
44919
45030
|
"../../packages/companion-core/src/contracts/index.ts"() {
|
|
@@ -45099,7 +45210,7 @@ async function buildSessionTitles(segments, entitle) {
|
|
|
45099
45210
|
const project = first.tags.find((t) => t.root_key === "projects")?.name;
|
|
45100
45211
|
const facts = [
|
|
45101
45212
|
project ? `repo ${project}` : null,
|
|
45102
|
-
`${sorted.length} part${sorted.length === 1 ? "" : "s"} on ${first.
|
|
45213
|
+
`${sorted.length} part${sorted.length === 1 ? "" : "s"} on ${first.agent}`
|
|
45103
45214
|
].filter(Boolean).join("; ");
|
|
45104
45215
|
try {
|
|
45105
45216
|
title = sanitiseTitle(await entitle({ abstracts: sampleAbstracts(abstracts), facts }));
|
|
@@ -45254,14 +45365,14 @@ async function summariseSlice(sessionId, slice, adapters2) {
|
|
|
45254
45365
|
const promptFacts = [
|
|
45255
45366
|
first.git?.remote_slug ? `repo ${first.git.remote_slug}` : null,
|
|
45256
45367
|
first.git?.branch ? `branch ${first.git.branch}` : null,
|
|
45257
|
-
`${slice.length} turns on ${first.
|
|
45368
|
+
`${slice.length} turns on ${first.agent}`,
|
|
45258
45369
|
first.files_touched?.length ? `files touched: ${first.files_touched.slice(0, 5).join(", ")}` : null,
|
|
45259
45370
|
Object.keys(first.tool_calls ?? {}).length ? `tool calls: ${Object.keys(first.tool_calls).slice(0, 5).join(", ")}` : null
|
|
45260
45371
|
].filter(Boolean).join("; ");
|
|
45261
45372
|
const excerpts = sampleAndRedactExcerpts(slice);
|
|
45262
45373
|
if (excerpts.length === 0) {
|
|
45263
45374
|
throw new Error(
|
|
45264
|
-
`parser produced 0 content excerpts for session ${sessionId} (${slice.length} turns) \u2014 the summariser would only see metadata and produce "${slice.length} turns on ${first.
|
|
45375
|
+
`parser produced 0 content excerpts for session ${sessionId} (${slice.length} turns) \u2014 the summariser would only see metadata and produce "${slice.length} turns on ${first.agent}". Check the parser for ${first.agent} (likely extractExcerpt stripped everything as code or the session is pure tool_use).`
|
|
45265
45376
|
);
|
|
45266
45377
|
}
|
|
45267
45378
|
const excerptBlock = excerpts.map((e, i) => ` [turn ${i + 1}] "${e.replace(/\s+/g, " ").trim()}"`).join("\n");
|
|
@@ -45304,7 +45415,7 @@ Write the SHORTEST keyword-dense paragraph (1-3 sentences, \u2264${ABSTRACT_OUTP
|
|
|
45304
45415
|
}
|
|
45305
45416
|
}
|
|
45306
45417
|
const tags = [
|
|
45307
|
-
{ root_key: "
|
|
45418
|
+
{ root_key: "agents", name: first.agent, confidence: 1 },
|
|
45308
45419
|
{ root_key: "providers", name: first.provider, confidence: 1 }
|
|
45309
45420
|
];
|
|
45310
45421
|
if (first.model) tags.push({ root_key: "models", name: first.model, confidence: 1 });
|
|
@@ -45355,7 +45466,7 @@ Write the SHORTEST keyword-dense paragraph (1-3 sentences, \u2264${ABSTRACT_OUTP
|
|
|
45355
45466
|
return {
|
|
45356
45467
|
segment_id: id,
|
|
45357
45468
|
session_id: sessionId,
|
|
45358
|
-
|
|
45469
|
+
agent: first.agent,
|
|
45359
45470
|
started_at: first.ts,
|
|
45360
45471
|
ended_at: last.ts,
|
|
45361
45472
|
// Slice to the user-visible cap (ABSTRACT_OUTPUT_MAX_CHARS, default
|
|
@@ -45399,7 +45510,7 @@ function sampleAndRedactExcerpts(slice) {
|
|
|
45399
45510
|
return out;
|
|
45400
45511
|
}
|
|
45401
45512
|
function turnSurface(e) {
|
|
45402
|
-
const parts = [e.kind, e.
|
|
45513
|
+
const parts = [e.kind, e.agent];
|
|
45403
45514
|
if (e.model) parts.push(e.model);
|
|
45404
45515
|
const toolCalls = Object.keys(e.tool_calls ?? {});
|
|
45405
45516
|
if (toolCalls.length) parts.push(`tools:${toolCalls.join(",")}`);
|
|
@@ -45484,7 +45595,7 @@ var init_file_queue_store = __esm({
|
|
|
45484
45595
|
try {
|
|
45485
45596
|
const raw = await fs3.readFile(this.filePath, "utf8");
|
|
45486
45597
|
const parsed = JSON.parse(raw);
|
|
45487
|
-
if (parsed.version ===
|
|
45598
|
+
if (parsed.version === 2 && parsed.items) {
|
|
45488
45599
|
const now = Date.now();
|
|
45489
45600
|
for (const [k, v] of Object.entries(parsed.items)) {
|
|
45490
45601
|
if (v.synced && now - v.last_event_ts_ms > SENT_TTL_MS) continue;
|
|
@@ -45496,7 +45607,7 @@ var init_file_queue_store = __esm({
|
|
|
45496
45607
|
try {
|
|
45497
45608
|
const bak = await fs3.readFile(`${this.filePath}.bak`, "utf8");
|
|
45498
45609
|
const parsed = JSON.parse(bak);
|
|
45499
|
-
if (parsed.version ===
|
|
45610
|
+
if (parsed.version === 2 && parsed.items) {
|
|
45500
45611
|
for (const [k, v] of Object.entries(parsed.items)) {
|
|
45501
45612
|
this.items.set(k, v);
|
|
45502
45613
|
}
|
|
@@ -45515,7 +45626,7 @@ var init_file_queue_store = __esm({
|
|
|
45515
45626
|
const run = async () => {
|
|
45516
45627
|
await prior?.catch(() => void 0);
|
|
45517
45628
|
const snap = {
|
|
45518
|
-
version:
|
|
45629
|
+
version: 2,
|
|
45519
45630
|
items: Object.fromEntries(this.items.entries())
|
|
45520
45631
|
};
|
|
45521
45632
|
const tmp = `${this.filePath}.tmp`;
|
|
@@ -45696,14 +45807,14 @@ var init_ollama = __esm({
|
|
|
45696
45807
|
|
|
45697
45808
|
// ../../packages/companion-core/src/node/llama.ts
|
|
45698
45809
|
import { mkdir } from "fs/promises";
|
|
45699
|
-
import { existsSync as
|
|
45700
|
-
import { homedir as
|
|
45701
|
-
import { dirname as dirname5, join as
|
|
45810
|
+
import { existsSync as existsSync7 } from "fs";
|
|
45811
|
+
import { homedir as homedir5 } from "os";
|
|
45812
|
+
import { dirname as dirname5, join as join5 } from "path";
|
|
45702
45813
|
function defaultLlamaConfig() {
|
|
45703
45814
|
const env2 = globalThis.process?.env ?? {};
|
|
45704
|
-
const modelsDir = env2.MODELSTAT_MODELS_DIR ??
|
|
45815
|
+
const modelsDir = env2.MODELSTAT_MODELS_DIR ?? join5(homedir5(), ".modelstat", "models");
|
|
45705
45816
|
const modelUrl = env2.MODELSTAT_LLAMA_MODEL_URL ?? DEFAULT_LLAMA_MODEL_URL;
|
|
45706
|
-
const modelPath = env2.MODELSTAT_LLAMA_MODEL_PATH ??
|
|
45817
|
+
const modelPath = env2.MODELSTAT_LLAMA_MODEL_PATH ?? join5(modelsDir, basenameFromUrl(modelUrl));
|
|
45707
45818
|
return {
|
|
45708
45819
|
modelPath,
|
|
45709
45820
|
modelUrl,
|
|
@@ -45724,7 +45835,7 @@ function basenameFromUrl(url) {
|
|
|
45724
45835
|
return parts[parts.length - 1] || "model.gguf";
|
|
45725
45836
|
}
|
|
45726
45837
|
async function ensureLlamaModel(cfg = defaultLlamaConfig()) {
|
|
45727
|
-
if (
|
|
45838
|
+
if (existsSync7(cfg.modelPath)) return cfg.modelPath;
|
|
45728
45839
|
await mkdir(dirname5(cfg.modelPath), { recursive: true });
|
|
45729
45840
|
const res = await fetch(cfg.modelUrl);
|
|
45730
45841
|
if (!res.ok || !res.body) {
|
|
@@ -46237,8 +46348,8 @@ var init_pipeline2 = __esm({
|
|
|
46237
46348
|
|
|
46238
46349
|
// src/scan.ts
|
|
46239
46350
|
import { readdir, stat as stat2 } from "fs/promises";
|
|
46240
|
-
import { homedir as
|
|
46241
|
-
import { join as
|
|
46351
|
+
import { homedir as homedir6 } from "os";
|
|
46352
|
+
import { join as join6 } from "path";
|
|
46242
46353
|
function withNonNullTokens(e) {
|
|
46243
46354
|
return e.tokens ? e : { ...e, tokens: { ...ZERO_TOKENS } };
|
|
46244
46355
|
}
|
|
@@ -46247,16 +46358,16 @@ async function scanAll(cb = {}) {
|
|
|
46247
46358
|
if (!deviceId) throw new Error("agent not enrolled \u2014 run `register` first");
|
|
46248
46359
|
const jobs = [];
|
|
46249
46360
|
try {
|
|
46250
|
-
const base =
|
|
46361
|
+
const base = join6(homedir6(), ".claude/projects");
|
|
46251
46362
|
const projects = await readdir(base).catch(() => []);
|
|
46252
46363
|
for (const p of projects) {
|
|
46253
|
-
const dir =
|
|
46364
|
+
const dir = join6(base, p);
|
|
46254
46365
|
const ds = await stat2(dir).catch(() => null);
|
|
46255
46366
|
if (!ds?.isDirectory()) continue;
|
|
46256
46367
|
const files = await readdir(dir);
|
|
46257
46368
|
for (const f of files) {
|
|
46258
46369
|
if (!f.endsWith(".jsonl")) continue;
|
|
46259
|
-
const full =
|
|
46370
|
+
const full = join6(dir, f);
|
|
46260
46371
|
jobs.push({
|
|
46261
46372
|
path: full,
|
|
46262
46373
|
parse: async (sink2) => {
|
|
@@ -46270,17 +46381,17 @@ async function scanAll(cb = {}) {
|
|
|
46270
46381
|
console.warn("claude scan skipped:", e.message);
|
|
46271
46382
|
}
|
|
46272
46383
|
try {
|
|
46273
|
-
const base =
|
|
46384
|
+
const base = join6(homedir6(), ".codex/sessions");
|
|
46274
46385
|
const years = await readdir(base).catch(() => []);
|
|
46275
46386
|
for (const y of years) {
|
|
46276
|
-
const months = await readdir(
|
|
46387
|
+
const months = await readdir(join6(base, y)).catch(() => []);
|
|
46277
46388
|
for (const m of months) {
|
|
46278
|
-
const days = await readdir(
|
|
46389
|
+
const days = await readdir(join6(base, y, m)).catch(() => []);
|
|
46279
46390
|
for (const d of days) {
|
|
46280
|
-
const files = await readdir(
|
|
46391
|
+
const files = await readdir(join6(base, y, m, d)).catch(() => []);
|
|
46281
46392
|
for (const f of files) {
|
|
46282
46393
|
if (!f.startsWith("rollout-") || !f.endsWith(".jsonl")) continue;
|
|
46283
|
-
const full =
|
|
46394
|
+
const full = join6(base, y, m, d, f);
|
|
46284
46395
|
jobs.push({
|
|
46285
46396
|
path: full,
|
|
46286
46397
|
parse: async (sink2) => {
|
|
@@ -46332,7 +46443,7 @@ async function scanAll(cb = {}) {
|
|
|
46332
46443
|
const batch = {
|
|
46333
46444
|
batch_id: batchId(),
|
|
46334
46445
|
device_id: deviceId,
|
|
46335
|
-
|
|
46446
|
+
companion_version: AGENT_VERSION,
|
|
46336
46447
|
events,
|
|
46337
46448
|
segments,
|
|
46338
46449
|
tool_calls: attachSegmentIdsByMap(toolCallBuffer, callSegmentByEvent),
|
|
@@ -46397,7 +46508,7 @@ var init_scan = __esm({
|
|
|
46397
46508
|
init_api();
|
|
46398
46509
|
init_config2();
|
|
46399
46510
|
init_pipeline2();
|
|
46400
|
-
AGENT_VERSION = true ? "agent-0.0.
|
|
46511
|
+
AGENT_VERSION = true ? "agent-0.0.50" : "agent-dev";
|
|
46401
46512
|
BATCH_MAX_EVENTS = 2e3;
|
|
46402
46513
|
BATCH_MAX_TOOL_CALLS = 2e4;
|
|
46403
46514
|
BATCH_BUFFER_HARD_CAP = BATCH_MAX_EVENTS * 2;
|
|
@@ -46414,17 +46525,17 @@ var init_scan = __esm({
|
|
|
46414
46525
|
// src/lock.ts
|
|
46415
46526
|
import {
|
|
46416
46527
|
closeSync,
|
|
46417
|
-
existsSync as
|
|
46418
|
-
mkdirSync as
|
|
46528
|
+
existsSync as existsSync9,
|
|
46529
|
+
mkdirSync as mkdirSync4,
|
|
46419
46530
|
openSync,
|
|
46420
|
-
readFileSync as
|
|
46531
|
+
readFileSync as readFileSync5,
|
|
46421
46532
|
renameSync as renameSync2,
|
|
46422
46533
|
unlinkSync as unlinkSync2,
|
|
46423
|
-
writeFileSync as
|
|
46534
|
+
writeFileSync as writeFileSync5,
|
|
46424
46535
|
writeSync
|
|
46425
46536
|
} from "fs";
|
|
46426
|
-
import { homedir as
|
|
46427
|
-
import { join as
|
|
46537
|
+
import { homedir as homedir8 } from "os";
|
|
46538
|
+
import { join as join8 } from "path";
|
|
46428
46539
|
function isProcessAlive(pid) {
|
|
46429
46540
|
if (!pid || pid <= 0) return false;
|
|
46430
46541
|
try {
|
|
@@ -46438,13 +46549,13 @@ function isProcessAlive(pid) {
|
|
|
46438
46549
|
}
|
|
46439
46550
|
function readDaemonLock(lockFile = LOCK_FILE) {
|
|
46440
46551
|
try {
|
|
46441
|
-
const raw =
|
|
46552
|
+
const raw = readFileSync5(lockFile, "utf8");
|
|
46442
46553
|
const obj = JSON.parse(raw);
|
|
46443
46554
|
if (typeof obj.pid !== "number") return null;
|
|
46444
46555
|
return {
|
|
46445
46556
|
pid: obj.pid,
|
|
46446
46557
|
startedAt: obj.startedAt ?? "unknown",
|
|
46447
|
-
|
|
46558
|
+
companionVersion: obj.companionVersion ?? "unknown",
|
|
46448
46559
|
apiUrl: obj.apiUrl ?? "unknown"
|
|
46449
46560
|
};
|
|
46450
46561
|
} catch {
|
|
@@ -46452,7 +46563,7 @@ function readDaemonLock(lockFile = LOCK_FILE) {
|
|
|
46452
46563
|
}
|
|
46453
46564
|
}
|
|
46454
46565
|
function writeLockAtomic(meta) {
|
|
46455
|
-
|
|
46566
|
+
mkdirSync4(LOCK_DIR, { recursive: true });
|
|
46456
46567
|
const tmp = `${LOCK_FILE}.${meta.pid}.${Date.now()}.tmp`;
|
|
46457
46568
|
const fd = openSync(tmp, "wx");
|
|
46458
46569
|
try {
|
|
@@ -46486,7 +46597,7 @@ function acquireDaemonLock(opts) {
|
|
|
46486
46597
|
const meta = {
|
|
46487
46598
|
pid: process.pid,
|
|
46488
46599
|
startedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
46489
|
-
|
|
46600
|
+
companionVersion: opts.companionVersion,
|
|
46490
46601
|
apiUrl: opts.apiUrl
|
|
46491
46602
|
};
|
|
46492
46603
|
writeLockAtomic(meta);
|
|
@@ -46544,8 +46655,8 @@ var LOCK_DIR, LOCK_FILE, LOCK_RECHECK_MS;
|
|
|
46544
46655
|
var init_lock = __esm({
|
|
46545
46656
|
"src/lock.ts"() {
|
|
46546
46657
|
"use strict";
|
|
46547
|
-
LOCK_DIR =
|
|
46548
|
-
LOCK_FILE =
|
|
46658
|
+
LOCK_DIR = join8(homedir8(), ".modelstat");
|
|
46659
|
+
LOCK_FILE = join8(LOCK_DIR, "daemon.lock");
|
|
46549
46660
|
LOCK_RECHECK_MS = 5e3;
|
|
46550
46661
|
}
|
|
46551
46662
|
});
|
|
@@ -48342,7 +48453,7 @@ __export(daemon_exports, {
|
|
|
48342
48453
|
setQueue: () => setQueue,
|
|
48343
48454
|
setStat: () => setStat
|
|
48344
48455
|
});
|
|
48345
|
-
import { existsSync as
|
|
48456
|
+
import { existsSync as existsSync10, statSync as statSync2 } from "fs";
|
|
48346
48457
|
function setPhase(phase, message) {
|
|
48347
48458
|
status.phase = phase;
|
|
48348
48459
|
status.message = message ?? null;
|
|
@@ -48384,7 +48495,8 @@ function snapshotBody() {
|
|
|
48384
48495
|
queue_size: status.queueSize,
|
|
48385
48496
|
stats: status.stats,
|
|
48386
48497
|
last_event_at: status.lastEventAt,
|
|
48387
|
-
|
|
48498
|
+
companion_version: AGENT_VERSION2,
|
|
48499
|
+
machine_id: machineKey()
|
|
48388
48500
|
};
|
|
48389
48501
|
}
|
|
48390
48502
|
function scheduleLocalFlush() {
|
|
@@ -48421,12 +48533,12 @@ async function sendHeartbeat() {
|
|
|
48421
48533
|
writeLocalStatus(body).catch(() => void 0);
|
|
48422
48534
|
}
|
|
48423
48535
|
async function rotateRunawayLogs() {
|
|
48424
|
-
const { homedir:
|
|
48425
|
-
const { join:
|
|
48536
|
+
const { homedir: homedir11 } = await import("os");
|
|
48537
|
+
const { join: join13 } = await import("path");
|
|
48426
48538
|
const { open: open2, stat: stat6, truncate, writeFile } = await import("fs/promises");
|
|
48427
|
-
const dir =
|
|
48539
|
+
const dir = join13(homedir11(), ".modelstat", "logs");
|
|
48428
48540
|
for (const name of ["out.log", "err.log"]) {
|
|
48429
|
-
const p =
|
|
48541
|
+
const p = join13(dir, name);
|
|
48430
48542
|
try {
|
|
48431
48543
|
const st = await stat6(p);
|
|
48432
48544
|
if (st.size <= LOG_MAX_BYTES) continue;
|
|
@@ -48448,16 +48560,16 @@ async function rotateRunawayLogs() {
|
|
|
48448
48560
|
}
|
|
48449
48561
|
}
|
|
48450
48562
|
async function writeLocalStatus(snapshot) {
|
|
48451
|
-
const { homedir:
|
|
48452
|
-
const { join:
|
|
48563
|
+
const { homedir: homedir11 } = await import("os");
|
|
48564
|
+
const { join: join13 } = await import("path");
|
|
48453
48565
|
const { writeFile, mkdir: mkdir2, rename } = await import("fs/promises");
|
|
48454
48566
|
if (!lastStatusPath) {
|
|
48455
|
-
const dir =
|
|
48567
|
+
const dir = join13(homedir11(), ".modelstat");
|
|
48456
48568
|
try {
|
|
48457
48569
|
await mkdir2(dir, { recursive: true });
|
|
48458
48570
|
} catch {
|
|
48459
48571
|
}
|
|
48460
|
-
lastStatusPath =
|
|
48572
|
+
lastStatusPath = join13(dir, "last-status.json");
|
|
48461
48573
|
}
|
|
48462
48574
|
const tmp = `${lastStatusPath}.tmp`;
|
|
48463
48575
|
try {
|
|
@@ -48499,10 +48611,7 @@ async function runScanCycle(reason) {
|
|
|
48499
48611
|
if (p.segment === 0) {
|
|
48500
48612
|
setPhase("processing", `Analyzing${sess}`);
|
|
48501
48613
|
} else {
|
|
48502
|
-
setPhase(
|
|
48503
|
-
"processing",
|
|
48504
|
-
`Summarising segment ${p.segment}/${p.segmentTotal}${sess}`
|
|
48505
|
-
);
|
|
48614
|
+
setPhase("processing", `Summarising segment ${p.segment}/${p.segmentTotal}${sess}`);
|
|
48506
48615
|
}
|
|
48507
48616
|
},
|
|
48508
48617
|
onUpload({ segments }) {
|
|
@@ -48537,7 +48646,7 @@ async function runDaemon(opts = {}) {
|
|
|
48537
48646
|
throw new Error("not enrolled \u2014 run `npx modelstat@latest` first");
|
|
48538
48647
|
}
|
|
48539
48648
|
const lock = acquireDaemonLock({
|
|
48540
|
-
|
|
48649
|
+
companionVersion: AGENT_VERSION2,
|
|
48541
48650
|
apiUrl: state.apiUrl,
|
|
48542
48651
|
force: opts.force === true,
|
|
48543
48652
|
// If a racing daemon out-renamed us for the lock (see lock.ts
|
|
@@ -48555,14 +48664,10 @@ async function runDaemon(opts = {}) {
|
|
|
48555
48664
|
console.log(
|
|
48556
48665
|
`modelstat daemon is already running \u2014 PID ${lock.owner.pid}, started ${formatAge(
|
|
48557
48666
|
lock.ageSec
|
|
48558
|
-
)} ago, agent ${lock.owner.
|
|
48559
|
-
);
|
|
48560
|
-
console.log(
|
|
48561
|
-
" \u2192 to stop it: kill " + lock.owner.pid
|
|
48562
|
-
);
|
|
48563
|
-
console.log(
|
|
48564
|
-
" \u2192 to force-replace it: modelstat start --force"
|
|
48667
|
+
)} ago, agent ${lock.owner.companionVersion}.`
|
|
48565
48668
|
);
|
|
48669
|
+
console.log(" \u2192 to stop it: kill " + lock.owner.pid);
|
|
48670
|
+
console.log(" \u2192 to force-replace it: modelstat start --force");
|
|
48566
48671
|
return;
|
|
48567
48672
|
}
|
|
48568
48673
|
setPhase("starting", "Booting");
|
|
@@ -48590,21 +48695,19 @@ async function runDaemon(opts = {}) {
|
|
|
48590
48695
|
await runDiscovery();
|
|
48591
48696
|
await requestScan("startup");
|
|
48592
48697
|
const chokidar = (await Promise.resolve().then(() => (init_esm2(), esm_exports))).default;
|
|
48593
|
-
const { homedir:
|
|
48594
|
-
const { join:
|
|
48595
|
-
const home2 =
|
|
48698
|
+
const { homedir: homedir11, platform: platform6 } = await import("os");
|
|
48699
|
+
const { join: join13 } = await import("path");
|
|
48700
|
+
const home2 = homedir11();
|
|
48596
48701
|
const dirs = [
|
|
48597
|
-
|
|
48598
|
-
|
|
48599
|
-
|
|
48600
|
-
|
|
48601
|
-
...
|
|
48602
|
-
|
|
48603
|
-
|
|
48604
|
-
] : [
|
|
48605
|
-
|
|
48606
|
-
]
|
|
48607
|
-
].filter((p) => existsSync9(p) && statSync2(p).isDirectory());
|
|
48702
|
+
join13(home2, ".claude/projects"),
|
|
48703
|
+
join13(home2, ".codex/sessions"),
|
|
48704
|
+
join13(home2, ".cursor/ai-tracking"),
|
|
48705
|
+
join13(home2, ".gemini"),
|
|
48706
|
+
...platform6() === "darwin" ? [
|
|
48707
|
+
join13(home2, "Library/Application Support/Cursor/User/workspaceStorage"),
|
|
48708
|
+
join13(home2, "Library/Application Support/Claude")
|
|
48709
|
+
] : [join13(home2, ".config/Cursor/User/workspaceStorage")]
|
|
48710
|
+
].filter((p) => existsSync10(p) && statSync2(p).isDirectory());
|
|
48608
48711
|
setPhase("watching", `Watching ${dirs.length} directories`);
|
|
48609
48712
|
const watcher = chokidar.watch(dirs, {
|
|
48610
48713
|
persistent: true,
|
|
@@ -48629,10 +48732,7 @@ async function runDaemon(opts = {}) {
|
|
|
48629
48732
|
});
|
|
48630
48733
|
const backstop = setInterval(() => void requestScan("interval"), SCAN_INTERVAL_MS);
|
|
48631
48734
|
backstop.unref();
|
|
48632
|
-
const discoveryTimer = setInterval(
|
|
48633
|
-
() => void runDiscovery(),
|
|
48634
|
-
DISCOVERY_INTERVAL_MS
|
|
48635
|
-
);
|
|
48735
|
+
const discoveryTimer = setInterval(() => void runDiscovery(), DISCOVERY_INTERVAL_MS);
|
|
48636
48736
|
discoveryTimer.unref();
|
|
48637
48737
|
const shutdown = async () => {
|
|
48638
48738
|
setPhase("offline", "Shutting down");
|
|
@@ -48649,15 +48749,16 @@ var import_undici2, AGENT_VERSION2, HEARTBEAT_INTERVAL_MS, SCAN_INTERVAL_MS, DIS
|
|
|
48649
48749
|
var init_daemon = __esm({
|
|
48650
48750
|
"src/daemon.ts"() {
|
|
48651
48751
|
"use strict";
|
|
48652
|
-
import_undici2 = __toESM(require_undici(), 1);
|
|
48653
48752
|
init_logger();
|
|
48654
48753
|
init_src2();
|
|
48754
|
+
import_undici2 = __toESM(require_undici(), 1);
|
|
48655
48755
|
init_api();
|
|
48656
48756
|
init_config2();
|
|
48657
48757
|
init_lock();
|
|
48758
|
+
init_machine_key();
|
|
48658
48759
|
init_scan();
|
|
48659
48760
|
init_single_flight();
|
|
48660
|
-
AGENT_VERSION2 = true ? "agent-0.0.
|
|
48761
|
+
AGENT_VERSION2 = true ? "agent-0.0.50" : "agent-dev";
|
|
48661
48762
|
HEARTBEAT_INTERVAL_MS = 1e4;
|
|
48662
48763
|
SCAN_INTERVAL_MS = 5 * 60 * 1e3;
|
|
48663
48764
|
DISCOVERY_INTERVAL_MS = 6e4;
|
|
@@ -48685,37 +48786,37 @@ var watch_exports = {};
|
|
|
48685
48786
|
__export(watch_exports, {
|
|
48686
48787
|
watchForever: () => watchForever
|
|
48687
48788
|
});
|
|
48688
|
-
import { existsSync as
|
|
48689
|
-
import { homedir as
|
|
48690
|
-
import { join as
|
|
48789
|
+
import { existsSync as existsSync11 } from "fs";
|
|
48790
|
+
import { homedir as homedir10, platform as platform4 } from "os";
|
|
48791
|
+
import { join as join12 } from "path";
|
|
48691
48792
|
function resolveWatchDirs() {
|
|
48692
|
-
const home2 =
|
|
48693
|
-
const xdgConfig = process.env.XDG_CONFIG_HOME ??
|
|
48694
|
-
const xdgData = process.env.XDG_DATA_HOME ??
|
|
48793
|
+
const home2 = homedir10();
|
|
48794
|
+
const xdgConfig = process.env.XDG_CONFIG_HOME ?? join12(home2, ".config");
|
|
48795
|
+
const xdgData = process.env.XDG_DATA_HOME ?? join12(home2, ".local/share");
|
|
48695
48796
|
const candidates = [
|
|
48696
48797
|
// universal (default HOME-rooted CLI data dirs)
|
|
48697
|
-
|
|
48698
|
-
|
|
48699
|
-
|
|
48700
|
-
|
|
48701
|
-
|
|
48798
|
+
join12(home2, ".claude/projects"),
|
|
48799
|
+
join12(home2, ".codex/sessions"),
|
|
48800
|
+
join12(home2, ".cursor/ai-tracking"),
|
|
48801
|
+
join12(home2, ".gemini"),
|
|
48802
|
+
join12(home2, ".aider"),
|
|
48702
48803
|
// XDG / Linux
|
|
48703
|
-
|
|
48704
|
-
|
|
48705
|
-
|
|
48706
|
-
|
|
48707
|
-
|
|
48708
|
-
|
|
48804
|
+
join12(xdgConfig, "claude/projects"),
|
|
48805
|
+
join12(xdgConfig, "codex/sessions"),
|
|
48806
|
+
join12(xdgConfig, "Cursor/User/workspaceStorage"),
|
|
48807
|
+
join12(xdgConfig, "Code/User/workspaceStorage"),
|
|
48808
|
+
join12(xdgConfig, "Code - Insiders/User/workspaceStorage"),
|
|
48809
|
+
join12(xdgData, "claude/projects"),
|
|
48709
48810
|
// macOS
|
|
48710
|
-
...
|
|
48711
|
-
|
|
48712
|
-
|
|
48713
|
-
|
|
48714
|
-
|
|
48715
|
-
|
|
48811
|
+
...platform4() === "darwin" ? [
|
|
48812
|
+
join12(home2, "Library/Application Support/Cursor/User/workspaceStorage"),
|
|
48813
|
+
join12(home2, "Library/Application Support/Claude"),
|
|
48814
|
+
join12(home2, "Library/Application Support/Code/User/workspaceStorage"),
|
|
48815
|
+
join12(home2, "Library/Application Support/Windsurf/User/workspaceStorage"),
|
|
48816
|
+
join12(home2, "Library/Application Support/Zed")
|
|
48716
48817
|
] : []
|
|
48717
48818
|
];
|
|
48718
|
-
return Array.from(new Set(candidates)).filter((p) =>
|
|
48819
|
+
return Array.from(new Set(candidates)).filter((p) => existsSync11(p));
|
|
48719
48820
|
}
|
|
48720
48821
|
async function safeScan(reason) {
|
|
48721
48822
|
if (scanning) {
|
|
@@ -48780,53 +48881,53 @@ init_src2();
|
|
|
48780
48881
|
init_api();
|
|
48781
48882
|
init_config2();
|
|
48782
48883
|
init_identity();
|
|
48884
|
+
init_machine_key();
|
|
48783
48885
|
init_scan();
|
|
48784
48886
|
import { spawn } from "child_process";
|
|
48785
|
-
import {
|
|
48786
|
-
import { arch as cpuArch, hostname as hostname2, platform as platform4, release } from "os";
|
|
48887
|
+
import { arch as cpuArch, hostname as hostname2, platform as platform5, release } from "os";
|
|
48787
48888
|
import { createInterface as createInterface3 } from "readline";
|
|
48788
48889
|
|
|
48789
48890
|
// src/service.ts
|
|
48790
|
-
import { spawnSync } from "child_process";
|
|
48891
|
+
import { spawnSync as spawnSync2 } from "child_process";
|
|
48791
48892
|
import {
|
|
48792
48893
|
copyFileSync,
|
|
48793
|
-
existsSync as
|
|
48794
|
-
mkdirSync as
|
|
48795
|
-
readFileSync as
|
|
48894
|
+
existsSync as existsSync8,
|
|
48895
|
+
mkdirSync as mkdirSync3,
|
|
48896
|
+
readFileSync as readFileSync4,
|
|
48796
48897
|
realpathSync,
|
|
48797
48898
|
unlinkSync,
|
|
48798
|
-
writeFileSync as
|
|
48899
|
+
writeFileSync as writeFileSync4
|
|
48799
48900
|
} from "fs";
|
|
48800
48901
|
import { createRequire } from "module";
|
|
48801
|
-
import { homedir as
|
|
48802
|
-
import { dirname as dirname6, join as
|
|
48902
|
+
import { homedir as homedir7, platform as platform3, userInfo } from "os";
|
|
48903
|
+
import { dirname as dirname6, join as join7 } from "path";
|
|
48803
48904
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
48804
48905
|
var SERVICE_LABEL = "ai.modelstat.agent";
|
|
48805
48906
|
var SYSTEMD_UNIT = "modelstat";
|
|
48806
48907
|
function home() {
|
|
48807
|
-
return
|
|
48908
|
+
return homedir7();
|
|
48808
48909
|
}
|
|
48809
48910
|
function stateDir() {
|
|
48810
|
-
return
|
|
48911
|
+
return join7(home(), ".modelstat");
|
|
48811
48912
|
}
|
|
48812
48913
|
function binDir() {
|
|
48813
|
-
return
|
|
48914
|
+
return join7(stateDir(), "bin");
|
|
48814
48915
|
}
|
|
48815
48916
|
function logDir() {
|
|
48816
|
-
return
|
|
48917
|
+
return join7(stateDir(), "logs");
|
|
48817
48918
|
}
|
|
48818
48919
|
function installedCliPath() {
|
|
48819
|
-
return
|
|
48920
|
+
return join7(binDir(), "modelstat.mjs");
|
|
48820
48921
|
}
|
|
48821
48922
|
function runningCliPath() {
|
|
48822
48923
|
return fileURLToPath2(import.meta.url).replace(/service\.(mjs|js|ts)$/, "cli.mjs");
|
|
48823
48924
|
}
|
|
48824
48925
|
function installBundle() {
|
|
48825
|
-
|
|
48826
|
-
|
|
48926
|
+
mkdirSync3(binDir(), { recursive: true });
|
|
48927
|
+
mkdirSync3(logDir(), { recursive: true });
|
|
48827
48928
|
const src = runningCliPath();
|
|
48828
48929
|
const dest = installedCliPath();
|
|
48829
|
-
if (!
|
|
48930
|
+
if (!existsSync8(src)) {
|
|
48830
48931
|
throw new Error(
|
|
48831
48932
|
`Can't find the CLI bundle to install from (${src}). Are you running a local dev build?`
|
|
48832
48933
|
);
|
|
@@ -48844,9 +48945,9 @@ function sourceLlamaVersion(sourceCli) {
|
|
|
48844
48945
|
const req = createRequire(sourceCli);
|
|
48845
48946
|
let d = dirname6(realpathSync(req.resolve("node-llama-cpp")));
|
|
48846
48947
|
for (let i = 0; i < 10; i++) {
|
|
48847
|
-
const pj =
|
|
48848
|
-
if (
|
|
48849
|
-
const p = JSON.parse(
|
|
48948
|
+
const pj = join7(d, "package.json");
|
|
48949
|
+
if (existsSync8(pj)) {
|
|
48950
|
+
const p = JSON.parse(readFileSync4(pj, "utf8"));
|
|
48850
48951
|
if (p.name === "node-llama-cpp" && p.version) return p.version;
|
|
48851
48952
|
}
|
|
48852
48953
|
const up = dirname6(d);
|
|
@@ -48862,19 +48963,19 @@ function installNativeRuntime(sourceCli) {
|
|
|
48862
48963
|
const dest = binDir();
|
|
48863
48964
|
try {
|
|
48864
48965
|
const have = JSON.parse(
|
|
48865
|
-
|
|
48866
|
-
|
|
48966
|
+
readFileSync4(
|
|
48967
|
+
join7(dest, "node_modules", "node-llama-cpp", "package.json"),
|
|
48867
48968
|
"utf8"
|
|
48868
48969
|
)
|
|
48869
48970
|
);
|
|
48870
48971
|
if (have.version === version) return [`node-llama-cpp@${version} (cached)`];
|
|
48871
48972
|
} catch {
|
|
48872
48973
|
}
|
|
48873
|
-
|
|
48974
|
+
mkdirSync3(dest, { recursive: true });
|
|
48874
48975
|
const childEnv = { ...process.env };
|
|
48875
48976
|
delete childEnv.npm_config_global;
|
|
48876
48977
|
delete childEnv.npm_config_prefix;
|
|
48877
|
-
const r =
|
|
48978
|
+
const r = spawnSync2(
|
|
48878
48979
|
"npm",
|
|
48879
48980
|
[
|
|
48880
48981
|
"install",
|
|
@@ -48904,21 +49005,21 @@ function nodeBinary() {
|
|
|
48904
49005
|
return process.execPath;
|
|
48905
49006
|
}
|
|
48906
49007
|
function plistPath() {
|
|
48907
|
-
return
|
|
49008
|
+
return join7(home(), "Library", "LaunchAgents", `${SERVICE_LABEL}.plist`);
|
|
48908
49009
|
}
|
|
48909
49010
|
function locateTrayExecutable() {
|
|
48910
49011
|
const candidates = [
|
|
48911
|
-
|
|
49012
|
+
join7(home(), "Applications", "ModelstatTray.app", "Contents", "MacOS", "modelstat-tray"),
|
|
48912
49013
|
"/Applications/ModelstatTray.app/Contents/MacOS/modelstat-tray"
|
|
48913
49014
|
];
|
|
48914
49015
|
for (const p of candidates) {
|
|
48915
|
-
if (
|
|
49016
|
+
if (existsSync8(p)) return p;
|
|
48916
49017
|
}
|
|
48917
49018
|
return null;
|
|
48918
49019
|
}
|
|
48919
49020
|
function writePlist(cliPath) {
|
|
48920
49021
|
const p = plistPath();
|
|
48921
|
-
|
|
49022
|
+
mkdirSync3(dirname6(p), { recursive: true });
|
|
48922
49023
|
const tray = locateTrayExecutable();
|
|
48923
49024
|
const programArgs = tray ? ` <string>${tray}</string>` : [
|
|
48924
49025
|
` <string>${nodeBinary()}</string>`,
|
|
@@ -48938,8 +49039,8 @@ ${programArgs}
|
|
|
48938
49039
|
<key>KeepAlive</key>
|
|
48939
49040
|
<dict><key>SuccessfulExit</key><false/></dict>
|
|
48940
49041
|
<key>ThrottleInterval</key><integer>30</integer>
|
|
48941
|
-
<key>StandardOutPath</key><string>${
|
|
48942
|
-
<key>StandardErrorPath</key><string>${
|
|
49042
|
+
<key>StandardOutPath</key><string>${join7(logDir(), "out.log")}</string>
|
|
49043
|
+
<key>StandardErrorPath</key><string>${join7(logDir(), "err.log")}</string>
|
|
48943
49044
|
<key>EnvironmentVariables</key>
|
|
48944
49045
|
<dict>
|
|
48945
49046
|
<key>PATH</key><string>/usr/local/bin:/opt/homebrew/bin:/usr/bin:/bin</string>
|
|
@@ -48953,11 +49054,11 @@ ${programArgs}
|
|
|
48953
49054
|
</dict>
|
|
48954
49055
|
</plist>
|
|
48955
49056
|
`;
|
|
48956
|
-
|
|
49057
|
+
writeFileSync4(p, plist, { mode: 420 });
|
|
48957
49058
|
return p;
|
|
48958
49059
|
}
|
|
48959
49060
|
function launchctl(args) {
|
|
48960
|
-
const r =
|
|
49061
|
+
const r = spawnSync2("launchctl", args, { encoding: "utf8" });
|
|
48961
49062
|
return { ok: r.status === 0, out: r.stdout ?? "", err: r.stderr ?? "" };
|
|
48962
49063
|
}
|
|
48963
49064
|
function macInstall() {
|
|
@@ -48984,7 +49085,7 @@ function macUninstall() {
|
|
|
48984
49085
|
const target = `gui/${uid}/${SERVICE_LABEL}`;
|
|
48985
49086
|
launchctl(["bootout", target]);
|
|
48986
49087
|
const plist = plistPath();
|
|
48987
|
-
if (
|
|
49088
|
+
if (existsSync8(plist)) {
|
|
48988
49089
|
try {
|
|
48989
49090
|
unlinkSync(plist);
|
|
48990
49091
|
} catch {
|
|
@@ -48997,12 +49098,12 @@ function macStatus() {
|
|
|
48997
49098
|
return { running: r.ok, hint: r.ok ? "launchd managed" : "not installed" };
|
|
48998
49099
|
}
|
|
48999
49100
|
function systemdUnitPath() {
|
|
49000
|
-
const xdg = process.env.XDG_CONFIG_HOME ??
|
|
49001
|
-
return
|
|
49101
|
+
const xdg = process.env.XDG_CONFIG_HOME ?? join7(home(), ".config");
|
|
49102
|
+
return join7(xdg, "systemd", "user", `${SYSTEMD_UNIT}.service`);
|
|
49002
49103
|
}
|
|
49003
49104
|
function writeSystemdUnit(cliPath) {
|
|
49004
49105
|
const unitPath = systemdUnitPath();
|
|
49005
|
-
|
|
49106
|
+
mkdirSync3(dirname6(unitPath), { recursive: true });
|
|
49006
49107
|
const unit = `[Unit]
|
|
49007
49108
|
Description=modelstat agent
|
|
49008
49109
|
Documentation=https://modelstat.ai
|
|
@@ -49021,17 +49122,17 @@ RestartSec=10
|
|
|
49021
49122
|
# Don't restart-storm if the service is persistently unreachable.
|
|
49022
49123
|
StartLimitIntervalSec=300
|
|
49023
49124
|
StartLimitBurst=10
|
|
49024
|
-
StandardOutput=append:${
|
|
49025
|
-
StandardError=append:${
|
|
49125
|
+
StandardOutput=append:${join7(logDir(), "out.log")}
|
|
49126
|
+
StandardError=append:${join7(logDir(), "err.log")}
|
|
49026
49127
|
|
|
49027
49128
|
[Install]
|
|
49028
49129
|
WantedBy=default.target
|
|
49029
49130
|
`;
|
|
49030
|
-
|
|
49131
|
+
writeFileSync4(unitPath, unit, { mode: 420 });
|
|
49031
49132
|
return unitPath;
|
|
49032
49133
|
}
|
|
49033
49134
|
function systemctl(args) {
|
|
49034
|
-
const r =
|
|
49135
|
+
const r = spawnSync2("systemctl", ["--user", ...args], { encoding: "utf8" });
|
|
49035
49136
|
return { ok: r.status === 0, out: r.stdout ?? "", err: r.stderr ?? "" };
|
|
49036
49137
|
}
|
|
49037
49138
|
function linuxInstall() {
|
|
@@ -49047,7 +49148,7 @@ function linuxInstall() {
|
|
|
49047
49148
|
function linuxUninstall() {
|
|
49048
49149
|
systemctl(["disable", "--now", `${SYSTEMD_UNIT}.service`]);
|
|
49049
49150
|
const unit = systemdUnitPath();
|
|
49050
|
-
if (
|
|
49151
|
+
if (existsSync8(unit)) {
|
|
49051
49152
|
try {
|
|
49052
49153
|
unlinkSync(unit);
|
|
49053
49154
|
} catch {
|
|
@@ -49061,7 +49162,7 @@ function linuxStatus() {
|
|
|
49061
49162
|
return { running: active, hint: active ? "systemd managed" : "not running" };
|
|
49062
49163
|
}
|
|
49063
49164
|
function installService() {
|
|
49064
|
-
const p =
|
|
49165
|
+
const p = platform3();
|
|
49065
49166
|
if (p === "darwin") {
|
|
49066
49167
|
macInstall();
|
|
49067
49168
|
return { path: plistPath(), logs: logDir() };
|
|
@@ -49075,13 +49176,13 @@ function installService() {
|
|
|
49075
49176
|
);
|
|
49076
49177
|
}
|
|
49077
49178
|
function uninstallService() {
|
|
49078
|
-
const p =
|
|
49179
|
+
const p = platform3();
|
|
49079
49180
|
if (p === "darwin") return macUninstall();
|
|
49080
49181
|
if (p === "linux") return linuxUninstall();
|
|
49081
49182
|
throw new Error(`Service uninstall isn't supported on ${p}.`);
|
|
49082
49183
|
}
|
|
49083
49184
|
function serviceStatus() {
|
|
49084
|
-
const p =
|
|
49185
|
+
const p = platform3();
|
|
49085
49186
|
if (p === "darwin") return macStatus();
|
|
49086
49187
|
if (p === "linux") return linuxStatus();
|
|
49087
49188
|
return { running: false, hint: `unsupported platform (${p})` };
|
|
@@ -49090,67 +49191,67 @@ function logsDir() {
|
|
|
49090
49191
|
return logDir();
|
|
49091
49192
|
}
|
|
49092
49193
|
function installTrayApp(sourceAppPath) {
|
|
49093
|
-
if (
|
|
49094
|
-
if (!
|
|
49095
|
-
const dest =
|
|
49096
|
-
|
|
49097
|
-
|
|
49098
|
-
const r =
|
|
49194
|
+
if (platform3() !== "darwin") return null;
|
|
49195
|
+
if (!existsSync8(sourceAppPath)) return null;
|
|
49196
|
+
const dest = join7(home(), "Applications", "ModelstatTray.app");
|
|
49197
|
+
mkdirSync3(dirname6(dest), { recursive: true });
|
|
49198
|
+
spawnSync2("rm", ["-rf", dest]);
|
|
49199
|
+
const r = spawnSync2("cp", ["-R", sourceAppPath, dest], { encoding: "utf8" });
|
|
49099
49200
|
if (r.status !== 0) {
|
|
49100
49201
|
throw new Error(`cp ModelstatTray.app failed: ${r.stderr?.trim() || `exit ${r.status}`}`);
|
|
49101
49202
|
}
|
|
49102
49203
|
return { installedAt: dest };
|
|
49103
49204
|
}
|
|
49104
49205
|
function bundledTrayAppPath() {
|
|
49105
|
-
if (
|
|
49206
|
+
if (platform3() !== "darwin") return null;
|
|
49106
49207
|
const here2 = dirname6(fileURLToPath2(import.meta.url));
|
|
49107
49208
|
const candidates = [
|
|
49108
49209
|
// Pre-built .app — CI with codesigning drops one here.
|
|
49109
|
-
|
|
49210
|
+
join7(here2, "..", "vendor", "ModelstatTray.app"),
|
|
49110
49211
|
// Local dev layout: apps/agent-dev/src/service.ts → ../../tray-mac/build/ModelstatTray.app
|
|
49111
|
-
|
|
49212
|
+
join7(here2, "..", "..", "tray-mac", "build", "ModelstatTray.app")
|
|
49112
49213
|
];
|
|
49113
49214
|
for (const c of candidates) {
|
|
49114
|
-
if (
|
|
49215
|
+
if (existsSync8(c)) return c;
|
|
49115
49216
|
}
|
|
49116
49217
|
const sourceDirs = [
|
|
49117
|
-
|
|
49118
|
-
|
|
49218
|
+
join7(here2, "..", "vendor", "tray-mac"),
|
|
49219
|
+
join7(here2, "..", "..", "tray-mac")
|
|
49119
49220
|
];
|
|
49120
49221
|
for (const src of sourceDirs) {
|
|
49121
|
-
const build =
|
|
49122
|
-
if (!
|
|
49222
|
+
const build = join7(src, "build-app.sh");
|
|
49223
|
+
if (!existsSync8(build)) continue;
|
|
49123
49224
|
if (!hasSwift()) return null;
|
|
49124
|
-
const r =
|
|
49225
|
+
const r = spawnSync2("bash", [build], { cwd: src, encoding: "utf8" });
|
|
49125
49226
|
if (r.status === 0) {
|
|
49126
|
-
const app =
|
|
49127
|
-
if (
|
|
49227
|
+
const app = join7(src, "build", "ModelstatTray.app");
|
|
49228
|
+
if (existsSync8(app)) return app;
|
|
49128
49229
|
}
|
|
49129
49230
|
}
|
|
49130
49231
|
return null;
|
|
49131
49232
|
}
|
|
49132
49233
|
function hasSwift() {
|
|
49133
|
-
const r =
|
|
49234
|
+
const r = spawnSync2("swift", ["--version"], { encoding: "utf8" });
|
|
49134
49235
|
return r.status === 0;
|
|
49135
49236
|
}
|
|
49136
49237
|
function trayStatus() {
|
|
49137
|
-
if (
|
|
49238
|
+
if (platform3() !== "darwin") return { installed: false, path: null };
|
|
49138
49239
|
const exe = locateTrayExecutable();
|
|
49139
49240
|
return exe ? { installed: true, path: exe.replace(/\/Contents\/MacOS\/modelstat-tray$/, "") } : { installed: false, path: null };
|
|
49140
49241
|
}
|
|
49141
49242
|
|
|
49142
49243
|
// src/supervise.ts
|
|
49143
49244
|
init_lock();
|
|
49144
|
-
import { readFileSync as
|
|
49145
|
-
import { homedir as
|
|
49146
|
-
import { join as
|
|
49245
|
+
import { readFileSync as readFileSync6 } from "fs";
|
|
49246
|
+
import { homedir as homedir9 } from "os";
|
|
49247
|
+
import { join as join9 } from "path";
|
|
49147
49248
|
var STATUS_FRESH_MS = 12e4;
|
|
49148
49249
|
var BOOT_GRACE_MS = 9e4;
|
|
49149
49250
|
function decideSupervision(input) {
|
|
49150
49251
|
const fresh = input.statusFreshMs ?? STATUS_FRESH_MS;
|
|
49151
49252
|
const grace = input.bootGraceMs ?? BOOT_GRACE_MS;
|
|
49152
49253
|
if (!input.lock || !input.ownerAlive) return "spawn";
|
|
49153
|
-
if (input.
|
|
49254
|
+
if (input.myCompanionVersion && input.lock.companionVersion !== "unknown" && input.lock.companionVersion !== input.myCompanionVersion) {
|
|
49154
49255
|
return "replace";
|
|
49155
49256
|
}
|
|
49156
49257
|
if (input.statusAgeMs !== null && input.statusAgeMs <= fresh) return "adopt";
|
|
@@ -49160,13 +49261,13 @@ function decideSupervision(input) {
|
|
|
49160
49261
|
function daemonHealth(opts = {}) {
|
|
49161
49262
|
const now = opts.now ?? Date.now();
|
|
49162
49263
|
const pidAlive = opts.pidAlive ?? isProcessAlive;
|
|
49163
|
-
const statusPath = opts.statusPath ??
|
|
49264
|
+
const statusPath = opts.statusPath ?? join9(homedir9(), ".modelstat", "last-status.json");
|
|
49164
49265
|
const lock = opts.lockPath === void 0 ? readDaemonLock() : readDaemonLock(opts.lockPath);
|
|
49165
49266
|
const ownerAlive = lock !== null && pidAlive(lock.pid);
|
|
49166
49267
|
const lockAgeMs = lock ? ageMs(lock.startedAt, now) : null;
|
|
49167
49268
|
let statusAgeMs = null;
|
|
49168
49269
|
try {
|
|
49169
|
-
const raw =
|
|
49270
|
+
const raw = readFileSync6(statusPath, "utf8");
|
|
49170
49271
|
const writtenAt = JSON.parse(raw).written_at;
|
|
49171
49272
|
statusAgeMs = writtenAt ? ageMs(writtenAt, now) : null;
|
|
49172
49273
|
} catch {
|
|
@@ -49178,7 +49279,7 @@ function daemonHealth(opts = {}) {
|
|
|
49178
49279
|
ownerAlive,
|
|
49179
49280
|
lockAgeMs,
|
|
49180
49281
|
statusAgeMs,
|
|
49181
|
-
|
|
49282
|
+
myCompanionVersion: opts.myCompanionVersion
|
|
49182
49283
|
}),
|
|
49183
49284
|
lock,
|
|
49184
49285
|
ownerAlive,
|
|
@@ -49208,7 +49309,7 @@ async function confirmPrompt(question, defaultYes) {
|
|
|
49208
49309
|
}
|
|
49209
49310
|
}
|
|
49210
49311
|
function tryOpenBrowser(url) {
|
|
49211
|
-
const p =
|
|
49312
|
+
const p = platform5();
|
|
49212
49313
|
const cmd = p === "darwin" ? "open" : p === "win32" ? "cmd" : "xdg-open";
|
|
49213
49314
|
const args = p === "win32" ? ["/c", "start", "", url] : [url];
|
|
49214
49315
|
try {
|
|
@@ -49222,9 +49323,9 @@ function tryOpenBrowser(url) {
|
|
|
49222
49323
|
return false;
|
|
49223
49324
|
}
|
|
49224
49325
|
}
|
|
49225
|
-
var AGENT_VERSION3 = true ? "agent-0.0.
|
|
49326
|
+
var AGENT_VERSION3 = true ? "agent-0.0.50" : "agent-dev";
|
|
49226
49327
|
function osFamily() {
|
|
49227
|
-
const p =
|
|
49328
|
+
const p = platform5();
|
|
49228
49329
|
if (p === "darwin") return "macos";
|
|
49229
49330
|
if (p === "linux") return "linux";
|
|
49230
49331
|
return "other";
|
|
@@ -49235,35 +49336,33 @@ function osArch() {
|
|
|
49235
49336
|
if (a === "arm64") return "arm64";
|
|
49236
49337
|
return "other";
|
|
49237
49338
|
}
|
|
49238
|
-
function
|
|
49239
|
-
const
|
|
49240
|
-
const
|
|
49241
|
-
|
|
49242
|
-
rand[0] = rand[0] & 15 | 112;
|
|
49243
|
-
rand[2] = rand[2] & 63 | 128;
|
|
49244
|
-
const hex = tsHex + rand.toString("hex");
|
|
49245
|
-
return [
|
|
49246
|
-
hex.slice(0, 8),
|
|
49247
|
-
hex.slice(8, 12),
|
|
49248
|
-
hex.slice(12, 16),
|
|
49249
|
-
hex.slice(16, 20),
|
|
49250
|
-
hex.slice(20, 32)
|
|
49251
|
-
].join("-");
|
|
49339
|
+
function intendedDeviceUuid() {
|
|
49340
|
+
const salt = process.env.MODELSTAT_DEVICE_SALT?.trim();
|
|
49341
|
+
const key = salt ? `${machineKey()}:${salt}` : machineKey();
|
|
49342
|
+
return deviceUuidFromMachineKey(key);
|
|
49252
49343
|
}
|
|
49253
49344
|
async function cmdSelfRegister() {
|
|
49254
|
-
const deviceUuid = state.deviceUuid ??
|
|
49255
|
-
const
|
|
49345
|
+
const deviceUuid = state.deviceUuid ?? intendedDeviceUuid();
|
|
49346
|
+
const derived = !state.deviceUuid;
|
|
49347
|
+
const mid = machineKey();
|
|
49256
49348
|
const fingerprint = {
|
|
49257
49349
|
hostname: hostname2(),
|
|
49258
49350
|
os_family: osFamily(),
|
|
49259
49351
|
os_version: release(),
|
|
49260
49352
|
arch: osArch(),
|
|
49261
|
-
|
|
49262
|
-
|
|
49353
|
+
companion: "modelstat-agent-dev",
|
|
49354
|
+
companion_version: AGENT_VERSION3,
|
|
49355
|
+
// Stable, install-method-independent machine key. The server
|
|
49356
|
+
// dedupes self-register on this so the same physical machine can
|
|
49357
|
+
// never become two device rows, even if the UUID somehow differs
|
|
49358
|
+
// (legacy random UUID → deterministic UUID transition).
|
|
49359
|
+
machine_id: mid
|
|
49263
49360
|
};
|
|
49264
|
-
if (
|
|
49265
|
-
process.stdout.write(
|
|
49266
|
-
`)
|
|
49361
|
+
if (derived) {
|
|
49362
|
+
process.stdout.write(
|
|
49363
|
+
` \x1B[2mdevice id derived from machine key (${machineKeySource()}): ${deviceUuid.slice(0, 8)}\u2026\x1B[0m
|
|
49364
|
+
`
|
|
49365
|
+
);
|
|
49267
49366
|
}
|
|
49268
49367
|
process.stdout.write(` \x1B[2m\u2192 POST ${state.apiUrl}/v1/devices/self-register\x1B[0m
|
|
49269
49368
|
`);
|
|
@@ -49343,7 +49442,7 @@ async function cmdConnect(opts) {
|
|
|
49343
49442
|
await cmdSelfRegister();
|
|
49344
49443
|
};
|
|
49345
49444
|
if (opts.fresh && hasIdentityFile()) {
|
|
49346
|
-
step("`--fresh` passed \u2014
|
|
49445
|
+
step("`--fresh` passed \u2014 re-registering this device");
|
|
49347
49446
|
await wipeAndSelfRegister("forced fresh start");
|
|
49348
49447
|
} else if (!state.deviceUuid || !state.bearer || !state.deviceId) {
|
|
49349
49448
|
step("Registering this device with modelstat.ai");
|
|
@@ -49388,7 +49487,7 @@ async function cmdConnect(opts) {
|
|
|
49388
49487
|
claim_url: claimUrl,
|
|
49389
49488
|
agent_url: agentUrl
|
|
49390
49489
|
});
|
|
49391
|
-
if (
|
|
49490
|
+
if (platform5() === "darwin") {
|
|
49392
49491
|
step("Installing menu-bar tray (macOS)");
|
|
49393
49492
|
try {
|
|
49394
49493
|
const src = bundledTrayAppPath();
|
|
@@ -49432,7 +49531,7 @@ async function cmdConnect(opts) {
|
|
|
49432
49531
|
logs: svc.logs,
|
|
49433
49532
|
summariser_ready: modelReady
|
|
49434
49533
|
});
|
|
49435
|
-
ok(`${
|
|
49534
|
+
ok(`${platform5() === "darwin" ? "launchd" : "systemd --user"}: ${svc.path}`);
|
|
49436
49535
|
} catch (e) {
|
|
49437
49536
|
emitEvent(opts, "service_install_failed", { error: e.message });
|
|
49438
49537
|
warn(`couldn't install service: ${e.message}`);
|
|
@@ -49475,7 +49574,7 @@ async function cmdConnect(opts) {
|
|
|
49475
49574
|
` detected: \x1B[32m${discovered.installations} installs \xB7 ${discovered.identities} accounts\x1B[0m`
|
|
49476
49575
|
);
|
|
49477
49576
|
}
|
|
49478
|
-
if (
|
|
49577
|
+
if (platform5() === "darwin") {
|
|
49479
49578
|
console.log(
|
|
49480
49579
|
` tray : \x1B[${tray.installed ? "32" : "2"}m${tray.installed ? "menu-bar icon ready" : "not installed"}\x1B[0m`
|
|
49481
49580
|
);
|
|
@@ -49606,10 +49705,10 @@ function fmtTokens(v) {
|
|
|
49606
49705
|
}
|
|
49607
49706
|
async function readLocalStatus() {
|
|
49608
49707
|
try {
|
|
49609
|
-
const { homedir:
|
|
49610
|
-
const { join:
|
|
49708
|
+
const { homedir: homedir11 } = await import("os");
|
|
49709
|
+
const { join: join13 } = await import("path");
|
|
49611
49710
|
const { readFile } = await import("fs/promises");
|
|
49612
|
-
const p =
|
|
49711
|
+
const p = join13(homedir11(), ".modelstat", "last-status.json");
|
|
49613
49712
|
const txt = await readFile(p, "utf8");
|
|
49614
49713
|
return JSON.parse(txt);
|
|
49615
49714
|
} catch {
|
|
@@ -49668,9 +49767,9 @@ async function cmdStats(args) {
|
|
|
49668
49767
|
}
|
|
49669
49768
|
console.log(`device: ${view.device.id}`);
|
|
49670
49769
|
console.log(`host: ${view.device.hostname ?? "(unknown)"} (${view.device.os_family ?? "?"})`);
|
|
49671
|
-
console.log(`
|
|
49770
|
+
console.log(`companion: ${view.device.companion_version ?? "(unknown)"}`);
|
|
49672
49771
|
console.log(
|
|
49673
|
-
`status: ${view.device.
|
|
49772
|
+
`status: ${view.device.companion_status ?? "(unknown)"}${view.device.last_seen_at ? ` \xB7 last seen ${view.device.last_seen_at}` : ""}`
|
|
49674
49773
|
);
|
|
49675
49774
|
console.log(
|
|
49676
49775
|
`claim: ${view.status}${view.status === "unclaimed" ? ` (at ${view.claim_url})` : ""}`
|
|
@@ -49729,11 +49828,17 @@ async function cmdJobs(args) {
|
|
|
49729
49828
|
}
|
|
49730
49829
|
}
|
|
49731
49830
|
function cmdPaths(args) {
|
|
49831
|
+
const intended = intendedDeviceUuid();
|
|
49732
49832
|
const data = {
|
|
49733
49833
|
state: state.storePath,
|
|
49834
|
+
identity: identityPath(),
|
|
49734
49835
|
logs: logsDir(),
|
|
49735
49836
|
api: state.apiUrl,
|
|
49736
|
-
paired: !!state.bearer && !!state.deviceId
|
|
49837
|
+
paired: !!state.bearer && !!state.deviceId,
|
|
49838
|
+
device_id: state.deviceId ?? "(none)",
|
|
49839
|
+
device_uuid: state.deviceUuid ?? "(none)",
|
|
49840
|
+
intended_uuid: intended,
|
|
49841
|
+
machine_key_source: machineKeySource()
|
|
49737
49842
|
};
|
|
49738
49843
|
if (args.includes("--json")) {
|
|
49739
49844
|
process.stdout.write(`${JSON.stringify(data)}
|
|
@@ -49792,7 +49897,7 @@ async function main() {
|
|
|
49792
49897
|
}
|
|
49793
49898
|
case "_daemon-health": {
|
|
49794
49899
|
try {
|
|
49795
|
-
console.log(JSON.stringify(daemonHealth({
|
|
49900
|
+
console.log(JSON.stringify(daemonHealth({ myCompanionVersion: AGENT_VERSION3 })));
|
|
49796
49901
|
} catch (e) {
|
|
49797
49902
|
console.log(JSON.stringify({ decision: "spawn", error: e.message }));
|
|
49798
49903
|
}
|
|
@@ -49840,10 +49945,18 @@ async function main() {
|
|
|
49840
49945
|
console.log();
|
|
49841
49946
|
console.log("Diagnostics:");
|
|
49842
49947
|
console.log(" npx modelstat@latest status \u2014 show pairing + service state");
|
|
49843
|
-
console.log(
|
|
49844
|
-
|
|
49845
|
-
|
|
49846
|
-
console.log(
|
|
49948
|
+
console.log(
|
|
49949
|
+
" npx modelstat@latest stats \u2014 live device summary: sessions \xB7 tokens \xB7 cost (--json)"
|
|
49950
|
+
);
|
|
49951
|
+
console.log(
|
|
49952
|
+
" npx modelstat@latest jobs \u2014 pipeline queue + recent processing ledger (--json)"
|
|
49953
|
+
);
|
|
49954
|
+
console.log(
|
|
49955
|
+
" npx modelstat@latest paths \u2014 print state file + log dir + api URL (--json)"
|
|
49956
|
+
);
|
|
49957
|
+
console.log(
|
|
49958
|
+
" npx modelstat@latest token \u2014 print the device token for hosted MCP / API access (--json)"
|
|
49959
|
+
);
|
|
49847
49960
|
console.log();
|
|
49848
49961
|
console.log("Dev / one-shots:");
|
|
49849
49962
|
console.log(" npx modelstat@latest scan \u2014 one-shot parse + upload of local JSONL");
|