@@ -624,7 +624,7 @@ export const OpenAIOAuthPlugin: Plugin = async ({ client }: PluginInput) => {
624624
625625
626626 type IdentityIndexes = {
627- byOrganizationId : Map < string , number > ;
627+ byOrganizationId : Map < string , number [ ] > ;
628628 byAccountIdNoOrg : Map < string , number > ;
629629 byRefreshTokenNoOrg : Map < string , number [ ] > ;
630630 byEmailNoOrg : Map < string , number > ;
@@ -633,6 +633,56 @@ export const OpenAIOAuthPlugin: Plugin = async ({ client }: PluginInput) => {
633633 byRefreshTokenGlobal : Map < string , number [ ] > ;
634634 } ;
635635
636+ const resolveOrganizationMatch = (
637+ indexes : IdentityIndexes ,
638+ organizationId : string ,
639+ candidateAccountId : string | undefined ,
640+ ) : number | undefined => {
641+ const matches = indexes . byOrganizationId . get ( organizationId ) ;
642+ if ( ! matches || matches . length === 0 ) return undefined ;
643+
644+ const candidateId = candidateAccountId ?. trim ( ) || undefined ;
645+ let newestNoAccountId : number | undefined ;
646+ let newestExactAccountId : number | undefined ;
647+ let newestAnyNonEmptyAccountId : number | undefined ;
648+ let nonEmptyAccountIdCount = 0 ;
649+
650+ for ( const index of matches ) {
651+ const existing = accounts [ index ] ;
652+ if ( ! existing ) continue ;
653+ const existingAccountId = normalizeStoredAccountId ( existing ) ;
654+ if ( ! existingAccountId ) {
655+ newestNoAccountId =
656+ typeof newestNoAccountId === "number"
657+ ? pickNewestAccountIndex ( newestNoAccountId , index )
658+ : index ;
659+ continue ;
660+ }
661+ nonEmptyAccountIdCount += 1 ;
662+ newestAnyNonEmptyAccountId =
663+ typeof newestAnyNonEmptyAccountId === "number"
664+ ? pickNewestAccountIndex ( newestAnyNonEmptyAccountId , index )
665+ : index ;
666+ if ( candidateId && existingAccountId === candidateId ) {
667+ newestExactAccountId =
668+ typeof newestExactAccountId === "number"
669+ ? pickNewestAccountIndex ( newestExactAccountId , index )
670+ : index ;
671+ }
672+ }
673+
674+ if ( candidateId ) {
675+ return newestExactAccountId ?? newestNoAccountId ;
676+ }
677+ if ( typeof newestNoAccountId === "number" ) {
678+ return newestNoAccountId ;
679+ }
680+ if ( nonEmptyAccountIdCount === 1 ) {
681+ return newestAnyNonEmptyAccountId ;
682+ }
683+ return undefined ;
684+ } ;
685+
636686 const resolveNoOrgRefreshMatch = (
637687 indexes : IdentityIndexes ,
638688 refreshToken : string ,
@@ -683,7 +733,7 @@ export const OpenAIOAuthPlugin: Plugin = async ({ client }: PluginInput) => {
683733 } ;
684734
685735 const buildIdentityIndexes = ( ) : IdentityIndexes => {
686- const byOrganizationId = new Map < string , number > ( ) ;
736+ const byOrganizationId = new Map < string , number [ ] > ( ) ;
687737 const byAccountIdNoOrg = new Map < string , number > ( ) ;
688738 const byRefreshTokenNoOrg = new Map < string , number [ ] > ( ) ;
689739 const byEmailNoOrg = new Map < string , number > ( ) ;
@@ -707,7 +757,7 @@ export const OpenAIOAuthPlugin: Plugin = async ({ client }: PluginInput) => {
707757 }
708758
709759 if ( organizationId ) {
710- byOrganizationId . set ( organizationId , i ) ;
760+ pushIndex ( byOrganizationId , organizationId , i ) ;
711761 if ( accountId ) {
712762 pushIndex ( byAccountIdOrgScoped , accountId , i ) ;
713763 }
@@ -755,7 +805,11 @@ export const OpenAIOAuthPlugin: Plugin = async ({ client }: PluginInput) => {
755805
756806 const existingIndex = ( ( ) => {
757807 if ( organizationId ) {
758- return identityIndexes . byOrganizationId . get ( organizationId ) ;
808+ return resolveOrganizationMatch (
809+ identityIndexes ,
810+ organizationId ,
811+ normalizedAccountId ,
812+ ) ;
759813 }
760814 if ( normalizedAccountId ) {
761815 const byAccountId = identityIndexes . byAccountIdNoOrg . get ( normalizedAccountId ) ;
@@ -859,7 +913,7 @@ export const OpenAIOAuthPlugin: Plugin = async ({ client }: PluginInput) => {
859913 const refreshMap = new Map <
860914 string ,
861915 {
862- byOrg : Map < string , number > ;
916+ byOrg : Map < string , number [ ] > ;
863917 preferredOrgIndex ?: number ;
864918 fallbackNoAccountIdIndex ?: number ;
865919 fallbackByAccountId : Map < string , number > ;
@@ -875,7 +929,7 @@ export const OpenAIOAuthPlugin: Plugin = async ({ client }: PluginInput) => {
875929 } ;
876930
877931 const collapseFallbackIntoPreferredOrg = ( entry : {
878- byOrg : Map < string , number > ;
932+ byOrg : Map < string , number [ ] > ;
879933 preferredOrgIndex ?: number ;
880934 fallbackNoAccountIdIndex ?: number ;
881935 fallbackByAccountId : Map < string , number > ;
@@ -929,7 +983,7 @@ export const OpenAIOAuthPlugin: Plugin = async ({ client }: PluginInput) => {
929983 let entry = refreshMap . get ( refreshToken ) ;
930984 if ( ! entry ) {
931985 entry = {
932- byOrg : new Map < string , number > ( ) ,
986+ byOrg : new Map < string , number [ ] > ( ) ,
933987 preferredOrgIndex : undefined ,
934988 fallbackNoAccountIdIndex : undefined ,
935989 fallbackByAccountId : new Map < string , number > ( ) ,
@@ -938,18 +992,35 @@ export const OpenAIOAuthPlugin: Plugin = async ({ client }: PluginInput) => {
938992 }
939993
940994 if ( orgKey ) {
941- const existingIndex = entry . byOrg . get ( orgKey ) ;
995+ const orgMatches = entry . byOrg . get ( orgKey ) ?? [ ] ;
996+ const existingIndex = resolveOrganizationMatch (
997+ {
998+ byOrganizationId : new Map ( [ [ orgKey , orgMatches ] ] ) ,
999+ byAccountIdNoOrg : new Map ( ) ,
1000+ byRefreshTokenNoOrg : new Map ( ) ,
1001+ byEmailNoOrg : new Map ( ) ,
1002+ byAccountIdOrgScoped : new Map ( ) ,
1003+ byRefreshTokenOrgScoped : new Map ( ) ,
1004+ byRefreshTokenGlobal : new Map ( ) ,
1005+ } ,
1006+ orgKey ,
1007+ normalizeStoredAccountId ( account ) ,
1008+ ) ;
9421009 if ( existingIndex !== undefined ) {
9431010 const newestIndex = pickNewestAccountIndex ( existingIndex , i ) ;
9441011 const obsoleteIndex = newestIndex === existingIndex ? i : existingIndex ;
9451012 mergeAccountRecords ( newestIndex , obsoleteIndex ) ;
9461013 indicesToRemove . add ( obsoleteIndex ) ;
947- entry . byOrg . set ( orgKey , newestIndex ) ;
1014+ const nextOrgMatches = orgMatches . filter (
1015+ ( index ) => index !== obsoleteIndex && index !== newestIndex ,
1016+ ) ;
1017+ nextOrgMatches . push ( newestIndex ) ;
1018+ entry . byOrg . set ( orgKey , nextOrgMatches ) ;
9481019 entry . preferredOrgIndex = pickPreferredOrgIndex ( entry . preferredOrgIndex , newestIndex ) ;
9491020 collapseFallbackIntoPreferredOrg ( entry ) ;
9501021 continue ;
9511022 }
952- entry . byOrg . set ( orgKey , i ) ;
1023+ entry . byOrg . set ( orgKey , [ ... orgMatches , i ] ) ;
9531024 entry . preferredOrgIndex = pickPreferredOrgIndex ( entry . preferredOrgIndex , i ) ;
9541025 collapseFallbackIntoPreferredOrg ( entry ) ;
9551026 continue ;
0 commit comments