charness 3.0.0 → 3.1.0

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 (227) hide show
  1. package/README.md +188 -16
  2. package/dist/adapters/claudeCliAdapter.d.ts +15 -0
  3. package/dist/adapters/claudeCliAdapter.d.ts.map +1 -1
  4. package/dist/adapters/claudeCliAdapter.js +36 -1
  5. package/dist/adapters/claudeCliAdapter.js.map +1 -1
  6. package/dist/adapters/claudeConfigDir.d.ts +40 -0
  7. package/dist/adapters/claudeConfigDir.d.ts.map +1 -0
  8. package/dist/adapters/claudeConfigDir.js +3 -0
  9. package/dist/adapters/claudeConfigDir.js.map +1 -0
  10. package/dist/adapters/claudeJsonStreamAdapter.d.ts +32 -0
  11. package/dist/adapters/claudeJsonStreamAdapter.d.ts.map +1 -1
  12. package/dist/adapters/claudeJsonStreamAdapter.js +89 -8
  13. package/dist/adapters/claudeJsonStreamAdapter.js.map +1 -1
  14. package/dist/adapters/claudePlatformFlags.d.ts +4 -4
  15. package/dist/adapters/claudePlatformFlags.js +4 -4
  16. package/dist/adapters/createAdapter.d.ts +8 -0
  17. package/dist/adapters/createAdapter.d.ts.map +1 -1
  18. package/dist/adapters/createAdapter.js +37 -0
  19. package/dist/adapters/createAdapter.js.map +1 -1
  20. package/dist/adapters/openCodeAdapter.d.ts +23 -0
  21. package/dist/adapters/openCodeAdapter.d.ts.map +1 -1
  22. package/dist/adapters/openCodeAdapter.js +84 -1
  23. package/dist/adapters/openCodeAdapter.js.map +1 -1
  24. package/dist/agentLogin/agentLogin.d.ts +15 -2
  25. package/dist/agentLogin/agentLogin.d.ts.map +1 -1
  26. package/dist/agentLogin/agentLogin.js +53 -16
  27. package/dist/agentLogin/agentLogin.js.map +1 -1
  28. package/dist/apiErrorRetry.d.ts +8 -3
  29. package/dist/apiErrorRetry.d.ts.map +1 -1
  30. package/dist/apiErrorRetry.js +36 -5
  31. package/dist/apiErrorRetry.js.map +1 -1
  32. package/dist/apiRetryKick.d.ts +9 -0
  33. package/dist/apiRetryKick.d.ts.map +1 -1
  34. package/dist/apiRetryKick.js +16 -0
  35. package/dist/apiRetryKick.js.map +1 -1
  36. package/dist/bot.d.ts.map +1 -1
  37. package/dist/bot.js +639 -24
  38. package/dist/bot.js.map +1 -1
  39. package/dist/cli/claudeProfiles.d.ts +42 -0
  40. package/dist/cli/claudeProfiles.d.ts.map +1 -0
  41. package/dist/cli/claudeProfiles.js +106 -0
  42. package/dist/cli/claudeProfiles.js.map +1 -0
  43. package/dist/cli.js +10 -0
  44. package/dist/cli.js.map +1 -1
  45. package/dist/connectors/jira/adf.d.ts +2 -0
  46. package/dist/connectors/jira/adf.d.ts.map +1 -1
  47. package/dist/connectors/jira/adf.js +5 -0
  48. package/dist/connectors/jira/adf.js.map +1 -1
  49. package/dist/connectors/jira/answerSink.d.ts +7 -0
  50. package/dist/connectors/jira/answerSink.d.ts.map +1 -1
  51. package/dist/connectors/jira/answerSink.js +24 -10
  52. package/dist/connectors/jira/answerSink.js.map +1 -1
  53. package/dist/connectors/jira/attachmentTool.d.ts +7 -0
  54. package/dist/connectors/jira/attachmentTool.d.ts.map +1 -1
  55. package/dist/connectors/jira/attachmentTool.js +16 -0
  56. package/dist/connectors/jira/attachmentTool.js.map +1 -1
  57. package/dist/connectors/jira/client.d.ts +32 -0
  58. package/dist/connectors/jira/client.d.ts.map +1 -1
  59. package/dist/connectors/jira/client.js +43 -5
  60. package/dist/connectors/jira/client.js.map +1 -1
  61. package/dist/connectors/jira/config.d.ts +3 -16
  62. package/dist/connectors/jira/config.d.ts.map +1 -1
  63. package/dist/connectors/jira/config.js +5 -32
  64. package/dist/connectors/jira/config.js.map +1 -1
  65. package/dist/connectors/jira/connector.d.ts +3 -0
  66. package/dist/connectors/jira/connector.d.ts.map +1 -1
  67. package/dist/connectors/jira/connector.js +70 -15
  68. package/dist/connectors/jira/connector.js.map +1 -1
  69. package/dist/connectors/jira/contextLedger.d.ts +1 -0
  70. package/dist/connectors/jira/contextLedger.d.ts.map +1 -1
  71. package/dist/connectors/jira/contextLedger.js +2 -0
  72. package/dist/connectors/jira/contextLedger.js.map +1 -1
  73. package/dist/connectors/jira/inbound.d.ts +15 -6
  74. package/dist/connectors/jira/inbound.d.ts.map +1 -1
  75. package/dist/connectors/jira/inbound.js +37 -22
  76. package/dist/connectors/jira/inbound.js.map +1 -1
  77. package/dist/connectors/jira/issueBlocks.d.ts +26 -3
  78. package/dist/connectors/jira/issueBlocks.d.ts.map +1 -1
  79. package/dist/connectors/jira/issueBlocks.js +104 -29
  80. package/dist/connectors/jira/issueBlocks.js.map +1 -1
  81. package/dist/connectors/jira/issueContext.d.ts +11 -5
  82. package/dist/connectors/jira/issueContext.d.ts.map +1 -1
  83. package/dist/connectors/jira/issueContext.js +23 -6
  84. package/dist/connectors/jira/issueContext.js.map +1 -1
  85. package/dist/connectors/jira/issueDelta.d.ts +3 -0
  86. package/dist/connectors/jira/issueDelta.d.ts.map +1 -1
  87. package/dist/connectors/jira/issueDelta.js +15 -6
  88. package/dist/connectors/jira/issueDelta.js.map +1 -1
  89. package/dist/connectors/jira/mediaPlaceholders.d.ts +2 -0
  90. package/dist/connectors/jira/mediaPlaceholders.d.ts.map +1 -1
  91. package/dist/connectors/jira/mediaPlaceholders.js +16 -3
  92. package/dist/connectors/jira/mediaPlaceholders.js.map +1 -1
  93. package/dist/connectors/jira/prompt.d.ts +2 -0
  94. package/dist/connectors/jira/prompt.d.ts.map +1 -1
  95. package/dist/connectors/jira/prompt.js +4 -1
  96. package/dist/connectors/jira/prompt.js.map +1 -1
  97. package/dist/connectors/jira/sessionKeyCodec.d.ts +2 -0
  98. package/dist/connectors/jira/sessionKeyCodec.d.ts.map +1 -1
  99. package/dist/connectors/jira/sessionKeyCodec.js +5 -0
  100. package/dist/connectors/jira/sessionKeyCodec.js.map +1 -1
  101. package/dist/connectors/jira/trigger.d.ts +4 -0
  102. package/dist/connectors/jira/trigger.d.ts.map +1 -1
  103. package/dist/connectors/jira/trigger.js +9 -1
  104. package/dist/connectors/jira/trigger.js.map +1 -1
  105. package/dist/connectors/jira/triggerLog.d.ts +4 -2
  106. package/dist/connectors/jira/triggerLog.d.ts.map +1 -1
  107. package/dist/connectors/jira/triggerLog.js +1 -1
  108. package/dist/connectors/jira/triggerLog.js.map +1 -1
  109. package/dist/connectors/jira/trustedGroup.d.ts +54 -0
  110. package/dist/connectors/jira/trustedGroup.d.ts.map +1 -0
  111. package/dist/connectors/jira/trustedGroup.js +98 -0
  112. package/dist/connectors/jira/trustedGroup.js.map +1 -0
  113. package/dist/connectors/telegram/commands/autoContinueLimits.d.ts +3 -0
  114. package/dist/connectors/telegram/commands/autoContinueLimits.d.ts.map +1 -1
  115. package/dist/connectors/telegram/commands/autoContinueLimits.js +15 -45
  116. package/dist/connectors/telegram/commands/autoContinueLimits.js.map +1 -1
  117. package/dist/connectors/telegram/commands/claudeAccounts.d.ts +58 -0
  118. package/dist/connectors/telegram/commands/claudeAccounts.d.ts.map +1 -0
  119. package/dist/connectors/telegram/commands/claudeAccounts.js +591 -0
  120. package/dist/connectors/telegram/commands/claudeAccounts.js.map +1 -0
  121. package/dist/connectors/telegram/commands/fallbackChain.d.ts +49 -0
  122. package/dist/connectors/telegram/commands/fallbackChain.d.ts.map +1 -0
  123. package/dist/connectors/telegram/commands/fallbackChain.js +624 -0
  124. package/dist/connectors/telegram/commands/fallbackChain.js.map +1 -0
  125. package/dist/connectors/telegram/commands/modelProviders.d.ts +23 -1
  126. package/dist/connectors/telegram/commands/modelProviders.d.ts.map +1 -1
  127. package/dist/connectors/telegram/commands/modelProviders.js +131 -6
  128. package/dist/connectors/telegram/commands/modelProviders.js.map +1 -1
  129. package/dist/i18n/de.d.ts.map +1 -1
  130. package/dist/i18n/de.js +137 -9
  131. package/dist/i18n/de.js.map +1 -1
  132. package/dist/i18n/en.d.ts.map +1 -1
  133. package/dist/i18n/en.js +137 -9
  134. package/dist/i18n/en.js.map +1 -1
  135. package/dist/i18n/es.d.ts.map +1 -1
  136. package/dist/i18n/es.js +137 -9
  137. package/dist/i18n/es.js.map +1 -1
  138. package/dist/i18n/fr.d.ts.map +1 -1
  139. package/dist/i18n/fr.js +137 -9
  140. package/dist/i18n/fr.js.map +1 -1
  141. package/dist/i18n/hi.d.ts.map +1 -1
  142. package/dist/i18n/hi.js +137 -9
  143. package/dist/i18n/hi.js.map +1 -1
  144. package/dist/i18n/ja.d.ts.map +1 -1
  145. package/dist/i18n/ja.js +137 -9
  146. package/dist/i18n/ja.js.map +1 -1
  147. package/dist/i18n/ka.d.ts.map +1 -1
  148. package/dist/i18n/ka.js +137 -9
  149. package/dist/i18n/ka.js.map +1 -1
  150. package/dist/i18n/pt.d.ts.map +1 -1
  151. package/dist/i18n/pt.js +137 -9
  152. package/dist/i18n/pt.js.map +1 -1
  153. package/dist/i18n/ru.d.ts.map +1 -1
  154. package/dist/i18n/ru.js +137 -9
  155. package/dist/i18n/ru.js.map +1 -1
  156. package/dist/i18n/uk.d.ts.map +1 -1
  157. package/dist/i18n/uk.js +137 -9
  158. package/dist/i18n/uk.js.map +1 -1
  159. package/dist/i18n/uz.d.ts.map +1 -1
  160. package/dist/i18n/uz.js +137 -9
  161. package/dist/i18n/uz.js.map +1 -1
  162. package/dist/i18n/zh.d.ts.map +1 -1
  163. package/dist/i18n/zh.js +137 -9
  164. package/dist/i18n/zh.js.map +1 -1
  165. package/dist/scheduler/mcpSurface.d.ts +8 -0
  166. package/dist/scheduler/mcpSurface.d.ts.map +1 -1
  167. package/dist/scheduler/mcpSurface.js +42 -2
  168. package/dist/scheduler/mcpSurface.js.map +1 -1
  169. package/dist/state.d.ts +172 -1
  170. package/dist/state.d.ts.map +1 -1
  171. package/dist/state.js +298 -0
  172. package/dist/state.js.map +1 -1
  173. package/dist/types.d.ts +7 -0
  174. package/dist/types.d.ts.map +1 -1
  175. package/dist/utils/autoContinueOnLimit.d.ts +7 -0
  176. package/dist/utils/autoContinueOnLimit.d.ts.map +1 -1
  177. package/dist/utils/autoContinueOnLimit.js +10 -0
  178. package/dist/utils/autoContinueOnLimit.js.map +1 -1
  179. package/dist/utils/claudeAccountPickerPlan.d.ts +85 -0
  180. package/dist/utils/claudeAccountPickerPlan.d.ts.map +1 -0
  181. package/dist/utils/claudeAccountPickerPlan.js +123 -0
  182. package/dist/utils/claudeAccountPickerPlan.js.map +1 -0
  183. package/dist/utils/claudeLimitSwitch.d.ts +40 -0
  184. package/dist/utils/claudeLimitSwitch.d.ts.map +1 -0
  185. package/dist/utils/claudeLimitSwitch.js +54 -0
  186. package/dist/utils/claudeLimitSwitch.js.map +1 -0
  187. package/dist/utils/claudeProfileUsageLines.d.ts +15 -0
  188. package/dist/utils/claudeProfileUsageLines.d.ts.map +1 -0
  189. package/dist/utils/claudeProfileUsageLines.js +42 -0
  190. package/dist/utils/claudeProfileUsageLines.js.map +1 -0
  191. package/dist/utils/claudeProfiles.d.ts +117 -0
  192. package/dist/utils/claudeProfiles.d.ts.map +1 -0
  193. package/dist/utils/claudeProfiles.js +285 -0
  194. package/dist/utils/claudeProfiles.js.map +1 -0
  195. package/dist/utils/claudeStreamJson.d.ts +13 -1
  196. package/dist/utils/claudeStreamJson.d.ts.map +1 -1
  197. package/dist/utils/claudeStreamJson.js +13 -0
  198. package/dist/utils/claudeStreamJson.js.map +1 -1
  199. package/dist/utils/claudeUsage.d.ts +209 -0
  200. package/dist/utils/claudeUsage.d.ts.map +1 -0
  201. package/dist/utils/claudeUsage.js +413 -0
  202. package/dist/utils/claudeUsage.js.map +1 -0
  203. package/dist/utils/claudeUsageRefresher.d.ts +44 -0
  204. package/dist/utils/claudeUsageRefresher.d.ts.map +1 -0
  205. package/dist/utils/claudeUsageRefresher.js +95 -0
  206. package/dist/utils/claudeUsageRefresher.js.map +1 -0
  207. package/dist/utils/fallbackBridge.d.ts +32 -0
  208. package/dist/utils/fallbackBridge.d.ts.map +1 -0
  209. package/dist/utils/fallbackBridge.js +62 -0
  210. package/dist/utils/fallbackBridge.js.map +1 -0
  211. package/dist/utils/fallbackChain.d.ts +299 -0
  212. package/dist/utils/fallbackChain.d.ts.map +1 -0
  213. package/dist/utils/fallbackChain.js +542 -0
  214. package/dist/utils/fallbackChain.js.map +1 -0
  215. package/dist/utils/jsonStreamHost.d.ts +14 -3
  216. package/dist/utils/jsonStreamHost.d.ts.map +1 -1
  217. package/dist/utils/jsonStreamHost.js +26 -5
  218. package/dist/utils/jsonStreamHost.js.map +1 -1
  219. package/dist/utils/modelRecentPlan.d.ts +56 -0
  220. package/dist/utils/modelRecentPlan.d.ts.map +1 -0
  221. package/dist/utils/modelRecentPlan.js +107 -0
  222. package/dist/utils/modelRecentPlan.js.map +1 -0
  223. package/dist/utils/threadStatusReport.d.ts +25 -1
  224. package/dist/utils/threadStatusReport.d.ts.map +1 -1
  225. package/dist/utils/threadStatusReport.js +24 -1
  226. package/dist/utils/threadStatusReport.js.map +1 -1
  227. package/package.json +1 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"claudeUsage.d.ts","sourceRoot":"","sources":["../../src/utils/claudeUsage.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,413 @@
1
+ "use strict";
2
+ /**
3
+ * @description Per-profile Claude USAGE — how much of each subscription window an account profile
4
+ * (`utils/claudeProfiles.ts`) has used, and which profile a new process should run on.
5
+ *
6
+ * Two sources feed one snapshot per profile (`ClaudeProfileRecord.usage`):
7
+ * - the OAuth usage endpoint (`GET https://api.anthropic.com/api/oauth/usage`, the profile's own access
8
+ * token off its `.credentials.json`), polled by the bot (`claudeUsageRefresher.ts`) and on demand — its
9
+ * `limits[]` carry the three windows: `session` (five hours), `weekly_all` (seven days, every model) and
10
+ * `weekly_scoped` (seven days, ONE model — Fable; `scope.model.display_name`), measured on 2026-10-12;
11
+ * - the `rate_limit_event` frames of a json-stream session, one per API request, whose `unifiedWindows`
12
+ * carry the same windows under their CLI names (`five_hour`, `seven_day`, `seven_day_overage_included`
13
+ * — the last one IS the Fable window: same utilization and reset instant as the endpoint's scoped limit).
14
+ *
15
+ * Token refresh is the CLI's job: a token past its `expiresAt` is never used (nor refreshed here) — the
16
+ * snapshot is marked stale and the next CLI run renews it. The token itself is never logged or returned.
17
+ *
18
+ * Pure except {@link readClaudeOAuthToken} (one file read) and {@link fetchClaudeUsage} (one GET through an
19
+ * injectable `fetch`), so the rest is unit-tested without the network.
20
+ */
21
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
22
+ if (k2 === undefined) k2 = k;
23
+ var desc = Object.getOwnPropertyDescriptor(m, k);
24
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
25
+ desc = { enumerable: true, get: function() { return m[k]; } };
26
+ }
27
+ Object.defineProperty(o, k2, desc);
28
+ }) : (function(o, m, k, k2) {
29
+ if (k2 === undefined) k2 = k;
30
+ o[k2] = m[k];
31
+ }));
32
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
33
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
34
+ }) : function(o, v) {
35
+ o["default"] = v;
36
+ });
37
+ var __importStar = (this && this.__importStar) || (function () {
38
+ var ownKeys = function(o) {
39
+ ownKeys = Object.getOwnPropertyNames || function (o) {
40
+ var ar = [];
41
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
42
+ return ar;
43
+ };
44
+ return ownKeys(o);
45
+ };
46
+ return function (mod) {
47
+ if (mod && mod.__esModule) return mod;
48
+ var result = {};
49
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
50
+ __setModuleDefault(result, mod);
51
+ return result;
52
+ };
53
+ })();
54
+ Object.defineProperty(exports, "__esModule", { value: true });
55
+ exports.englishRelativeResetWords = exports.claudeUsageBucketKinds = exports.claudeUsageFetchTimeoutMs = exports.claudeUsageEndpoint = void 0;
56
+ exports.readClaudeOAuthToken = readClaudeOAuthToken;
57
+ exports.checkIsClaudeTokenExpired = checkIsClaudeTokenExpired;
58
+ exports.fetchClaudeUsage = fetchClaudeUsage;
59
+ exports.parseClaudeUsageResponse = parseClaudeUsageResponse;
60
+ exports.buildBucketsFromRateLimitWindows = buildBucketsFromRateLimitWindows;
61
+ exports.mergeClaudeUsageSnapshot = mergeClaudeUsageSnapshot;
62
+ exports.markClaudeUsageSnapshotStale = markClaudeUsageSnapshotStale;
63
+ exports.checkClaudeUsageBucketsChanged = checkClaudeUsageBucketsChanged;
64
+ exports.getClaudeUsageBucket = getClaudeUsageBucket;
65
+ exports.checkIsScopedWeeklyModel = checkIsScopedWeeklyModel;
66
+ exports.getRelevantClaudeUsageKinds = getRelevantClaudeUsageKinds;
67
+ exports.buildClaudeProfilesReport = buildClaudeProfilesReport;
68
+ exports.buildClaudeProfileUsageViews = buildClaudeProfileUsageViews;
69
+ exports.readClaudeProfileRecordsFromStateFile = readClaudeProfileRecordsFromStateFile;
70
+ exports.formatClaudeUsageResetAt = formatClaudeUsageResetAt;
71
+ exports.formatClaudeUsageRelativeReset = formatClaudeUsageRelativeReset;
72
+ exports.formatClaudeUsageBucket = formatClaudeUsageBucket;
73
+ const fs = __importStar(require("fs"));
74
+ const path = __importStar(require("path"));
75
+ const claudeProfiles_1 = require("./claudeProfiles");
76
+ exports.claudeUsageEndpoint = 'https://api.anthropic.com/api/oauth/usage';
77
+ /** The OAuth beta header the CLI sends with its subscription token. */
78
+ const claudeOAuthBetaHeader = 'oauth-2025-04-20';
79
+ exports.claudeUsageFetchTimeoutMs = 15_000;
80
+ exports.claudeUsageBucketKinds = ['session', 'weekly_all', 'weekly_scoped'];
81
+ /**
82
+ * @description The subscription access token of a profile, off `<configDir>/.credentials.json`
83
+ * (`~/.claude/.credentials.json` for the default profile). `null` when the file or the OAuth entry is absent —
84
+ * a logged-out directory. The caller never logs the result.
85
+ */
86
+ function readClaudeOAuthToken(configDir, homeClaudeDir = (0, claudeProfiles_1.resolveHomeClaudeDir)()) {
87
+ const file = path.join(configDir ?? homeClaudeDir, '.credentials.json');
88
+ let parsed;
89
+ try {
90
+ parsed = JSON.parse(fs.readFileSync(file, 'utf8'));
91
+ }
92
+ catch {
93
+ return null;
94
+ }
95
+ const oauth = checkIsRecord(parsed) && checkIsRecord(parsed.claudeAiOauth) ? parsed.claudeAiOauth : null;
96
+ if (!oauth || typeof oauth.accessToken !== 'string' || oauth.accessToken === '')
97
+ return null;
98
+ return { accessToken: oauth.accessToken, expiresAtMs: typeof oauth.expiresAt === 'number' ? oauth.expiresAt : null };
99
+ }
100
+ /** Whether the token is past its expiry at `nowMs` (a token without expiry counts as live). */
101
+ function checkIsClaudeTokenExpired(token, nowMs) {
102
+ return token.expiresAtMs !== null && token.expiresAtMs <= nowMs;
103
+ }
104
+ /**
105
+ * @description One GET of the usage endpoint with the profile's token. A 401/403 is an auth error (the
106
+ * token is no longer accepted — the CLI's next run renews it); anything else is a plain failure. Never
107
+ * throws; never includes the token in the result.
108
+ */
109
+ async function fetchClaudeUsage(token, options = {}) {
110
+ const fetchImpl = options.fetchImpl ?? globalThis.fetch;
111
+ const controller = new AbortController();
112
+ const timer = setTimeout(() => controller.abort(), options.timeoutMs ?? exports.claudeUsageFetchTimeoutMs);
113
+ try {
114
+ const response = await fetchImpl(exports.claudeUsageEndpoint, {
115
+ headers: { Authorization: `Bearer ${token}`, 'anthropic-beta': claudeOAuthBetaHeader, Accept: 'application/json' },
116
+ signal: controller.signal,
117
+ });
118
+ if (response.status === 401 || response.status === 403)
119
+ return { ok: false, error: `http ${response.status}`, isAuthError: true };
120
+ if (response.status !== 200)
121
+ return { ok: false, error: `http ${response.status}`, isAuthError: false };
122
+ const buckets = parseClaudeUsageResponse(await response.json());
123
+ if (buckets.length === 0)
124
+ return { ok: false, error: 'no limits in the response', isAuthError: false };
125
+ return { ok: true, buckets };
126
+ }
127
+ catch (e) {
128
+ const reason = e instanceof Error ? (e.name === 'AbortError' ? 'timeout' : e.message) : String(e);
129
+ return { ok: false, error: reason.slice(0, 120), isAuthError: false };
130
+ }
131
+ finally {
132
+ clearTimeout(timer);
133
+ }
134
+ }
135
+ /**
136
+ * @description The buckets of a usage response. Reads `limits[]` (`kind` session / weekly_all /
137
+ * weekly_scoped, `percent`, `resets_at`, `scope.model.display_name`); a response without it (an older
138
+ * shape) falls back to the top-level `five_hour` / `seven_day` objects (`utilization` already 0..100).
139
+ * Unknown kinds are dropped, so a window the API adds later never breaks a reader.
140
+ */
141
+ function parseClaudeUsageResponse(body) {
142
+ if (!checkIsRecord(body))
143
+ return [];
144
+ if (Array.isArray(body.limits)) {
145
+ const buckets = [];
146
+ for (const limit of body.limits) {
147
+ if (!checkIsRecord(limit))
148
+ continue;
149
+ const kind = readBucketKind(limit.kind);
150
+ if (!kind || typeof limit.percent !== 'number')
151
+ continue;
152
+ const scope = checkIsRecord(limit.scope) && checkIsRecord(limit.scope.model) ? limit.scope.model : null;
153
+ buckets.push({
154
+ kind,
155
+ percent: clampPercent(limit.percent),
156
+ resetsAt: readIso(limit.resets_at),
157
+ scopeModel: scope && typeof scope.display_name === 'string' ? scope.display_name : null,
158
+ });
159
+ }
160
+ if (buckets.length > 0)
161
+ return buckets;
162
+ }
163
+ const buckets = [];
164
+ for (const [field, kind] of [['five_hour', 'session'], ['seven_day', 'weekly_all']]) {
165
+ const window = body[field];
166
+ if (!checkIsRecord(window) || typeof window.utilization !== 'number')
167
+ continue;
168
+ buckets.push({ kind, percent: clampPercent(window.utilization), resetsAt: readIso(window.resets_at), scopeModel: null });
169
+ }
170
+ return buckets;
171
+ }
172
+ function readBucketKind(value) {
173
+ return value === 'session' || value === 'weekly_all' || value === 'weekly_scoped' ? value : null;
174
+ }
175
+ /** The CLI's window names → bucket kinds; `seven_day_overage_included` is the Fable window (see the module doc). */
176
+ const rateLimitWindowKinds = {
177
+ five_hour: { kind: 'session', scopeModel: null },
178
+ seven_day: { kind: 'weekly_all', scopeModel: null },
179
+ seven_day_overage_included: { kind: 'weekly_scoped', scopeModel: 'Fable' },
180
+ };
181
+ /** The buckets a frame's windows carry (unknown window names are dropped). */
182
+ function buildBucketsFromRateLimitWindows(windows) {
183
+ const buckets = [];
184
+ for (const window of windows) {
185
+ const mapping = rateLimitWindowKinds[window.name];
186
+ if (!mapping)
187
+ continue;
188
+ buckets.push({
189
+ kind: mapping.kind,
190
+ percent: clampPercent(window.utilization * 100),
191
+ resetsAt: window.resetsAtMs === null ? null : new Date(window.resetsAtMs).toISOString(),
192
+ scopeModel: mapping.scopeModel,
193
+ });
194
+ }
195
+ return buckets;
196
+ }
197
+ // ── the snapshot ──
198
+ /**
199
+ * @description Fold fresh buckets into a profile's snapshot. The endpoint answers with EVERY window, so an
200
+ * `api` read replaces the set; a frame carries only the windows the request touched, so a `stream` read
201
+ * upserts those and keeps the rest. Either way the snapshot is fresh (not stale) afterwards.
202
+ */
203
+ function mergeClaudeUsageSnapshot(previous, incoming, source, nowMs) {
204
+ let buckets;
205
+ if (source === 'api' || !previous) {
206
+ buckets = [...incoming];
207
+ }
208
+ else {
209
+ buckets = previous.buckets.filter((bucket) => !incoming.some((fresh) => fresh.kind === bucket.kind));
210
+ buckets.push(...incoming);
211
+ }
212
+ buckets.sort((a, b) => exports.claudeUsageBucketKinds.indexOf(a.kind) - exports.claudeUsageBucketKinds.indexOf(b.kind));
213
+ return { fetchedAt: new Date(nowMs).toISOString(), source, buckets };
214
+ }
215
+ /** The snapshot kept as it was, marked stale with the reason (a failed or impossible poll). */
216
+ function markClaudeUsageSnapshotStale(previous, error, nowMs) {
217
+ return { fetchedAt: previous?.fetchedAt ?? new Date(nowMs).toISOString(), source: previous?.source ?? 'api', buckets: previous?.buckets ?? [], isStale: true, error };
218
+ }
219
+ /** Whether `next` says anything `previous` did not — a stream frame per API request must not rewrite state.json each time. */
220
+ function checkClaudeUsageBucketsChanged(previous, next) {
221
+ if (!previous || previous.isStale)
222
+ return true;
223
+ return next.some((bucket) => {
224
+ const old = previous.buckets.find((candidate) => candidate.kind === bucket.kind);
225
+ return !old || old.percent !== bucket.percent || old.resetsAt !== bucket.resetsAt;
226
+ });
227
+ }
228
+ function getClaudeUsageBucket(snapshot, kind) {
229
+ return snapshot?.buckets.find((bucket) => bucket.kind === kind) ?? null;
230
+ }
231
+ // ── which profile for a model ──
232
+ /** Whether a model name (`fable`, `claude-fable-5-1`, …) runs on the scoped weekly window. */
233
+ function checkIsScopedWeeklyModel(model) {
234
+ return model !== null && /fable/i.test(model);
235
+ }
236
+ /** The windows that bound a launch of `model`: the session window plus the weekly one the model drains. */
237
+ function getRelevantClaudeUsageKinds(model) {
238
+ return ['session', checkIsScopedWeeklyModel(model) ? 'weekly_scoped' : 'weekly_all'];
239
+ }
240
+ /**
241
+ * @description Rank the profiles for a launch of `model`: a profile that is signed out, marked limited
242
+ * (`limitedUntil` in the future) or at 100 % on a relevant window is out; the rest are ordered by headroom on
243
+ * the relevant windows (most first; unknown usage ranks after any known one; a tie goes to the lower total of
244
+ * the relevant percentages). The first in that order is `recommended`. The entries keep the input order.
245
+ */
246
+ function buildClaudeProfilesReport(profiles, model, nowMs) {
247
+ const relevantBuckets = getRelevantClaudeUsageKinds(model);
248
+ const entries = profiles.map((profile) => {
249
+ const relevant = relevantBuckets
250
+ .map((kind) => getClaudeUsageBucket(profile.usage, kind))
251
+ .filter((bucket) => bucket !== null);
252
+ const maxPercent = relevant.length === 0 ? null : Math.max(...relevant.map((bucket) => bucket.percent));
253
+ const isLimited = profile.limitedUntil !== null && Date.parse(profile.limitedUntil) > nowMs;
254
+ const isEligible = profile.loggedIn !== false && !isLimited && (maxPercent === null || maxPercent < 100);
255
+ return {
256
+ name: profile.name,
257
+ configDir: profile.configDir,
258
+ email: profile.email,
259
+ kind: (0, claudeProfiles_1.getClaudeAccountKind)(profile.subscriptionType),
260
+ subscriptionType: profile.subscriptionType,
261
+ loggedIn: profile.loggedIn ?? null,
262
+ buckets: profile.usage?.buckets ?? [],
263
+ usageFetchedAt: profile.usage?.fetchedAt ?? null,
264
+ isUsageStale: profile.usage?.isStale === true,
265
+ limitedUntil: profile.limitedUntil,
266
+ isEligible,
267
+ headroomPercent: maxPercent === null ? null : 100 - maxPercent,
268
+ isRecommended: false,
269
+ };
270
+ });
271
+ const ranked = entries
272
+ .filter((entry) => entry.isEligible)
273
+ .sort((a, b) => {
274
+ if (a.headroomPercent === null || b.headroomPercent === null) {
275
+ return (a.headroomPercent === null ? 1 : 0) - (b.headroomPercent === null ? 1 : 0);
276
+ }
277
+ if (a.headroomPercent !== b.headroomPercent)
278
+ return b.headroomPercent - a.headroomPercent;
279
+ return sumRelevantPercent(a, relevantBuckets) - sumRelevantPercent(b, relevantBuckets);
280
+ });
281
+ const recommended = ranked[0] ?? null;
282
+ if (recommended)
283
+ recommended.isRecommended = true;
284
+ return { model, relevantBuckets, recommended: recommended?.name ?? null, profiles: entries };
285
+ }
286
+ function sumRelevantPercent(entry, kinds) {
287
+ return entry.buckets.filter((bucket) => kinds.includes(bucket.kind)).reduce((sum, bucket) => sum + bucket.percent, 0);
288
+ }
289
+ /**
290
+ * @description The ranking's view of every profile off the registry: `default` (its hidden record, when the
291
+ * bot has written one) first, then the added profiles in creation order. Shared by the bot (live state) and
292
+ * the CLI (`state.json` read directly).
293
+ */
294
+ function buildClaudeProfileUsageViews(input) {
295
+ // A `default` the operator signed out through /accounts stays out of every ranking until it is signed in again.
296
+ const isDefaultRemoved = input.records.default?.isRemoved === true;
297
+ const toView = (name, record) => ({
298
+ name,
299
+ configDir: (0, claudeProfiles_1.resolveClaudeProfileDir)(input.dataDir, name),
300
+ loggedIn: record?.loggedIn,
301
+ email: record?.email ?? null,
302
+ subscriptionType: record?.subscriptionType ?? null,
303
+ usage: record?.usage,
304
+ limitedUntil: record?.limitedUntil ?? null,
305
+ });
306
+ const added = Object.entries(input.records)
307
+ .filter(([name]) => name !== 'default')
308
+ .sort(([, a], [, b]) => a.createdAt.localeCompare(b.createdAt));
309
+ return [...(isDefaultRemoved ? [] : [toView('default', input.records.default)]), ...added.map(([name, record]) => toView(name, record))];
310
+ }
311
+ /** The profile registry as `state.json` holds it — the CLI's read, no `StateStore` (which would migrate and lock). */
312
+ function readClaudeProfileRecordsFromStateFile(dataDir) {
313
+ let parsed;
314
+ try {
315
+ parsed = JSON.parse(fs.readFileSync(path.join(dataDir, 'state.json'), 'utf8'));
316
+ }
317
+ catch {
318
+ return {};
319
+ }
320
+ const records = checkIsRecord(parsed) && checkIsRecord(parsed.claudeProfiles) ? parsed.claudeProfiles : {};
321
+ const result = {};
322
+ for (const [name, record] of Object.entries(records)) {
323
+ if (checkIsRecord(record) && typeof record.createdAt === 'string')
324
+ result[name] = record;
325
+ }
326
+ return result;
327
+ }
328
+ // ── rendering ──
329
+ /**
330
+ * @description A reset instant for a human, in the instance zone: `16:00` when it is today there, `Sat 00:00`
331
+ * within the week, `17.10 00:00` beyond. The weekday is English on purpose (a three-letter token every locale
332
+ * reads; the surrounding line is localised).
333
+ */
334
+ function formatClaudeUsageResetAt(resetsAt, timezone, nowMs) {
335
+ if (resetsAt === null)
336
+ return '?';
337
+ const exact = Date.parse(resetsAt);
338
+ if (Number.isNaN(exact))
339
+ return '?';
340
+ // Windows reset on a minute boundary; the endpoint's instant carries jitter below a second (`13:00:00.40`,
341
+ // once `12:59:59.9`), which must not read as a minute earlier.
342
+ const at = Math.round(exact / 60_000) * 60_000;
343
+ const read = (options, instant) => new Intl.DateTimeFormat('en-GB', { timeZone: timezone, hourCycle: 'h23', ...options }).format(instant);
344
+ const time = read({ hour: '2-digit', minute: '2-digit' }, at);
345
+ const dayOf = (instant) => read({ year: 'numeric', month: '2-digit', day: '2-digit' }, instant);
346
+ if (dayOf(at) === dayOf(nowMs))
347
+ return time;
348
+ if (at - nowMs < 6 * 24 * 3_600_000)
349
+ return `${read({ weekday: 'short' }, at)} ${time}`;
350
+ return `${read({ day: '2-digit' }, at)}.${read({ month: '2-digit' }, at)} ${time}`;
351
+ }
352
+ /** English words, the CLI's (the bot passes its localised ones). */
353
+ exports.englishRelativeResetWords = { pattern: '🔄 in {time}', day: 'd', hour: 'h', minute: 'm' };
354
+ /**
355
+ * @description A reset instant as a time from now: `🔄 in 2d 1h`, `🔄 in 2h`, `🔄 in 30m`. The two largest
356
+ * units at most, minutes only under an hour: from a day up it is days + hours (hours dropped when zero), from
357
+ * an hour up whole hours (rounded), below that minutes (at least one). An instant already past reads as
358
+ * `🔄 in 1m` (the window is about to roll over). `?` for a missing or unparseable instant.
359
+ */
360
+ function formatClaudeUsageRelativeReset(resetsAt, nowMs, words = exports.englishRelativeResetWords) {
361
+ if (resetsAt === null)
362
+ return '?';
363
+ const at = Date.parse(resetsAt);
364
+ if (Number.isNaN(at))
365
+ return '?';
366
+ const totalMinutes = Math.max(1, Math.round((at - nowMs) / 60_000));
367
+ let time;
368
+ if (totalMinutes < 60) {
369
+ time = `${totalMinutes}${words.minute}`;
370
+ }
371
+ else if (totalMinutes < 24 * 60) {
372
+ // 23h40m rounds to 24h: that is a day.
373
+ time = totalMinutes / 60 >= 23.5 ? `1${words.day}` : `${Math.round(totalMinutes / 60)}${words.hour}`;
374
+ }
375
+ else {
376
+ let days = Math.floor(totalMinutes / 1440);
377
+ let hours = Math.round((totalMinutes % 1440) / 60);
378
+ if (hours === 24) {
379
+ days += 1;
380
+ hours = 0;
381
+ }
382
+ time = hours === 0 ? `${days}${words.day}` : `${days}${words.day} ${hours}${words.hour}`;
383
+ }
384
+ return words.pattern.replace('{time}', time);
385
+ }
386
+ /**
387
+ * @description `81% 🔄 in 2h` for a bucket, `—` for a missing one. A bucket whose reset is unknown shows
388
+ * `fallbackResetsAt` instead (the session window's reset is often missing while the weekly one is known);
389
+ * with neither it is the bare percent — a «?» after a number would read as a doubt about the number.
390
+ */
391
+ function formatClaudeUsageBucket(bucket, nowMs, options = {}) {
392
+ if (bucket === null)
393
+ return '—';
394
+ const known = bucket.resetsAt !== null && !Number.isNaN(Date.parse(bucket.resetsAt));
395
+ const resetsAt = known ? bucket.resetsAt : options.fallbackResetsAt ?? null;
396
+ if (resetsAt === null || Number.isNaN(Date.parse(resetsAt)))
397
+ return `${bucket.percent}%`;
398
+ return `${bucket.percent}% ${formatClaudeUsageRelativeReset(resetsAt, nowMs, options.words)}`;
399
+ }
400
+ // ── small readers ──
401
+ function checkIsRecord(value) {
402
+ return typeof value === 'object' && value !== null && !Array.isArray(value);
403
+ }
404
+ function readIso(value) {
405
+ if (typeof value !== 'string')
406
+ return null;
407
+ const ms = Date.parse(value);
408
+ return Number.isNaN(ms) ? null : new Date(ms).toISOString();
409
+ }
410
+ function clampPercent(value) {
411
+ return Math.max(0, Math.min(100, Math.round(value)));
412
+ }
413
+ //# sourceMappingURL=claudeUsage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"claudeUsage.js","sourceRoot":"","sources":["../../src/utils/claudeUsage.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;GAkBG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAyDH,oDAWC;AAGD,8DAEC;AAeD,4CAuBC;AAQD,4DAyBC;AA0BD,4EAaC;AASD,4DAeC;AAGD,oEAEC;AAGD,wEAMC;AAED,oDAEC;AAKD,4DAEC;AAGD,kEAEC;AAiDD,8DAqCC;AAWD,oEAoBC;AAGD,sFAaC;AASD,4DAcC;AAmBD,wEAkBC;AAOD,0DAUC;AA7bD,uCAAyB;AACzB,2CAA6B;AAE7B,qDAA+H;AAElH,QAAA,mBAAmB,GAAG,2CAA2C,CAAC;AAE/E,uEAAuE;AACvE,MAAM,qBAAqB,GAAG,kBAAkB,CAAC;AAEpC,QAAA,yBAAyB,GAAG,MAAM,CAAC;AAKnC,QAAA,sBAAsB,GAAqC,CAAC,SAAS,EAAE,YAAY,EAAE,eAAe,CAAC,CAAC;AAmCnH;;;;GAIG;AACH,SAAgB,oBAAoB,CAAC,SAAwB,EAAE,gBAAwB,IAAA,qCAAoB,GAAE;IAC3G,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,IAAI,aAAa,EAAE,mBAAmB,CAAC,CAAC;IACxE,IAAI,MAAe,CAAC;IACpB,IAAI,CAAC;QACH,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC;IACrD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;IACD,MAAM,KAAK,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,aAAa,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC;IACzG,IAAI,CAAC,KAAK,IAAI,OAAO,KAAK,CAAC,WAAW,KAAK,QAAQ,IAAI,KAAK,CAAC,WAAW,KAAK,EAAE;QAAE,OAAO,IAAI,CAAC;IAC7F,OAAO,EAAE,WAAW,EAAE,KAAK,CAAC,WAAW,EAAE,WAAW,EAAE,OAAO,KAAK,CAAC,SAAS,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;AACvH,CAAC;AAED,+FAA+F;AAC/F,SAAgB,yBAAyB,CAAC,KAAuB,EAAE,KAAa;IAC9E,OAAO,KAAK,CAAC,WAAW,KAAK,IAAI,IAAI,KAAK,CAAC,WAAW,IAAI,KAAK,CAAC;AAClE,CAAC;AAUD;;;;GAIG;AACI,KAAK,UAAU,gBAAgB,CACpC,KAAa,EACb,UAAyD,EAAE;IAE3D,MAAM,SAAS,GAAc,OAAO,CAAC,SAAS,IAAK,UAAU,CAAC,KAA8B,CAAC;IAC7F,MAAM,UAAU,GAAG,IAAI,eAAe,EAAE,CAAC;IACzC,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC,KAAK,EAAE,EAAE,OAAO,CAAC,SAAS,IAAI,iCAAyB,CAAC,CAAC;IACnG,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,MAAM,SAAS,CAAC,2BAAmB,EAAE;YACpD,OAAO,EAAE,EAAE,aAAa,EAAE,UAAU,KAAK,EAAE,EAAE,gBAAgB,EAAE,qBAAqB,EAAE,MAAM,EAAE,kBAAkB,EAAE;YAClH,MAAM,EAAE,UAAU,CAAC,MAAM;SAC1B,CAAC,CAAC;QACH,IAAI,QAAQ,CAAC,MAAM,KAAK,GAAG,IAAI,QAAQ,CAAC,MAAM,KAAK,GAAG;YAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,QAAQ,QAAQ,CAAC,MAAM,EAAE,EAAE,WAAW,EAAE,IAAI,EAAE,CAAC;QAClI,IAAI,QAAQ,CAAC,MAAM,KAAK,GAAG;YAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,QAAQ,QAAQ,CAAC,MAAM,EAAE,EAAE,WAAW,EAAE,KAAK,EAAE,CAAC;QACxG,MAAM,OAAO,GAAG,wBAAwB,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC;QAChE,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,2BAA2B,EAAE,WAAW,EAAE,KAAK,EAAE,CAAC;QACvG,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;IAC/B,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,MAAM,MAAM,GAAG,CAAC,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,KAAK,YAAY,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;QAClG,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,WAAW,EAAE,KAAK,EAAE,CAAC;IACxE,CAAC;YAAS,CAAC;QACT,YAAY,CAAC,KAAK,CAAC,CAAC;IACtB,CAAC;AACH,CAAC;AAED;;;;;GAKG;AACH,SAAgB,wBAAwB,CAAC,IAAa;IACpD,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC;QAAE,OAAO,EAAE,CAAC;IACpC,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;QAC/B,MAAM,OAAO,GAAwB,EAAE,CAAC;QACxC,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;YAChC,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC;gBAAE,SAAS;YACpC,MAAM,IAAI,GAAG,cAAc,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;YACxC,IAAI,CAAC,IAAI,IAAI,OAAO,KAAK,CAAC,OAAO,KAAK,QAAQ;gBAAE,SAAS;YACzD,MAAM,KAAK,GAAG,aAAa,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,aAAa,CAAC,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC;YACxG,OAAO,CAAC,IAAI,CAAC;gBACX,IAAI;gBACJ,OAAO,EAAE,YAAY,CAAC,KAAK,CAAC,OAAO,CAAC;gBACpC,QAAQ,EAAE,OAAO,CAAC,KAAK,CAAC,SAAS,CAAC;gBAClC,UAAU,EAAE,KAAK,IAAI,OAAO,KAAK,CAAC,YAAY,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC,CAAC,IAAI;aACxF,CAAC,CAAC;QACL,CAAC;QACD,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC;YAAE,OAAO,OAAO,CAAC;IACzC,CAAC;IACD,MAAM,OAAO,GAAwB,EAAE,CAAC;IACxC,KAAK,MAAM,CAAC,KAAK,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC,WAAW,EAAE,SAAS,CAAC,EAAE,CAAC,WAAW,EAAE,YAAY,CAAC,CAAU,EAAE,CAAC;QAC7F,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC;QAC3B,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,OAAO,MAAM,CAAC,WAAW,KAAK,QAAQ;YAAE,SAAS;QAC/E,OAAO,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,YAAY,CAAC,MAAM,CAAC,WAAW,CAAC,EAAE,QAAQ,EAAE,OAAO,CAAC,MAAM,CAAC,SAAS,CAAC,EAAE,UAAU,EAAE,IAAI,EAAE,CAAC,CAAC;IAC3H,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,SAAS,cAAc,CAAC,KAAc;IACpC,OAAO,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,YAAY,IAAI,KAAK,KAAK,eAAe,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC;AACnG,CAAC;AAcD,oHAAoH;AACpH,MAAM,oBAAoB,GAA+E;IACvG,SAAS,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,UAAU,EAAE,IAAI,EAAE;IAChD,SAAS,EAAE,EAAE,IAAI,EAAE,YAAY,EAAE,UAAU,EAAE,IAAI,EAAE;IACnD,0BAA0B,EAAE,EAAE,IAAI,EAAE,eAAe,EAAE,UAAU,EAAE,OAAO,EAAE;CAC3E,CAAC;AAEF,8EAA8E;AAC9E,SAAgB,gCAAgC,CAAC,OAAyC;IACxF,MAAM,OAAO,GAAwB,EAAE,CAAC;IACxC,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;QAC7B,MAAM,OAAO,GAAG,oBAAoB,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QAClD,IAAI,CAAC,OAAO;YAAE,SAAS;QACvB,OAAO,CAAC,IAAI,CAAC;YACX,IAAI,EAAE,OAAO,CAAC,IAAI;YAClB,OAAO,EAAE,YAAY,CAAC,MAAM,CAAC,WAAW,GAAG,GAAG,CAAC;YAC/C,QAAQ,EAAE,MAAM,CAAC,UAAU,KAAK,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,WAAW,EAAE;YACvF,UAAU,EAAE,OAAO,CAAC,UAAU;SAC/B,CAAC,CAAC;IACL,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,qBAAqB;AAErB;;;;GAIG;AACH,SAAgB,wBAAwB,CACtC,QAAyC,EACzC,QAAsC,EACtC,MAAqC,EACrC,KAAa;IAEb,IAAI,OAA4B,CAAC;IACjC,IAAI,MAAM,KAAK,KAAK,IAAI,CAAC,QAAQ,EAAE,CAAC;QAClC,OAAO,GAAG,CAAC,GAAG,QAAQ,CAAC,CAAC;IAC1B,CAAC;SAAM,CAAC;QACN,OAAO,GAAG,QAAQ,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,KAAK,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC;QACrG,OAAO,CAAC,IAAI,CAAC,GAAG,QAAQ,CAAC,CAAC;IAC5B,CAAC;IACD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,8BAAsB,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,8BAAsB,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;IACxG,OAAO,EAAE,SAAS,EAAE,IAAI,IAAI,CAAC,KAAK,CAAC,CAAC,WAAW,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC;AACvE,CAAC;AAED,+FAA+F;AAC/F,SAAgB,4BAA4B,CAAC,QAAyC,EAAE,KAAa,EAAE,KAAa;IAClH,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,SAAS,IAAI,IAAI,IAAI,CAAC,KAAK,CAAC,CAAC,WAAW,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,IAAI,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,OAAO,IAAI,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC;AACxK,CAAC;AAED,8HAA8H;AAC9H,SAAgB,8BAA8B,CAAC,QAAyC,EAAE,IAAkC;IAC1H,IAAI,CAAC,QAAQ,IAAI,QAAQ,CAAC,OAAO;QAAE,OAAO,IAAI,CAAC;IAC/C,OAAO,IAAI,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,EAAE;QAC1B,MAAM,GAAG,GAAG,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,SAAS,CAAC,IAAI,KAAK,MAAM,CAAC,IAAI,CAAC,CAAC;QACjF,OAAO,CAAC,GAAG,IAAI,GAAG,CAAC,OAAO,KAAK,MAAM,CAAC,OAAO,IAAI,GAAG,CAAC,QAAQ,KAAK,MAAM,CAAC,QAAQ,CAAC;IACpF,CAAC,CAAC,CAAC;AACL,CAAC;AAED,SAAgB,oBAAoB,CAAC,QAAyC,EAAE,IAA2B;IACzG,OAAO,QAAQ,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,KAAK,IAAI,CAAC,IAAI,IAAI,CAAC;AAC1E,CAAC;AAED,kCAAkC;AAElC,8FAA8F;AAC9F,SAAgB,wBAAwB,CAAC,KAAoB;IAC3D,OAAO,KAAK,KAAK,IAAI,IAAI,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;AAChD,CAAC;AAED,2GAA2G;AAC3G,SAAgB,2BAA2B,CAAC,KAAoB;IAC9D,OAAO,CAAC,SAAS,EAAE,wBAAwB,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC;AACvF,CAAC;AA2CD;;;;;GAKG;AACH,SAAgB,yBAAyB,CAAC,QAA2C,EAAE,KAAoB,EAAE,KAAa;IACxH,MAAM,eAAe,GAAG,2BAA2B,CAAC,KAAK,CAAC,CAAC;IAC3D,MAAM,OAAO,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC,OAAO,EAA4B,EAAE;QACjE,MAAM,QAAQ,GAAG,eAAe;aAC7B,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,oBAAoB,CAAC,OAAO,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;aACxD,MAAM,CAAC,CAAC,MAAM,EAA+B,EAAE,CAAC,MAAM,KAAK,IAAI,CAAC,CAAC;QACpE,MAAM,UAAU,GAAG,QAAQ,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC;QACxG,MAAM,SAAS,GAAG,OAAO,CAAC,YAAY,KAAK,IAAI,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,YAAY,CAAC,GAAG,KAAK,CAAC;QAC5F,MAAM,UAAU,GAAG,OAAO,CAAC,QAAQ,KAAK,KAAK,IAAI,CAAC,SAAS,IAAI,CAAC,UAAU,KAAK,IAAI,IAAI,UAAU,GAAG,GAAG,CAAC,CAAC;QACzG,OAAO;YACL,IAAI,EAAE,OAAO,CAAC,IAAI;YAClB,SAAS,EAAE,OAAO,CAAC,SAAS;YAC5B,KAAK,EAAE,OAAO,CAAC,KAAK;YACpB,IAAI,EAAE,IAAA,qCAAoB,EAAC,OAAO,CAAC,gBAAgB,CAAC;YACpD,gBAAgB,EAAE,OAAO,CAAC,gBAAgB;YAC1C,QAAQ,EAAE,OAAO,CAAC,QAAQ,IAAI,IAAI;YAClC,OAAO,EAAE,OAAO,CAAC,KAAK,EAAE,OAAO,IAAI,EAAE;YACrC,cAAc,EAAE,OAAO,CAAC,KAAK,EAAE,SAAS,IAAI,IAAI;YAChD,YAAY,EAAE,OAAO,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI;YAC7C,YAAY,EAAE,OAAO,CAAC,YAAY;YAClC,UAAU;YACV,eAAe,EAAE,UAAU,KAAK,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,GAAG,UAAU;YAC9D,aAAa,EAAE,KAAK;SACrB,CAAC;IACJ,CAAC,CAAC,CAAC;IACH,MAAM,MAAM,GAAG,OAAO;SACnB,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,UAAU,CAAC;SACnC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;QACb,IAAI,CAAC,CAAC,eAAe,KAAK,IAAI,IAAI,CAAC,CAAC,eAAe,KAAK,IAAI,EAAE,CAAC;YAC7D,OAAO,CAAC,CAAC,CAAC,eAAe,KAAK,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,eAAe,KAAK,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QACrF,CAAC;QACD,IAAI,CAAC,CAAC,eAAe,KAAK,CAAC,CAAC,eAAe;YAAE,OAAO,CAAC,CAAC,eAAe,GAAG,CAAC,CAAC,eAAe,CAAC;QAC1F,OAAO,kBAAkB,CAAC,CAAC,EAAE,eAAe,CAAC,GAAG,kBAAkB,CAAC,CAAC,EAAE,eAAe,CAAC,CAAC;IACzF,CAAC,CAAC,CAAC;IACL,MAAM,WAAW,GAAG,MAAM,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC;IACtC,IAAI,WAAW;QAAE,WAAW,CAAC,aAAa,GAAG,IAAI,CAAC;IAClD,OAAO,EAAE,KAAK,EAAE,eAAe,EAAE,WAAW,EAAE,WAAW,EAAE,IAAI,IAAI,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC;AAC/F,CAAC;AAED,SAAS,kBAAkB,CAAC,KAA+B,EAAE,KAAuC;IAClG,OAAO,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,MAAM,EAAE,EAAE,CAAC,GAAG,GAAG,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;AACxH,CAAC;AAED;;;;GAIG;AACH,SAAgB,4BAA4B,CAAC,KAI5C;IACC,gHAAgH;IAChH,MAAM,gBAAgB,GAAG,KAAK,CAAC,OAAO,CAAC,OAAO,EAAE,SAAS,KAAK,IAAI,CAAC;IACnE,MAAM,MAAM,GAAG,CAAC,IAAY,EAAE,MAAuC,EAA0B,EAAE,CAAC,CAAC;QACjG,IAAI;QACJ,SAAS,EAAE,IAAA,wCAAuB,EAAC,KAAK,CAAC,OAAO,EAAE,IAAI,CAAC;QACvD,QAAQ,EAAE,MAAM,EAAE,QAAQ;QAC1B,KAAK,EAAE,MAAM,EAAE,KAAK,IAAI,IAAI;QAC5B,gBAAgB,EAAE,MAAM,EAAE,gBAAgB,IAAI,IAAI;QAClD,KAAK,EAAE,MAAM,EAAE,KAAK;QACpB,YAAY,EAAE,MAAM,EAAE,YAAY,IAAI,IAAI;KAC3C,CAAC,CAAC;IACH,MAAM,KAAK,GAAG,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC;SACxC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC,IAAI,KAAK,SAAS,CAAC;SACtC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,aAAa,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC;IAClE,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,SAAS,EAAE,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,MAAM,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC;AAC3I,CAAC;AAED,sHAAsH;AACtH,SAAgB,qCAAqC,CAAC,OAAe;IACnE,IAAI,MAAe,CAAC;IACpB,IAAI,CAAC;QACH,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,YAAY,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC;IACjF,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;IACD,MAAM,OAAO,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,aAAa,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC,CAAC,EAAE,CAAC;IAC3G,MAAM,MAAM,GAAwC,EAAE,CAAC;IACvD,KAAK,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;QACrD,IAAI,aAAa,CAAC,MAAM,CAAC,IAAI,OAAO,MAAM,CAAC,SAAS,KAAK,QAAQ;YAAE,MAAM,CAAC,IAAI,CAAC,GAAG,MAAwC,CAAC;IAC7H,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,kBAAkB;AAElB;;;;GAIG;AACH,SAAgB,wBAAwB,CAAC,QAAuB,EAAE,QAAgB,EAAE,KAAa;IAC/F,IAAI,QAAQ,KAAK,IAAI;QAAE,OAAO,GAAG,CAAC;IAClC,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;IACnC,IAAI,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC;QAAE,OAAO,GAAG,CAAC;IACpC,2GAA2G;IAC3G,+DAA+D;IAC/D,MAAM,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,GAAG,MAAM,CAAC,GAAG,MAAM,CAAC;IAC/C,MAAM,IAAI,GAAG,CAAC,OAAmC,EAAE,OAAe,EAAU,EAAE,CAC5E,IAAI,IAAI,CAAC,cAAc,CAAC,OAAO,EAAE,EAAE,QAAQ,EAAE,QAAQ,EAAE,SAAS,EAAE,KAAK,EAAE,GAAG,OAAO,EAAE,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IACzG,MAAM,IAAI,GAAG,IAAI,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,EAAE,EAAE,CAAC,CAAC;IAC9D,MAAM,KAAK,GAAG,CAAC,OAAe,EAAE,EAAE,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,SAAS,EAAE,GAAG,EAAE,SAAS,EAAE,EAAE,OAAO,CAAC,CAAC;IACxG,IAAI,KAAK,CAAC,EAAE,CAAC,KAAK,KAAK,CAAC,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IAC5C,IAAI,EAAE,GAAG,KAAK,GAAG,CAAC,GAAG,EAAE,GAAG,SAAS;QAAE,OAAO,GAAG,IAAI,CAAC,EAAE,OAAO,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC,IAAI,IAAI,EAAE,CAAC;IACxF,OAAO,GAAG,IAAI,CAAC,EAAE,GAAG,EAAE,SAAS,EAAE,EAAE,EAAE,CAAC,IAAI,IAAI,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE,EAAE,EAAE,CAAC,IAAI,IAAI,EAAE,CAAC;AACrF,CAAC;AAUD,oEAAoE;AACvD,QAAA,yBAAyB,GAA6B,EAAE,OAAO,EAAE,cAAc,EAAE,GAAG,EAAE,GAAG,EAAE,IAAI,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC;AAEjI;;;;;GAKG;AACH,SAAgB,8BAA8B,CAAC,QAAuB,EAAE,KAAa,EAAE,QAAkC,iCAAyB;IAChJ,IAAI,QAAQ,KAAK,IAAI;QAAE,OAAO,GAAG,CAAC;IAClC,MAAM,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;IAChC,IAAI,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC;QAAE,OAAO,GAAG,CAAC;IACjC,MAAM,YAAY,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,KAAK,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC;IACpE,IAAI,IAAY,CAAC;IACjB,IAAI,YAAY,GAAG,EAAE,EAAE,CAAC;QACtB,IAAI,GAAG,GAAG,YAAY,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC;IAC1C,CAAC;SAAM,IAAI,YAAY,GAAG,EAAE,GAAG,EAAE,EAAE,CAAC;QAClC,uCAAuC;QACvC,IAAI,GAAG,YAAY,GAAG,EAAE,IAAI,IAAI,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,GAAG,EAAE,CAAC,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC;IACvG,CAAC;SAAM,CAAC;QACN,IAAI,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,GAAG,IAAI,CAAC,CAAC;QAC3C,IAAI,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,YAAY,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC;QACnD,IAAI,KAAK,KAAK,EAAE,EAAE,CAAC;YAAC,IAAI,IAAI,CAAC,CAAC;YAAC,KAAK,GAAG,CAAC,CAAC;QAAC,CAAC;QAC3C,IAAI,GAAG,KAAK,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,GAAG,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,GAAG,IAAI,GAAG,KAAK,CAAC,GAAG,IAAI,KAAK,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC;IAC3F,CAAC;IACD,OAAO,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;AAC/C,CAAC;AAED;;;;GAIG;AACH,SAAgB,uBAAuB,CACrC,MAAgC,EAChC,KAAa,EACb,UAAkF,EAAE;IAEpF,IAAI,MAAM,KAAK,IAAI;QAAE,OAAO,GAAG,CAAC;IAChC,MAAM,KAAK,GAAG,MAAM,CAAC,QAAQ,KAAK,IAAI,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC;IACrF,MAAM,QAAQ,GAAG,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,gBAAgB,IAAI,IAAI,CAAC;IAC5E,IAAI,QAAQ,KAAK,IAAI,IAAI,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;QAAE,OAAO,GAAG,MAAM,CAAC,OAAO,GAAG,CAAC;IACzF,OAAO,GAAG,MAAM,CAAC,OAAO,KAAK,8BAA8B,CAAC,QAAQ,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;AAChG,CAAC;AAED,sBAAsB;AAEtB,SAAS,aAAa,CAAC,KAAc;IACnC,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;AAC9E,CAAC;AAED,SAAS,OAAO,CAAC,KAAc;IAC7B,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,IAAI,CAAC;IAC3C,MAAM,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IAC7B,OAAO,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,EAAE,CAAC,CAAC,WAAW,EAAE,CAAC;AAC9D,CAAC;AAED,SAAS,YAAY,CAAC,KAAa;IACjC,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AACvD,CAAC"}
@@ -0,0 +1,44 @@
1
+ /**
2
+ * @description The usage poller behind `/account`, the `claude_profiles` MCP tool and the stream frames: keeps
3
+ * one `ClaudeUsageSnapshot` per account profile current (`utils/claudeUsage.ts`), reading every signed-in
4
+ * profile's own token. Runs on a modest timer (`claudeUsageRefreshIntervalMs`), on `/account` open and on
5
+ * demand (`refreshAll({ maxAgeMs })` skips a snapshot fresher than that), and folds in the `rate_limit_event`
6
+ * windows a json-stream session reports (`noteStreamWindows`), persisting only when a bucket actually moved.
7
+ *
8
+ * A profile whose token has expired is NOT refreshed here (the CLI renews tokens; a bot-side refresh would
9
+ * race it and could invalidate the CLI's own) — its snapshot is marked stale instead. Every dependency is
10
+ * injected, so the unit test drives it without the network, the file system or a `StateStore`.
11
+ */
12
+ import { type ClaudeOAuthToken, type ClaudeRateLimitWindow, type ClaudeUsageFetchResult, type ClaudeUsageSnapshot } from './claudeUsage';
13
+ export declare const claudeUsageRefreshIntervalMs: number;
14
+ /** A snapshot younger than this is served as is by the on-demand readers (`/account`, the MCP tool). */
15
+ export declare const claudeUsageOnDemandMaxAgeMs = 60000;
16
+ export interface ClaudeUsageRefresherProfile {
17
+ name: string;
18
+ configDir: string | null;
19
+ /** The last auth probe; a profile known to be signed out is skipped. */
20
+ loggedIn: boolean | undefined;
21
+ }
22
+ export interface ClaudeUsageRefresherDeps {
23
+ listProfiles: () => ClaudeUsageRefresherProfile[];
24
+ getSnapshot: (name: string) => ClaudeUsageSnapshot | undefined;
25
+ saveSnapshot: (name: string, snapshot: ClaudeUsageSnapshot) => void;
26
+ readToken: (configDir: string | null) => ClaudeOAuthToken | null;
27
+ fetchUsage: (accessToken: string) => Promise<ClaudeUsageFetchResult>;
28
+ now?: () => number;
29
+ log?: (line: string) => void;
30
+ }
31
+ export interface ClaudeUsageRefresher {
32
+ /** Poll every signed-in profile; with `maxAgeMs`, only those whose snapshot is older (or stale). One poll in flight at a time. */
33
+ refreshAll: (options?: {
34
+ maxAgeMs?: number;
35
+ }) => Promise<void>;
36
+ /** Poll one profile now (a fresh sign-in, a tap). */
37
+ refreshOne: (name: string) => Promise<void>;
38
+ /** A json-stream frame's windows for the profile the session runs on. */
39
+ noteStreamWindows: (name: string, windows: readonly ClaudeRateLimitWindow[]) => void;
40
+ start: (intervalMs?: number) => void;
41
+ stop: () => void;
42
+ }
43
+ export declare function createClaudeUsageRefresher(deps: ClaudeUsageRefresherDeps): ClaudeUsageRefresher;
44
+ //# sourceMappingURL=claudeUsageRefresher.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"claudeUsageRefresher.d.ts","sourceRoot":"","sources":["../../src/utils/claudeUsageRefresher.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAML,KAAK,gBAAgB,EACrB,KAAK,qBAAqB,EAC1B,KAAK,sBAAsB,EAC3B,KAAK,mBAAmB,EACzB,MAAM,eAAe,CAAC;AAEvB,eAAO,MAAM,4BAA4B,QAAc,CAAC;AAExD,wGAAwG;AACxG,eAAO,MAAM,2BAA2B,QAAS,CAAC;AAElD,MAAM,WAAW,2BAA2B;IAC1C,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,wEAAwE;IACxE,QAAQ,EAAE,OAAO,GAAG,SAAS,CAAC;CAC/B;AAED,MAAM,WAAW,wBAAwB;IACvC,YAAY,EAAE,MAAM,2BAA2B,EAAE,CAAC;IAClD,WAAW,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,mBAAmB,GAAG,SAAS,CAAC;IAC/D,YAAY,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,mBAAmB,KAAK,IAAI,CAAC;IACpE,SAAS,EAAE,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,KAAK,gBAAgB,GAAG,IAAI,CAAC;IACjE,UAAU,EAAE,CAAC,WAAW,EAAE,MAAM,KAAK,OAAO,CAAC,sBAAsB,CAAC,CAAC;IACrE,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;IACnB,GAAG,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;CAC9B;AAED,MAAM,WAAW,oBAAoB;IACnC,kIAAkI;IAClI,UAAU,EAAE,CAAC,OAAO,CAAC,EAAE;QAAE,QAAQ,CAAC,EAAE,MAAM,CAAA;KAAE,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC/D,qDAAqD;IACrD,UAAU,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC5C,yEAAyE;IACzE,iBAAiB,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,SAAS,qBAAqB,EAAE,KAAK,IAAI,CAAC;IACrF,KAAK,EAAE,CAAC,UAAU,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;IACrC,IAAI,EAAE,MAAM,IAAI,CAAC;CAClB;AAED,wBAAgB,0BAA0B,CAAC,IAAI,EAAE,wBAAwB,GAAG,oBAAoB,CAyE/F"}
@@ -0,0 +1,95 @@
1
+ "use strict";
2
+ /**
3
+ * @description The usage poller behind `/account`, the `claude_profiles` MCP tool and the stream frames: keeps
4
+ * one `ClaudeUsageSnapshot` per account profile current (`utils/claudeUsage.ts`), reading every signed-in
5
+ * profile's own token. Runs on a modest timer (`claudeUsageRefreshIntervalMs`), on `/account` open and on
6
+ * demand (`refreshAll({ maxAgeMs })` skips a snapshot fresher than that), and folds in the `rate_limit_event`
7
+ * windows a json-stream session reports (`noteStreamWindows`), persisting only when a bucket actually moved.
8
+ *
9
+ * A profile whose token has expired is NOT refreshed here (the CLI renews tokens; a bot-side refresh would
10
+ * race it and could invalidate the CLI's own) — its snapshot is marked stale instead. Every dependency is
11
+ * injected, so the unit test drives it without the network, the file system or a `StateStore`.
12
+ */
13
+ Object.defineProperty(exports, "__esModule", { value: true });
14
+ exports.claudeUsageOnDemandMaxAgeMs = exports.claudeUsageRefreshIntervalMs = void 0;
15
+ exports.createClaudeUsageRefresher = createClaudeUsageRefresher;
16
+ const claudeUsage_1 = require("./claudeUsage");
17
+ exports.claudeUsageRefreshIntervalMs = 10 * 60_000;
18
+ /** A snapshot younger than this is served as is by the on-demand readers (`/account`, the MCP tool). */
19
+ exports.claudeUsageOnDemandMaxAgeMs = 60_000;
20
+ function createClaudeUsageRefresher(deps) {
21
+ const now = deps.now ?? (() => Date.now());
22
+ const log = deps.log ?? ((line) => console.log(line));
23
+ let inFlight = null;
24
+ let timer = null;
25
+ async function pollProfile(profile) {
26
+ const previous = deps.getSnapshot(profile.name);
27
+ const token = deps.readToken(profile.configDir);
28
+ if (token === null) {
29
+ // No credentials on disk: nothing to poll, nothing to keep — an old snapshot of a signed-out directory is noise.
30
+ if (previous && !previous.isStale)
31
+ deps.saveSnapshot(profile.name, (0, claudeUsage_1.markClaudeUsageSnapshotStale)(previous, 'not signed in', now()));
32
+ return;
33
+ }
34
+ if ((0, claudeUsage_1.checkIsClaudeTokenExpired)(token, now())) {
35
+ if (!previous?.isStale || previous.error !== 'token expired') {
36
+ deps.saveSnapshot(profile.name, (0, claudeUsage_1.markClaudeUsageSnapshotStale)(previous, 'token expired', now()));
37
+ }
38
+ return;
39
+ }
40
+ const result = await deps.fetchUsage(token.accessToken);
41
+ if (!result.ok) {
42
+ log(`[usage] ${profile.name}: usage poll failed (${result.error})`);
43
+ deps.saveSnapshot(profile.name, (0, claudeUsage_1.markClaudeUsageSnapshotStale)(previous, result.error, now()));
44
+ return;
45
+ }
46
+ deps.saveSnapshot(profile.name, (0, claudeUsage_1.mergeClaudeUsageSnapshot)(previous, result.buckets, 'api', now()));
47
+ }
48
+ function checkNeedsPoll(profile, maxAgeMs) {
49
+ if (profile.loggedIn === false)
50
+ return false;
51
+ if (maxAgeMs === undefined)
52
+ return true;
53
+ const snapshot = deps.getSnapshot(profile.name);
54
+ if (!snapshot || snapshot.isStale)
55
+ return true;
56
+ return now() - Date.parse(snapshot.fetchedAt) >= maxAgeMs;
57
+ }
58
+ async function refreshAll(options = {}) {
59
+ if (inFlight)
60
+ return inFlight;
61
+ inFlight = (async () => {
62
+ const due = deps.listProfiles().filter((profile) => checkNeedsPoll(profile, options.maxAgeMs));
63
+ await Promise.all(due.map((profile) => pollProfile(profile).catch((e) => {
64
+ log(`[usage] ${profile.name}: usage poll threw: ${e instanceof Error ? e.message : String(e)}`);
65
+ })));
66
+ })().finally(() => { inFlight = null; });
67
+ return inFlight;
68
+ }
69
+ async function refreshOne(name) {
70
+ const profile = deps.listProfiles().find((candidate) => candidate.name === name);
71
+ if (profile)
72
+ await pollProfile(profile);
73
+ }
74
+ function noteStreamWindows(name, windows) {
75
+ const buckets = (0, claudeUsage_1.buildBucketsFromRateLimitWindows)(windows);
76
+ if (buckets.length === 0)
77
+ return;
78
+ const previous = deps.getSnapshot(name);
79
+ if (!(0, claudeUsage_1.checkClaudeUsageBucketsChanged)(previous, buckets))
80
+ return;
81
+ deps.saveSnapshot(name, (0, claudeUsage_1.mergeClaudeUsageSnapshot)(previous, buckets, 'stream', now()));
82
+ }
83
+ function start(intervalMs = exports.claudeUsageRefreshIntervalMs) {
84
+ stop();
85
+ timer = setInterval(() => { void refreshAll(); }, intervalMs);
86
+ timer.unref?.();
87
+ }
88
+ function stop() {
89
+ if (timer)
90
+ clearInterval(timer);
91
+ timer = null;
92
+ }
93
+ return { refreshAll, refreshOne, noteStreamWindows, start, stop };
94
+ }
95
+ //# sourceMappingURL=claudeUsageRefresher.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"claudeUsageRefresher.js","sourceRoot":"","sources":["../../src/utils/claudeUsageRefresher.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,32 @@
1
+ /**
2
+ * @description The CONTEXT BRIDGE a cross-backend fallback switch hands the new agent (`utils/fallbackChain.ts`):
3
+ * when a topic moves between Claude Code and OpenCode the adapter changes, the new session cannot read the
4
+ * old transcript, and the only thing it knows is what its first prompt tells it. That prompt is built here:
5
+ * why it takes over, the folder it shares with its predecessor, the predecessor's last turns verbatim
6
+ * (user and assistant), and the instruction to establish the state of the work from the project itself
7
+ * before carrying on — then to say in one short message what the task is, what is done and what remains.
8
+ *
9
+ * English on purpose (an agent-facing template, like the thread-context preamble) with a baked reply-language
10
+ * directive. Pure: the turns and labels come from the caller, so the shape is unit-tested.
11
+ */
12
+ import type { RecentTurn } from '../types';
13
+ /** How many of the previous agent's last turns the bridge carries (user and assistant turns alike). */
14
+ export declare const fallbackBridgeTurnLimit = 6;
15
+ /** A single turn longer than this is cut in the middle — the bridge is a hand-over, not a transcript copy. */
16
+ export declare const fallbackBridgeTurnMaxChars = 2500;
17
+ /**
18
+ * @description The bridge prompt. `turns` are chronological (oldest first), already capped by the caller;
19
+ * `resetsAtText` names when the exhausted account comes back (omitted when unknown).
20
+ */
21
+ export declare function buildFallbackBridgePrompt(input: {
22
+ fromLabel: string;
23
+ toLabel: string;
24
+ turns: readonly RecentTurn[];
25
+ resetsAtText: string | null;
26
+ replyLanguage: string;
27
+ }): string;
28
+ /** Cut the middle of an over-long turn, keeping its head and tail (the ask and the outcome are at the ends). */
29
+ export declare function truncateTurnText(text: string, maxChars?: number): string;
30
+ /** Whether a prompt is a bridge (the request ledger and the trace must not read it as the user's own text). */
31
+ export declare function checkIsFallbackBridgePrompt(text: string): boolean;
32
+ //# sourceMappingURL=fallbackBridge.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fallbackBridge.d.ts","sourceRoot":"","sources":["../../src/utils/fallbackBridge.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAGH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAE3C,uGAAuG;AACvG,eAAO,MAAM,uBAAuB,IAAI,CAAC;AAEzC,8GAA8G;AAC9G,eAAO,MAAM,0BAA0B,OAAO,CAAC;AAI/C;;;GAGG;AACH,wBAAgB,yBAAyB,CAAC,KAAK,EAAE;IAC/C,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,SAAS,UAAU,EAAE,CAAC;IAC7B,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,aAAa,EAAE,MAAM,CAAC;CACvB,GAAG,MAAM,CAsBT;AAED,gHAAgH;AAChH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,GAAE,MAAmC,GAAG,MAAM,CAIpG;AAED,+GAA+G;AAC/G,wBAAgB,2BAA2B,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAEjE"}