fix: use internal URL for AI HTTP tools
Prefer IA_WEB_INTERNAL_URL or local HOST for AI tool requests while preserving public page links for users.
This commit is contained in:
@@ -1,5 +1,12 @@
|
|||||||
# 更新日志
|
# 更新日志
|
||||||
|
|
||||||
|
## 0.2.16 - 2026-07-07
|
||||||
|
|
||||||
|
- 修复 AI 内置页面工具在配置了受保护公开地址时,请求 `/v1/web/pages` 命中 NetBird 鉴权页并返回 401 的问题。
|
||||||
|
- `create_web_page`、`create_markdown_preview`、`query_web_pages` 的内部 HTTP 请求现在优先使用 `IA_WEB_INTERNAL_URL` 或本地 `HOST`;返回给用户的页面链接仍优先使用 `IA_WEB_BASE_URL`。
|
||||||
|
- `query_api_docs` 同步优先使用内部地址查询 API 文档,避免内部工具调用被公开入口鉴权拦截。
|
||||||
|
- 无数据库结构变化;新增 `0.2.16` 升级日志记录,`ias-ai` 升级至 `0.1.6`,`ias-service` 升级至 `0.1.13`。
|
||||||
|
|
||||||
## 0.2.15 - 2026-07-07
|
## 0.2.15 - 2026-07-07
|
||||||
|
|
||||||
- 新增 Markdown 预览页面能力:`page_type=markdown` 的动态页面公开路径为 `/md/{slug}`,React 前端按 Markdown/GFM 渲染标题、列表、表格、引用、链接和代码块。
|
- 新增 Markdown 预览页面能力:`page_type=markdown` 的动态页面公开路径为 `/md/{slug}`,React 前端按 Markdown/GFM 渲染标题、列表、表格、引用、链接和代码块。
|
||||||
|
|||||||
Generated
+3
-3
@@ -1042,7 +1042,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ias-ai"
|
name = "ias-ai"
|
||||||
version = "0.1.5"
|
version = "0.1.6"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"chrono",
|
"chrono",
|
||||||
@@ -1120,7 +1120,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ias-main"
|
name = "ias-main"
|
||||||
version = "0.2.15"
|
version = "0.2.16"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"clap",
|
"clap",
|
||||||
@@ -1135,7 +1135,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ias-service"
|
name = "ias-service"
|
||||||
version = "0.1.12"
|
version = "0.1.13"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"axum",
|
"axum",
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "ias-ai"
|
name = "ias-ai"
|
||||||
version = "0.1.5"
|
version = "0.1.6"
|
||||||
edition = "2024"
|
edition = "2024"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
|||||||
@@ -196,8 +196,7 @@ fn validate_endpoint_id(value: &str) -> anyhow::Result<String> {
|
|||||||
|
|
||||||
fn api_docs_base_url() -> String {
|
fn api_docs_base_url() -> String {
|
||||||
std::env::var("IA_API_DOCS_BASE_URL")
|
std::env::var("IA_API_DOCS_BASE_URL")
|
||||||
.or_else(|_| std::env::var("IA_WEB_BASE_URL"))
|
.or_else(|_| std::env::var("IA_WEB_INTERNAL_URL"))
|
||||||
.or_else(|_| std::env::var("WEB_BASE_URL"))
|
|
||||||
.or_else(|_| std::env::var("HOST").map(|host| format!("http://{host}")))
|
.or_else(|_| std::env::var("HOST").map(|host| format!("http://{host}")))
|
||||||
.unwrap_or_else(|_| "http://127.0.0.1:9003".to_string())
|
.unwrap_or_else(|_| "http://127.0.0.1:9003".to_string())
|
||||||
.trim()
|
.trim()
|
||||||
|
|||||||
+13
-4
@@ -129,7 +129,7 @@ async fn create_markdown_preview_inner(arguments: &str) -> anyhow::Result<String
|
|||||||
}
|
}
|
||||||
|
|
||||||
async fn create_page_request(payload: Value) -> anyhow::Result<String> {
|
async fn create_page_request(payload: Value) -> anyhow::Result<String> {
|
||||||
let base_url = web_base_url();
|
let base_url = web_request_base_url();
|
||||||
let endpoint = format!("{base_url}/v1/web/pages");
|
let endpoint = format!("{base_url}/v1/web/pages");
|
||||||
let client = reqwest::Client::new();
|
let client = reqwest::Client::new();
|
||||||
let response = client
|
let response = client
|
||||||
@@ -184,7 +184,7 @@ async fn query_web_pages_inner(arguments: &str) -> anyhow::Result<String> {
|
|||||||
let page = args.page.unwrap_or(1).max(1);
|
let page = args.page.unwrap_or(1).max(1);
|
||||||
let per_page = args.per_page.unwrap_or(10).clamp(1, 20);
|
let per_page = args.per_page.unwrap_or(10).clamp(1, 20);
|
||||||
|
|
||||||
let mut url = reqwest::Url::parse(&format!("{}/v1/web/pages", web_base_url()))
|
let mut url = reqwest::Url::parse(&format!("{}/v1/web/pages", web_request_base_url()))
|
||||||
.context("构造 web 页面查询地址失败")?;
|
.context("构造 web 页面查询地址失败")?;
|
||||||
{
|
{
|
||||||
let mut query_pairs = url.query_pairs_mut();
|
let mut query_pairs = url.query_pairs_mut();
|
||||||
@@ -266,7 +266,7 @@ fn web_page_url(page: &WebPageItem) -> String {
|
|||||||
} else {
|
} else {
|
||||||
format!("/web/{}/{}", page.page_type, page.slug)
|
format!("/web/{}/{}", page.page_type, page.slug)
|
||||||
};
|
};
|
||||||
format!("{}{}", web_base_url(), path)
|
format!("{}{}", web_public_base_url(), path)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn optional_text(value: Option<String>) -> Option<String> {
|
fn optional_text(value: Option<String>) -> Option<String> {
|
||||||
@@ -275,7 +275,16 @@ fn optional_text(value: Option<String>) -> Option<String> {
|
|||||||
.filter(|value| !value.is_empty())
|
.filter(|value| !value.is_empty())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn web_base_url() -> String {
|
fn web_request_base_url() -> String {
|
||||||
|
std::env::var("IA_WEB_INTERNAL_URL")
|
||||||
|
.or_else(|_| std::env::var("HOST").map(|host| format!("http://{host}")))
|
||||||
|
.unwrap_or_else(|_| "http://127.0.0.1:9003".to_string())
|
||||||
|
.trim()
|
||||||
|
.trim_end_matches('/')
|
||||||
|
.replace("0.0.0.0", "127.0.0.1")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn web_public_base_url() -> String {
|
||||||
std::env::var("IA_WEB_BASE_URL")
|
std::env::var("IA_WEB_BASE_URL")
|
||||||
.or_else(|_| std::env::var("WEB_BASE_URL"))
|
.or_else(|_| std::env::var("WEB_BASE_URL"))
|
||||||
.or_else(|_| std::env::var("HOST").map(|host| format!("http://{host}")))
|
.or_else(|_| std::env::var("HOST").map(|host| format!("http://{host}")))
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "ias-main"
|
name = "ias-main"
|
||||||
version = "0.2.15"
|
version = "0.2.16"
|
||||||
edition = "2024"
|
edition = "2024"
|
||||||
|
|
||||||
[[bin]]
|
[[bin]]
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "ias-service"
|
name = "ias-service"
|
||||||
version = "0.1.12"
|
version = "0.1.13"
|
||||||
edition = "2024"
|
edition = "2024"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
|||||||
@@ -0,0 +1,34 @@
|
|||||||
|
INSERT INTO ias_upgrade_logs (
|
||||||
|
version,
|
||||||
|
released_at,
|
||||||
|
title,
|
||||||
|
description,
|
||||||
|
changes,
|
||||||
|
modules
|
||||||
|
) VALUES (
|
||||||
|
'0.2.16',
|
||||||
|
'2026-07-07T00:00:00+08:00',
|
||||||
|
'修复 AI 页面工具内部访问地址',
|
||||||
|
'修复 AI 内置页面工具在公开地址受 NetBird 鉴权保护时无法创建 Markdown 预览页的问题,内部请求改为优先使用内部地址或本地服务地址。',
|
||||||
|
'[
|
||||||
|
"修复 AI 内置页面工具在配置了受保护公开地址时,请求 /v1/web/pages 命中 NetBird 鉴权页并返回 401 的问题。",
|
||||||
|
"create_web_page、create_markdown_preview、query_web_pages 的内部 HTTP 请求现在优先使用 IA_WEB_INTERNAL_URL 或本地 HOST;返回给用户的页面链接仍优先使用 IA_WEB_BASE_URL。",
|
||||||
|
"query_api_docs 同步优先使用内部地址查询 API 文档,避免内部工具调用被公开入口鉴权拦截。",
|
||||||
|
"无数据库结构变化;ias-ai 升级至 0.1.6,ias-service 升级至 0.1.13。"
|
||||||
|
]'::jsonb,
|
||||||
|
'{
|
||||||
|
"ias-common": "0.1.1",
|
||||||
|
"ias-ai": "0.1.6",
|
||||||
|
"ias-wechat": "0.1.0",
|
||||||
|
"ias-context": "0.1.2",
|
||||||
|
"ias-http": "0.1.9",
|
||||||
|
"ias-mail": "0.1.15",
|
||||||
|
"ias-service": "0.1.13",
|
||||||
|
"ias-main": "0.2.16"
|
||||||
|
}'::jsonb
|
||||||
|
) ON CONFLICT (version) DO UPDATE SET
|
||||||
|
released_at = EXCLUDED.released_at,
|
||||||
|
title = EXCLUDED.title,
|
||||||
|
description = EXCLUDED.description,
|
||||||
|
changes = EXCLUDED.changes,
|
||||||
|
modules = EXCLUDED.modules;
|
||||||
Reference in New Issue
Block a user