Skip to content

feat: add a websocket proxy, make it available to send a frontend fun… #4285

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
151 changes: 151 additions & 0 deletions plugins/nodejs-websocket-bridge/GUIDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
# FastGPT 前端工具调用集成指南

## 概述

本指南介绍如何实现工作流来调用前端工具,以达到Agent真的在帮助用户进行页面操作,填写表单等效果。

## 架构说明

1. **集成流程**:
- FastGPT通过iframe嵌入到您的页面
- 工作流中的工具调用组件可调用前端功能(如读取DOM、触发点击)
- Proxy组件通过chatId维持前后端连接
- 工作流通过HTTP调用Proxy,Proxy通过WebSocket与前端通信

2. **数据流向**:
- 工作流 → HTTP → Proxy → WebSocket → share页面
- share页面 → postMessage → 父页面执行函数 → postMessage回传 → WebSocket → Proxy → HTTP → 工作流

## 实现步骤

### 1. 实现消息处理器

在您的父页面中添加以下消息处理代码:

```javascript
const messageHandler = (event) => {
// 验证消息来源(根据实际域名修改)
// const trustedOrigin = 'http://localhost:3000';
// if (event.origin !== trustedOrigin) return;

// 处理不同类型的消息
const iframe = document.querySelector('iframe');
switch (event.data.type) {
case 'functionCall':
function makeResponse(result, requestId) {
iframe?.contentWindow?.postMessage({
type: 'functionCallResponse',
requestId,
result
}, '*'); // 生产环境应替换为实际的trustedOrigin
}
try {
let obj = event.data.value;
if (typeof obj === 'string') {
obj = JSON.parse(obj);
}
const requestId = obj.requestId;
const tool_name = obj.tool_name;
const tool_param = obj.tool_param;

// 示例工具调用处理
if (tool_name === 'get_dom') {
try {
const pageContent = document.querySelector(tool_param);
if (pageContent) {
const DOM = pageContent.innerHTML;
makeResponse(DOM, requestId);
}
} catch (error) {
makeResponse('Error processing page content: ' + error, requestId);
}
}

// 添加其他工具处理逻辑
// else if (tool_name === '其他工具名') {...}

} catch (error) {
console.error('Error parsing JSON:', error);
}
break;
}
};

window.addEventListener('message', messageHandler);
```

### 2. 配置Nginx转发

添加以下配置到您的Nginx(share页面将通过该接口建立websocket连接):

```nginx
location /ws-proxy {
# 将/ws-proxy路径重写为根路径,以便WebSocket服务器能正确处理
rewrite ^/ws-proxy(/.*)$ $1 break;

proxy_pass http://localhost:3003;
proxy_http_version 1.1;

# WebSocket特定设置
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

# WebSocket连接不应该被Nginx缓存服务器自动关闭
proxy_read_timeout 3600s;
proxy_send_timeout 3600s;
}
```

### 3. 嵌入FastGPT iframe

将FastGPT的iframe嵌入到您的页面:


### 4. 工作流中配置HTTP节点

在FastGPT工作流中创建HTTP节点,配置如下:

- 请求方式: POST
- 请求地址: http://localhost:3003/execute-tool
- 请求内容:
```json
{
"chatId": "{{$VARIABLE_NODE_ID.chatId$}}", // 选择变量,当前对话ID
"tool_name": "get_dom", // 工具名称
"tool_param": "#root" // 工具参数,此处为DOM选择器
}
```

工作流将通过HTTP节点将请求发送到proxy服务,proxy再通过WebSocket与前端通信,实现工具调用。

## 注意事项

1. 目前proxy设置的HTTP超时设为5分钟,请确保在此时间内完成响应
2. 生产环境中请设置正确的trustedOrigin以增强安全性
3. 根据需要扩展messageHandler以支持更多工具调用类型

## 工具实现示例

### DOM读取工具
如上述代码所示,实现了get_dom工具

### 按钮点击工具示例
```javascript
if (tool_name === 'click_button') {
try {
const buttonSelector = tool_param.selector;
const button = document.querySelector(buttonSelector);
if (button) {
button.click();
makeResponse('Button clicked successfully', requestId);
} else {
makeResponse('Button not found', requestId);
}
} catch (error) {
makeResponse('Error clicking button: ' + error, requestId);
}
}
```
Loading