log-llm-config 1.3.31 → 1.3.34

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.
@@ -2,6 +2,7 @@ import crypto from 'node:crypto';
2
2
  import { classifyEndpointResponse, postStartupPayload } from '../endpoint_client/index.js';
3
3
  import { resolveHardwareUuid } from './hardware_uuid.js';
4
4
  import { writeAuthKey, readStoredAuthKey, loadEndpointBase, buildStartupEndpointUrl } from './auth_key_store.js';
5
+ import { resolveUserProfile } from './user_profile.js';
5
6
  const canonicalizeValue = (value) => {
6
7
  if (Array.isArray(value))
7
8
  return value.map(canonicalizeValue);
@@ -25,6 +26,7 @@ const getMetadata = () => ({
25
26
  branch: process.env.GITHUB_REF_NAME || process.env.BRANCH_NAME || '',
26
27
  commit_sha: process.env.GITHUB_SHA || '',
27
28
  agent_name: process.env.OPTIMUS_AGENT || '',
29
+ user_profile: { ...resolveUserProfile() },
28
30
  });
29
31
  function buildRequestBody(hardwareUuid, timestamp) {
30
32
  const payloadSummary = { timestamp, directory: process.cwd(), hardware_uuid: hardwareUuid };
@@ -12,7 +12,7 @@ const safeJsonParse = (raw) => {
12
12
  return null;
13
13
  }
14
14
  };
15
- const readCursorCachedEmail = () => {
15
+ const readCursorCachedEmailFromVscdb = () => {
16
16
  const dbPath = path.join(os.homedir(), 'Library/Application Support/Cursor/User/globalStorage/state.vscdb');
17
17
  if (!fs.existsSync(dbPath))
18
18
  return '';
@@ -24,7 +24,31 @@ const readCursorCachedEmail = () => {
24
24
  return '';
25
25
  }
26
26
  };
27
- const readClaudeAuthEmail = () => {
27
+ /** Fallback: `storage.json` key path `cursor.auth.email` (design_notes). */
28
+ const readCursorCachedEmailFromStorageJson = () => {
29
+ const fp = path.join(os.homedir(), 'Library/Application Support/Cursor/User/globalStorage/storage.json');
30
+ if (!fs.existsSync(fp))
31
+ return '';
32
+ try {
33
+ const parsed = safeJsonParse(fs.readFileSync(fp, { encoding: 'utf8' }));
34
+ if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed))
35
+ return '';
36
+ const root = parsed;
37
+ const cursor = root.cursor;
38
+ if (!cursor || typeof cursor !== 'object' || Array.isArray(cursor))
39
+ return '';
40
+ const auth = cursor.auth;
41
+ if (!auth || typeof auth !== 'object' || Array.isArray(auth))
42
+ return '';
43
+ const email = auth.email;
44
+ return typeof email === 'string' ? email.trim() : '';
45
+ }
46
+ catch {
47
+ return '';
48
+ }
49
+ };
50
+ const readCursorCachedEmail = () => readCursorCachedEmailFromVscdb() || readCursorCachedEmailFromStorageJson();
51
+ const readClaudeAuthEmailFromCli = () => {
28
52
  try {
29
53
  const out = execFileSync('claude', ['auth', 'status'], {
30
54
  encoding: 'utf8',
@@ -35,7 +59,7 @@ const readClaudeAuthEmail = () => {
35
59
  const parsed = safeJsonParse(out);
36
60
  if (parsed && typeof parsed === 'object' && !Array.isArray(parsed)) {
37
61
  const email = parsed.email;
38
- return typeof email === 'string' ? email : '';
62
+ return typeof email === 'string' ? email.trim() : '';
39
63
  }
40
64
  }
41
65
  catch {
@@ -43,6 +67,30 @@ const readClaudeAuthEmail = () => {
43
67
  }
44
68
  return '';
45
69
  };
70
+ /** Fallback: optional Claude config files under ~/.claude/ (design_notes). */
71
+ const readClaudeEmailFromHomeFiles = () => {
72
+ const candidates = [
73
+ path.join(os.homedir(), '.claude/.credentials.json'),
74
+ path.join(os.homedir(), '.claude/.claude.json'),
75
+ ];
76
+ for (const fp of candidates) {
77
+ if (!fs.existsSync(fp))
78
+ continue;
79
+ try {
80
+ const parsed = safeJsonParse(fs.readFileSync(fp, { encoding: 'utf8' }));
81
+ if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed))
82
+ continue;
83
+ const email = parsed.email;
84
+ if (typeof email === 'string' && email.includes('@'))
85
+ return email.trim();
86
+ }
87
+ catch {
88
+ /* try next */
89
+ }
90
+ }
91
+ return '';
92
+ };
93
+ const readClaudeAuthEmail = () => readClaudeAuthEmailFromCli().trim() || readClaudeEmailFromHomeFiles();
46
94
  const readMacUsername = () => {
47
95
  const fromEnv = process.env.OPTIMUS_MAC_USERNAME?.trim() ||
48
96
  process.env.USER?.trim() ||
@@ -52,7 +100,23 @@ const readMacUsername = () => {
52
100
  return fromEnv;
53
101
  return readCommandOutput('id -un');
54
102
  };
103
+ /**
104
+ * Matches design_notes order: `gh api user` (login), then CI-style env, then `git config user.name`.
105
+ * `metadata.github_username` in startup_sender still uses env only; this field is the richer probe.
106
+ */
55
107
  const readGithubUsername = () => {
108
+ try {
109
+ const out = execFileSync('gh', ['api', 'user', '--jq', '.login'], {
110
+ encoding: 'utf8',
111
+ stdio: ['ignore', 'pipe', 'ignore'],
112
+ maxBuffer: 1024 * 1024,
113
+ }).trim();
114
+ if (out)
115
+ return out;
116
+ }
117
+ catch {
118
+ /* gh missing or not authenticated */
119
+ }
56
120
  return (process.env.GITHUB_USER?.trim() ||
57
121
  process.env.GH_USER?.trim() ||
58
122
  readCommandOutput('git config user.name'));
@@ -72,8 +136,35 @@ const readUserProfileFromEnvOrFile = () => {
72
136
  }
73
137
  return null;
74
138
  };
139
+ const isPlausibleUuid = (s) => /^[\da-f]{8}-[\da-f]{4}-[\da-f]{4}-[\da-f]{4}-[\da-f]{12}$/i.test(s.trim());
140
+ /**
141
+ * macOS Open Directory **GeneratedUID** for the console user (same concept as Directory Utility).
142
+ * See `dscl . -read /Users/<shortname> GeneratedUID`. Not the hardware UUID (that is `machineuuid`).
143
+ *
144
+ * `OPTIMUS_MAC_GENERATED_UID` overrides for tests or locked-down environments where `dscl` is unavailable.
145
+ */
146
+ const readMacAccountGeneratedUid = () => {
147
+ const env = process.env.OPTIMUS_MAC_GENERATED_UID?.trim();
148
+ if (env && isPlausibleUuid(env))
149
+ return env.trim().toLowerCase();
150
+ if (process.platform !== 'darwin')
151
+ return '';
152
+ const user = readMacUsername();
153
+ if (!user || !/^[a-zA-Z0-9._-]+$/.test(user))
154
+ return '';
155
+ try {
156
+ const out = execFileSync('dscl', ['.', '-read', `/Users/${user}`, 'GeneratedUID'], { encoding: 'utf8', stdio: ['ignore', 'pipe', 'ignore'] });
157
+ const m = out.match(/GeneratedUID:\s*([0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{12})/);
158
+ if (m?.[1] && isPlausibleUuid(m[1]))
159
+ return m[1].toLowerCase();
160
+ }
161
+ catch {
162
+ return '';
163
+ }
164
+ return '';
165
+ };
75
166
  const buildDefaultUserProfile = () => ({
76
- generateduuid: crypto.randomUUID(),
167
+ generateduuid: readMacAccountGeneratedUid() || crypto.randomUUID(),
77
168
  machineuuid: resolveHardwareUuid(),
78
169
  mac_username: readMacUsername(),
79
170
  github_username: readGithubUsername(),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "log-llm-config",
3
- "version": "1.3.31",
3
+ "version": "1.3.34",
4
4
  "description": "CLI helpers for logging hardware UUIDs and posting startup payloads to Optimus Security.",
5
5
  "type": "module",
6
6
  "bin": {