mirror of
http://112.124.100.131/huang.ze/ebiz-dify-ai.git
synced 2025-12-10 03:16:51 +08:00
Initial commit
This commit is contained in:
305
web/app/components/develop/code.tsx
Normal file
305
web/app/components/develop/code.tsx
Normal file
@@ -0,0 +1,305 @@
|
||||
'use client'
|
||||
import {
|
||||
Children,
|
||||
createContext,
|
||||
useContext,
|
||||
useEffect,
|
||||
useRef,
|
||||
useState,
|
||||
} from 'react'
|
||||
import { Tab } from '@headlessui/react'
|
||||
import classNames from 'classnames'
|
||||
|
||||
import { Tag } from './tag'
|
||||
|
||||
const languageNames = {
|
||||
js: 'JavaScript',
|
||||
ts: 'TypeScript',
|
||||
javascript: 'JavaScript',
|
||||
typescript: 'TypeScript',
|
||||
php: 'PHP',
|
||||
python: 'Python',
|
||||
ruby: 'Ruby',
|
||||
go: 'Go',
|
||||
} as { [key: string]: string }
|
||||
|
||||
type IChildrenProps = {
|
||||
children: React.ReactElement
|
||||
[key: string]: any
|
||||
}
|
||||
|
||||
function getPanelTitle({ className }: { className: string }) {
|
||||
const language = className.split('-')[1]
|
||||
return languageNames[language] ?? 'Code'
|
||||
}
|
||||
|
||||
function ClipboardIcon(props: any) {
|
||||
return (
|
||||
<svg viewBox="0 0 20 20" aria-hidden="true" {...props}>
|
||||
<path
|
||||
strokeWidth="0"
|
||||
d="M5.5 13.5v-5a2 2 0 0 1 2-2l.447-.894A2 2 0 0 1 9.737 4.5h.527a2 2 0 0 1 1.789 1.106l.447.894a2 2 0 0 1 2 2v5a2 2 0 0 1-2 2h-5a2 2 0 0 1-2-2Z"
|
||||
/>
|
||||
<path
|
||||
fill="none"
|
||||
strokeLinejoin="round"
|
||||
d="M12.5 6.5a2 2 0 0 1 2 2v5a2 2 0 0 1-2 2h-5a2 2 0 0 1-2-2v-5a2 2 0 0 1 2-2m5 0-.447-.894a2 2 0 0 0-1.79-1.106h-.527a2 2 0 0 0-1.789 1.106L7.5 6.5m5 0-1 1h-3l-1-1"
|
||||
/>
|
||||
</svg>
|
||||
)
|
||||
}
|
||||
|
||||
function CopyButton({ code }: { code: string }) {
|
||||
const [copyCount, setCopyCount] = useState(0)
|
||||
const copied = copyCount > 0
|
||||
|
||||
useEffect(() => {
|
||||
if (copyCount > 0) {
|
||||
const timeout = setTimeout(() => setCopyCount(0), 1000)
|
||||
return () => {
|
||||
clearTimeout(timeout)
|
||||
}
|
||||
}
|
||||
}, [copyCount])
|
||||
|
||||
return (
|
||||
<button
|
||||
type="button"
|
||||
className={classNames(
|
||||
'group/button absolute top-3.5 right-4 overflow-hidden rounded-full py-1 pl-2 pr-3 text-2xs font-medium opacity-0 backdrop-blur transition focus:opacity-100 group-hover:opacity-100',
|
||||
copied
|
||||
? 'bg-emerald-400/10 ring-1 ring-inset ring-emerald-400/20'
|
||||
: 'bg-white/5 hover:bg-white/7.5 dark:bg-white/2.5 dark:hover:bg-white/5',
|
||||
)}
|
||||
onClick={() => {
|
||||
window.navigator.clipboard.writeText(code).then(() => {
|
||||
setCopyCount(count => count + 1)
|
||||
})
|
||||
}}
|
||||
>
|
||||
<span
|
||||
aria-hidden={copied}
|
||||
className={classNames(
|
||||
'pointer-events-none flex items-center gap-0.5 text-zinc-400 transition duration-300',
|
||||
copied && '-translate-y-1.5 opacity-0',
|
||||
)}
|
||||
>
|
||||
<ClipboardIcon className="w-5 h-5 transition-colors fill-zinc-500/20 stroke-zinc-500 group-hover/button:stroke-zinc-400" />
|
||||
Copy
|
||||
</span>
|
||||
<span
|
||||
aria-hidden={!copied}
|
||||
className={classNames(
|
||||
'pointer-events-none absolute inset-0 flex items-center justify-center text-emerald-400 transition duration-300',
|
||||
!copied && 'translate-y-1.5 opacity-0',
|
||||
)}
|
||||
>
|
||||
Copied!
|
||||
</span>
|
||||
</button>
|
||||
)
|
||||
}
|
||||
|
||||
function CodePanelHeader({ tag, label }: { tag: string; label: string }) {
|
||||
if (!tag && !label)
|
||||
return null
|
||||
|
||||
return (
|
||||
<div className="flex h-9 items-center gap-2 border-y border-t-transparent border-b-white/7.5 bg-zinc-900 bg-white/2.5 px-4 dark:border-b-white/5 dark:bg-white/1">
|
||||
{tag && (
|
||||
<div className="flex dark">
|
||||
<Tag variant="small">{tag}</Tag>
|
||||
</div>
|
||||
)}
|
||||
{tag && label && (
|
||||
<span className="h-0.5 w-0.5 rounded-full bg-zinc-500" />
|
||||
)}
|
||||
{label && (
|
||||
<span className="font-mono text-xs text-zinc-400">{label}</span>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
type ICodePanelProps = {
|
||||
children: React.ReactElement
|
||||
tag?: string
|
||||
code?: string
|
||||
label?: string
|
||||
targetCode?: string
|
||||
}
|
||||
function CodePanel({ tag, label, code, children, targetCode }: ICodePanelProps) {
|
||||
const child = Children.only(children)
|
||||
|
||||
return (
|
||||
<div className="group dark:bg-white/2.5">
|
||||
<CodePanelHeader
|
||||
tag={child.props.tag ?? tag}
|
||||
label={child.props.label ?? label}
|
||||
/>
|
||||
<div className="relative">
|
||||
{/* <pre className="p-4 overflow-x-auto text-xs text-white">{children}</pre> */}
|
||||
{/* <CopyButton code={child.props.code ?? code} /> */}
|
||||
{/* <CopyButton code={child.props.children.props.children} /> */}
|
||||
<pre className="p-4 overflow-x-auto text-xs text-white">{targetCode || children}</pre>
|
||||
<CopyButton code={targetCode || child.props.children.props.children} />
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
function CodeGroupHeader({ title, children, selectedIndex }: IChildrenProps) {
|
||||
const hasTabs = Children.count(children) > 1
|
||||
|
||||
if (!title && !hasTabs)
|
||||
return null
|
||||
|
||||
return (
|
||||
<div className="flex min-h-[calc(theme(spacing.12)+1px)] flex-wrap items-start gap-x-4 border-b border-zinc-700 bg-zinc-800 px-4 dark:border-zinc-800 dark:bg-transparent">
|
||||
{title && (
|
||||
<h3 className="pt-3 mr-auto text-xs font-semibold text-white">
|
||||
{title}
|
||||
</h3>
|
||||
)}
|
||||
{hasTabs && (
|
||||
<Tab.List className="flex gap-4 -mb-px text-xs font-medium">
|
||||
{Children.map(children, (child, childIndex) => (
|
||||
<Tab
|
||||
className={classNames(
|
||||
'border-b py-3 transition focus:[&:not(:focus-visible)]:outline-none',
|
||||
childIndex === selectedIndex
|
||||
? 'border-emerald-500 text-emerald-400'
|
||||
: 'border-transparent text-zinc-400 hover:text-zinc-300',
|
||||
)}
|
||||
>
|
||||
{getPanelTitle(child.props.children.props)}
|
||||
</Tab>
|
||||
))}
|
||||
</Tab.List>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
type ICodeGroupPanelsProps = {
|
||||
children: React.ReactElement
|
||||
[key: string]: any
|
||||
}
|
||||
function CodeGroupPanels({ children, targetCode, ...props }: ICodeGroupPanelsProps) {
|
||||
const hasTabs = Children.count(children) > 1
|
||||
|
||||
if (hasTabs) {
|
||||
return (
|
||||
<Tab.Panels>
|
||||
{Children.map(children, child => (
|
||||
<Tab.Panel>
|
||||
<CodePanel {...props}>{child}</CodePanel>
|
||||
</Tab.Panel>
|
||||
))}
|
||||
</Tab.Panels>
|
||||
)
|
||||
}
|
||||
|
||||
return <CodePanel {...props} targetCode={targetCode}>{children}</CodePanel>
|
||||
}
|
||||
|
||||
function usePreventLayoutShift() {
|
||||
const positionRef = useRef<any>()
|
||||
const rafRef = useRef<any>()
|
||||
|
||||
useEffect(() => {
|
||||
return () => {
|
||||
window.cancelAnimationFrame(rafRef.current)
|
||||
}
|
||||
}, [])
|
||||
|
||||
return {
|
||||
positionRef,
|
||||
preventLayoutShift(callback: () => {}) {
|
||||
const initialTop = positionRef.current.getBoundingClientRect().top
|
||||
|
||||
callback()
|
||||
|
||||
rafRef.current = window.requestAnimationFrame(() => {
|
||||
const newTop = positionRef.current.getBoundingClientRect().top
|
||||
window.scrollBy(0, newTop - initialTop)
|
||||
})
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
function useTabGroupProps(availableLanguages: string[]) {
|
||||
const [preferredLanguages, addPreferredLanguage] = useState<any>([])
|
||||
const [selectedIndex, setSelectedIndex] = useState(0)
|
||||
const activeLanguage = [...availableLanguages].sort(
|
||||
(a, z) => preferredLanguages.indexOf(z) - preferredLanguages.indexOf(a),
|
||||
)[0]
|
||||
const languageIndex = availableLanguages.indexOf(activeLanguage)
|
||||
const newSelectedIndex = languageIndex === -1 ? selectedIndex : languageIndex
|
||||
if (newSelectedIndex !== selectedIndex)
|
||||
setSelectedIndex(newSelectedIndex)
|
||||
|
||||
const { positionRef, preventLayoutShift } = usePreventLayoutShift()
|
||||
|
||||
return {
|
||||
as: 'div',
|
||||
ref: positionRef,
|
||||
selectedIndex,
|
||||
onChange: (newSelectedIndex: number) => {
|
||||
preventLayoutShift(() =>
|
||||
(addPreferredLanguage(availableLanguages[newSelectedIndex]) as any),
|
||||
)
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
const CodeGroupContext = createContext(false)
|
||||
|
||||
export function CodeGroup({ children, title, inputs, targetCode, ...props }: IChildrenProps) {
|
||||
const languages = Children.map(children, child =>
|
||||
getPanelTitle(child.props.children.props)
|
||||
)
|
||||
const tabGroupProps = useTabGroupProps(languages)
|
||||
const hasTabs = Children.count(children) > 1
|
||||
const Container = hasTabs ? Tab.Group : 'div'
|
||||
const containerProps = hasTabs ? tabGroupProps : {}
|
||||
const headerProps = hasTabs
|
||||
? { selectedIndex: tabGroupProps.selectedIndex }
|
||||
: {}
|
||||
|
||||
return (
|
||||
<CodeGroupContext.Provider value={true}>
|
||||
<Container
|
||||
{...containerProps}
|
||||
className="my-6 overflow-hidden shadow-md not-prose rounded-2xl bg-zinc-900 dark:ring-1 dark:ring-white/10"
|
||||
>
|
||||
<CodeGroupHeader title={title} {...headerProps}>
|
||||
{children}
|
||||
</CodeGroupHeader>
|
||||
<CodeGroupPanels {...props} targetCode={targetCode}>{children}</CodeGroupPanels>
|
||||
</Container>
|
||||
</CodeGroupContext.Provider>
|
||||
)
|
||||
}
|
||||
|
||||
type IChildProps = {
|
||||
children: string
|
||||
[key: string]: any
|
||||
}
|
||||
export function Code({ children, ...props }: IChildProps) {
|
||||
const isGrouped = useContext(CodeGroupContext)
|
||||
|
||||
if (isGrouped)
|
||||
return <code {...props} dangerouslySetInnerHTML={{ __html: children }} />
|
||||
|
||||
return <code {...props}>{children}</code>
|
||||
}
|
||||
|
||||
export function Pre({ children, ...props }: IChildrenProps) {
|
||||
const isGrouped = useContext(CodeGroupContext)
|
||||
|
||||
if (isGrouped)
|
||||
return children
|
||||
|
||||
return <CodeGroup {...props}>{children}</CodeGroup>
|
||||
}
|
||||
33
web/app/components/develop/doc.tsx
Normal file
33
web/app/components/develop/doc.tsx
Normal file
@@ -0,0 +1,33 @@
|
||||
'use client'
|
||||
import TemplateEn from './template/template.en.mdx'
|
||||
import TemplateZh from './template/template.zh.mdx'
|
||||
import TemplateChatEn from './template/template_chat.en.mdx'
|
||||
import TemplateChatZh from './template/template_chat.zh.mdx'
|
||||
import { useContext } from 'use-context-selector'
|
||||
import I18n from '@/context/i18n'
|
||||
|
||||
type IDocProps = {
|
||||
appDetail: any
|
||||
}
|
||||
|
||||
const Doc = ({ appDetail }: IDocProps) => {
|
||||
const { locale } = useContext(I18n)
|
||||
const variables = appDetail?.model_config?.configs?.prompt_variables || []
|
||||
const inputs = variables.reduce((res: any, variable: any) => {
|
||||
res[variable.key] = variable.name || '';
|
||||
return res
|
||||
}, {})
|
||||
|
||||
return (
|
||||
<article className="prose prose-xl" >
|
||||
{appDetail?.mode === 'completion' ? (
|
||||
locale === 'en' ? <TemplateEn appDetail={appDetail} variables={variables} inputs={inputs} /> : <TemplateZh appDetail={appDetail} variables={variables} inputs={inputs} />
|
||||
) : (
|
||||
locale === 'en' ? <TemplateChatEn appDetail={appDetail} variables={variables} inputs={inputs} /> : <TemplateChatZh appDetail={appDetail} variables={variables} inputs={inputs} />
|
||||
)}
|
||||
</article>
|
||||
)
|
||||
|
||||
}
|
||||
|
||||
export default Doc
|
||||
47
web/app/components/develop/index.tsx
Normal file
47
web/app/components/develop/index.tsx
Normal file
@@ -0,0 +1,47 @@
|
||||
'use client'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import useSWR from 'swr'
|
||||
import Doc from '@/app/components/develop/doc'
|
||||
import InputCopy from '@/app/components/develop/secret-key/input-copy'
|
||||
import SecretKeyButton from '@/app/components/develop/secret-key/secret-key-button'
|
||||
import { fetchAppDetail } from '@/service/apps'
|
||||
import s from './secret-key/style.module.css'
|
||||
|
||||
type IDevelopMainProps = {
|
||||
appId: string
|
||||
dictionary: any
|
||||
}
|
||||
|
||||
const DevelopMain = ({ appId, dictionary }: IDevelopMainProps) => {
|
||||
const commonParams = { url: '/apps', id: appId }
|
||||
const { data: appDetail } = useSWR(commonParams, fetchAppDetail)
|
||||
const { t } = useTranslation()
|
||||
|
||||
// const serverApi = `${appDetail?.site?.app_base_url}/api/${appDetail?.site?.access_token}`
|
||||
|
||||
return (
|
||||
<div className='relative flex flex-col h-full overflow-hidden'>
|
||||
<div className='flex items-center justify-between flex-shrink-0 px-6 border-b border-solid h-14 border-b-gray-100'>
|
||||
<div className='text-lg font-medium text-gray-900'>{dictionary.app?.develop?.title}</div>
|
||||
<div className='flex items-center'>
|
||||
<InputCopy className={`flex-shrink-0 mr-1 w-60 ${s.w320}`} value={appDetail?.api_base_url}>
|
||||
<div className={`ml-2 border border-gray-200 border-solid flex-shrink-0 px-2 py-0.5 rounded-[6px] text-gray-500 text-[0.625rem] ${s.customApi}`}>
|
||||
{t('appApi.apiServer')}
|
||||
</div>
|
||||
</InputCopy>
|
||||
<div className={`flex items-center h-9 px-3 rounded-lg
|
||||
text-[13px] font-normal mr-2 ${appDetail?.enable_api ? 'text-green-500 bg-green-50' : 'text-yellow-500 bg-yellow-50'}`}>
|
||||
<div className='mr-1'>{t('appApi.status')}</div>
|
||||
<div className='font-semibold'>{appDetail?.enable_api ? `${t('appApi.ok')}` : `${t('appApi.disabled')}`}</div>
|
||||
</div>
|
||||
<SecretKeyButton className='flex-shrink-0' appId={appId} />
|
||||
</div>
|
||||
</div>
|
||||
<div className='px-10 py-4 overflow-auto grow'>
|
||||
<Doc appDetail={appDetail} />
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default DevelopMain
|
||||
140
web/app/components/develop/md.tsx
Normal file
140
web/app/components/develop/md.tsx
Normal file
@@ -0,0 +1,140 @@
|
||||
'use client'
|
||||
import classNames from 'classnames'
|
||||
|
||||
type IChildrenProps = {
|
||||
children: React.ReactNode
|
||||
id?: string
|
||||
tag?: any
|
||||
label?: any
|
||||
anchor: boolean
|
||||
}
|
||||
|
||||
type IHeaderingProps = {
|
||||
url: string
|
||||
method: 'PUT' | 'DELETE' | 'GET' | 'POST'
|
||||
title: string
|
||||
name: string
|
||||
}
|
||||
|
||||
export const Heading = function H2({
|
||||
url,
|
||||
method,
|
||||
title,
|
||||
name,
|
||||
}: IHeaderingProps) {
|
||||
let style = '';
|
||||
switch (method) {
|
||||
case 'PUT':
|
||||
style = 'ring-amber-300 bg-amber-400/10 text-amber-500 dark:ring-amber-400/30 dark:bg-amber-400/10 dark:text-amber-400';
|
||||
break;
|
||||
case 'DELETE':
|
||||
style = 'ring-rose-200 bg-rose-50 text-red-500 dark:ring-rose-500/20 dark:bg-rose-400/10 dark:text-rose-400';
|
||||
break;
|
||||
case 'POST':
|
||||
style = 'ring-sky-300 bg-sky-400/10 text-sky-500 dark:ring-sky-400/30 dark:bg-sky-400/10 dark:text-sky-400';
|
||||
break;
|
||||
default:
|
||||
style = 'ring-emerald-300 dark:ring-emerald-400/30 bg-emerald-400/10 text-emerald-500 dark:text-emerald-400';
|
||||
break;
|
||||
}
|
||||
return (
|
||||
<>
|
||||
<div className="flex items-center gap-x-3" >
|
||||
<span className={`font-mono text-[0.625rem] font-semibold leading-6 rounded-lg px-1.5 ring-1 ring-inset ${style}`}>{method}</span>
|
||||
{/* <span className="h-0.5 w-0.5 rounded-full bg-zinc-300 dark:bg-zinc-600"></span> */}
|
||||
<span className="font-mono text-xs text-zinc-400">{url}</span>
|
||||
</div>
|
||||
<h2 className='mt-2 scroll-mt-32'>
|
||||
<a href={name} className='no-underline group text-inherit hover:text-inherit'>{title}</a>
|
||||
</h2>
|
||||
</>
|
||||
|
||||
)
|
||||
}
|
||||
|
||||
export function Row({ children }: IChildrenProps) {
|
||||
return (
|
||||
<div className="grid items-start grid-cols-1 gap-x-16 gap-y-10 xl:max-w-none xl:grid-cols-2">
|
||||
{children}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
type IColProps = IChildrenProps & {
|
||||
sticky: boolean
|
||||
}
|
||||
export function Col({ children, sticky = false }: IColProps) {
|
||||
return (
|
||||
<div
|
||||
className={classNames(
|
||||
'[&>:first-child]:mt-0 [&>:last-child]:mb-0',
|
||||
sticky && 'xl:sticky xl:top-24',
|
||||
)}
|
||||
>
|
||||
{children}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export function Properties({ children }: IChildrenProps) {
|
||||
return (
|
||||
<div className="my-6">
|
||||
<ul
|
||||
role="list"
|
||||
className="m-0 max-w-[calc(theme(maxWidth.lg)-theme(spacing.8))] list-none divide-y divide-zinc-900/5 p-0 dark:divide-white/5"
|
||||
>
|
||||
{children}
|
||||
</ul>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
type IProperty = IChildrenProps & {
|
||||
name: string
|
||||
type: string
|
||||
}
|
||||
export function Property({ name, type, children }: IProperty) {
|
||||
return (
|
||||
<li className="px-0 py-4 m-0 first:pt-0 last:pb-0">
|
||||
<dl className="flex flex-wrap items-center m-0 gap-x-3 gap-y-2">
|
||||
<dt className="sr-only">Name</dt>
|
||||
<dd>
|
||||
<code>{name}</code>
|
||||
</dd>
|
||||
<dt className="sr-only">Type</dt>
|
||||
<dd className="font-mono text-xs text-zinc-400 dark:text-zinc-500">
|
||||
{type}
|
||||
</dd>
|
||||
<dt className="sr-only">Description</dt>
|
||||
<dd className="w-full flex-none [&>:first-child]:mt-0 [&>:last-child]:mb-0">
|
||||
{children}
|
||||
</dd>
|
||||
</dl>
|
||||
</li>
|
||||
)
|
||||
}
|
||||
|
||||
type ISubProperty = IChildrenProps & {
|
||||
name: string
|
||||
type: string
|
||||
}
|
||||
export function SubProperty({ name, type, children }: ISubProperty) {
|
||||
return (
|
||||
<li className="px-0 py-1 m-0 last:pb-0">
|
||||
<dl className="flex flex-wrap items-center m-0 gap-x-3">
|
||||
<dt className="sr-only">Name</dt>
|
||||
<dd>
|
||||
<code>{name}</code>
|
||||
</dd>
|
||||
<dt className="sr-only">Type</dt>
|
||||
<dd className="font-mono text-xs text-zinc-400 dark:text-zinc-500">
|
||||
{type}
|
||||
</dd>
|
||||
<dt className="sr-only">Description</dt>
|
||||
<dd className="w-full flex-none [&>:first-child]:mt-0 [&>:last-child]:mb-0">
|
||||
{children}
|
||||
</dd>
|
||||
</dl>
|
||||
</li>
|
||||
)
|
||||
}
|
||||
3
web/app/components/develop/secret-key/assets/copied.svg
Normal file
3
web/app/components/develop/secret-key/assets/copied.svg
Normal file
@@ -0,0 +1,3 @@
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M10.6665 2.66683C11.2865 2.66683 11.5965 2.66683 11.8508 2.73498C12.541 2.91991 13.0801 3.45901 13.265 4.14919C13.3332 4.40352 13.3332 4.71352 13.3332 5.3335V11.4668C13.3332 12.5869 13.3332 13.147 13.1152 13.5748C12.9234 13.9511 12.6175 14.2571 12.2412 14.4488C11.8133 14.6668 11.2533 14.6668 10.1332 14.6668H5.8665C4.7464 14.6668 4.18635 14.6668 3.75852 14.4488C3.3822 14.2571 3.07624 13.9511 2.88449 13.5748C2.6665 13.147 2.6665 12.5869 2.6665 11.4668V5.3335C2.6665 4.71352 2.6665 4.40352 2.73465 4.14919C2.91959 3.45901 3.45868 2.91991 4.14887 2.73498C4.4032 2.66683 4.71319 2.66683 5.33317 2.66683M5.99984 10.0002L7.33317 11.3335L10.3332 8.3335M6.39984 4.00016H9.59984C9.9732 4.00016 10.1599 4.00016 10.3025 3.9275C10.4279 3.86359 10.5299 3.7616 10.5938 3.63616C10.6665 3.49355 10.6665 3.30686 10.6665 2.9335V2.40016C10.6665 2.02679 10.6665 1.84011 10.5938 1.6975C10.5299 1.57206 10.4279 1.47007 10.3025 1.40616C10.1599 1.3335 9.97321 1.3335 9.59984 1.3335H6.39984C6.02647 1.3335 5.83978 1.3335 5.69718 1.40616C5.57174 1.47007 5.46975 1.57206 5.40583 1.6975C5.33317 1.84011 5.33317 2.02679 5.33317 2.40016V2.9335C5.33317 3.30686 5.33317 3.49355 5.40583 3.63616C5.46975 3.7616 5.57174 3.86359 5.69718 3.9275C5.83978 4.00016 6.02647 4.00016 6.39984 4.00016Z" stroke="#1D2939" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.4 KiB |
@@ -0,0 +1,3 @@
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M10.6665 2.66634H11.9998C12.3535 2.66634 12.6926 2.80682 12.9426 3.05687C13.1927 3.30691 13.3332 3.64605 13.3332 3.99967V13.333C13.3332 13.6866 13.1927 14.0258 12.9426 14.2758C12.6926 14.5259 12.3535 14.6663 11.9998 14.6663H3.99984C3.64622 14.6663 3.30708 14.5259 3.05703 14.2758C2.80698 14.0258 2.6665 13.6866 2.6665 13.333V3.99967C2.6665 3.64605 2.80698 3.30691 3.05703 3.05687C3.30708 2.80682 3.64622 2.66634 3.99984 2.66634H5.33317M5.99984 1.33301H9.99984C10.368 1.33301 10.6665 1.63148 10.6665 1.99967V3.33301C10.6665 3.7012 10.368 3.99967 9.99984 3.99967H5.99984C5.63165 3.99967 5.33317 3.7012 5.33317 3.33301V1.99967C5.33317 1.63148 5.63165 1.33301 5.99984 1.33301Z" stroke="#1D2939" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 875 B |
3
web/app/components/develop/secret-key/assets/copy.svg
Normal file
3
web/app/components/develop/secret-key/assets/copy.svg
Normal file
@@ -0,0 +1,3 @@
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M10.6665 2.66634H11.9998C12.3535 2.66634 12.6926 2.80682 12.9426 3.05687C13.1927 3.30691 13.3332 3.64605 13.3332 3.99967V13.333C13.3332 13.6866 13.1927 14.0258 12.9426 14.2758C12.6926 14.5259 12.3535 14.6663 11.9998 14.6663H3.99984C3.64622 14.6663 3.30708 14.5259 3.05703 14.2758C2.80698 14.0258 2.6665 13.6866 2.6665 13.333V3.99967C2.6665 3.64605 2.80698 3.30691 3.05703 3.05687C3.30708 2.80682 3.64622 2.66634 3.99984 2.66634H5.33317M5.99984 1.33301H9.99984C10.368 1.33301 10.6665 1.63148 10.6665 1.99967V3.33301C10.6665 3.7012 10.368 3.99967 9.99984 3.99967H5.99984C5.63165 3.99967 5.33317 3.7012 5.33317 3.33301V1.99967C5.33317 1.63148 5.63165 1.33301 5.99984 1.33301Z" stroke="#667085" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 875 B |
@@ -0,0 +1,3 @@
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M6 2H10M2 4H14M12.6667 4L12.1991 11.0129C12.129 12.065 12.0939 12.5911 11.8667 12.99C11.6666 13.3412 11.3648 13.6235 11.0011 13.7998C10.588 14 10.0607 14 9.00623 14H6.99377C5.93927 14 5.41202 14 4.99889 13.7998C4.63517 13.6235 4.33339 13.3412 4.13332 12.99C3.90607 12.5911 3.871 12.065 3.80086 11.0129L3.33333 4M6.66667 7V10.3333M9.33333 7V10.3333" stroke="#667085" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 548 B |
@@ -0,0 +1,3 @@
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M6 2H10M2 4H14M12.6667 4L12.1991 11.0129C12.129 12.065 12.0939 12.5911 11.8667 12.99C11.6666 13.3412 11.3648 13.6235 11.0011 13.7998C10.588 14 10.0607 14 9.00623 14H6.99377C5.93927 14 5.41202 14 4.99889 13.7998C4.63517 13.6235 4.33339 13.3412 4.13332 12.99C3.90607 12.5911 3.871 12.065 3.80086 11.0129L3.33333 4M6.66667 7V10.3333M9.33333 7V10.3333" stroke="#D92D20" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 550 B |
71
web/app/components/develop/secret-key/input-copy.tsx
Normal file
71
web/app/components/develop/secret-key/input-copy.tsx
Normal file
@@ -0,0 +1,71 @@
|
||||
'use client'
|
||||
import React, { useEffect, useState } from 'react'
|
||||
import useCopyToClipboard from '@/hooks/use-copy-to-clipboard'
|
||||
import Tooltip from '@/app/components/base/tooltip'
|
||||
import { t } from 'i18next'
|
||||
import s from './style.module.css'
|
||||
|
||||
type IInputCopyProps = {
|
||||
value?: string
|
||||
className?: string
|
||||
readOnly?: boolean
|
||||
children?: React.ReactNode
|
||||
}
|
||||
|
||||
const InputCopy = ({
|
||||
value,
|
||||
className,
|
||||
readOnly = true,
|
||||
children,
|
||||
}: IInputCopyProps) => {
|
||||
const [_, copy] = useCopyToClipboard()
|
||||
const [isCopied, setIsCopied] = useState(false)
|
||||
|
||||
useEffect(() => {
|
||||
if (isCopied) {
|
||||
const timeout = setTimeout(() => {
|
||||
setIsCopied(false)
|
||||
}, 1000)
|
||||
|
||||
return () => {
|
||||
clearTimeout(timeout)
|
||||
}
|
||||
}
|
||||
}, [isCopied])
|
||||
|
||||
return (
|
||||
<div className={`flex rounded-lg bg-gray-50 hover:bg-gray-50 py-2 items-center ${className}`}>
|
||||
<div className="flex items-center flex-grow h-5">
|
||||
{children}
|
||||
<div className='flex-grow bg-gray-50 text-[13px] relative h-full'>
|
||||
<Tooltip
|
||||
selector="top-uniq"
|
||||
content={isCopied ? `${t('appApi.copied')}` : `${t('appApi.copy')}`}
|
||||
className='z-10'
|
||||
>
|
||||
<div className='absolute top-0 left-0 w-full pl-2 pr-2 truncate cursor-pointer r-0' onClick={() => {
|
||||
copy(value)
|
||||
setIsCopied(true)
|
||||
}}>{value}</div>
|
||||
</Tooltip>
|
||||
</div>
|
||||
<div className="flex-shrink-0 h-4 bg-gray-200 border" />
|
||||
<Tooltip
|
||||
selector="top-uniq"
|
||||
content={isCopied ? `${t('appApi.copied')}` : `${t('appApi.copy')}`}
|
||||
className='z-10'
|
||||
>
|
||||
<div className="px-0.5 flex-shrink-0">
|
||||
<div className={`box-border w-[30px] h-[30px] flex items-center justify-center rounded-lg hover:bg-gray-100 cursor-pointer ${s.copyIcon} ${isCopied ? s.copied : ''}`} onClick={() => {
|
||||
copy(value)
|
||||
setIsCopied(true)
|
||||
}}>
|
||||
</div>
|
||||
</div>
|
||||
</Tooltip>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default InputCopy
|
||||
31
web/app/components/develop/secret-key/secret-key-button.tsx
Normal file
31
web/app/components/develop/secret-key/secret-key-button.tsx
Normal file
@@ -0,0 +1,31 @@
|
||||
'use client'
|
||||
import { useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import Button from '@/app/components/base/button'
|
||||
import SecretKeyModal from '@/app/components/develop/secret-key/secret-key-modal'
|
||||
// import { KeyIcon } from '@heroicons/react/20/solid'
|
||||
|
||||
type ISecretKeyButtonProps = {
|
||||
className?: string
|
||||
appId: string
|
||||
}
|
||||
|
||||
const SecretKeyButton = ({ className, appId }: ISecretKeyButtonProps) => {
|
||||
const [isVisible, setVisible] = useState(false)
|
||||
const { t } = useTranslation()
|
||||
return (
|
||||
<>
|
||||
<Button className={`px-3 ${className}`} type='default' onClick={() => setVisible(true)}>
|
||||
<div className='flex items-center justify-center w-4 h-4 mr-2'>
|
||||
<svg width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M9 3.66672C9.35362 3.66672 9.69276 3.80719 9.94281 4.05724C10.1929 4.30729 10.3333 4.64643 10.3333 5.00005M13 5.00005C13.0002 5.62483 12.854 6.24097 12.5732 6.79908C12.2924 7.3572 11.8847 7.84177 11.3829 8.21397C10.8811 8.58617 10.2991 8.83564 9.68347 8.94239C9.06788 9.04915 8.43584 9.01022 7.838 8.82872L6.33333 10.3334H5V11.6667H3.66667V13.0001H1.66667C1.48986 13.0001 1.32029 12.9298 1.19526 12.8048C1.07024 12.6798 1 12.5102 1 12.3334V10.6094C1.00004 10.4326 1.0703 10.263 1.19533 10.1381L5.17133 6.16205C5.00497 5.61206 4.95904 5.03268 5.0367 4.46335C5.11435 3.89402 5.31375 3.3481 5.62133 2.86275C5.92891 2.3774 6.33744 1.96401 6.81913 1.65073C7.30082 1.33745 7.84434 1.13162 8.41272 1.04725C8.9811 0.96289 9.56098 1.00197 10.1129 1.16184C10.6648 1.32171 11.1758 1.59861 11.6111 1.97369C12.0464 2.34878 12.3958 2.81324 12.6354 3.33548C12.8751 3.85771 12.9994 4.42545 13 5.00005Z" stroke="#1F2A37" strokeLinecap="round" strokeLinejoin="round" />
|
||||
</svg>
|
||||
</div>
|
||||
<div className='text-[13px] text-gray-800'>{t('appApi.apiKey')}</div>
|
||||
</Button>
|
||||
<SecretKeyModal isShow={isVisible} onClose={() => setVisible(false)} appId={appId} />
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
export default SecretKeyButton
|
||||
@@ -0,0 +1,41 @@
|
||||
'use client'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { XMarkIcon } from '@heroicons/react/20/solid'
|
||||
import InputCopy from './input-copy'
|
||||
import s from './style.module.css'
|
||||
import Button from '@/app/components/base/button'
|
||||
import Modal from '@/app/components/base/modal'
|
||||
import type { CreateApiKeyResponse } from '@/models/app'
|
||||
|
||||
type ISecretKeyGenerateModalProps = {
|
||||
isShow: boolean
|
||||
onClose: () => void
|
||||
newKey?: CreateApiKeyResponse
|
||||
className?: string
|
||||
}
|
||||
|
||||
const SecretKeyGenerateModal = ({
|
||||
isShow = false,
|
||||
onClose,
|
||||
newKey,
|
||||
className
|
||||
}: ISecretKeyGenerateModalProps) => {
|
||||
const { t } = useTranslation()
|
||||
return (
|
||||
<Modal isShow={isShow} onClose={onClose} title={`${t('appApi.apiKeyModal.apiSecretKey')}`} className={`px-8 ${className}`}>
|
||||
<XMarkIcon className={`w-6 h-6 absolute cursor-pointer text-gray-500 ${s.close}`} onClick={onClose} />
|
||||
<p className='mt-1 text-[13px] text-gray-500 font-normal leading-5'>{t('appApi.apiKeyModal.generateTips')}</p>
|
||||
<div className='my-4'>
|
||||
<InputCopy className='w-full' value={newKey?.token} />
|
||||
</div>
|
||||
<div className='flex justify-end my-4'>
|
||||
<Button type='default' className={`flex-shrink-0 ${s.w64}`} onClick={onClose}>
|
||||
<span className='text-xs font-medium text-gray-800'>{t('appApi.actionMsg.ok')}</span>
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
</Modal >
|
||||
)
|
||||
}
|
||||
|
||||
export default SecretKeyGenerateModal
|
||||
165
web/app/components/develop/secret-key/secret-key-modal.tsx
Normal file
165
web/app/components/develop/secret-key/secret-key-modal.tsx
Normal file
@@ -0,0 +1,165 @@
|
||||
'use client'
|
||||
import {
|
||||
useEffect,
|
||||
useState,
|
||||
} from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { PlusIcon, XMarkIcon } from '@heroicons/react/20/solid'
|
||||
import useSWR, { useSWRConfig } from 'swr'
|
||||
import SecretKeyGenerateModal from './secret-key-generate'
|
||||
import s from './style.module.css'
|
||||
import Modal from '@/app/components/base/modal'
|
||||
import Button from '@/app/components/base/button'
|
||||
import { createApikey, delApikey, fetchApiKeysList } from '@/service/apps'
|
||||
import type { CreateApiKeyResponse } from '@/models/app'
|
||||
import Tooltip from '@/app/components/base/tooltip'
|
||||
import Loading from '@/app/components/base/loading'
|
||||
import Confirm from '@/app/components/base/confirm'
|
||||
import useCopyToClipboard from '@/hooks/use-copy-to-clipboard'
|
||||
import { useContext } from 'use-context-selector'
|
||||
import I18n from '@/context/i18n'
|
||||
|
||||
type ISecretKeyModalProps = {
|
||||
isShow: boolean
|
||||
appId: string
|
||||
onClose: () => void
|
||||
}
|
||||
|
||||
const SecretKeyModal = ({
|
||||
isShow = false,
|
||||
appId,
|
||||
onClose,
|
||||
}: ISecretKeyModalProps) => {
|
||||
const { t } = useTranslation()
|
||||
const [showConfirmDelete, setShowConfirmDelete] = useState(false)
|
||||
const [isVisible, setVisible] = useState(false)
|
||||
const [newKey, setNewKey] = useState<CreateApiKeyResponse | undefined>(undefined)
|
||||
const { mutate } = useSWRConfig()
|
||||
const commonParams = { url: `/apps/${appId}/api-keys`, params: {} }
|
||||
const { data: apiKeysList } = useSWR(commonParams, fetchApiKeysList)
|
||||
|
||||
const [delKeyID, setDelKeyId] = useState('')
|
||||
const [_, copy] = useCopyToClipboard()
|
||||
|
||||
const { locale } = useContext(I18n)
|
||||
|
||||
// const [isCopied, setIsCopied] = useState(false)
|
||||
const [copyValue, setCopyValue] = useState('')
|
||||
|
||||
useEffect(() => {
|
||||
if (copyValue) {
|
||||
const timeout = setTimeout(() => {
|
||||
setCopyValue('')
|
||||
}, 1000)
|
||||
|
||||
return () => {
|
||||
clearTimeout(timeout)
|
||||
}
|
||||
}
|
||||
}, [copyValue])
|
||||
|
||||
|
||||
const onDel = async () => {
|
||||
setShowConfirmDelete(false)
|
||||
if (!delKeyID) {
|
||||
return
|
||||
}
|
||||
await delApikey({ url: `/apps/${appId}/api-keys/${delKeyID}`, params: {} })
|
||||
mutate(commonParams)
|
||||
}
|
||||
|
||||
const onCreate = async () => {
|
||||
const res = await createApikey({ url: `/apps/${appId}/api-keys`, body: {} })
|
||||
setVisible(true)
|
||||
setNewKey(res)
|
||||
mutate(commonParams)
|
||||
}
|
||||
|
||||
const generateToken = (token: string) => {
|
||||
return `${token.slice(0, 3)}...${token.slice(-20)}`
|
||||
}
|
||||
|
||||
const formatDate = (timestamp: any) => {
|
||||
if (locale === 'en') {
|
||||
return new Intl.DateTimeFormat('en-US', { year: 'numeric', month: 'long', day: 'numeric' }).format((+timestamp) * 1000)
|
||||
} else {
|
||||
return new Intl.DateTimeFormat('fr-CA', { year: 'numeric', month: '2-digit', day: '2-digit' }).format((+timestamp) * 1000)
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<Modal isShow={isShow} onClose={onClose} title={`${t('appApi.apiKeyModal.apiSecretKey')}`} className={`${s.customModal} px-8 flex flex-col`}>
|
||||
<XMarkIcon className={`w-6 h-6 absolute cursor-pointer text-gray-500 ${s.close}`} onClick={onClose} />
|
||||
<p className='mt-1 text-[13px] text-gray-500 font-normal leading-5 flex-shrink-0'>{t('appApi.apiKeyModal.apiSecretKeyTips')}</p>
|
||||
{!apiKeysList && <div className='mt-4'><Loading /></div>}
|
||||
{
|
||||
!!apiKeysList?.data?.length && (
|
||||
<div className='flex flex-col flex-grow mt-4 overflow-hidden'>
|
||||
<div className='flex items-center flex-shrink-0 text-xs font-semibold text-gray-500 border-b border-solid h-9'>
|
||||
<div className='flex-shrink-0 w-64 px-3'>{t('appApi.apiKeyModal.secretKey')}</div>
|
||||
<div className='flex-shrink-0 px-3 w-28'>{t('appApi.apiKeyModal.created')}</div>
|
||||
<div className='flex-shrink-0 px-3 w-28'>{t('appApi.apiKeyModal.lastUsed')}</div>
|
||||
<div className='flex-grow px-3'></div>
|
||||
</div>
|
||||
<div className='flex-grow overflow-auto'>
|
||||
{apiKeysList.data.map(api => (
|
||||
<div className='flex items-center text-sm font-normal text-gray-700 border-b border-solid h-9' key={api.id}>
|
||||
<div className='flex-shrink-0 w-64 px-3 font-mono truncate'>{generateToken(api.token)}</div>
|
||||
<div className='flex-shrink-0 px-3 truncate w-28'>{formatDate(api.created_at)}</div>
|
||||
{/* <div className='flex-shrink-0 px-3 truncate w-28'>{dayjs((+api.created_at) * 1000).format('MMM D, YYYY')}</div> */}
|
||||
{/* <div className='flex-shrink-0 px-3 truncate w-28'>{api.last_used_at ? dayjs((+api.last_used_at) * 1000).format('MMM D, YYYY') : 'Never'}</div> */}
|
||||
<div className='flex-shrink-0 px-3 truncate w-28'>{api.last_used_at ? formatDate(api.last_used_at) : t('appApi.never')}</div>
|
||||
<div className='flex flex-grow px-3'>
|
||||
<Tooltip
|
||||
selector="top-uniq"
|
||||
content={copyValue === api.token ? `${t('appApi.copied')}` : `${t('appApi.copy')}`}
|
||||
className='z-10'
|
||||
>
|
||||
<div className={`flex items-center justify-center flex-shrink-0 w-6 h-6 mr-1 rounded-lg cursor-pointer hover:bg-gray-100 ${s.copyIcon} ${copyValue === api.token ? s.copied : ''}`} onClick={() => {
|
||||
// setIsCopied(true)
|
||||
copy(api.token)
|
||||
setCopyValue(api.token)
|
||||
}}></div>
|
||||
</Tooltip>
|
||||
<div className={`flex items-center justify-center flex-shrink-0 w-6 h-6 rounded-lg cursor-pointer ${s.trashIcon}`} onClick={() => {
|
||||
setDelKeyId(api.id)
|
||||
setShowConfirmDelete(true)
|
||||
}}>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
<div className='flex'>
|
||||
<Button type='default' className={`flex flex-shrink-0 mt-4 ${s.autoWidth}`} onClick={() =>
|
||||
onCreate()
|
||||
}>
|
||||
<PlusIcon className='flex flex-shrink-0 w-4 h-4' />
|
||||
<div className='text-xs font-medium text-gray-800'>{t('appApi.apiKeyModal.createNewSecretKey')}</div>
|
||||
</Button>
|
||||
</div>
|
||||
<SecretKeyGenerateModal className='flex-shrink-0' isShow={isVisible} onClose={() => setVisible(false)} newKey={newKey} />
|
||||
{showConfirmDelete && (
|
||||
<Confirm
|
||||
title={`${t('appApi.actionMsg.deleteConfirmTitle')}`}
|
||||
content={`${t('appApi.actionMsg.deleteConfirmTips')}`}
|
||||
isShow={showConfirmDelete}
|
||||
onClose={() => {
|
||||
setDelKeyId('')
|
||||
setShowConfirmDelete(false)
|
||||
}}
|
||||
onConfirm={onDel}
|
||||
onCancel={() => {
|
||||
setDelKeyId('')
|
||||
setShowConfirmDelete(false)
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
</Modal >
|
||||
)
|
||||
}
|
||||
|
||||
export default SecretKeyModal
|
||||
61
web/app/components/develop/secret-key/style.module.css
Normal file
61
web/app/components/develop/secret-key/style.module.css
Normal file
@@ -0,0 +1,61 @@
|
||||
.customModal {
|
||||
max-width: 40rem !important;
|
||||
max-height: calc(100vh - 80px);
|
||||
}
|
||||
|
||||
.close {
|
||||
top: 1.5rem;
|
||||
right: 1.5rem;
|
||||
}
|
||||
|
||||
.trash {
|
||||
color: transparent;
|
||||
}
|
||||
|
||||
.w64 {
|
||||
width: 4rem;
|
||||
}
|
||||
|
||||
.w320 {
|
||||
width: 20rem;
|
||||
}
|
||||
|
||||
.customApi {
|
||||
font-size: 11px;
|
||||
}
|
||||
|
||||
.autoWidth {
|
||||
width: auto;
|
||||
}
|
||||
|
||||
.trashIcon {
|
||||
background-color: transparent;
|
||||
background-image: url(./assets/trash-gray.svg);
|
||||
background-position: center;
|
||||
background-repeat: no-repeat;
|
||||
background-size: 16px 16px;
|
||||
}
|
||||
|
||||
.trashIcon:hover {
|
||||
background-color: rgba(254, 228, 226, 1);
|
||||
background-image: url(./assets/trash-red.svg);
|
||||
background-position: center;
|
||||
background-repeat: no-repeat;
|
||||
background-size: 16px 16px;
|
||||
}
|
||||
|
||||
.copyIcon {
|
||||
background-image: url(./assets/copy.svg);
|
||||
background-position: center;
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
|
||||
.copyIcon:hover {
|
||||
background-image: url(./assets/copy-hover.svg);
|
||||
background-position: center;
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
|
||||
.copyIcon.copied {
|
||||
background-image: url(./assets/copied.svg);
|
||||
}
|
||||
65
web/app/components/develop/tag.tsx
Normal file
65
web/app/components/develop/tag.tsx
Normal file
@@ -0,0 +1,65 @@
|
||||
'use client'
|
||||
import classNames from 'classnames'
|
||||
|
||||
const variantStyles = {
|
||||
medium: 'rounded-lg px-1.5 ring-1 ring-inset',
|
||||
} as { [key: string]: string }
|
||||
|
||||
const colorStyles = {
|
||||
emerald: {
|
||||
small: 'text-emerald-500 dark:text-emerald-400',
|
||||
medium:
|
||||
'ring-emerald-300 dark:ring-emerald-400/30 bg-emerald-400/10 text-emerald-500 dark:text-emerald-400',
|
||||
},
|
||||
sky: {
|
||||
small: 'text-sky-500',
|
||||
medium:
|
||||
'ring-sky-300 bg-sky-400/10 text-sky-500 dark:ring-sky-400/30 dark:bg-sky-400/10 dark:text-sky-400',
|
||||
},
|
||||
amber: {
|
||||
small: 'text-amber-500',
|
||||
medium:
|
||||
'ring-amber-300 bg-amber-400/10 text-amber-500 dark:ring-amber-400/30 dark:bg-amber-400/10 dark:text-amber-400',
|
||||
},
|
||||
rose: {
|
||||
small: 'text-red-500 dark:text-rose-500',
|
||||
medium:
|
||||
'ring-rose-200 bg-rose-50 text-red-500 dark:ring-rose-500/20 dark:bg-rose-400/10 dark:text-rose-400',
|
||||
},
|
||||
zinc: {
|
||||
small: 'text-zinc-400 dark:text-zinc-500',
|
||||
medium:
|
||||
'ring-zinc-200 bg-zinc-50 text-zinc-500 dark:ring-zinc-500/20 dark:bg-zinc-400/10 dark:text-zinc-400',
|
||||
},
|
||||
} as { [key: string]: { [key: string]: string } }
|
||||
|
||||
const valueColorMap = {
|
||||
get: 'emerald',
|
||||
post: 'sky',
|
||||
put: 'amber',
|
||||
delete: 'rose',
|
||||
} as { [key: string]: string }
|
||||
|
||||
type ITagProps = {
|
||||
children: string
|
||||
color?: string
|
||||
variant?: string
|
||||
}
|
||||
|
||||
export function Tag({
|
||||
children,
|
||||
variant = 'medium',
|
||||
color = valueColorMap[children.toLowerCase()] ?? 'emerald',
|
||||
}: ITagProps) {
|
||||
return (
|
||||
<span
|
||||
className={classNames(
|
||||
'font-mono text-[0.625rem] font-semibold leading-6',
|
||||
variantStyles[variant],
|
||||
colorStyles[color][variant],
|
||||
)}
|
||||
>
|
||||
{children}
|
||||
</span>
|
||||
)
|
||||
}
|
||||
206
web/app/components/develop/template/template.en.mdx
Normal file
206
web/app/components/develop/template/template.en.mdx
Normal file
@@ -0,0 +1,206 @@
|
||||
import { CodeGroup } from '../code.tsx'
|
||||
import { Row, Col, Properties, Property, Heading, SubProperty, Paragraph } from '../md.tsx'
|
||||
|
||||
# Completion App API
|
||||
|
||||
For high-quality text generation, such as articles, summaries, and translations, use the completion-messages API with user input. Text generation relies on the model parameters and prompt templates set in LangGenius Prompt Engineering.
|
||||
|
||||
<Heading
|
||||
url='/completion-messages'
|
||||
method='POST'
|
||||
title='Create Completion Message'
|
||||
name='#Create-Completion-Message'
|
||||
/>
|
||||
<Row>
|
||||
<Col>
|
||||
Create a Completion Message to support the question-and-answer mode.
|
||||
|
||||
### Request Body
|
||||
|
||||
<Properties>
|
||||
<Property name='inputs' type='object' key='inputs'>
|
||||
(Optional) Provide user input fields as key-value pairs, corresponding to variables in Prompt Eng. Key is the variable name, Value is the parameter value. If the field type is Select, the submitted Value must be one of the preset choices.
|
||||
<ul>
|
||||
{!!props.variables.length && props.variables.map(
|
||||
val => (
|
||||
<SubProperty name={val.key} type={val.type} key={val.key}>
|
||||
{val.name ? `${val.name}` : ''}
|
||||
</SubProperty>
|
||||
)
|
||||
)}
|
||||
</ul>
|
||||
</Property>
|
||||
<Property name='query' type='string' key='query'>
|
||||
User input text content.
|
||||
</Property>
|
||||
<Property name='response_mode' type='string' key='response_mode'>
|
||||
- Blocking type, waiting for execution to complete and returning results. (Requests may be interrupted if the process is long)
|
||||
- streaming returns. Implementation of streaming return based on SSE (**[Server-Sent Events](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events)**).
|
||||
</Property>
|
||||
<Property name='user' type='string' key='user'>
|
||||
The user identifier, defined by the developer, must ensure uniqueness within the app.
|
||||
</Property>
|
||||
</Properties>
|
||||
</Col>
|
||||
<Col sticky>
|
||||
|
||||
<CodeGroup title="Request" tag="POST" label="/completion-messages" targetCode={`curl --location --request POST '${props.appDetail.api_base_url}/completion-messages' \\\n--header 'Authorization: Bearer ENTER-YOUR-SECRET-KEY' \\\n--header 'Content-Type: application/json' \\\n--data-raw '{\n "inputs": ${JSON.stringify(props.inputs)},\n "query": "Hi",\n "response_mode": "streaming"\n "user": "abc-123"\n}'\n`}>
|
||||
|
||||
```bash {{ title: 'cURL' }}
|
||||
curl --location --request POST 'https://cloud.langgenius.dev/api/completion-messages' \
|
||||
--header 'Authorization: Bearer ENTER-YOUR-SECRET-KEY' \
|
||||
--header 'Content-Type: application/json' \
|
||||
--data-raw '{
|
||||
"inputs": {},
|
||||
"query": "Hi",
|
||||
"response_mode": "streaming",
|
||||
"user": "abc-123"
|
||||
}'
|
||||
```
|
||||
|
||||
</CodeGroup>
|
||||
### blocking
|
||||
<CodeGroup title="Response">
|
||||
```json {{ title: 'Response' }}
|
||||
{
|
||||
"id": "0b089b9a-24d9-48cc-94f8-762677276261",
|
||||
"answer": "how are you?",
|
||||
"created_at": 1679586667
|
||||
}
|
||||
```
|
||||
</CodeGroup>
|
||||
### streaming
|
||||
<CodeGroup title="Response">
|
||||
```streaming {{ title: 'Response' }}
|
||||
data: {"id": "5ad4cb98-f0c7-4085-b384-88c403be6290", "answer": " I", "created_at": 1679586595}
|
||||
data: {"id": "5ad4cb98-f0c7-4085-b384-88c403be6290", "answer": " I", "created_at": 1679586595}
|
||||
```
|
||||
</CodeGroup>
|
||||
</Col>
|
||||
</Row>
|
||||
|
||||
---
|
||||
|
||||
<Heading
|
||||
url='/messages/{message_id}/feedbacks'
|
||||
method='POST'
|
||||
title='Message feedback (like)'
|
||||
name='#feedbacks'
|
||||
/>
|
||||
<Row>
|
||||
<Col>
|
||||
Rate received messages on behalf of end-users with likes or dislikes. This data is visible in the Logs & Annotations page and used for future model fine-tuning.
|
||||
|
||||
### Path Params
|
||||
|
||||
<Properties>
|
||||
<Property name='message_id' type='string' key='message_id'>
|
||||
Message ID
|
||||
</Property>
|
||||
</Properties>
|
||||
|
||||
### Request Body
|
||||
|
||||
<Properties>
|
||||
<Property name='rating' type='string' key='rating'>
|
||||
like or dislike, null is undo
|
||||
</Property>
|
||||
<Property name='user' type='string' key='user'>
|
||||
The user identifier, defined by the developer, must ensure uniqueness within the app.
|
||||
</Property>
|
||||
</Properties>
|
||||
</Col>
|
||||
<Col sticky>
|
||||
|
||||
<CodeGroup title="Request" tag="POST" label="/messages/{message_id}/feedbacks" targetCode={`curl --location --request POST '${props.appDetail.api_base_url}/messages/{message_id}/feedbacks \\\n--header 'Authorization: Bearer ENTER-YOUR-SECRET-KEY' \\\n--header 'Content-Type: application/json' \\\n --data-raw '{ \n "rating": "like",\n "user": "abc-123"\n}'`}>
|
||||
|
||||
```bash {{ title: 'cURL' }}
|
||||
curl --location --request POST 'https://cloud.langgenius.dev/api/messages/{message_id}/feedbacks' \
|
||||
--header 'Authorization: Bearer ENTER-YOUR-SECRET-KEY' \
|
||||
--header 'Content-Type: application/json' \
|
||||
--data-raw '{
|
||||
"rating": "like",
|
||||
"user": "abc-123"
|
||||
}'
|
||||
```
|
||||
|
||||
</CodeGroup>
|
||||
|
||||
<CodeGroup title="Response">
|
||||
```json {{ title: 'Response' }}
|
||||
{
|
||||
"has_more": false,
|
||||
"data": [
|
||||
{
|
||||
"id": "WAz8eIbvDR60rouK",
|
||||
"username": "FrankMcCallister",
|
||||
"phone_number": "1-800-759-3000",
|
||||
"avatar_url": "https://assets.protocol.chat/avatars/frank.jpg",
|
||||
"display_name": null,
|
||||
"conversation_id": "xgQQXg3hrtjh7AvZ",
|
||||
"last_active_at": 705103200,
|
||||
"created_at": 692233200
|
||||
},
|
||||
{
|
||||
"id": "hSIhXBhNe8X1d8Et"
|
||||
// ...
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
</CodeGroup>
|
||||
</Col>
|
||||
</Row>
|
||||
|
||||
---
|
||||
|
||||
<Heading
|
||||
url='/parameters'
|
||||
method='GET'
|
||||
title='Obtain application parameter information'
|
||||
name='#parameters'
|
||||
/>
|
||||
<Row>
|
||||
<Col>
|
||||
Retrieve configured Input parameters, including variable names, field names, types, and default values. Typically used for displaying these fields in a form or filling in default values after the client loads.
|
||||
|
||||
### Query
|
||||
|
||||
<Properties>
|
||||
<Property name='user' type='string' key='user'>
|
||||
The user identifier, defined by the developer, must ensure uniqueness within the app.
|
||||
</Property>
|
||||
</Properties>
|
||||
</Col>
|
||||
<Col sticky>
|
||||
|
||||
<CodeGroup title="Request" tag="GET" label="/parameters" targetCode={`curl --location --request GET '${props.appDetail.api_base_url}/parameters?user=abc-123' \\\n--header 'Authorization: Bearer ENTER-YOUR-SECRET-KEY'`}>
|
||||
|
||||
```bash {{ title: 'cURL' }}
|
||||
curl --location --request GET 'https://cloud.langgenius.dev/api/parameters?user=abc-123' \
|
||||
--header 'Authorization: Bearer ENTER-YOUR-SECRET-KEY'
|
||||
```
|
||||
|
||||
</CodeGroup>
|
||||
|
||||
<CodeGroup title="Response">
|
||||
```json {{ title: 'Response' }}
|
||||
{
|
||||
"introduction": "nice to meet you",
|
||||
"variables": [
|
||||
{
|
||||
"key": "book",
|
||||
"name": "Which book?",
|
||||
"description": null,
|
||||
"type": "string",
|
||||
"default": null,
|
||||
"options": null
|
||||
},
|
||||
{
|
||||
// ...
|
||||
]
|
||||
}
|
||||
```
|
||||
</CodeGroup>
|
||||
</Col>
|
||||
</Row>
|
||||
206
web/app/components/develop/template/template.zh.mdx
Normal file
206
web/app/components/develop/template/template.zh.mdx
Normal file
@@ -0,0 +1,206 @@
|
||||
import { CodeGroup } from '../code.tsx'
|
||||
import { Row, Col, Properties, Property, Heading, SubProperty } from '../md.tsx'
|
||||
|
||||
# 文本生成型应用 API
|
||||
|
||||
可用于生成高质量文本的应用,例如生成文章、摘要、翻译等,通过调用 completion-messages 接口,发送用户输入得到生成文本结果。用于生成文本的模型参数和提示词模版取决于开发者在 LangGenius 提示词编排页的设置。
|
||||
|
||||
<Heading
|
||||
url='/completion-messages'
|
||||
method='POST'
|
||||
title='创建文本补全消息'
|
||||
name='#Create-Completion-Message'
|
||||
/>
|
||||
<Row>
|
||||
<Col>
|
||||
创建文本补全消息,支持一问一答模式。
|
||||
|
||||
### Request Body
|
||||
|
||||
<Properties>
|
||||
<Property name='inputs' type='object' key='inputs'>
|
||||
(选填)以键值对方式提供用户输入字段,与提示词编排中的变量对应。Key 为变量名称,Value 是参数值。如果字段类型为 Select,传入的 Value 需为预设选项之一。
|
||||
<ul>
|
||||
{!!props.variables.length && props.variables.map(
|
||||
val => (
|
||||
<SubProperty name={val.key} type={val.type} key={val.key}>
|
||||
{val.name ? `${val.name}` : ''}
|
||||
</SubProperty>
|
||||
)
|
||||
)}
|
||||
</ul>
|
||||
</Property>
|
||||
<Property name='query' type='string' key='query'>
|
||||
用户输入的文本正文。
|
||||
</Property>
|
||||
<Property name='response_mode' type='string' key='response_mode'>
|
||||
- blocking 阻塞型,等待执行完毕后返回结果。(请求若流程较长可能会被中断)
|
||||
- streaming 流式返回。基于 SSE(**[Server-Sent Events](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events)**)实现流式返回。
|
||||
</Property>
|
||||
<Property name='user' type='string' key='user'>
|
||||
用户标识,由开发者定义规则,需保证用户标识在应用内唯一。
|
||||
</Property>
|
||||
</Properties>
|
||||
</Col>
|
||||
<Col sticky>
|
||||
|
||||
<CodeGroup title="Request" tag="POST" label="/completion-messages" targetCode={`curl --location --request POST '${props.appDetail.api_base_url}/completion-messages' \\\n--header 'Authorization: Bearer ENTER-YOUR-SECRET-KEY' \\\n--header 'Content-Type: application/json' \\\n--data-raw '{\n "inputs": ${JSON.stringify(props.inputs)},\n "query": "Hi",\n "response_mode": "streaming",\n "user": "abc-123"\n}'\n`}>
|
||||
|
||||
```bash {{ title: 'cURL' }}
|
||||
curl --location --request POST 'https://cloud.langgenius.dev/api/completion-messages' \
|
||||
--header 'Authorization: Bearer ENTER-YOUR-SECRET-KEY' \
|
||||
--header 'Content-Type: application/json' \
|
||||
--data-raw '{
|
||||
"inputs": {},
|
||||
"query": "Hi",
|
||||
"response_mode": "streaming",
|
||||
"user": "abc-123"
|
||||
}'
|
||||
```
|
||||
|
||||
</CodeGroup>
|
||||
### blocking
|
||||
<CodeGroup title="Response">
|
||||
```json {{ title: 'Response' }}
|
||||
{
|
||||
"id": "0b089b9a-24d9-48cc-94f8-762677276261",
|
||||
"answer": "how are you?",
|
||||
"created_at": 1679586667
|
||||
}
|
||||
```
|
||||
</CodeGroup>
|
||||
### streaming
|
||||
<CodeGroup title="Response">
|
||||
```streaming {{ title: 'Response' }}
|
||||
data: {"id": "5ad4cb98-f0c7-4085-b384-88c403be6290", "answer": " I", "created_at": 1679586595}
|
||||
data: {"id": "5ad4cb98-f0c7-4085-b384-88c403be6290", "answer": " I", "created_at": 1679586595}
|
||||
```
|
||||
</CodeGroup>
|
||||
</Col>
|
||||
</Row>
|
||||
|
||||
---
|
||||
|
||||
<Heading
|
||||
url='/messages/{message_id}/feedbacks'
|
||||
method='POST'
|
||||
title='消息反馈(点赞)'
|
||||
name='#feedbacks'
|
||||
/>
|
||||
<Row>
|
||||
<Col>
|
||||
代表最终用户对返回消息进行评价,可以点赞与点踩,该数据将在“日志与标注”页中可见,并用于后续的模型微调。
|
||||
|
||||
### Path Params
|
||||
|
||||
<Properties>
|
||||
<Property name='message_id' type='string' key='message_id'>
|
||||
消息 ID
|
||||
</Property>
|
||||
</Properties>
|
||||
|
||||
### Request Body
|
||||
|
||||
<Properties>
|
||||
<Property name='rating' type='string' key='rating'>
|
||||
like 或 dislike, 空值为撤销
|
||||
</Property>
|
||||
<Property name='user' type='string' key='user'>
|
||||
用户标识,由开发者定义规则,需保证用户标识在应用内唯一。
|
||||
</Property>
|
||||
</Properties>
|
||||
</Col>
|
||||
<Col sticky>
|
||||
|
||||
<CodeGroup title="Request" tag="POST" label="/messages/{message_id}/feedbacks" targetCode={`curl --location --request POST '${props.appDetail.api_base_url}/messages/{message_id}/feedbacks \\\n--header 'Authorization: Bearer ENTER-YOUR-SECRET-KEY' \\\n--header 'Content-Type: application/json' \\\n --data-raw '{ \n "rating": "like",\n "user": "abc-123"\n}'`}>
|
||||
|
||||
```bash {{ title: 'cURL' }}
|
||||
curl --location --request POST 'https://cloud.langgenius.dev/api/messages/{message_id}/feedbacks' \
|
||||
--header 'Authorization: Bearer ENTER-YOUR-SECRET-KEY' \
|
||||
--header 'Content-Type: application/json' \
|
||||
--data-raw '{
|
||||
"rating": "like",
|
||||
"user": "abc-123"
|
||||
}'
|
||||
```
|
||||
|
||||
</CodeGroup>
|
||||
|
||||
<CodeGroup title="Response">
|
||||
```json {{ title: 'Response' }}
|
||||
{
|
||||
"has_more": false,
|
||||
"data": [
|
||||
{
|
||||
"id": "WAz8eIbvDR60rouK",
|
||||
"username": "FrankMcCallister",
|
||||
"phone_number": "1-800-759-3000",
|
||||
"avatar_url": "https://assets.protocol.chat/avatars/frank.jpg",
|
||||
"display_name": null,
|
||||
"conversation_id": "xgQQXg3hrtjh7AvZ",
|
||||
"last_active_at": 705103200,
|
||||
"created_at": 692233200
|
||||
},
|
||||
{
|
||||
"id": "hSIhXBhNe8X1d8Et"
|
||||
// ...
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
</CodeGroup>
|
||||
</Col>
|
||||
</Row>
|
||||
|
||||
---
|
||||
|
||||
<Heading
|
||||
url='/parameters'
|
||||
method='GET'
|
||||
title='获取应用配置信息'
|
||||
name='#parameters'
|
||||
/>
|
||||
<Row>
|
||||
<Col>
|
||||
获取已配置的 Input 参数,包括变量名、字段名称、类型与默认值。通常用于客户端加载后显示这些字段的表单或填入默认值。
|
||||
|
||||
### Query
|
||||
|
||||
<Properties>
|
||||
<Property name='user' type='string' key='user'>
|
||||
用户标识,由开发者定义规则,需保证用户标识在应用内唯一。
|
||||
</Property>
|
||||
</Properties>
|
||||
</Col>
|
||||
<Col sticky>
|
||||
|
||||
<CodeGroup title="Request" tag="GET" label="/parameters" targetCode={`curl --location --request GET '${props.appDetail.api_base_url}/parameters?user=abc-123' \\\n--header 'Authorization: Bearer ENTER-YOUR-SECRET-KEY'`}>
|
||||
|
||||
```bash {{ title: 'cURL' }}
|
||||
curl --location --request GET 'https://cloud.langgenius.dev/api/parameters?user=abc-123' \
|
||||
--header 'Authorization: Bearer ENTER-YOUR-SECRET-KEY'
|
||||
```
|
||||
|
||||
</CodeGroup>
|
||||
|
||||
<CodeGroup title="Response">
|
||||
```json {{ title: 'Response' }}
|
||||
{
|
||||
"introduction": "nice to meet you",
|
||||
"variables": [
|
||||
{
|
||||
"key": "book",
|
||||
"name": "Which book?",
|
||||
"description": null,
|
||||
"type": "string",
|
||||
"default": null,
|
||||
"options": null
|
||||
},
|
||||
{
|
||||
// ...
|
||||
]
|
||||
}
|
||||
```
|
||||
</CodeGroup>
|
||||
</Col>
|
||||
</Row>
|
||||
391
web/app/components/develop/template/template_chat.en.mdx
Normal file
391
web/app/components/develop/template/template_chat.en.mdx
Normal file
@@ -0,0 +1,391 @@
|
||||
import { CodeGroup } from '../code.tsx'
|
||||
import { Row, Col, Properties, Property, Heading, SubProperty, Paragraph } from '../md.tsx'
|
||||
|
||||
# Chat App API
|
||||
|
||||
For versatile conversational apps using a Q&A format, call the chat-messages API to initiate dialogue. Maintain ongoing conversations by passing the returned conversation_id. Response parameters and templates depend on LangGenius Prompt Eng. settings.
|
||||
|
||||
<Heading
|
||||
url='/chat-messages'
|
||||
method='POST'
|
||||
title='Create chat message'
|
||||
name='#Create-Chat-Message'
|
||||
/>
|
||||
<Row>
|
||||
<Col>
|
||||
Create a new conversation message or continue an existing dialogue.
|
||||
|
||||
### Request Body
|
||||
|
||||
<Properties>
|
||||
<Property name='inputs' type='object' key='inputs'>
|
||||
(Optional) Provide user input fields as key-value pairs, corresponding to variables in Prompt Eng. Key is the variable name, Value is the parameter value. If the field type is Select, the submitted Value must be one of the preset choices.
|
||||
<ul>
|
||||
{!!props.variables.length && props.variables.map(
|
||||
val => (
|
||||
<SubProperty name={val.key} type={val.type} key={val.key}>
|
||||
{val.name ? `${val.name}` : ''}
|
||||
</SubProperty>
|
||||
)
|
||||
)}
|
||||
</ul>
|
||||
</Property>
|
||||
<Property name='query' type='string' key='query'>
|
||||
User input/question content
|
||||
</Property>
|
||||
<Property name='response_mode' type='string' key='response_mode'>
|
||||
- Blocking type, waiting for execution to complete and returning results. (Requests may be interrupted if the process is long)
|
||||
- streaming returns. Implementation of streaming return based on SSE (**[Server-Sent Events](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events)**).
|
||||
</Property>
|
||||
<Property name='conversation_id' type='string' key='conversation_id'>
|
||||
(Optional) Conversation ID: leave empty for first-time conversation; pass conversation_id from context to continue dialogue.
|
||||
</Property>
|
||||
<Property name='user' type='string' key='user'>
|
||||
The user identifier, defined by the developer, must ensure uniqueness within the app.
|
||||
</Property>
|
||||
</Properties>
|
||||
</Col>
|
||||
<Col sticky>
|
||||
|
||||
<CodeGroup title="Request" tag="POST" label="/chat-messages" targetCode={`curl --location --request POST '${props.appDetail.api_base_url}/chat-messages' \\\n--header 'Authorization: Bearer ENTER-YOUR-SECRET-KEY' \\\n--header 'Content-Type: application/json' \\\n--data-raw '{\n "inputs": ${JSON.stringify(props.inputs)},\n "query": "eh",\n "response_mode": "streaming",\n "conversation_id": "1c7e55fb-1ba2-4e10-81b5-30addcea2276",\n "user": "abc-123"\n}'\n`}>
|
||||
|
||||
```bash {{ title: 'cURL' }}
|
||||
curl --location --request POST 'https://cloud.langgenius.dev/api/chat-messages' \
|
||||
--header 'Authorization: Bearer ENTER-YOUR-SECRET-KEY' \
|
||||
--header 'Content-Type: application/json' \
|
||||
--data-raw '{
|
||||
"inputs": {},
|
||||
"query": "eh",
|
||||
"response_mode": "streaming",
|
||||
"conversation_id": "1c7e55fb-1ba2-4e10-81b5-30addcea2276",
|
||||
"user": "abc-123"
|
||||
}'
|
||||
```
|
||||
|
||||
</CodeGroup>
|
||||
### blocking
|
||||
<CodeGroup title="Response">
|
||||
```json {{ title: 'Response' }}
|
||||
{
|
||||
"answer": "Hi, is there anything I can help you?",
|
||||
"conversation_id": "45701982-8118-4bc5-8e9b-64562b4555f2",
|
||||
"created_at": 1679587005,
|
||||
"id": "059f87d9-15c0-473a-870c-fde95cdcc1e4"
|
||||
}
|
||||
```
|
||||
</CodeGroup>
|
||||
### streaming
|
||||
<CodeGroup title="Response">
|
||||
```streaming {{ title: 'Response' }}
|
||||
data: {"id": "5ad4cb98-f0c7-4085-b384-88c403be6290", "answer": " I", "created_at": 1679586595}
|
||||
data: {"id": "5ad4cb98-f0c7-4085-b384-88c403be6290", "answer": " I", "created_at": 1679586595}
|
||||
```
|
||||
</CodeGroup>
|
||||
</Col>
|
||||
</Row>
|
||||
|
||||
---
|
||||
|
||||
<Heading
|
||||
url='/messages/{message_id}/feedbacks'
|
||||
method='POST'
|
||||
title='Message terminal user feedback, like'
|
||||
name='#feedbacks'
|
||||
/>
|
||||
<Row>
|
||||
<Col>
|
||||
Rate received messages on behalf of end-users with likes or dislikes. This data is visible in the Logs & Annotations page and used for future model fine-tuning.
|
||||
|
||||
### Path Params
|
||||
<Properties>
|
||||
<Property name='message_id' type='string' key='message_id'>
|
||||
Message ID
|
||||
</Property>
|
||||
</Properties>
|
||||
|
||||
### Request Body
|
||||
|
||||
<Properties>
|
||||
<Property name='rating' type='string' key='rating'>
|
||||
like or dislike, null is undo
|
||||
</Property>
|
||||
<Property name='user' type='string' key='user'>
|
||||
The user identifier, defined by the developer, must ensure uniqueness within the app.
|
||||
</Property>
|
||||
</Properties>
|
||||
</Col>
|
||||
<Col sticky>
|
||||
|
||||
<CodeGroup title="Request" tag="POST" label="/messages/{message_id}/feedbacks" targetCode={`curl --location --request POST '${props.appDetail.api_base_url}/messages/{message_id}/feedbacks \\\n --header 'Authorization: Bearer ENTER-YOUR-SECRET-KEY' \\\n--header 'Content-Type: application/json' \\\n--data-raw '{\n "rating": "like",\n "user": "abc-123"\n}'`}>
|
||||
|
||||
```bash {{ title: 'cURL' }}
|
||||
curl --location --request POST 'https://cloud.langgenius.dev/api/messages/{message_id}/feedbacks' \
|
||||
--header 'Authorization: Bearer ENTER-YOUR-SECRET-KEY' \
|
||||
--header 'Content-Type: application/json' \
|
||||
--data-raw '{
|
||||
"rating": "like",
|
||||
"user": "abc-123"
|
||||
}'
|
||||
```
|
||||
|
||||
</CodeGroup>
|
||||
|
||||
<CodeGroup title="Response">
|
||||
```json {{ title: 'Response' }}
|
||||
{
|
||||
"has_more": false,
|
||||
"data": [
|
||||
{
|
||||
"id": "WAz8eIbvDR60rouK",
|
||||
"username": "FrankMcCallister",
|
||||
"phone_number": "1-800-759-3000",
|
||||
"avatar_url": "https://assets.protocol.chat/avatars/frank.jpg",
|
||||
"display_name": null,
|
||||
"conversation_id": "xgQQXg3hrtjh7AvZ",
|
||||
"last_active_at": 705103200,
|
||||
"created_at": 692233200
|
||||
},
|
||||
{
|
||||
"id": "hSIhXBhNe8X1d8Et"
|
||||
// ...
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
</CodeGroup>
|
||||
</Col>
|
||||
</Row>
|
||||
|
||||
---
|
||||
|
||||
<Heading
|
||||
url='/messages'
|
||||
method='GET'
|
||||
title='Get the chat history message'
|
||||
name='#messages'
|
||||
/>
|
||||
<Row>
|
||||
<Col>
|
||||
The first page returns the latest `limit` bar, which is in reverse order.
|
||||
|
||||
### Query
|
||||
|
||||
<Properties>
|
||||
<Property name='conversation_id' type='string' key='conversation_id'>
|
||||
Conversation ID
|
||||
</Property>
|
||||
<Property name='first_id' type='string' key='first_id'>
|
||||
ID of the first chat record on the current page. The default is none.
|
||||
</Property>
|
||||
<Property name='limit' type='int' key='limit'>
|
||||
How many chats are returned in one request
|
||||
</Property>
|
||||
<Property name='user' type='string' key='user'>
|
||||
The user identifier, defined by the developer, must ensure uniqueness within the app.
|
||||
</Property>
|
||||
</Properties>
|
||||
</Col>
|
||||
<Col sticky>
|
||||
|
||||
<CodeGroup title="Request" tag="GET" label="/messages" targetCode={`curl --location --request GET '${props.appDetail.api_base_url}/messages?user=abc-123&conversation_id='\\\n --header 'Authorization: Bearer ENTER-YOUR-SECRET-KEY'`}>
|
||||
|
||||
```bash {{ title: 'cURL' }}
|
||||
curl --location --request GET 'https://cloud.langgenius.dev/api/messages?user=abc-123&conversation_id='
|
||||
--header 'Authorization: Bearer ENTER-YOUR-SECRET-KEY'
|
||||
```
|
||||
|
||||
</CodeGroup>
|
||||
|
||||
<CodeGroup title="Response">
|
||||
```json {{ title: 'Response' }}
|
||||
{
|
||||
"has_more": false,
|
||||
"data": [
|
||||
{
|
||||
"id": "WAz8eIbvDR60rouK",
|
||||
"username": "FrankMcCallister",
|
||||
"phone_number": "1-800-759-3000",
|
||||
"avatar_url": "https://assets.protocol.chat/avatars/frank.jpg",
|
||||
"display_name": null,
|
||||
"conversation_id": "xgQQXg3hrtjh7AvZ",
|
||||
"last_active_at": 705103200,
|
||||
"created_at": 692233200
|
||||
},
|
||||
{
|
||||
"id": "hSIhXBhNe8X1d8Et"
|
||||
// ...
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
</CodeGroup>
|
||||
</Col>
|
||||
</Row>
|
||||
|
||||
---
|
||||
|
||||
<Heading
|
||||
url='/conversations'
|
||||
method='GET'
|
||||
title='Get conversation list'
|
||||
name='#conversations'
|
||||
/>
|
||||
<Row>
|
||||
<Col>
|
||||
Gets the session list of the current user. By default, the last 20 sessions are returned.
|
||||
|
||||
### Query
|
||||
|
||||
<Properties>
|
||||
<Property name='last_id' type='string' key='last_id'>
|
||||
The ID of the last record on the current page, default none.
|
||||
</Property>
|
||||
<Property name='limit' type='int' key='limit'>
|
||||
"How many chats are returned in one request
|
||||
</Property>
|
||||
<Property name='user' type='string' key='user'>
|
||||
The user identifier, defined by the developer, must ensure uniqueness within the app.
|
||||
</Property>
|
||||
</Properties>
|
||||
</Col>
|
||||
<Col sticky>
|
||||
|
||||
<CodeGroup title="Request" tag="GET" label="/conversations" targetCode={`curl --location --request GET '${props.appDetail.api_base_url}/conversations?user=abc-123&last_id=&limit=20'`}>
|
||||
|
||||
```bash {{ title: 'cURL' }}
|
||||
curl --location --request GET 'https://cloud.langgenius.dev/api/conversations?user=abc-123&last_id=&limit=20' \
|
||||
--header 'Authorization: Bearer ENTER-YOUR-SECRET-KEY'
|
||||
```
|
||||
|
||||
</CodeGroup>
|
||||
|
||||
<CodeGroup title="Response">
|
||||
```json {{ title: 'Response' }}
|
||||
{
|
||||
"limit": 20,
|
||||
"has_more": false,
|
||||
"data": [
|
||||
{
|
||||
"id": "10799fb8-64f7-4296-bbf7-b42bfbe0ae54",
|
||||
"name": "New chat",
|
||||
"inputs": {
|
||||
"book": "book",
|
||||
"myName": "Lucy"
|
||||
},
|
||||
"status": "normal",
|
||||
"created_at": 1679667915
|
||||
},
|
||||
{
|
||||
"id": "hSIhXBhNe8X1d8Et"
|
||||
// ...
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
</CodeGroup>
|
||||
</Col>
|
||||
</Row>
|
||||
|
||||
---
|
||||
|
||||
<Heading
|
||||
url='/conversations/{converation_id}/name'
|
||||
method='POST'
|
||||
title='Conversation renaming'
|
||||
name='#rename'
|
||||
/>
|
||||
<Row>
|
||||
<Col>
|
||||
Rename conversations; the name is displayed in multi-session client interfaces.
|
||||
|
||||
### Request Body
|
||||
|
||||
<Properties>
|
||||
<Property name='name' type='string' key='name'>
|
||||
New name
|
||||
</Property>
|
||||
<Property name='user' type='string' key='user'>
|
||||
The user identifier, defined by the developer, must ensure uniqueness within the app.
|
||||
</Property>
|
||||
</Properties>
|
||||
</Col>
|
||||
<Col sticky>
|
||||
|
||||
<CodeGroup title="Request" tag="POST" label="/conversations/{converation_id}/name" targetCode={`curl --location --request POST '${props.appDetail.api_base_url}/conversations/name' \\\n--header 'Authorization: Bearer ENTER-YOUR-SECRET-KEY' \\\n--header 'Content-Type: application/json' \\\n--data-raw '{ \n "name": "", \n "user": "abc-123"\n}'`}>
|
||||
|
||||
```bash {{ title: 'cURL' }}
|
||||
curl --location --request POST 'https://cloud.langgenius.dev/api/conversations/name' \
|
||||
--header 'Content-Type: application/json' \
|
||||
--header 'Authorization: Bearer ENTER-YOUR-SECRET-KEY' \
|
||||
--data-raw '{
|
||||
"name": "",
|
||||
"user": "abc-123"
|
||||
}'
|
||||
```
|
||||
|
||||
</CodeGroup>
|
||||
|
||||
<CodeGroup title="Response">
|
||||
```json {{ title: 'Response' }}
|
||||
{
|
||||
"result": "success"
|
||||
}
|
||||
```
|
||||
</CodeGroup>
|
||||
</Col>
|
||||
</Row>
|
||||
|
||||
|
||||
---
|
||||
|
||||
<Heading
|
||||
url='/parameters'
|
||||
method='GET'
|
||||
title='Obtain application parameter information'
|
||||
name='#rename'
|
||||
/>
|
||||
<Row>
|
||||
<Col>
|
||||
Retrieve configured Input parameters, including variable names, field names, types, and default values. Typically used for displaying these fields in a form or filling in default values after the client loads.
|
||||
|
||||
### Query
|
||||
|
||||
<Properties>
|
||||
<Property name='user' type='string' key='user'>
|
||||
The user identifier, defined by the developer, must ensure uniqueness within the app.
|
||||
</Property>
|
||||
</Properties>
|
||||
</Col>
|
||||
<Col sticky>
|
||||
|
||||
<CodeGroup title="Request" tag="GET" label="/parameters" targetCode={` curl --location --request GET '${props.appDetail.api_base_url}/parameters?user=abc-123'`}>
|
||||
|
||||
```bash {{ title: 'cURL' }}
|
||||
curl --location --request GET 'https://cloud.langgenius.dev/api/parameters?user=abc-123' \
|
||||
--header 'Authorization: Bearer ENTER-YOUR-SECRET-KEY'
|
||||
```
|
||||
|
||||
</CodeGroup>
|
||||
|
||||
<CodeGroup title="Response">
|
||||
```json {{ title: 'Response' }}
|
||||
{
|
||||
"introduction": "nice to meet you",
|
||||
"variables": [
|
||||
{
|
||||
"key": "book",
|
||||
"name": "book",
|
||||
"description": null,
|
||||
"type": "string",
|
||||
"default": null,
|
||||
"options": null
|
||||
},
|
||||
{
|
||||
// ...
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
</CodeGroup>
|
||||
</Col>
|
||||
</Row>
|
||||
391
web/app/components/develop/template/template_chat.zh.mdx
Normal file
391
web/app/components/develop/template/template_chat.zh.mdx
Normal file
@@ -0,0 +1,391 @@
|
||||
import { CodeGroup } from '../code.tsx'
|
||||
import { Row, Col, Properties, Property, Heading, SubProperty } from '../md.tsx'
|
||||
|
||||
# 对话型应用 API
|
||||
|
||||
可用于大部分场景的对话型应用,采用一问一答模式与用户持续对话。要开始一个对话请调用 chat-messages 接口,通过继续传入返回的 conversation_id 可持续保持该会话。
|
||||
|
||||
<Heading
|
||||
url='/chat-messages'
|
||||
method='POST'
|
||||
title='发送对话消息'
|
||||
name='#Create-Chat-Message'
|
||||
/>
|
||||
<Row>
|
||||
<Col>
|
||||
创建会话消息,或基于此前的对话继续发送消息。
|
||||
|
||||
### Request Body
|
||||
|
||||
<Properties>
|
||||
<Property name='inputs' type='object' key='inputs'>
|
||||
(选填)以键值对方式提供用户输入字段,与提示词编排中的变量对应。Key 为变量名称,Value 是参数值。如果字段类型为 Select,传入的 Value 需为预设选项之一。
|
||||
<ul>
|
||||
{!!props.variables.length && props.variables.map(
|
||||
val => (
|
||||
<SubProperty name={val.key} type={val.type} key={val.key}>
|
||||
{val.name ? `${val.name}` : ''}
|
||||
</SubProperty>
|
||||
)
|
||||
)}
|
||||
</ul>
|
||||
</Property>
|
||||
<Property name='query' type='string' key='query'>
|
||||
用户输入/提问内容
|
||||
</Property>
|
||||
<Property name='response_mode' type='string' key='response_mode'>
|
||||
- blocking 阻塞型,等待执行完毕后返回结果。(请求若流程较长可能会被中断)
|
||||
- streaming 流式返回。基于 SSE(**[Server-Sent Events](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events)**)实现流式返回。
|
||||
</Property>
|
||||
<Property name='conversation_id' type='string' key='conversation_id'>
|
||||
(选填)会话标识符,首次对话可为空,如果要继续对话请传入上下文返回的 conversation_id
|
||||
</Property>
|
||||
<Property name='user' type='string' key='user'>
|
||||
用户标识,由开发者定义规则,需保证用户标识在应用内唯一。
|
||||
</Property>
|
||||
</Properties>
|
||||
</Col>
|
||||
<Col sticky>
|
||||
|
||||
<CodeGroup title="Request" tag="POST" label="/chat-messages" targetCode={`curl --location --request POST '${props.appDetail.api_base_url}/chat-messages' \\\n--header 'Authorization: Bearer ENTER-YOUR-SECRET-KEY' \\\n--header 'Content-Type: application/json' \\\n--data-raw '{\n "inputs": ${JSON.stringify(props.inputs)},\n "query": "eh",\n "response_mode": "streaming",\n "conversation_id": "1c7e55fb-1ba2-4e10-81b5-30addcea2276",\n "user": "abc-123"\n}'\n`}>
|
||||
|
||||
```bash {{ title: 'cURL' }}
|
||||
curl --location --request POST 'https://cloud.langgenius.dev/api/chat-messages' \
|
||||
--header 'Authorization: Bearer ENTER-YOUR-SECRET-KEY' \
|
||||
--header 'Content-Type: application/json' \
|
||||
--data-raw '{
|
||||
"inputs": {},
|
||||
"query": "eh",
|
||||
"response_mode": "streaming",
|
||||
"conversation_id": "1c7e55fb-1ba2-4e10-81b5-30addcea2276",
|
||||
"user": "abc-123"
|
||||
}'
|
||||
```
|
||||
|
||||
</CodeGroup>
|
||||
### blocking
|
||||
<CodeGroup title="Response">
|
||||
```json {{ title: 'Response' }}
|
||||
{
|
||||
"answer": "Hi, is there anything I can help you?",
|
||||
"conversation_id": "45701982-8118-4bc5-8e9b-64562b4555f2",
|
||||
"created_at": 1679587005,
|
||||
"id": "059f87d9-15c0-473a-870c-fde95cdcc1e4"
|
||||
}
|
||||
```
|
||||
</CodeGroup>
|
||||
### streaming
|
||||
<CodeGroup title="Response">
|
||||
```streaming {{ title: 'Response' }}
|
||||
data: {"id": "5ad4cb98-f0c7-4085-b384-88c403be6290", "answer": " I", "created_at": 1679586595}
|
||||
data: {"id": "5ad4cb98-f0c7-4085-b384-88c403be6290", "answer": " I", "created_at": 1679586595}
|
||||
```
|
||||
</CodeGroup>
|
||||
</Col>
|
||||
</Row>
|
||||
|
||||
---
|
||||
|
||||
<Heading
|
||||
url='/messages/{message_id}/feedbacks'
|
||||
method='POST'
|
||||
title='消息反馈(点赞)'
|
||||
name='#feedbacks'
|
||||
/>
|
||||
<Row>
|
||||
<Col>
|
||||
代表最终用户对返回消息进行评价,可以点赞与点踩,该数据将在“日志与标注”页中可见,并用于后续的模型微调。
|
||||
|
||||
### Path Params
|
||||
<Properties>
|
||||
<Property name='message_id' type='string' key='message_id'>
|
||||
消息 ID
|
||||
</Property>
|
||||
</Properties>
|
||||
|
||||
### Request Body
|
||||
|
||||
<Properties>
|
||||
<Property name='rating' type='string' key='rating'>
|
||||
like 或 dislike, 空值为撤销
|
||||
</Property>
|
||||
<Property name='user' type='string' key='user'>
|
||||
用户标识,由开发者定义规则,需保证用户标识在应用内唯一。
|
||||
</Property>
|
||||
</Properties>
|
||||
</Col>
|
||||
<Col sticky>
|
||||
|
||||
<CodeGroup title="Request" tag="POST" label="/messages/{message_id}/feedbacks" targetCode={`curl --location --request POST '${props.appDetail.api_base_url}/messages/{message_id}/feedbacks \\\n--header 'Authorization: Bearer ENTER-YOUR-SECRET-KEY' \\\n--header 'Content-Type: application/json' \\\n--data-raw '{\n "rating": "like",\n "user": "abc-123"\n}'`}>
|
||||
|
||||
```bash {{ title: 'cURL' }}
|
||||
curl --location --request POST 'https://cloud.langgenius.dev/api/messages/{message_id}/feedbacks' \
|
||||
--header 'Authorization: Bearer ENTER-YOUR-SECRET-KEY' \
|
||||
--header 'Content-Type: application/json' \
|
||||
--data-raw '{
|
||||
"rating": "like",
|
||||
"user": "abc-123"
|
||||
}'
|
||||
```
|
||||
|
||||
</CodeGroup>
|
||||
|
||||
<CodeGroup title="Response">
|
||||
```json {{ title: 'Response' }}
|
||||
{
|
||||
"has_more": false,
|
||||
"data": [
|
||||
{
|
||||
"id": "WAz8eIbvDR60rouK",
|
||||
"username": "FrankMcCallister",
|
||||
"phone_number": "1-800-759-3000",
|
||||
"avatar_url": "https://assets.protocol.chat/avatars/frank.jpg",
|
||||
"display_name": null,
|
||||
"conversation_id": "xgQQXg3hrtjh7AvZ",
|
||||
"last_active_at": 705103200,
|
||||
"created_at": 692233200
|
||||
},
|
||||
{
|
||||
"id": "hSIhXBhNe8X1d8Et"
|
||||
// ...
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
</CodeGroup>
|
||||
</Col>
|
||||
</Row>
|
||||
|
||||
---
|
||||
|
||||
<Heading
|
||||
url='/messages'
|
||||
method='GET'
|
||||
title='获取会话历史消息'
|
||||
name='#messages'
|
||||
/>
|
||||
<Row>
|
||||
<Col>
|
||||
滚动加载形式返回历史聊天记录,第一页返回最新 `limit` 条,即:倒序返回。
|
||||
|
||||
### Query
|
||||
|
||||
<Properties>
|
||||
<Property name='conversation_id' type='string' key='conversation_id'>
|
||||
会话 ID
|
||||
</Property>
|
||||
<Property name='first_id' type='string' key='first_id'>
|
||||
当前页第一条聊天记录的 ID,默认 none
|
||||
</Property>
|
||||
<Property name='limit' type='int' key='limit'>
|
||||
一次请求返回多少条聊天记录
|
||||
</Property>
|
||||
<Property name='user' type='string' key='user'>
|
||||
用户标识,由开发者定义规则,需保证用户标识在应用内唯一。
|
||||
</Property>
|
||||
</Properties>
|
||||
</Col>
|
||||
<Col sticky>
|
||||
|
||||
<CodeGroup title="Request" tag="GET" label="/messages" targetCode={`curl --location --request GET '${props.appDetail.api_base_url}/messages?user=abc-123&conversation_id=' \\\n--header 'Authorization: Bearer ENTER-YOUR-SECRET-KEY'`}>
|
||||
|
||||
```bash {{ title: 'cURL' }}
|
||||
curl --location --request GET 'https://cloud.langgenius.dev/api/messages?user=abc-123&conversation_id='
|
||||
--header 'Authorization: Bearer ENTER-YOUR-SECRET-KEY'
|
||||
```
|
||||
|
||||
</CodeGroup>
|
||||
|
||||
<CodeGroup title="Response">
|
||||
```json {{ title: 'Response' }}
|
||||
{
|
||||
"has_more": false,
|
||||
"data": [
|
||||
{
|
||||
"id": "WAz8eIbvDR60rouK",
|
||||
"username": "FrankMcCallister",
|
||||
"phone_number": "1-800-759-3000",
|
||||
"avatar_url": "https://assets.protocol.chat/avatars/frank.jpg",
|
||||
"display_name": null,
|
||||
"conversation_id": "xgQQXg3hrtjh7AvZ",
|
||||
"last_active_at": 705103200,
|
||||
"created_at": 692233200
|
||||
},
|
||||
{
|
||||
"id": "hSIhXBhNe8X1d8Et"
|
||||
// ...
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
</CodeGroup>
|
||||
</Col>
|
||||
</Row>
|
||||
|
||||
---
|
||||
|
||||
<Heading
|
||||
url='/conversations'
|
||||
method='GET'
|
||||
title='获取会话列表'
|
||||
name='#conversations'
|
||||
/>
|
||||
<Row>
|
||||
<Col>
|
||||
获取当前用户的会话列表,默认返回最近的 20 条。
|
||||
|
||||
### Query
|
||||
|
||||
<Properties>
|
||||
<Property name='last_id' type='string' key='last_id'>
|
||||
当前页最后面一条记录的 ID,默认 none
|
||||
</Property>
|
||||
<Property name='limit' type='int' key='limit'>
|
||||
一次请求返回多少条记录
|
||||
</Property>
|
||||
<Property name='user' type='string' key='user'>
|
||||
用户标识,由开发者定义规则,需保证用户标识在应用内唯一。
|
||||
</Property>
|
||||
</Properties>
|
||||
</Col>
|
||||
<Col sticky>
|
||||
|
||||
<CodeGroup title="Request" tag="GET" label="/conversations" targetCode={`curl --location --request GET '${props.appDetail.api_base_url}/conversations?user=abc-123&last_id=&limit=20'\\\n--header 'Authorization: Bearer ENTER-YOUR-SECRET-KEY'`}>
|
||||
|
||||
```bash {{ title: 'cURL' }}
|
||||
curl --location --request GET 'https://cloud.langgenius.dev/api/conversations?user=abc-123&last_id=&limit=20' \
|
||||
--header 'Authorization: Bearer ENTER-YOUR-SECRET-KEY'
|
||||
```
|
||||
|
||||
</CodeGroup>
|
||||
|
||||
<CodeGroup title="Response">
|
||||
```json {{ title: 'Response' }}
|
||||
{
|
||||
"limit": 20,
|
||||
"has_more": false,
|
||||
"data": [
|
||||
{
|
||||
"id": "10799fb8-64f7-4296-bbf7-b42bfbe0ae54",
|
||||
"name": "New chat",
|
||||
"inputs": {
|
||||
"book": "book",
|
||||
"myName": "Lucy"
|
||||
},
|
||||
"status": "normal",
|
||||
"created_at": 1679667915
|
||||
},
|
||||
{
|
||||
"id": "hSIhXBhNe8X1d8Et"
|
||||
// ...
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
</CodeGroup>
|
||||
</Col>
|
||||
</Row>
|
||||
|
||||
---
|
||||
|
||||
<Heading
|
||||
url='/conversations/{converation_id}/name'
|
||||
method='POST'
|
||||
title='会话重命名'
|
||||
name='#rename'
|
||||
/>
|
||||
<Row>
|
||||
<Col>
|
||||
对会话进行重命名,会话名称用于显示在支持多会话的客户端上。
|
||||
|
||||
### Request Body
|
||||
|
||||
<Properties>
|
||||
<Property name='name' type='string' key='name'>
|
||||
新的名称
|
||||
</Property>
|
||||
<Property name='user' type='string' key='user'>
|
||||
用户标识,由开发者定义规则,需保证用户标识在应用内唯一。
|
||||
</Property>
|
||||
</Properties>
|
||||
</Col>
|
||||
<Col sticky>
|
||||
|
||||
<CodeGroup title="Request" tag="POST" label="/conversations/{converation_id}/name" targetCode={`curl --location --request POST '${props.appDetail.api_base_url}/conversations/name' \\\n--header 'Authorization: Bearer ENTER-YOUR-SECRET-KEY' \\\n--header 'Content-Type: application/json' \\\n--data-raw '{ \n "name": "", \n "user": "abc-123"\n}'`}>
|
||||
|
||||
```bash {{ title: 'cURL' }}
|
||||
curl --location --request POST 'https://cloud.langgenius.dev/api/conversations/name' \
|
||||
--header 'Authorization: Bearer ENTER-YOUR-SECRET-KEY' \
|
||||
--header 'Content-Type: application/json' \
|
||||
--data-raw '{
|
||||
"name": "",
|
||||
"user": "abc-123"
|
||||
}'
|
||||
```
|
||||
|
||||
</CodeGroup>
|
||||
|
||||
<CodeGroup title="Response">
|
||||
```json {{ title: 'Response' }}
|
||||
{
|
||||
"result": "success"
|
||||
}
|
||||
```
|
||||
</CodeGroup>
|
||||
</Col>
|
||||
</Row>
|
||||
|
||||
|
||||
---
|
||||
|
||||
<Heading
|
||||
url='/parameters'
|
||||
method='GET'
|
||||
title='获取应用配置信息'
|
||||
name='#rename'
|
||||
/>
|
||||
<Row>
|
||||
<Col>
|
||||
获取已配置的 Input 参数,包括变量名、字段名称、类型与默认值。通常用于客户端加载后显示这些字段的表单或填入默认值。
|
||||
|
||||
### Query
|
||||
|
||||
<Properties>
|
||||
<Property name='user' type='string' key='user'>
|
||||
用户标识,由开发者定义规则,需保证用户标识在应用内唯一。
|
||||
</Property>
|
||||
</Properties>
|
||||
</Col>
|
||||
<Col sticky>
|
||||
|
||||
<CodeGroup title="Request" tag="GET" label="/parameters" targetCode={` curl --location --request GET '${props.appDetail.api_base_url}/parameters'\\\n--header 'Authorization: Bearer ENTER-YOUR-SECRET-KEY'`}>
|
||||
|
||||
```bash {{ title: 'cURL' }}
|
||||
curl --location --request GET 'https://cloud.langgenius.dev/api/parameters?user=abc-123' \
|
||||
--header 'Authorization: Bearer ENTER-YOUR-SECRET-KEY'
|
||||
```
|
||||
|
||||
</CodeGroup>
|
||||
|
||||
<CodeGroup title="Response">
|
||||
```json {{ title: 'Response' }}
|
||||
{
|
||||
"introduction": "nice to meet you",
|
||||
"variables": [
|
||||
{
|
||||
"key": "book",
|
||||
"name": "book",
|
||||
"description": null,
|
||||
"type": "string",
|
||||
"default": null,
|
||||
"options": null
|
||||
},
|
||||
{
|
||||
// ...
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
</CodeGroup>
|
||||
</Col>
|
||||
</Row>
|
||||
Reference in New Issue
Block a user