mirror of https://github.com/langgenius/dify.git
chore: support Zendesk widget (#25517)
This commit is contained in:
parent
af7f67dc9c
commit
07d067d828
|
|
@ -24,7 +24,7 @@ const GA: FC<IGAProps> = ({
|
|||
if (IS_CE_EDITION)
|
||||
return null
|
||||
|
||||
const nonce = process.env.NODE_ENV === 'production' ? (headers() as unknown as UnsafeUnwrappedHeaders).get('x-nonce') : ''
|
||||
const nonce = process.env.NODE_ENV === 'production' ? (headers() as unknown as UnsafeUnwrappedHeaders).get('x-nonce') ?? '' : ''
|
||||
|
||||
return (
|
||||
<>
|
||||
|
|
@ -32,7 +32,7 @@ const GA: FC<IGAProps> = ({
|
|||
strategy="beforeInteractive"
|
||||
async
|
||||
src={`https://www.googletagmanager.com/gtag/js?id=${gaIdMaps[gaType]}`}
|
||||
nonce={nonce!}
|
||||
nonce={nonce ?? undefined}
|
||||
></Script>
|
||||
<Script
|
||||
id="ga-init"
|
||||
|
|
@ -44,14 +44,14 @@ gtag('js', new Date());
|
|||
gtag('config', '${gaIdMaps[gaType]}');
|
||||
`,
|
||||
}}
|
||||
nonce={nonce!}
|
||||
nonce={nonce ?? undefined}
|
||||
>
|
||||
</Script>
|
||||
{/* Cookie banner */}
|
||||
<Script
|
||||
id="cookieyes"
|
||||
src='https://cdn-cookieyes.com/client_data/2a645945fcae53f8e025a2b1/script.js'
|
||||
nonce={nonce!}
|
||||
nonce={nonce ?? undefined}
|
||||
></Script>
|
||||
</>
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,21 @@
|
|||
import { memo } from 'react'
|
||||
import { type UnsafeUnwrappedHeaders, headers } from 'next/headers'
|
||||
import Script from 'next/script'
|
||||
import { IS_CE_EDITION, ZENDESK_WIDGET_KEY } from '@/config'
|
||||
|
||||
const Zendesk = () => {
|
||||
if (IS_CE_EDITION || !ZENDESK_WIDGET_KEY)
|
||||
return null
|
||||
|
||||
const nonce = process.env.NODE_ENV === 'production' ? (headers() as unknown as UnsafeUnwrappedHeaders).get('x-nonce') ?? '' : ''
|
||||
|
||||
return (
|
||||
<Script
|
||||
nonce={nonce ?? undefined}
|
||||
id="ze-snippet"
|
||||
src={`https://static.zdassets.com/ekr/snippet.js?key=${ZENDESK_WIDGET_KEY}`}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
export default memo(Zendesk)
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
import { IS_CE_EDITION } from '@/config'
|
||||
|
||||
export type ConversationField = {
|
||||
id: string,
|
||||
value: any,
|
||||
}
|
||||
|
||||
declare global {
|
||||
// eslint-disable-next-line ts/consistent-type-definitions
|
||||
interface Window {
|
||||
zE?: (
|
||||
command: string,
|
||||
value: string,
|
||||
payload?: ConversationField[] | string | string[] | (() => any),
|
||||
callback?: () => any,
|
||||
) => void;
|
||||
}
|
||||
}
|
||||
|
||||
export const setZendeskConversationFields = (fields: ConversationField[], callback?: () => any) => {
|
||||
if (!IS_CE_EDITION && window.zE)
|
||||
window.zE('messenger:set', 'conversationFields', fields, callback)
|
||||
}
|
||||
|
|
@ -3,6 +3,7 @@ import type { Viewport } from 'next'
|
|||
import I18nServer from './components/i18n-server'
|
||||
import BrowserInitializer from './components/browser-initializer'
|
||||
import SentryInitializer from './components/sentry-initializer'
|
||||
import Zendesk from './components/base/zendesk'
|
||||
import { getLocaleOnServer } from '@/i18n-config/server'
|
||||
import { TanstackQueryInitializer } from '@/context/query-client'
|
||||
import { ThemeProvider } from 'next-themes'
|
||||
|
|
@ -48,6 +49,12 @@ const LocaleLayout = async ({
|
|||
[DatasetAttr.DATA_PUBLIC_ENABLE_WEBSITE_JINAREADER]: process.env.NEXT_PUBLIC_ENABLE_WEBSITE_JINAREADER,
|
||||
[DatasetAttr.DATA_PUBLIC_ENABLE_WEBSITE_FIRECRAWL]: process.env.NEXT_PUBLIC_ENABLE_WEBSITE_FIRECRAWL,
|
||||
[DatasetAttr.DATA_PUBLIC_ENABLE_WEBSITE_WATERCRAWL]: process.env.NEXT_PUBLIC_ENABLE_WEBSITE_WATERCRAWL,
|
||||
[DatasetAttr.NEXT_PUBLIC_ZENDESK_WIDGET_KEY]: process.env.NEXT_PUBLIC_ZENDESK_WIDGET_KEY,
|
||||
[DatasetAttr.NEXT_PUBLIC_ZENDESK_FIELD_ID_ENVIRONMENT]: process.env.NEXT_PUBLIC_ZENDESK_FIELD_ID_ENVIRONMENT,
|
||||
[DatasetAttr.NEXT_PUBLIC_ZENDESK_FIELD_ID_VERSION]: process.env.NEXT_PUBLIC_ZENDESK_FIELD_ID_VERSION,
|
||||
[DatasetAttr.NEXT_PUBLIC_ZENDESK_FIELD_ID_EMAIL]: process.env.NEXT_PUBLIC_ZENDESK_FIELD_ID_EMAIL,
|
||||
[DatasetAttr.NEXT_PUBLIC_ZENDESK_FIELD_ID_WORKSPACE_ID]: process.env.NEXT_PUBLIC_ZENDESK_FIELD_ID_WORKSPACE_ID,
|
||||
[DatasetAttr.NEXT_PUBLIC_ZENDESK_FIELD_ID_PLAN]: process.env.NEXT_PUBLIC_ZENDESK_FIELD_ID_PLAN,
|
||||
}
|
||||
|
||||
return (
|
||||
|
|
@ -89,6 +96,7 @@ const LocaleLayout = async ({
|
|||
</BrowserInitializer>
|
||||
</ThemeProvider>
|
||||
<RoutePrefixHandle />
|
||||
<Zendesk />
|
||||
</body>
|
||||
</html>
|
||||
)
|
||||
|
|
|
|||
|
|
@ -173,46 +173,46 @@ export const DEFAULT_AGENT_SETTING = {
|
|||
export const DEFAULT_AGENT_PROMPT = {
|
||||
chat: `Respond to the human as helpfully and accurately as possible.
|
||||
|
||||
{{instruction}}
|
||||
{{instruction}}
|
||||
|
||||
You have access to the following tools:
|
||||
You have access to the following tools:
|
||||
|
||||
{{tools}}
|
||||
{{tools}}
|
||||
|
||||
Use a json blob to specify a tool by providing an {{TOOL_NAME_KEY}} key (tool name) and an {{ACTION_INPUT_KEY}} key (tool input).
|
||||
Valid "{{TOOL_NAME_KEY}}" values: "Final Answer" or {{tool_names}}
|
||||
Use a json blob to specify a tool by providing an {{TOOL_NAME_KEY}} key (tool name) and an {{ACTION_INPUT_KEY}} key (tool input).
|
||||
Valid "{{TOOL_NAME_KEY}}" values: "Final Answer" or {{tool_names}}
|
||||
|
||||
Provide only ONE action per $JSON_BLOB, as shown:
|
||||
Provide only ONE action per $JSON_BLOB, as shown:
|
||||
|
||||
\`\`\`
|
||||
{
|
||||
"{{TOOL_NAME_KEY}}": $TOOL_NAME,
|
||||
"{{ACTION_INPUT_KEY}}": $ACTION_INPUT
|
||||
}
|
||||
\`\`\`
|
||||
\`\`\`
|
||||
{
|
||||
"{{TOOL_NAME_KEY}}": $TOOL_NAME,
|
||||
"{{ACTION_INPUT_KEY}}": $ACTION_INPUT
|
||||
}
|
||||
\`\`\`
|
||||
|
||||
Follow this format:
|
||||
Follow this format:
|
||||
|
||||
Question: input question to answer
|
||||
Thought: consider previous and subsequent steps
|
||||
Action:
|
||||
\`\`\`
|
||||
$JSON_BLOB
|
||||
\`\`\`
|
||||
Observation: action result
|
||||
... (repeat Thought/Action/Observation N times)
|
||||
Thought: I know what to respond
|
||||
Action:
|
||||
\`\`\`
|
||||
{
|
||||
"{{TOOL_NAME_KEY}}": "Final Answer",
|
||||
"{{ACTION_INPUT_KEY}}": "Final response to human"
|
||||
}
|
||||
\`\`\`
|
||||
Question: input question to answer
|
||||
Thought: consider previous and subsequent steps
|
||||
Action:
|
||||
\`\`\`
|
||||
$JSON_BLOB
|
||||
\`\`\`
|
||||
Observation: action result
|
||||
... (repeat Thought/Action/Observation N times)
|
||||
Thought: I know what to respond
|
||||
Action:
|
||||
\`\`\`
|
||||
{
|
||||
"{{TOOL_NAME_KEY}}": "Final Answer",
|
||||
"{{ACTION_INPUT_KEY}}": "Final response to human"
|
||||
}
|
||||
\`\`\`
|
||||
|
||||
Begin! Reminder to ALWAYS respond with a valid json blob of a single action. Use tools if necessary. Respond directly if appropriate. Format is Action:\`\`\`$JSON_BLOB\`\`\`then Observation:.`,
|
||||
Begin! Reminder to ALWAYS respond with a valid json blob of a single action. Use tools if necessary. Respond directly if appropriate. Format is Action:\`\`\`$JSON_BLOB\`\`\`then Observation:.`,
|
||||
completion: `
|
||||
Respond to the human as helpfully and accurately as possible.
|
||||
Respond to the human as helpfully and accurately as possible.
|
||||
|
||||
{{instruction}}
|
||||
|
||||
|
|
@ -285,3 +285,12 @@ export const ENABLE_WEBSITE_WATERCRAWL = getBooleanConfig(process.env.NEXT_PUBLI
|
|||
export const VALUE_SELECTOR_DELIMITER = '@@@'
|
||||
|
||||
export const validPassword = /^(?=.*[a-zA-Z])(?=.*\d)\S{8,}$/
|
||||
|
||||
export const ZENDESK_WIDGET_KEY = getStringConfig(process.env.NEXT_PUBLIC_ZENDESK_WIDGET_KEY, DatasetAttr.NEXT_PUBLIC_ZENDESK_WIDGET_KEY, '')
|
||||
export const ZENDESK_FIELD_IDS = {
|
||||
ENVIRONMENT: getStringConfig(process.env.NEXT_PUBLIC_ZENDESK_FIELD_ID_ENVIRONMENT, DatasetAttr.NEXT_PUBLIC_ZENDESK_FIELD_ID_ENVIRONMENT, ''),
|
||||
VERSION: getStringConfig(process.env.NEXT_PUBLIC_ZENDESK_FIELD_ID_VERSION, DatasetAttr.NEXT_PUBLIC_ZENDESK_FIELD_ID_VERSION, ''),
|
||||
EMAIL: getStringConfig(process.env.NEXT_PUBLIC_ZENDESK_FIELD_ID_EMAIL, DatasetAttr.NEXT_PUBLIC_ZENDESK_FIELD_ID_EMAIL, ''),
|
||||
WORKSPACE_ID: getStringConfig(process.env.NEXT_PUBLIC_ZENDESK_FIELD_ID_WORKSPACE_ID, DatasetAttr.NEXT_PUBLIC_ZENDESK_FIELD_ID_WORKSPACE_ID, ''),
|
||||
PLAN: getStringConfig(process.env.NEXT_PUBLIC_ZENDESK_FIELD_ID_PLAN, DatasetAttr.NEXT_PUBLIC_ZENDESK_FIELD_ID_PLAN, ''),
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,6 +8,8 @@ import { fetchCurrentWorkspace, fetchLangGeniusVersion, fetchUserProfile } from
|
|||
import type { ICurrentWorkspace, LangGeniusVersionResponse, UserProfileResponse } from '@/models/common'
|
||||
import MaintenanceNotice from '@/app/components/header/maintenance-notice'
|
||||
import { noop } from 'lodash-es'
|
||||
import { setZendeskConversationFields } from '@/app/components/base/zendesk/utils'
|
||||
import { ZENDESK_FIELD_IDS } from '@/config'
|
||||
|
||||
export type AppContextValue = {
|
||||
userProfile: UserProfileResponse
|
||||
|
|
@ -115,6 +117,44 @@ export const AppContextProvider: FC<AppContextProviderProps> = ({ children }) =>
|
|||
setCurrentWorkspace(currentWorkspaceResponse)
|
||||
}, [currentWorkspaceResponse])
|
||||
|
||||
// #region Zendesk conversation fields
|
||||
useEffect(() => {
|
||||
if (ZENDESK_FIELD_IDS.ENVIRONMENT && langGeniusVersionInfo?.current_env) {
|
||||
setZendeskConversationFields([{
|
||||
id: ZENDESK_FIELD_IDS.ENVIRONMENT,
|
||||
value: langGeniusVersionInfo.current_env.toLowerCase(),
|
||||
}])
|
||||
}
|
||||
}, [langGeniusVersionInfo?.current_env])
|
||||
|
||||
useEffect(() => {
|
||||
if (ZENDESK_FIELD_IDS.VERSION && langGeniusVersionInfo?.version) {
|
||||
setZendeskConversationFields([{
|
||||
id: ZENDESK_FIELD_IDS.VERSION,
|
||||
value: langGeniusVersionInfo.version,
|
||||
}])
|
||||
}
|
||||
}, [langGeniusVersionInfo?.version])
|
||||
|
||||
useEffect(() => {
|
||||
if (ZENDESK_FIELD_IDS.EMAIL && userProfile?.email) {
|
||||
setZendeskConversationFields([{
|
||||
id: ZENDESK_FIELD_IDS.EMAIL,
|
||||
value: userProfile.email,
|
||||
}])
|
||||
}
|
||||
}, [userProfile?.email])
|
||||
|
||||
useEffect(() => {
|
||||
if (ZENDESK_FIELD_IDS.WORKSPACE_ID && currentWorkspace?.id) {
|
||||
setZendeskConversationFields([{
|
||||
id: ZENDESK_FIELD_IDS.WORKSPACE_ID,
|
||||
value: currentWorkspace.id,
|
||||
}])
|
||||
}
|
||||
}, [currentWorkspace?.id])
|
||||
// #endregion Zendesk conversation fields
|
||||
|
||||
return (
|
||||
<AppContext.Provider value={{
|
||||
userProfile,
|
||||
|
|
|
|||
|
|
@ -27,6 +27,8 @@ import {
|
|||
useEducationStatus,
|
||||
} from '@/service/use-education'
|
||||
import { noop } from 'lodash-es'
|
||||
import { setZendeskConversationFields } from '@/app/components/base/zendesk/utils'
|
||||
import { ZENDESK_FIELD_IDS } from '@/config'
|
||||
|
||||
type ProviderContextState = {
|
||||
modelProviders: ModelProvider[]
|
||||
|
|
@ -189,6 +191,17 @@ export const ProviderContextProvider = ({
|
|||
fetchPlan()
|
||||
}, [])
|
||||
|
||||
// #region Zendesk conversation fields
|
||||
useEffect(() => {
|
||||
if (ZENDESK_FIELD_IDS.PLAN && plan.type) {
|
||||
setZendeskConversationFields([{
|
||||
id: ZENDESK_FIELD_IDS.PLAN,
|
||||
value: `${plan.type}-plan`,
|
||||
}])
|
||||
}
|
||||
}, [plan.type])
|
||||
// #endregion Zendesk conversation fields
|
||||
|
||||
const { t } = useTranslation()
|
||||
useEffect(() => {
|
||||
if (localStorage.getItem('anthropic_quota_notice') === 'true')
|
||||
|
|
|
|||
|
|
@ -122,4 +122,10 @@ export enum DatasetAttr {
|
|||
DATA_PUBLIC_ENABLE_WEBSITE_JINAREADER = 'data-public-enable-website-jinareader',
|
||||
DATA_PUBLIC_ENABLE_WEBSITE_FIRECRAWL = 'data-public-enable-website-firecrawl',
|
||||
DATA_PUBLIC_ENABLE_WEBSITE_WATERCRAWL = 'data-public-enable-website-watercrawl',
|
||||
NEXT_PUBLIC_ZENDESK_WIDGET_KEY = 'next-public-zendesk-widget-key',
|
||||
NEXT_PUBLIC_ZENDESK_FIELD_ID_ENVIRONMENT = 'next-public-zendesk-field-id-environment',
|
||||
NEXT_PUBLIC_ZENDESK_FIELD_ID_VERSION = 'next-public-zendesk-field-id-version',
|
||||
NEXT_PUBLIC_ZENDESK_FIELD_ID_EMAIL = 'next-public-zendesk-field-id-email',
|
||||
NEXT_PUBLIC_ZENDESK_FIELD_ID_WORKSPACE_ID = 'next-public-zendesk-field-id-workspace-id',
|
||||
NEXT_PUBLIC_ZENDESK_FIELD_ID_PLAN = 'next-public-zendesk-field-id-plan',
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue