From d10433cd1f727332a7b0a90d589f270f1260caea Mon Sep 17 00:00:00 2001 From: Christian Gastrell Date: Fri, 6 Sep 2024 15:23:34 -0300 Subject: [PATCH 1/5] set unlimited fair usage limit --- .../ai-client/changelog/fix-jetpack-ai-unlimited-tier-props | 4 ++++ .../jetpack/changelog/fix-jetpack-ai-unlimited-tier-props | 4 ++++ 2 files changed, 8 insertions(+) create mode 100644 projects/js-packages/ai-client/changelog/fix-jetpack-ai-unlimited-tier-props create mode 100644 projects/plugins/jetpack/changelog/fix-jetpack-ai-unlimited-tier-props diff --git a/projects/js-packages/ai-client/changelog/fix-jetpack-ai-unlimited-tier-props b/projects/js-packages/ai-client/changelog/fix-jetpack-ai-unlimited-tier-props new file mode 100644 index 0000000000000..b67027ada1403 --- /dev/null +++ b/projects/js-packages/ai-client/changelog/fix-jetpack-ai-unlimited-tier-props @@ -0,0 +1,4 @@ +Significance: minor +Type: changed + +Change unlimited tier plan props to reflect the fair usage limit diff --git a/projects/plugins/jetpack/changelog/fix-jetpack-ai-unlimited-tier-props b/projects/plugins/jetpack/changelog/fix-jetpack-ai-unlimited-tier-props new file mode 100644 index 0000000000000..04cb3e388eff9 --- /dev/null +++ b/projects/plugins/jetpack/changelog/fix-jetpack-ai-unlimited-tier-props @@ -0,0 +1,4 @@ +Significance: minor +Type: other + +Change unlimited tier plan props to reflect the fair usage limit From 5c9a0859a581ce5ce7b9189e532aafd7e0b8f04a Mon Sep 17 00:00:00 2001 From: Christian Gastrell Date: Mon, 9 Sep 2024 18:21:24 -0300 Subject: [PATCH 2/5] remove most uses of tierPlansEnabled, add notes on what seems still fuzzy --- .../components/generator-modal.tsx | 10 +-- .../src/logo-generator/components/prompt.tsx | 5 +- .../src/logo-generator/hooks/use-checkout.ts | 8 +-- .../src/logo-generator/store/selectors.ts | 18 +---- .../quota-exceeded-message/index.tsx | 68 +------------------ .../extensions/blocks/ai-assistant/edit.js | 4 +- .../ai-assistant-plugin-sidebar/index.tsx | 5 +- .../extensions/store/wordpress-com/reducer.ts | 3 + 8 files changed, 13 insertions(+), 108 deletions(-) diff --git a/projects/js-packages/ai-client/src/logo-generator/components/generator-modal.tsx b/projects/js-packages/ai-client/src/logo-generator/components/generator-modal.tsx index dfba25feb65fa..5b39fb7c3a9a8 100644 --- a/projects/js-packages/ai-client/src/logo-generator/components/generator-modal.tsx +++ b/projects/js-packages/ai-client/src/logo-generator/components/generator-modal.tsx @@ -13,7 +13,6 @@ import { useState, useEffect, useCallback, useRef } from 'react'; * Internal dependencies */ import { - DEFAULT_LOGO_COST, EVENT_MODAL_OPEN, EVENT_FEEDBACK, EVENT_MODAL_CLOSE, @@ -117,8 +116,6 @@ export const GeneratorModal: React.FC< GeneratorModalProps > = ( { const hasHistory = ! isLogoHistoryEmpty( String( siteId ) ); - const logoCost = feature?.costs?.[ 'jetpack-ai-logo-generator' ]?.logo ?? DEFAULT_LOGO_COST; - const promptCreationCost = 1; const currentLimit = feature?.currentTier?.limit || 0; const currentValue = feature?.currentTier?.value || 0; const currentUsage = feature?.usagePeriod?.requestsCount || 0; @@ -127,12 +124,7 @@ export const GeneratorModal: React.FC< GeneratorModalProps > = ( { // The user needs an upgrade immediately if they have no logos and not enough requests remaining for one prompt and one logo generation. const siteNeedsMoreRequests = - ! isUnlimited && - ! hasNoNextTier && - ! hasHistory && - ( tierPlansEnabled - ? currentLimit - currentUsage < logoCost + promptCreationCost - : currentLimit < currentUsage ); + ! isUnlimited && ! hasNoNextTier && ! hasHistory && currentLimit < currentUsage; // If the site requires an upgrade, show the upgrade screen immediately. setNeedsFeature( currentValue === 0 ); diff --git a/projects/js-packages/ai-client/src/logo-generator/components/prompt.tsx b/projects/js-packages/ai-client/src/logo-generator/components/prompt.tsx index 643bd0e3eb9fa..4f94ca5d53640 100644 --- a/projects/js-packages/ai-client/src/logo-generator/components/prompt.tsx +++ b/projects/js-packages/ai-client/src/logo-generator/components/prompt.tsx @@ -24,7 +24,6 @@ import { useCheckout } from '../hooks/use-checkout.js'; import useLogoGenerator from '../hooks/use-logo-generator.js'; import useRequestErrors from '../hooks/use-request-errors.js'; import { FairUsageNotice } from './fair-usage-notice.js'; -import { UpgradeNudge } from './upgrade-nudge.js'; import './prompt.scss'; /** * Types @@ -59,7 +58,6 @@ export const Prompt = ( { initialPrompt = '' }: PromptProps ) => { getAiAssistantFeature, requireUpgrade, context, - tierPlansEnabled, imageStyles, guessStyle, } = useLogoGenerator(); @@ -273,8 +271,7 @@ export const Prompt = ( { initialPrompt = '' }: PromptProps ) => { ) } - { requireUpgrade && tierPlansEnabled && } - { requireUpgrade && ! tierPlansEnabled && } + { requireUpgrade && } { enhancePromptFetchError && (
{ __( 'Error enhancing prompt. Please try again.', 'jetpack-ai-client' ) } diff --git a/projects/js-packages/ai-client/src/logo-generator/hooks/use-checkout.ts b/projects/js-packages/ai-client/src/logo-generator/hooks/use-checkout.ts index 1d77573b27d7b..2c5ac7ca661ee 100644 --- a/projects/js-packages/ai-client/src/logo-generator/hooks/use-checkout.ts +++ b/projects/js-packages/ai-client/src/logo-generator/hooks/use-checkout.ts @@ -17,11 +17,10 @@ import { STORE_NAME } from '../store/index.js'; import type { Selectors } from '../store/types.js'; export const useCheckout = () => { - const { nextTier, tierPlansEnabled } = useSelect( select => { + const { nextTier } = useSelect( select => { const selectors: Selectors = select( STORE_NAME ); return { nextTier: selectors.getAiAssistantFeature().nextTier, - tierPlansEnabled: selectors.getAiAssistantFeature().tierPlansEnabled, }; }, [] ); @@ -42,10 +41,7 @@ export const useCheckout = () => { const checkoutUrl = new URL( `https://jetpack.com/redirect/` ); checkoutUrl.searchParams.set( 'source', redirectSource ); checkoutUrl.searchParams.set( 'site', siteFragment ); - checkoutUrl.searchParams.set( - 'path', - tierPlansEnabled ? `jetpack_ai_yearly:-q-${ nextTier?.limit }` : 'jetpack_ai_yearly' - ); + checkoutUrl.searchParams.set( 'path', 'jetpack_ai_yearly' ); // For Jetpack sites, the redirect_to parameter is handled by the Jetpack redirect source if ( ! isJetpackSite ) { diff --git a/projects/js-packages/ai-client/src/logo-generator/store/selectors.ts b/projects/js-packages/ai-client/src/logo-generator/store/selectors.ts index 16c984b15c7aa..9f85aa54ff3d7 100644 --- a/projects/js-packages/ai-client/src/logo-generator/store/selectors.ts +++ b/projects/js-packages/ai-client/src/logo-generator/store/selectors.ts @@ -1,7 +1,6 @@ /** * Types */ -import { DEFAULT_LOGO_COST } from '../constants.js'; import type { AiFeatureProps, LogoGeneratorStateProp, Logo, RequestError } from './types.js'; import type { SiteDetails } from '../types.js'; @@ -120,22 +119,7 @@ const selectors = { * @return {boolean} The requireUpgrade flag. */ getRequireUpgrade( state: LogoGeneratorStateProp ): boolean { - const feature = state.features.aiAssistantFeature; - - if ( ! feature?.tierPlansEnabled ) { - return feature?.requireUpgrade; - } - const logoCost = feature?.costs?.[ 'jetpack-ai-logo-generator' ]?.logo ?? DEFAULT_LOGO_COST; - const currentLimit = feature?.currentTier?.value || 0; - const currentUsage = feature?.usagePeriod?.requestsCount || 0; - const isUnlimited = currentLimit === 1; - const hasNoNextTier = ! feature?.nextTier; // If there is no next tier, the user cannot upgrade. - - // Add a local check on top of the feature flag, based on the current usage and logo cost. - return ( - state.features.aiAssistantFeature?.requireUpgrade || - ( ! isUnlimited && ! hasNoNextTier && currentLimit - currentUsage < logoCost ) - ); + return state.features?.aiAssistantFeature?.requireUpgrade || false; }, /** diff --git a/projects/plugins/jetpack/extensions/blocks/ai-assistant/components/quota-exceeded-message/index.tsx b/projects/plugins/jetpack/extensions/blocks/ai-assistant/components/quota-exceeded-message/index.tsx index 8163e41c2d46e..2be6d6ca4dd70 100644 --- a/projects/plugins/jetpack/extensions/blocks/ai-assistant/components/quota-exceeded-message/index.tsx +++ b/projects/plugins/jetpack/extensions/blocks/ai-assistant/components/quota-exceeded-message/index.tsx @@ -1,7 +1,6 @@ /* * External dependencies */ -import { getRedirectUrl } from '@automattic/jetpack-components'; import { useAnalytics } from '@automattic/jetpack-shared-extension-utils'; import { Notice } from '@wordpress/components'; import { createInterpolateElement, useCallback } from '@wordpress/element'; @@ -97,7 +96,7 @@ const DefaultUpgradePrompt = ( { const { checkoutUrl } = useAICheckout(); const canUpgrade = canUserPurchasePlan(); - const { nextTier, tierPlansEnabled, currentTier, requestsCount } = useAiFeature(); + const { currentTier, requestsCount } = useAiFeature(); const { tracks } = useAnalytics(); @@ -110,13 +109,6 @@ const DefaultUpgradePrompt = ( { } ); }, [ currentTier, requestsCount, tracks, placement ] ); - const handleContactUsClick = useCallback( () => { - debug( 'contact us', placement ); - tracks.recordEvent( 'jetpack_ai_upgrade_contact_us', { - placement: placement, - } ); - }, [ tracks, placement ] ); - if ( ! canUpgrade ) { const cantUpgradeDescription = createInterpolateElement( __( @@ -141,64 +133,6 @@ const DefaultUpgradePrompt = ( { ); } - if ( tierPlansEnabled ) { - if ( ! nextTier ) { - const contactHref = getRedirectUrl( 'jetpack-ai-tiers-more-requests-contact' ); - const contactUsDescription = __( - 'You have reached the request limit for your current plan.', - 'jetpack' - ); - - return ( - - ); - } - - const upgradeDescription = createInterpolateElement( - sprintf( - /* Translators: number of requests */ - __( - 'You have reached the requests limit for your current plan. Upgrade now to increase your requests limit to %d.', - 'jetpack' - ), - nextTier.limit - ), - { - strong: , - } - ); - - return ( - - ); - } - return (
- { ( planType === PLAN_TYPE_FREE || - ( tierPlansEnabled && planType !== PLAN_TYPE_UNLIMITED ) ) && ( + { planType === PLAN_TYPE_FREE && ( diff --git a/projects/plugins/jetpack/extensions/plugins/ai-assistant-plugin/components/ai-assistant-plugin-sidebar/index.tsx b/projects/plugins/jetpack/extensions/plugins/ai-assistant-plugin/components/ai-assistant-plugin-sidebar/index.tsx index c3d44c1491ac5..bb3da65fdbc82 100644 --- a/projects/plugins/jetpack/extensions/plugins/ai-assistant-plugin/components/ai-assistant-plugin-sidebar/index.tsx +++ b/projects/plugins/jetpack/extensions/plugins/ai-assistant-plugin/components/ai-assistant-plugin-sidebar/index.tsx @@ -186,8 +186,7 @@ export default function AiAssistantPluginSidebar() { tracks.recordEvent( 'jetpack_ai_panel_open', { placement } ); }; - const showUsagePanel = - planType === PLAN_TYPE_FREE || ( tierPlansEnabled && planType !== PLAN_TYPE_UNLIMITED ); + const showUsagePanel = planType === PLAN_TYPE_FREE; const showFairUsageNotice = planType === PLAN_TYPE_UNLIMITED && isOverLimit; const isBreveAvailable = getBreveAvailability(); @@ -245,6 +244,8 @@ export default function AiAssistantPluginSidebar() { busy={ false } disabled={ requireUpgrade } /> + + { /* check this for removal, it will never be true */ } { requireUpgrade && tierPlansEnabled && ( = requestsLimit; // highest tier holds a soft limit so requireUpgrade is false on that case (nextTier null means highest tier) + // we shouldn't need this anymore, use requireUpgrade as it comes from backend const requireUpgrade = isOverLimit && state.features.aiAssistant.nextTier !== null; return { From 4957a95b20c026e1e5cdafab4793f1ee87f86074 Mon Sep 17 00:00:00 2001 From: Christian Gastrell Date: Wed, 11 Sep 2024 10:45:57 -0300 Subject: [PATCH 3/5] remove use of hasFeature from plugin and ai-client js package --- .../src/logo-generator/store/actions.ts | 1 - .../src/logo-generator/store/initial-state.ts | 1 - .../src/logo-generator/store/reducer.ts | 29 ++++------------- .../src/logo-generator/store/types.ts | 2 -- .../hooks/use-ai-feature/Readme.md | 9 ++---- .../extensions/store/wordpress-com/actions.ts | 1 - .../extensions/store/wordpress-com/reducer.ts | 31 +++++-------------- .../store/wordpress-com/test/index.ts | 12 +------ .../extensions/store/wordpress-com/types.ts | 1 - projects/plugins/jetpack/extensions/types.ts | 1 - 10 files changed, 17 insertions(+), 71 deletions(-) diff --git a/projects/js-packages/ai-client/src/logo-generator/store/actions.ts b/projects/js-packages/ai-client/src/logo-generator/store/actions.ts index 497ab74246fc9..0d154222cb41d 100644 --- a/projects/js-packages/ai-client/src/logo-generator/store/actions.ts +++ b/projects/js-packages/ai-client/src/logo-generator/store/actions.ts @@ -48,7 +48,6 @@ export function mapAiFeatureResponseToAiFeatureProps( response: AiAssistantFeatureEndpointResponseProps ): AiFeatureProps { return { - hasFeature: !! response[ 'has-feature' ], isOverLimit: !! response[ 'is-over-limit' ], requestsCount: response[ 'requests-count' ], requestsLimit: response[ 'requests-limit' ], diff --git a/projects/js-packages/ai-client/src/logo-generator/store/initial-state.ts b/projects/js-packages/ai-client/src/logo-generator/store/initial-state.ts index d07579e8f9793..8acaef0b165d7 100644 --- a/projects/js-packages/ai-client/src/logo-generator/store/initial-state.ts +++ b/projects/js-packages/ai-client/src/logo-generator/store/initial-state.ts @@ -8,7 +8,6 @@ const INITIAL_STATE: LogoGeneratorStateProp = { siteDetails: {}, features: { aiAssistantFeature: { - hasFeature: true, isOverLimit: false, requestsCount: 0, requestsLimit: FREE_PLAN_REQUESTS_LIMIT, diff --git a/projects/js-packages/ai-client/src/logo-generator/store/reducer.ts b/projects/js-packages/ai-client/src/logo-generator/store/reducer.ts index 9322c3c21a0b4..22c622c7464a3 100644 --- a/projects/js-packages/ai-client/src/logo-generator/store/reducer.ts +++ b/projects/js-packages/ai-client/src/logo-generator/store/reducer.ts @@ -9,7 +9,6 @@ import { ACTION_STORE_AI_ASSISTANT_FEATURE, ASYNC_REQUEST_COUNTDOWN_INIT_VALUE, FREE_PLAN_REQUESTS_LIMIT, - UNLIMITED_PLAN_REQUESTS_LIMIT, ACTION_SET_TIER_PLANS_ENABLED, ACTION_SET_SITE_DETAILS, ACTION_SET_SELECTED_LOGO_INDEX, @@ -149,30 +148,15 @@ export default function reducer( // Current tier value const currentTierValue = state?.features?.aiAssistantFeature?.currentTier?.value; - const isFreeTierPlan = - ( typeof currentTierValue === 'undefined' && - ! state?.features?.aiAssistantFeature?.hasFeature ) || - currentTierValue === 0; - - const isUnlimitedTierPlan = - ( typeof currentTierValue === 'undefined' && - state?.features?.aiAssistantFeature?.hasFeature ) || - currentTierValue === 1; + const isFreeTierPlan = currentTierValue === 0; // Request limit defined with the current tier limit by default. - let requestsLimit: TierLimitProp = + const requestsLimit: TierLimitProp = state?.features?.aiAssistantFeature?.currentTier?.limit || FREE_PLAN_REQUESTS_LIMIT; - if ( isUnlimitedTierPlan ) { - requestsLimit = UNLIMITED_PLAN_REQUESTS_LIMIT; - } else if ( isFreeTierPlan ) { - requestsLimit = state?.features?.aiAssistantFeature?.requestsLimit as TierLimitProp; - } - - const currentCount = - isUnlimitedTierPlan || isFreeTierPlan // @todo: update once tier data is available - ? requestsCount - : state?.features?.aiAssistantFeature?.usagePeriod?.requestsCount || 0; + const currentCount = isFreeTierPlan + ? requestsCount + : state?.features?.aiAssistantFeature?.usagePeriod?.requestsCount || 0; /** * Compute the AI Assistant Feature data optimistically, @@ -182,8 +166,7 @@ export default function reducer( const isOverLimit = currentCount >= requestsLimit; // highest tier holds a soft limit so requireUpgrade is false on that case (nextTier null means highest tier) - const requireUpgrade = - isFreeTierPlan || ( isOverLimit && state?.features?.aiAssistantFeature?.nextTier !== null ); + const requireUpgrade = isOverLimit; return { ...state, diff --git a/projects/js-packages/ai-client/src/logo-generator/store/types.ts b/projects/js-packages/ai-client/src/logo-generator/store/types.ts index b34f3b9f8a22e..5be545026e1c6 100644 --- a/projects/js-packages/ai-client/src/logo-generator/store/types.ts +++ b/projects/js-packages/ai-client/src/logo-generator/store/types.ts @@ -102,7 +102,6 @@ export type FeaturesControl = { }; export type AiFeatureProps = { - hasFeature: boolean; isOverLimit: boolean; requestsCount: number; requestsLimit: number; @@ -196,7 +195,6 @@ export type Selectors = { */ export type AiAssistantFeatureEndpointResponseProps = { 'is-enabled': boolean; - 'has-feature': boolean; 'is-over-limit': boolean; 'requests-count': number; 'requests-limit': number; diff --git a/projects/plugins/jetpack/extensions/blocks/ai-assistant/hooks/use-ai-feature/Readme.md b/projects/plugins/jetpack/extensions/blocks/ai-assistant/hooks/use-ai-feature/Readme.md index 4bdea1895e17a..a1a86babc8646 100644 --- a/projects/plugins/jetpack/extensions/blocks/ai-assistant/hooks/use-ai-feature/Readme.md +++ b/projects/plugins/jetpack/extensions/blocks/ai-assistant/hooks/use-ai-feature/Readme.md @@ -4,17 +4,14 @@ React custom hook that provides valuable data about AI requests for the site. ```es6 function UpgradePlan() { - const { hasFeature, count, refresh } = useAiFeature(); - if ( ! hasFeature ) { - return null; - } + const { count, refresh } = useAiFeature(); return (
{ `You have made ${ count } requests so far.` } - +
); } -``` \ No newline at end of file +``` diff --git a/projects/plugins/jetpack/extensions/store/wordpress-com/actions.ts b/projects/plugins/jetpack/extensions/store/wordpress-com/actions.ts index cc8a54cc7c3ab..3934cf507643e 100644 --- a/projects/plugins/jetpack/extensions/store/wordpress-com/actions.ts +++ b/projects/plugins/jetpack/extensions/store/wordpress-com/actions.ts @@ -33,7 +33,6 @@ export function mapAiFeatureResponseToAiFeatureProps( response: SiteAIAssistantFeatureEndpointResponseProps ): AiFeatureProps { return { - hasFeature: !! response[ 'has-feature' ], isOverLimit: !! response[ 'is-over-limit' ], requestsCount: response[ 'requests-count' ], requestsLimit: response[ 'requests-limit' ], diff --git a/projects/plugins/jetpack/extensions/store/wordpress-com/reducer.ts b/projects/plugins/jetpack/extensions/store/wordpress-com/reducer.ts index bdf47e2468e80..d93df8e6e059f 100644 --- a/projects/plugins/jetpack/extensions/store/wordpress-com/reducer.ts +++ b/projects/plugins/jetpack/extensions/store/wordpress-com/reducer.ts @@ -11,16 +11,14 @@ import { ACTION_STORE_AI_ASSISTANT_FEATURE, ASYNC_REQUEST_COUNTDOWN_INIT_VALUE, FREE_PLAN_REQUESTS_LIMIT, - UNLIMITED_PLAN_REQUESTS_LIMIT, ACTION_SET_TIER_PLANS_ENABLED, } from './constants'; -import type { PlanStateProps, TierLimitProp } from './types'; +import type { PlanStateProps } from './types'; const INITIAL_STATE: PlanStateProps = { plans: [], features: { aiAssistant: { - hasFeature: true, isOverLimit: false, requestsCount: 0, requestsLimit: FREE_PLAN_REQUESTS_LIMIT, @@ -101,29 +99,14 @@ export default function reducer( state = INITIAL_STATE, action ) { // Current tier value const currentTierValue = state.features.aiAssistant.currentTier?.value; - const isFreeTierPlan = - ( typeof currentTierValue === 'undefined' && ! state.features.aiAssistant.hasFeature ) || - currentTierValue === 0; - - const isUnlimitedTierPlan = - ( typeof currentTierValue === 'undefined' && state.features.aiAssistant.hasFeature ) || - currentTierValue === 1; + const isFreeTierPlan = currentTierValue === 0; // Request limit defined with the current tier limit by default. - let requestsLimit = state.features.aiAssistant.currentTier?.limit; - - if ( isUnlimitedTierPlan ) { - // since the introduction of the unlimited plan limit, we could take it from there instead - // of a fixed constant - requestsLimit = UNLIMITED_PLAN_REQUESTS_LIMIT; - } else if ( isFreeTierPlan ) { - requestsLimit = state.features.aiAssistant.requestsLimit as TierLimitProp; - } + const requestsLimit = state.features.aiAssistant.currentTier?.limit; - const currentCount = - isUnlimitedTierPlan || isFreeTierPlan // @todo: update once tier data is available - ? requestsCount - : state.features.aiAssistant.usagePeriod?.requestsCount; + const currentCount = isFreeTierPlan // @todo: update once tier data is available + ? requestsCount + : state.features.aiAssistant.usagePeriod?.requestsCount; /** * Compute the AI Assistant Feature data optimistically, @@ -135,7 +118,7 @@ export default function reducer( state = INITIAL_STATE, action ) { // highest tier holds a soft limit so requireUpgrade is false on that case (nextTier null means highest tier) // we shouldn't need this anymore, use requireUpgrade as it comes from backend - const requireUpgrade = isOverLimit && state.features.aiAssistant.nextTier !== null; + const requireUpgrade = isOverLimit; return { ...state, diff --git a/projects/plugins/jetpack/extensions/store/wordpress-com/test/index.ts b/projects/plugins/jetpack/extensions/store/wordpress-com/test/index.ts index f04541a772f33..a77c444a934c1 100644 --- a/projects/plugins/jetpack/extensions/store/wordpress-com/test/index.ts +++ b/projects/plugins/jetpack/extensions/store/wordpress-com/test/index.ts @@ -13,7 +13,6 @@ import { AiFeatureProps, PlanStateProps } from '../types'; describe( 'actions', () => { it( 'should create an action to store the AI Assistant feature', () => { const feature_in_free_plan: AiFeatureProps = { - hasFeature: false, isOverLimit: false, requestsCount: 10, requestsLimit: FREE_PLAN_REQUESTS_LIMIT, @@ -37,7 +36,6 @@ describe( 'reducer', () => { plans: [], features: { aiAssistant: { - hasFeature: false, isOverLimit: false, requestsCount: 19, // 1 request left :screams: requestsLimit: FREE_PLAN_REQUESTS_LIMIT, @@ -70,7 +68,6 @@ describe( 'reducer', () => { features: { aiAssistant: { ...initialState.features.aiAssistant, - hasFeature: false, isOverLimit: true, requestsCount: 20, requireUpgrade: true, @@ -90,7 +87,6 @@ describe( 'reducer', () => { plans: [], features: { aiAssistant: { - hasFeature: true, isOverLimit: false, requestsCount: 12345, requestsLimit: UNLIMITED_PLAN_REQUESTS_LIMIT, @@ -114,8 +110,7 @@ describe( 'reducer', () => { features: { aiAssistant: { ...initialState.features.aiAssistant, - hasFeature: true, - isOverLimit: true, + isOverLimit: false, requestsCount: 12346, requireUpgrade: false, usagePeriod: { @@ -134,7 +129,6 @@ describe( 'reducer', () => { plans: [], features: { aiAssistant: { - hasFeature: true, isOverLimit: false, requestsCount: 2998, requestsLimit: UNLIMITED_PLAN_REQUESTS_LIMIT, @@ -178,7 +172,6 @@ describe( 'reducer', () => { plans: [], features: { aiAssistant: { - hasFeature: true, isOverLimit: false, requestsCount: 123, // ignored for Tier plans requestsLimit: UNLIMITED_PLAN_REQUESTS_LIMIT, // ignored for Tier plans @@ -205,7 +198,6 @@ describe( 'reducer', () => { features: { aiAssistant: { ...initialState.features.aiAssistant, - hasFeature: true, isOverLimit: false, requestsCount: 124, requireUpgrade: false, @@ -225,7 +217,6 @@ describe( 'reducer', () => { plans: [], features: { aiAssistant: { - hasFeature: true, isOverLimit: false, requestsCount: 123, // ignored for Tier plans requestsLimit: UNLIMITED_PLAN_REQUESTS_LIMIT, // ignored for Tier plans @@ -252,7 +243,6 @@ describe( 'reducer', () => { features: { aiAssistant: { ...initialState.features.aiAssistant, - hasFeature: true, // @todo: should it be false? isOverLimit: true, requestsCount: 124, requireUpgrade: true, diff --git a/projects/plugins/jetpack/extensions/store/wordpress-com/types.ts b/projects/plugins/jetpack/extensions/store/wordpress-com/types.ts index e06d6b5d54e4a..da6037172d25a 100644 --- a/projects/plugins/jetpack/extensions/store/wordpress-com/types.ts +++ b/projects/plugins/jetpack/extensions/store/wordpress-com/types.ts @@ -92,7 +92,6 @@ export type FeatureControl = { export type FeaturesControl = { [ key: string ]: FeatureControl }; export type AiFeatureProps = { - hasFeature: boolean; isOverLimit: boolean; requestsCount: number; requestsLimit: number; diff --git a/projects/plugins/jetpack/extensions/types.ts b/projects/plugins/jetpack/extensions/types.ts index 722902dd215a3..831cfa275425c 100644 --- a/projects/plugins/jetpack/extensions/types.ts +++ b/projects/plugins/jetpack/extensions/types.ts @@ -8,7 +8,6 @@ import type { TierProp, UpgradeTypeProp, FeaturesControl } from './store/wordpre */ export type SiteAIAssistantFeatureEndpointResponseProps = { 'is-enabled': boolean; - 'has-feature': boolean; 'is-over-limit': boolean; 'requests-count': number; 'requests-limit': number; From 3101f75be185dd2013241a13898db90c3dea5bd7 Mon Sep 17 00:00:00 2001 From: Christian Gastrell Date: Wed, 11 Sep 2024 10:51:27 -0300 Subject: [PATCH 4/5] remove use of has-feature in forms package. Use site-require-upgrade instead as it's only use is in src/dashboard/landing/index.js --- .../forms/changelog/fix-jetpack-ai-unlimited-tier-props | 4 ++++ projects/packages/forms/src/dashboard/class-dashboard.php | 8 +++++--- 2 files changed, 9 insertions(+), 3 deletions(-) create mode 100644 projects/packages/forms/changelog/fix-jetpack-ai-unlimited-tier-props diff --git a/projects/packages/forms/changelog/fix-jetpack-ai-unlimited-tier-props b/projects/packages/forms/changelog/fix-jetpack-ai-unlimited-tier-props new file mode 100644 index 0000000000000..a90329db528fd --- /dev/null +++ b/projects/packages/forms/changelog/fix-jetpack-ai-unlimited-tier-props @@ -0,0 +1,4 @@ +Significance: minor +Type: changed + +Forms: take hasAI value from Jetpack connected status diff --git a/projects/packages/forms/src/dashboard/class-dashboard.php b/projects/packages/forms/src/dashboard/class-dashboard.php index d77c1e1caac48..0e1977a74553d 100644 --- a/projects/packages/forms/src/dashboard/class-dashboard.php +++ b/projects/packages/forms/src/dashboard/class-dashboard.php @@ -150,8 +150,10 @@ public function render_dashboard() { require_once JETPACK__PLUGIN_DIR . '_inc/lib/class-jetpack-ai-helper.php'; } - $ai_feature = \Jetpack_AI_Helper::get_ai_assistance_feature(); - $has_ai = ! is_wp_error( $ai_feature ) ? $ai_feature['has-feature'] : false; + $ai_feature = \Jetpack_AI_Helper::get_ai_assistance_feature(); + $require_upgrade = ! is_wp_error( $ai_feature ) && isset( $ai_feature['site-require-upgrade'] ) + ? $ai_feature['site-require-upgrade'] + : false; $jetpack_connected = ( defined( 'IS_WPCOM' ) && IS_WPCOM ) || ( new Connection_Manager( 'jetpack-forms' ) )->is_user_connected( get_current_user_id() ); $user_id = (int) get_current_user_id(); @@ -167,7 +169,7 @@ public function render_dashboard() { 'pluginAssetsURL' => Jetpack_Forms::assets_url(), 'siteURL' => ( new Status() )->get_site_suffix(), 'hasFeedback' => $this->has_feedback(), - 'hasAI' => $has_ai, + 'hasAI' => ! $require_upgrade, ); ?>
From 881bc7b74eea83246a32e6c73e64d8cd82b2484f Mon Sep 17 00:00:00 2001 From: Christian Gastrell Date: Wed, 11 Sep 2024 11:35:48 -0300 Subject: [PATCH 5/5] take jetpack_ai_enabled into consideration, don't waste cycles if user has disabled it. Respond with default payload --- .../_inc/lib/class-jetpack-ai-helper.php | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/projects/plugins/jetpack/_inc/lib/class-jetpack-ai-helper.php b/projects/plugins/jetpack/_inc/lib/class-jetpack-ai-helper.php index e2bad07111546..daa27527101b0 100644 --- a/projects/plugins/jetpack/_inc/lib/class-jetpack-ai-helper.php +++ b/projects/plugins/jetpack/_inc/lib/class-jetpack-ai-helper.php @@ -415,6 +415,11 @@ public static function get_ai_assistance_feature() { return $cache; } + if ( ! apply_filters( 'jetpack_ai_enabled', true ) ) { + // if user has disabled AI, don't waste request/computing cycles and return default payload. + return self::get_default_feature_payload(); + } + if ( null !== static::$ai_assistant_failed_request ) { return static::$ai_assistant_failed_request; } @@ -453,4 +458,27 @@ public static function get_ai_assistance_feature() { return $error; } } + + /** + * Get the default feature payload for when the feature is NOT available for a site. + * This is a default response for consistency. + */ + private static function get_default_feature_payload() { + return array( + 'has-feature' => false, + 'is-over-limit' => false, + 'requests-count' => 0, + 'requests-limit' => 20, + 'usage-period' => array(), + 'site-require-upgrade' => false, + 'upgrade-type' => 'default', + 'upgrade-url' => '', + 'current-tier' => null, + 'next-tier' => null, + 'tier-plans' => array(), + 'tier-plans-enabled' => false, + 'costs' => array(), + 'features-control' => array(), + ); + } }