@@ -37,8 +37,8 @@ export class ChatGPTAdapter extends BaseAdapterPlugin {
3737 DROP_ZONE : '#prompt-textarea, .ProseMirror, [data-testid="composer-text-input"], .composer-parent' ,
3838 // File preview elements
3939 FILE_PREVIEW : '.file-preview, .attachment-preview, [data-testid="file-attachment"]' ,
40- // Button insertion points (for MCP popover)
41- BUTTON_INSERTION_CONTAINER : '[data-testid="composer-footer-actions "], .composer-footer -actions, .flex.items-center [data-testid* ="composer"]' ,
40+ // Button insertion points (for MCP popover) - targeting leading area next to plus button
41+ BUTTON_INSERTION_CONTAINER : '[grid-area="leading "], .composer-leading -actions, [data-testid="composer-plus-btn "]' ,
4242 // Alternative insertion points
4343 FALLBACK_INSERTION : '.composer-parent, .relative.flex.w-full.items-end, [data-testid="composer-trailing-actions"]'
4444 } ;
@@ -226,6 +226,16 @@ export class ChatGPTAdapter extends BaseAdapterPlugin {
226226 paragraph . textContent = newContent ;
227227 targetElement . appendChild ( paragraph ) ;
228228
229+ // Position cursor at the end of the inserted text
230+ const range = document . createRange ( ) ;
231+ const selection = window . getSelection ( ) ;
232+ if ( selection && paragraph . firstChild ) {
233+ range . setStartAfter ( paragraph . lastChild || paragraph ) ;
234+ range . collapse ( true ) ;
235+ selection . removeAllRanges ( ) ;
236+ selection . addRange ( range ) ;
237+ }
238+
229239 // Dispatch events to simulate user typing for better compatibility
230240 targetElement . dispatchEvent ( new Event ( 'input' , { bubbles : true } ) ) ;
231241 targetElement . dispatchEvent ( new Event ( 'change' , { bubbles : true } ) ) ;
@@ -621,10 +631,17 @@ export class ChatGPTAdapter extends BaseAdapterPlugin {
621631
622632 /* Integration with ChatGPT's composer layout */
623633 [data-testid="composer-footer-actions"] .mcp-chatgpt-button-base,
624- .composer-footer-actions .mcp-chatgpt-button-base {
634+ .composer-footer-actions .mcp-chatgpt-button-base,
635+ [grid-area="leading"] .mcp-chatgpt-button-base {
625636 margin: 0 4px;
626637 }
627638
639+ /* Specific styling for leading area placement next to plus button */
640+ [grid-area="leading"] .mcp-chatgpt-button-base {
641+ margin-left: 8px;
642+ margin-right: 4px;
643+ }
644+
628645 /* Ensure proper stacking with ChatGPT's UI elements */
629646 .mcp-chatgpt-button-base {
630647 position: relative;
@@ -945,19 +962,30 @@ export class ChatGPTAdapter extends BaseAdapterPlugin {
945962 }
946963
947964 private findButtonInsertionPoint ( ) : { container : Element ; insertAfter : Element | null } | null {
948- this . context . logger . debug ( 'Finding button insertion point for MCP popover' ) ;
949-
950- // Try primary selector first - ChatGPT's composer footer actions
951- const footerActions = document . querySelector ( '[data-testid="composer-footer-actions"]' ) ;
952- if ( footerActions ) {
953- this . context . logger . debug ( 'Found insertion point: [data-testid="composer-footer-actions"]' ) ;
954- const buttons = footerActions . querySelectorAll ( 'button' ) ;
955- const lastButton = buttons . length > 0 ? buttons [ buttons . length - 1 ] : null ;
956- return { container : footerActions , insertAfter : lastButton } ;
965+ this . context . logger . debug ( 'Finding button insertion point for MCP popover next to plus button' ) ;
966+
967+ // Try to find the plus button first
968+ const plusButton = document . querySelector ( '[data-testid="composer-plus-btn"]' ) ;
969+ if ( plusButton && plusButton . parentElement ) {
970+ this . context . logger . debug ( 'Found plus button, inserting MCP button after it' ) ;
971+ return { container : plusButton . parentElement , insertAfter : plusButton } ;
957972 }
958973
959- // Try fallback selectors
974+ // Try to find the leading area container
975+ const leadingArea = document . querySelector ( '[grid-area="leading"]' ) ;
976+ if ( leadingArea ) {
977+ this . context . logger . debug ( 'Found leading area, looking for plus button within it' ) ;
978+ const plusButtonInLeading = leadingArea . querySelector ( 'button' ) ;
979+ if ( plusButtonInLeading ) {
980+ return { container : leadingArea , insertAfter : plusButtonInLeading } ;
981+ }
982+ // If no button found in leading area, append to the end
983+ return { container : leadingArea , insertAfter : null } ;
984+ }
985+
986+ // Fallback to original trailing area selectors if leading area not found
960987 const fallbackSelectors = [
988+ '[data-testid="composer-footer-actions"]' ,
961989 '.composer-footer-actions' ,
962990 '.flex.items-center[data-testid*="composer"]' ,
963991 '.relative.flex.w-full.items-end' ,
@@ -992,10 +1020,16 @@ export class ChatGPTAdapter extends BaseAdapterPlugin {
9921020 const reactContainer = document . createElement ( 'div' ) ;
9931021 reactContainer . id = 'mcp-popover-container' ;
9941022 reactContainer . style . display = 'inline-block' ;
995- reactContainer . style . margin = '0 4px' ;
1023+
1024+ // Adjust margin based on container type
1025+ const { container, insertAfter } = insertionPoint ;
1026+ if ( container . matches ( '[grid-area="leading"]' ) || container . closest ( '[grid-area="leading"]' ) ) {
1027+ reactContainer . style . margin = '0 0 0 8px' ; // More space from plus button
1028+ } else {
1029+ reactContainer . style . margin = '0 4px' ; // Default spacing
1030+ }
9961031
9971032 // Insert at appropriate location
998- const { container, insertAfter } = insertionPoint ;
9991033 if ( insertAfter && insertAfter . parentNode === container ) {
10001034 container . insertBefore ( reactContainer , insertAfter . nextSibling ) ;
10011035 this . context . logger . debug ( 'Inserted popover container after specified element' ) ;
0 commit comments