Skip to content

Commit

Permalink
Studio: Disable text input if the limit is reached UI and update to n…
Browse files Browse the repository at this point in the history
…ew headers (#244)

* Studio: Fix quota headers based on new endpoint

* Studio: Disable input on reached quota
  • Loading branch information
kozer authored Jun 14, 2024
1 parent c458692 commit ed27130
Show file tree
Hide file tree
Showing 4 changed files with 26 additions and 25 deletions.
4 changes: 3 additions & 1 deletion src/components/content-tab-assistant.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { useAssistant, Message as MessageType } from '../hooks/use-assistant';
import { useAssistantApi } from '../hooks/use-assistant-api';
import { useAuth } from '../hooks/use-auth';
import { useOffline } from '../hooks/use-offline';
import { usePromptUsage } from '../hooks/use-prompt-usage';
import { cx } from '../lib/cx';
import { getIpcApi } from '../lib/get-ipc-api';
import { AIInput } from './ai-input';
Expand Down Expand Up @@ -233,6 +234,7 @@ const UnauthenticatedView = ( { onAuthenticate }: { onAuthenticate: () => void }

export function ContentTabAssistant( { selectedSite }: ContentTabAssistantProps ) {
const { messages, addMessage, clearMessages } = useAssistant( selectedSite.name );
const { userCanSendMessage } = usePromptUsage();
const { fetchAssistant, isLoading: isAssistantThinking } = useAssistantApi();
const [ input, setInput ] = useState< string >( '' );
const endOfMessagesRef = useRef< HTMLDivElement >( null );
Expand Down Expand Up @@ -284,7 +286,7 @@ export function ContentTabAssistant( { selectedSite }: ContentTabAssistantProps
}
}, [ messages ] );

const disabled = isOffline || ! isAuthenticated;
const disabled = isOffline || ! isAuthenticated || ! userCanSendMessage;

return (
<div className="h-full flex flex-col bg-gray-50">
Expand Down
4 changes: 2 additions & 2 deletions src/components/user-settings.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { sprintf } from '@wordpress/i18n';
import { moreVertical, trash } from '@wordpress/icons';
import { useI18n } from '@wordpress/react-i18n';
import { useCallback, useState, useEffect } from 'react';
import { WPCOM_PROFILE_URL } from '../constants';
import { LIMIT_OF_PROMPTS_PER_USER, WPCOM_PROFILE_URL } from '../constants';
import { useAuth } from '../hooks/use-auth';
import { useDeleteSnapshot } from '../hooks/use-delete-snapshot';
import { useFetchSnapshots } from '../hooks/use-fetch-snapshots';
Expand Down Expand Up @@ -142,7 +142,7 @@ const SnapshotInfo = ( {

function PromptInfo() {
const { __ } = useI18n();
const { promptCount = 0, promptLimit = 10 } = usePromptUsage();
const { promptCount = 0, promptLimit = LIMIT_OF_PROMPTS_PER_USER } = usePromptUsage();
const assistantEnabled = getAppGlobals().assistantEnabled;
if ( ! assistantEnabled ) {
return null;
Expand Down
5 changes: 4 additions & 1 deletion src/hooks/use-assistant-api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,10 @@ export function useAssistantApi() {
setIsLoading( false );
}
const message = response?.choices?.[ 0 ]?.message?.content;
updatePromptUsage( headers );
updatePromptUsage( {
maxQuota: headers[ 'x-quota-max' ] || '',
remainingQuota: headers[ 'x-quota-remaining' ] || '',
} );
return { message };
},
[ client, updatePromptUsage ]
Expand Down
38 changes: 17 additions & 21 deletions src/hooks/use-prompt-usage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,16 @@ type PromptUsage = {
promptLimit: number;
promptCount: number;
fetchPromptUsage: () => Promise< void >;
updatePromptUsage: ( headers: Record< string, string > ) => void;
updatePromptUsage: ( data: { maxQuota: string; remainingQuota: string } ) => void;
userCanSendMessage: boolean;
};

const initState = {
promptLimit: LIMIT_OF_PROMPTS_PER_USER,
promptCount: 0,
fetchPromptUsage: async () => undefined,
updatePromptUsage: ( _headers: Record< string, string > ) => undefined,
updatePromptUsage: ( _data: { maxQuota: string; remainingQuota: string } ) => undefined,
userCanSendMessage: true,
};
const promptUsageContext = createContext< PromptUsage >( initState );

Expand All @@ -37,9 +39,9 @@ export function PromptUsageProvider( { children }: PromptUsageProps ) {
const { client } = useAuth();

const updatePromptUsage = useCallback(
( headers: Record< string, string > ) => {
const limit = parseInt( headers[ 'x-ratelimit-limit' ] );
const remaining = parseInt( headers[ 'x-ratelimit-remaining' ] );
( data: { maxQuota: string; remainingQuota: string } ) => {
const limit = parseInt( data.maxQuota as string );
const remaining = parseInt( data.remainingQuota as string );
if ( isNaN( limit ) || isNaN( remaining ) ) {
return;
}
Expand All @@ -57,22 +59,15 @@ export function PromptUsageProvider( { children }: PromptUsageProps ) {
return;
}
try {
await client.req.get(
{
method: 'HEAD',
path: '/studio-app/ai-assistant/chat',
apiNamespace: 'wpcom/v2',
},
( error: Error, _data: unknown, headers: Record< string, string > ) => {
if ( error ) {
return;
}
if ( ! headers ) {
return;
}
updatePromptUsage( headers );
}
);
const response = await client.req.get( {
method: 'GET',
path: '/studio-app/ai-assistant/quota',
apiNamespace: 'wpcom/v2',
} );
updatePromptUsage( {
maxQuota: response.max_quota || '',
remainingQuota: response.remaining_quota || '',
} );
} catch ( error ) {
Sentry.captureException( error );
console.error( error );
Expand All @@ -92,6 +87,7 @@ export function PromptUsageProvider( { children }: PromptUsageProps ) {
promptLimit,
promptCount,
updatePromptUsage,
userCanSendMessage: promptCount < promptLimit,
};
}, [ fetchPromptUsage, promptLimit, promptCount, updatePromptUsage ] );

Expand Down

0 comments on commit ed27130

Please sign in to comment.