offsite 0.0.80 → 0.0.82

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.
@@ -88,6 +88,208 @@ function publish$2(sessionId, event) {
88
88
  function broadcast(event) {
89
89
  for (const client of clients) client.send(event);
90
90
  }
91
+ // src/services/usage.ts
92
+ const freshFor = 6e4;
93
+ const forcedFreshFor = 1e4;
94
+ const entries = /* @__PURE__ */ new Map();
95
+ const fetching = /* @__PURE__ */ new Map();
96
+ function cachedUsage(accountId) {
97
+ return entries.get(accountId) ?? {
98
+ limits: [],
99
+ fetchedAt: null,
100
+ updatedAt: null,
101
+ error: null
102
+ };
103
+ }
104
+ function recordLimits(accountId, limits) {
105
+ const current = cachedUsage(accountId);
106
+ entries.set(accountId, {
107
+ ...current,
108
+ limits: [...current.limits.map((limit) => limits.find((item) => item.window === limit.window) ?? limit), ...limits.filter((item) => !current.limits.some((limit) => limit.window === item.window))],
109
+ updatedAt: Date.now()
110
+ });
111
+ broadcast({
112
+ type: "limits",
113
+ accountId,
114
+ limits
115
+ });
116
+ }
117
+ async function readUsage(accountId, force) {
118
+ const current = cachedUsage(accountId);
119
+ if (current.fetchedAt !== null && Date.now() - current.fetchedAt < (force ? forcedFreshFor : freshFor)) return current;
120
+ const pending = fetching.get(accountId);
121
+ if (pending !== void 0) return pending;
122
+ const next = fetchUsage(accountId);
123
+ fetching.set(accountId, next);
124
+ try {
125
+ return await next;
126
+ } finally {
127
+ fetching.delete(accountId);
128
+ }
129
+ }
130
+ function forgetUsage(accountId) {
131
+ entries.delete(accountId);
132
+ }
133
+ async function fetchUsage(accountId) {
134
+ const account = storedAccounts().find((item) => item.id === accountId);
135
+ if (account === void 0) throw new Error("That account was removed");
136
+ let usage;
137
+ try {
138
+ usage = {
139
+ limits: await providerLimits(account),
140
+ fetchedAt: Date.now(),
141
+ updatedAt: Date.now(),
142
+ error: null
143
+ };
144
+ } catch (error) {
145
+ console.warn(`could not read usage limits for ${account.name}: ${error}`);
146
+ usage = {
147
+ ...cachedUsage(accountId),
148
+ fetchedAt: Date.now(),
149
+ error: error instanceof Error ? error.message : String(error)
150
+ };
151
+ }
152
+ entries.set(accountId, usage);
153
+ broadcast({
154
+ type: "usage",
155
+ accountId,
156
+ usage
157
+ });
158
+ return usage;
159
+ }
160
+ function providerLimits(account) {
161
+ switch (account.provider) {
162
+ case "claude": return claudeLimits(account);
163
+ case "codex": return codexLimits(account);
164
+ }
165
+ }
166
+ // src/lib/claude/content.ts
167
+ const imageTypes = [
168
+ "image/png",
169
+ "image/jpeg",
170
+ "image/gif",
171
+ "image/webp"
172
+ ];
173
+ function toMessage(type, item, time) {
174
+ return {
175
+ type,
176
+ uuid: item.uuid,
177
+ time,
178
+ content: isRecord(item.message) ? toBlocks(item.message.content, answersOf(item.tool_use_result)) : [],
179
+ parent: item.parent_tool_use_id
180
+ };
181
+ }
182
+ function toUserInput(prompt, uuid, priority) {
183
+ for (const image of prompt.images) if (!imageTypes.includes(image.mediaType)) throw new Error(`${image.mediaType} images are not supported`);
184
+ return {
185
+ type: "user",
186
+ message: {
187
+ role: "user",
188
+ content: [...prompt.text === "" ? [] : [{
189
+ type: "text",
190
+ text: prompt.text
191
+ }], ...prompt.images.map((image) => ({
192
+ type: "image",
193
+ source: {
194
+ type: "base64",
195
+ media_type: image.mediaType,
196
+ data: image.data
197
+ }
198
+ }))]
199
+ },
200
+ parent_tool_use_id: null,
201
+ uuid,
202
+ ...priority === void 0 ? {} : { priority }
203
+ };
204
+ }
205
+ function promptMessage(prompt, uuid) {
206
+ return {
207
+ type: "user",
208
+ uuid,
209
+ time: Date.now(),
210
+ content: [...prompt.text === "" ? [] : [{
211
+ type: "text",
212
+ text: prompt.text
213
+ }], ...prompt.images.map((image) => ({
214
+ type: "image",
215
+ ...image
216
+ }))],
217
+ parent: null
218
+ };
219
+ }
220
+ function notice(text) {
221
+ return {
222
+ type: "notice",
223
+ uuid: randomUUID(),
224
+ time: Date.now(),
225
+ text,
226
+ isError: true
227
+ };
228
+ }
229
+ function contextTokens(message) {
230
+ if (!isRecord(message) || !isRecord(message.usage)) return null;
231
+ const usage = message.usage;
232
+ return [
233
+ usage.input_tokens,
234
+ usage.cache_creation_input_tokens,
235
+ usage.cache_read_input_tokens,
236
+ usage.output_tokens
237
+ ].reduce((total, value) => total + (typeof value === "number" ? value : 0), 0);
238
+ }
239
+ function answersOf(output) {
240
+ if (!isRecord(output) || !isRecord(output.answers)) return null;
241
+ const answers = {};
242
+ for (const [question, answer] of Object.entries(output.answers)) {
243
+ if (typeof answer !== "string") return null;
244
+ answers[question] = answer;
245
+ }
246
+ return answers;
247
+ }
248
+ function toBlocks(content, answers) {
249
+ if (typeof content === "string") return [{
250
+ type: "text",
251
+ text: content
252
+ }];
253
+ if (!Array.isArray(content)) return [];
254
+ return content.flatMap((block) => {
255
+ if (!isRecord(block)) return [];
256
+ switch (block.type) {
257
+ case "text": return typeof block.text === "string" && !block.text.startsWith("<system-reminder>") && !block.text.startsWith("<local-command-caveat>") ? [{
258
+ type: "text",
259
+ text: block.text
260
+ }] : [];
261
+ case "thinking": return typeof block.thinking === "string" && block.thinking !== "" ? [{
262
+ type: "thinking",
263
+ thinking: block.thinking
264
+ }] : [];
265
+ case "image": {
266
+ const source = block.source;
267
+ return isRecord(source) && source.type === "base64" && typeof source.media_type === "string" && typeof source.data === "string" ? [{
268
+ type: "image",
269
+ mediaType: source.media_type,
270
+ data: source.data
271
+ }] : [];
272
+ }
273
+ case "tool_use": return typeof block.id === "string" && typeof block.name === "string" && isRecord(block.input) ? [{
274
+ type: "tool_use",
275
+ id: block.id,
276
+ name: block.name,
277
+ input: block.input
278
+ }] : [];
279
+ case "tool_result": return typeof block.tool_use_id === "string" ? [{
280
+ type: "tool_result",
281
+ toolUseId: block.tool_use_id,
282
+ content: toBlocks(block.content, null).filter((item) => item.type === "text"),
283
+ isError: block.is_error === true,
284
+ answers
285
+ }] : [];
286
+ default: return [];
287
+ }
288
+ });
289
+ }
290
+ function isRecord(value) {
291
+ return typeof value === "object" && value !== null && !Array.isArray(value);
292
+ }
91
293
  // src/args.ts
92
294
  let command = "web";
93
295
  let name = null;
@@ -478,13 +680,13 @@ async function codexAccount(account) {
478
680
  const base = {
479
681
  ...account,
480
682
  email: null,
683
+ displayName: null,
684
+ organization: null,
481
685
  plan: null,
482
- limits: [],
483
686
  linked
484
687
  };
485
688
  try {
486
- const server = appServer(configDir);
487
- const result = await server.request("account/read", {});
689
+ const result = await appServer(configDir).request("account/read", {});
488
690
  if (result.account === null) return {
489
691
  ...base,
490
692
  error: `Not logged in. Run CODEX_HOME=${configDir} codex login in a terminal`,
@@ -494,9 +696,10 @@ async function codexAccount(account) {
494
696
  case "chatgpt": return {
495
697
  ...base,
496
698
  email: result.account.email,
699
+ displayName: codexDisplayName(configDir),
700
+ organization: result.account.workspaceName,
497
701
  plan: result.account.planType,
498
702
  error: null,
499
- limits: await rateLimits(server),
500
703
  valid: linked
501
704
  };
502
705
  case "apiKey": return {
@@ -552,19 +755,10 @@ async function skills(server, cwd) {
552
755
  return (await server.request("skills/list", { cwds: [cwd] })).data.flatMap((entry) => entry.skills.filter((skill) => skill.enabled));
553
756
  }
554
757
  function publishCodexLimits(home, snapshot) {
555
- for (const account of storedAccounts()) if (account.provider === "codex" && (account.configDir ?? codexBaseDir) === home) broadcast({
556
- type: "limits",
557
- accountId: account.id,
558
- limits: toLimits(snapshot)
559
- });
758
+ for (const account of storedAccounts()) if (account.provider === "codex" && (account.configDir ?? codexBaseDir) === home) recordLimits(account.id, toLimits(snapshot));
560
759
  }
561
- async function rateLimits(server) {
562
- try {
563
- return toLimits((await server.request("account/rateLimits/read", {})).rateLimits);
564
- } catch (error) {
565
- console.warn(`could not read Codex usage limits: ${error}`);
566
- return [];
567
- }
760
+ async function codexLimits(account) {
761
+ return toLimits((await appServer(account.configDir ?? codexBaseDir).request("account/rateLimits/read", {})).rateLimits);
568
762
  }
569
763
  function toLimits(snapshot) {
570
764
  return [snapshot.primary, snapshot.secondary].flatMap((window) => window === null ? [] : [{
@@ -574,6 +768,22 @@ function toLimits(snapshot) {
574
768
  rejected: window.usedPercent >= 100
575
769
  }]);
576
770
  }
771
+ function codexDisplayName(home) {
772
+ let raw;
773
+ try {
774
+ raw = JSON.parse(readFileSync(path.join(home, "auth.json"), "utf8"));
775
+ } catch (error) {
776
+ if (error.code !== "ENOENT") console.warn(`could not read the Codex account name: ${error}`);
777
+ return null;
778
+ }
779
+ if (!isRecord(raw) || !isRecord(raw.tokens) || typeof raw.tokens.id_token !== "string") return null;
780
+ const payload = raw.tokens.id_token.split(".").at(1);
781
+ if (payload === void 0) return null;
782
+ const claims = JSON.parse(Buffer.from(payload, "base64url").toString("utf8"));
783
+ if (!isRecord(claims) || typeof claims.name !== "string") return null;
784
+ const name = claims.name.trim();
785
+ return name === "" ? null : name;
786
+ }
577
787
  function isMirror(dir) {
578
788
  try {
579
789
  if (realpathSync(dir) === realpathSync(codexBaseDir)) return true;
@@ -583,133 +793,6 @@ function isMirror(dir) {
583
793
  throw error;
584
794
  }
585
795
  }
586
- // src/lib/claude/content.ts
587
- const imageTypes = [
588
- "image/png",
589
- "image/jpeg",
590
- "image/gif",
591
- "image/webp"
592
- ];
593
- function toMessage(type, item, time) {
594
- return {
595
- type,
596
- uuid: item.uuid,
597
- time,
598
- content: isRecord(item.message) ? toBlocks(item.message.content, answersOf(item.tool_use_result)) : [],
599
- parent: item.parent_tool_use_id
600
- };
601
- }
602
- function toUserInput(prompt, uuid, priority) {
603
- for (const image of prompt.images) if (!imageTypes.includes(image.mediaType)) throw new Error(`${image.mediaType} images are not supported`);
604
- return {
605
- type: "user",
606
- message: {
607
- role: "user",
608
- content: [...prompt.text === "" ? [] : [{
609
- type: "text",
610
- text: prompt.text
611
- }], ...prompt.images.map((image) => ({
612
- type: "image",
613
- source: {
614
- type: "base64",
615
- media_type: image.mediaType,
616
- data: image.data
617
- }
618
- }))]
619
- },
620
- parent_tool_use_id: null,
621
- uuid,
622
- ...priority === void 0 ? {} : { priority }
623
- };
624
- }
625
- function promptMessage(prompt, uuid) {
626
- return {
627
- type: "user",
628
- uuid,
629
- time: Date.now(),
630
- content: [...prompt.text === "" ? [] : [{
631
- type: "text",
632
- text: prompt.text
633
- }], ...prompt.images.map((image) => ({
634
- type: "image",
635
- ...image
636
- }))],
637
- parent: null
638
- };
639
- }
640
- function notice(text) {
641
- return {
642
- type: "notice",
643
- uuid: randomUUID(),
644
- time: Date.now(),
645
- text,
646
- isError: true
647
- };
648
- }
649
- function contextTokens(message) {
650
- if (!isRecord(message) || !isRecord(message.usage)) return null;
651
- const usage = message.usage;
652
- return [
653
- usage.input_tokens,
654
- usage.cache_creation_input_tokens,
655
- usage.cache_read_input_tokens,
656
- usage.output_tokens
657
- ].reduce((total, value) => total + (typeof value === "number" ? value : 0), 0);
658
- }
659
- function answersOf(output) {
660
- if (!isRecord(output) || !isRecord(output.answers)) return null;
661
- const answers = {};
662
- for (const [question, answer] of Object.entries(output.answers)) {
663
- if (typeof answer !== "string") return null;
664
- answers[question] = answer;
665
- }
666
- return answers;
667
- }
668
- function toBlocks(content, answers) {
669
- if (typeof content === "string") return [{
670
- type: "text",
671
- text: content
672
- }];
673
- if (!Array.isArray(content)) return [];
674
- return content.flatMap((block) => {
675
- if (!isRecord(block)) return [];
676
- switch (block.type) {
677
- case "text": return typeof block.text === "string" && !block.text.startsWith("<system-reminder>") && !block.text.startsWith("<local-command-caveat>") ? [{
678
- type: "text",
679
- text: block.text
680
- }] : [];
681
- case "thinking": return typeof block.thinking === "string" && block.thinking !== "" ? [{
682
- type: "thinking",
683
- thinking: block.thinking
684
- }] : [];
685
- case "image": {
686
- const source = block.source;
687
- return isRecord(source) && source.type === "base64" && typeof source.media_type === "string" && typeof source.data === "string" ? [{
688
- type: "image",
689
- mediaType: source.media_type,
690
- data: source.data
691
- }] : [];
692
- }
693
- case "tool_use": return typeof block.id === "string" && typeof block.name === "string" && isRecord(block.input) ? [{
694
- type: "tool_use",
695
- id: block.id,
696
- name: block.name,
697
- input: block.input
698
- }] : [];
699
- case "tool_result": return typeof block.tool_use_id === "string" ? [{
700
- type: "tool_result",
701
- toolUseId: block.tool_use_id,
702
- content: toBlocks(block.content, null).filter((item) => item.type === "text"),
703
- isError: block.is_error === true,
704
- answers
705
- }] : [];
706
- default: return [];
707
- }
708
- });
709
- }
710
- function isRecord(value) {
711
- return typeof value === "object" && value !== null && !Array.isArray(value);
712
- }
713
796
  // src/lib/images.ts
714
797
  const extensions = {
715
798
  "image/png": "png",
@@ -4404,9 +4487,10 @@ function disabledAccount(account) {
4404
4487
  return {
4405
4488
  ...account,
4406
4489
  email: null,
4490
+ displayName: null,
4491
+ organization: null,
4407
4492
  plan: null,
4408
4493
  error: null,
4409
- limits: [],
4410
4494
  linked: true,
4411
4495
  valid: false
4412
4496
  };
@@ -4490,6 +4574,7 @@ async function updateAccount(update) {
4490
4574
  } : item)
4491
4575
  });
4492
4576
  forgetClaude(update.id);
4577
+ forgetUsage(update.id);
4493
4578
  if (before.enabled && !update.enabled) await stopAccount(before);
4494
4579
  }
4495
4580
  function removeAccount(id) {
@@ -4500,6 +4585,7 @@ function removeAccount(id) {
4500
4585
  codexAccounts: config.codexAccounts.filter((item) => item.id !== id)
4501
4586
  });
4502
4587
  forgetClaude(id);
4588
+ forgetUsage(id);
4503
4589
  }
4504
4590
  function validAccount(name, configDir) {
4505
4591
  if (name.trim() === "") throw new Error("Give the account a name");
@@ -4649,7 +4735,6 @@ const modes = [
4649
4735
  "auto"
4650
4736
  ];
4651
4737
  const probes = /* @__PURE__ */ new Map();
4652
- const limits = /* @__PURE__ */ new Map();
4653
4738
  let executable$1 = "";
4654
4739
  function findClaude() {
4655
4740
  const name = process.platform === "win32" ? "claude.exe" : "claude";
@@ -4765,15 +4850,17 @@ async function claudeCapabilities(account, cwd) {
4765
4850
  };
4766
4851
  }
4767
4852
  async function claudeAccount(account) {
4768
- const linked = isLinked(account.configDir ?? claudeBaseDir());
4853
+ const configDir = account.configDir ?? claudeBaseDir();
4854
+ const linked = isLinked(configDir);
4769
4855
  try {
4770
4856
  const info = (await initialization(account.id, os.homedir())).account;
4771
4857
  return {
4772
4858
  ...account,
4773
4859
  email: info.email ?? null,
4860
+ displayName: claudeDisplayName(configDir),
4861
+ organization: info.organization ?? null,
4774
4862
  plan: info.subscriptionType ?? null,
4775
4863
  error: null,
4776
- limits: accountLimits(account.id),
4777
4864
  linked,
4778
4865
  valid: linked
4779
4866
  };
@@ -4781,9 +4868,10 @@ async function claudeAccount(account) {
4781
4868
  return {
4782
4869
  ...account,
4783
4870
  email: null,
4871
+ displayName: null,
4872
+ organization: null,
4784
4873
  plan: null,
4785
4874
  error: error instanceof Error ? error.message : String(error),
4786
- limits: accountLimits(account.id),
4787
4875
  linked,
4788
4876
  valid: linked
4789
4877
  };
@@ -4791,52 +4879,87 @@ async function claudeAccount(account) {
4791
4879
  }
4792
4880
  function forgetClaude(accountId) {
4793
4881
  for (const key of probes.keys()) if (key.startsWith(`${accountId}\n`)) probes.delete(key);
4794
- limits.delete(accountId);
4795
4882
  }
4796
- function recordLimit(accountId, info) {
4797
- const current = limits.get(accountId) ?? /* @__PURE__ */ new Map();
4883
+ function eventLimits(info, current) {
4884
+ const changed = /* @__PURE__ */ new Map();
4798
4885
  const windows = info.unifiedWindows;
4799
4886
  if (isRecord(windows)) {
4800
- for (const [name, value] of Object.entries(windows)) if (isRecord(value)) current.set(name, {
4887
+ for (const [name, value] of Object.entries(windows)) if (isRecord(value)) changed.set(name, {
4801
4888
  window: name,
4802
4889
  utilization: typeof value.utilization === "number" ? value.utilization : null,
4803
4890
  resetsAt: typeof value.resetsAt === "number" ? value.resetsAt : null,
4804
- rejected: current.get(name)?.rejected ?? false
4891
+ rejected: current.find((limit) => limit.window === name)?.rejected ?? false
4805
4892
  });
4806
4893
  }
4807
4894
  if (info.rateLimitType !== void 0) {
4808
- const existing = current.get(info.rateLimitType);
4809
- current.set(info.rateLimitType, {
4895
+ const existing = changed.get(info.rateLimitType) ?? current.find((limit) => limit.window === info.rateLimitType);
4896
+ changed.set(info.rateLimitType, {
4810
4897
  window: info.rateLimitType,
4811
4898
  utilization: info.utilization ?? existing?.utilization ?? null,
4812
4899
  resetsAt: info.resetsAt ?? existing?.resetsAt ?? null,
4813
4900
  rejected: info.status === "rejected"
4814
4901
  });
4815
4902
  }
4816
- limits.set(accountId, current);
4817
- return accountLimits(accountId);
4903
+ return [...changed.values()];
4818
4904
  }
4819
- async function recordUsage(accountId, probe) {
4905
+ async function claudeLimits(account) {
4906
+ const closed = Promise.withResolvers();
4907
+ const probe = query({
4908
+ prompt: idle(closed.promise),
4909
+ options: claudeOptions(account.id, os.homedir())
4910
+ });
4820
4911
  try {
4912
+ await probe.initializationResult();
4821
4913
  const usage = await probe.usage_EXPERIMENTAL_MAY_CHANGE_DO_NOT_RELY_ON_THIS_API_YET({ skipBehaviors: true });
4822
- if (usage.rate_limits === null) return;
4823
- const current = limits.get(accountId) ?? /* @__PURE__ */ new Map();
4824
- const windows = {
4825
- five_hour: usage.rate_limits.five_hour,
4826
- seven_day: usage.rate_limits.seven_day,
4827
- seven_day_opus: usage.rate_limits.seven_day_opus,
4828
- seven_day_sonnet: usage.rate_limits.seven_day_sonnet
4829
- };
4830
- for (const [name, window] of Object.entries(windows)) if (window !== void 0 && window !== null) current.set(name, {
4831
- window: name,
4832
- utilization: window.utilization === null ? null : window.utilization / 100,
4833
- resetsAt: window.resets_at === null ? null : Date.parse(window.resets_at) / 1e3,
4834
- rejected: window.utilization !== null && window.utilization >= 100
4914
+ if (usage.rate_limits === null) return [];
4915
+ return [
4916
+ {
4917
+ name: "five_hour",
4918
+ window: usage.rate_limits.five_hour
4919
+ },
4920
+ {
4921
+ name: "seven_day",
4922
+ window: usage.rate_limits.seven_day
4923
+ },
4924
+ {
4925
+ name: "seven_day_opus",
4926
+ window: usage.rate_limits.seven_day_opus
4927
+ },
4928
+ {
4929
+ name: "seven_day_sonnet",
4930
+ window: usage.rate_limits.seven_day_sonnet
4931
+ },
4932
+ ...(usage.rate_limits.model_scoped ?? []).map((row) => ({
4933
+ name: row.display_name,
4934
+ window: row
4935
+ }))
4936
+ ].flatMap((entry) => {
4937
+ const window = entry.window;
4938
+ if (window === void 0 || window === null) return [];
4939
+ return [{
4940
+ window: entry.name,
4941
+ utilization: window.utilization === null ? null : window.utilization / 100,
4942
+ resetsAt: window.resets_at === null ? null : Date.parse(window.resets_at) / 1e3,
4943
+ rejected: window.utilization !== null && window.utilization >= 100
4944
+ }];
4835
4945
  });
4836
- limits.set(accountId, current);
4946
+ } finally {
4947
+ closed.resolve();
4948
+ probe.close();
4949
+ }
4950
+ }
4951
+ function claudeDisplayName(configDir) {
4952
+ const file = path.resolve(configDir) === path.join(os.homedir(), ".claude") ? path.join(os.homedir(), ".claude.json") : path.join(configDir, ".claude.json");
4953
+ let raw;
4954
+ try {
4955
+ raw = JSON.parse(readFileSync(file, "utf8"));
4837
4956
  } catch (error) {
4838
- console.warn(`could not read Claude usage limits: ${error}`);
4957
+ if (error.code !== "ENOENT") console.warn(`could not read the Claude account name: ${error}`);
4958
+ return null;
4839
4959
  }
4960
+ if (!isRecord(raw) || !isRecord(raw.oauthAccount) || typeof raw.oauthAccount.displayName !== "string") return null;
4961
+ const name = raw.oauthAccount.displayName.trim();
4962
+ return name === "" ? null : name;
4840
4963
  }
4841
4964
  function isLinked(configDir) {
4842
4965
  const base = claudeBaseDir();
@@ -4848,9 +4971,6 @@ function isLinked(configDir) {
4848
4971
  throw error;
4849
4972
  }
4850
4973
  }
4851
- function accountLimits(accountId) {
4852
- return [...limits.get(accountId)?.values() ?? []];
4853
- }
4854
4974
  function initialization(accountId, cwd) {
4855
4975
  const key = `${accountId}\n${cwd}`;
4856
4976
  const existing = probes.get(key);
@@ -4867,9 +4987,7 @@ async function runProbe(accountId, cwd) {
4867
4987
  options: claudeOptions(accountId, cwd)
4868
4988
  });
4869
4989
  try {
4870
- const result = await probe.initializationResult();
4871
- await recordUsage(accountId, probe);
4872
- return result;
4990
+ return await probe.initializationResult();
4873
4991
  } finally {
4874
4992
  closed.resolve();
4875
4993
  probe.close();
@@ -5664,11 +5782,7 @@ var Run = class {
5664
5782
  case "rate_limit_event": {
5665
5783
  const accountId = this.settings.accountId;
5666
5784
  if (accountId === null) throw new Error("Rate limit event for a run without an account");
5667
- broadcast({
5668
- type: "limits",
5669
- accountId,
5670
- limits: recordLimit(accountId, message.rate_limit_info)
5671
- });
5785
+ recordLimits(accountId, eventLimits(message.rate_limit_info, cachedUsage(accountId).limits));
5672
5786
  return;
5673
5787
  }
5674
5788
  case "result": {
@@ -7926,6 +8040,7 @@ const handlers = {
7926
8040
  publishAccounts();
7927
8041
  return null;
7928
8042
  },
8043
+ "accounts.usage": (params) => readUsage(params.id, params.force),
7929
8044
  capabilities: (params) => capabilities(params.provider, params.accountId, params.projectId === null || params.projectId === "no-project" ? os.homedir() : projectPath(params.projectId)),
7930
8045
  "files.list": (params) => params.projectId === "no-project" ? [] : listFiles(projectPath(params.projectId)),
7931
8046
  "files.entries": (params) => listEntries(projectPath(params.projectId)),