@@ -58,7 +58,15 @@ import {
5858import { ChatHistory , ChatHistoryList } from './features/history'
5959import { pairProgrammingModeOff , pairProgrammingModeOn , programmerModeCard } from './texts/pairProgramming'
6060import { getModelSelectionChatItem } from './texts/modelSelection'
61- import { paidTierSuccessCard , freeTierLimitReachedCard , upgradeQButton } from './texts/paidTier'
61+ import {
62+ paidTierInfoCard ,
63+ paidTierUpgradeForm ,
64+ freeTierLimitSticky ,
65+ continueUpgradeQButton ,
66+ upgradeSuccessSticky ,
67+ upgradePendingSticky ,
68+ plansAndPricingTitle ,
69+ } from './texts/paidTier'
6270
6371export interface InboundChatApi {
6472 addChatResponse ( params : ChatResult , tabId : string , isPartialResult : boolean ) : void
@@ -94,6 +102,31 @@ const getTabPairProgrammingMode = (mynahUi: MynahUI, tabId: string) =>
94102const getTabModelSelection = ( mynahUi : MynahUI , tabId : string ) =>
95103 getTabPromptInputValue ( mynahUi , tabId , 'model-selection' )
96104
105+ /** When user provides AWS account by clicking "Continue" or hitting Enter key. */
106+ function onLinkAwsAccountId (
107+ tabId : string ,
108+ messageId : string ,
109+ messager : Messager ,
110+ action : { id : string ; text ?: string ; formData ?: Record < string , string > }
111+ ) {
112+ const awsAccountId = action . formData ?. [ 'awsAccountId' ]
113+ if ( ! awsAccountId ) {
114+ return false
115+ // throw new Error(`onInBodyButtonClicked: ${continueUpgradeQButton.id} button did not provide awsAccountId`)
116+ }
117+ // HACK: emit "followUp" to send form data "outbound".
118+ const payload : FollowUpClickParams = {
119+ tabId,
120+ messageId,
121+ followUp : {
122+ pillText : awsAccountId ,
123+ type : 'awsAccountId' ,
124+ } ,
125+ }
126+ messager . onFollowUpClicked ( payload )
127+ return true
128+ }
129+
97130export const handlePromptInputChange = ( mynahUi : MynahUI , tabId : string , optionsValues : Record < string , string > ) => {
98131 const previousPairProgrammerValue = getTabPairProgrammingMode ( mynahUi , tabId )
99132 const currentPairProgrammerValue = optionsValues [ 'pair-programmer-mode' ] === 'true'
@@ -385,7 +418,9 @@ export const createMynahUi = (
385418 messager . onInfoLinkClick ( payload )
386419 } ,
387420 onInBodyButtonClicked : ( tabId , messageId , action , eventId ) => {
388- if ( action . id === disclaimerAcknowledgeButtonId ) {
421+ if ( action . id === continueUpgradeQButton . id ) {
422+ onLinkAwsAccountId ( tabId , messageId , messager , { id : action . id , formData : action . formItemValues } )
423+ } else if ( action . id === disclaimerAcknowledgeButtonId ) {
389424 // Hide the legal disclaimer card
390425 disclaimerCardActive = false
391426
@@ -459,11 +494,20 @@ export const createMynahUi = (
459494 messager . onCreatePrompt ( action . formItemValues ! [ ContextPrompt . PromptNameFieldId ] )
460495 }
461496 } ,
462- onFormTextualItemKeyPress : ( event : KeyboardEvent , formData : Record < string , string > , itemId : string ) => {
497+ onFormTextualItemKeyPress : (
498+ event : KeyboardEvent ,
499+ formData : Record < string , string > ,
500+ itemId : string ,
501+ tabId : string ,
502+ eventId ?: string
503+ ) => {
463504 if ( itemId === ContextPrompt . PromptNameFieldId && event . key === 'Enter' ) {
464505 event . preventDefault ( )
465506 messager . onCreatePrompt ( formData [ ContextPrompt . PromptNameFieldId ] )
466507 return true
508+ } else if ( itemId === 'awsAccountId' && event . key === 'Enter' ) {
509+ event . preventDefault ( )
510+ return onLinkAwsAccountId ( tabId , '' , messager , { id : continueUpgradeQButton . id , formData : formData } )
467511 }
468512 return false
469513 } ,
@@ -850,34 +894,102 @@ export const createMynahUi = (
850894 * Shows a message if the user reaches free-tier limit.
851895 * Shows a message if the user just upgraded to paid-tier.
852896 */
853- const onPaidTierModeChange = (
854- tabId : string ,
855- mode : 'paidtier' | 'paidtier-success' | 'freetier' | 'freetier-limit'
856- ) => {
857- if ( ! [ 'paidtier' , 'paidtier-success' , 'freetier' , 'freetier-limit' ] . includes ( mode ) ) {
858- return // invalid mode
897+ const onPaidTierModeChange = ( tabId : string , mode : string | undefined ) => {
898+ if (
899+ ! mode ||
900+ ! [
901+ 'freetier' ,
902+ 'freetier-limit' ,
903+ 'freetier-upgrade-info' ,
904+ 'upgrade-start' ,
905+ 'upgrade-pending' ,
906+ 'paidtier' ,
907+ ] . includes ( mode )
908+ ) {
909+ return false // invalid mode
859910 }
860911
861- tabId = tabId !== '' ? tabId : getOrCreateTabId ( ) !
912+ tabId = ! ! tabId ? tabId : getOrCreateTabId ( ) !
913+
914+ // Detect if the tab is already showing the "Upgrade Q" UI.
915+ const isFreeTierLimitUi =
916+ mynahUi . getTabData ( tabId ) ?. getStore ( ) ?. promptInputStickyCard ?. messageId === freeTierLimitSticky . messageId
917+ const isUpgradePendingUi =
918+ mynahUi . getTabData ( tabId ) ?. getStore ( ) ?. promptInputStickyCard ?. messageId === upgradePendingSticky . messageId
919+ const isPlansAndPricingTab = plansAndPricingTitle === mynahUi . getTabData ( tabId ) . getStore ( ) ?. tabTitle
920+
921+ if ( mode === 'freetier-limit' ) {
922+ mynahUi . updateStore ( tabId , {
923+ promptInputStickyCard : freeTierLimitSticky ,
924+ } )
862925
863- // Detect if the tab is already showing the "Upgrade Q" calls-to-action.
864- const didShowLimitReached = mynahUi . getTabData ( tabId ) ?. getStore ( ) ?. promptInputButtons ?. [ 0 ] === upgradeQButton
865- if ( mode === 'freetier-limit' && ! didShowLimitReached ) {
866- mynahUi . addChatItem ( tabId , freeTierLimitReachedCard )
867- } else if ( mode === 'paidtier-success' ) {
868- mynahUi . addChatItem ( tabId , paidTierSuccessCard )
926+ if ( ! isFreeTierLimitUi ) {
927+ // Avoid duplicate "limit reached" cards.
928+ // REMOVED: don't want the "card", just use the "banner" only.
929+ // mynahUi.addChatItem(tabId, freeTierLimitCard)
930+ }
931+ } else if ( mode === 'freetier-upgrade-info' ) {
932+ mynahUi . addChatItem ( tabId , paidTierInfoCard )
933+ } else if ( mode === 'upgrade-start' ) {
934+ // Show the "Upgrade" form in its own tab.
935+ const newTabId = createTabId ( ) ?? tabId
936+ mynahUi . updateStore ( newTabId , {
937+ tabTitle : plansAndPricingTitle ,
938+ chatItems : [ ] , // Clear the tab.
939+ promptInputDisabledState : true , // This special tab is not a "chat" tab.
940+ promptInputButtons : [ ] ,
941+ promptInputOptions : [ ] ,
942+ promptInputPlaceholder : '' ,
943+ promptInputVisible : false ,
944+ } )
945+ mynahUi . addChatItem ( newTabId , paidTierUpgradeForm )
946+ // openTab('upgrade-start', { tabId: 'upgrade-start' })
947+ } else if ( mode === 'upgrade-pending' ) {
948+ // Change the sticky banner to show a progress spinner.
949+ const card : typeof freeTierLimitSticky = {
950+ ...( isFreeTierLimitUi ? freeTierLimitSticky : upgradePendingSticky ) ,
951+ icon : 'progress' ,
952+ }
953+ mynahUi . updateStore ( tabId , {
954+ // Show a progress ribbon.
955+ promptInputVisible : true ,
956+ promptInputProgress : {
957+ status : 'default' ,
958+ text : 'Waiting for subscription status...' ,
959+ value : - 1 , // infinite
960+ // valueText: 'Waiting 2...',
961+ } ,
962+ promptInputStickyCard : isFreeTierLimitUi ? card : null ,
963+ } )
964+ } else if ( mode === 'paidtier' ) {
965+ mynahUi . updateStore ( tabId , {
966+ promptInputStickyCard : null ,
967+ promptInputProgress : null ,
968+ promptInputVisible : ! isPlansAndPricingTab ,
969+ } )
970+ if ( isFreeTierLimitUi || isUpgradePendingUi || isPlansAndPricingTab ) {
971+ // Transitioning from 'upgrade-pending' to upgrade success.
972+ const card : typeof upgradeSuccessSticky = {
973+ ...upgradeSuccessSticky ,
974+ canBeDismissed : ! isPlansAndPricingTab ,
975+ }
976+ mynahUi . updateStore ( tabId , {
977+ promptInputStickyCard : card ,
978+ } )
979+ }
869980 }
870981
871982 mynahUi . updateStore ( tabId , {
872- promptInputButtons : mode === 'freetier-limit' ? [ upgradeQButton ] : [ ] ,
873- promptInputDisabledState : mode === 'freetier-limit' ,
983+ // promptInputButtons: mode === 'freetier-limit' ? [upgradeQButton] : [],
984+ // promptInputDisabledState: mode === 'freetier-limit',
874985 } )
986+
987+ return true
875988 }
876989
877990 const updateChat = ( params : ChatUpdateParams ) => {
878991 // HACK: Special field sent by `agenticChatController.ts:setPaidTierMode()`.
879- if ( ( params as any ) . paidTierMode ) {
880- onPaidTierModeChange ( params . tabId , ( params as any ) . paidTierMode as any )
992+ if ( onPaidTierModeChange ( params . tabId , ( params as any ) . paidTierMode as string ) ) {
881993 return
882994 }
883995
0 commit comments