@@ -57,7 +57,15 @@ import {
57
57
} from './utils'
58
58
import { ChatHistory , ChatHistoryList } from './features/history'
59
59
import { pairProgrammingModeOff , pairProgrammingModeOn , programmerModeCard } from './texts/pairProgramming'
60
- import { paidTierSuccessCard , freeTierLimitReachedCard , upgradeQButton } from './texts/paidTier'
60
+ import {
61
+ paidTierInfoCard ,
62
+ paidTierUpgradeForm ,
63
+ freeTierLimitSticky ,
64
+ continueUpgradeQButton ,
65
+ upgradeSuccessSticky ,
66
+ upgradePendingSticky ,
67
+ plansAndPricingTitle ,
68
+ } from './texts/paidTier'
61
69
62
70
export interface InboundChatApi {
63
71
addChatResponse ( params : ChatResult , tabId : string , isPartialResult : boolean ) : void
@@ -87,6 +95,31 @@ const getTabPairProgrammingMode = (mynahUi: MynahUI, tabId: string) => {
87
95
return promptInputOptions . find ( item => item . id === 'pair-programmer-mode' ) ?. value === 'true'
88
96
}
89
97
98
+ /** When user provides AWS account by clicking "Continue" or hitting Enter key. */
99
+ function onLinkAwsAccountId (
100
+ tabId : string ,
101
+ messageId : string ,
102
+ messager : Messager ,
103
+ action : { id : string ; text ?: string ; formData ?: Record < string , string > }
104
+ ) {
105
+ const awsAccountId = action . formData ?. [ 'awsAccountId' ]
106
+ if ( ! awsAccountId ) {
107
+ return false
108
+ // throw new Error(`onInBodyButtonClicked: ${continueUpgradeQButton.id} button did not provide awsAccountId`)
109
+ }
110
+ // HACK: emit "followUp" to send form data "outbound".
111
+ const payload : FollowUpClickParams = {
112
+ tabId,
113
+ messageId,
114
+ followUp : {
115
+ pillText : awsAccountId ,
116
+ type : 'awsAccountId' ,
117
+ } ,
118
+ }
119
+ messager . onFollowUpClicked ( payload )
120
+ return true
121
+ }
122
+
90
123
export const handlePromptInputChange = ( mynahUi : MynahUI , tabId : string , optionsValues : Record < string , string > ) => {
91
124
const promptTypeValue = optionsValues [ 'pair-programmer-mode' ]
92
125
@@ -374,7 +407,9 @@ export const createMynahUi = (
374
407
messager . onInfoLinkClick ( payload )
375
408
} ,
376
409
onInBodyButtonClicked : ( tabId , messageId , action , eventId ) => {
377
- if ( action . id === disclaimerAcknowledgeButtonId ) {
410
+ if ( action . id === continueUpgradeQButton . id ) {
411
+ onLinkAwsAccountId ( tabId , messageId , messager , { id : action . id , formData : action . formItemValues } )
412
+ } else if ( action . id === disclaimerAcknowledgeButtonId ) {
378
413
// Hide the legal disclaimer card
379
414
disclaimerCardActive = false
380
415
@@ -448,11 +483,20 @@ export const createMynahUi = (
448
483
messager . onCreatePrompt ( action . formItemValues ! [ ContextPrompt . PromptNameFieldId ] )
449
484
}
450
485
} ,
451
- onFormTextualItemKeyPress : ( event : KeyboardEvent , formData : Record < string , string > , itemId : string ) => {
486
+ onFormTextualItemKeyPress : (
487
+ event : KeyboardEvent ,
488
+ formData : Record < string , string > ,
489
+ itemId : string ,
490
+ tabId : string ,
491
+ eventId ?: string
492
+ ) => {
452
493
if ( itemId === ContextPrompt . PromptNameFieldId && event . key === 'Enter' ) {
453
494
event . preventDefault ( )
454
495
messager . onCreatePrompt ( formData [ ContextPrompt . PromptNameFieldId ] )
455
496
return true
497
+ } else if ( itemId === 'awsAccountId' && event . key === 'Enter' ) {
498
+ event . preventDefault ( )
499
+ return onLinkAwsAccountId ( tabId , '' , messager , { id : continueUpgradeQButton . id , formData : formData } )
456
500
}
457
501
return false
458
502
} ,
@@ -839,34 +883,102 @@ export const createMynahUi = (
839
883
* Shows a message if the user reaches free-tier limit.
840
884
* Shows a message if the user just upgraded to paid-tier.
841
885
*/
842
- const onPaidTierModeChange = (
843
- tabId : string ,
844
- mode : 'paidtier' | 'paidtier-success' | 'freetier' | 'freetier-limit'
845
- ) => {
846
- if ( ! [ 'paidtier' , 'paidtier-success' , 'freetier' , 'freetier-limit' ] . includes ( mode ) ) {
847
- return // invalid mode
886
+ const onPaidTierModeChange = ( tabId : string , mode : string | undefined ) => {
887
+ if (
888
+ ! mode ||
889
+ ! [
890
+ 'freetier' ,
891
+ 'freetier-limit' ,
892
+ 'freetier-upgrade-info' ,
893
+ 'upgrade-start' ,
894
+ 'upgrade-pending' ,
895
+ 'paidtier' ,
896
+ ] . includes ( mode )
897
+ ) {
898
+ return false // invalid mode
848
899
}
849
900
850
- tabId = tabId !== '' ? tabId : getOrCreateTabId ( ) !
901
+ tabId = ! ! tabId ? tabId : getOrCreateTabId ( ) !
902
+
903
+ // Detect if the tab is already showing the "Upgrade Q" UI.
904
+ const isFreeTierLimitUi =
905
+ mynahUi . getTabData ( tabId ) ?. getStore ( ) ?. promptInputStickyCard ?. messageId === freeTierLimitSticky . messageId
906
+ const isUpgradePendingUi =
907
+ mynahUi . getTabData ( tabId ) ?. getStore ( ) ?. promptInputStickyCard ?. messageId === upgradePendingSticky . messageId
908
+ const isPlansAndPricingTab = plansAndPricingTitle === mynahUi . getTabData ( tabId ) . getStore ( ) ?. tabTitle
909
+
910
+ if ( mode === 'freetier-limit' ) {
911
+ mynahUi . updateStore ( tabId , {
912
+ promptInputStickyCard : freeTierLimitSticky ,
913
+ } )
851
914
852
- // Detect if the tab is already showing the "Upgrade Q" calls-to-action.
853
- const didShowLimitReached = mynahUi . getTabData ( tabId ) ?. getStore ( ) ?. promptInputButtons ?. [ 0 ] === upgradeQButton
854
- if ( mode === 'freetier-limit' && ! didShowLimitReached ) {
855
- mynahUi . addChatItem ( tabId , freeTierLimitReachedCard )
856
- } else if ( mode === 'paidtier-success' ) {
857
- mynahUi . addChatItem ( tabId , paidTierSuccessCard )
915
+ if ( ! isFreeTierLimitUi ) {
916
+ // Avoid duplicate "limit reached" cards.
917
+ // REMOVED: don't want the "card", just use the "banner" only.
918
+ // mynahUi.addChatItem(tabId, freeTierLimitCard)
919
+ }
920
+ } else if ( mode === 'freetier-upgrade-info' ) {
921
+ mynahUi . addChatItem ( tabId , paidTierInfoCard )
922
+ } else if ( mode === 'upgrade-start' ) {
923
+ // Show the "Upgrade" form in its own tab.
924
+ const newTabId = createTabId ( ) ?? tabId
925
+ mynahUi . updateStore ( newTabId , {
926
+ tabTitle : plansAndPricingTitle ,
927
+ chatItems : [ ] , // Clear the tab.
928
+ promptInputDisabledState : true , // This special tab is not a "chat" tab.
929
+ promptInputButtons : [ ] ,
930
+ promptInputOptions : [ ] ,
931
+ promptInputPlaceholder : '' ,
932
+ promptInputVisible : false ,
933
+ } )
934
+ mynahUi . addChatItem ( newTabId , paidTierUpgradeForm )
935
+ // openTab('upgrade-start', { tabId: 'upgrade-start' })
936
+ } else if ( mode === 'upgrade-pending' ) {
937
+ // Change the sticky banner to show a progress spinner.
938
+ const card : typeof freeTierLimitSticky = {
939
+ ...( isFreeTierLimitUi ? freeTierLimitSticky : upgradePendingSticky ) ,
940
+ icon : 'progress' ,
941
+ }
942
+ mynahUi . updateStore ( tabId , {
943
+ // Show a progress ribbon.
944
+ promptInputVisible : true ,
945
+ promptInputProgress : {
946
+ status : 'default' ,
947
+ text : 'Waiting for subscription status...' ,
948
+ value : - 1 , // infinite
949
+ // valueText: 'Waiting 2...',
950
+ } ,
951
+ promptInputStickyCard : isFreeTierLimitUi ? card : null ,
952
+ } )
953
+ } else if ( mode === 'paidtier' ) {
954
+ mynahUi . updateStore ( tabId , {
955
+ promptInputStickyCard : null ,
956
+ promptInputProgress : null ,
957
+ promptInputVisible : ! isPlansAndPricingTab ,
958
+ } )
959
+ if ( isFreeTierLimitUi || isUpgradePendingUi || isPlansAndPricingTab ) {
960
+ // Transitioning from 'upgrade-pending' to upgrade success.
961
+ const card : typeof upgradeSuccessSticky = {
962
+ ...upgradeSuccessSticky ,
963
+ canBeDismissed : ! isPlansAndPricingTab ,
964
+ }
965
+ mynahUi . updateStore ( tabId , {
966
+ promptInputStickyCard : card ,
967
+ } )
968
+ }
858
969
}
859
970
860
971
mynahUi . updateStore ( tabId , {
861
- promptInputButtons : mode === 'freetier-limit' ? [ upgradeQButton ] : [ ] ,
862
- promptInputDisabledState : mode === 'freetier-limit' ,
972
+ // promptInputButtons: mode === 'freetier-limit' ? [upgradeQButton] : [],
973
+ // promptInputDisabledState: mode === 'freetier-limit',
863
974
} )
975
+
976
+ return true
864
977
}
865
978
866
979
const updateChat = ( params : ChatUpdateParams ) => {
867
980
// HACK: Special field sent by `agenticChatController.ts:setPaidTierMode()`.
868
- if ( ( params as any ) . paidTierMode ) {
869
- onPaidTierModeChange ( params . tabId , ( params as any ) . paidTierMode as any )
981
+ if ( onPaidTierModeChange ( params . tabId , ( params as any ) . paidTierMode as string ) ) {
870
982
return
871
983
}
872
984
0 commit comments