新增: 小程序端跨端AI对话

This commit is contained in:
2026-06-24 00:19:54 +08:00
parent 0c7c5e6068
commit 698d981962
20 changed files with 5647 additions and 1242 deletions

View File

@@ -105,7 +105,10 @@ pub fn run() {
id
}
};
// relay_url:KV 取,无则默认本地(df-miniapp config.ts:33 同源 localhost:8080)。
// relay_url:KV 取,无则默认本地(localhost:8080,本地开发 df-relay 默认监听)。
// settings value 契约模糊(JSON 序列化带引号或裸值并存,见 SettingsRepo get/set 不解析 JSON):
// 统一解析去引号 —— serde_json::from_str 处理 JSON 字符串值,失败(裸值)则 trim 首尾引号兜底,
// 确保拿到纯净 URL 供 connect_async(带引号 URL 解析失败致 connect 静默失败,relay 无 device 接入)。
let relay_url = state
.settings
.get("relay_url")
@@ -113,6 +116,10 @@ pub fn run() {
.ok()
.flatten()
.filter(|s| !s.is_empty())
.map(|raw| {
serde_json::from_str::<String>(&raw)
.unwrap_or_else(|_| raw.trim_matches('"').to_string())
})
.unwrap_or_else(|| "ws://localhost:8080/ws/device".to_string());
// token:固定常量(三端同源,对齐 df-relay relay.rs:37 DEFAULT_TOKEN)
let token = "devflow-relay-default-token".to_string();
@@ -157,10 +164,11 @@ pub fn run() {
},
);
// connect(失败非阻断,tunnel 可后续手动重连)。收发循环在 client 内部 spawn。
// connect(失败非阻断,supervisor 兜底重连)。收发循环在 client 内部 spawn。
// 注:on_command 用 clone 传入 connect(原值留给 supervisor 重连复用,Arc clone 廉价)。
match state
.tunnel
.connect(&relay_url, &device_id, &token, on_command)
.connect(&relay_url, &device_id, &token, on_command.clone())
.await
{
Ok(()) => tracing::info!(
@@ -168,7 +176,44 @@ pub fn run() {
device_id,
relay_url
),
Err(e) => tracing::warn!("[tunnel] 连接 relay 失败(非阻断): {}", e),
Err(e) => tracing::warn!("[tunnel] 连接 relay 失败(非阻断,supervisor 将重试): {}", e),
}
// ── supervisor:断线自动重连(根治 device 离线) ──
// df-tunnel 无内置 auto-reconnect(tunnel.rs:332 注释留外层 supervisor)。
// 桌面端进程重启 / 网络断 / relay 重启 → device 离线 → miniapp 命令 delivered=0
// → 点发无响应。supervisor 轮询 is_connected,断开则用保存参数指数退避重连,
// 复用同一 on_command 回调(逻辑不变)。task 永驻(supervisor 生命周期 = 应用生命周期)。
let mut backoff = std::time::Duration::from_secs(2);
loop {
tokio::time::sleep(std::time::Duration::from_secs(5)).await;
if !state.tunnel.is_connected() {
tracing::info!(
"[tunnel-supervisor] 检测到断开,尝试重连 url={} device_id={}",
relay_url,
device_id
);
match state
.tunnel
.connect(&relay_url, &device_id, &token, on_command.clone())
.await
{
Ok(()) => {
tracing::info!("[tunnel-supervisor] 重连成功,退避重置");
backoff = std::time::Duration::from_secs(2);
}
Err(e) => {
tracing::warn!(
error = %e,
backoff_secs = backoff.as_secs(),
"[tunnel-supervisor] 重连失败,退避后重试"
);
tokio::time::sleep(backoff).await;
// 指数退避上限 60s,防网络长故障时高频重连打 relay
backoff = (backoff * 2).min(std::time::Duration::from_secs(60));
}
}
}
}
});