@scrylog/cli 0.3.0 → 0.3.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.
Files changed (195) hide show
  1. package/dist/assets/highlights-eq9cgrbb.scm +604 -0
  2. package/dist/assets/highlights-ghv9g403.scm +205 -0
  3. package/dist/assets/highlights-hk7bwhj4.scm +284 -0
  4. package/dist/assets/highlights-r812a2qc.scm +150 -0
  5. package/dist/assets/highlights-x6tmsnaa.scm +115 -0
  6. package/dist/assets/injections-73j83es3.scm +27 -0
  7. package/dist/assets/parser.worker-xyhf83rf.js +4563 -0
  8. package/dist/assets/tree-sitter-3jzf13jk.wasm +0 -0
  9. package/dist/assets/tree-sitter-javascript-nd0q4pe9.wasm +0 -0
  10. package/dist/assets/tree-sitter-markdown-411r6y9b.wasm +0 -0
  11. package/dist/assets/tree-sitter-markdown_inline-j5349f42.wasm +0 -0
  12. package/dist/assets/tree-sitter-typescript-zxjzwt75.wasm +0 -0
  13. package/dist/assets/tree-sitter-zig-e78zbjpm.wasm +0 -0
  14. package/dist/cli/index.js +499 -0
  15. package/dist/cli/index.js.map +61 -0
  16. package/dist/daemon/index.js +670 -0
  17. package/dist/daemon/index.js.map +1475 -0
  18. package/dist/hooks/claude.js +6 -0
  19. package/dist/hooks/claude.js.map +11 -0
  20. package/dist/hooks/codex.js +10 -0
  21. package/dist/hooks/codex.js.map +11 -0
  22. package/dist/mcp/index.js +100 -0
  23. package/dist/mcp/index.js.map +231 -0
  24. package/dist/oc/index.js +21 -0
  25. package/dist/oc/index.js.map +10 -0
  26. package/package.json +16 -13
  27. package/src/api/docs/sessions.keys.ts +0 -6
  28. package/src/api/docs/sessions.ts +0 -82
  29. package/src/api/docs/system.keys.ts +0 -5
  30. package/src/api/docs/system.ts +0 -69
  31. package/src/api/docs/usage.keys.ts +0 -3
  32. package/src/api/docs/usage.ts +0 -24
  33. package/src/api/docs/webhooks.keys.ts +0 -5
  34. package/src/api/docs/webhooks.ts +0 -78
  35. package/src/api/index.ts +0 -18
  36. package/src/api/lib/auth.ts +0 -43
  37. package/src/api/lib/errors.ts +0 -28
  38. package/src/api/lib/route.ts +0 -18
  39. package/src/api/models/claude.ts +0 -4
  40. package/src/api/models/codex.ts +0 -4
  41. package/src/api/models/opencode.ts +0 -11
  42. package/src/api/routes/sessions.ts +0 -51
  43. package/src/api/routes/system.ts +0 -106
  44. package/src/api/routes/usage.ts +0 -15
  45. package/src/api/routes/webhooks/claude.ts +0 -149
  46. package/src/api/routes/webhooks/codex.ts +0 -175
  47. package/src/api/routes/webhooks/opencode.ts +0 -112
  48. package/src/api/routes.ts +0 -93
  49. package/src/api/schemas/common.ts +0 -29
  50. package/src/api/schemas/sessions.ts +0 -86
  51. package/src/api/schemas/usage.ts +0 -51
  52. package/src/api/schemas/webhooks/claude.ts +0 -32
  53. package/src/api/schemas/webhooks/codex.ts +0 -34
  54. package/src/api/schemas/webhooks/opencode.ts +0 -29
  55. package/src/api/services/claude-session.ts +0 -9
  56. package/src/api/services/codex-session.ts +0 -8
  57. package/src/api/services/opencode-session.ts +0 -73
  58. package/src/classifier.ts +0 -206
  59. package/src/cli/commands.ts +0 -714
  60. package/src/cli/index.ts +0 -18
  61. package/src/cli/program.ts +0 -175
  62. package/src/cli/prompt.ts +0 -44
  63. package/src/daemon/cli.ts +0 -27
  64. package/src/daemon/collectors/claude/README.md +0 -108
  65. package/src/daemon/collectors/claude/collector.ts +0 -423
  66. package/src/daemon/collectors/claude/discovery.ts +0 -127
  67. package/src/daemon/collectors/claude/hooks.ts +0 -181
  68. package/src/daemon/collectors/claude/index.ts +0 -8
  69. package/src/daemon/collectors/claude/jsonl.ts +0 -85
  70. package/src/daemon/collectors/claude/transcript.ts +0 -246
  71. package/src/daemon/collectors/codex/README.md +0 -147
  72. package/src/daemon/collectors/codex/collector.ts +0 -661
  73. package/src/daemon/collectors/codex/discovery.ts +0 -104
  74. package/src/daemon/collectors/codex/hooks.ts +0 -179
  75. package/src/daemon/collectors/codex/index.ts +0 -7
  76. package/src/daemon/collectors/codex/jsonl.ts +0 -108
  77. package/src/daemon/collectors/codex/transcript.ts +0 -299
  78. package/src/daemon/collectors/git.ts +0 -353
  79. package/src/daemon/collectors/herdr/collector.ts +0 -128
  80. package/src/daemon/collectors/herdr/index.ts +0 -2
  81. package/src/daemon/collectors/herdr/normalization.ts +0 -111
  82. package/src/daemon/collectors/opencode/README.md +0 -106
  83. package/src/daemon/collectors/opencode/collector.ts +0 -545
  84. package/src/daemon/collectors/opencode/discovery.ts +0 -257
  85. package/src/daemon/collectors/opencode/index.ts +0 -5
  86. package/src/daemon/collectors/opencode/session-builder.ts +0 -59
  87. package/src/daemon/collectors/opencode-db.ts +0 -294
  88. package/src/daemon/collectors/process.ts +0 -201
  89. package/src/daemon/collectors/tmux/README.md +0 -128
  90. package/src/daemon/collectors/tmux/collector.ts +0 -492
  91. package/src/daemon/collectors/tmux/enrichment.ts +0 -242
  92. package/src/daemon/collectors/tmux/index.ts +0 -4
  93. package/src/daemon/collectors/tmux/parse.ts +0 -128
  94. package/src/daemon/collectors/usage.ts +0 -259
  95. package/src/daemon/index.ts +0 -209
  96. package/src/daemon/scheduler.ts +0 -86
  97. package/src/daemon/store.ts +0 -630
  98. package/src/detect.ts +0 -143
  99. package/src/hooks/claude.ts +0 -596
  100. package/src/hooks/codex.ts +0 -517
  101. package/src/legacy/classifier.ts +0 -215
  102. package/src/legacy/detect.ts +0 -143
  103. package/src/mcp/client-server.ts +0 -21
  104. package/src/mcp/http-handler.ts +0 -126
  105. package/src/mcp/index.ts +0 -61
  106. package/src/mcp/resources/config-current.ts +0 -19
  107. package/src/mcp/resources/index.ts +0 -11
  108. package/src/mcp/resources/sessions-active.ts +0 -19
  109. package/src/mcp/resources/sessions-all.ts +0 -19
  110. package/src/mcp/schemas/sessions.ts +0 -3
  111. package/src/mcp/server.ts +0 -17
  112. package/src/mcp/services/api-adapter.ts +0 -48
  113. package/src/mcp/services/data-source.ts +0 -22
  114. package/src/mcp/services/store-adapter.ts +0 -40
  115. package/src/mcp/tools/get-active-sessions.ts +0 -16
  116. package/src/mcp/tools/get-session-children.ts +0 -24
  117. package/src/mcp/tools/get-session-messages.ts +0 -24
  118. package/src/mcp/tools/get-session.ts +0 -23
  119. package/src/mcp/tools/index.ts +0 -15
  120. package/src/mcp/tools/list-sessions.ts +0 -16
  121. package/src/oc/index.ts +0 -302
  122. package/src/service/manager.ts +0 -284
  123. package/src/shared/config.ts +0 -511
  124. package/src/shared/ipc.ts +0 -80
  125. package/src/shared/logger.ts +0 -248
  126. package/src/shared/paths.ts +0 -73
  127. package/src/shared/platform.ts +0 -110
  128. package/src/shared/session-exclusions.ts +0 -5
  129. package/src/shared/session-view.ts +0 -302
  130. package/src/shared/terminal-capabilities.ts +0 -130
  131. package/src/shared/types.ts +0 -330
  132. package/src/shared/utils.ts +0 -339
  133. package/src/shared/version.ts +0 -44
  134. package/src/tui/App.tsx +0 -240
  135. package/src/tui/client.ts +0 -163
  136. package/src/tui/components/BindingsModal.tsx +0 -82
  137. package/src/tui/components/DashboardHeader.tsx +0 -256
  138. package/src/tui/components/KeyBar.tsx +0 -67
  139. package/src/tui/components/SessionDetailModal.tsx +0 -169
  140. package/src/tui/components/SessionsView.tsx +0 -184
  141. package/src/tui/components/TabBar.tsx +0 -40
  142. package/src/tui/components/UsageSummaryPane.tsx +0 -272
  143. package/src/tui/components/UsageView.tsx +0 -242
  144. package/src/tui/components/tool-icons.ts +0 -24
  145. package/src/tui/index.tsx +0 -106
  146. package/src/tui/keybindings.ts +0 -49
  147. package/src/tui/model.ts +0 -295
  148. package/src/tui/state.ts +0 -77
  149. package/src/tui/theme.ts +0 -110
  150. package/src/types.ts +0 -113
  151. package/src/usage/README.md +0 -323
  152. package/src/usage/api.ts +0 -99
  153. package/src/usage/client.ts +0 -3
  154. package/src/usage/clients/anthropic-oauth-usage.ts +0 -258
  155. package/src/usage/clients/anthropic-web-usage.ts +0 -329
  156. package/src/usage/clients/claude-cli-probe.ts +0 -513
  157. package/src/usage/clients/codex-app-server.ts +0 -354
  158. package/src/usage/clients/codex-oauth-usage.ts +0 -240
  159. package/src/usage/clients/opencode-go-api.ts +0 -100
  160. package/src/usage/clients/opencode-go-usage.ts +0 -577
  161. package/src/usage/errors.ts +0 -33
  162. package/src/usage/index.ts +0 -20
  163. package/src/usage/local/opencode-go-local.ts +0 -194
  164. package/src/usage/mappers.ts +0 -282
  165. package/src/usage/planner.ts +0 -118
  166. package/src/usage/providers/claude.ts +0 -233
  167. package/src/usage/providers/codex.ts +0 -115
  168. package/src/usage/providers/opencode-go.ts +0 -115
  169. package/src/usage/resolver.ts +0 -4
  170. package/src/usage/resolvers/browser-cookies.ts +0 -808
  171. package/src/usage/resolvers/claude-auth.ts +0 -208
  172. package/src/usage/resolvers/claude-cli.ts +0 -24
  173. package/src/usage/resolvers/claude-desktop-auth.ts +0 -170
  174. package/src/usage/resolvers/claude-web.ts +0 -82
  175. package/src/usage/resolvers/codex-auth.ts +0 -174
  176. package/src/usage/resolvers/keychain-coordinator.ts +0 -397
  177. package/src/usage/resolvers/opencode-go-web.ts +0 -55
  178. package/src/usage/types.ts +0 -225
  179. package/src/usage/web-session-cache.ts +0 -37
  180. /package/{src/tui → dist/cli}/assets/providers/SOURCES.md +0 -0
  181. /package/{src/tui → dist/cli}/assets/providers/claude-terminal.png +0 -0
  182. /package/{src/tui → dist/cli}/assets/providers/claude-terminal.svg +0 -0
  183. /package/{src/tui → dist/cli}/assets/providers/claude.png +0 -0
  184. /package/{src/tui → dist/cli}/assets/providers/copilot.png +0 -0
  185. /package/{src/tui → dist/cli}/assets/providers/copilot.svg +0 -0
  186. /package/{src/tui → dist/cli}/assets/providers/openai-terminal.png +0 -0
  187. /package/{src/tui → dist/cli}/assets/providers/openai-terminal.svg +0 -0
  188. /package/{src/tui → dist/cli}/assets/providers/openai.png +0 -0
  189. /package/{src/tui → dist/cli}/assets/providers/opencode-terminal.png +0 -0
  190. /package/{src/tui → dist/cli}/assets/providers/opencode-terminal.svg +0 -0
  191. /package/{src/tui → dist/cli}/assets/providers/opencode.png +0 -0
  192. /package/{src/tui → dist/cli}/assets/providers/shell.png +0 -0
  193. /package/{src/tui → dist/cli}/assets/providers/shell.svg +0 -0
  194. /package/{src/tui → dist/cli}/assets/providers/unknown.png +0 -0
  195. /package/{src/tui → dist/cli}/assets/providers/unknown.svg +0 -0
@@ -1,329 +0,0 @@
1
- import type { UsageClient } from "../client";
2
- import type { ClaudeUsageSnapshot, NamedRateWindowLegacy, ProviderCostSnapshotLegacy, RateWindowLegacy, ClaudeWebSession } from "../types";
3
- import { classifyUsageError, UsageError } from "../errors";
4
- import { usageWebSessionCache } from "../web-session-cache";
5
- import { CLAUDE_WEB_CACHE_KEY } from "../resolvers/claude-web";
6
-
7
- export class InvalidCredentialsError extends UsageError {
8
- constructor(message: string) {
9
- super("invalid-credentials", message);
10
- this.name = "InvalidCredentialsError";
11
- }
12
- }
13
-
14
- interface Org {
15
- uuid: string;
16
- name?: string;
17
- capabilities?: string[];
18
- }
19
-
20
- interface UsageResponse {
21
- five_hour?: { utilization?: number | null; resets_at?: string | null } | null;
22
- seven_day?: { utilization?: number | null; resets_at?: string | null } | null;
23
- seven_day_sonnet?: { utilization?: number | null; resets_at?: string | null } | null;
24
- seven_day_opus?: { utilization?: number | null; resets_at?: string | null } | null;
25
- seven_day_design?: { utilization?: number | null; resets_at?: string | null } | null;
26
- seven_day_routines?: { utilization?: number | null; resets_at?: string | null } | null;
27
- [key: string]: unknown;
28
- }
29
-
30
- interface OverageResponse {
31
- monthly_credit_limit?: number;
32
- currency?: string;
33
- used_credits?: number;
34
- is_enabled?: boolean;
35
- }
36
-
37
- interface AccountResponse {
38
- email_address?: string;
39
- memberships?: Array<{
40
- organization?: {
41
- uuid: string;
42
- name?: string;
43
- rate_limit_tier?: string;
44
- billing_type?: string;
45
- };
46
- }>;
47
- }
48
-
49
- const DESIGN_ALTERNATES = [
50
- "seven_day_design",
51
- "seven_day_claude_design",
52
- "claude_design",
53
- "design",
54
- "seven_day_omelette",
55
- "omelette",
56
- "omelette_promotional",
57
- ];
58
-
59
- const ROUTINES_ALTERNATES = [
60
- "seven_day_routines",
61
- "seven_day_claude_routines",
62
- "claude_routines",
63
- "routines",
64
- "routine",
65
- "seven_day_cowork",
66
- "cowork",
67
- ];
68
-
69
- const OAUTH_APPS_ALTERNATES = ["seven_day_oauth_apps", "oauth_apps"];
70
-
71
- function pickWindowData(data: UsageResponse, keys: string[]): { utilization?: number | null; resets_at?: string | null } | null {
72
- for (const key of keys) {
73
- const val = data[key];
74
- if (val && typeof val === "object") {
75
- return val as { utilization?: number | null; resets_at?: string | null };
76
- }
77
- }
78
- return null;
79
- }
80
-
81
- function toRateWindow(
82
- utilization: number | null | undefined,
83
- resetsAt: string | null | undefined,
84
- windowMinutes: number,
85
- ): RateWindowLegacy {
86
- const usedPercent = typeof utilization === "number" ? Math.max(0, Math.min(100, utilization)) : 0;
87
- const resetsAtDate = resetsAt ? new Date(resetsAt) : null;
88
- const resetDescription = resetsAtDate && !Number.isNaN(resetsAtDate.getTime())
89
- ? resetsAtDate.toLocaleString()
90
- : null;
91
- return {
92
- usedPercent,
93
- windowMinutes,
94
- resetsAt: resetsAtDate && !Number.isNaN(resetsAtDate.getTime()) ? resetsAtDate : null,
95
- resetDescription,
96
- };
97
- }
98
-
99
- export class AnthropicWebUsageClient implements UsageClient<ClaudeWebSession, ClaudeUsageSnapshot> {
100
- async fetch(creds: ClaudeWebSession, options?: { signal?: AbortSignal }): Promise<ClaudeUsageSnapshot> {
101
- const candidates: string[] = [...new Set(creds.cookieCandidates ?? (creds.cookieHeader ? [creds.cookieHeader] : []))].slice(0, 2);
102
- let expectedRevision = creds.cacheRevision ?? usageWebSessionCache.observe(CLAUDE_WEB_CACHE_KEY).revision;
103
-
104
- for (let index = 0; index < candidates.length; index++) {
105
- let rotated = false;
106
- try {
107
- const snapshot = await this.fetchWithCookie(candidates[index]!, options?.signal, (cookieHeader) => {
108
- const stored = usageWebSessionCache.store(CLAUDE_WEB_CACHE_KEY, cookieHeader, expectedRevision);
109
- if (stored) expectedRevision = stored.revision;
110
- rotated = true;
111
- });
112
- if (!rotated) {
113
- const stored = usageWebSessionCache.store(CLAUDE_WEB_CACHE_KEY, candidates[index]!, expectedRevision);
114
- if (stored) expectedRevision = stored.revision;
115
- }
116
- return snapshot;
117
- } catch (error) {
118
- const failure = classifyUsageError(error);
119
- if (failure.kind === "invalid-credentials") {
120
- if (usageWebSessionCache.clear(CLAUDE_WEB_CACHE_KEY, expectedRevision)) expectedRevision = 0;
121
- if (index + 1 < candidates.length) continue;
122
- // Advance the demand-driven cursor at most once per attempt, keeping
123
- // the two-candidate bound across imported and rotated candidates.
124
- const imported = candidates.length < 2 ? (await creds.importNext?.()) ?? null : null;
125
- if (imported && !candidates.includes(imported)) {
126
- candidates.push(imported);
127
- continue;
128
- }
129
- }
130
- throw failure;
131
- }
132
- }
133
- throw new InvalidCredentialsError("Session cookie invalid or expired");
134
- }
135
-
136
- private async fetchWithCookie(
137
- initialCookieHeader: string,
138
- signal: AbortSignal | undefined,
139
- onCookieRotation: (cookieHeader: string) => void,
140
- ): Promise<ClaudeUsageSnapshot> {
141
- let cookieHeader = initialCookieHeader;
142
- const request = async (url: string): Promise<Response> => {
143
- let response: Response;
144
- try {
145
- response = await fetch(url, {
146
- signal,
147
- headers: { Cookie: cookieHeader, Accept: "application/json" },
148
- });
149
- } catch (error) {
150
- throw classifyUsageError(error);
151
- }
152
- const rotated = applyClaudeSessionRotation(cookieHeader, response.headers);
153
- if (rotated !== cookieHeader) {
154
- cookieHeader = rotated;
155
- onCookieRotation(cookieHeader);
156
- }
157
- return response;
158
- };
159
-
160
- // 1. Fetch organizations
161
- const orgRes = await request("https://claude.ai/api/organizations");
162
-
163
- if (orgRes.status === 401) {
164
- throw new InvalidCredentialsError("Session cookie invalid or expired");
165
- }
166
- if (orgRes.status === 403) throw new UsageError("forbidden", "Organizations access forbidden");
167
- if (orgRes.status === 429) throw new UsageError("rate-limited", "Organizations fetch rate limited");
168
- if (orgRes.status >= 500) throw new UsageError("transient", `Organizations fetch failed: ${orgRes.status}`);
169
- if (!orgRes.ok) {
170
- throw new UsageError("invalid-response", `Organizations fetch failed: ${orgRes.status}`);
171
- }
172
-
173
- const orgs = (await orgRes.json()) as Org[];
174
- if (!Array.isArray(orgs) || orgs.length === 0) {
175
- throw new UsageError("invalid-response", "No organizations found");
176
- }
177
-
178
- // Select org
179
- let org = orgs.find((o) => o.capabilities?.includes("chat"));
180
- if (!org) {
181
- org = orgs.find((o) => JSON.stringify(o.capabilities) !== '["api"]');
182
- }
183
- if (!org) {
184
- org = orgs[0];
185
- }
186
-
187
- // 2. Fetch usage
188
- const usageRes = await request(`https://claude.ai/api/organizations/${org.uuid}/usage`);
189
-
190
- if (usageRes.status === 401) {
191
- throw new InvalidCredentialsError("Session cookie invalid or expired");
192
- }
193
- if (usageRes.status === 403) throw new UsageError("forbidden", "Usage access forbidden");
194
- if (usageRes.status === 429) throw new UsageError("rate-limited", "Usage fetch rate limited");
195
- if (usageRes.status >= 500) throw new UsageError("transient", `Usage fetch failed: ${usageRes.status}`);
196
- if (!usageRes.ok) {
197
- throw new UsageError("invalid-response", `Usage fetch failed: ${usageRes.status}`);
198
- }
199
-
200
- const data = (await usageRes.json()) as UsageResponse;
201
-
202
- // Null or missing windows mean "no usage recorded for the period" — a
203
- // valid response, presented as an empty window at 0% (matches the
204
- // reference implementation's "100% left" presentation).
205
- const primaryWindow = pickWindowData(data, ["five_hour"]);
206
- const secondaryWindow = pickWindowData(data, ["seven_day"]);
207
-
208
- const primary = toRateWindow(
209
- primaryWindow && typeof primaryWindow.utilization === "number" ? primaryWindow.utilization : 0,
210
- primaryWindow?.resets_at ?? null,
211
- 300,
212
- );
213
- const secondary = secondaryWindow && typeof secondaryWindow.utilization === "number"
214
- ? toRateWindow(secondaryWindow.utilization, secondaryWindow.resets_at, 10080)
215
- : null;
216
-
217
- const opusWindow = pickWindowData(data, ["seven_day_sonnet", "seven_day_opus"]);
218
- const opus = opusWindow && typeof opusWindow.utilization === "number"
219
- ? toRateWindow(opusWindow.utilization, opusWindow.resets_at, 10080)
220
- : null;
221
-
222
- const extraRateWindows: NamedRateWindowLegacy[] = [];
223
- const designWindow = pickWindowData(data, DESIGN_ALTERNATES);
224
- if (designWindow && typeof designWindow.utilization === "number") {
225
- extraRateWindows.push({
226
- id: "claude-design",
227
- title: "Designs",
228
- window: toRateWindow(designWindow.utilization, designWindow.resets_at, 10080),
229
- });
230
- }
231
- const routinesWindow = pickWindowData(data, ROUTINES_ALTERNATES);
232
- if (routinesWindow && typeof routinesWindow.utilization === "number") {
233
- extraRateWindows.push({
234
- id: "claude-routines",
235
- title: "Daily Routines",
236
- window: toRateWindow(routinesWindow.utilization, routinesWindow.resets_at, 10080),
237
- });
238
- }
239
- const oauthAppsWindow = pickWindowData(data, OAUTH_APPS_ALTERNATES);
240
- if (oauthAppsWindow && typeof oauthAppsWindow.utilization === "number") {
241
- extraRateWindows.push({
242
- id: "claude-oauth-apps",
243
- title: "OAuth Apps",
244
- window: toRateWindow(oauthAppsWindow.utilization, oauthAppsWindow.resets_at, 10080),
245
- });
246
- }
247
-
248
- // 3. Best-effort overage
249
- let providerCost: ProviderCostSnapshotLegacy | null = null;
250
- try {
251
- const overageRes = await request(`https://claude.ai/api/organizations/${org.uuid}/overage_spend_limit`);
252
- if (overageRes.ok) {
253
- const overage = (await overageRes.json()) as OverageResponse;
254
- if (overage.is_enabled) {
255
- providerCost = {
256
- used: (overage.used_credits ?? 0) / 100,
257
- limit: (overage.monthly_credit_limit ?? 0) / 100,
258
- currencyCode: (overage.currency || "USD").trim() || "USD",
259
- period: "Monthly",
260
- resetsAt: null,
261
- updatedAt: new Date(),
262
- };
263
- }
264
- }
265
- } catch (error) {
266
- if (classifyUsageError(error).kind === "cancelled") throw error;
267
- // Ignore best-effort failure
268
- }
269
-
270
- // 4. Best-effort account info
271
- let accountEmail: string | null = null;
272
- let accountOrganization: string | null = null;
273
- let accountOrganizationId: string | null = null;
274
- let loginMethod: string | null = null;
275
- try {
276
- const accountRes = await request("https://claude.ai/api/account");
277
- if (accountRes.ok) {
278
- const account = (await accountRes.json()) as AccountResponse;
279
- if (account.email_address) {
280
- accountEmail = account.email_address.trim();
281
- }
282
- const membership = account.memberships?.find((m) => m.organization?.uuid === org.uuid);
283
- if (membership?.organization?.name) {
284
- accountOrganization = membership.organization.name;
285
- if (membership.organization.rate_limit_tier) {
286
- loginMethod = membership.organization.rate_limit_tier;
287
- }
288
- }
289
- accountOrganizationId = org.uuid;
290
- }
291
- } catch (error) {
292
- if (classifyUsageError(error).kind === "cancelled") throw error;
293
- // Ignore best-effort failure
294
- }
295
-
296
- return {
297
- source: "web",
298
- primary,
299
- secondary,
300
- opus,
301
- extraRateWindows,
302
- providerCost,
303
- updatedAt: new Date(),
304
- accountEmail,
305
- accountOrganization,
306
- accountOrganizationId,
307
- loginMethod,
308
- subscriptionType: null,
309
- rateLimitTier: null,
310
- };
311
- }
312
- }
313
-
314
- function applyClaudeSessionRotation(current: string, headers: Headers): string {
315
- const values = (headers as Headers & { getSetCookie?: () => string[] }).getSetCookie?.()
316
- ?? (headers.get("set-cookie") ? [headers.get("set-cookie")!] : []);
317
- let sessionKey = current.split(";").map((part) => part.trim()).find((part) => part.startsWith("sessionKey="));
318
- for (const value of values) {
319
- const [pair, ...attributes] = value.split(";");
320
- if (!pair?.trim().startsWith("sessionKey=")) continue;
321
- const expired = attributes.some((attribute) => {
322
- const [name, raw = ""] = attribute.trim().split("=", 2);
323
- if (name?.toLowerCase() === "max-age") return Number(raw) <= 0;
324
- return name?.toLowerCase() === "expires" && Date.parse(raw) <= Date.now();
325
- });
326
- sessionKey = expired || pair.trim() === "sessionKey=" ? undefined : pair.trim();
327
- }
328
- return sessionKey ?? "";
329
- }