Files
FastGPT/packages/service/common/system/utils.ts
T
Archer 76d6234de6 V4.14.7 features (#6406)
* Agent features (#6345)

* Test agent (#6220)

* squash: compress all commits into one

* feat: plan response in ui

* response ui

* perf: agent config

* merge

* tool select ux

* perf: chat ui

* perf: agent editform

* tmp code

* feat: save chat

* Complete agent parent  (#6049)

* add role and tools filling

* add: file-upload

---------

Co-authored-by: xxyyh <2289112474@qq>

* perf: top agent code

* top agent (#6062)

Co-authored-by: xxyyh <2289112474@qq>

* fix: ts

* skill editor ui

* ui

* perf: rewrite type with zod

* skill edit ui

* skill agent (#6089)

* cp skill chat

* rebase fdf933d
 and add skill chat

* 1. skill 的 CRUD
2. skill 的信息渲染到前端界面

* solve comment

* remove chatid and chatItemId

* skill match

* perf: skill manage

* fix: ts

---------

Co-authored-by: xxyyh <2289112474@qq>
Co-authored-by: archer <545436317@qq.com>

* fix: ts

* fix: loop import

* skill tool config (#6114)

Co-authored-by: xxyyh <2289112474@qq>

* feat: load tool in agent

* skill memory (#6126)

Co-authored-by: xxyyh <2289112474@qq>

* perf: agent skill editor

* perf: helperbot ui

* agent code

* perf: context

* fix: request context

* agent usage

* perf: agent context and pause

* perf: plan response

* Test agent sigle skill (#6184)

* feat:top box fill

* prompt fix

---------

Co-authored-by: xxyyh <2289112474@qq>

* perf: agent chat ui

* Test agent new (#6219)

* have-replan

* agent

---------

Co-authored-by: xxyyh <2289112474@qq>

* fix: ts

---------

Co-authored-by: YeYuheng <57035043+YYH211@users.noreply.github.com>
Co-authored-by: xxyyh <2289112474@qq>

* feat: consolidate agent and MCP improvements

This commit consolidates 17 commits including:
- MCP tools enhancements and fixes
- Agent system improvements and optimizations
- Auth limit and prompt updates
- Tool response compression and error tracking
- Simple app adaptation
- Code quality improvements (TypeScript, ESLint, Zod)
- Version type migration to schema
- Remove deprecated useRequest2
- Add LLM error tracking
- Toolset ID validation fixes

---------

Co-authored-by: YeYuheng <57035043+YYH211@users.noreply.github.com>
Co-authored-by: xxyyh <2289112474@qq>

* fix: transform avatar copy;perf: filter invalid tool

* update llm response storage time

* fix: openapi schema

* update skill desc

* feat: cache hit data

* i18n

* lock

* chat logs support error filter & user search (#6373)

* chat log support searching by user name

* support error filter

* fix

* fix overflow

* optimize

* fix init script

* fix

* perf: get log users

* updat ecomment

* fix: ts

* fix: test

---------

Co-authored-by: archer <545436317@qq.com>

* Fix: agent  (#6376)

* Agent features (#6345)

* Test agent (#6220)

* squash: compress all commits into one

* feat: plan response in ui

* response ui

* perf: agent config

* merge

* tool select ux

* perf: chat ui

* perf: agent editform

* tmp code

* feat: save chat

* Complete agent parent  (#6049)

* add role and tools filling

* add: file-upload

---------

Co-authored-by: xxyyh <2289112474@qq>

* perf: top agent code

* top agent (#6062)

Co-authored-by: xxyyh <2289112474@qq>

* fix: ts

* skill editor ui

* ui

* perf: rewrite type with zod

* skill edit ui

* skill agent (#6089)

* cp skill chat

* rebase fdf933d
 and add skill chat

* 1. skill 的 CRUD
2. skill 的信息渲染到前端界面

* solve comment

* remove chatid and chatItemId

* skill match

* perf: skill manage

* fix: ts

---------

Co-authored-by: xxyyh <2289112474@qq>
Co-authored-by: archer <545436317@qq.com>

* fix: ts

* fix: loop import

* skill tool config (#6114)

Co-authored-by: xxyyh <2289112474@qq>

* feat: load tool in agent

* skill memory (#6126)

Co-authored-by: xxyyh <2289112474@qq>

* perf: agent skill editor

* perf: helperbot ui

* agent code

* perf: context

* fix: request context

* agent usage

* perf: agent context and pause

* perf: plan response

* Test agent sigle skill (#6184)

* feat:top box fill

* prompt fix

---------

Co-authored-by: xxyyh <2289112474@qq>

* perf: agent chat ui

* Test agent new (#6219)

* have-replan

* agent

---------

Co-authored-by: xxyyh <2289112474@qq>

* fix: ts

---------

Co-authored-by: YeYuheng <57035043+YYH211@users.noreply.github.com>
Co-authored-by: xxyyh <2289112474@qq>

* feat: consolidate agent and MCP improvements

This commit consolidates 17 commits including:
- MCP tools enhancements and fixes
- Agent system improvements and optimizations
- Auth limit and prompt updates
- Tool response compression and error tracking
- Simple app adaptation
- Code quality improvements (TypeScript, ESLint, Zod)
- Version type migration to schema
- Remove deprecated useRequest2
- Add LLM error tracking
- Toolset ID validation fixes

---------

Co-authored-by: YeYuheng <57035043+YYH211@users.noreply.github.com>
Co-authored-by: xxyyh <2289112474@qq>

* 1. 把辅助生成前端上的 system prompt 加入到上下文中
2. mcp工具的前端渲染(图标)
3. 文件读取工具和文件上传进行关联
4. 添加了辅助生成返回格式出错的重试方案
5. ask 不出现在 plan 步骤中
6. 添加了辅助生成的头像和交互 UI

* fix:read_file

* helperbot ui

* ts error

* helper ui

* delete Unused import

* perf: helper bot

* lock

---------

Co-authored-by: Archer <545436317@qq.com>
Co-authored-by: xxyyh <2289112474@qq>

* fix date variable required & model auth (#6386)

* fix date variable required & model auth

* doc

* feat: add chat id to finish callback

* fix: iphone safari shareId (#6387)

* fix: iphone safari shareId

* fix: mcp file list can't setting

* fix: reason output field

* fix: skip JSON validation for HTTP tool body with variable (#6392)

* fix: skip JSON validation for HTTP tool body with variable

* doc

* workflow fitview

* perf: selecting memory

* perf: cp api

* ui

* perf: toolcall auto adapt

* fix: catch workflow error

* fix: ts

* perf: pagination type

* remove

* ignore

* update doc

* fix: simple app tool select

* add default avatar to logs user

* perf: loading user

* select dataset ui

* rename version

* feat: add global/common test

* perf: packages/global/common test

* feat: package/global/ai,app test

* add global/chat test

* global/core test

* global/core test

* feat: packages/global all test

* perf: test

* add server api test

* perf: init shell

* perf: init4150 shell

* remove invalid code

* update doc

* remove log

* fix: chat effect

* fix: plan fake tool  (#6398)

* 1. 提示词防注入功能
2. 无工具不进入 plan,防止虚拟工具生成

* Agent-dataset

* dataset

* dataset presetInfo

* prefix

* perf: prompt

---------

Co-authored-by: xxyyh <2289112474@qq>
Co-authored-by: archer <545436317@qq.com>

* fix: review

* adapt kimi2.5 think toolcall

* feat: invoke fastgpt user info (#6403)

feat: invoke fastgpt user info

* fix: invoke fastgpt user info return orgs (#6404)

* skill and version

* retry helperbot (#6405)

Co-authored-by: xxyyh <2289112474@qq>

* update template

* remove log

* doc

* update doc

* doc

* perf: internal ip check

* adapt get paginationRecords

* tool call adapt

* fix: test

* doc

* fix: agent initial version

* adapt completions v1

* feat: instrumentation check

* rename skill

* add workflow demo mode tracks (#6407)

* chore: 统一 skills 目录命名为小写

将 .claude/Skills/ 重命名为 .claude/skills/ 以保持命名一致性。

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* add workflow demo mode tracks

* code

* optimize

* fix: improve workflowDemoTrack based on PR review

- Add comment to empty catch block for maintainability
- Add @param docs to onDemoChange clarifying nodeCount usage
- Replace silent .catch with console.debug for dev debugging
- Handle appId changes by reporting old data before re-init

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: archer <545436317@qq.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>

* remove repeat skill

* fix(workflow): filter out orphan edges to prevent runtime errors (#6399)

* fix(workflow): filter out orphan edges to prevent runtime errors

Runtime edges that reference non-existent nodes (orphan edges) can cause
unexpected behavior or crashes during workflow dispatch. This change adds
a pre-check to filter out such edges before execution begins, ensuring
system stability even with inconsistent graph data.

* fix(workflow): enhance orphan edge filtering with logging and tests

- Refactor: Extract logic to 'filterOrphanEdges' in utils.ts for better reusability
- Feat: Add performance monitoring (warn if >100ms) and comprehensive logging
- Feat: Support detailed edge inspection in debug mode
- Docs: Add JSDoc explaining causes of orphan edges (migration, manual edits)
- Test: Add unit tests covering edge cases and performance (1000 edges)

Addresses PR review feedback regarding logging, variable naming, and testing."

* move code

* move code

* add more unit test

---------

Co-authored-by: archer <545436317@qq.com>

* test

* perf: test

* add server/common/string test

* fix: resolve $ref references in MCP tool input schemas (#6395) (#6409)

* fix: resolve $ref references in MCP tool input schemas (#6395)

* add test code

---------

Co-authored-by: archer <545436317@qq.com>

* chore(docs): add fastgpt, fastgpt-plugin version choice guide (#6411)

* chore(doc): add fastgpt version description

* doc

* doc

---------

Co-authored-by: archer <545436317@qq.com>

* fix:dataset cite and description info (#6410)

* 1. 添加知识库引用(plan 步骤和直接知识库调用)
2. 提示词框中的@知识库工具
3. plan 中 step 的 description dataset_search 改为中文

* fix: i18n

* prompt

* prompt

---------

Co-authored-by: xxyyh <2289112474@qq>

* fix: tool call

* perf: workflow props

* fix: merge ECharts toolbox options instead of overwriting (#6269) (#6412)

* feat: integrate logtape and otel (#6400)

* fix: deps

* feat(logger): integrate logtape and otel

* wip(log): add basic infras logs

* wip(log): add request id and inject it into context

* wip(log): add basic tx logs

* wip(log): migrate

* wip(log): category

* wip(log): more sub category

* fix: type

* fix: sessionRun

* fix: export getLogger from client.ts

* chore: improve logs

* docs: update signoz and changelog

* change type

* fix: ts

* remove skill.md

* fix: lockfile specifier

* fix: test

---------

Co-authored-by: archer <545436317@qq.com>

* init log

* doc

* remove invalid log

* fix: review

* template

* replace new log

* fix: ts

* remove log

* chore: migrate all addLog to logtape

* move skill

* chore: migrate all addLog to logtape (#6417)

* update skill

* remove log

* fix: tool check

---------

Co-authored-by: YeYuheng <57035043+YYH211@users.noreply.github.com>
Co-authored-by: xxyyh <2289112474@qq>
Co-authored-by: heheer <heheer@sealos.io>
Co-authored-by: Finley Ge <32237950+FinleyGe@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: xuyafei1996 <54217479+xuyafei1996@users.noreply.github.com>
Co-authored-by: ToukoYui <2331631097@qq.com>
Co-authored-by: roy <whoeverimf5@gmail.com>
2026-02-12 16:37:50 +08:00

187 lines
6.4 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { SERVICE_LOCAL_HOST } from './tools';
import { isIP } from 'net';
import * as dns from 'node:dns/promises';
export const isInternalAddress = async (url: string): Promise<boolean> => {
const isInternalIPv6 = (ip: string): boolean => {
// 移除 IPv6 地址中的方括号(如果有)
const cleanIp = ip.replace(/^\[|\]$/g, '');
// 检查 IPv4-mapped IPv6 地址(格式:::ffff:xxxx:xxxx
// Node.js URL 解析器会将 IPv4 部分转换为十六进制
const ipv4MappedPattern = /^::ffff:([0-9a-f]{1,4}):([0-9a-f]{1,4})$/i;
const ipv4MappedMatch = cleanIp.match(ipv4MappedPattern);
if (ipv4MappedMatch) {
// 将十六进制转换回 IPv4 地址
const hex1 = parseInt(ipv4MappedMatch[1], 16);
const hex2 = parseInt(ipv4MappedMatch[2], 16);
// hex1 包含前两个字节,hex2 包含后两个字节
const byte1 = (hex1 >> 8) & 0xff;
const byte2 = hex1 & 0xff;
const byte3 = (hex2 >> 8) & 0xff;
const byte4 = hex2 & 0xff;
const ipv4 = `${byte1}.${byte2}.${byte3}.${byte4}`;
return isInternalIPv4(ipv4);
}
// IPv6 内部地址范围
const internalIPv6Patterns = [
/^::1$/, // Loopback
/^::$/, // Unspecified
/^fe80:/i, // Link-local
/^fc00:/i, // Unique local address (ULA)
/^fd00:/i, // Unique local address (ULA)
/^::ffff:0:0/i, // IPv4-mapped IPv6
/^::ffff:127\./i, // IPv4-mapped loopback
/^::ffff:10\./i, // IPv4-mapped private (10.0.0.0/8)
/^::ffff:172\.(1[6-9]|2[0-9]|3[0-1])\./i, // IPv4-mapped private (172.16.0.0/12)
/^::ffff:192\.168\./i, // IPv4-mapped private (192.168.0.0/16)
/^::ffff:169\.254\./i, // IPv4-mapped link-local
/^::ffff:100\.(6[4-9]|[7-9][0-9]|1[0-1][0-9]|12[0-7])\./i // IPv4-mapped shared address space
];
return internalIPv6Patterns.some((pattern) => pattern.test(cleanIp));
};
const isInternalIPv4 = (ip: string): boolean => {
// 验证是否为有效的 IPv4 格式
const ipv4Pattern = /^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/;
const match = ip.match(ipv4Pattern);
if (!match) {
return false;
}
// 解析 IP 地址的各个部分
const parts = [
parseInt(match[1], 10),
parseInt(match[2], 10),
parseInt(match[3], 10),
parseInt(match[4], 10)
];
// 验证每个部分是否在有效范围内 (0-255)
if (parts.some((part) => part < 0 || part > 255)) {
return false;
}
// 检查是否为内部 IP 地址范围
return (
parts[0] === 0 || // 0.0.0.0/8 - Current network
parts[0] === 10 || // 10.0.0.0/8 - Private network
parts[0] === 127 || // 127.0.0.0/8 - Loopback
(parts[0] === 169 && parts[1] === 254) || // 169.254.0.0/16 - Link-local
(parts[0] === 172 && parts[1] >= 16 && parts[1] <= 31) || // 172.16.0.0/12 - Private network
(parts[0] === 192 && parts[1] === 168) || // 192.168.0.0/16 - Private network
(parts[0] >= 224 && parts[0] <= 239) || // 224.0.0.0/4 - Multicast
(parts[0] >= 240 && parts[0] <= 255) || // 240.0.0.0/4 - Reserved
(parts[0] === 100 && parts[1] >= 64 && parts[1] <= 127) || // 100.64.0.0/10 - Shared address space
(parts[0] === 192 && parts[1] === 0 && parts[2] === 0) || // 192.0.0.0/24 - IETF Protocol Assignments
(parts[0] === 192 && parts[1] === 0 && parts[2] === 2) || // 192.0.2.0/24 - Documentation (TEST-NET-1)
(parts[0] === 198 && parts[1] === 18) || // 198.18.0.0/15 - Benchmarking
(parts[0] === 198 && parts[1] === 19) || // 198.18.0.0/15 - Benchmarking
(parts[0] === 198 && parts[1] === 51 && parts[2] === 100) || // 198.51.100.0/24 - Documentation (TEST-NET-2)
(parts[0] === 203 && parts[1] === 0 && parts[2] === 113) // 203.0.113.0/24 - Documentation (TEST-NET-3)
);
};
try {
const parsedUrl = new URL(url);
// 移除 IPv6 地址的方括号(如果有)
const hostname = parsedUrl.hostname.replace(/^\[|\]$/g, '');
const fullUrl = parsedUrl.toString();
// 1. 检查 localhost 和常见的本地域名变体
const localhostVariants = ['localhost', '127.0.0.1', '::1', '0.0.0.0'];
const localHostname = SERVICE_LOCAL_HOST.split(':')[0];
if (localhostVariants.includes(hostname) || hostname === localHostname) {
return true;
}
// 2. 检查云服务商元数据端点(始终阻止,无论 CHECK_INTERNAL_IP 设置如何)
const metadataEndpoints = [
// AWS
'http://169.254.169.254/',
'http://[fd00:ec2::254]/',
// Azure
'http://169.254.169.254/',
// GCP
'http://metadata.google.internal/',
'http://metadata/',
// Alibaba Cloud
'http://100.100.100.200/',
// Tencent Cloud
'http://metadata.tencentyun.com/',
// Huawei Cloud
'http://169.254.169.254/',
// Oracle Cloud
'http://169.254.169.254/',
// DigitalOcean
'http://169.254.169.254/',
// Kubernetes
'http://kubernetes.default.svc/',
'https://kubernetes.default.svc/'
];
if (metadataEndpoints.some((endpoint) => fullUrl.startsWith(endpoint))) {
return true;
}
// 3. 如果未启用内部 IP 检查,则不进行进一步检查(保持向后兼容)
if (process.env.CHECK_INTERNAL_IP !== 'true') {
return false;
}
// 4. 使用 Node.js 的 isIP 函数检测 IP 版本
const ipVersion = isIP(hostname);
if (ipVersion === 4) {
// IPv4 地址检查
return isInternalIPv4(hostname);
} else if (ipVersion === 6) {
// IPv6 地址检查
return isInternalIPv6(hostname);
} else {
// 不是 IP 地址,是域名 - 需要解析
try {
// 解析所有 A 和 AAAA 记录
const [ipv4Addresses, ipv6Addresses] = await Promise.allSettled([
dns.resolve4(hostname),
dns.resolve6(hostname)
]);
// 检查所有解析的 IP 是否为内部地址
const allIPs = [
...(ipv4Addresses.status === 'fulfilled' ? ipv4Addresses.value : []),
...(ipv6Addresses.status === 'fulfilled' ? ipv6Addresses.value : [])
];
// 如果任何一个解析的 IP 是内部地址,则拒绝
for (const ip of allIPs) {
if (isInternalIPv4(ip) || isInternalIPv6(ip)) {
return true;
}
}
return false;
} catch (error) {
return false;
}
}
} catch (error) {
// URL 解析失败 - 宽松策略:允许访问
return false;
}
};