Merge branch 'main' into add-endpoint-of-get-feedback

pull/18697/head
Ganondorf 1 year ago committed by GitHub
commit 657ed52d9c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -79,7 +79,7 @@ class AnnotationListApi(Resource):
class AnnotationUpdateDeleteApi(Resource): class AnnotationUpdateDeleteApi(Resource):
@validate_app_token(fetch_user_arg=FetchUserArg(fetch_from=WhereisUserArg.JSON)) @validate_app_token(fetch_user_arg=FetchUserArg(fetch_from=WhereisUserArg.JSON))
@marshal_with(annotation_fields) @marshal_with(annotation_fields)
def post(self, app_model: App, end_user: EndUser, annotation_id): def put(self, app_model: App, end_user: EndUser, annotation_id):
if not current_user.is_editor: if not current_user.is_editor:
raise Forbidden() raise Forbidden()

@ -1,6 +1,7 @@
from collections.abc import Mapping
from datetime import datetime from datetime import datetime
from enum import StrEnum from enum import StrEnum
from typing import Generic, Optional, TypeVar from typing import Any, Generic, Optional, TypeVar
from pydantic import BaseModel, ConfigDict, Field from pydantic import BaseModel, ConfigDict, Field
@ -158,3 +159,11 @@ class PluginInstallTaskStartResponse(BaseModel):
class PluginUploadResponse(BaseModel): class PluginUploadResponse(BaseModel):
unique_identifier: str = Field(description="The unique identifier of the plugin.") unique_identifier: str = Field(description="The unique identifier of the plugin.")
manifest: PluginDeclaration manifest: PluginDeclaration
class PluginOAuthAuthorizationUrlResponse(BaseModel):
authorization_url: str = Field(description="The URL of the authorization.")
class PluginOAuthCredentialsResponse(BaseModel):
credentials: Mapping[str, Any] = Field(description="The credentials of the OAuth.")

@ -1,6 +1,98 @@
from collections.abc import Mapping
from typing import Any
from werkzeug import Request
from core.plugin.entities.plugin_daemon import PluginOAuthAuthorizationUrlResponse, PluginOAuthCredentialsResponse
from core.plugin.impl.base import BasePluginClient from core.plugin.impl.base import BasePluginClient
class OAuthHandler(BasePluginClient): class OAuthHandler(BasePluginClient):
def get_authorization_url(self, tenant_id: str, user_id: str, provider_name: str) -> str: def get_authorization_url(
return "1234567890" self,
tenant_id: str,
user_id: str,
plugin_id: str,
provider: str,
system_credentials: Mapping[str, Any],
) -> PluginOAuthAuthorizationUrlResponse:
return self._request_with_plugin_daemon_response(
"POST",
f"plugin/{tenant_id}/dispatch/oauth/get_authorization_url",
PluginOAuthAuthorizationUrlResponse,
data={
"user_id": user_id,
"data": {
"provider": provider,
"system_credentials": system_credentials,
},
},
headers={
"X-Plugin-ID": plugin_id,
"Content-Type": "application/json",
},
)
def get_credentials(
self,
tenant_id: str,
user_id: str,
plugin_id: str,
provider: str,
system_credentials: Mapping[str, Any],
request: Request,
) -> PluginOAuthCredentialsResponse:
"""
Get credentials from the given request.
"""
# encode request to raw http request
raw_request_bytes = self._convert_request_to_raw_data(request)
return self._request_with_plugin_daemon_response(
"POST",
f"plugin/{tenant_id}/dispatch/oauth/get_credentials",
PluginOAuthCredentialsResponse,
data={
"user_id": user_id,
"data": {
"provider": provider,
"system_credentials": system_credentials,
"raw_request_bytes": raw_request_bytes,
},
},
headers={
"X-Plugin-ID": plugin_id,
"Content-Type": "application/json",
},
)
def _convert_request_to_raw_data(self, request: Request) -> bytes:
"""
Convert a Request object to raw HTTP data.
Args:
request: The Request object to convert.
Returns:
The raw HTTP data as bytes.
"""
# Start with the request line
method = request.method
path = request.path
protocol = request.headers.get("HTTP_VERSION", "HTTP/1.1")
raw_data = f"{method} {path} {protocol}\r\n".encode()
# Add headers
for header_name, header_value in request.headers.items():
raw_data += f"{header_name}: {header_value}\r\n".encode()
# Add empty line to separate headers from body
raw_data += b"\r\n"
# Add body if exists
body = request.get_data(as_text=False)
if body:
raw_data += body
return raw_data

@ -36,6 +36,31 @@ from configs import dify_config
from dify_app import DifyApp from dify_app import DifyApp
class ExceptionLoggingHandler(logging.Handler):
"""Custom logging handler that creates spans for logging.exception() calls"""
def emit(self, record):
try:
if record.exc_info:
tracer = get_tracer_provider().get_tracer("dify.exception.logging")
with tracer.start_as_current_span(
"log.exception",
attributes={
"log.level": record.levelname,
"log.message": record.getMessage(),
"log.logger": record.name,
"log.file.path": record.pathname,
"log.file.line": record.lineno,
},
) as span:
span.set_status(StatusCode.ERROR)
span.record_exception(record.exc_info[1])
span.set_attribute("exception.type", record.exc_info[0].__name__)
span.set_attribute("exception.message", str(record.exc_info[1]))
except Exception:
pass
@user_logged_in.connect @user_logged_in.connect
@user_loaded_from_request.connect @user_loaded_from_request.connect
def on_user_loaded(_sender, user): def on_user_loaded(_sender, user):
@ -103,6 +128,7 @@ def init_app(app: DifyApp):
if not is_celery_worker(): if not is_celery_worker():
init_flask_instrumentor(app) init_flask_instrumentor(app)
CeleryInstrumentor(tracer_provider=get_tracer_provider(), meter_provider=get_meter_provider()).instrument() CeleryInstrumentor(tracer_provider=get_tracer_provider(), meter_provider=get_meter_provider()).instrument()
instrument_exception_logging()
init_sqlalchemy_instrumentor(app) init_sqlalchemy_instrumentor(app)
atexit.register(shutdown_tracer) atexit.register(shutdown_tracer)
@ -111,6 +137,11 @@ def is_celery_worker():
return "celery" in sys.argv[0].lower() return "celery" in sys.argv[0].lower()
def instrument_exception_logging():
exception_handler = ExceptionLoggingHandler()
logging.getLogger().addHandler(exception_handler)
def init_flask_instrumentor(app: DifyApp): def init_flask_instrumentor(app: DifyApp):
meter = get_meter("http_metrics", version=dify_config.CURRENT_VERSION) meter = get_meter("http_metrics", version=dify_config.CURRENT_VERSION)
_http_response_counter = meter.create_counter( _http_response_counter = meter.create_counter(

@ -0,0 +1,20 @@
from werkzeug import Request
from werkzeug.datastructures import Headers
from werkzeug.test import EnvironBuilder
from core.plugin.impl.oauth import OAuthHandler
def test_oauth_convert_request_to_raw_data():
oauth_handler = OAuthHandler()
builder = EnvironBuilder(
method="GET",
path="/test",
headers=Headers({"Content-Type": "application/json"}),
)
request = Request(builder.get_environ())
raw_request_bytes = oauth_handler._convert_request_to_raw_data(request)
assert b"GET /test HTTP/1.1" in raw_request_bytes
assert b"Content-Type: application/json" in raw_request_bytes
assert b"\r\n\r\n" in raw_request_bytes

@ -4,7 +4,6 @@ import { useMount } from 'ahooks'
import { useTranslation } from 'react-i18next' import { useTranslation } from 'react-i18next'
import { isEqual } from 'lodash-es' import { isEqual } from 'lodash-es'
import { RiCloseLine } from '@remixicon/react' import { RiCloseLine } from '@remixicon/react'
import { BookOpenIcon } from '@heroicons/react/24/outline'
import { ApiConnectionMod } from '@/app/components/base/icons/src/vender/solid/development' import { ApiConnectionMod } from '@/app/components/base/icons/src/vender/solid/development'
import cn from '@/utils/classnames' import cn from '@/utils/classnames'
import IndexMethodRadio from '@/app/components/datasets/settings/index-method-radio' import IndexMethodRadio from '@/app/components/datasets/settings/index-method-radio'
@ -223,10 +222,6 @@ const SettingsModal: FC<SettingsModalProps> = ({
className='resize-none' className='resize-none'
placeholder={t('datasetSettings.form.descPlaceholder') || ''} placeholder={t('datasetSettings.form.descPlaceholder') || ''}
/> />
<a className='mt-2 flex h-[18px] items-center px-3 text-xs text-text-tertiary' href="https://docs.dify.ai/features/datasets#how-to-write-a-good-dataset-description" target='_blank' rel='noopener noreferrer'>
<BookOpenIcon className='mr-1 h-[18px] w-3' />
{t('datasetSettings.form.descWrite')}
</a>
</div> </div>
</div> </div>
<div className={rowClass}> <div className={rowClass}>

@ -356,32 +356,31 @@ import { Row, Col, Properties, Property, Heading, SubProperty } from '../md.tsx'
</Row> </Row>
--- ---
<Heading <Heading
url='/app/feedbacks' url='/app/feedbacks'
method='GET' method='GET'
title='获取APP的消息点赞和反馈' title='Get feedbacks of application'
name='#app-feedbacks' name='#app-feedbacks'
/> />
<Row> <Row>
<Col> <Col>
获取应用的终端用户反馈、点赞。 Get application's feedbacks.
### Query ### Query
<Properties> <Properties>
<Property name='page' type='string' key='page'> <Property name='page' type='string' key='page'>
选填)分页,默认值1 optionalpaginationdefault1
</Property> </Property>
</Properties> </Properties>
<Properties> <Properties>
<Property name='limit' type='string' key='limit'> <Property name='limit' type='string' key='limit'>
选填)每页数量,默认值20 optional records per page default20
</Property> </Property>
</Properties> </Properties>
### Response ### Response
- `data` (List) 返回该APP的点赞、反馈列表。 - `data` (List) return apps feedback list.
</Col> </Col>
<Col sticky> <Col sticky>
@ -397,23 +396,23 @@ import { Row, Col, Properties, Property, Heading, SubProperty } from '../md.tsx'
<CodeGroup title="Response"> <CodeGroup title="Response">
```json {{ title: 'Response' }} ```json {{ title: 'Response' }}
{ {
"data": [ "data": [
{ {
"id": "8c0fbed8-e2f9-49ff-9f0e-15a35bdd0e25", "id": "8c0fbed8-e2f9-49ff-9f0e-15a35bdd0e25",
"app_id": "f252d396-fe48-450e-94ec-e184218e7346", "app_id": "f252d396-fe48-450e-94ec-e184218e7346",
"conversation_id": "2397604b-9deb-430e-b285-4726e51fd62d", "conversation_id": "2397604b-9deb-430e-b285-4726e51fd62d",
"message_id": "709c0b0f-0a96-4a4e-91a4-ec0889937b11", "message_id": "709c0b0f-0a96-4a4e-91a4-ec0889937b11",
"rating": "like", "rating": "like",
"content": "message feedback information-3", "content": "message feedback information-3",
"from_source": "user", "from_source": "user",
"from_end_user_id": "74286412-9a1a-42c1-929c-01edb1d381d5", "from_end_user_id": "74286412-9a1a-42c1-929c-01edb1d381d5",
"from_account_id": null, "from_account_id": null,
"created_at": "2025-04-24T09:24:38", "created_at": "2025-04-24T09:24:38",
"updated_at": "2025-04-24T09:24:38" "updated_at": "2025-04-24T09:24:38"
} }
] ]
} }
``` ```
</CodeGroup> </CodeGroup>
</Col> </Col>
@ -706,13 +705,11 @@ import { Row, Col, Properties, Property, Heading, SubProperty } from '../md.tsx'
<CodeGroup title="Response"> <CodeGroup title="Response">
```json {{ title: 'Response' }} ```json {{ title: 'Response' }}
{ {
{ "id": "69d48372-ad81-4c75-9c46-2ce197b4d402",
"id": "69d48372-ad81-4c75-9c46-2ce197b4d402", "question": "What is your name?",
"question": "What is your name?", "answer": "I am Dify.",
"answer": "I am Dify.", "hit_count": 0,
"hit_count": 0, "created_at": 1735625869
"created_at": 1735625869
}
} }
``` ```
</CodeGroup> </CodeGroup>
@ -746,10 +743,10 @@ import { Row, Col, Properties, Property, Heading, SubProperty } from '../md.tsx'
title="Request" title="Request"
tag="PUT" tag="PUT"
label="/apps/annotations/{annotation_id}" label="/apps/annotations/{annotation_id}"
targetCode={`curl --location --request POST '${props.apiBaseUrl}/apps/annotations/{annotation_id}' \\\n--header 'Authorization: Bearer {api_key}' \\\n--header 'Content-Type: application/json' \\\n--data-raw '{"question": "What is your name?","answer": "I am Dify."}'`} targetCode={`curl --location --request PUT '${props.apiBaseUrl}/apps/annotations/{annotation_id}' \\\n--header 'Authorization: Bearer {api_key}' \\\n--header 'Content-Type: application/json' \\\n--data-raw '{"question": "What is your name?","answer": "I am Dify."}'`}
> >
```bash {{ title: 'cURL' }} ```bash {{ title: 'cURL' }}
curl --location --request POST '${props.apiBaseUrl}/apps/annotations/{annotation_id}' \ curl --location --request PUT '${props.apiBaseUrl}/apps/annotations/{annotation_id}' \
--header 'Authorization: Bearer {api_key}' \ --header 'Authorization: Bearer {api_key}' \
--header 'Content-Type: application/json' \ --header 'Content-Type: application/json' \
--data-raw '{ --data-raw '{
@ -762,13 +759,11 @@ import { Row, Col, Properties, Property, Heading, SubProperty } from '../md.tsx'
<CodeGroup title="Response"> <CodeGroup title="Response">
```json {{ title: 'Response' }} ```json {{ title: 'Response' }}
{ {
{ "id": "69d48372-ad81-4c75-9c46-2ce197b4d402",
"id": "69d48372-ad81-4c75-9c46-2ce197b4d402", "question": "What is your name?",
"question": "What is your name?", "answer": "I am Dify.",
"answer": "I am Dify.", "hit_count": 0,
"hit_count": 0, "created_at": 1735625869
"created_at": 1735625869
}
} }
``` ```
</CodeGroup> </CodeGroup>
@ -826,10 +821,10 @@ import { Row, Col, Properties, Property, Heading, SubProperty } from '../md.tsx'
<Property name='action' type='string' key='action'> <Property name='action' type='string' key='action'>
动作,只能是 'enable' 或 'disable' 动作,只能是 'enable' 或 'disable'
</Property> </Property>
<Property name='embedding_model_provider' type='string' key='embedding_model_provider'> <Property name='embedding_provider_name' type='string' key='embedding_provider_name'>
指定的嵌入模型提供商, 必须先在系统内设定好接入的模型对应的是provider字段 指定的嵌入模型提供商, 必须先在系统内设定好接入的模型对应的是provider字段
</Property> </Property>
<Property name='embedding_model' type='string' key='embedding_model'> <Property name='embedding_model_name' type='string' key='embedding_model_name'>
指定的嵌入模型对应的是model字段 指定的嵌入模型对应的是model字段
</Property> </Property>
<Property name='score_threshold' type='number' key='score_threshold'> <Property name='score_threshold' type='number' key='score_threshold'>

@ -1400,13 +1400,11 @@ Chat applications support session persistence, allowing previous chat history to
<CodeGroup title="Response"> <CodeGroup title="Response">
```json {{ title: 'Response' }} ```json {{ title: 'Response' }}
{ {
{ "id": "69d48372-ad81-4c75-9c46-2ce197b4d402",
"id": "69d48372-ad81-4c75-9c46-2ce197b4d402", "question": "What is your name?",
"question": "What is your name?", "answer": "I am Dify.",
"answer": "I am Dify.", "hit_count": 0,
"hit_count": 0, "created_at": 1735625869
"created_at": 1735625869
}
} }
``` ```
</CodeGroup> </CodeGroup>
@ -1440,10 +1438,10 @@ Chat applications support session persistence, allowing previous chat history to
title="Request" title="Request"
tag="PUT" tag="PUT"
label="/apps/annotations/{annotation_id}" label="/apps/annotations/{annotation_id}"
targetCode={`curl --location --request POST '${props.apiBaseUrl}/apps/annotations/{annotation_id}' \\\n--header 'Authorization: Bearer {api_key}' \\\n--header 'Content-Type: application/json' \\\n--data-raw '{"question": "What is your name?","answer": "I am Dify."}'`} targetCode={`curl --location --request PUT '${props.apiBaseUrl}/apps/annotations/{annotation_id}' \\\n--header 'Authorization: Bearer {api_key}' \\\n--header 'Content-Type: application/json' \\\n--data-raw '{"question": "What is your name?","answer": "I am Dify."}'`}
> >
```bash {{ title: 'cURL' }} ```bash {{ title: 'cURL' }}
curl --location --request POST '${props.apiBaseUrl}/apps/annotations/{annotation_id}' \ curl --location --request PUT '${props.apiBaseUrl}/apps/annotations/{annotation_id}' \
--header 'Authorization: Bearer {api_key}' \ --header 'Authorization: Bearer {api_key}' \
--header 'Content-Type: application/json' \ --header 'Content-Type: application/json' \
--data-raw '{ --data-raw '{
@ -1456,13 +1454,11 @@ Chat applications support session persistence, allowing previous chat history to
<CodeGroup title="Response"> <CodeGroup title="Response">
```json {{ title: 'Response' }} ```json {{ title: 'Response' }}
{ {
{ "id": "69d48372-ad81-4c75-9c46-2ce197b4d402",
"id": "69d48372-ad81-4c75-9c46-2ce197b4d402", "question": "What is your name?",
"question": "What is your name?", "answer": "I am Dify.",
"answer": "I am Dify.", "hit_count": 0,
"hit_count": 0, "created_at": 1735625869
"created_at": 1735625869
}
} }
``` ```
</CodeGroup> </CodeGroup>
@ -1520,10 +1516,10 @@ Chat applications support session persistence, allowing previous chat history to
<Property name='action' type='string' key='action'> <Property name='action' type='string' key='action'>
Action, can only be 'enable' or 'disable' Action, can only be 'enable' or 'disable'
</Property> </Property>
<Property name='embedding_model_provider' type='string' key='embedding_model_provider'> <Property name='embedding_provider_name' type='string' key='embedding_provider_name'>
Specified embedding model provider, must be set up in the system first, corresponding to the provider field(Optional) Specified embedding model provider, must be set up in the system first, corresponding to the provider field(Optional)
</Property> </Property>
<Property name='embedding_model' type='string' key='embedding_model'> <Property name='embedding_model_name' type='string' key='embedding_model_name'>
Specified embedding model, corresponding to the model field(Optional) Specified embedding model, corresponding to the model field(Optional)
</Property> </Property>
<Property name='score_threshold' type='number' key='score_threshold'> <Property name='score_threshold' type='number' key='score_threshold'>

@ -1426,13 +1426,11 @@ import { Row, Col, Properties, Property, Heading, SubProperty } from '../md.tsx'
<CodeGroup title="Response"> <CodeGroup title="Response">
```json {{ title: 'Response' }} ```json {{ title: 'Response' }}
{ {
{ "id": "69d48372-ad81-4c75-9c46-2ce197b4d402",
"id": "69d48372-ad81-4c75-9c46-2ce197b4d402", "question": "What is your name?",
"question": "What is your name?", "answer": "I am Dify.",
"answer": "I am Dify.", "hit_count": 0,
"hit_count": 0, "created_at": 1735625869
"created_at": 1735625869
}
} }
``` ```
</CodeGroup> </CodeGroup>
@ -1466,10 +1464,10 @@ import { Row, Col, Properties, Property, Heading, SubProperty } from '../md.tsx'
title="Request" title="Request"
tag="PUT" tag="PUT"
label="/apps/annotations/{annotation_id}" label="/apps/annotations/{annotation_id}"
targetCode={`curl --location --request POST '${props.appDetail.api_base_url}/apps/annotations/{annotation_id}' \\\n--header 'Authorization: Bearer {api_key}' \\\n--header 'Content-Type: application/json' \\\n--data-raw '{"question": "What is your name?","answer": "I am Dify."}'`} targetCode={`curl --location --request PUT '${props.appDetail.api_base_url}/apps/annotations/{annotation_id}' \\\n--header 'Authorization: Bearer {api_key}' \\\n--header 'Content-Type: application/json' \\\n--data-raw '{"question": "What is your name?","answer": "I am Dify."}'`}
> >
```bash {{ title: 'cURL' }} ```bash {{ title: 'cURL' }}
curl --location --request POST '${props.appDetail.api_base_url}/apps/annotations/{annotation_id}' \ curl --location --request PUT '${props.appDetail.api_base_url}/apps/annotations/{annotation_id}' \
--header 'Authorization: Bearer {api_key}' \ --header 'Authorization: Bearer {api_key}' \
--header 'Content-Type: application/json' \ --header 'Content-Type: application/json' \
--data-raw '{ --data-raw '{
@ -1482,13 +1480,11 @@ import { Row, Col, Properties, Property, Heading, SubProperty } from '../md.tsx'
<CodeGroup title="Response"> <CodeGroup title="Response">
```json {{ title: 'Response' }} ```json {{ title: 'Response' }}
{ {
{ "id": "69d48372-ad81-4c75-9c46-2ce197b4d402",
"id": "69d48372-ad81-4c75-9c46-2ce197b4d402", "question": "What is your name?",
"question": "What is your name?", "answer": "I am Dify.",
"answer": "I am Dify.", "hit_count": 0,
"hit_count": 0, "created_at": 1735625869
"created_at": 1735625869
}
} }
``` ```
</CodeGroup> </CodeGroup>
@ -1546,10 +1542,10 @@ import { Row, Col, Properties, Property, Heading, SubProperty } from '../md.tsx'
<Property name='action' type='string' key='action'> <Property name='action' type='string' key='action'>
动作,只能是 'enable' 或 'disable' 动作,只能是 'enable' 或 'disable'
</Property> </Property>
<Property name='embedding_model_provider' type='string' key='embedding_model_provider'> <Property name='embedding_provider_name' type='string' key='embedding_provider_name'>
指定的嵌入模型提供商, 必须先在系统内设定好接入的模型对应的是provider字段 指定的嵌入模型提供商, 必须先在系统内设定好接入的模型对应的是provider字段
</Property> </Property>
<Property name='embedding_model' type='string' key='embedding_model'> <Property name='embedding_model_name' type='string' key='embedding_model_name'>
指定的嵌入模型对应的是model字段 指定的嵌入模型对应的是model字段
</Property> </Property>
<Property name='score_threshold' type='number' key='score_threshold'> <Property name='score_threshold' type='number' key='score_threshold'>

@ -17,6 +17,7 @@ type Props = {
children?: React.JSX.Element | string | null children?: React.JSX.Element | string | null
operations?: React.JSX.Element operations?: React.JSX.Element
inline?: boolean inline?: boolean
required?: boolean
} }
const Field: FC<Props> = ({ const Field: FC<Props> = ({
@ -28,6 +29,7 @@ const Field: FC<Props> = ({
operations, operations,
inline, inline,
supportFold, supportFold,
required,
}) => { }) => {
const [fold, { const [fold, {
toggle: toggleFold, toggle: toggleFold,
@ -38,7 +40,9 @@ const Field: FC<Props> = ({
onClick={() => supportFold && toggleFold()} onClick={() => supportFold && toggleFold()}
className={cn('flex items-center justify-between', supportFold && 'cursor-pointer')}> className={cn('flex items-center justify-between', supportFold && 'cursor-pointer')}>
<div className='flex h-6 items-center'> <div className='flex h-6 items-center'>
<div className={cn(isSubTitle ? 'system-xs-medium-uppercase text-text-tertiary' : 'system-sm-semibold-uppercase text-text-secondary')}>{title}</div> <div className={cn(isSubTitle ? 'system-xs-medium-uppercase text-text-tertiary' : 'system-sm-semibold-uppercase text-text-secondary')}>
{title} {required && <span className='text-text-destructive'>*</span>}
</div>
{tooltip && ( {tooltip && (
<Tooltip <Tooltip
popupContent={tooltip} popupContent={tooltip}

@ -81,7 +81,11 @@ const AgentPanel: FC<NodePanelProps<AgentNodeType>> = (props) => {
const resetEditor = useStore(s => s.setControlPromptEditorRerenderKey) const resetEditor = useStore(s => s.setControlPromptEditorRerenderKey)
return <div className='my-2'> return <div className='my-2'>
<Field title={t('workflow.nodes.agent.strategy.label')} className='px-4 py-2' tooltip={t('workflow.nodes.agent.strategy.tooltip')} > <Field
required
title={t('workflow.nodes.agent.strategy.label')}
className='px-4 py-2'
tooltip={t('workflow.nodes.agent.strategy.tooltip')} >
<AgentStrategy <AgentStrategy
strategy={inputs.agent_strategy_name ? { strategy={inputs.agent_strategy_name ? {
agent_strategy_provider_name: inputs.agent_strategy_provider_name!, agent_strategy_provider_name: inputs.agent_strategy_provider_name!,

@ -117,8 +117,8 @@ const Panel: FC<NodePanelProps<CodeNodeType>> = ({
operations={ operations={
<AddButton onClick={handleAddOutputVariable} /> <AddButton onClick={handleAddOutputVariable} />
} }
required
> >
<OutputVarList <OutputVarList
readonly={readOnly} readonly={readOnly}
outputs={inputs.outputs} outputs={inputs.outputs}

@ -64,6 +64,7 @@ const Panel: FC<NodePanelProps<DocExtractorNodeType>> = ({
<div className='space-y-4 px-4 pb-4'> <div className='space-y-4 px-4 pb-4'>
<Field <Field
title={t(`${i18nPrefix}.inputVar`)} title={t(`${i18nPrefix}.inputVar`)}
required
> >
<> <>
<VarReferencePicker <VarReferencePicker

@ -69,6 +69,7 @@ const Panel: FC<NodePanelProps<HttpNodeType>> = ({
<div className='space-y-4 px-4 pb-4'> <div className='space-y-4 px-4 pb-4'>
<Field <Field
title={t(`${i18nPrefix}.api`)} title={t(`${i18nPrefix}.api`)}
required
operations={ operations={
<div className='flex'> <div className='flex'>
<div <div
@ -126,6 +127,7 @@ const Panel: FC<NodePanelProps<HttpNodeType>> = ({
</Field> </Field>
<Field <Field
title={t(`${i18nPrefix}.body`)} title={t(`${i18nPrefix}.body`)}
required
> >
<EditBody <EditBody
nodeId={id} nodeId={id}

@ -73,6 +73,7 @@ const Panel: FC<NodePanelProps<IterationNodeType>> = ({
<div className='space-y-4 px-4 pb-4'> <div className='space-y-4 px-4 pb-4'>
<Field <Field
title={t(`${i18nPrefix}.input`)} title={t(`${i18nPrefix}.input`)}
required
operations={( operations={(
<div className='system-2xs-medium-uppercase flex h-[18px] items-center rounded-[5px] border border-divider-deep px-1 capitalize text-text-tertiary'>Array</div> <div className='system-2xs-medium-uppercase flex h-[18px] items-center rounded-[5px] border border-divider-deep px-1 capitalize text-text-tertiary'>Array</div>
)} )}
@ -91,6 +92,7 @@ const Panel: FC<NodePanelProps<IterationNodeType>> = ({
<div className='mt-2 space-y-4 px-4 pb-4'> <div className='mt-2 space-y-4 px-4 pb-4'>
<Field <Field
title={t(`${i18nPrefix}.output`)} title={t(`${i18nPrefix}.output`)}
required
operations={( operations={(
<div className='system-2xs-medium-uppercase flex h-[18px] items-center rounded-[5px] border border-divider-deep px-1 capitalize text-text-tertiary'>Array</div> <div className='system-2xs-medium-uppercase flex h-[18px] items-center rounded-[5px] border border-divider-deep px-1 capitalize text-text-tertiary'>Array</div>
)} )}

@ -81,6 +81,7 @@ const Panel: FC<NodePanelProps<KnowledgeRetrievalNodeType>> = ({
{/* {JSON.stringify(inputs, null, 2)} */} {/* {JSON.stringify(inputs, null, 2)} */}
<Field <Field
title={t(`${i18nPrefix}.queryVariable`)} title={t(`${i18nPrefix}.queryVariable`)}
required
> >
<VarReferencePicker <VarReferencePicker
nodeId={id} nodeId={id}
@ -94,6 +95,7 @@ const Panel: FC<NodePanelProps<KnowledgeRetrievalNodeType>> = ({
<Field <Field
title={t(`${i18nPrefix}.knowledge`)} title={t(`${i18nPrefix}.knowledge`)}
required
operations={ operations={
<div className='flex items-center space-x-1'> <div className='flex items-center space-x-1'>
<RetrievalConfig <RetrievalConfig

@ -46,6 +46,7 @@ const Panel: FC<NodePanelProps<ListFilterNodeType>> = ({
<div className='space-y-4 px-4'> <div className='space-y-4 px-4'>
<Field <Field
title={t(`${i18nPrefix}.inputVar`)} title={t(`${i18nPrefix}.inputVar`)}
required
> >
<VarReferencePicker <VarReferencePicker
readonly={readOnly} readonly={readOnly}

@ -147,6 +147,7 @@ const Panel: FC<NodePanelProps<LLMNodeType>> = ({
<div className='space-y-4 px-4 pb-4'> <div className='space-y-4 px-4 pb-4'>
<Field <Field
title={t(`${i18nPrefix}.model`)} title={t(`${i18nPrefix}.model`)}
required
> >
<ModelParameterModal <ModelParameterModal
popupClassName='!w-[387px]' popupClassName='!w-[387px]'

@ -115,6 +115,7 @@ const Panel: FC<NodePanelProps<ParameterExtractorNodeType>> = ({
<div className='space-y-4 px-4'> <div className='space-y-4 px-4'>
<Field <Field
title={t(`${i18nCommonPrefix}.model`)} title={t(`${i18nCommonPrefix}.model`)}
required
> >
<ModelParameterModal <ModelParameterModal
popupClassName='!w-[387px]' popupClassName='!w-[387px]'
@ -133,6 +134,7 @@ const Panel: FC<NodePanelProps<ParameterExtractorNodeType>> = ({
</Field> </Field>
<Field <Field
title={t(`${i18nPrefix}.inputVar`)} title={t(`${i18nPrefix}.inputVar`)}
required
> >
<> <>
<VarReferencePicker <VarReferencePicker
@ -157,6 +159,7 @@ const Panel: FC<NodePanelProps<ParameterExtractorNodeType>> = ({
/> />
<Field <Field
title={t(`${i18nPrefix}.extractParameters`)} title={t(`${i18nPrefix}.extractParameters`)}
required
operations={ operations={
!readOnly !readOnly
? ( ? (

@ -103,6 +103,7 @@ const Panel: FC<NodePanelProps<QuestionClassifierNodeType>> = ({
<div className='space-y-4 px-4'> <div className='space-y-4 px-4'>
<Field <Field
title={t(`${i18nPrefix}.model`)} title={t(`${i18nPrefix}.model`)}
required
> >
<ModelParameterModal <ModelParameterModal
popupClassName='!w-[387px]' popupClassName='!w-[387px]'
@ -121,6 +122,7 @@ const Panel: FC<NodePanelProps<QuestionClassifierNodeType>> = ({
</Field> </Field>
<Field <Field
title={t(`${i18nPrefix}.inputVars`)} title={t(`${i18nPrefix}.inputVars`)}
required
> >
<VarReferencePicker <VarReferencePicker
readonly={readOnly} readonly={readOnly}
@ -143,6 +145,7 @@ const Panel: FC<NodePanelProps<QuestionClassifierNodeType>> = ({
/> />
<Field <Field
title={t(`${i18nPrefix}.class`)} title={t(`${i18nPrefix}.class`)}
required
> >
<ClassList <ClassList
nodeId={id} nodeId={id}

Loading…
Cancel
Save