Merge pull request #6755 from menloresearch/chore/analytic-model-used

chore: create event to track model provider and id model
This commit is contained in:
Faisal Amir 2025-10-07 20:36:42 +07:00 committed by GitHub
commit e5be683a97
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -40,6 +40,8 @@ import { useShallow } from 'zustand/react/shallow'
import { McpExtensionToolLoader } from './McpExtensionToolLoader' import { McpExtensionToolLoader } from './McpExtensionToolLoader'
import { ExtensionTypeEnum, MCPExtension } from '@janhq/core' import { ExtensionTypeEnum, MCPExtension } from '@janhq/core'
import { ExtensionManager } from '@/lib/extension' import { ExtensionManager } from '@/lib/extension'
import { useAnalytic } from '@/hooks/useAnalytic'
import posthog from 'posthog-js'
type ChatInputProps = { type ChatInputProps = {
className?: string className?: string
@ -88,6 +90,7 @@ const ChatInput = ({
const selectedModel = useModelProvider((state) => state.selectedModel) const selectedModel = useModelProvider((state) => state.selectedModel)
const selectedProvider = useModelProvider((state) => state.selectedProvider) const selectedProvider = useModelProvider((state) => state.selectedProvider)
const sendMessage = useChat() const sendMessage = useChat()
const { productAnalytic } = useAnalytic()
const [message, setMessage] = useState('') const [message, setMessage] = useState('')
const [dropdownToolsAvailable, setDropdownToolsAvailable] = useState(false) const [dropdownToolsAvailable, setDropdownToolsAvailable] = useState(false)
const [tooltipToolsAvailable, setTooltipToolsAvailable] = useState(false) const [tooltipToolsAvailable, setTooltipToolsAvailable] = useState(false)
@ -179,8 +182,7 @@ const ChatInput = ({
const mcpExtension = extensionManager.get<MCPExtension>(ExtensionTypeEnum.MCP) const mcpExtension = extensionManager.get<MCPExtension>(ExtensionTypeEnum.MCP)
const MCPToolComponent = mcpExtension?.getToolComponent?.() const MCPToolComponent = mcpExtension?.getToolComponent?.()
const handleSendMessage = async (prompt: string) => {
const handleSendMesage = async (prompt: string) => {
if (!selectedModel) { if (!selectedModel) {
setMessage('Please select a model to start chatting.') setMessage('Please select a model to start chatting.')
return return
@ -189,6 +191,19 @@ const ChatInput = ({
return return
} }
setMessage('') setMessage('')
// Track message send event with PostHog (only if product analytics is enabled)
if (productAnalytic && selectedModel && selectedProvider) {
try {
posthog.capture('message_sent', {
model_provider: selectedProvider,
model_id: selectedModel.id,
})
} catch (error) {
console.debug('Failed to track message send event:', error)
}
}
sendMessage( sendMessage(
prompt, prompt,
true, true,
@ -618,7 +633,7 @@ const ChatInput = ({
) { ) {
e.preventDefault() e.preventDefault()
// Submit the message when Enter is pressed without Shift // Submit the message when Enter is pressed without Shift
handleSendMesage(prompt) handleSendMessage(prompt)
// When Shift+Enter is pressed, a new line is added (default behavior) // When Shift+Enter is pressed, a new line is added (default behavior)
} }
}} }}
@ -706,74 +721,75 @@ const ChatInput = ({
)} )}
{selectedModel?.capabilities?.includes('tools') && {selectedModel?.capabilities?.includes('tools') &&
hasActiveMCPServers && ( hasActiveMCPServers &&
MCPToolComponent ? ( (MCPToolComponent ? (
// Use custom MCP component // Use custom MCP component
<McpExtensionToolLoader <McpExtensionToolLoader
tools={tools} tools={tools}
hasActiveMCPServers={hasActiveMCPServers} hasActiveMCPServers={hasActiveMCPServers}
selectedModelHasTools={selectedModel?.capabilities?.includes('tools') ?? false} selectedModelHasTools={
initialMessage={initialMessage} selectedModel?.capabilities?.includes('tools') ?? false
MCPToolComponent={MCPToolComponent} }
/> initialMessage={initialMessage}
) : ( MCPToolComponent={MCPToolComponent}
// Use default tools dropdown />
<TooltipProvider> ) : (
<Tooltip // Use default tools dropdown
open={tooltipToolsAvailable} <TooltipProvider>
onOpenChange={setTooltipToolsAvailable} <Tooltip
open={tooltipToolsAvailable}
onOpenChange={setTooltipToolsAvailable}
>
<TooltipTrigger
asChild
disabled={dropdownToolsAvailable}
> >
<TooltipTrigger <div
asChild onClick={(e) => {
disabled={dropdownToolsAvailable} setDropdownToolsAvailable(false)
e.stopPropagation()
}}
> >
<div <DropdownToolsAvailable
onClick={(e) => { initialMessage={initialMessage}
setDropdownToolsAvailable(false) onOpenChange={(isOpen) => {
e.stopPropagation() setDropdownToolsAvailable(isOpen)
if (isOpen) {
setTooltipToolsAvailable(false)
}
}} }}
> >
<DropdownToolsAvailable {(isOpen, toolsCount) => {
initialMessage={initialMessage} return (
onOpenChange={(isOpen) => { <div
setDropdownToolsAvailable(isOpen) className={cn(
if (isOpen) { 'h-7 p-1 flex items-center justify-center rounded-sm hover:bg-main-view-fg/10 transition-all duration-200 ease-in-out gap-1 cursor-pointer relative',
setTooltipToolsAvailable(false) isOpen && 'bg-main-view-fg/10'
} )}
}} >
> <IconTool
{(isOpen, toolsCount) => { size={18}
return ( className="text-main-view-fg/50"
<div />
className={cn( {toolsCount > 0 && (
'h-7 p-1 flex items-center justify-center rounded-sm hover:bg-main-view-fg/10 transition-all duration-200 ease-in-out gap-1 cursor-pointer relative', <div className="absolute -top-2 -right-2 bg-accent text-accent-fg text-xs rounded-full size-5 flex items-center justify-center font-medium">
isOpen && 'bg-main-view-fg/10' <span className="leading-0 text-xs">
)} {toolsCount > 99 ? '99+' : toolsCount}
> </span>
<IconTool </div>
size={18} )}
className="text-main-view-fg/50" </div>
/> )
{toolsCount > 0 && ( }}
<div className="absolute -top-2 -right-2 bg-accent text-accent-fg text-xs rounded-full size-5 flex items-center justify-center font-medium"> </DropdownToolsAvailable>
<span className="leading-0 text-xs"> </div>
{toolsCount > 99 ? '99+' : toolsCount} </TooltipTrigger>
</span> <TooltipContent>
</div> <p>{t('tools')}</p>
)} </TooltipContent>
</div> </Tooltip>
) </TooltipProvider>
}} ))}
</DropdownToolsAvailable>
</div>
</TooltipTrigger>
<TooltipContent>
<p>{t('tools')}</p>
</TooltipContent>
</Tooltip>
</TooltipProvider>
)
)}
{selectedModel?.capabilities?.includes('web_search') && ( {selectedModel?.capabilities?.includes('web_search') && (
<TooltipProvider> <TooltipProvider>
<Tooltip> <Tooltip>
@ -846,7 +862,7 @@ const ChatInput = ({
size="icon" size="icon"
disabled={!prompt.trim() && uploadedFiles.length === 0} disabled={!prompt.trim() && uploadedFiles.length === 0}
data-test-id="send-message-button" data-test-id="send-message-button"
onClick={() => handleSendMesage(prompt)} onClick={() => handleSendMessage(prompt)}
> >
{streamingContent ? ( {streamingContent ? (
<span className="animate-spin h-4 w-4 border-2 border-current border-t-transparent rounded-full" /> <span className="animate-spin h-4 w-4 border-2 border-current border-t-transparent rounded-full" />