github-issue-tower-defence-management 1.84.0 → 1.84.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +7 -0
- package/README.md +4 -4
- package/bin/adapter/proxy/RateLimitCache.js +27 -2
- package/bin/adapter/proxy/RateLimitCache.js.map +1 -1
- package/bin/adapter/repositories/ProxyClaudeTokenUsageRepository.js +5 -1
- package/bin/adapter/repositories/ProxyClaudeTokenUsageRepository.js.map +1 -1
- package/bin/domain/usecases/StartPreparationUseCase.js +6 -6
- package/bin/domain/usecases/StartPreparationUseCase.js.map +1 -1
- package/package.json +1 -1
- package/src/adapter/proxy/RateLimitCache.test.ts +95 -0
- package/src/adapter/proxy/RateLimitCache.ts +32 -1
- package/src/adapter/repositories/ProxyClaudeTokenUsageRepository.test.ts +43 -0
- package/src/adapter/repositories/ProxyClaudeTokenUsageRepository.ts +6 -1
- package/src/domain/entities/ClaudeTokenUsage.ts +1 -0
- package/src/domain/usecases/StartPreparationUseCase.test.ts +343 -0
- package/src/domain/usecases/StartPreparationUseCase.ts +6 -6
- package/types/adapter/proxy/RateLimitCache.d.ts +1 -0
- package/types/adapter/proxy/RateLimitCache.d.ts.map +1 -1
- package/types/adapter/repositories/ProxyClaudeTokenUsageRepository.d.ts.map +1 -1
- package/types/domain/entities/ClaudeTokenUsage.d.ts +1 -0
- package/types/domain/entities/ClaudeTokenUsage.d.ts.map +1 -1
|
@@ -1270,6 +1270,7 @@ describe('StartPreparationUseCase', () => {
|
|
|
1270
1270
|
sevenDayUtilization: 0,
|
|
1271
1271
|
blocked: false,
|
|
1272
1272
|
rejected: false,
|
|
1273
|
+
fiveHourRejected: false,
|
|
1273
1274
|
blockedUntilEpoch: 0,
|
|
1274
1275
|
modelWeeklyLimits: {},
|
|
1275
1276
|
},
|
|
@@ -1280,6 +1281,7 @@ describe('StartPreparationUseCase', () => {
|
|
|
1280
1281
|
sevenDayUtilization: 0,
|
|
1281
1282
|
blocked: false,
|
|
1282
1283
|
rejected: false,
|
|
1284
|
+
fiveHourRejected: false,
|
|
1283
1285
|
blockedUntilEpoch: 0,
|
|
1284
1286
|
modelWeeklyLimits: {},
|
|
1285
1287
|
},
|
|
@@ -1339,6 +1341,7 @@ describe('StartPreparationUseCase', () => {
|
|
|
1339
1341
|
sevenDayUtilization: 0,
|
|
1340
1342
|
blocked: false,
|
|
1341
1343
|
rejected: false,
|
|
1344
|
+
fiveHourRejected: false,
|
|
1342
1345
|
blockedUntilEpoch: 0,
|
|
1343
1346
|
modelWeeklyLimits: {},
|
|
1344
1347
|
},
|
|
@@ -1349,6 +1352,7 @@ describe('StartPreparationUseCase', () => {
|
|
|
1349
1352
|
sevenDayUtilization: 0,
|
|
1350
1353
|
blocked: false,
|
|
1351
1354
|
rejected: false,
|
|
1355
|
+
fiveHourRejected: false,
|
|
1352
1356
|
blockedUntilEpoch: 0,
|
|
1353
1357
|
modelWeeklyLimits: {},
|
|
1354
1358
|
},
|
|
@@ -2377,6 +2381,7 @@ describe('StartPreparationUseCase', () => {
|
|
|
2377
2381
|
sevenDayUtilization: 0,
|
|
2378
2382
|
blocked: false,
|
|
2379
2383
|
rejected: false,
|
|
2384
|
+
fiveHourRejected: false,
|
|
2380
2385
|
blockedUntilEpoch: 0,
|
|
2381
2386
|
modelWeeklyLimits: {},
|
|
2382
2387
|
},
|
|
@@ -2456,6 +2461,7 @@ describe('StartPreparationUseCase', () => {
|
|
|
2456
2461
|
sevenDayUtilization: 0,
|
|
2457
2462
|
blocked: false,
|
|
2458
2463
|
rejected: false,
|
|
2464
|
+
fiveHourRejected: false,
|
|
2459
2465
|
blockedUntilEpoch: 0,
|
|
2460
2466
|
modelWeeklyLimits: {},
|
|
2461
2467
|
},
|
|
@@ -2466,6 +2472,7 @@ describe('StartPreparationUseCase', () => {
|
|
|
2466
2472
|
sevenDayUtilization: 0,
|
|
2467
2473
|
blocked: false,
|
|
2468
2474
|
rejected: false,
|
|
2475
|
+
fiveHourRejected: false,
|
|
2469
2476
|
blockedUntilEpoch: 0,
|
|
2470
2477
|
modelWeeklyLimits: {},
|
|
2471
2478
|
},
|
|
@@ -2578,6 +2585,7 @@ describe('StartPreparationUseCase', () => {
|
|
|
2578
2585
|
sevenDayUtilization: 0.1,
|
|
2579
2586
|
blocked: false,
|
|
2580
2587
|
rejected: false,
|
|
2588
|
+
fiveHourRejected: false,
|
|
2581
2589
|
blockedUntilEpoch: 0,
|
|
2582
2590
|
modelWeeklyLimits: {
|
|
2583
2591
|
seven_day_opus: {
|
|
@@ -2593,6 +2601,7 @@ describe('StartPreparationUseCase', () => {
|
|
|
2593
2601
|
sevenDayUtilization: 0.1,
|
|
2594
2602
|
blocked: false,
|
|
2595
2603
|
rejected: false,
|
|
2604
|
+
fiveHourRejected: false,
|
|
2596
2605
|
blockedUntilEpoch: 0,
|
|
2597
2606
|
modelWeeklyLimits: {
|
|
2598
2607
|
seven_day_opus: {
|
|
@@ -2655,6 +2664,7 @@ describe('StartPreparationUseCase', () => {
|
|
|
2655
2664
|
sevenDayUtilization: 0.1,
|
|
2656
2665
|
blocked: false,
|
|
2657
2666
|
rejected: false,
|
|
2667
|
+
fiveHourRejected: false,
|
|
2658
2668
|
blockedUntilEpoch: 0,
|
|
2659
2669
|
modelWeeklyLimits: {
|
|
2660
2670
|
seven_day_opus: {
|
|
@@ -2670,6 +2680,7 @@ describe('StartPreparationUseCase', () => {
|
|
|
2670
2680
|
sevenDayUtilization: 0.1,
|
|
2671
2681
|
blocked: false,
|
|
2672
2682
|
rejected: false,
|
|
2683
|
+
fiveHourRejected: false,
|
|
2673
2684
|
blockedUntilEpoch: 0,
|
|
2674
2685
|
modelWeeklyLimits: {
|
|
2675
2686
|
seven_day_opus: {
|
|
@@ -2731,6 +2742,7 @@ describe('StartPreparationUseCase', () => {
|
|
|
2731
2742
|
sevenDayUtilization: 0.1,
|
|
2732
2743
|
blocked: false,
|
|
2733
2744
|
rejected: false,
|
|
2745
|
+
fiveHourRejected: false,
|
|
2734
2746
|
blockedUntilEpoch: 0,
|
|
2735
2747
|
modelWeeklyLimits: {
|
|
2736
2748
|
seven_day_opus: {
|
|
@@ -2746,6 +2758,7 @@ describe('StartPreparationUseCase', () => {
|
|
|
2746
2758
|
sevenDayUtilization: 0.1,
|
|
2747
2759
|
blocked: false,
|
|
2748
2760
|
rejected: false,
|
|
2761
|
+
fiveHourRejected: false,
|
|
2749
2762
|
blockedUntilEpoch: 0,
|
|
2750
2763
|
modelWeeklyLimits: {
|
|
2751
2764
|
seven_day_opus: {
|
|
@@ -2804,6 +2817,7 @@ describe('StartPreparationUseCase', () => {
|
|
|
2804
2817
|
sevenDayUtilization: 0.7,
|
|
2805
2818
|
blocked: false,
|
|
2806
2819
|
rejected: false,
|
|
2820
|
+
fiveHourRejected: false,
|
|
2807
2821
|
blockedUntilEpoch: 0,
|
|
2808
2822
|
modelWeeklyLimits: {
|
|
2809
2823
|
seven_day_opus: {
|
|
@@ -2819,6 +2833,7 @@ describe('StartPreparationUseCase', () => {
|
|
|
2819
2833
|
sevenDayUtilization: 0.2,
|
|
2820
2834
|
blocked: false,
|
|
2821
2835
|
rejected: false,
|
|
2836
|
+
fiveHourRejected: false,
|
|
2822
2837
|
blockedUntilEpoch: 0,
|
|
2823
2838
|
modelWeeklyLimits: {
|
|
2824
2839
|
seven_day_opus: {
|
|
@@ -2890,6 +2905,7 @@ describe('StartPreparationUseCase', () => {
|
|
|
2890
2905
|
sevenDayUtilization: 0.7,
|
|
2891
2906
|
blocked: false,
|
|
2892
2907
|
rejected: false,
|
|
2908
|
+
fiveHourRejected: false,
|
|
2893
2909
|
blockedUntilEpoch: 0,
|
|
2894
2910
|
modelWeeklyLimits: {
|
|
2895
2911
|
seven_day_opus: {
|
|
@@ -2905,6 +2921,7 @@ describe('StartPreparationUseCase', () => {
|
|
|
2905
2921
|
sevenDayUtilization: 0.2,
|
|
2906
2922
|
blocked: false,
|
|
2907
2923
|
rejected: false,
|
|
2924
|
+
fiveHourRejected: false,
|
|
2908
2925
|
blockedUntilEpoch: 0,
|
|
2909
2926
|
modelWeeklyLimits: {
|
|
2910
2927
|
seven_day_opus: {
|
|
@@ -2965,6 +2982,7 @@ describe('StartPreparationUseCase', () => {
|
|
|
2965
2982
|
sevenDayUtilization: 0,
|
|
2966
2983
|
blocked: true,
|
|
2967
2984
|
rejected: false,
|
|
2985
|
+
fiveHourRejected: false,
|
|
2968
2986
|
blockedUntilEpoch: 0,
|
|
2969
2987
|
modelWeeklyLimits: {},
|
|
2970
2988
|
},
|
|
@@ -2975,6 +2993,7 @@ describe('StartPreparationUseCase', () => {
|
|
|
2975
2993
|
sevenDayUtilization: 0,
|
|
2976
2994
|
blocked: false,
|
|
2977
2995
|
rejected: false,
|
|
2996
|
+
fiveHourRejected: false,
|
|
2978
2997
|
blockedUntilEpoch: 0,
|
|
2979
2998
|
modelWeeklyLimits: {},
|
|
2980
2999
|
},
|
|
@@ -3031,6 +3050,7 @@ describe('StartPreparationUseCase', () => {
|
|
|
3031
3050
|
sevenDayUtilization: 0,
|
|
3032
3051
|
blocked: false,
|
|
3033
3052
|
rejected: false,
|
|
3053
|
+
fiveHourRejected: false,
|
|
3034
3054
|
blockedUntilEpoch: nowEpochSeconds + 90,
|
|
3035
3055
|
modelWeeklyLimits: {},
|
|
3036
3056
|
},
|
|
@@ -3041,6 +3061,7 @@ describe('StartPreparationUseCase', () => {
|
|
|
3041
3061
|
sevenDayUtilization: 0,
|
|
3042
3062
|
blocked: false,
|
|
3043
3063
|
rejected: false,
|
|
3064
|
+
fiveHourRejected: false,
|
|
3044
3065
|
blockedUntilEpoch: 0,
|
|
3045
3066
|
modelWeeklyLimits: {},
|
|
3046
3067
|
},
|
|
@@ -3096,6 +3117,7 @@ describe('StartPreparationUseCase', () => {
|
|
|
3096
3117
|
sevenDayUtilization: 0,
|
|
3097
3118
|
blocked: true,
|
|
3098
3119
|
rejected: false,
|
|
3120
|
+
fiveHourRejected: false,
|
|
3099
3121
|
blockedUntilEpoch: 0,
|
|
3100
3122
|
modelWeeklyLimits: {},
|
|
3101
3123
|
},
|
|
@@ -3106,6 +3128,7 @@ describe('StartPreparationUseCase', () => {
|
|
|
3106
3128
|
sevenDayUtilization: 0,
|
|
3107
3129
|
blocked: true,
|
|
3108
3130
|
rejected: false,
|
|
3131
|
+
fiveHourRejected: false,
|
|
3109
3132
|
blockedUntilEpoch: 0,
|
|
3110
3133
|
modelWeeklyLimits: {},
|
|
3111
3134
|
},
|
|
@@ -3167,6 +3190,7 @@ describe('StartPreparationUseCase', () => {
|
|
|
3167
3190
|
sevenDayUtilization: 0,
|
|
3168
3191
|
blocked: false,
|
|
3169
3192
|
rejected: false,
|
|
3193
|
+
fiveHourRejected: false,
|
|
3170
3194
|
blockedUntilEpoch: 0,
|
|
3171
3195
|
modelWeeklyLimits: {},
|
|
3172
3196
|
},
|
|
@@ -3177,6 +3201,7 @@ describe('StartPreparationUseCase', () => {
|
|
|
3177
3201
|
sevenDayUtilization: 0,
|
|
3178
3202
|
blocked: false,
|
|
3179
3203
|
rejected: false,
|
|
3204
|
+
fiveHourRejected: false,
|
|
3180
3205
|
blockedUntilEpoch: 0,
|
|
3181
3206
|
modelWeeklyLimits: {},
|
|
3182
3207
|
},
|
|
@@ -3257,6 +3282,7 @@ describe('StartPreparationUseCase', () => {
|
|
|
3257
3282
|
sevenDayUtilization: 0.5,
|
|
3258
3283
|
blocked: false,
|
|
3259
3284
|
rejected: false,
|
|
3285
|
+
fiveHourRejected: false,
|
|
3260
3286
|
blockedUntilEpoch: 0,
|
|
3261
3287
|
modelWeeklyLimits: {
|
|
3262
3288
|
seven_day_opus: {
|
|
@@ -3272,6 +3298,7 @@ describe('StartPreparationUseCase', () => {
|
|
|
3272
3298
|
sevenDayUtilization: 0.1,
|
|
3273
3299
|
blocked: false,
|
|
3274
3300
|
rejected: false,
|
|
3301
|
+
fiveHourRejected: false,
|
|
3275
3302
|
blockedUntilEpoch: 0,
|
|
3276
3303
|
modelWeeklyLimits: {
|
|
3277
3304
|
seven_day_opus: {
|
|
@@ -3287,6 +3314,7 @@ describe('StartPreparationUseCase', () => {
|
|
|
3287
3314
|
sevenDayUtilization: 0.7,
|
|
3288
3315
|
blocked: false,
|
|
3289
3316
|
rejected: false,
|
|
3317
|
+
fiveHourRejected: false,
|
|
3290
3318
|
blockedUntilEpoch: 0,
|
|
3291
3319
|
modelWeeklyLimits: {
|
|
3292
3320
|
seven_day_opus: {
|
|
@@ -3356,6 +3384,7 @@ describe('StartPreparationUseCase', () => {
|
|
|
3356
3384
|
sevenDayUtilization: 0.1,
|
|
3357
3385
|
blocked: false,
|
|
3358
3386
|
rejected: false,
|
|
3387
|
+
fiveHourRejected: false,
|
|
3359
3388
|
blockedUntilEpoch: 0,
|
|
3360
3389
|
modelWeeklyLimits: {
|
|
3361
3390
|
seven_day_opus: {
|
|
@@ -3371,6 +3400,7 @@ describe('StartPreparationUseCase', () => {
|
|
|
3371
3400
|
sevenDayUtilization: 0.1,
|
|
3372
3401
|
blocked: false,
|
|
3373
3402
|
rejected: false,
|
|
3403
|
+
fiveHourRejected: false,
|
|
3374
3404
|
blockedUntilEpoch: 0,
|
|
3375
3405
|
modelWeeklyLimits: {
|
|
3376
3406
|
seven_day_opus: {
|
|
@@ -3436,6 +3466,7 @@ describe('StartPreparationUseCase', () => {
|
|
|
3436
3466
|
sevenDayUtilization: 0.9,
|
|
3437
3467
|
blocked: false,
|
|
3438
3468
|
rejected: false,
|
|
3469
|
+
fiveHourRejected: false,
|
|
3439
3470
|
blockedUntilEpoch: 0,
|
|
3440
3471
|
modelWeeklyLimits: {},
|
|
3441
3472
|
},
|
|
@@ -3491,6 +3522,7 @@ describe('StartPreparationUseCase', () => {
|
|
|
3491
3522
|
sevenDayUtilization: 0,
|
|
3492
3523
|
blocked: false,
|
|
3493
3524
|
rejected: true,
|
|
3525
|
+
fiveHourRejected: true,
|
|
3494
3526
|
blockedUntilEpoch: 0,
|
|
3495
3527
|
modelWeeklyLimits: {},
|
|
3496
3528
|
},
|
|
@@ -3501,6 +3533,7 @@ describe('StartPreparationUseCase', () => {
|
|
|
3501
3533
|
sevenDayUtilization: 0,
|
|
3502
3534
|
blocked: false,
|
|
3503
3535
|
rejected: false,
|
|
3536
|
+
fiveHourRejected: false,
|
|
3504
3537
|
blockedUntilEpoch: 0,
|
|
3505
3538
|
modelWeeklyLimits: {},
|
|
3506
3539
|
},
|
|
@@ -3556,6 +3589,7 @@ describe('StartPreparationUseCase', () => {
|
|
|
3556
3589
|
sevenDayUtilization: 0,
|
|
3557
3590
|
blocked: false,
|
|
3558
3591
|
rejected: false,
|
|
3592
|
+
fiveHourRejected: false,
|
|
3559
3593
|
blockedUntilEpoch: 0,
|
|
3560
3594
|
modelWeeklyLimits: {},
|
|
3561
3595
|
},
|
|
@@ -3566,6 +3600,7 @@ describe('StartPreparationUseCase', () => {
|
|
|
3566
3600
|
sevenDayUtilization: 0,
|
|
3567
3601
|
blocked: false,
|
|
3568
3602
|
rejected: false,
|
|
3603
|
+
fiveHourRejected: false,
|
|
3569
3604
|
blockedUntilEpoch: 0,
|
|
3570
3605
|
modelWeeklyLimits: {},
|
|
3571
3606
|
},
|
|
@@ -3621,6 +3656,7 @@ describe('StartPreparationUseCase', () => {
|
|
|
3621
3656
|
sevenDayUtilization: 0,
|
|
3622
3657
|
blocked: false,
|
|
3623
3658
|
rejected: true,
|
|
3659
|
+
fiveHourRejected: true,
|
|
3624
3660
|
blockedUntilEpoch: 0,
|
|
3625
3661
|
modelWeeklyLimits: {},
|
|
3626
3662
|
},
|
|
@@ -3631,6 +3667,7 @@ describe('StartPreparationUseCase', () => {
|
|
|
3631
3667
|
sevenDayUtilization: 0,
|
|
3632
3668
|
blocked: false,
|
|
3633
3669
|
rejected: false,
|
|
3670
|
+
fiveHourRejected: false,
|
|
3634
3671
|
blockedUntilEpoch: 0,
|
|
3635
3672
|
modelWeeklyLimits: {},
|
|
3636
3673
|
},
|
|
@@ -3686,6 +3723,7 @@ describe('StartPreparationUseCase', () => {
|
|
|
3686
3723
|
sevenDayUtilization: 0,
|
|
3687
3724
|
blocked: false,
|
|
3688
3725
|
rejected: true,
|
|
3726
|
+
fiveHourRejected: true,
|
|
3689
3727
|
blockedUntilEpoch: 0,
|
|
3690
3728
|
modelWeeklyLimits: {},
|
|
3691
3729
|
},
|
|
@@ -3696,6 +3734,7 @@ describe('StartPreparationUseCase', () => {
|
|
|
3696
3734
|
sevenDayUtilization: 0,
|
|
3697
3735
|
blocked: false,
|
|
3698
3736
|
rejected: true,
|
|
3737
|
+
fiveHourRejected: true,
|
|
3699
3738
|
blockedUntilEpoch: 0,
|
|
3700
3739
|
modelWeeklyLimits: {},
|
|
3701
3740
|
},
|
|
@@ -3803,6 +3842,7 @@ describe('StartPreparationUseCase', () => {
|
|
|
3803
3842
|
sevenDayUtilization: 0,
|
|
3804
3843
|
blocked: false,
|
|
3805
3844
|
rejected: false,
|
|
3845
|
+
fiveHourRejected: false,
|
|
3806
3846
|
blockedUntilEpoch: 0,
|
|
3807
3847
|
modelWeeklyLimits: {
|
|
3808
3848
|
seven_day_sonnet: { rejected: false, resetsAt: pastReset },
|
|
@@ -3815,6 +3855,7 @@ describe('StartPreparationUseCase', () => {
|
|
|
3815
3855
|
sevenDayUtilization: 0,
|
|
3816
3856
|
blocked: false,
|
|
3817
3857
|
rejected: false,
|
|
3858
|
+
fiveHourRejected: false,
|
|
3818
3859
|
blockedUntilEpoch: 0,
|
|
3819
3860
|
modelWeeklyLimits: {},
|
|
3820
3861
|
},
|
|
@@ -3871,6 +3912,7 @@ describe('StartPreparationUseCase', () => {
|
|
|
3871
3912
|
sevenDayUtilization: 0,
|
|
3872
3913
|
blocked: false,
|
|
3873
3914
|
rejected: false,
|
|
3915
|
+
fiveHourRejected: false,
|
|
3874
3916
|
blockedUntilEpoch: 0,
|
|
3875
3917
|
modelWeeklyLimits: {
|
|
3876
3918
|
seven_day_sonnet: { rejected: true, resetsAt: futureReset },
|
|
@@ -3883,6 +3925,7 @@ describe('StartPreparationUseCase', () => {
|
|
|
3883
3925
|
sevenDayUtilization: 0,
|
|
3884
3926
|
blocked: false,
|
|
3885
3927
|
rejected: false,
|
|
3928
|
+
fiveHourRejected: false,
|
|
3886
3929
|
blockedUntilEpoch: 0,
|
|
3887
3930
|
modelWeeklyLimits: {},
|
|
3888
3931
|
},
|
|
@@ -3939,6 +3982,7 @@ describe('StartPreparationUseCase', () => {
|
|
|
3939
3982
|
sevenDayUtilization: 0,
|
|
3940
3983
|
blocked: false,
|
|
3941
3984
|
rejected: false,
|
|
3985
|
+
fiveHourRejected: false,
|
|
3942
3986
|
blockedUntilEpoch: 0,
|
|
3943
3987
|
modelWeeklyLimits: {
|
|
3944
3988
|
seven_day: { rejected: true, resetsAt: futureReset },
|
|
@@ -3951,6 +3995,7 @@ describe('StartPreparationUseCase', () => {
|
|
|
3951
3995
|
sevenDayUtilization: 0,
|
|
3952
3996
|
blocked: false,
|
|
3953
3997
|
rejected: false,
|
|
3998
|
+
fiveHourRejected: false,
|
|
3954
3999
|
blockedUntilEpoch: 0,
|
|
3955
4000
|
modelWeeklyLimits: {},
|
|
3956
4001
|
},
|
|
@@ -4007,6 +4052,7 @@ describe('StartPreparationUseCase', () => {
|
|
|
4007
4052
|
sevenDayUtilization: 0.1,
|
|
4008
4053
|
blocked: false,
|
|
4009
4054
|
rejected: false,
|
|
4055
|
+
fiveHourRejected: false,
|
|
4010
4056
|
blockedUntilEpoch: 0,
|
|
4011
4057
|
modelWeeklyLimits: {
|
|
4012
4058
|
seven_day_opus: {
|
|
@@ -4022,6 +4068,7 @@ describe('StartPreparationUseCase', () => {
|
|
|
4022
4068
|
sevenDayUtilization: 0.1,
|
|
4023
4069
|
blocked: false,
|
|
4024
4070
|
rejected: false,
|
|
4071
|
+
fiveHourRejected: false,
|
|
4025
4072
|
blockedUntilEpoch: 0,
|
|
4026
4073
|
modelWeeklyLimits: {
|
|
4027
4074
|
seven_day_opus: {
|
|
@@ -4083,6 +4130,7 @@ describe('StartPreparationUseCase', () => {
|
|
|
4083
4130
|
sevenDayUtilization: 0.1,
|
|
4084
4131
|
blocked: true,
|
|
4085
4132
|
rejected: false,
|
|
4133
|
+
fiveHourRejected: false,
|
|
4086
4134
|
blockedUntilEpoch: 0,
|
|
4087
4135
|
modelWeeklyLimits: {
|
|
4088
4136
|
seven_day_opus: {
|
|
@@ -4098,6 +4146,7 @@ describe('StartPreparationUseCase', () => {
|
|
|
4098
4146
|
sevenDayUtilization: 0.1,
|
|
4099
4147
|
blocked: false,
|
|
4100
4148
|
rejected: false,
|
|
4149
|
+
fiveHourRejected: false,
|
|
4101
4150
|
blockedUntilEpoch: 0,
|
|
4102
4151
|
modelWeeklyLimits: {
|
|
4103
4152
|
seven_day_opus: {
|
|
@@ -4169,6 +4218,7 @@ describe('StartPreparationUseCase', () => {
|
|
|
4169
4218
|
sevenDayUtilization: 0.1,
|
|
4170
4219
|
blocked: false,
|
|
4171
4220
|
rejected: false,
|
|
4221
|
+
fiveHourRejected: false,
|
|
4172
4222
|
blockedUntilEpoch: 0,
|
|
4173
4223
|
modelWeeklyLimits: {},
|
|
4174
4224
|
},
|
|
@@ -4179,6 +4229,7 @@ describe('StartPreparationUseCase', () => {
|
|
|
4179
4229
|
sevenDayUtilization: 0.1,
|
|
4180
4230
|
blocked: false,
|
|
4181
4231
|
rejected: false,
|
|
4232
|
+
fiveHourRejected: false,
|
|
4182
4233
|
blockedUntilEpoch: 0,
|
|
4183
4234
|
modelWeeklyLimits: {
|
|
4184
4235
|
seven_day_opus: {
|
|
@@ -4258,6 +4309,7 @@ describe('StartPreparationUseCase', () => {
|
|
|
4258
4309
|
sevenDayUtilization: 0.1,
|
|
4259
4310
|
blocked: false,
|
|
4260
4311
|
rejected: false,
|
|
4312
|
+
fiveHourRejected: false,
|
|
4261
4313
|
blockedUntilEpoch: 0,
|
|
4262
4314
|
modelWeeklyLimits: {
|
|
4263
4315
|
seven_day: {
|
|
@@ -4273,6 +4325,7 @@ describe('StartPreparationUseCase', () => {
|
|
|
4273
4325
|
sevenDayUtilization: 0.1,
|
|
4274
4326
|
blocked: false,
|
|
4275
4327
|
rejected: false,
|
|
4328
|
+
fiveHourRejected: false,
|
|
4276
4329
|
blockedUntilEpoch: 0,
|
|
4277
4330
|
modelWeeklyLimits: {
|
|
4278
4331
|
seven_day: {
|
|
@@ -4288,6 +4341,7 @@ describe('StartPreparationUseCase', () => {
|
|
|
4288
4341
|
sevenDayUtilization: 0.1,
|
|
4289
4342
|
blocked: false,
|
|
4290
4343
|
rejected: false,
|
|
4344
|
+
fiveHourRejected: false,
|
|
4291
4345
|
blockedUntilEpoch: 0,
|
|
4292
4346
|
modelWeeklyLimits: {
|
|
4293
4347
|
seven_day: {
|
|
@@ -4353,6 +4407,7 @@ describe('StartPreparationUseCase', () => {
|
|
|
4353
4407
|
sevenDayUtilization: 0.1,
|
|
4354
4408
|
blocked: false,
|
|
4355
4409
|
rejected: false,
|
|
4410
|
+
fiveHourRejected: false,
|
|
4356
4411
|
blockedUntilEpoch: 0,
|
|
4357
4412
|
modelWeeklyLimits: {
|
|
4358
4413
|
seven_day: { rejected: false, resetsAt: sharedResetsAt },
|
|
@@ -4365,6 +4420,7 @@ describe('StartPreparationUseCase', () => {
|
|
|
4365
4420
|
sevenDayUtilization: 0.1,
|
|
4366
4421
|
blocked: false,
|
|
4367
4422
|
rejected: false,
|
|
4423
|
+
fiveHourRejected: false,
|
|
4368
4424
|
blockedUntilEpoch: 0,
|
|
4369
4425
|
modelWeeklyLimits: {
|
|
4370
4426
|
seven_day: { rejected: false, resetsAt: sharedResetsAt },
|
|
@@ -4424,6 +4480,7 @@ describe('StartPreparationUseCase', () => {
|
|
|
4424
4480
|
sevenDayUtilization: 0.1,
|
|
4425
4481
|
blocked: false,
|
|
4426
4482
|
rejected: false,
|
|
4483
|
+
fiveHourRejected: false,
|
|
4427
4484
|
blockedUntilEpoch: 0,
|
|
4428
4485
|
modelWeeklyLimits: {
|
|
4429
4486
|
seven_day_opus: { rejected: false, resetsAt: sharedResetsAt },
|
|
@@ -4436,6 +4493,7 @@ describe('StartPreparationUseCase', () => {
|
|
|
4436
4493
|
sevenDayUtilization: 0.1,
|
|
4437
4494
|
blocked: false,
|
|
4438
4495
|
rejected: false,
|
|
4496
|
+
fiveHourRejected: false,
|
|
4439
4497
|
blockedUntilEpoch: 0,
|
|
4440
4498
|
modelWeeklyLimits: {
|
|
4441
4499
|
seven_day_opus: { rejected: false, resetsAt: sharedResetsAt },
|
|
@@ -4630,6 +4688,7 @@ describe('StartPreparationUseCase', () => {
|
|
|
4630
4688
|
sevenDayUtilization: 0,
|
|
4631
4689
|
blocked: false,
|
|
4632
4690
|
rejected: false,
|
|
4691
|
+
fiveHourRejected: false,
|
|
4633
4692
|
blockedUntilEpoch: 0,
|
|
4634
4693
|
modelWeeklyLimits: {
|
|
4635
4694
|
seven_day_sonnet: { rejected: true, resetsAt: futureReset },
|
|
@@ -4696,6 +4755,7 @@ describe('StartPreparationUseCase', () => {
|
|
|
4696
4755
|
sevenDayUtilization: 0,
|
|
4697
4756
|
blocked: false,
|
|
4698
4757
|
rejected: false,
|
|
4758
|
+
fiveHourRejected: false,
|
|
4699
4759
|
blockedUntilEpoch: 0,
|
|
4700
4760
|
modelWeeklyLimits: {
|
|
4701
4761
|
seven_day_sonnet: { rejected: true, resetsAt: futureReset },
|
|
@@ -4750,6 +4810,7 @@ describe('StartPreparationUseCase', () => {
|
|
|
4750
4810
|
sevenDayUtilization: 0,
|
|
4751
4811
|
blocked: false,
|
|
4752
4812
|
rejected: false,
|
|
4813
|
+
fiveHourRejected: false,
|
|
4753
4814
|
blockedUntilEpoch: 0,
|
|
4754
4815
|
modelWeeklyLimits: {
|
|
4755
4816
|
seven_day_sonnet: { rejected: true, resetsAt: futureReset },
|
|
@@ -4810,6 +4871,7 @@ describe('StartPreparationUseCase', () => {
|
|
|
4810
4871
|
sevenDayUtilization: 0,
|
|
4811
4872
|
blocked: false,
|
|
4812
4873
|
rejected: false,
|
|
4874
|
+
fiveHourRejected: false,
|
|
4813
4875
|
blockedUntilEpoch: 0,
|
|
4814
4876
|
modelWeeklyLimits: {},
|
|
4815
4877
|
},
|
|
@@ -4862,6 +4924,7 @@ describe('StartPreparationUseCase', () => {
|
|
|
4862
4924
|
sevenDayUtilization: 0,
|
|
4863
4925
|
blocked: false,
|
|
4864
4926
|
rejected: false,
|
|
4927
|
+
fiveHourRejected: false,
|
|
4865
4928
|
blockedUntilEpoch: 0,
|
|
4866
4929
|
modelWeeklyLimits: {
|
|
4867
4930
|
seven_day_sonnet: { rejected: true, resetsAt: futureReset },
|
|
@@ -4916,6 +4979,7 @@ describe('StartPreparationUseCase', () => {
|
|
|
4916
4979
|
sevenDayUtilization: 0,
|
|
4917
4980
|
blocked: false,
|
|
4918
4981
|
rejected: false,
|
|
4982
|
+
fiveHourRejected: false,
|
|
4919
4983
|
blockedUntilEpoch: 0,
|
|
4920
4984
|
modelWeeklyLimits: {},
|
|
4921
4985
|
},
|
|
@@ -4986,6 +5050,7 @@ describe('StartPreparationUseCase', () => {
|
|
|
4986
5050
|
sevenDayUtilization: 0,
|
|
4987
5051
|
blocked: false,
|
|
4988
5052
|
rejected: false,
|
|
5053
|
+
fiveHourRejected: false,
|
|
4989
5054
|
blockedUntilEpoch: 0,
|
|
4990
5055
|
modelWeeklyLimits: {
|
|
4991
5056
|
seven_day_sonnet: { rejected: true, resetsAt: futureReset },
|
|
@@ -4998,6 +5063,7 @@ describe('StartPreparationUseCase', () => {
|
|
|
4998
5063
|
sevenDayUtilization: 0,
|
|
4999
5064
|
blocked: false,
|
|
5000
5065
|
rejected: false,
|
|
5066
|
+
fiveHourRejected: false,
|
|
5001
5067
|
blockedUntilEpoch: 0,
|
|
5002
5068
|
modelWeeklyLimits: {},
|
|
5003
5069
|
},
|
|
@@ -5059,6 +5125,7 @@ describe('StartPreparationUseCase', () => {
|
|
|
5059
5125
|
sevenDayUtilization: 0,
|
|
5060
5126
|
blocked: false,
|
|
5061
5127
|
rejected: false,
|
|
5128
|
+
fiveHourRejected: false,
|
|
5062
5129
|
blockedUntilEpoch: 0,
|
|
5063
5130
|
modelWeeklyLimits: {
|
|
5064
5131
|
seven_day_sonnet: { rejected: true, resetsAt: futureReset },
|
|
@@ -5119,6 +5186,7 @@ describe('StartPreparationUseCase', () => {
|
|
|
5119
5186
|
sevenDayUtilization: 0,
|
|
5120
5187
|
blocked: false,
|
|
5121
5188
|
rejected: false,
|
|
5189
|
+
fiveHourRejected: false,
|
|
5122
5190
|
blockedUntilEpoch: 0,
|
|
5123
5191
|
modelWeeklyLimits: {
|
|
5124
5192
|
seven_day: { rejected: true, resetsAt: futureReset },
|
|
@@ -5177,6 +5245,7 @@ describe('StartPreparationUseCase', () => {
|
|
|
5177
5245
|
sevenDayUtilization: 0,
|
|
5178
5246
|
blocked: false,
|
|
5179
5247
|
rejected: false,
|
|
5248
|
+
fiveHourRejected: false,
|
|
5180
5249
|
blockedUntilEpoch: 0,
|
|
5181
5250
|
modelWeeklyLimits: {
|
|
5182
5251
|
seven_day_sonnet: { rejected: true, resetsAt: futureReset },
|
|
@@ -5210,6 +5279,186 @@ describe('StartPreparationUseCase', () => {
|
|
|
5210
5279
|
},
|
|
5211
5280
|
});
|
|
5212
5281
|
});
|
|
5282
|
+
|
|
5283
|
+
it('includes a token whose unified representative-claim status is rejected (seven_day_sonnet) while its Opus weekly window is allowed and routes it to Opus', async () => {
|
|
5284
|
+
const awaitingIssue = createMockIssue({
|
|
5285
|
+
url: 'url1',
|
|
5286
|
+
title: 'Issue 1',
|
|
5287
|
+
labels: ['category:impl'],
|
|
5288
|
+
status: 'Awaiting Workspace',
|
|
5289
|
+
number: 1,
|
|
5290
|
+
itemId: 'item-1',
|
|
5291
|
+
});
|
|
5292
|
+
mockProjectRepository.getByUrl.mockResolvedValue(mockProject);
|
|
5293
|
+
mockIssueRepository.getStoryObjectMap.mockResolvedValue(
|
|
5294
|
+
createMockStoryObjectMap([awaitingIssue]),
|
|
5295
|
+
);
|
|
5296
|
+
mockLocalCommandRunner.runCommand.mockResolvedValue({
|
|
5297
|
+
stdout: '',
|
|
5298
|
+
stderr: '',
|
|
5299
|
+
exitCode: 0,
|
|
5300
|
+
});
|
|
5301
|
+
mockClaudeTokenUsageRepository.getAvailableTokenUsages.mockResolvedValue([
|
|
5302
|
+
{
|
|
5303
|
+
name: 'token-sonnet-rejected-unified',
|
|
5304
|
+
token: 'token-sonnet-rejected-unified',
|
|
5305
|
+
fiveHourUtilization: 0.53,
|
|
5306
|
+
sevenDayUtilization: 0.88,
|
|
5307
|
+
blocked: false,
|
|
5308
|
+
rejected: true,
|
|
5309
|
+
fiveHourRejected: false,
|
|
5310
|
+
blockedUntilEpoch: 0,
|
|
5311
|
+
modelWeeklyLimits: {
|
|
5312
|
+
seven_day_sonnet: { rejected: true, resetsAt: futureReset },
|
|
5313
|
+
seven_day_opus: { rejected: false, resetsAt: futureReset },
|
|
5314
|
+
},
|
|
5315
|
+
},
|
|
5316
|
+
]);
|
|
5317
|
+
|
|
5318
|
+
await useCase.run({
|
|
5319
|
+
projectUrl: 'https://github.com/user/repo',
|
|
5320
|
+
defaultAgentName: 'agent1',
|
|
5321
|
+
defaultLlmModelName: 'claude-sonnet-4-6',
|
|
5322
|
+
fallbackLlmModelName: 'claude-opus-4-8',
|
|
5323
|
+
defaultLlmAgentName: null,
|
|
5324
|
+
configFilePath: '/path/to/config.yml',
|
|
5325
|
+
maximumPreparingIssuesCount: null,
|
|
5326
|
+
utilizationPercentageThreshold: 90,
|
|
5327
|
+
allowedIssueAuthors: null,
|
|
5328
|
+
codexHomeCandidates: null,
|
|
5329
|
+
allowIssueCacheMinutes: 0,
|
|
5330
|
+
labelsAsLlmAgentName: null,
|
|
5331
|
+
});
|
|
5332
|
+
|
|
5333
|
+
expect(mockLocalCommandRunner.runCommand.mock.calls).toHaveLength(1);
|
|
5334
|
+
expect(
|
|
5335
|
+
mockLocalCommandRunner.runCommand.mock.calls[0][2]?.env
|
|
5336
|
+
?.CLAUDE_CODE_OAUTH_TOKEN,
|
|
5337
|
+
).toBe('token-sonnet-rejected-unified');
|
|
5338
|
+
expect(mockLocalCommandRunner.runCommand.mock.calls[0][1][2]).toBe(
|
|
5339
|
+
'claude-opus-4-8',
|
|
5340
|
+
);
|
|
5341
|
+
});
|
|
5342
|
+
|
|
5343
|
+
it('excludes a token whose 5-hour window is rejected even when its Opus weekly window is allowed', async () => {
|
|
5344
|
+
const awaitingIssue = createMockIssue({
|
|
5345
|
+
url: 'url1',
|
|
5346
|
+
title: 'Issue 1',
|
|
5347
|
+
labels: ['category:impl'],
|
|
5348
|
+
status: 'Awaiting Workspace',
|
|
5349
|
+
number: 1,
|
|
5350
|
+
itemId: 'item-1',
|
|
5351
|
+
});
|
|
5352
|
+
mockProjectRepository.getByUrl.mockResolvedValue(mockProject);
|
|
5353
|
+
mockIssueRepository.getStoryObjectMap.mockResolvedValue(
|
|
5354
|
+
createMockStoryObjectMap([awaitingIssue]),
|
|
5355
|
+
);
|
|
5356
|
+
mockLocalCommandRunner.runCommand.mockResolvedValue({
|
|
5357
|
+
stdout: '',
|
|
5358
|
+
stderr: '',
|
|
5359
|
+
exitCode: 0,
|
|
5360
|
+
});
|
|
5361
|
+
mockClaudeTokenUsageRepository.getAvailableTokenUsages.mockResolvedValue([
|
|
5362
|
+
{
|
|
5363
|
+
name: 'token-5h-rejected',
|
|
5364
|
+
token: 'token-5h-rejected',
|
|
5365
|
+
fiveHourUtilization: 0.1,
|
|
5366
|
+
sevenDayUtilization: 0,
|
|
5367
|
+
blocked: false,
|
|
5368
|
+
rejected: true,
|
|
5369
|
+
fiveHourRejected: true,
|
|
5370
|
+
blockedUntilEpoch: 0,
|
|
5371
|
+
modelWeeklyLimits: {
|
|
5372
|
+
seven_day_opus: { rejected: false, resetsAt: futureReset },
|
|
5373
|
+
},
|
|
5374
|
+
},
|
|
5375
|
+
]);
|
|
5376
|
+
const consoleWarnSpy = jest
|
|
5377
|
+
.spyOn(console, 'warn')
|
|
5378
|
+
.mockImplementation(() => {});
|
|
5379
|
+
|
|
5380
|
+
await useCase.run({
|
|
5381
|
+
projectUrl: 'https://github.com/user/repo',
|
|
5382
|
+
defaultAgentName: 'agent1',
|
|
5383
|
+
defaultLlmModelName: 'claude-sonnet-4-6',
|
|
5384
|
+
fallbackLlmModelName: 'claude-opus-4-8',
|
|
5385
|
+
defaultLlmAgentName: null,
|
|
5386
|
+
configFilePath: '/path/to/config.yml',
|
|
5387
|
+
maximumPreparingIssuesCount: null,
|
|
5388
|
+
utilizationPercentageThreshold: 90,
|
|
5389
|
+
allowedIssueAuthors: null,
|
|
5390
|
+
codexHomeCandidates: null,
|
|
5391
|
+
allowIssueCacheMinutes: 0,
|
|
5392
|
+
labelsAsLlmAgentName: null,
|
|
5393
|
+
});
|
|
5394
|
+
|
|
5395
|
+
expect(mockLocalCommandRunner.runCommand.mock.calls).toHaveLength(0);
|
|
5396
|
+
expect(mockIssueRepository.updateStatus.mock.calls).toHaveLength(0);
|
|
5397
|
+
expect(consoleWarnSpy).toHaveBeenCalledWith(
|
|
5398
|
+
expect.stringContaining('Skipping starting preparation'),
|
|
5399
|
+
);
|
|
5400
|
+
consoleWarnSpy.mockRestore();
|
|
5401
|
+
});
|
|
5402
|
+
|
|
5403
|
+
it('excludes a token whose unified status is rejected and whose seven_day_sonnet and seven_day_opus weekly windows are both rejected', async () => {
|
|
5404
|
+
const awaitingIssue = createMockIssue({
|
|
5405
|
+
url: 'url1',
|
|
5406
|
+
title: 'Issue 1',
|
|
5407
|
+
labels: ['category:impl'],
|
|
5408
|
+
status: 'Awaiting Workspace',
|
|
5409
|
+
number: 1,
|
|
5410
|
+
itemId: 'item-1',
|
|
5411
|
+
});
|
|
5412
|
+
mockProjectRepository.getByUrl.mockResolvedValue(mockProject);
|
|
5413
|
+
mockIssueRepository.getStoryObjectMap.mockResolvedValue(
|
|
5414
|
+
createMockStoryObjectMap([awaitingIssue]),
|
|
5415
|
+
);
|
|
5416
|
+
mockLocalCommandRunner.runCommand.mockResolvedValue({
|
|
5417
|
+
stdout: '',
|
|
5418
|
+
stderr: '',
|
|
5419
|
+
exitCode: 0,
|
|
5420
|
+
});
|
|
5421
|
+
mockClaudeTokenUsageRepository.getAvailableTokenUsages.mockResolvedValue([
|
|
5422
|
+
{
|
|
5423
|
+
name: 'token-both-rejected-unified',
|
|
5424
|
+
token: 'token-both-rejected-unified',
|
|
5425
|
+
fiveHourUtilization: 0.1,
|
|
5426
|
+
sevenDayUtilization: 0,
|
|
5427
|
+
blocked: false,
|
|
5428
|
+
rejected: true,
|
|
5429
|
+
fiveHourRejected: false,
|
|
5430
|
+
blockedUntilEpoch: 0,
|
|
5431
|
+
modelWeeklyLimits: {
|
|
5432
|
+
seven_day_sonnet: { rejected: true, resetsAt: futureReset },
|
|
5433
|
+
seven_day_opus: { rejected: true, resetsAt: futureReset },
|
|
5434
|
+
},
|
|
5435
|
+
},
|
|
5436
|
+
]);
|
|
5437
|
+
const consoleWarnSpy = jest
|
|
5438
|
+
.spyOn(console, 'warn')
|
|
5439
|
+
.mockImplementation(() => {});
|
|
5440
|
+
|
|
5441
|
+
await useCase.run({
|
|
5442
|
+
projectUrl: 'https://github.com/user/repo',
|
|
5443
|
+
defaultAgentName: 'agent1',
|
|
5444
|
+
defaultLlmModelName: 'claude-sonnet-4-6',
|
|
5445
|
+
fallbackLlmModelName: 'claude-opus-4-8',
|
|
5446
|
+
defaultLlmAgentName: null,
|
|
5447
|
+
configFilePath: '/path/to/config.yml',
|
|
5448
|
+
maximumPreparingIssuesCount: null,
|
|
5449
|
+
utilizationPercentageThreshold: 90,
|
|
5450
|
+
allowedIssueAuthors: null,
|
|
5451
|
+
codexHomeCandidates: null,
|
|
5452
|
+
allowIssueCacheMinutes: 0,
|
|
5453
|
+
labelsAsLlmAgentName: null,
|
|
5454
|
+
});
|
|
5455
|
+
|
|
5456
|
+
expect(mockLocalCommandRunner.runCommand.mock.calls).toHaveLength(0);
|
|
5457
|
+
expect(consoleWarnSpy).toHaveBeenCalledWith(
|
|
5458
|
+
expect.stringContaining('Skipping starting preparation'),
|
|
5459
|
+
);
|
|
5460
|
+
consoleWarnSpy.mockRestore();
|
|
5461
|
+
});
|
|
5213
5462
|
});
|
|
5214
5463
|
|
|
5215
5464
|
describe('per-token in-flight global concurrency enforcement', () => {
|
|
@@ -5241,6 +5490,7 @@ describe('StartPreparationUseCase', () => {
|
|
|
5241
5490
|
sevenDayUtilization: 0.9,
|
|
5242
5491
|
blocked: false,
|
|
5243
5492
|
rejected: false,
|
|
5493
|
+
fiveHourRejected: false,
|
|
5244
5494
|
blockedUntilEpoch: 0,
|
|
5245
5495
|
modelWeeklyLimits: {},
|
|
5246
5496
|
},
|
|
@@ -5295,6 +5545,7 @@ describe('StartPreparationUseCase', () => {
|
|
|
5295
5545
|
sevenDayUtilization: 0.9,
|
|
5296
5546
|
blocked: false,
|
|
5297
5547
|
rejected: false,
|
|
5548
|
+
fiveHourRejected: false,
|
|
5298
5549
|
blockedUntilEpoch: 0,
|
|
5299
5550
|
modelWeeklyLimits: {},
|
|
5300
5551
|
},
|
|
@@ -5349,6 +5600,7 @@ describe('StartPreparationUseCase', () => {
|
|
|
5349
5600
|
sevenDayUtilization: 0.9,
|
|
5350
5601
|
blocked: false,
|
|
5351
5602
|
rejected: false,
|
|
5603
|
+
fiveHourRejected: false,
|
|
5352
5604
|
blockedUntilEpoch: 0,
|
|
5353
5605
|
modelWeeklyLimits: {},
|
|
5354
5606
|
},
|
|
@@ -5359,6 +5611,7 @@ describe('StartPreparationUseCase', () => {
|
|
|
5359
5611
|
sevenDayUtilization: 0.1,
|
|
5360
5612
|
blocked: false,
|
|
5361
5613
|
rejected: false,
|
|
5614
|
+
fiveHourRejected: false,
|
|
5362
5615
|
blockedUntilEpoch: 0,
|
|
5363
5616
|
modelWeeklyLimits: {},
|
|
5364
5617
|
},
|
|
@@ -5448,6 +5701,7 @@ describe('StartPreparationUseCase.buildRotationOrder', () => {
|
|
|
5448
5701
|
sevenDayUtilization: 0.8,
|
|
5449
5702
|
blocked: false,
|
|
5450
5703
|
rejected: false,
|
|
5704
|
+
fiveHourRejected: false,
|
|
5451
5705
|
blockedUntilEpoch: 0,
|
|
5452
5706
|
modelWeeklyLimits: {
|
|
5453
5707
|
seven_day: {
|
|
@@ -5463,6 +5717,7 @@ describe('StartPreparationUseCase.buildRotationOrder', () => {
|
|
|
5463
5717
|
sevenDayUtilization: 0.1,
|
|
5464
5718
|
blocked: false,
|
|
5465
5719
|
rejected: false,
|
|
5720
|
+
fiveHourRejected: false,
|
|
5466
5721
|
blockedUntilEpoch: 0,
|
|
5467
5722
|
modelWeeklyLimits: {
|
|
5468
5723
|
seven_day: {
|
|
@@ -5478,6 +5733,7 @@ describe('StartPreparationUseCase.buildRotationOrder', () => {
|
|
|
5478
5733
|
sevenDayUtilization: 0,
|
|
5479
5734
|
blocked: true,
|
|
5480
5735
|
rejected: false,
|
|
5736
|
+
fiveHourRejected: false,
|
|
5481
5737
|
blockedUntilEpoch: 0,
|
|
5482
5738
|
modelWeeklyLimits: {},
|
|
5483
5739
|
},
|
|
@@ -5500,6 +5756,7 @@ describe('StartPreparationUseCase.buildRotationOrder', () => {
|
|
|
5500
5756
|
sevenDayUtilization: 0,
|
|
5501
5757
|
blocked: false,
|
|
5502
5758
|
rejected: false,
|
|
5759
|
+
fiveHourRejected: false,
|
|
5503
5760
|
blockedUntilEpoch: 0,
|
|
5504
5761
|
modelWeeklyLimits: {},
|
|
5505
5762
|
},
|
|
@@ -5520,6 +5777,7 @@ describe('StartPreparationUseCase.buildRotationOrder', () => {
|
|
|
5520
5777
|
sevenDayUtilization: 0,
|
|
5521
5778
|
blocked: false,
|
|
5522
5779
|
rejected: false,
|
|
5780
|
+
fiveHourRejected: false,
|
|
5523
5781
|
blockedUntilEpoch: 0,
|
|
5524
5782
|
modelWeeklyLimits: {},
|
|
5525
5783
|
},
|
|
@@ -5541,6 +5799,7 @@ describe('StartPreparationUseCase.buildRotationOrder', () => {
|
|
|
5541
5799
|
sevenDayUtilization: 0,
|
|
5542
5800
|
blocked: false,
|
|
5543
5801
|
rejected: false,
|
|
5802
|
+
fiveHourRejected: false,
|
|
5544
5803
|
blockedUntilEpoch: 0,
|
|
5545
5804
|
modelWeeklyLimits: {},
|
|
5546
5805
|
},
|
|
@@ -5564,6 +5823,7 @@ describe('StartPreparationUseCase.buildRotationOrder', () => {
|
|
|
5564
5823
|
sevenDayUtilization: 0,
|
|
5565
5824
|
blocked: false,
|
|
5566
5825
|
rejected: false,
|
|
5826
|
+
fiveHourRejected: false,
|
|
5567
5827
|
blockedUntilEpoch: nowEpochSeconds + 90,
|
|
5568
5828
|
modelWeeklyLimits: {},
|
|
5569
5829
|
},
|
|
@@ -5574,6 +5834,7 @@ describe('StartPreparationUseCase.buildRotationOrder', () => {
|
|
|
5574
5834
|
sevenDayUtilization: 0,
|
|
5575
5835
|
blocked: false,
|
|
5576
5836
|
rejected: false,
|
|
5837
|
+
fiveHourRejected: false,
|
|
5577
5838
|
blockedUntilEpoch: 0,
|
|
5578
5839
|
modelWeeklyLimits: {},
|
|
5579
5840
|
},
|
|
@@ -5599,6 +5860,7 @@ describe('StartPreparationUseCase.buildRotationOrder', () => {
|
|
|
5599
5860
|
sevenDayUtilization: 0,
|
|
5600
5861
|
blocked: false,
|
|
5601
5862
|
rejected: false,
|
|
5863
|
+
fiveHourRejected: false,
|
|
5602
5864
|
blockedUntilEpoch: nowEpochSeconds - 1,
|
|
5603
5865
|
modelWeeklyLimits: {},
|
|
5604
5866
|
},
|
|
@@ -5611,6 +5873,87 @@ describe('StartPreparationUseCase.buildRotationOrder', () => {
|
|
|
5611
5873
|
expect(result[0].cooldownExcluded).toBe(false);
|
|
5612
5874
|
expect(result[0].thresholdExcluded).toBe(false);
|
|
5613
5875
|
});
|
|
5876
|
+
|
|
5877
|
+
it('selects a token whose unified status is rejected but whose requested model weekly window is allowed', () => {
|
|
5878
|
+
const nowEpochSeconds = Math.floor(Date.now() / 1000);
|
|
5879
|
+
const tokenUsages: ClaudeTokenUsage[] = [
|
|
5880
|
+
{
|
|
5881
|
+
name: 'sonnet-rejected-opus-ok',
|
|
5882
|
+
token: 'sk-ant-sonnet-rejected',
|
|
5883
|
+
fiveHourUtilization: 0.53,
|
|
5884
|
+
sevenDayUtilization: 0.88,
|
|
5885
|
+
blocked: false,
|
|
5886
|
+
rejected: true,
|
|
5887
|
+
fiveHourRejected: false,
|
|
5888
|
+
blockedUntilEpoch: 0,
|
|
5889
|
+
modelWeeklyLimits: {
|
|
5890
|
+
seven_day_sonnet: {
|
|
5891
|
+
rejected: true,
|
|
5892
|
+
resetsAt: nowEpochSeconds + 20 * 3600,
|
|
5893
|
+
},
|
|
5894
|
+
seven_day_opus: {
|
|
5895
|
+
rejected: false,
|
|
5896
|
+
resetsAt: nowEpochSeconds + 20 * 3600,
|
|
5897
|
+
},
|
|
5898
|
+
},
|
|
5899
|
+
},
|
|
5900
|
+
];
|
|
5901
|
+
|
|
5902
|
+
const result = useCase.buildRotationOrder(
|
|
5903
|
+
tokenUsages,
|
|
5904
|
+
90,
|
|
5905
|
+
'claude-opus-4-8',
|
|
5906
|
+
);
|
|
5907
|
+
|
|
5908
|
+
expect(result).toHaveLength(1);
|
|
5909
|
+
expect(result[0].name).toBe('sonnet-rejected-opus-ok');
|
|
5910
|
+
expect(result[0].rejected).toBe(false);
|
|
5911
|
+
expect(result[0].thresholdExcluded).toBe(false);
|
|
5912
|
+
expect(result[0].cooldownExcluded).toBe(false);
|
|
5913
|
+
});
|
|
5914
|
+
|
|
5915
|
+
it('excludes a token whose 5-hour window is rejected and marks it rejected in the rotation entry', () => {
|
|
5916
|
+
const nowEpochSeconds = Math.floor(Date.now() / 1000);
|
|
5917
|
+
const tokenUsages: ClaudeTokenUsage[] = [
|
|
5918
|
+
{
|
|
5919
|
+
name: 'five-hour-rejected',
|
|
5920
|
+
token: 'sk-ant-5h-rejected',
|
|
5921
|
+
fiveHourUtilization: 0.1,
|
|
5922
|
+
sevenDayUtilization: 0,
|
|
5923
|
+
blocked: false,
|
|
5924
|
+
rejected: true,
|
|
5925
|
+
fiveHourRejected: true,
|
|
5926
|
+
blockedUntilEpoch: 0,
|
|
5927
|
+
modelWeeklyLimits: {
|
|
5928
|
+
seven_day_opus: {
|
|
5929
|
+
rejected: false,
|
|
5930
|
+
resetsAt: nowEpochSeconds + 20 * 3600,
|
|
5931
|
+
},
|
|
5932
|
+
},
|
|
5933
|
+
},
|
|
5934
|
+
{
|
|
5935
|
+
name: 'available',
|
|
5936
|
+
token: 'sk-ant-available',
|
|
5937
|
+
fiveHourUtilization: 0.2,
|
|
5938
|
+
sevenDayUtilization: 0,
|
|
5939
|
+
blocked: false,
|
|
5940
|
+
rejected: false,
|
|
5941
|
+
fiveHourRejected: false,
|
|
5942
|
+
blockedUntilEpoch: 0,
|
|
5943
|
+
modelWeeklyLimits: {},
|
|
5944
|
+
},
|
|
5945
|
+
];
|
|
5946
|
+
|
|
5947
|
+
const result = useCase.buildRotationOrder(tokenUsages, 90, null);
|
|
5948
|
+
|
|
5949
|
+
expect(result[0].name).toBe('available');
|
|
5950
|
+
const excluded = result.find(
|
|
5951
|
+
(entry) => entry.name === 'five-hour-rejected',
|
|
5952
|
+
);
|
|
5953
|
+
expect(excluded?.rejected).toBe(true);
|
|
5954
|
+
expect(excluded?.thresholdExcluded).toBe(false);
|
|
5955
|
+
expect(excluded?.cooldownExcluded).toBe(false);
|
|
5956
|
+
});
|
|
5614
5957
|
});
|
|
5615
5958
|
|
|
5616
5959
|
describe('StartPreparationUseCase.getTokenConcurrentLimit', () => {
|