github-issue-tower-defence-management 1.127.0 → 1.128.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 (64) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/README.md +3 -3
  3. package/bin/adapter/entry-points/console/ui-dist/assets/index-CufymFM1.js +103 -0
  4. package/bin/adapter/entry-points/console/ui-dist/index.html +1 -1
  5. package/bin/adapter/entry-points/console/webServer.js +56 -3
  6. package/bin/adapter/entry-points/console/webServer.js.map +1 -1
  7. package/bin/adapter/entry-points/handlers/InTmuxByHumanSessionTokenCountHandler.js +1 -0
  8. package/bin/adapter/entry-points/handlers/InTmuxByHumanSessionTokenCountHandler.js.map +1 -1
  9. package/bin/adapter/entry-points/handlers/LiveSessionOauthTokenSelectHandler.js +5 -0
  10. package/bin/adapter/entry-points/handlers/LiveSessionOauthTokenSelectHandler.js.map +1 -1
  11. package/bin/adapter/entry-points/handlers/OauthTokenSelectHandler.js +5 -0
  12. package/bin/adapter/entry-points/handlers/OauthTokenSelectHandler.js.map +1 -1
  13. package/bin/adapter/entry-points/handlers/tokenStatusWriter.js +1 -0
  14. package/bin/adapter/entry-points/handlers/tokenStatusWriter.js.map +1 -1
  15. package/bin/adapter/proxy/RateLimitCache.js +35 -4
  16. package/bin/adapter/proxy/RateLimitCache.js.map +1 -1
  17. package/bin/adapter/proxy/proxyEntry.js +48 -0
  18. package/bin/adapter/proxy/proxyEntry.js.map +1 -1
  19. package/bin/domain/usecases/OauthTokenSelectUseCase.js +5 -2
  20. package/bin/domain/usecases/OauthTokenSelectUseCase.js.map +1 -1
  21. package/package.json +1 -1
  22. package/src/adapter/entry-points/console/ui/src/features/console/components/content/ConsoleMarkdownContent.stories.tsx +1 -2
  23. package/src/adapter/entry-points/console/ui/src/features/console/hooks/useConsoleCaches.ts +2 -4
  24. package/src/adapter/entry-points/console/ui/src/features/console/hooks/useConsoleOperations.test.ts +7 -7
  25. package/src/adapter/entry-points/console/ui/src/features/console/hooks/useConsoleOperations.ts +15 -18
  26. package/src/adapter/entry-points/console/ui/src/features/console/hooks/useConsoleTabData.ts +2 -5
  27. package/src/adapter/entry-points/console/ui/src/features/console/lib/consoleApi.test.ts +22 -25
  28. package/src/adapter/entry-points/console/ui/src/features/console/lib/consoleApi.ts +12 -23
  29. package/src/adapter/entry-points/console/ui/src/features/console/lib/imageProxy.test.ts +7 -10
  30. package/src/adapter/entry-points/console/ui/src/features/console/lib/imageProxy.ts +2 -9
  31. package/src/adapter/entry-points/console/ui/src/features/console/pages/ConsoleItemDetailContainer.tsx +2 -4
  32. package/src/adapter/entry-points/console/ui-dist/assets/index-CufymFM1.js +103 -0
  33. package/src/adapter/entry-points/console/ui-dist/index.html +1 -1
  34. package/src/adapter/entry-points/console/webServer.test.ts +283 -6
  35. package/src/adapter/entry-points/console/webServer.ts +64 -0
  36. package/src/adapter/entry-points/handlers/InTmuxByHumanSessionTokenCountHandler.ts +1 -0
  37. package/src/adapter/entry-points/handlers/LiveSessionOauthTokenSelectHandler.test.ts +49 -1
  38. package/src/adapter/entry-points/handlers/LiveSessionOauthTokenSelectHandler.ts +7 -1
  39. package/src/adapter/entry-points/handlers/OauthTokenSelectHandler.test.ts +65 -1
  40. package/src/adapter/entry-points/handlers/OauthTokenSelectHandler.ts +11 -1
  41. package/src/adapter/entry-points/handlers/tokenStatusWriter.ts +1 -0
  42. package/src/adapter/proxy/RateLimitCache.test.ts +148 -0
  43. package/src/adapter/proxy/RateLimitCache.ts +56 -3
  44. package/src/adapter/proxy/proxyEntry.test.ts +126 -0
  45. package/src/adapter/proxy/proxyEntry.ts +60 -0
  46. package/src/domain/usecases/InTmuxByHumanSessionTokenCountUseCase.test.ts +1 -0
  47. package/src/domain/usecases/LiveSessionOauthTokenSelectUseCase.test.ts +2 -0
  48. package/src/domain/usecases/OauthTokenSelectUseCase.test.ts +25 -0
  49. package/src/domain/usecases/OauthTokenSelectUseCase.ts +6 -0
  50. package/types/adapter/entry-points/console/webServer.d.ts +5 -1
  51. package/types/adapter/entry-points/console/webServer.d.ts.map +1 -1
  52. package/types/adapter/entry-points/handlers/InTmuxByHumanSessionTokenCountHandler.d.ts.map +1 -1
  53. package/types/adapter/entry-points/handlers/LiveSessionOauthTokenSelectHandler.d.ts.map +1 -1
  54. package/types/adapter/entry-points/handlers/OauthTokenSelectHandler.d.ts.map +1 -1
  55. package/types/adapter/entry-points/handlers/tokenStatusWriter.d.ts.map +1 -1
  56. package/types/adapter/proxy/RateLimitCache.d.ts +8 -0
  57. package/types/adapter/proxy/RateLimitCache.d.ts.map +1 -1
  58. package/types/adapter/proxy/proxyEntry.d.ts.map +1 -1
  59. package/types/domain/usecases/OauthTokenSelectUseCase.d.ts +1 -0
  60. package/types/domain/usecases/OauthTokenSelectUseCase.d.ts.map +1 -1
  61. package/bin/adapter/entry-points/console/ui-dist/assets/index-8H0HejYa.js +0 -103
  62. package/src/adapter/entry-points/console/ui/src/features/console/hooks/useConsoleToken.test.ts +0 -41
  63. package/src/adapter/entry-points/console/ui/src/features/console/hooks/useConsoleToken.ts +0 -64
  64. package/src/adapter/entry-points/console/ui-dist/assets/index-8H0HejYa.js +0 -103
@@ -4,13 +4,17 @@ import * as path from 'path';
4
4
  import {
5
5
  cacheDir,
6
6
  cachePathForToken,
7
+ FABLE_LIMIT_TYPE,
7
8
  hashToken,
8
9
  HEADERLESS_429_DEFAULT_COOLDOWN_SECONDS,
9
10
  HEADERLESS_429_MAX_COOLDOWN_SECONDS,
11
+ isFableModel,
10
12
  parseModelRateLimitsFromBody,
11
13
  parseModelRateLimitsFromHeaders,
14
+ parseSevenDayRejection,
12
15
  PERMISSION_DISABLED_COOLDOWN_SECONDS,
13
16
  readRateLimit,
17
+ writeFableRejection,
14
18
  writeModelRateLimit,
15
19
  writeRateLimit,
16
20
  writeSubscriptionDisabled,
@@ -699,6 +703,149 @@ describe('RateLimitCache', () => {
699
703
  });
700
704
  });
701
705
 
706
+ describe('isFableModel', () => {
707
+ it('should return true for the fable model id', () => {
708
+ expect(isFableModel('claude-fable-5')).toBe(true);
709
+ });
710
+
711
+ it('should be case insensitive', () => {
712
+ expect(isFableModel('Claude-FABLE-5')).toBe(true);
713
+ });
714
+
715
+ it('should return false for sonnet and opus models', () => {
716
+ expect(isFableModel('claude-sonnet-4-6')).toBe(false);
717
+ expect(isFableModel('claude-opus-4-8')).toBe(false);
718
+ });
719
+
720
+ it('should return false for a null model', () => {
721
+ expect(isFableModel(null)).toBe(false);
722
+ });
723
+ });
724
+
725
+ describe('writeFableRejection', () => {
726
+ it('should persist a rejected fable weekly limit readable by readRateLimit', () => {
727
+ const token = 'fable-rejection-token';
728
+ const nowEpochSeconds = Date.now() / 1000;
729
+ writeFableRejection(token, 120);
730
+ const snapshot = readRateLimit(token);
731
+ const fableLimit = snapshot?.modelWeeklyLimits[FABLE_LIMIT_TYPE];
732
+ expect(fableLimit?.rejected).toBe(true);
733
+ expect(fableLimit?.resetsAt).toBeGreaterThanOrEqual(
734
+ nowEpochSeconds + 120,
735
+ );
736
+ expect(fableLimit?.resetsAt).toBeLessThanOrEqual(
737
+ nowEpochSeconds + 120 + 5,
738
+ );
739
+ });
740
+
741
+ it('should cap the reset from an oversized retry-after at the max cooldown', () => {
742
+ const token = 'fable-rejection-cap-token';
743
+ const nowEpochSeconds = Date.now() / 1000;
744
+ writeFableRejection(token, HEADERLESS_429_MAX_COOLDOWN_SECONDS + 10_000);
745
+ const fableLimit =
746
+ readRateLimit(token)?.modelWeeklyLimits[FABLE_LIMIT_TYPE];
747
+ expect(fableLimit?.resetsAt).toBeLessThanOrEqual(
748
+ nowEpochSeconds + HEADERLESS_429_MAX_COOLDOWN_SECONDS + 5,
749
+ );
750
+ });
751
+
752
+ it('should use the default cooldown when retry-after is absent', () => {
753
+ const token = 'fable-rejection-default-token';
754
+ const nowEpochSeconds = Date.now() / 1000;
755
+ writeFableRejection(token, null);
756
+ const fableLimit =
757
+ readRateLimit(token)?.modelWeeklyLimits[FABLE_LIMIT_TYPE];
758
+ expect(fableLimit?.resetsAt).toBeGreaterThanOrEqual(
759
+ nowEpochSeconds + HEADERLESS_429_DEFAULT_COOLDOWN_SECONDS,
760
+ );
761
+ expect(fableLimit?.resetsAt).toBeLessThanOrEqual(
762
+ nowEpochSeconds + HEADERLESS_429_DEFAULT_COOLDOWN_SECONDS + 5,
763
+ );
764
+ });
765
+
766
+ it('should preserve other model weekly limits already recorded', () => {
767
+ const token = 'fable-rejection-merge-token';
768
+ writeModelRateLimit(token, {
769
+ seven_day_sonnet: { rejected: true, resetsAt: 1779642000 },
770
+ });
771
+ writeFableRejection(token, 90);
772
+ const limits = readRateLimit(token)?.modelWeeklyLimits;
773
+ expect(limits?.seven_day_sonnet).toEqual({
774
+ rejected: true,
775
+ resetsAt: 1779642000,
776
+ });
777
+ expect(limits?.[FABLE_LIMIT_TYPE]?.rejected).toBe(true);
778
+ });
779
+
780
+ it('should use the seven-day reset for resetsAt when provided instead of the retry-after cooldown', () => {
781
+ const token = 'fable-rejection-sevenday-reset-token';
782
+ const sevenDayReset = 1893456000;
783
+ writeFableRejection(token, 120, sevenDayReset);
784
+ const fableLimit =
785
+ readRateLimit(token)?.modelWeeklyLimits[FABLE_LIMIT_TYPE];
786
+ expect(fableLimit?.rejected).toBe(true);
787
+ expect(fableLimit?.resetsAt).toBe(sevenDayReset);
788
+ });
789
+
790
+ it('should fall back to the retry-after cooldown when the seven-day reset is null', () => {
791
+ const token = 'fable-rejection-null-reset-token';
792
+ const nowEpochSeconds = Date.now() / 1000;
793
+ writeFableRejection(token, 120, null);
794
+ const fableLimit =
795
+ readRateLimit(token)?.modelWeeklyLimits[FABLE_LIMIT_TYPE];
796
+ expect(fableLimit?.resetsAt).toBeGreaterThanOrEqual(
797
+ nowEpochSeconds + 120,
798
+ );
799
+ expect(fableLimit?.resetsAt).toBeLessThanOrEqual(
800
+ nowEpochSeconds + 120 + 5,
801
+ );
802
+ });
803
+ });
804
+
805
+ describe('parseSevenDayRejection', () => {
806
+ it('should report a rejection and the reset epoch when the 7-day status is rejected', () => {
807
+ expect(
808
+ parseSevenDayRejection({
809
+ 'anthropic-ratelimit-unified-7d-status': 'rejected',
810
+ 'anthropic-ratelimit-unified-7d-reset': '1893456000',
811
+ }),
812
+ ).toEqual({ sevenDayRejected: true, sevenDayReset: 1893456000 });
813
+ });
814
+
815
+ it('should report no rejection when only the 5-hour status is rejected', () => {
816
+ expect(
817
+ parseSevenDayRejection({
818
+ 'anthropic-ratelimit-unified-5h-status': 'rejected',
819
+ 'anthropic-ratelimit-unified-7d-status': 'allowed',
820
+ }),
821
+ ).toEqual({ sevenDayRejected: false, sevenDayReset: null });
822
+ });
823
+
824
+ it('should report no rejection when no rate-limit headers are present', () => {
825
+ expect(parseSevenDayRejection({})).toEqual({
826
+ sevenDayRejected: false,
827
+ sevenDayReset: null,
828
+ });
829
+ });
830
+
831
+ it('should return a null reset when the 7-day status is rejected but no reset header is present', () => {
832
+ expect(
833
+ parseSevenDayRejection({
834
+ 'anthropic-ratelimit-unified-7d-status': 'rejected',
835
+ }),
836
+ ).toEqual({ sevenDayRejected: true, sevenDayReset: null });
837
+ });
838
+
839
+ it('should pick the first value when a header is an array', () => {
840
+ expect(
841
+ parseSevenDayRejection({
842
+ 'anthropic-ratelimit-unified-7d-status': ['rejected', 'allowed'],
843
+ 'anthropic-ratelimit-unified-7d-reset': ['1893456000'],
844
+ }),
845
+ ).toEqual({ sevenDayRejected: true, sevenDayReset: 1893456000 });
846
+ });
847
+ });
848
+
702
849
  describe('parseModelRateLimitsFromHeaders', () => {
703
850
  it('should extract a rejected seven_day_sonnet limit from the per-model unified headers', () => {
704
851
  expect(
@@ -915,6 +1062,7 @@ describe('RateLimitCache', () => {
915
1062
  },
916
1063
  subscriptionDisabled: snapshot?.subscriptionDisabled ?? false,
917
1064
  unifiedRejected: snapshot?.unifiedRejected ?? false,
1065
+ fableRejected: false,
918
1066
  },
919
1067
  ],
920
1068
  Date.now() / 1000,
@@ -28,6 +28,8 @@ export interface RateLimitSnapshot {
28
28
 
29
29
  export const PROXY_PORT = 8787;
30
30
 
31
+ export const FABLE_LIMIT_TYPE = 'seven_day_fable';
32
+
31
33
  const HASH_ALGORITHM = 'sha256';
32
34
 
33
35
  export const HEADERLESS_429_DEFAULT_COOLDOWN_SECONDS = 90;
@@ -36,6 +38,12 @@ export const HEADERLESS_429_MAX_COOLDOWN_SECONDS = 600;
36
38
 
37
39
  export const PERMISSION_DISABLED_COOLDOWN_SECONDS = 3600;
38
40
 
41
+ const FIVE_HOUR_STATUS_HEADER = 'anthropic-ratelimit-unified-5h-status';
42
+
43
+ const SEVEN_DAY_STATUS_HEADER = 'anthropic-ratelimit-unified-7d-status';
44
+
45
+ const SEVEN_DAY_RESET_HEADER = 'anthropic-ratelimit-unified-7d-reset';
46
+
39
47
  export const cacheDir = (): string => {
40
48
  const base = process.env.XDG_CACHE_HOME ?? path.join(os.homedir(), '.cache');
41
49
  return path.join(base, 'tdpm', 'ratelimit');
@@ -182,6 +190,51 @@ export const writeModelRateLimit = (
182
190
  fs.writeFileSync(filePath, JSON.stringify(payload));
183
191
  };
184
192
 
193
+ export const isFableModel = (modelName: string | null): boolean =>
194
+ (modelName ?? '').toLowerCase().includes('fable');
195
+
196
+ export interface SevenDayRejectionSignal {
197
+ sevenDayRejected: boolean;
198
+ sevenDayReset: number | null;
199
+ }
200
+
201
+ const pickHeaderValue = (
202
+ headers: Record<string, string | string[] | undefined>,
203
+ key: string,
204
+ ): string | undefined => {
205
+ const value = headers[key];
206
+ return Array.isArray(value) ? value[0] : value;
207
+ };
208
+
209
+ export const parseSevenDayRejection = (
210
+ headers: Record<string, string | string[] | undefined>,
211
+ ): SevenDayRejectionSignal => {
212
+ const status = pickHeaderValue(headers, SEVEN_DAY_STATUS_HEADER);
213
+ const resetRaw = pickHeaderValue(headers, SEVEN_DAY_RESET_HEADER);
214
+ const sevenDayReset =
215
+ resetRaw !== undefined && Number.isFinite(Number(resetRaw))
216
+ ? Number(resetRaw)
217
+ : null;
218
+ return {
219
+ sevenDayRejected: status === 'rejected',
220
+ sevenDayReset,
221
+ };
222
+ };
223
+
224
+ export const writeFableRejection = (
225
+ token: string,
226
+ retryAfterSeconds: number | null,
227
+ sevenDayReset: number | null = null,
228
+ ): void => {
229
+ const resetsAt =
230
+ sevenDayReset !== null && sevenDayReset > 0
231
+ ? sevenDayReset
232
+ : cooldownEndFromRetryAfter(retryAfterSeconds, Date.now() / 1000);
233
+ writeModelRateLimit(token, {
234
+ [FABLE_LIMIT_TYPE]: { rejected: true, resetsAt },
235
+ });
236
+ };
237
+
185
238
  export const writeSubscriptionDisabled = (
186
239
  token: string,
187
240
  baseDir: string = cacheDir(),
@@ -283,8 +336,8 @@ export const readRateLimit = (
283
336
  return Number.isFinite(parsedValue) ? parsedValue : 0;
284
337
  };
285
338
  const status = headers['anthropic-ratelimit-unified-status'];
286
- const fiveHourStatus = headers['anthropic-ratelimit-unified-5h-status'];
287
- const sevenDayStatus = headers['anthropic-ratelimit-unified-7d-status'];
339
+ const fiveHourStatus = headers[FIVE_HOUR_STATUS_HEADER];
340
+ const sevenDayStatus = headers[SEVEN_DAY_STATUS_HEADER];
288
341
  const overageDisabledReason =
289
342
  headers['anthropic-ratelimit-unified-overage-disabled-reason'];
290
343
  const unifiedRejected = status === 'rejected';
@@ -309,7 +362,7 @@ export const readRateLimit = (
309
362
  fiveHourUtilization: num('anthropic-ratelimit-unified-5h-utilization'),
310
363
  fiveHourReset: num('anthropic-ratelimit-unified-5h-reset'),
311
364
  sevenDayUtilization: num('anthropic-ratelimit-unified-7d-utilization'),
312
- sevenDayReset: num('anthropic-ratelimit-unified-7d-reset'),
365
+ sevenDayReset: num(SEVEN_DAY_RESET_HEADER),
313
366
  blocked:
314
367
  status === 'blocked' ||
315
368
  fiveHourStatus === 'blocked' ||
@@ -103,6 +103,7 @@ describe('startProxy', () => {
103
103
  let proxyPort = 0;
104
104
  let writeRateLimitSpy: jest.SpyInstance;
105
105
  let writeModelRateLimitSpy: jest.SpyInstance;
106
+ let writeFableRejectionSpy: jest.SpyInstance;
106
107
 
107
108
  const listen = (server: http.Server): Promise<number> =>
108
109
  new Promise((resolve) => {
@@ -191,6 +192,9 @@ describe('startProxy', () => {
191
192
  writeModelRateLimitSpy = jest
192
193
  .spyOn(RateLimitCache, 'writeModelRateLimit')
193
194
  .mockImplementation(() => undefined);
195
+ writeFableRejectionSpy = jest
196
+ .spyOn(RateLimitCache, 'writeFableRejection')
197
+ .mockImplementation(() => undefined);
194
198
 
195
199
  proxyPort = await new Promise<number>((resolve) => {
196
200
  const probe = http.createServer();
@@ -207,6 +211,7 @@ describe('startProxy', () => {
207
211
  httpsRequestImpl = null;
208
212
  writeRateLimitSpy.mockRestore();
209
213
  writeModelRateLimitSpy.mockRestore();
214
+ writeFableRejectionSpy.mockRestore();
210
215
  await closeServer(proxyServer);
211
216
  await closeServer(upstreamServer);
212
217
  });
@@ -308,6 +313,127 @@ describe('startProxy', () => {
308
313
  );
309
314
  });
310
315
 
316
+ it('should mark the fable weekly limit when a fable 429 carries a rejected 7-day status, using the 7-day reset', async () => {
317
+ const sevenDayReset = 1893456000;
318
+ upstreamHandler = (_request, response) => {
319
+ response.writeHead(429, {
320
+ 'content-type': 'application/json',
321
+ 'retry-after': '120',
322
+ 'anthropic-ratelimit-unified-7d-status': 'rejected',
323
+ 'anthropic-ratelimit-unified-7d-reset': String(sevenDayReset),
324
+ });
325
+ response.end('{"type":"error","error":{"type":"rate_limit_error"}}');
326
+ };
327
+
328
+ const response = await requestThroughProxy(
329
+ 'POST',
330
+ '/v1/messages',
331
+ JSON.stringify({ model: 'claude-fable-5', messages: [] }),
332
+ );
333
+
334
+ expect(response.statusCode).toBe(429);
335
+ expect(writeFableRejectionSpy).toHaveBeenCalledTimes(1);
336
+ expect(writeFableRejectionSpy).toHaveBeenCalledWith(
337
+ TOKEN,
338
+ 120,
339
+ sevenDayReset,
340
+ );
341
+ });
342
+
343
+ it('should fall back to retry-after for the reset when a rejected 7-day status carries no 7-day reset header', async () => {
344
+ upstreamHandler = (_request, response) => {
345
+ response.writeHead(429, {
346
+ 'content-type': 'application/json',
347
+ 'retry-after': '120',
348
+ 'anthropic-ratelimit-unified-7d-status': 'rejected',
349
+ });
350
+ response.end('{"type":"error","error":{"type":"rate_limit_error"}}');
351
+ };
352
+
353
+ const response = await requestThroughProxy(
354
+ 'POST',
355
+ '/v1/messages',
356
+ JSON.stringify({ model: 'claude-fable-5', messages: [] }),
357
+ );
358
+
359
+ expect(response.statusCode).toBe(429);
360
+ expect(writeFableRejectionSpy).toHaveBeenCalledTimes(1);
361
+ expect(writeFableRejectionSpy).toHaveBeenCalledWith(TOKEN, 120, null);
362
+ });
363
+
364
+ it('should not mark the fable weekly limit when a fable 429 is a 5-hour rejection without a 7-day rejection', async () => {
365
+ upstreamHandler = (_request, response) => {
366
+ response.writeHead(429, {
367
+ 'content-type': 'application/json',
368
+ 'retry-after': '120',
369
+ 'anthropic-ratelimit-unified-5h-status': 'rejected',
370
+ 'anthropic-ratelimit-unified-7d-status': 'allowed',
371
+ });
372
+ response.end('{"type":"error","error":{"type":"rate_limit_error"}}');
373
+ };
374
+
375
+ const response = await requestThroughProxy(
376
+ 'POST',
377
+ '/v1/messages',
378
+ JSON.stringify({ model: 'claude-fable-5', messages: [] }),
379
+ );
380
+
381
+ expect(response.statusCode).toBe(429);
382
+ expect(writeFableRejectionSpy).not.toHaveBeenCalled();
383
+ });
384
+
385
+ it('should not mark the fable weekly limit when a fable 429 carries no rate-limit rejection headers', async () => {
386
+ upstreamHandler = (_request, response) => {
387
+ response.writeHead(429, { 'content-type': 'application/json' });
388
+ response.end('{"type":"error","error":{"type":"rate_limit_error"}}');
389
+ };
390
+
391
+ const response = await requestThroughProxy(
392
+ 'POST',
393
+ '/v1/messages',
394
+ JSON.stringify({ model: 'claude-fable-5', messages: [] }),
395
+ );
396
+
397
+ expect(response.statusCode).toBe(429);
398
+ expect(writeFableRejectionSpy).not.toHaveBeenCalled();
399
+ });
400
+
401
+ it('should not mark the fable weekly limit when a non-fable request is rejected with a 7-day-rejected 429', async () => {
402
+ upstreamHandler = (_request, response) => {
403
+ response.writeHead(429, {
404
+ 'content-type': 'application/json',
405
+ 'anthropic-ratelimit-unified-7d-status': 'rejected',
406
+ 'anthropic-ratelimit-unified-7d-reset': '1893456000',
407
+ });
408
+ response.end('{"type":"error","error":{"type":"rate_limit_error"}}');
409
+ };
410
+
411
+ const response = await requestThroughProxy(
412
+ 'POST',
413
+ '/v1/messages',
414
+ JSON.stringify({ model: 'claude-sonnet-4-6', messages: [] }),
415
+ );
416
+
417
+ expect(response.statusCode).toBe(429);
418
+ expect(writeFableRejectionSpy).not.toHaveBeenCalled();
419
+ });
420
+
421
+ it('should not mark the fable weekly limit when a fable request succeeds', async () => {
422
+ upstreamHandler = (_request, response) => {
423
+ response.writeHead(200, { 'content-type': 'application/json' });
424
+ response.end('{"model":"claude-fable-5"}');
425
+ };
426
+
427
+ const response = await requestThroughProxy(
428
+ 'POST',
429
+ '/v1/messages',
430
+ JSON.stringify({ model: 'claude-fable-5', messages: [] }),
431
+ );
432
+
433
+ expect(response.statusCode).toBe(200);
434
+ expect(writeFableRejectionSpy).not.toHaveBeenCalled();
435
+ });
436
+
311
437
  it('should forward non-SSE responses without crashing', async () => {
312
438
  upstreamHandler = (_request, response) => {
313
439
  response.writeHead(200, { 'content-type': 'application/json' });
@@ -3,7 +3,10 @@ import * as https from 'https';
3
3
  import {
4
4
  PROXY_PORT,
5
5
  hashToken,
6
+ isFableModel,
6
7
  parseModelRateLimitsFromBody,
8
+ parseSevenDayRejection,
9
+ writeFableRejection,
7
10
  writeModelRateLimit,
8
11
  writeRateLimit,
9
12
  writeSubscriptionDisabled,
@@ -46,12 +49,49 @@ const isPermissionError = (body: string): boolean => {
46
49
  return error.type === 'permission_error';
47
50
  };
48
51
 
52
+ const matchModelInBody = (requestBody: string): string | null => {
53
+ const match = requestBody.match(/"model"\s*:\s*"([^"]+)"/);
54
+ return match !== null ? match[1] : null;
55
+ };
56
+
57
+ const extractRequestModel = (requestBody: string): string | null => {
58
+ try {
59
+ const parsed: unknown = JSON.parse(requestBody);
60
+ if (isRecord(parsed) && typeof parsed.model === 'string') {
61
+ return parsed.model;
62
+ }
63
+ return null;
64
+ } catch {
65
+ return matchModelInBody(requestBody);
66
+ }
67
+ };
68
+
69
+ const parseRetryAfterSeconds = (
70
+ headers: http.IncomingHttpHeaders,
71
+ ): number | null => {
72
+ const raw = headers['retry-after'];
73
+ const value =
74
+ typeof raw === 'string' ? raw : Array.isArray(raw) ? raw[0] : null;
75
+ if (typeof value !== 'string') return null;
76
+ const parsed = Number(value);
77
+ return Number.isFinite(parsed) ? parsed : null;
78
+ };
79
+
49
80
  const startProxy = (
50
81
  port: number,
51
82
  claudeMessageResponseRepository: ClaudeMessageResponseRepository | null = null,
52
83
  ): http.Server => {
53
84
  const server = http.createServer((clientRequest, clientResponse) => {
54
85
  const token = extractToken(clientRequest.headers['authorization']);
86
+ const requestChunks: Uint8Array[] = [];
87
+ let requestBytes = 0;
88
+ if (token !== null) {
89
+ clientRequest.on('data', (chunk: Buffer) => {
90
+ if (requestBytes >= MAX_INSPECTED_BODY_BYTES) return;
91
+ requestChunks.push(new Uint8Array(chunk));
92
+ requestBytes += chunk.length;
93
+ });
94
+ }
55
95
  const upstreamHeaders: Record<string, string | string[] | undefined> = {
56
96
  ...clientRequest.headers,
57
97
  host: UPSTREAM_HOST,
@@ -105,6 +145,26 @@ const startProxy = (
105
145
  );
106
146
  }
107
147
  }
148
+ if (upstreamResponse.statusCode === 429) {
149
+ try {
150
+ const requestModel = extractRequestModel(
151
+ Buffer.concat(requestChunks).toString('utf8'),
152
+ );
153
+ if (isFableModel(requestModel)) {
154
+ const { sevenDayRejected, sevenDayReset } =
155
+ parseSevenDayRejection(upstreamResponse.headers);
156
+ if (sevenDayRejected) {
157
+ writeFableRejection(
158
+ token,
159
+ parseRetryAfterSeconds(upstreamResponse.headers),
160
+ sevenDayReset,
161
+ );
162
+ }
163
+ }
164
+ } catch (error) {
165
+ console.error('Failed to write fable rejection cache:', error);
166
+ }
167
+ }
108
168
  if (claudeMessageResponseRepository !== null) {
109
169
  try {
110
170
  const response = parseClaudeMessageResponse(
@@ -13,6 +13,7 @@ const candidate = (name: string): OauthTokenCandidate => ({
13
13
  snapshot: null,
14
14
  subscriptionDisabled: false,
15
15
  unifiedRejected: false,
16
+ fableRejected: false,
16
17
  });
17
18
 
18
19
  const session = (
@@ -24,12 +24,14 @@ const candidate = (
24
24
  snapshotValue: OauthTokenWindowSnapshot | null,
25
25
  subscriptionDisabled = false,
26
26
  unifiedRejected = false,
27
+ fableRejected = false,
27
28
  ): OauthTokenCandidate => ({
28
29
  name,
29
30
  token: `fake-token-${name}`,
30
31
  snapshot: snapshotValue,
31
32
  subscriptionDisabled,
32
33
  unifiedRejected,
34
+ fableRejected,
33
35
  });
34
36
 
35
37
  const session = (name: string, sessionKey: string): ClaudeLiveSession => ({
@@ -23,12 +23,14 @@ const candidate = (
23
23
  snapshotValue: OauthTokenWindowSnapshot | null,
24
24
  subscriptionDisabled = false,
25
25
  unifiedRejected = false,
26
+ fableRejected = false,
26
27
  ): OauthTokenCandidate => ({
27
28
  name,
28
29
  token: `fake-token-${name}`,
29
30
  snapshot: snapshotValue,
30
31
  subscriptionDisabled,
31
32
  unifiedRejected,
33
+ fableRejected,
32
34
  });
33
35
 
34
36
  describe('OauthTokenSelectUseCase', () => {
@@ -221,4 +223,27 @@ describe('OauthTokenSelectUseCase', () => {
221
223
  expect(rejected?.eligible).toBe(false);
222
224
  expect(rejected?.exclusionReason).toContain('rejected');
223
225
  });
226
+
227
+ it('excludes a fable-rejected token even when rate-limit windows are fully free', () => {
228
+ const result = useCase.run(
229
+ [
230
+ candidate('fable-out', snapshot({}), false, false, true),
231
+ candidate('active', snapshot({}), false, false, false),
232
+ ],
233
+ NOW,
234
+ );
235
+
236
+ expect(result.selected?.name).toBe('active');
237
+ const fableOut = result.metrics.find((m) => m.name === 'fable-out');
238
+ expect(fableOut?.eligible).toBe(false);
239
+ expect(fableOut?.exclusionReason).toContain('fable weekly limit exhausted');
240
+ });
241
+
242
+ it('treats a token without a fable marker as eligible for fable selection', () => {
243
+ const result = useCase.run([candidate('alive', snapshot({}))], NOW);
244
+
245
+ expect(result.selected?.name).toBe('alive');
246
+ const alive = result.metrics.find((m) => m.name === 'alive');
247
+ expect(alive?.eligible).toBe(true);
248
+ });
224
249
  });
@@ -11,6 +11,7 @@ export type OauthTokenCandidate = {
11
11
  snapshot: OauthTokenWindowSnapshot | null;
12
12
  subscriptionDisabled: boolean;
13
13
  unifiedRejected: boolean;
14
+ fableRejected: boolean;
14
15
  };
15
16
 
16
17
  export type OauthTokenCandidateMetrics = {
@@ -79,6 +80,7 @@ export class OauthTokenSelectUseCase {
79
80
  const exclusionReason = this.exclusionReason(
80
81
  candidate.subscriptionDisabled,
81
82
  candidate.unifiedRejected,
83
+ candidate.fableRejected,
82
84
  fiveHourFreeRatio,
83
85
  sevenDayFreeRatio,
84
86
  );
@@ -96,6 +98,7 @@ export class OauthTokenSelectUseCase {
96
98
  private exclusionReason = (
97
99
  subscriptionDisabled: boolean,
98
100
  unifiedRejected: boolean,
101
+ fableRejected: boolean,
99
102
  fiveHourFreeRatio: number,
100
103
  sevenDayFreeRatio: number,
101
104
  ): string | null => {
@@ -105,6 +108,9 @@ export class OauthTokenSelectUseCase {
105
108
  if (unifiedRejected) {
106
109
  return 'token request was rejected (anthropic-ratelimit-unified-status: rejected)';
107
110
  }
111
+ if (fableRejected) {
112
+ return 'fable weekly limit exhausted (a fable request was rejected with HTTP 429)';
113
+ }
108
114
  if (fiveHourFreeRatio < FIVE_HOUR_MIN_FREE_RATIO) {
109
115
  return `5h window only ${this.toPercent(fiveHourFreeRatio)}% free (requires >= ${this.toPercent(FIVE_HOUR_MIN_FREE_RATIO)}%)`;
110
116
  }
@@ -6,11 +6,15 @@ import { ImageFetcher } from './consoleImageProxy';
6
6
  export declare const DEFAULT_WEB_PORT = 9981;
7
7
  export declare const DEFAULT_DASHBOARD_PROJECT_NAMES: string[];
8
8
  export declare const CONSOLE_TOKEN_HEADER = "x-pv-token";
9
+ export declare const CONSOLE_TOKEN_COOKIE = "pv_token";
9
10
  export declare const hasDotSegment: (requestPath: string) => boolean;
10
11
  export declare const requiresToken: (requestPath: string) => boolean;
11
12
  export declare const isConsoleAppRoute: (requestPath: string) => boolean;
12
13
  export declare const isTokenValid: (expectedToken: string, providedToken: string | null) => boolean;
13
- export declare const extractProvidedToken: (queryToken: string | string[] | null, headerToken: string | string[] | undefined) => string | null;
14
+ export declare const extractCookieToken: (cookieHeader: string | undefined) => string | null;
15
+ export declare const extractProvidedToken: (queryToken: string | string[] | null, headerToken: string | string[] | undefined, cookieToken: string | null) => string | null;
16
+ export declare const buildTokenCookie: (token: string) => string;
17
+ export declare const buildKeylessLocation: (requestUrl: URL) => string;
14
18
  export type WebServerOptions = {
15
19
  accessToken: string;
16
20
  uiDistDir: string;
@@ -1 +1 @@
1
- {"version":3,"file":"webServer.d.ts","sourceRoot":"","sources":["../../../../src/adapter/entry-points/console/webServer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAG7B,OAAO,EAAE,eAAe,EAAE,MAAM,6DAA6D,CAAC;AAM9F,OAAO,EACL,oBAAoB,EACpB,sBAAsB,EAQvB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAEL,sBAAsB,EACtB,sBAAsB,EAMvB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,YAAY,EAAqB,MAAM,qBAAqB,CAAC;AAOtE,eAAO,MAAM,gBAAgB,OAAO,CAAC;AAErC,eAAO,MAAM,+BAA+B,UAA0B,CAAC;AAEvE,eAAO,MAAM,oBAAoB,eAAe,CAAC;AAmCjD,eAAO,MAAM,aAAa,GAAI,aAAa,MAAM,KAAG,OAGiB,CAAC;AAEtE,eAAO,MAAM,aAAa,GAAI,aAAa,MAAM,KAAG,OAGrB,CAAC;AAIhC,eAAO,MAAM,iBAAiB,GAAI,aAAa,MAAM,KAAG,OAmBvD,CAAC;AAEF,eAAO,MAAM,YAAY,GACvB,eAAe,MAAM,EACrB,eAAe,MAAM,GAAG,IAAI,KAC3B,OAAoE,CAAC;AAExE,eAAO,MAAM,oBAAoB,GAC/B,YAAY,MAAM,GAAG,MAAM,EAAE,GAAG,IAAI,EACpC,aAAa,MAAM,GAAG,MAAM,EAAE,GAAG,SAAS,KACzC,MAAM,GAAG,IAQX,CAAC;AAuCF,MAAM,MAAM,gBAAgB,GAAG;IAC7B,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,oBAAoB,EAAE,MAAM,GAAG,IAAI,CAAC;IACpC,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,qBAAqB,EAAE,MAAM,EAAE,CAAC;IAChC,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,YAAY,CAAC,EAAE,YAAY,GAAG,IAAI,CAAC;IACnC,eAAe,CAAC,EAAE,eAAe,GAAG,IAAI,CAAC;IACzC,cAAc,CAAC,EAAE,sBAAsB,GAAG,IAAI,CAAC;IAC/C,kBAAkB,CAAC,EAAE,sBAAsB,GAAG,IAAI,CAAC;IACnD,oBAAoB,CAAC,EAAE,oBAAoB,GAAG,IAAI,CAAC;IACnD,sBAAsB,CAAC,EAAE,sBAAsB,GAAG,IAAI,CAAC;CACxD,CAAC;AAMF,eAAO,MAAM,sBAAsB,cAAc,CAAC;AAElD,eAAO,MAAM,wBAAwB,aAAa,CAAC;AAInD,eAAO,MAAM,wBAAwB,GACnC,cAAc,MAAM,EACpB,aAAa,MAAM,KAClB,MAAM,GAAG,IAWX,CAAC;AAEF,eAAO,MAAM,yBAAyB,GACpC,eAAe,MAAM,EACrB,aAAa,MAAM,KAClB,MAAM,GAAG,IAeX,CAAC;AA0VF,eAAO,MAAM,uBAAuB,GAClC,SAAS,gBAAgB,EACzB,aAAa,MAAM,KAClB,MAAM,GAAG,IAeX,CAAC;AAEF,eAAO,MAAM,gBAAgB,GAC3B,SAAS,gBAAgB,EACzB,SAAS,IAAI,CAAC,eAAe,EAC7B,UAAU,IAAI,CAAC,cAAc,KAC5B,OAAO,CAAC,IAAI,CAwEd,CAAC;AAcF,eAAO,MAAM,eAAe,GAAI,SAAS,gBAAgB,KAAG,IAAI,CAAC,MAM7D,CAAC;AAEL,MAAM,MAAM,qBAAqB,GAAG,gBAAgB,GAAG;IACrD,IAAI,EAAE,MAAM,CAAC;CACd,CAAC;AAEF,eAAO,MAAM,cAAc,GACzB,SAAS,qBAAqB,KAC7B,OAAO,CAAC,IAAI,CAAC,MAAM,CAQlB,CAAC"}
1
+ {"version":3,"file":"webServer.d.ts","sourceRoot":"","sources":["../../../../src/adapter/entry-points/console/webServer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAG7B,OAAO,EAAE,eAAe,EAAE,MAAM,6DAA6D,CAAC;AAM9F,OAAO,EACL,oBAAoB,EACpB,sBAAsB,EAQvB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAEL,sBAAsB,EACtB,sBAAsB,EAMvB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,YAAY,EAAqB,MAAM,qBAAqB,CAAC;AAOtE,eAAO,MAAM,gBAAgB,OAAO,CAAC;AAErC,eAAO,MAAM,+BAA+B,UAA0B,CAAC;AAEvE,eAAO,MAAM,oBAAoB,eAAe,CAAC;AAEjD,eAAO,MAAM,oBAAoB,aAAa,CAAC;AAmC/C,eAAO,MAAM,aAAa,GAAI,aAAa,MAAM,KAAG,OAGiB,CAAC;AAEtE,eAAO,MAAM,aAAa,GAAI,aAAa,MAAM,KAAG,OAGrB,CAAC;AAIhC,eAAO,MAAM,iBAAiB,GAAI,aAAa,MAAM,KAAG,OAmBvD,CAAC;AAEF,eAAO,MAAM,YAAY,GACvB,eAAe,MAAM,EACrB,eAAe,MAAM,GAAG,IAAI,KAC3B,OAAoE,CAAC;AAExE,eAAO,MAAM,kBAAkB,GAC7B,cAAc,MAAM,GAAG,SAAS,KAC/B,MAAM,GAAG,IAoBX,CAAC;AAEF,eAAO,MAAM,oBAAoB,GAC/B,YAAY,MAAM,GAAG,MAAM,EAAE,GAAG,IAAI,EACpC,aAAa,MAAM,GAAG,MAAM,EAAE,GAAG,SAAS,EAC1C,aAAa,MAAM,GAAG,IAAI,KACzB,MAAM,GAAG,IAWX,CAAC;AAEF,eAAO,MAAM,gBAAgB,GAAI,OAAO,MAAM,KAAG,MAC0C,CAAC;AAE5F,eAAO,MAAM,oBAAoB,GAAI,YAAY,GAAG,KAAG,MAOtD,CAAC;AAuCF,MAAM,MAAM,gBAAgB,GAAG;IAC7B,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,oBAAoB,EAAE,MAAM,GAAG,IAAI,CAAC;IACpC,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,qBAAqB,EAAE,MAAM,EAAE,CAAC;IAChC,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,YAAY,CAAC,EAAE,YAAY,GAAG,IAAI,CAAC;IACnC,eAAe,CAAC,EAAE,eAAe,GAAG,IAAI,CAAC;IACzC,cAAc,CAAC,EAAE,sBAAsB,GAAG,IAAI,CAAC;IAC/C,kBAAkB,CAAC,EAAE,sBAAsB,GAAG,IAAI,CAAC;IACnD,oBAAoB,CAAC,EAAE,oBAAoB,GAAG,IAAI,CAAC;IACnD,sBAAsB,CAAC,EAAE,sBAAsB,GAAG,IAAI,CAAC;CACxD,CAAC;AAMF,eAAO,MAAM,sBAAsB,cAAc,CAAC;AAElD,eAAO,MAAM,wBAAwB,aAAa,CAAC;AAInD,eAAO,MAAM,wBAAwB,GACnC,cAAc,MAAM,EACpB,aAAa,MAAM,KAClB,MAAM,GAAG,IAWX,CAAC;AAEF,eAAO,MAAM,yBAAyB,GACpC,eAAe,MAAM,EACrB,aAAa,MAAM,KAClB,MAAM,GAAG,IAeX,CAAC;AA0WF,eAAO,MAAM,uBAAuB,GAClC,SAAS,gBAAgB,EACzB,aAAa,MAAM,KAClB,MAAM,GAAG,IAeX,CAAC;AAEF,eAAO,MAAM,gBAAgB,GAC3B,SAAS,gBAAgB,EACzB,SAAS,IAAI,CAAC,eAAe,EAC7B,UAAU,IAAI,CAAC,cAAc,KAC5B,OAAO,CAAC,IAAI,CA8Ed,CAAC;AAcF,eAAO,MAAM,eAAe,GAAI,SAAS,gBAAgB,KAAG,IAAI,CAAC,MAM7D,CAAC;AAEL,MAAM,MAAM,qBAAqB,GAAG,gBAAgB,GAAG;IACrD,IAAI,EAAE,MAAM,CAAC;CACd,CAAC;AAEF,eAAO,MAAM,cAAc,GACzB,SAAS,qBAAqB,KAC7B,OAAO,CAAC,IAAI,CAAC,MAAM,CAQlB,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"InTmuxByHumanSessionTokenCountHandler.d.ts","sourceRoot":"","sources":["../../../../src/adapter/entry-points/handlers/InTmuxByHumanSessionTokenCountHandler.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,gCAAgC,CAAC;AACvD,OAAO,EAAE,kCAAkC,EAAE,MAAM,gFAAgF,CAAC;AACpI,OAAO,EAAE,qCAAqC,EAAE,MAAM,gEAAgE,CAAC;AAMvH,MAAM,MAAM,0CAA0C,GAAG;IACvD,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,MAAM,EAAE,KAAK,EAAE,CAAC;CACjB,CAAC;AAEF,MAAM,MAAM,2CAA2C,GAAG;IACxD,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,WAAW,EAAE,MAAM,EAAE,CAAC;CACvB,CAAC;AAEF,qBAAa,qCAAqC;IAE9C,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,OAAO,CAAC,QAAQ,CAAC,4BAA4B;gBAD5B,OAAO,GAAE,qCAAmF,EAC5F,4BAA4B,GAAE,kCAAiF;IAGlI,MAAM,GACJ,OAAO,0CAA0C,KAChD,2CAA2C,CAmD5C;CACH"}
1
+ {"version":3,"file":"InTmuxByHumanSessionTokenCountHandler.d.ts","sourceRoot":"","sources":["../../../../src/adapter/entry-points/handlers/InTmuxByHumanSessionTokenCountHandler.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,gCAAgC,CAAC;AACvD,OAAO,EAAE,kCAAkC,EAAE,MAAM,gFAAgF,CAAC;AACpI,OAAO,EAAE,qCAAqC,EAAE,MAAM,gEAAgE,CAAC;AAMvH,MAAM,MAAM,0CAA0C,GAAG;IACvD,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,MAAM,EAAE,KAAK,EAAE,CAAC;CACjB,CAAC;AAEF,MAAM,MAAM,2CAA2C,GAAG;IACxD,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,WAAW,EAAE,MAAM,EAAE,CAAC;CACvB,CAAC;AAEF,qBAAa,qCAAqC;IAE9C,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,OAAO,CAAC,QAAQ,CAAC,4BAA4B;gBAD5B,OAAO,GAAE,qCAAmF,EAC5F,4BAA4B,GAAE,kCAAiF;IAGlI,MAAM,GACJ,OAAO,0CAA0C,KAChD,2CAA2C,CAoD5C;CACH"}
@@ -1 +1 @@
1
- {"version":3,"file":"LiveSessionOauthTokenSelectHandler.d.ts","sourceRoot":"","sources":["../../../../src/adapter/entry-points/handlers/LiveSessionOauthTokenSelectHandler.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,2BAA2B,EAAE,MAAM,yEAAyE,CAAC;AACtH,OAAO,EAEL,kCAAkC,EACnC,MAAM,6DAA6D,CAAC;AAcrE,MAAM,MAAM,uCAAuC,GAAG;IACpD,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,eAAe,EAAE,MAAM,CAAC;CACzB,CAAC;AAEF,MAAM,MAAM,wCAAwC,GAAG;IACrD,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,WAAW,EAAE,MAAM,EAAE,CAAC;CACvB,CAAC;AAEF,qBAAa,kCAAkC;IAE3C,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,OAAO,CAAC,QAAQ,CAAC,qBAAqB;gBADrB,OAAO,GAAE,kCAA6E,EACtF,qBAAqB,GAAE,2BAAmE;IAG7G,MAAM,GACJ,OAAO,uCAAuC,KAC7C,wCAAwC,CAyDzC;IAEF,OAAO,CAAC,iBAAiB,CAyBvB;CACH"}
1
+ {"version":3,"file":"LiveSessionOauthTokenSelectHandler.d.ts","sourceRoot":"","sources":["../../../../src/adapter/entry-points/handlers/LiveSessionOauthTokenSelectHandler.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,2BAA2B,EAAE,MAAM,yEAAyE,CAAC;AACtH,OAAO,EAEL,kCAAkC,EACnC,MAAM,6DAA6D,CAAC;AAcrE,MAAM,MAAM,uCAAuC,GAAG;IACpD,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,eAAe,EAAE,MAAM,CAAC;CACzB,CAAC;AAEF,MAAM,MAAM,wCAAwC,GAAG;IACrD,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,WAAW,EAAE,MAAM,EAAE,CAAC;CACvB,CAAC;AAEF,qBAAa,kCAAkC;IAE3C,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,OAAO,CAAC,QAAQ,CAAC,qBAAqB;gBADrB,OAAO,GAAE,kCAA6E,EACtF,qBAAqB,GAAE,2BAAmE;IAG7G,MAAM,GACJ,OAAO,uCAAuC,KAC7C,wCAAwC,CA+DzC;IAEF,OAAO,CAAC,iBAAiB,CAyBvB;CACH"}
@@ -1 +1 @@
1
- {"version":3,"file":"OauthTokenSelectHandler.d.ts","sourceRoot":"","sources":["../../../../src/adapter/entry-points/handlers/OauthTokenSelectHandler.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,uBAAuB,EACxB,MAAM,kDAAkD,CAAC;AAI1D,MAAM,MAAM,4BAA4B,GAAG;IACzC,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,eAAe,EAAE,MAAM,CAAC;CACzB,CAAC;AAEF,MAAM,MAAM,6BAA6B,GAAG;IAC1C,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,WAAW,EAAE,MAAM,EAAE,CAAC;CACvB,CAAC;AAKF,eAAO,MAAM,wBAAwB,GACnC,cAAc,MAAM,GAAG,IAAI,KAC1B,MAAM,GAAG,IASX,CAAC;AAEF,eAAO,MAAM,qBAAqB,GAChC,mBAAmB,MAAM,GAAG,IAAI,KAC/B,MASF,CAAC;AAEF,qBAAa,uBAAuB;IAEhC,OAAO,CAAC,QAAQ,CAAC,OAAO;gBAAP,OAAO,GAAE,uBAAuD;IAGnF,MAAM,GACJ,OAAO,4BAA4B,KAClC,6BAA6B,CAmD9B;IAEF,OAAO,CAAC,iBAAiB,CAuBvB;CACH"}
1
+ {"version":3,"file":"OauthTokenSelectHandler.d.ts","sourceRoot":"","sources":["../../../../src/adapter/entry-points/handlers/OauthTokenSelectHandler.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,uBAAuB,EACxB,MAAM,kDAAkD,CAAC;AAQ1D,MAAM,MAAM,4BAA4B,GAAG;IACzC,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,eAAe,EAAE,MAAM,CAAC;CACzB,CAAC;AAEF,MAAM,MAAM,6BAA6B,GAAG;IAC1C,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,WAAW,EAAE,MAAM,EAAE,CAAC;CACvB,CAAC;AAKF,eAAO,MAAM,wBAAwB,GACnC,cAAc,MAAM,GAAG,IAAI,KAC1B,MAAM,GAAG,IASX,CAAC;AAEF,eAAO,MAAM,qBAAqB,GAChC,mBAAmB,MAAM,GAAG,IAAI,KAC/B,MASF,CAAC;AAEF,qBAAa,uBAAuB;IAEhC,OAAO,CAAC,QAAQ,CAAC,OAAO;gBAAP,OAAO,GAAE,uBAAuD;IAGnF,MAAM,GACJ,OAAO,4BAA4B,KAClC,6BAA6B,CAyD9B;IAEF,OAAO,CAAC,iBAAiB,CAuBvB;CACH"}
@@ -1 +1 @@
1
- {"version":3,"file":"tokenStatusWriter.d.ts","sourceRoot":"","sources":["../../../../src/adapter/entry-points/handlers/tokenStatusWriter.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,gCAAgC,CAAC;AAE5D,OAAO,EAEL,sBAAsB,EACtB,WAAW,EAEZ,MAAM,+DAA+D,CAAC;AAGvE,OAAO,EAAE,kCAAkC,EAAE,MAAM,gFAAgF,CAAC;AACpI,OAAO,EAAE,4BAA4B,EAAE,MAAM,0EAA0E,CAAC;AACxH,OAAO,EAAE,iBAAiB,EAAiB,MAAM,4BAA4B,CAAC;AAU9E,MAAM,MAAM,uBAAuB,GAAG;IACpC,gBAAgB,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;IAC5C,iBAAiB,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;IAC7C,MAAM,EAAE,KAAK,EAAE,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;IACnC,GAAG,CAAC,EAAE,IAAI,CAAC;IACX,YAAY,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,iBAAiB,GAAG,IAAI,CAAC;IAC3D,4BAA4B,CAAC,EAAE,kCAAkC,CAAC;IAClE,eAAe,CAAC,EAAE,4BAA4B,CAAC;CAChD,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG;IAC5B,MAAM,EAAE,WAAW,EAAE,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;CACpB,CAAC;AA0EF,eAAO,MAAM,wBAAwB,GACnC,UAAU,iBAAiB,GAAG,IAAI,KACjC,sBAAsB,GAAG,IA0B3B,CAAC;AAEF,eAAO,MAAM,gBAAgB,GAAI,QAAQ,uBAAuB,KAAG,IA8GlE,CAAC"}
1
+ {"version":3,"file":"tokenStatusWriter.d.ts","sourceRoot":"","sources":["../../../../src/adapter/entry-points/handlers/tokenStatusWriter.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,gCAAgC,CAAC;AAE5D,OAAO,EAEL,sBAAsB,EACtB,WAAW,EAEZ,MAAM,+DAA+D,CAAC;AAGvE,OAAO,EAAE,kCAAkC,EAAE,MAAM,gFAAgF,CAAC;AACpI,OAAO,EAAE,4BAA4B,EAAE,MAAM,0EAA0E,CAAC;AACxH,OAAO,EAAE,iBAAiB,EAAiB,MAAM,4BAA4B,CAAC;AAU9E,MAAM,MAAM,uBAAuB,GAAG;IACpC,gBAAgB,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;IAC5C,iBAAiB,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;IAC7C,MAAM,EAAE,KAAK,EAAE,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;IACnC,GAAG,CAAC,EAAE,IAAI,CAAC;IACX,YAAY,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,iBAAiB,GAAG,IAAI,CAAC;IAC3D,4BAA4B,CAAC,EAAE,kCAAkC,CAAC;IAClE,eAAe,CAAC,EAAE,4BAA4B,CAAC;CAChD,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG;IAC5B,MAAM,EAAE,WAAW,EAAE,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;CACpB,CAAC;AA0EF,eAAO,MAAM,wBAAwB,GACnC,UAAU,iBAAiB,GAAG,IAAI,KACjC,sBAAsB,GAAG,IA0B3B,CAAC;AAEF,eAAO,MAAM,gBAAgB,GAAI,QAAQ,uBAAuB,KAAG,IA+GlE,CAAC"}