2025-10-09 12:36:19 +08:00
|
|
|
import { setInitialChatVariableEnabledFieldValue } from '@/utils/chat';
|
2026-02-10 14:04:50 +08:00
|
|
|
import {
|
|
|
|
|
Circle,
|
|
|
|
|
CircleDashed,
|
|
|
|
|
CircleDotDashed,
|
|
|
|
|
CircleSlash2,
|
|
|
|
|
} from 'lucide-react';
|
2025-10-09 12:36:19 +08:00
|
|
|
import { ChatVariableEnabledField, variableEnabledFieldMap } from './chat';
|
|
|
|
|
|
2025-05-16 09:53:00 +08:00
|
|
|
export enum ProgrammingLanguage {
|
|
|
|
|
Python = 'python',
|
|
|
|
|
Javascript = 'javascript',
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export const CodeTemplateStrMap = {
|
2025-05-19 19:34:43 +08:00
|
|
|
[ProgrammingLanguage.Python]: `def main(arg1: str, arg2: str) -> str:
|
|
|
|
|
return f"result: {arg1 + arg2}"
|
|
|
|
|
`,
|
|
|
|
|
[ProgrammingLanguage.Javascript]: `const axios = require('axios');
|
2025-07-23 15:09:24 +08:00
|
|
|
async function main({}) {
|
2025-05-19 19:34:43 +08:00
|
|
|
try {
|
|
|
|
|
const response = await axios.get('https://github.com/infiniflow/ragflow');
|
2025-07-23 15:09:24 +08:00
|
|
|
return 'Body:' + response.data;
|
2025-05-19 19:34:43 +08:00
|
|
|
} catch (error) {
|
2025-07-23 15:09:24 +08:00
|
|
|
return 'Error:' + error.message;
|
2025-05-19 19:34:43 +08:00
|
|
|
}
|
2025-07-23 15:09:24 +08:00
|
|
|
}`,
|
2025-05-16 09:53:00 +08:00
|
|
|
};
|
2025-06-10 17:06:30 +08:00
|
|
|
|
|
|
|
|
export enum AgentGlobals {
|
|
|
|
|
SysQuery = 'sys.query',
|
|
|
|
|
SysUserId = 'sys.user_id',
|
|
|
|
|
SysConversationTurns = 'sys.conversation_turns',
|
|
|
|
|
SysFiles = 'sys.files',
|
2026-01-26 17:54:30 +08:00
|
|
|
SysHistory = 'sys.history',
|
2026-03-12 17:49:13 +08:00
|
|
|
SysDate = 'sys.date',
|
2025-06-10 17:06:30 +08:00
|
|
|
}
|
2025-09-03 13:03:23 +08:00
|
|
|
|
|
|
|
|
export const AgentGlobalsSysQueryWithBrace = `{${AgentGlobals.SysQuery}}`;
|
2025-10-09 12:36:19 +08:00
|
|
|
|
|
|
|
|
export const variableCheckBoxFieldMap = Object.keys(
|
|
|
|
|
variableEnabledFieldMap,
|
|
|
|
|
).reduce<Record<string, boolean>>((pre, cur) => {
|
|
|
|
|
pre[cur] = setInitialChatVariableEnabledFieldValue(
|
|
|
|
|
cur as ChatVariableEnabledField,
|
|
|
|
|
);
|
|
|
|
|
return pre;
|
|
|
|
|
}, {});
|
|
|
|
|
|
|
|
|
|
export const initialLlmBaseValues = {
|
|
|
|
|
...variableCheckBoxFieldMap,
|
|
|
|
|
temperature: 0.1,
|
|
|
|
|
top_p: 0.3,
|
|
|
|
|
frequency_penalty: 0.7,
|
|
|
|
|
presence_penalty: 0.4,
|
|
|
|
|
max_tokens: 256,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
export enum AgentCategory {
|
|
|
|
|
AgentCanvas = 'agent_canvas',
|
|
|
|
|
DataflowCanvas = 'dataflow_canvas',
|
|
|
|
|
}
|
2025-10-09 19:03:29 +08:00
|
|
|
|
2025-10-17 18:47:33 +08:00
|
|
|
export enum AgentQuery {
|
|
|
|
|
Category = 'category',
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export enum Operator {
|
|
|
|
|
Begin = 'Begin',
|
|
|
|
|
Retrieval = 'Retrieval',
|
|
|
|
|
Categorize = 'Categorize',
|
|
|
|
|
Message = 'Message',
|
|
|
|
|
RewriteQuestion = 'RewriteQuestion',
|
|
|
|
|
DuckDuckGo = 'DuckDuckGo',
|
|
|
|
|
Wikipedia = 'Wikipedia',
|
|
|
|
|
PubMed = 'PubMed',
|
|
|
|
|
ArXiv = 'ArXiv',
|
|
|
|
|
Google = 'Google',
|
|
|
|
|
Bing = 'Bing',
|
|
|
|
|
GoogleScholar = 'GoogleScholar',
|
|
|
|
|
GitHub = 'GitHub',
|
|
|
|
|
ExeSQL = 'ExeSQL',
|
|
|
|
|
Switch = 'Switch',
|
|
|
|
|
WenCai = 'WenCai',
|
|
|
|
|
YahooFinance = 'YahooFinance',
|
|
|
|
|
Note = 'Note',
|
|
|
|
|
Crawler = 'Crawler',
|
|
|
|
|
Invoke = 'Invoke',
|
|
|
|
|
Email = 'Email',
|
|
|
|
|
Iteration = 'Iteration',
|
|
|
|
|
IterationStart = 'IterationItem',
|
|
|
|
|
Code = 'CodeExec',
|
|
|
|
|
WaitingDialogue = 'WaitingDialogue',
|
|
|
|
|
Agent = 'Agent',
|
|
|
|
|
Tool = 'Tool',
|
|
|
|
|
TavilySearch = 'TavilySearch',
|
|
|
|
|
TavilyExtract = 'TavilyExtract',
|
2026-07-30 09:36:16 +08:00
|
|
|
QueritSearch = 'QueritSearch',
|
2025-10-17 18:47:33 +08:00
|
|
|
UserFillUp = 'UserFillUp',
|
|
|
|
|
StringTransform = 'StringTransform',
|
|
|
|
|
SearXNG = 'SearXNG',
|
2026-06-30 23:52:24 -06:00
|
|
|
BGPT = 'BGPT',
|
Add Keenable web search tool to the agent (#16233)
Adds Keenable as a web search tool in the agent, alongside the existing
Tavily/DuckDuckGo/SearXNG/Google tools.
The main difference from the other search tools is that it doesn't
require an
API key. By default it uses Keenable's keyless public endpoint, so it
works out
of the box. Providing a key (in the tool config) switches to the
authenticated
endpoint and lifts the rate limits.
### Changes
- Backend: `agent/tools/keenable.py` — `KeenableSearch`, follows the
Tavily/DuckDuckGo tool shape (results go through `_retrieve_chunks`).
Auto-registered by `agent/tools/__init__.py`.
- Frontend: wired into the agent builder — operator + icon, config form
(optional API key, search mode, site filter, top N), the search tool
menu,
and the existing api_key export sanitizer.
### Config
- API key: optional. Blank = keyless free tier; set it to lift limits /
enable
`realtime` mode.
- `site`: restrict to a single domain.
- `mode`: `pro` (default) or `realtime`.
### Notes
`KEENABLE_API_URL` can override the API base (HTTPS enforced; defaults
to
`https://api.keenable.ai`). The tool only sends the query (no URL
fetch), so
there's no SSRF surface. Verified the frontend with `vite build` and the
backend search path against the public endpoint.
2026-06-25 07:12:28 +03:00
|
|
|
KeenableSearch = 'KeenableSearch',
|
2026-04-14 15:24:43 +08:00
|
|
|
DocGenerator = 'DocGenerator',
|
2026-05-21 14:09:06 +08:00
|
|
|
Browser = 'Browser',
|
2025-10-17 18:47:33 +08:00
|
|
|
Placeholder = 'Placeholder',
|
2025-11-04 13:48:44 +08:00
|
|
|
DataOperations = 'DataOperations',
|
2025-11-14 16:33:20 +08:00
|
|
|
ListOperations = 'ListOperations',
|
2025-11-06 14:42:47 +08:00
|
|
|
VariableAssigner = 'VariableAssigner',
|
2025-11-06 16:18:00 +08:00
|
|
|
VariableAggregator = 'VariableAggregator',
|
2025-10-17 18:47:33 +08:00
|
|
|
File = 'File', // pipeline
|
|
|
|
|
Parser = 'Parser',
|
|
|
|
|
Tokenizer = 'Tokenizer',
|
2026-04-03 19:26:45 +08:00
|
|
|
TokenChunker = 'TokenChunker',
|
|
|
|
|
TitleChunker = 'TitleChunker',
|
2025-10-17 18:47:33 +08:00
|
|
|
Extractor = 'Extractor',
|
2026-07-30 10:39:01 +08:00
|
|
|
Compiler = 'Compiler',
|
2025-11-27 15:55:46 +08:00
|
|
|
Loop = 'Loop',
|
|
|
|
|
LoopStart = 'LoopItem',
|
|
|
|
|
ExitLoop = 'ExitLoop',
|
2025-12-16 10:45:52 +05:30
|
|
|
ExcelProcessor = 'ExcelProcessor',
|
2025-10-17 18:47:33 +08:00
|
|
|
}
|
2025-11-05 17:32:35 +08:00
|
|
|
|
|
|
|
|
export enum ComparisonOperator {
|
|
|
|
|
Equal = '=',
|
|
|
|
|
NotEqual = '≠',
|
|
|
|
|
GreatThan = '>',
|
|
|
|
|
GreatEqual = '≥',
|
|
|
|
|
LessThan = '<',
|
|
|
|
|
LessEqual = '≤',
|
|
|
|
|
Contains = 'contains',
|
|
|
|
|
NotContains = 'not contains',
|
|
|
|
|
StartWith = 'start with',
|
|
|
|
|
EndWith = 'end with',
|
|
|
|
|
Empty = 'empty',
|
|
|
|
|
NotEmpty = 'not empty',
|
2025-11-25 14:25:32 +08:00
|
|
|
In = 'in',
|
|
|
|
|
NotIn = 'not in',
|
2025-11-05 17:32:35 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export const SwitchOperatorOptions = [
|
|
|
|
|
{ value: ComparisonOperator.Equal, label: 'equal', icon: 'equal' },
|
|
|
|
|
{ value: ComparisonOperator.NotEqual, label: 'notEqual', icon: 'not-equals' },
|
|
|
|
|
{ value: ComparisonOperator.GreatThan, label: 'gt', icon: 'Less' },
|
|
|
|
|
{
|
|
|
|
|
value: ComparisonOperator.GreatEqual,
|
|
|
|
|
label: 'ge',
|
|
|
|
|
icon: 'Greater-or-equal',
|
|
|
|
|
},
|
|
|
|
|
{ value: ComparisonOperator.LessThan, label: 'lt', icon: 'Less' },
|
|
|
|
|
{ value: ComparisonOperator.LessEqual, label: 'le', icon: 'less-or-equal' },
|
|
|
|
|
{ value: ComparisonOperator.Contains, label: 'contains', icon: 'Contains' },
|
|
|
|
|
{
|
|
|
|
|
value: ComparisonOperator.NotContains,
|
|
|
|
|
label: 'notContains',
|
|
|
|
|
icon: 'not-contains',
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
value: ComparisonOperator.StartWith,
|
|
|
|
|
label: 'startWith',
|
|
|
|
|
icon: 'list-start',
|
|
|
|
|
},
|
|
|
|
|
{ value: ComparisonOperator.EndWith, label: 'endWith', icon: 'list-end' },
|
|
|
|
|
{
|
|
|
|
|
value: ComparisonOperator.Empty,
|
|
|
|
|
label: 'empty',
|
|
|
|
|
icon: <Circle className="size-4" />,
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
value: ComparisonOperator.NotEmpty,
|
|
|
|
|
label: 'notEmpty',
|
|
|
|
|
icon: <CircleSlash2 className="size-4" />,
|
|
|
|
|
},
|
2025-11-25 14:25:32 +08:00
|
|
|
{
|
|
|
|
|
value: ComparisonOperator.In,
|
|
|
|
|
label: 'in',
|
2026-02-10 14:04:50 +08:00
|
|
|
icon: <CircleDotDashed className="size-4" />,
|
2025-11-25 14:25:32 +08:00
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
value: ComparisonOperator.NotIn,
|
|
|
|
|
label: 'notIn',
|
2026-02-10 14:04:50 +08:00
|
|
|
icon: <CircleDashed className="size-4" />,
|
2025-11-25 14:25:32 +08:00
|
|
|
},
|
2025-11-05 17:32:35 +08:00
|
|
|
];
|
2025-11-18 13:07:52 +08:00
|
|
|
|
|
|
|
|
export const AgentStructuredOutputField = 'structured';
|
|
|
|
|
|
|
|
|
|
export enum JsonSchemaDataType {
|
|
|
|
|
String = 'string',
|
|
|
|
|
Number = 'number',
|
|
|
|
|
Boolean = 'boolean',
|
|
|
|
|
Array = 'array',
|
|
|
|
|
Object = 'object',
|
|
|
|
|
}
|
2025-11-21 16:21:27 +08:00
|
|
|
|
|
|
|
|
export enum SwitchLogicOperator {
|
|
|
|
|
And = 'and',
|
|
|
|
|
Or = 'or',
|
|
|
|
|
}
|
2025-12-10 19:13:57 +08:00
|
|
|
|
2025-12-19 12:56:56 +08:00
|
|
|
export const WebhookJWTAlgorithmList = [
|
2025-12-10 19:13:57 +08:00
|
|
|
'hs256',
|
|
|
|
|
'hs384',
|
|
|
|
|
'hs512',
|
|
|
|
|
'rs256',
|
|
|
|
|
'rs384',
|
|
|
|
|
'rs512',
|
|
|
|
|
'es256',
|
|
|
|
|
'es384',
|
|
|
|
|
'es512',
|
|
|
|
|
'ps256',
|
|
|
|
|
'ps384',
|
|
|
|
|
'ps512',
|
|
|
|
|
'none',
|
|
|
|
|
] as const;
|
2025-12-31 11:19:33 +08:00
|
|
|
|
|
|
|
|
export enum AgentDialogueMode {
|
|
|
|
|
Conversational = 'conversational',
|
|
|
|
|
Task = 'task',
|
|
|
|
|
Webhook = 'Webhook',
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export const initialBeginValues = {
|
|
|
|
|
mode: AgentDialogueMode.Conversational,
|
|
|
|
|
prologue: `Hi! I'm your assistant. What can I do for you?`,
|
|
|
|
|
};
|
2026-03-02 11:41:38 +08:00
|
|
|
|
|
|
|
|
export const BeginId = 'begin';
|
|
|
|
|
|
|
|
|
|
export const EmptyDsl = {
|
|
|
|
|
graph: {
|
|
|
|
|
nodes: [
|
|
|
|
|
{
|
|
|
|
|
id: BeginId,
|
|
|
|
|
type: 'beginNode',
|
|
|
|
|
position: {
|
|
|
|
|
x: 50,
|
|
|
|
|
y: 200,
|
|
|
|
|
},
|
|
|
|
|
data: {
|
|
|
|
|
label: 'Begin',
|
|
|
|
|
name: 'begin',
|
|
|
|
|
form: initialBeginValues,
|
|
|
|
|
},
|
|
|
|
|
sourcePosition: 'left',
|
|
|
|
|
targetPosition: 'right',
|
|
|
|
|
},
|
|
|
|
|
],
|
|
|
|
|
edges: [],
|
|
|
|
|
},
|
|
|
|
|
components: {
|
|
|
|
|
begin: {
|
|
|
|
|
obj: {
|
|
|
|
|
component_name: 'Begin',
|
|
|
|
|
params: {},
|
|
|
|
|
},
|
|
|
|
|
downstream: [], // other edge target is downstream, edge source is current node id
|
|
|
|
|
upstream: [], // edge source is upstream, edge target is current node id
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
retrieval: [], // reference
|
|
|
|
|
history: [],
|
|
|
|
|
path: [],
|
|
|
|
|
variables: [],
|
|
|
|
|
globals: {
|
|
|
|
|
[AgentGlobals.SysQuery]: '',
|
|
|
|
|
[AgentGlobals.SysUserId]: '',
|
|
|
|
|
[AgentGlobals.SysConversationTurns]: 0,
|
|
|
|
|
[AgentGlobals.SysFiles]: [],
|
|
|
|
|
[AgentGlobals.SysHistory]: [],
|
2026-03-12 17:49:13 +08:00
|
|
|
[AgentGlobals.SysDate]: '',
|
2026-03-02 11:41:38 +08:00
|
|
|
},
|
|
|
|
|
};
|