kevin
0e622329a7
修复频道筛选框被遮挡:header+filter 包裹在 sticky 容器中一起固定
2026-08-07 19:38:00 +08:00
kevin
c107f6d6af
修复聊天卡片频道筛选框被 sticky header 遮挡的问题
2026-08-07 19:34:52 +08:00
kevin
d2b5832df3
频道筛选框从 topbar 移至聊天卡片内,ChatPanel v-model:channelFilter 双向绑定
2026-08-07 19:31:33 +08:00
kevin
4ce341208b
版本化数据库迁移系统:schema_migrations 表 + DBMigration 注册表,DBv1 修复 channel_id TEXT->VARCHAR(255) 解决 MySQL Error 1170
2026-08-07 19:26:18 +08:00
kevin
d919ea2c53
频道筛选:text_message 表增加 (channel_id, created_at) 复合索引,主页增加频道筛选输入框,服务端筛选+防抖重载,版本号 backend 1.1.0 / frontend 0.2.0
2026-08-07 19:10:49 +08:00
kevin
1c9f94dcf8
footer增加GitHub图标链接
2026-08-07 18:17:51 +08:00
kevin
362c8c7a57
节点列表去除横向滚动,公钥截断显示+复制按钮
2026-08-07 18:09:28 +08:00
kevin
ea2d33d1bf
加入版本显示
2026-08-07 17:37:58 +08:00
kevin
01aee47024
删除所有测试文件
2026-08-07 16:26:30 +08:00
kevin
7bc2e53ce6
屏蔽机器人消息
2026-07-02 11:02:48 +08:00
kevin
6052bf90ec
调用签到 🔧 注入时间
2026-07-01 12:43:05 +08:00
kevin
16d0d0ec0b
up
2026-07-01 12:36:55 +08:00
kevin
f11c2ed138
回复ai回复emoji的能力
2026-07-01 12:24:38 +08:00
kevin
04e105c6ba
更新迁移脚本
2026-07-01 12:12:23 +08:00
kevin
99fb474bcf
ai服务状态更新
2026-07-01 11:55:37 +08:00
kevin
f6fa167d76
更新ai服务提醒
2026-07-01 11:26:08 +08:00
kevin
716f711373
up 安装脚本
2026-07-01 11:05:40 +08:00
kevin
a75ab812d2
添加 MySQL 8 到 MySQL 5.7 数据库迁移脚本
2026-06-30 12:36:43 +08:00
kevin
01c7275763
admin 页面 MQTT 服务状态增加去重队列长度显示
2026-06-30 12:18:40 +08:00
kevin
4782e84c15
添加 MQTT 消息去重队列:Hook 层基于 payload+topic hash 去重,TTL 15 秒,定时清理
2026-06-30 12:10:29 +08:00
kevin
ca59c5f316
修改机器人hops为7
2026-06-29 10:43:18 +08:00
kevin and Claude Fable 5
6620192322
签到检查功能增强:返回签到时间和内容
...
问题:
- 用户询问'我什么时候签到的'时,AI 说'系统只记录是否签到,没有时间戳'
- 实际上数据库 signs 表有完整的 sign_time 和 sign_text 字段
解决方案:
- 修改 executeCheck 方法,改用 ListSigns 查询今天的签到记录
- 返回完整的签到详情:签到时间(HH:MM:SS格式)+ 签到内容
- 未签到时仍返回简单提示
改动内容:
- executeCheck 使用 ListSigns 替代 HasSignedOnDay
- 构建 ListOptions 查询今天的签到记录(过滤 NodeID + 时间范围)
- 返回格式:'XXX 今天已经签到过了。\n签到时间:10:30:45\n签到内容:上海-Kevin-GAT562签到'
- 更新测试验证返回内容包含时间和签到文本
- 更新 mockSignStore.ListSigns 支持 NodeID 和 Limit 过滤
使用效果:
- 用户:'我今天签到了吗?' → 返回是否签到 + 时间 + 内容
- 用户:'我什么时候签到的?' → 返回签到时间:10:30:45
测试:
- ✅ 未签到场景测试通过
- ✅ 已签到场景测试通过(验证时间和内容)
- ✅ 所有签到工具测试通过
- ✅ 项目编译成功
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com >
2026-06-23 21:47:16 +08:00
kevin and Claude Fable 5
cbb54c28ca
添加 QoS0 问题完整解决方案文档
...
添加综合文档总结所有修复和诊断工具:
- 问题描述和解决方案总览
- 快速诊断方法
- 常见原因和解决方案
- 文档索引
- 技术细节说明
- 性能指标对比
- 下一步行动指南
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com >
2026-06-23 21:43:36 +08:00
kevin and Claude Fable 5
bce6b70e8f
增强 MQTT 消息拒绝诊断功能
...
问题:
- TCP_NODELAY 修复了 TCP ACK 延迟,但设备仍然重发
- 需要确定是消息被服务器拒绝,还是设备端 bug
改进内容:
- OnPublish 中添加详细的拒绝日志输出
- 当消息验证失败时,输出 client_id、topic、qos、错误原因
- 当消息被屏蔽时,输出屏蔽类型和原因
- 帮助快速诊断 QoS0 重发的根本原因
新增文档:
- doc/QOS0_RETRANSMIT_ANALYSIS.md - 深度分析重发问题的各种原因
- doc/DIAGNOSTIC_GUIDE.md - 完整的诊断指南和解决方案
使用方法:
./meshtastic_mqtt_server --console-log-mqtt=true
观察日志中是否有:
[mqtt] PUBLISH rejected: ... - 消息被拒绝(服务器问题)
[mqtt] PUBLISH blocked: ... - 消息被屏蔽(配置问题)
如果没有 rejected/blocked 日志但仍重发,则是设备端 bug。
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com >
2026-06-23 21:42:50 +08:00
kevin and Claude Fable 5
57cca6bb7a
签到工具新增检查功能:修复状态误判问题
...
问题:
- 用户询问'我今天签到了吗'时,AI基于对话历史判断而非查询数据库
- 导致明明没签到,AI却说已经签到了(误判)
解决方案:
- 新增 action=check 操作,专门用于检查当前节点今天是否已签到
- 直接调用 HasSignedOnDay 查询数据库,返回准确的签到状态
- AI 现在会强制调用工具查询,而不是根据记忆猜测
改动内容:
- 工具定义中添加 check 操作类型
- 实现 executeCheck 方法,查询数据库并返回明确状态
- 添加完整的单元测试(未签到/已签到两种场景)
- 更新文档说明 check 操作的使用
使用示例:
- 用户:'我今天签到了吗?'
- AI 调用:{"action": "check"}
- 返回:'XXX 今天还没有签到。' 或 'XXX 今天已经签到过了。'
测试:
- ✅ 未签到场景测试通过
- ✅ 已签到场景测试通过
- ✅ 所有签到工具测试通过
- ✅ 项目编译成功
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com >
2026-06-23 21:37:44 +08:00
kevin
bd25b79724
up
2026-06-23 21:27:52 +08:00
kevin and Claude Fable 5
cd5dcb29f5
新增活跃度查询工具
...
功能:
- 查询指定时间范围内的活跃节点数和活跃人数
- 活跃节点:统计 nodeinfo 表 updated_at 字段
- 活跃人数:统计 text_message 表按 from_id 去重的用户数
使用场景:
- 用户问'现在有多少人活跃'时 AI 调用此工具
- 用户问'当前有多少节点在线'时 AI 调用此工具
- 支持附带时间条件,默认1小时,最大24小时
参数:
- hours: 查询最近N小时,默认1小时,最大24小时
- query_type: both/nodes/users,默认 both
实现:
- internal/agents/active/active.go - 工具主逻辑
- internal/store/active_store.go - 数据库查询方法
- 完整的单元测试,所有测试通过
- 在 ai/service.go 中注册工具
测试:
- ✅ 默认查询(1小时,both)
- ✅ 指定时间查询(6小时、24小时)
- ✅ 仅查询节点/人数
- ✅ 时间限制验证
- ✅ 项目编译成功
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com >
2026-06-23 21:26:14 +08:00
kevin and Claude Fable 5
2f83308dce
修复 LLM Provider 配置热更新问题
...
问题:在 /admin/llm/api 页面修改 AI 提供商配置后,配置没有立即生效,AI 依然使用旧的提供商工作
根本原因:
- LLM Provider 配置在程序启动时加载到内存 (llm.State)
- 管理后台修改配置时,只更新了数据库,内存配置未更新
- AI 继续使用内存中的旧配置
解决方案:
1. 为 llm.State 添加动态更新方法 (UpdateProvider/AddProvider/RemoveProvider)
2. 在 AI Service 中暴露配置更新接口,支持运行时重新加载
3. 在配置保存后自动触发内存配置重新加载
4. 创建新的 LLM Client 使新配置立即生效
关键特性:
- 线程安全:使用 sync.RWMutex 保护并发访问
- 容错处理:重新加载失败不影响数据库更新
- 无需重启:配置修改后立即生效
- 完整测试:添加单元测试验证功能
修改文件:
- internal/llm/state.go: 添加配置更新方法
- internal/ai/service.go: 添加配置重新加载接口
- internal/llmadmin/admin_llm_routes.go: 配置更新时触发重新加载
- internal/web/web.go: 传递 AI Service 到路由
- main.go: 连接组件
- internal/llm/state_test.go: 新增单元测试
- internal/web/map_tile_proxy_routes_test.go: 修复测试
测试:
- ✅ 所有现有测试通过
- ✅ 新增测试覆盖核心功能
- ✅ 项目成功编译
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com >
2026-06-23 21:13:31 +08:00
kevin
c50c7a57d7
签到
2026-06-23 21:04:31 +08:00
kevin and Claude Fable 5
ec24e70275
修复 MQTT QoS0 消息重发问题
...
问题:
- 设备发送 QoS0 消息后服务器未及时响应 TCP ACK
- 导致设备重发 3 次
- 有时能一次成功,有时需要多次重发
根本原因:
- TCP Nagle 算法延迟小数据包(包括 TCP ACK)40-200ms
- QoS0 不需要 MQTT 应用层 PUBACK,但依赖 TCP 层 ACK
- TCP ACK 延迟触发客户端 TCP 重传机制
解决方案:
- 在 OnConnect hook 中设置 TCP_NODELAY
- 禁用 Nagle 算法,确保 TCP ACK 立即发送
- TCP ACK 延迟从 40-200ms 降低到 ~0.05ms
测试:
- 添加 tcp_nodelay_test.go 验证修复
- 平均往返延迟:54µs
- 符合 MQTT broker 行业最佳实践(Mosquitto、EMQX、HiveMQ 均默认启用)
文档:
- doc/TCP_ACK_FIX_CN.md - 中文详细说明
- doc/TCP_ACK_FIX.md - 英文详细说明
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com >
2026-06-23 21:04:00 +08:00
kevin
cfe4ef04d7
修复消息重复问题
2026-06-20 12:32:05 +08:00
kevin
260bd12ec8
修复重复消息bug
2026-06-20 12:24:58 +08:00
kevin
dc5d9bf9a6
签到ai基本完成
2026-06-20 02:20:29 +08:00
kevin
54df706ca7
基本完成
2026-06-20 02:15:15 +08:00
kevin
fd766be731
up
2026-06-20 01:45:24 +08:00
kevin and Claude
94835a5f1d
fix(llm): 启用工具时最终回复改用主回复配置的 system prompt
...
此前工具循环把工具路由 prompt 同时塞进最终回复和路由决策,导致用户在
「主 AI 回复配置」编辑的系统提示词被工具路由 prompt 覆盖、未加载到回复。
现在 finalMessages 用主回复 prompt,decisionMessages 用工具路由 prompt。
Co-Authored-By: Claude <noreply@anthropic.com >
2026-06-20 00:53:21 +08:00
kevin and Claude
b9c2b8f0bd
fix(llm): 工具路由配置修改后立即生效,不再硬编码 system prompt
...
toolrouter 每轮调用都从 DB 读取最新配置,/admin/llm/api 保存后下一条消息即生效,
无需重启。ai.NewService 启动时从 DB 加载初始配置,移除硬编码 prompt 覆盖用户配置的问题。
Co-Authored-By: Claude <noreply@anthropic.com >
2026-06-20 00:41:28 +08:00
kevin
f5dacdce19
up
2026-06-19 23:39:30 +08:00
kevin
0ef477b15f
不明bug
2026-06-19 23:30:33 +08:00
kevin
fd66162d57
feat(mqtt): client_id 冲突时自动加 4 位随机后缀
...
同一 Meshtastic 节点被多台 Android 同时连时,broker 按 [MQTT-3.1.4-3]
强制顶号会让两边互相踢,日志被刷屏且无法稳定收发。
OnConnect 里检测 server.Clients 中是否已有未关闭的同 ID 客户端,命中
就把当前连接的 cl.ID 改成 "原ID-xxxx"(4 位 hex),避开顶号路径。
打 mqtt_client_id_renamed 日志记录原/新 ID 与双方 remote。
2026-06-19 22:51:34 +08:00
kevin
6cec82235a
fix(map): 节点右键菜单不再触发地图空白菜单
...
leaflet 与自定义的 handleMapContextMenu 都挂在 mapEl 容器上,普通
stopPropagation 不能阻止同节点上的后续监听器。改用
stopImmediatePropagation 并显式重置 menuMap,确保右键 marker 只显示
节点菜单。
2026-06-19 21:00:11 +08:00
kevin
2afd890de4
批量删除节点,一键屏蔽ip
2026-06-19 20:37:19 +08:00
kevin
b56cfb7b1e
新增删除节点功能
2026-06-19 20:03:25 +08:00
kevin
3fbc52c6c1
up
2026-06-19 19:08:44 +08:00
kevin
01b0ad1999
up
2026-06-19 18:51:28 +08:00
kevin
5aae81c831
up
2026-06-19 18:17:27 +08:00
kevin and Claude
8e7d11a162
feat(llm): 处理完成的消息自动软删除并隐藏删除按钮
...
- MarkAsProcessed 在写入 reply/processed_at 的同时设置 deleted_at,
避免 /admin/llm 队列页堆积已处理消息(仍可勾选"包含已删除"查看)
- 前端列表中已删除的消息行隐藏删除按钮,改为显示灰色"已删除"标签
Co-Authored-By: Claude <noreply@anthropic.com >
2026-06-19 17:50:56 +08:00
kevin and Claude
8bbe40c230
feat(llm): console_log.llm 控制可读单行流程日志,并追踪路由 AI 决策
...
autoreply.Service 增加 consoleLog 字段和 logf 辅助;processMessage 中
原本的 printJSON map dump 全部替换为 [llm] 前缀的单行 key=value 输出。
关闭开关时整条链路静默。
把原本传 nil 给 toolrouter.RunAgentToolLoop 的 emit 接进来,将
stream.Frame trace 帧渲染为可读行,区分三类来源:
- 主 AI:main_model / completion / 最终 reply
- 路由 AI:router=<model> prepare/decide iter=N → call_tools=[...] / no_tool
- 工具调用:tool=<name> args=... / result(Nms)=... / ERROR ...
ai.Config 增加 ConsoleLog 字段,由 main.go 传入 cfg.ConsoleLog.LLM,
再透传给 autoreply.NewService。
Co-Authored-By: Claude <noreply@anthropic.com >
2026-06-19 17:45:21 +08:00
kevin and Claude
49a287e6e7
feat: console_log.meshtastic 控制 packet 控制台输出;新增每客户端报文统计
...
- ConsoleLogConfig 增加 Meshtastic 字段(默认 true);旧配置自动补齐
- meshtasticFilterHook 增加 packetConsoleLog;OnPublish 中根据开关调用
新的 printMeshtasticRecord 输出可读单行(key=value、按 type 着色),
替代原来的 JSON dump;事件型 printJSON 调用保持不变
- 新增 internal/mqttforward/ClientStats,按 client_id 累计 in/out 报文计数
- meshtasticFilterHook 多挂 OnPacketRead / OnPacketSent / OnDisconnect
事件,用于增减计数;Provides() 同步声明
- AdminMQTTClient JSON 视图删除 RemoteHost/RemotePort,新增
packets_in / packets_out;前端 types.ts、AdminDashboard.vue 同步更新
Co-Authored-By: Claude <noreply@anthropic.com >
2026-06-19 17:09:00 +08:00
kevin and Claude
937580e24f
feat(mqtt): console_log.mqtt 控制连接/断开/订阅/取消订阅日志
...
为 meshtasticFilterHook 增加 consoleLog 字段;当 console_log.mqtt=true 时
向 stderr 输出 4 类事件(带 client_id、username、remote IP:port):
- OnSessionEstablished → [mqtt] connect ... (认证后才打,避开被 IP 屏蔽拒掉的客户端)
- OnDisconnect → [mqtt] disconnect ... (含 expire 和 mochi 上报的断开原因)
- OnSubscribed → [mqtt] subscribe ... (每个 filter 一行)
- OnUnsubscribed → [mqtt] unsubscribe ... (每个 filter 一行)
Provides() 同步多声明这 4 个事件类型;关闭开关时各 handler 立即返回。
Co-Authored-By: Claude <noreply@anthropic.com >
2026-06-19 16:21:55 +08:00