claude-code-session-manager 0.33.0 → 0.33.1

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/index.html CHANGED
@@ -7,7 +7,7 @@
7
7
  <link rel="preconnect" href="https://fonts.googleapis.com">
8
8
  <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
9
9
  <link href="https://fonts.googleapis.com/css2?family=Newsreader:ital,opsz,wght@0,6..72,400;0,6..72,500;0,6..72,600;0,6..72,700;1,6..72,400&family=Geist:wght@300;400;500;600;700&family=IBM+Plex+Mono:wght@400;500;600&display=swap" rel="stylesheet">
10
- <script type="module" crossorigin src="./assets/index-Bwwbc2mS.js"></script>
10
+ <script type="module" crossorigin src="./assets/index-1PpZBVUr.js"></script>
11
11
  <link rel="modulepreload" crossorigin href="./assets/monaco-editor-BW5C4Iv1.js">
12
12
  <link rel="stylesheet" crossorigin href="./assets/monaco-editor-BTnBOi8r.css">
13
13
  <link rel="stylesheet" crossorigin href="./assets/index-AKeGl-VM.css">
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-code-session-manager",
3
- "version": "0.33.0",
3
+ "version": "0.33.1",
4
4
  "description": "Local cockpit for the Claude Code CLI — multi-tab terminal, full config surface, scheduler, voice dictation, and live observability.",
5
5
  "type": "module",
6
6
  "main": "src/main/index.cjs",
@@ -16,6 +16,7 @@
16
16
  * }
17
17
  */
18
18
 
19
+ const fs = require('node:fs');
19
20
  const fsp = require('node:fs/promises');
20
21
  const path = require('node:path');
21
22
  const os = require('node:os');
@@ -30,28 +31,74 @@ function envEnabled(v) {
30
31
  return v != null && v !== '' && v !== '0' && String(v).toLowerCase() !== 'false';
31
32
  }
32
33
 
34
+ /**
35
+ * Reads enterprise-auth signals from Claude Code's own settings files — the
36
+ * `env` block and `apiKeyHelper`. This is where corporate gateways are usually
37
+ * configured (a managed/enterprise policy or the user's settings.json), NOT as
38
+ * exported shell vars. It matters most on macOS, where a GUI-launched app does
39
+ * not inherit the shell's environment, so `process.env` looks like a clean
40
+ * consumer install even when `claude` itself is talking to a gateway.
41
+ *
42
+ * Precedence mirrors Claude Code: managed (enterprise) settings, then user
43
+ * settings, then user-local settings. Missing/unreadable/invalid files are
44
+ * skipped. Returns `{ env, apiKeyHelper }`.
45
+ */
46
+ function readClaudeSettingsAuth() {
47
+ const merged = {};
48
+ let apiKeyHelper = false;
49
+ const managed = process.platform === 'darwin'
50
+ ? '/Library/Application Support/ClaudeCode/managed-settings.json'
51
+ : '/etc/claude-code/managed-settings.json';
52
+ const files = [
53
+ managed,
54
+ path.join(os.homedir(), '.claude', 'settings.json'),
55
+ path.join(os.homedir(), '.claude', 'settings.local.json'),
56
+ ];
57
+ for (const f of files) {
58
+ try {
59
+ const data = JSON.parse(fs.readFileSync(f, 'utf8'));
60
+ if (data && typeof data.env === 'object' && data.env) Object.assign(merged, data.env);
61
+ if (data && data.apiKeyHelper) apiKeyHelper = true;
62
+ } catch { /* missing / unreadable / invalid JSON → skip */ }
63
+ }
64
+ return { env: merged, apiKeyHelper };
65
+ }
66
+
33
67
  /**
34
68
  * Is the consumer 5-hour usage meter (/api/oauth/usage) even applicable here?
35
69
  *
36
70
  * That endpoint only exists for OAuth/subscription auth against
37
71
  * api.anthropic.com. Enterprise auth modes have no such meter, so polling it
38
- * just 404s/times-out and the scheduler must NOT gate on (or pause for) it.
39
- * Detected modes: Amazon Bedrock, Google Vertex, raw API-key, a custom auth
40
- * token, or a non-Anthropic base URL (corporate gateway/proxy).
72
+ * just 404s/times-out (or 401s with no credentials file) and the scheduler
73
+ * must NOT gate on (or pause for) it. Detected modes: Amazon Bedrock, Google
74
+ * Vertex, raw API-key, a custom auth token, a non-Anthropic base URL (corporate
75
+ * gateway/proxy), or an `apiKeyHelper` script.
76
+ *
77
+ * Signals are read from BOTH process.env and Claude Code's settings files, so a
78
+ * gateway configured purely in settings.json (the common enterprise case) is
79
+ * detected even when the GUI process inherited a clean environment.
41
80
  *
42
81
  * Returns false → caller should treat usage as unavailable-by-design and fire
43
82
  * work on its own (pending + memory) instead of waiting on a meter.
44
83
  */
45
- function usageMeterApplicable(env = process.env) {
46
- if (envEnabled(env.CLAUDE_CODE_USE_BEDROCK)) return false;
47
- if (envEnabled(env.CLAUDE_CODE_USE_VERTEX)) return false;
48
- if (env.ANTHROPIC_API_KEY) return false;
49
- if (env.ANTHROPIC_AUTH_TOKEN) return false;
50
- if (env.ANTHROPIC_BASE_URL) {
84
+ function usageMeterApplicable(env = process.env, settings = readClaudeSettingsAuth()) {
85
+ // Manual escape hatch: if detection misses an unusual gateway setup, the user
86
+ // can force "no consumer meter" so the scheduler stops pausing on 'auth'.
87
+ if (envEnabled(env.SM_NO_USAGE_METER)) return false;
88
+ // An apiKeyHelper means `claude` mints its own key → non-OAuth, no meter.
89
+ if (settings && settings.apiKeyHelper) return false;
90
+ // Effective env: settings.json provides values the GUI process didn't
91
+ // inherit; a real process.env var wins when both define the same key.
92
+ const eff = { ...(settings && settings.env), ...env };
93
+ if (envEnabled(eff.CLAUDE_CODE_USE_BEDROCK)) return false;
94
+ if (envEnabled(eff.CLAUDE_CODE_USE_VERTEX)) return false;
95
+ if (eff.ANTHROPIC_API_KEY) return false;
96
+ if (eff.ANTHROPIC_AUTH_TOKEN) return false;
97
+ if (eff.ANTHROPIC_BASE_URL) {
51
98
  // Parse the host rather than substring-match, so a deceptive gateway like
52
99
  // https://anthropic.com.attacker.example is correctly treated as enterprise.
53
100
  let host;
54
- try { host = new URL(env.ANTHROPIC_BASE_URL).hostname.toLowerCase(); }
101
+ try { host = new URL(eff.ANTHROPIC_BASE_URL).hostname.toLowerCase(); }
55
102
  catch { return false; } // unparseable custom URL → treat as a gateway
56
103
  if (host !== 'anthropic.com' && !host.endsWith('.anthropic.com')) return false;
57
104
  }
@@ -197,4 +244,4 @@ function registerBillingHandlers() {
197
244
  });
198
245
  }
199
246
 
200
- module.exports = { registerBillingHandlers, fetchUsage, classifyUsageResponse, usageMeterApplicable };
247
+ module.exports = { registerBillingHandlers, fetchUsage, classifyUsageResponse, usageMeterApplicable, readClaudeSettingsAuth };