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 CHANGED
@@ -78,11 +78,11 @@ var init_git = __esm({
78
78
  });
79
79
 
80
80
  // ../../packages/core/src/enums.ts
81
- var TOOLS, PROVIDERS, IDENTITY_OWNER_SCOPES, INSTALL_METHODS, OS_FAMILIES, EVENT_KINDS, TOOL_CALL_STATUSES, COMPANION_PHASES, CLASSIFICATION_CONFIDENCE;
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
- TOOLS = [
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 tools — same provider, different surface.
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
- tool: external_exports.enum(TOOLS),
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
- // tool-local session id (UUID in most cases)
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. Tools with a flat-fee subscription tier (Claude
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
- tool: external_exports.enum(TOOLS),
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
- /** Tool-local session id — same id space as RawEvent.session_id. */
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 (TOOLS enum — "tool" in legacy naming). */
4432
- agent: external_exports.enum(TOOLS),
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
- agent_version: external_exports.string().max(40),
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
- agent_version: external_exports.string().max(40)
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
- agent_version: external_exports.string().max(40)
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
- agent: external_exports.string().max(80).optional(),
4525
- agent_version: external_exports.string().max(40).optional()
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
- tool: external_exports.enum(TOOLS),
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
- tool: "claude_code",
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
- tool: "claude_code",
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
- tool: "codex_cli",
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
- tool: "codex_cli",
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.tool] ?? []) candidates.add(expandPath(extra));
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
- tool: spec.tool,
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
- tool: spec.tool,
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
- tool: spec.tool,
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.tool}|${i.binary_path ?? ""}|${i.data_dir ?? ""}`;
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
- tool: "claude_code",
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
- tool: "codex_cli",
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
- tool: "claude_desktop",
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
- tool: "cursor",
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
- tool: "windsurf",
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
- tool: "zed",
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
- tool: "gemini_cli",
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
- tool: "aider",
8170
+ agent: "aider",
8170
8171
  dataDirs: { macos: ["~/.aider"], linux: ["~/.aider"] },
8171
8172
  binaries: ["aider"]
8172
8173
  },
8173
8174
  {
8174
- tool: "ollama",
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
- tool: "openclaw",
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.tool}`
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.tool}`,
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.tool}". Check the parser for ${first.tool} (likely extractExcerpt stripped everything as code or the session is pure tool_use).`
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: "tools", name: first.tool, confidence: 1 },
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
- tool: first.tool,
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.tool];
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 === 1 && parsed.items) {
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 === 1 && parsed.items) {
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: 1,
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 existsSync6 } from "fs";
45700
- import { homedir as homedir4 } from "os";
45701
- import { dirname as dirname5, join as join4 } from "path";
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 ?? join4(homedir4(), ".modelstat", "models");
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 ?? join4(modelsDir, basenameFromUrl(modelUrl));
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 (existsSync6(cfg.modelPath)) return cfg.modelPath;
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 homedir5 } from "os";
46241
- import { join as join5 } from "path";
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 = join5(homedir5(), ".claude/projects");
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 = join5(base, p);
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 = join5(dir, f);
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 = join5(homedir5(), ".codex/sessions");
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(join5(base, y)).catch(() => []);
46387
+ const months = await readdir(join6(base, y)).catch(() => []);
46277
46388
  for (const m of months) {
46278
- const days = await readdir(join5(base, y, m)).catch(() => []);
46389
+ const days = await readdir(join6(base, y, m)).catch(() => []);
46279
46390
  for (const d of days) {
46280
- const files = await readdir(join5(base, y, m, d)).catch(() => []);
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 = join5(base, y, m, d, f);
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
- agent_version: AGENT_VERSION,
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.48" : "agent-dev";
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 existsSync8,
46418
- mkdirSync as mkdirSync3,
46528
+ existsSync as existsSync9,
46529
+ mkdirSync as mkdirSync4,
46419
46530
  openSync,
46420
- readFileSync as readFileSync4,
46531
+ readFileSync as readFileSync5,
46421
46532
  renameSync as renameSync2,
46422
46533
  unlinkSync as unlinkSync2,
46423
- writeFileSync as writeFileSync4,
46534
+ writeFileSync as writeFileSync5,
46424
46535
  writeSync
46425
46536
  } from "fs";
46426
- import { homedir as homedir7 } from "os";
46427
- import { join as join7 } from "path";
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 = readFileSync4(lockFile, "utf8");
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
- agentVersion: obj.agentVersion ?? "unknown",
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
- mkdirSync3(LOCK_DIR, { recursive: true });
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
- agentVersion: opts.agentVersion,
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 = join7(homedir7(), ".modelstat");
46548
- LOCK_FILE = join7(LOCK_DIR, "daemon.lock");
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 existsSync9, statSync as statSync2 } from "fs";
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
- agent_version: AGENT_VERSION2
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: homedir10 } = await import("os");
48425
- const { join: join12 } = await import("path");
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 = join12(homedir10(), ".modelstat", "logs");
48539
+ const dir = join13(homedir11(), ".modelstat", "logs");
48428
48540
  for (const name of ["out.log", "err.log"]) {
48429
- const p = join12(dir, name);
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: homedir10 } = await import("os");
48452
- const { join: join12 } = await import("path");
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 = join12(homedir10(), ".modelstat");
48567
+ const dir = join13(homedir11(), ".modelstat");
48456
48568
  try {
48457
48569
  await mkdir2(dir, { recursive: true });
48458
48570
  } catch {
48459
48571
  }
48460
- lastStatusPath = join12(dir, "last-status.json");
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
- agentVersion: AGENT_VERSION2,
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.agentVersion}.`
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: homedir10, platform: platform5 } = await import("os");
48594
- const { join: join12 } = await import("path");
48595
- const home2 = homedir10();
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
- join12(home2, ".claude/projects"),
48598
- join12(home2, ".codex/sessions"),
48599
- join12(home2, ".cursor/ai-tracking"),
48600
- join12(home2, ".gemini"),
48601
- ...platform5() === "darwin" ? [
48602
- join12(home2, "Library/Application Support/Cursor/User/workspaceStorage"),
48603
- join12(home2, "Library/Application Support/Claude")
48604
- ] : [
48605
- join12(home2, ".config/Cursor/User/workspaceStorage")
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.48" : "agent-dev";
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 existsSync10 } from "fs";
48689
- import { homedir as homedir9, platform as platform3 } from "os";
48690
- import { join as join11 } from "path";
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 = homedir9();
48693
- const xdgConfig = process.env.XDG_CONFIG_HOME ?? join11(home2, ".config");
48694
- const xdgData = process.env.XDG_DATA_HOME ?? join11(home2, ".local/share");
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
- join11(home2, ".claude/projects"),
48698
- join11(home2, ".codex/sessions"),
48699
- join11(home2, ".cursor/ai-tracking"),
48700
- join11(home2, ".gemini"),
48701
- join11(home2, ".aider"),
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
- join11(xdgConfig, "claude/projects"),
48704
- join11(xdgConfig, "codex/sessions"),
48705
- join11(xdgConfig, "Cursor/User/workspaceStorage"),
48706
- join11(xdgConfig, "Code/User/workspaceStorage"),
48707
- join11(xdgConfig, "Code - Insiders/User/workspaceStorage"),
48708
- join11(xdgData, "claude/projects"),
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
- ...platform3() === "darwin" ? [
48711
- join11(home2, "Library/Application Support/Cursor/User/workspaceStorage"),
48712
- join11(home2, "Library/Application Support/Claude"),
48713
- join11(home2, "Library/Application Support/Code/User/workspaceStorage"),
48714
- join11(home2, "Library/Application Support/Windsurf/User/workspaceStorage"),
48715
- join11(home2, "Library/Application Support/Zed")
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) => existsSync10(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 { randomBytes } from "crypto";
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 existsSync7,
48794
- mkdirSync as mkdirSync2,
48795
- readFileSync as readFileSync3,
48894
+ existsSync as existsSync8,
48895
+ mkdirSync as mkdirSync3,
48896
+ readFileSync as readFileSync4,
48796
48897
  realpathSync,
48797
48898
  unlinkSync,
48798
- writeFileSync as writeFileSync3
48899
+ writeFileSync as writeFileSync4
48799
48900
  } from "fs";
48800
48901
  import { createRequire } from "module";
48801
- import { homedir as homedir6, platform as platform2, userInfo } from "os";
48802
- import { dirname as dirname6, join as join6 } from "path";
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 homedir6();
48908
+ return homedir7();
48808
48909
  }
48809
48910
  function stateDir() {
48810
- return join6(home(), ".modelstat");
48911
+ return join7(home(), ".modelstat");
48811
48912
  }
48812
48913
  function binDir() {
48813
- return join6(stateDir(), "bin");
48914
+ return join7(stateDir(), "bin");
48814
48915
  }
48815
48916
  function logDir() {
48816
- return join6(stateDir(), "logs");
48917
+ return join7(stateDir(), "logs");
48817
48918
  }
48818
48919
  function installedCliPath() {
48819
- return join6(binDir(), "modelstat.mjs");
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
- mkdirSync2(binDir(), { recursive: true });
48826
- mkdirSync2(logDir(), { recursive: true });
48926
+ mkdirSync3(binDir(), { recursive: true });
48927
+ mkdirSync3(logDir(), { recursive: true });
48827
48928
  const src = runningCliPath();
48828
48929
  const dest = installedCliPath();
48829
- if (!existsSync7(src)) {
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 = join6(d, "package.json");
48848
- if (existsSync7(pj)) {
48849
- const p = JSON.parse(readFileSync3(pj, "utf8"));
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
- readFileSync3(
48866
- join6(dest, "node_modules", "node-llama-cpp", "package.json"),
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
- mkdirSync2(dest, { recursive: true });
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 = spawnSync(
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 join6(home(), "Library", "LaunchAgents", `${SERVICE_LABEL}.plist`);
49008
+ return join7(home(), "Library", "LaunchAgents", `${SERVICE_LABEL}.plist`);
48908
49009
  }
48909
49010
  function locateTrayExecutable() {
48910
49011
  const candidates = [
48911
- join6(home(), "Applications", "ModelstatTray.app", "Contents", "MacOS", "modelstat-tray"),
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 (existsSync7(p)) return p;
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
- mkdirSync2(dirname6(p), { recursive: true });
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>${join6(logDir(), "out.log")}</string>
48942
- <key>StandardErrorPath</key><string>${join6(logDir(), "err.log")}</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
- writeFileSync3(p, plist, { mode: 420 });
49057
+ writeFileSync4(p, plist, { mode: 420 });
48957
49058
  return p;
48958
49059
  }
48959
49060
  function launchctl(args) {
48960
- const r = spawnSync("launchctl", args, { encoding: "utf8" });
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 (existsSync7(plist)) {
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 ?? join6(home(), ".config");
49001
- return join6(xdg, "systemd", "user", `${SYSTEMD_UNIT}.service`);
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
- mkdirSync2(dirname6(unitPath), { recursive: true });
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:${join6(logDir(), "out.log")}
49025
- StandardError=append:${join6(logDir(), "err.log")}
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
- writeFileSync3(unitPath, unit, { mode: 420 });
49131
+ writeFileSync4(unitPath, unit, { mode: 420 });
49031
49132
  return unitPath;
49032
49133
  }
49033
49134
  function systemctl(args) {
49034
- const r = spawnSync("systemctl", ["--user", ...args], { encoding: "utf8" });
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 (existsSync7(unit)) {
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 = platform2();
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 = platform2();
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 = platform2();
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 (platform2() !== "darwin") return null;
49094
- if (!existsSync7(sourceAppPath)) return null;
49095
- const dest = join6(home(), "Applications", "ModelstatTray.app");
49096
- mkdirSync2(dirname6(dest), { recursive: true });
49097
- spawnSync("rm", ["-rf", dest]);
49098
- const r = spawnSync("cp", ["-R", sourceAppPath, dest], { encoding: "utf8" });
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 (platform2() !== "darwin") return null;
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
- join6(here2, "..", "vendor", "ModelstatTray.app"),
49210
+ join7(here2, "..", "vendor", "ModelstatTray.app"),
49110
49211
  // Local dev layout: apps/agent-dev/src/service.ts → ../../tray-mac/build/ModelstatTray.app
49111
- join6(here2, "..", "..", "tray-mac", "build", "ModelstatTray.app")
49212
+ join7(here2, "..", "..", "tray-mac", "build", "ModelstatTray.app")
49112
49213
  ];
49113
49214
  for (const c of candidates) {
49114
- if (existsSync7(c)) return c;
49215
+ if (existsSync8(c)) return c;
49115
49216
  }
49116
49217
  const sourceDirs = [
49117
- join6(here2, "..", "vendor", "tray-mac"),
49118
- join6(here2, "..", "..", "tray-mac")
49218
+ join7(here2, "..", "vendor", "tray-mac"),
49219
+ join7(here2, "..", "..", "tray-mac")
49119
49220
  ];
49120
49221
  for (const src of sourceDirs) {
49121
- const build = join6(src, "build-app.sh");
49122
- if (!existsSync7(build)) continue;
49222
+ const build = join7(src, "build-app.sh");
49223
+ if (!existsSync8(build)) continue;
49123
49224
  if (!hasSwift()) return null;
49124
- const r = spawnSync("bash", [build], { cwd: src, encoding: "utf8" });
49225
+ const r = spawnSync2("bash", [build], { cwd: src, encoding: "utf8" });
49125
49226
  if (r.status === 0) {
49126
- const app = join6(src, "build", "ModelstatTray.app");
49127
- if (existsSync7(app)) return app;
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 = spawnSync("swift", ["--version"], { encoding: "utf8" });
49234
+ const r = spawnSync2("swift", ["--version"], { encoding: "utf8" });
49134
49235
  return r.status === 0;
49135
49236
  }
49136
49237
  function trayStatus() {
49137
- if (platform2() !== "darwin") return { installed: false, path: null };
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 readFileSync5 } from "fs";
49145
- import { homedir as homedir8 } from "os";
49146
- import { join as join8 } from "path";
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.myAgentVersion && input.lock.agentVersion !== "unknown" && input.lock.agentVersion !== input.myAgentVersion) {
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 ?? join8(homedir8(), ".modelstat", "last-status.json");
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 = readFileSync5(statusPath, "utf8");
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
- myAgentVersion: opts.myAgentVersion
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 = platform4();
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.48" : "agent-dev";
49326
+ var AGENT_VERSION3 = true ? "agent-0.0.50" : "agent-dev";
49226
49327
  function osFamily() {
49227
- const p = platform4();
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 generateUuidV7() {
49239
- const ms = Date.now();
49240
- const tsHex = ms.toString(16).padStart(12, "0");
49241
- const rand = randomBytes(10);
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 ?? generateUuidV7();
49255
- const fresh = !state.deviceUuid;
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
- agent: "modelstat-agent-dev",
49262
- agent_version: AGENT_VERSION3
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 (fresh) {
49265
- process.stdout.write(` \x1B[2mgenerated UUIDv7 ${deviceUuid.slice(0, 8)}\u2026\x1B[0m
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 minting a new device identity");
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 (platform4() === "darwin") {
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(`${platform4() === "darwin" ? "launchd" : "systemd --user"}: ${svc.path}`);
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 (platform4() === "darwin") {
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: homedir10 } = await import("os");
49610
- const { join: join12 } = await import("path");
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 = join12(homedir10(), ".modelstat", "last-status.json");
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(`agent: ${view.device.agent_version ?? "(unknown)"}`);
49770
+ console.log(`companion: ${view.device.companion_version ?? "(unknown)"}`);
49672
49771
  console.log(
49673
- `status: ${view.device.agent_status ?? "(unknown)"}${view.device.last_seen_at ? ` \xB7 last seen ${view.device.last_seen_at}` : ""}`
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({ myAgentVersion: AGENT_VERSION3 })));
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(" npx modelstat@latest stats \u2014 live device summary: sessions \xB7 tokens \xB7 cost (--json)");
49844
- console.log(" npx modelstat@latest jobs \u2014 pipeline queue + recent processing ledger (--json)");
49845
- console.log(" npx modelstat@latest paths \u2014 print state file + log dir + api URL (--json)");
49846
- console.log(" npx modelstat@latest token \u2014 print the device token for hosted MCP / API access (--json)");
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");