qing
34cd295005
feat(core): mgmt 接入 core 进程管理 + 管理员认证
...
- gateway 新增 POST /admin/verify 验签接口,供内部服务校验管理员 Token
- core 的 /list /exec /kill 接入管理员认证(调用 gateway 验签,fail-closed)
- gateway 代理 opened 白名单加入 core:5200
- mgmt 管理页显示当前用户与角色,进程页接入 core 进程管理接口
2026-08-04 20:00:24 +08:00
qing
c8812dd27c
static: 迁移 mgmt 前端到 static/public 并移除静态列表
...
将 mgmt Jinja2 模板原封不动迁移为纯静态 HTML/CSS,
删除用户列表与模块列表,改为静态提示文字。
2026-08-04 19:23:57 +08:00
qing
3460a157d0
docs: 新增 libth 安全审计与 aibox 开放版开发计划
2026-08-04 19:02:22 +08:00
qing
fe618be1fa
fix(captcha): 验证码存储容量上限防 OOM (P1-1)
...
新增 MAX_STORE_SIZE(默认 10000,可配置 max_store/CAPTCHA_MAX_STORE),
_handle_image 在清理过期项后检查容量,超限拒绝生成并返回错误,
防止攻击者高频生成验证码填满内存。
2026-08-04 18:40:36 +08:00
qing
4d9bb5d940
fix(libhttp): WebSocket 发送/代理队列上限防 OOM (P1-6)
...
- 新增 setMaxWsQueueSize()(default 1000),每个入队点检查
- wsSend / onProxyReadClient / onProxyReadBackend 超限关闭连接
- 更新审计文档 P1-6 状态、README v3.4.3
2026-08-04 18:27:50 +08:00
qing
37c6d401d6
fix(libhttp): 服务器读超时防 Slowloris (P1-4)
...
- 新增 setHeaderTimeout()(default 10s) / setReadTimeout()(default 30s),对齐 WAF
- doSSLHandshake 设置头超时覆盖握手,doRead 拆分为 async_read_header (头超时) + async_read (体超时)
- doWsRead 每次读取设置空闲超时,自动清理长期空闲连接
- 更新审计文档 P1-4 状态、README v3.4.2
2026-08-04 17:39:27 +08:00
qing
507054c4b2
fix(libhttp): WebSocket 单条消息大小限制防 OOM (P1-3)
...
- 新增 setMaxWsMessageSize/getMaxWsMessageSize(默认 16MB,与 Beast 默认一致)
- 服务端 doWsUpgrade/doWssUpgrade 与代理流 onProxyConnect/onProxySslHandshake 创建后调用 read_message_max
- 超限消息由 Beast 在分配内存前拒绝并关闭连接
- 更新审计文档 P1-3 状态、README v3.4.1
2026-08-04 16:03:06 +08:00
qing
85e0d0740b
fix(libhttp): HttpClient 响应大小限制防 OOM
...
- request_stream_sync 改为真流式,按块回调不二次缓冲
- 新增 set_max_response_size/get_max_response_size(默认 10MB,对齐 WAF)
- write_callback 超限返回 0 中止传输并抛异常
- 更新审计文档 P1-2 状态、README v3.4.0、INDEX 移除不存在的文档
2026-08-04 15:12:06 +08:00
qing
dc52ec13ad
fix(aibox): 工具结果超长仅返回提示,隔离各会话命令执行器
...
- 工具结果超过 max_result_length 时不再保留截断内容,仅返回提示信息,避免超大结果污染 AI 上下文
- 每个任务/WebSocket 连接使用独立 SubprocessCommandExecutor,避免 cancel() 误杀其他任务/用户正在运行的子进程
2026-08-04 13:11:37 +08:00
qing
5ff1dfa4d2
系统状态技能
2026-08-04 12:57:27 +08:00
qing
2eb6d3c310
生成技术手册技能
2026-08-04 12:46:50 +08:00
qing
d921f84b83
feat(aibox): WebSocket连接用户独立AI实例,支持多用户并发对话
...
- 每个连接创建独立DeepSeekChat实例,拥有独立messages/工具注册表/消息锁
- 对话状态与并发控制从全局改为会话级,多用户可同时与AI对话互不干扰
- 中断/重置/重载提示词等命令改为针对当前连接的会话AI
- 技能管理器懒加载共享,避免每个连接重复扫描技能
2026-08-04 11:44:57 +08:00
qing
69a8eee192
feat(aibox): 调度器任务间上下文隔离
...
- 每个定时任务创建独立DeepSeekChat实例,拥有独立messages/工具注册表/消息锁
- 任务与WebSocket主对话互不干扰,消除并发冲突与上下文污染根因
- 共享技能管理器懒加载一次供所有任务复用,避免重复扫描技能
- DeepSeekChat支持传入skill_manager复用,任务实例history_manager=None不污染历史
2026-08-04 09:23:51 +08:00
qing
fa9679b7a6
fix(aibox): 修复并发线程导致对话历史污染引发HTTP 400错误
...
- 添加线程锁(RLock)保护 self.messages,防止WebSocket与调度器线程并发修改
- 重写 _repair_tool_pairs 方法,支持穿透system消息查找tool响应、去重、清理孤立tool消息
- 新增 _validate_enhanced_messages API调用前最终校验,就地修复消息结构
- 调度器执行定时任务前先cancel+wait锁释放,避免与WebSocket对话冲突
- /new命令和global_exit_handler改用锁保护的reset_conversation,不再裸改messages
- 新增 is_busy() 非阻塞方法供外部判断AI是否正在处理中
2026-08-04 09:11:31 +08:00
qing
53ddcb364f
feat(aibox): 创建/安装技能工具统一生成 .md 扩展名 + 下线旧版 smtp.py
...
- CreateSkillTool/InstallSkillTool 改为生成带 .md 扩展名的技能文件,与人格技能文件规范一致
- 同步更新 7_extension_skills.md 模板与工具描述
- 删除旧版 smtp.py(P0-1)并同步审计文档与 README
2026-08-04 08:26:57 +08:00
qing
fb485ebac4
fix(libhttp): 修复P1-5静态文件路径遍历 + 同步审计文档
...
- 新增 isSafeStaticPath() 校验静态文件路径,拒绝 ..、空字节、非/开头及URL编码遍历(%2e/%2f/%5c)
- handleRequest 静态文件服务前校验 target_path
- 审计文档标记 P1-5 已修复
2026-08-04 00:04:55 +08:00
qing
da4957c52d
fix(libhttp): 请求体大小限制可配置并超限返回 413 (P1-1)
2026-08-03 23:57:00 +08:00
qing
b37bf255d9
fix(libhttp): 删除遗留 WebSocketServer/WebSocketClient 并同步 CMakeLists 与 Makefile
2026-08-03 23:46:10 +08:00
qing
2f5fe8baaa
docs(security): 新增 libhttp 模块安全审计报告
2026-08-03 23:42:32 +08:00
qing
2e3f07bf4f
docs(gateway): 审计文档行号纠偏并补充 CORS 白名单死代码根因
...
- 修正 gateway 审计文档中因代码演进漂移的行号引用(handleProxy/handleLogout/wrapperHttp/限流/TLS/路径防护等)
- 补充 P2-3 CORS 根因:_CORS_ORIGINS 白名单已读取但 OPTIONS 预检由 libhttp 处理,白名单未生效
- 修正 README 中 OPTIONS 预检描述(反射请求 Origin 而非通配 *)及 CORS 配置失效提示
2026-08-03 23:37:47 +08:00
qing
028e0e0806
docs(security): 删除全局审计文档并将问题并入各模块文档
...
- 各模块专属 P0/P1/P2 问题已分发到 docs/security/ 下各模块审计文档
- gateway 补充 P1-6(反向代理响应无大小限制)、P2-3(CORS 通配)、P2-4(HTTP 无超时)
- 删除全局 SECURITY_AUDIT_20260801.md,避免重复
2026-08-03 23:32:28 +08:00
qing
37c50ed517
fix(static): 获取邮箱验证码后保留已输入的图形验证码
...
refreshCaptcha 增加 preserveInput 参数,获取验证码后的自动刷新不再清空图形验证码输入框,避免误清空用户输入
2026-08-03 23:11:10 +08:00
qing
02904f711e
fix(aibox): 修复工具调用配对缺失导致的 insufficient tool messages 400
...
当 assistant 携带 tool_calls 但对应 tool 响应缺失(工具被中断/压缩丢弃)时,
下一次请求报 400。新增 _repair_tool_pairs 在构建请求前补齐缺失的 tool 响应。
2026-08-03 23:05:28 +08:00
qing
d24066369b
refactor(aibox): 解耦大模型调用,新增 llm_client 抽象层以支持多厂商切换
...
将 think_and_respond 与 _compress_via_llm 中的直接 DeepSeek API 调用
收敛到 LLMClient 抽象层(DeepSeekClient 实现 + create_llm_client 工厂),
统一流式事件格式,为子代理/多模型切换预留扩展点;配置新增 api.provider。
2026-08-03 23:03:03 +08:00
qing
417fda5479
refactor(aibox): 文件/网络操作工具改为返回命令行指引并移除beautifulsoup4依赖
2026-08-03 22:52:12 +08:00
qing
fb5920d89f
feat(gateway): 新增重置密码接口并改造前端 forgot 页对接
...
- gateway 新增 POST /reset_password:复用注册校验链(限流/密码强度/邮箱格式/CAPTCHA/邮箱验证码),最后一步由创建用户改为 UPDATE Users SET password_hash,用户不存在时统一返回成功防枚举
- gateway 新增 POST /reset/send_code:CAPTCHA 强制 + 邮箱双窗口限流,定制重置密码文案
- 前端 forgot.html 弃用 static 被禁用的 /api/proxy_* 接口,对接 gateway 新接口,并改为中文 register.html 风格
2026-08-03 22:40:43 +08:00
qing
dd4fef6dee
fix(pymsg): 异常信息脱敏与JSON深度/大数字限制,防信息泄露与DoS
2026-08-03 22:30:17 +08:00
qing
87f209af73
fix(pymsg): 增加连接数与线程池队列上限,防资源耗尽
...
- P1-1: MsgServer 新增 max_connections(默认1000),_accept_client 超限
直接拒绝并关闭新连接,防连接耗尽攻击
- P1-2: 新增 _BoundedThreadPoolExecutor + max_queue_size(默认1000),
慢 handler 时任务排队超限即拒绝并断开连接,防内存无限增长
同步更新审计报告 P1-1/P1-2 状态,修复率 18.75% -> 25%
2026-08-03 22:25:32 +08:00
qing
47ab9f2fe6
fix(pymsg): 使用 deadline 模式修复 recv 总超时绕过(Slowloris DoS)
...
_recv_exact 从单次 sock.settimeout() 改为整体 deadline 模式:
header 与 payload 共享同一 total deadline,每次 recv_into 前按剩余
时间收紧超时,逐字节发送无法刷新 deadline,半开连接被及时关闭。
同步更新 pymsg 安全审计报告 P0-1 状态,修复率 6.25% -> 12.5%。
2026-08-03 22:15:44 +08:00
qing
ac16d89150
docs(aibox): 添加文件/网络操作命令行化开发计划
2026-08-03 22:05:52 +08:00
qing
f53085b2a6
fix(static): 禁用 yhdet 系列功能并迁移数据库访问到 db 服务
...
- 注释禁用 yhdet OAuth 相关常量、辅助函数和视图函数(yhdet_callback/yhdet_login/yhdet_verify/proxy_send_code),消除 P0-2/P0-3/P0-4/NEW-1/NEW-2 风险
- YHDET_SECRET 置空并标注已失效;PRIVATE_SECRET 与 YHDET_PRIVATE_API 一并注释
- 新增 _db_call() 辅助函数,api_check_user 改经 pymsg 调 db 服务,不再直连 SQLite
- 修复注册页验证码:点击获取邮箱验证码时图形验证码输入框被清空的问题
- 更新 static 安全审计报告,修复率 25% → 65%
2026-08-03 22:05:02 +08:00
qing
4749e58eeb
fix(static): 禁用无认证的 /api/reset_password 接口
2026-08-03 14:26:06 +08:00
qing
5fbe3ed5e4
docs(security): 更新全部模块审计报告,添加代码验证记录
...
逐模块对照实际代码验证审计报告中的问题修复状态,添加代码验证记录、逐条验证结果、修复率统计。合并aibox两份审计报告,删除重复文件。修复率:confs 61% > dnfs 60% > ai_review 50% > smtp 37.5% > db 33% > core 12.5% > gateway 12.5% > pymsg 6.25% > static 5% > captcha/aibox/BotOps 0%
2026-08-03 14:12:45 +08:00
qing
d3158c2420
docs: add date suffix to remaining documentation files
...
- Rename SECURITY_HARDENING_PLAN.md -> SECURITY_HARDENING_PLAN_20260803.md
- Rename aibox_SECURITY_AUDIT.md -> aibox_SECURITY_AUDIT_full_20260801.md
- Update INDEX.md links accordingly
2026-08-03 13:26:38 +08:00
qing
a7a78d1424
docs: aggregate project documentation under docs/ with unified index
...
- Move all per-module security audit reports to docs/security/
- Move code review logs to docs/reviews/, analysis reports to docs/reports/
- Add docs/INDEX.md as single entry point for all project documentation
- Add documentation management conventions section to README.md
- Clean up empty per-module docs/ directories
2026-08-03 13:21:48 +08:00
qing
9dbe395484
docs: 添加内网通信安全加固开发计划
2026-08-03 13:13:52 +08:00
qing
9f440ee884
fix(db): 监听地址改为 127.0.0.1 修复内网暴露
2026-08-03 13:10:17 +08:00
qing
4449a23ba1
docs(lci): 完善 LCI 图形系统架构文档
2026-08-02 21:37:02 +08:00
qing
84fb370da8
docs(lci): 添加 LCI 帧缓冲图形界面能力介绍到 README
2026-08-02 21:18:19 +08:00
qing
38a6e815f0
fix(static): __view.html 改为绝对路径,修复子目录下 CSS/JS 404
2026-08-02 16:41:08 +08:00
qing
c58ef2b873
fix(static): 修复令牌刷新死循环 + 补全 index/aibox 令牌管理
...
- expired estimate 改用 created_at 替代 iat,与网关校验逻辑一致
- index.html 和 aibox.html 补全 token_manager.js 引用
2026-08-02 16:11:23 +08:00
qing
52052e51a8
feat(aibox): 在pre_prompt中新增情绪感知提醒
...
每轮首轮对话的用户输入前,新增【情绪感知提醒】段落,引导AI:
- 识别用户情绪状态并共情回应
- 按情绪状态调整回应策略(安抚/分享/道歉)
- 用户要求特定情绪模式时搜索对应技能
2026-08-02 14:30:20 +08:00
qing
ffbe076a32
feat: add execute method to ExpressEmotionTool
2026-08-02 14:17:33 +08:00
qing
054f65f858
增加智能体生气的模板
2026-08-02 13:54:58 +08:00
qing
918f3ea32a
fix(aibox): reasoning展示严格遵循配置文件reasoning_enabled开关
...
之前即使reasoning_enabled=false,模型自发返回的reasoning_content
仍会被动态展示——配置只管了API请求参数,不管展示逻辑。
现在添加constants.REASONING_ENABLED门控,关着时静默忽略。
2026-08-02 13:26:34 +08:00
qing
b216535757
comment
2026-08-02 13:21:45 +08:00
qing
45db2f780b
refix core initialize list
2026-08-02 12:56:14 +08:00
qing
c1724ccea9
fix(redirect80): extract .content from confs RPC response dict
...
RpcClient.call() returns the data dict, not a raw string.
configparser.read_string() expects str, hence TypeError.
Now uses .get("content") to unwrap the ini text.
2026-08-02 12:52:51 +08:00
qing
f9c02cd6ad
feat(redirect80): new HTTP→HTTPS redirect service on port 80
...
Pure Python stdlib http.server + ThreadingMixIn, zero web framework deps.
- GET/HEAD → 301, POST/PUT/DELETE/PATCH → 308
- Reads Host header, strips port, redirects to https://{host}{path}
- Config via confs (retry_on_refused, hard dependency) + env var override
- Logs via log_client → db Logs table (fail-safe async batch)
- Port 80 privilege via setcap cap_net_bind_service in _run.sh
2026-08-02 12:50:23 +08:00
qing
c7364286b7
fix(static): getNode仅401跳登录,其他异常提示原因并上抛
2026-08-02 12:19:02 +08:00
qing
2e210e4729
chore(db): gitignore 忽略 SQLite WAL/SHM 运行时临时文件
2026-08-02 11:49:42 +08:00
qing
5a3dff9026
fix(static): 修复dnfs导航栈污染与返回键栈空越界
...
- 点卡片/返回上一层前先经 confirmLeaveIfDirty 守卫确认,用户选择
不放弃输入时不再执行 push/pop,stack 保持原样
- 返回键目标 id 判断由 length>=0(恒真,空栈取到 undefined)改为
length>0,空栈正确回根节点 0
2026-08-02 11:46:51 +08:00
qing
8200cbfba7
refix
2026-08-02 01:19:56 +08:00
qing
192610615e
feat(captcha): 接入 confs 配置中心并迁移字体路径
...
- confs/configs/captcha.ini: 新增 captcha 配置 (server + captcha 段, 含 font_path)
- captcha/log_client.py: 新增日志客户端副本 (service_name=captcha)
- captcha/captcha_service.py: 接入统一的 confs 配置加载模式
(confs 强依赖 retry_on_refused -> 环境变量覆盖 -> 完整性校验)
- CAPTCHA_LEN/CAPTCHA_TTL 改为可配置
- 字体路径迁移到 confs, 新增 CAPTCHA_FONT_PATH 环境变量覆盖与 PIL 回退兜底
- 关键路径 (启动/生成/校验失败) 接入 log_client 日志上报
2026-08-02 01:09:44 +08:00
qing
2bb1d69d8a
feat(static/aibox.js): 同步BotOps修复到Web前端
...
同步以下修复:
1. endReasoning()/abortReasoning() 结束后清除引用(DOM保留显示),
多轮工具调用时每轮创建独立思考区域,按时间顺序分布
2. 新增 breakAi() 分段函数,处理 ai_break 信号:工具调用前分段
AI文本,后续chunk创建新气泡,避免思考区域被夹在AI文本中间
3. line消息过滤前缀扩展:增加分析工具结果/需要调用工具等
4. 未知消息类型fallback从appendAi改为addTaskLine,防止非AI内容污染聊天区
2026-08-01 22:19:54 +08:00
qing
392a734707
fix(ai_review): 添加内容大小限制和频率限制
...
/review: 10KB内容上限(413)、30次/分钟/IP(429);/rag/feedback: 5次/分钟/IP。使用滑动窗口限流器,优先取X-Forwarded-For作为客户端IP。
2026-08-01 22:12:58 +08:00
qing
89b374c21d
fix(pymsg): 捕获 UnicodeDecodeError 防止同步模式服务崩溃
...
recv() payload.decode("utf-8") 抛出 UnicodeDecodeError(ValueError子类)不在 _handle_client 异常捕获列表中,同步模式(workers=0)下收到无效UTF-8字节会导致整个服务进程崩溃。修复:recv()中将UnicodeDecodeError包装为ConnectionError;_handle_client()异常列表增加防御性兜底。
2026-08-01 22:11:38 +08:00
qing
af5cd02663
fix(aibox/botops): 思考区域按时间顺序分布,不再全部堆在顶部
...
问题根因:
1. ChatView.end_reasoning() 不清空 _reasoning_widget 引用,导致
多轮工具调用时 start_reasoning() 直接 return,所有轮次的思考
内容都被追加到第一个思考区域(在聊天区最顶部)。
2. AI widget 在工具调用期间不重置,导致后续轮次的思考区域被
挂载在AI widget中间,顺序混乱。
修复:
1. end_reasoning()/abort_reasoning() 更新标签后清除引用(widget
保留在DOM显示),下一轮 reasoning_start 创建新的思考区域。
2. 新增 ai_break 协议信号:服务端在工具调用执行前发送,前端
break_ai() 清除AI widget引用(保留已显示内容),后续chunk
创建新的AI widget,确保思考区域按时间顺序插入在两段AI文本之间。
3. ai_break 前flush chunk_buffer,防止工具调用前的最后文本片段丢失。
2026-08-01 21:10:42 +08:00
qing
763faf9c83
Merge branch 'dev_qing' of https://git.cancerai.top/qing/micro_servers into dev_qing
2026-08-01 21:02:49 +08:00
qing
f3d06252bb
fix(aibox/botops): 修复两处重复输出根因
...
1. 侧栏重复:_handle_tool_calls 中 msg_type in ("line", "complete")
将流式工具末尾的 complete 信号也当作 line 转发,导致所有支持
流式输出的工具(get_current_time、run_command、read_file等20+个)
结果在侧栏显示两次。改为仅转发 "line" 类型。
2. 聊天区Markdown列表重复:Textual 的 Markdown.append() 在 chunk
边界切断 Markdown 语法(如列表项 "- "被拆成两个chunk)时,增量
解析可能导致内容重复渲染。改为累积完整文本后调用 update() 整体
重新解析,避免增量解析的边界问题。
2026-08-01 21:01:31 +08:00
qing
b60ac06d55
Merge branch 'dev_qing' of https://git.cancerai.top/qing/micro_servers into dev_qing
2026-08-01 20:57:02 +08:00
qing
66963092a3
feat(static): 优化社区首页 — Hero首屏+特性卡片+悬浮毛玻璃导航,CTA随登录态切换
2026-08-01 20:56:39 +08:00
qing
27ab50ae68
fix(aibox/botops): 修复重复输出问题
...
1. 服务端:is_continuation(工具调用后递归继续)时不再重复发送
"思考中"提示和reasoning_start信号,避免多轮工具调用时侧栏
出现多条冗余"思考中"消息
2. BotOps:line消息过滤前缀从5个扩展到9个,过滤掉"分析工具结果"
"需要调用工具"等被后续具体信息覆盖的过渡提示
3. BotOps:移除危险的fallback分支(未知消息类型直接append到AI
聊天区),改为写入侧栏日志,防止非AI内容污染回复
2026-08-01 20:53:40 +08:00
qing
f701730016
fix(aibox): 修复中断信号延迟生效问题,确保Ctrl+C能立即中断AI响应
...
根因:WebSocket消息接收循环使用await串行处理,导致interrupt消息在
AI整段对话完成后才被读取和处理。
修复内容:
1. 消息接收与处理解耦:用create_task异步处理消息,不再await阻塞接收循环
2. cancel()直接同步调用而非通过run_in_executor,消除线程池调度延迟
3. 强制关闭response.raw底层socket连接,中断阻塞的iter_lines() recv()
4. 添加_is_processing_message标志防止多消息并发污染对话历史
5. 连接关闭时自动取消正在进行的处理任务
2026-08-01 14:55:49 +08:00
qing
f319686571
feat(static): aibox Web客户端重写为移动端专版
...
- 移除桌面端媒体查询与限宽居中,任务面板固定为抽屉形态
- 新增 enterkeyhint=send、overscroll-behavior、tap-highlight 等移动端触控优化
- 配合已提交的中断机制改动,协议与 BotOps 保持兼容
2026-08-01 14:17:36 +08:00
qing
08f737ba2c
fix(static): aibox Web客户端适配中断机制(Ctrl+C可靠停止)
...
问题(与BotOps v1.3修复一致):
- interrupt_ack只显示系统消息,没有立即收尾前端状态
- 思考区域一直停留在"💭 思考中..."状态(服务端中断不发reasoning_end)
- AI状态未重置,残留reasoning片段可能重新创建思考区域
修复:
- 新增abortReasoning()函数:中断时更新思考区域标签为"🛑 思考已中断"(保留已展示内容)
- appendReasoning()增加aiActive===false检查,中断后丢弃残留片段
- interrupt_ack处理改为:先abortReasoning()更新思考区域,再finishAi()收尾AI状态,最后显示通知
- 中断后残留chunk/reasoning/complete均被安全忽略(appendAi已有aiActive检查,finishAi幂等)
2026-08-01 14:14:53 +08:00
qing
c7ef7e715c
fix(botops): v1.3 - 适配服务端中断机制,Ctrl+C立即可靠停止
...
问题:收到interrupt_ack时仅显示系统通知,没有立即收尾前端状态:
- 思考区域一直停留在"💭 思考中..."状态,不会更新
- AI回复状态未重置,后续残留chunk可能继续追加
- 服务端不发送reasoning_end,思考区域无法正常结束
修复:
- ChatView新增abort_reasoning()方法:中断时将思考区域标签更新为"🛑 思考已中断"(保留已展示内容)
- append_reasoning()增加_ai_finalized检查,中断后丢弃残留思考片段,防止重新创建思考区域
- app.py收到interrupt_ack时:先abort_reasoning()更新思考区域,再finish_ai()收尾AI状态,最后显示系统通知
- 中断后服务端发来的残留chunk/reasoning/complete均被安全忽略(append_ai已有_finalized检查,finish_ai幂等)
- 更新README v1.3日志
2026-08-01 14:12:27 +08:00
qing
9d737897df
fix(aibox): v2.6 - 修复Ctrl+C中断无法停止服务器的问题
...
问题根因:
1. WebSocketHandler.handle_message 完全没有处理 interrupt 消息类型(前端Ctrl+C发送的消息被丢弃)
2. DeepSeekChat 缺少取消机制,阻塞的 API 请求(iter_lines)和子进程无法被中断
修复方案 - 三层取消机制:
1. threading.Event 取消标志:流式响应循环每轮检查 _is_cancelled(),工具调用前检查
2. HTTP连接关闭:保存 _current_response 引用,cancel() 时调用 response.close() 中断 iter_lines()
3. 子进程终止:SubprocessCommandExecutor 添加 cancel() 方法,保存 _current_process,cancel时kill
修改内容:
- DeepSeekChat: 添加 _cancel_event/_current_response/_command_executor 字段,cancel()/_is_cancelled()/_check_cancelled() 方法
- SubprocessCommandExecutor: 添加 __init__/_process_lock/cancel(),execute()/execute_streaming() 中设置和清除进程引用
- WebSocketHandler: 添加 handle_interrupt() 处理 interrupt 消息,回复 interrupt_ack 后调用 ai_manager.cancel()
- EnhancedAIManager: 添加 cancel() 统一入口,同时取消AI和命令执行器
- think_and_respond: 首轮清除cancel标志,流式循环检查取消,API/JSON/未知异常中均检查取消标志
- _handle_tool_calls: 每个工具调用前检查取消信号
- 更新README v2.6日志和API文档
2026-08-01 14:09:24 +08:00
qing
b935fefb82
refactor(gateway): remove local ini fallback, configs only via confs
...
Follow the same convention as the static module: remove local config.ini
fallback and --config/-i command-line argument entirely. All configuration
is now managed exclusively through confs service.
- Delete gateway/example.ini (moved to confs/configs/gateway.ini).
- Remove -i/--input option from boost::program_options; help (-h) and
version (-v) are the only CLI flags remaining.
- Simplify main.cpp config loading: remove local-file branch, always fetch
gateway.ini from confs with retry_on_refused=true waiting for confs ready.
- Update _run.sh: no longer passes any arguments; config comes from confs.
- Update README: remove example.ini references, -i flag docs, local file
mode description, and example.ini from directory structure tree.
- Clarify changelog entry for v0.7.0.
2026-08-01 14:00:26 +08:00
qing
9ccb9cbdca
feat(gateway): migrate configuration to confs service (v0.7.0)
...
Migrate gateway from local -i ini file to the unified confs configuration
service, following the same two-layer pattern as Python services (dnfs/db/static):
- Add confs/configs/gateway.ini with all existing settings plus new
[Downstream] section for db/captcha/smtp host:port (previously hardcoded).
- Conf.hpp: add fromString() to parse ini from text (confs response),
env()/env_int() static helpers for environment variables, public default
constructor, and empty-filename guard in file constructor.
- DbC.hpp: add init(host, port) static method and static _host/_port members,
replacing hardcoded "127.0.0.1":8005. Defaults preserved for backward compat.
- main.cpp:
* Rewrite config loading: bootstrap CONFS_HOST/CONFS_PORT from env
(default 127.0.0.1:8010), fetch gateway.ini via pymsg from confs
(retry_on_refused=true), parse with ConfIni::fromString().
* -i flag is now optional; when provided, reads local ini (dev/debug mode).
* Add downstream host/port globals (_DB_HOST/_DB_PORT, _CAPTCHA_HOST/_CAPTCHA_PORT,
_SMTP_HOST/_SMTP_PORT, _CONFS_HOST/_CONFS_PORT), populated from [Downstream].
* Environment variable overrides (highest priority): LISTEN_ADDR/LISTEN_PORT,
DB_HOST/DB_PORT, CAPTCHA_HOST/CAPTCHA_PORT, SMTP_HOST/SMTP_PORT.
* Config integrity validation: required fields (Server.address/port,
Proxy.default, Downstream.db_host/db_port) cause startup failure if missing.
* Initialize DbC::init() and logs().set_endpoint() after config load.
* Replace all hardcoded "127.0.0.1":8005/8008/8009 in captcha/smtp/db calls
with configurable globals.
* Add downstream service info to startup log output.
* Fix: -v/--version flag now actually prints version and exits.
* Bump version to 0.7.0.
- _run.sh: remove -i example.ini default; now starts without args (confs mode),
passes "$@" through for optional -i override.
- Update README with new config loading docs, Downstream config section,
updated directory structure, and v0.7.0 changelog.
2026-08-01 13:55:18 +08:00
qing
de58c0487a
fix(dnfs): validate token via gateway /whoami with RSA signature verification
...
- Replace unsafe base64-only decode_token() with HTTP POST to gateway /whoami,
which performs RSA signature verification and expiry checks internally
- Fail-closed on gateway unreachable: return 503 instead of allowing access
- Add [gateway] config section (url/timeout) with GATEWAY_URL env override
- Add missing @_handle_exp decorator to delete_note and update_note views
- Fix Flask endpoint name collision using @functools.wraps on _handle_exp
- Remove unused base64 import
- Update dnfs.ini with gateway config (http://127.0.0.1:8443/whoami , timeout=5)
- Update docker-compose.yml with GATEWAY_URL and host.docker.internal for containers
2026-08-01 13:49:28 +08:00
qing
e7a2877422
feat(dnfs): delegate Token verification to gateway /whoami
...
Replace the insecure local base64 decode (with FIXME comment about
missing signature verification) with proper remote RSA signature
verification through gateway's /whoami endpoint:
- Add [gateway] config section (url, timeout) to dnfs.ini with defaults.
- Support GATEWAY_URL environment variable override for Docker.
- decode_token() now POSTs to gateway /whoami with Authorization: Bearer
<token>; gateway verifies RSA signature and expiry, returns login/user/
is_admin. Network/gateway errors fail-closed with 503.
- Add @_handle_exp decorators to delete_note() and update_note() which
were missing exception handling wrappers (consistent with other routes).
- docker-compose.yml: add GATEWAY_URL, CONFS_HOST, CONFS_PORT env vars
plus host.docker.internal extra_hosts so dnfs container can reach
host-side gateway and confs services.
2026-08-01 13:42:59 +08:00
qing
7d6ba6de93
feat(gateway): add retry_on_refused for pymsg MsgClient (v0.6.1)
...
- Add MsgConnectionRefusedException to distinguish ECONNREFUSED from other
connection errors; openConnection() now throws it when connect() returns
ECONNREFUSED.
- MsgClient::call() adds retry_on_refused/retry_interval parameters (defaults
false/1.0s), matching Python pymsg.MsgClient.call(retry_on_refused=True).
- Retry loop: only retries on ECONNREFUSED; other exceptions (timeout,
connection reset, business errors) propagate immediately. Throttled logging:
first failure prints immediately, subsequent logs every 5 seconds.
- DbC::call_msg() enables retry_on_refused=true (db is a hard dependency;
gateway blocks waiting for db on startup instead of crashing).
- LogC::_send() explicitly passes retry_on_refused=false (fail-safe; never
block the background log thread when db is unavailable).
- captcha/smtp auxiliary services keep default retry_on_refused=false
(fail-fast; blocking in request threads would exhaust the thread pool).
- Update README with pymsg protocol documentation, downstream retry strategy
table, and v0.6.1 changelog entry.
2026-08-01 13:42:24 +08:00
qing
b30ce1424b
docs(dnfs): update README with security audit findings and architecture corrections
...
- Fix architecture diagram to reflect pymsg TCP RPC (not HTTP), add confs dependency
- Update security headers to match actual security_middleware.py values
- Add complete P0/P1/P2 security audit findings (16 issues total):
- P0: Token without RSA signature verification (forgery risk)
- P0: review_content() fail-closed broken due to exception handling gaps
- P0: delete_note/update_note missing @_handle_exp decorator
- P0: Parent nodes with children can be deleted (no DB foreign key + TOCTOU race)
- P1: No token expiry check, no request body size limit, log_client config mismatch
- P2: Error message info leakage, overly permissive CORS, legacy commented code
- Correct file paths for frontend (static/public/), dependencies (pymsg, not nuitka)
- Fix outdated code line references
2026-08-01 13:28:41 +08:00
qing
7ef6a0b65f
Merge branch 'dev_qing' of https://git.cancerai.top/qing/micro_servers into dev_qing
2026-08-01 13:19:58 +08:00
qing
531358919c
fix conf
2026-08-01 13:16:45 +08:00
qing
bd1d7ca4d0
refactor(libhttp): split HttpServer into modular TUs for faster incremental builds
...
Split the 1400-line HttpServer.cpp into 6 focused translation units by
functional area:
- HttpServer.cpp: core lifecycle, SSL init, session management, debug
- HttpServer_Listener.cpp: TCP connection acceptor
- HttpServer_Routes.cpp: route registration, matching, wildcard/query parsing
- HttpServer_Request.cpp: request dispatch, static files, CORS, HTTP I/O
- HttpServer_Ws.cpp: WS route registry, client management, broadcast APIs
- HttpServer_WsSession.cpp: per-session WS frames + bidirectional WS proxy
Add inc/us/detail/HttpServerImpl.hpp for internal shared definitions
(exception classes, full Session/Listener declarations) installed under
/usr/include/us/detail/. Update Makefile with proper dependency tracking.
Update README with Source Layout section and v3.3.0 changelog entry.
Modifying one module now only requires recompiling its corresponding .o
instead of the entire monolithic translation unit.
2026-08-01 13:15:52 +08:00
qing
d883dc620e
refactor(pymsg): 新增AsyncRpcQueue通用异步队列,log_client基于此重构
...
- pymsg新增AsyncRpcQueue:提供内存队列+后台线程+攒批处理的通用异步基础设施,
支持两种模式:简单RPC模式(client+method+serialize)和自定义handler模式
- confs/dnfs/static的log_client.py重构为基于AsyncRpcQueue的薄封装,
保持API完全向后兼容(push/info/error/warning/debug/critical + 全局logs单例)
- 消除了三份log_client副本中重复的队列/线程/攒批逻辑(约150行/份),
代码量净减少约50行
- LogClient的行为与旧版一致:逐条INSERT到db、fail-fast网络错误、队列满丢最旧
2026-08-01 12:59:33 +08:00
qing
101aed48be
feat(pymsg): RpcClient 新增 retry_on_refused 阻塞等待模式,解决微服务启动顺序依赖
...
pymsg 客户端:
- MsgClient.call() 新增 retry_on_refused/retry_interval 参数
- retry_on_refused=True 时,ConnectionRefusedError 不抛出,按 retry_interval(默认1s)阻塞重试
- 重试期间每5秒向 stderr 打印等待提示,避免日志刷屏
- 仅对 ConnectionRefusedError 重试;TimeoutError/ConnectionError/RpcError 仍立即抛出
- 默认 retry_on_refused=False,完全向后兼容
- RpcClient 构造函数新增同名关键字参数,call() 支持单次调用覆盖
- 新增 time 模块导入
- 更新 README 文档(新增"启动等待模式"章节和参数表)
各服务(db/dnfs/static):
- _fetch_from_confs() 改用 retry_on_refused=True,移除手动 ConnectionRefusedError 捕获和 sys.exit
- 保留 RpcError(如配置文件不存在)的友好错误处理和 sys.exit(1)
- 启动时不再因 confs 未就绪而退出:pymsg 自动阻塞等待 confs 启动后自动连接成功
- 启动顺序从"刚性要求 confs 先启动"变为"不严格要求启动顺序"
- log_client 保持默认 retry_on_refused=False,后台线程不阻塞(fail-safe 丢弃日志)
- 更新各服务 README 和 confs README 的启动顺序描述
测试验证:
- 基本 call() 正常工作
- retry_on_refused=False 连接拒绝立即抛 ConnectionRefusedError
- retry_on_refused=True 阻塞等待(延迟1.5s启动服务后成功连接,重试日志正常输出)
2026-08-01 12:47:08 +08:00
qing
0ae107f953
refactor(static): 删除默认配置与本地回退逻辑,confs 改为强依赖
...
- 配置加载从三层(内置默认值→confs→本地config.ini回退)改为两层(confs 强依赖→环境变量覆盖)
- confs 连接失败直接 sys.exit(1),不再静默使用内置默认值或回退本地 config.ini
- file_config 初始值改为空字符串白名单模板,移除所有内置默认值
- 新增配置完整性校验:server.host/port、directory.root、cors.allowed_origins 必须非空
- ssl 段保留合理默认(enabled=false、cert/key 默认文件名),不强制配置
- 区分错误类型:连接拒绝/RpcError/通用异常分别打印明确错误信息到 stderr
- confs 连接地址改为引导配置(环境变量 CONFS_HOST/CONFS_PORT 优先,默认 127.0.0.1:8010)
- 移除 --config 命令行参数(本地 config.ini 回退已删除)
- 删除 static/config.ini 本地回退文件
- 更新 _run.sh 移除 --config 参数
- 更新 static/README.md 与 confs/README.md 文档
- confs 集成关系描述更新为"confs 最先启动"
2026-08-01 12:38:51 +08:00
qing
de0e4168b2
refactor(static): 首页内联样式解耦至 css/index.css
...
- 新增页面级样式文件 css/index.css(与 view.css/aibox.css 惯例一致)
- index.html 移除内联 <style> 块与头像内联样式,改为外链
- 头像圆角 100px 优化为 border-radius: 50%
2026-08-01 12:37:19 +08:00
qing
1a5e9f7064
feat(static): 首页添加登录态检测与进入笔记入口
...
- index.html: lang 改为 zh-CN,新增"关于本站"介绍段落,按钮改为有 id 的登录/注册/进入/退出四按钮(默认隐藏进入/退出)
- 新增 index.js: POST /whoami 检测登录态(HttpOnly Cookie 自动携带),已登录则显示用户名+进入笔记/退出按钮,未登录显示登录/注册
- 退出按钮调用 POST /logout 后刷新页面
2026-08-01 12:34:53 +08:00
qing
84adec4722
refactor(dnfs): 删除默认配置逻辑,confs 改为强依赖
...
- 配置加载从三层(默认值→confs→环境变量)改为两层(confs 强依赖→环境变量覆盖)
- confs 连接失败直接 sys.exit(1),不再静默使用内置默认值
- _dnfs_config 初始值改为空字符串白名单模板,移除内置默认值
- 新增配置完整性校验:confs 返回后检查所有必需 section/key 非空
- 区分错误类型:连接拒绝/RpcError/通用异常分别打印明确错误信息到 stderr
- confs 连接地址改为引导配置(环境变量优先,默认 127.0.0.1:8010),移除 dnfs.ini 中 [confs] 段
- 启动顺序调整为 confs → db → dnfs → ai_review/...(dnfs 同时依赖 confs 和 db)
- 更新 dnfs/README.md 与 confs/README.md 文档
2026-08-01 12:33:51 +08:00
qing
2cbb93b3b7
refactor(db): 删除 confs 连接失败时使用默认配置的 fail-safe 逻辑
...
- confs 改为 db 启动的强依赖:连接失败直接 sys.exit(1),不再静默使用默认值
- 配置加载从三层(默认值→confs→环境变量)改为两层(confs→环境变量覆盖)
- _db_config 初始值改为空字符串白名单模板,移除内置默认值
- 新增配置完整性校验:confs 返回后检查所有必需 section/key 非空,缺失则报错退出
- 区分错误类型:连接拒绝/RpcError/通用异常分别打印明确的错误信息到 stderr
- confs 连接地址改为引导配置(环境变量优先,默认 127.0.0.1:8010),不再从 db.ini 读取
- 更新 db/README.md 与 confs/README.md,说明启动顺序调整为 confs → db → ...
2026-08-01 12:29:55 +08:00
qing
6ebd544619
feat(db): 迁移 db 配置到 confs 统一配置服务
...
- 新增 confs/configs/db.ini 集中托管 db 服务配置(server/database/logs/confs)
- dbv2.py 采用三层 fail-safe 加载模式:内置默认值 → confs(db.ini,优先)→ 环境变量覆盖(最高优先级,Docker 兼容)
- _merge_ini() 白名单合并,仅覆盖已知 section/key,ConfigParser(interpolation=None) 禁用插值
- db 先于 confs 启动时连接失败静默 fail-safe,启动时打印配置来源
- db_tools.py 运维工具保持独立,直接读 DATABASE_URL 环境变量,不依赖 confs
- 更新 confs/README.md 与 db/README.md 文档
2026-08-01 12:23:21 +08:00
qing
c06eb19f64
refix
2026-08-01 11:47:14 +08:00
qing
46b66f8bd8
fix(gateway,static): 配置 /ws/aibox WS 反代路由;aibox 桌面端对话左对齐
2026-08-01 06:08:20 +08:00
qing
e25c132722
解耦libhttp/HttpClient
2026-08-01 06:04:36 +08:00
qing
373f6af352
^-^
2026-08-01 06:04:27 +08:00
qing
65580e7e50
refactor(static): aibox.html 拆分内联 CSS/JS 为独立文件
2026-08-01 05:27:02 +08:00
qing
227fbb17f4
build(libhttp): lower optimization to -O2 to avoid cc1plus OOM on low-memory machines
2026-08-01 05:26:52 +08:00
qing
cebef9fe70
docs: 各模块安全审计报告 + 补充 .gitignore 忽略规则
2026-08-01 05:21:23 +08:00
qing
12ece9020c
feat(libhttp,gateway): add admin-only WebSocket reverse proxy
...
libhttp v3.1:
- add ws_proxy(path, handshake) API with WsProxyHandshakeHandler callback
- implement full-duplex async bidirectional bridging (text+binary frames)
- support ws:// and wss:// backends with SNI, write queues for ordering
- proxy routes take priority over regular ws() routes
- 403 response on handshake rejection, graceful close propagation
gateway v0.6.0:
- add [WsProxy] config section (routes = /path=ws://backend;...)
- handshake callback verifies Token (Authorization/Cookie) is_admin=true
- non-admin / expired / missing token → 403, admin → transparent bridge
- fix LocalTime.hpp C++20 tzdb incompatibility on Apple clang (use strftime/get_time/mktime)
- update example.ini and README docs for both modules
2026-08-01 05:20:14 +08:00
qing
6ed88feaa4
feat(static): 新增 aibox 智能体 Web 客户端(移动端适配)
...
- aibox.html:自包含移动端聊天页,经 gateway [WsProxy] 反向代理与 aibox 通信
- 协议兼容 BotOps client.py:chunk 流式渲染 / reasoning 思考区 / task 任务面板 / 指数退避重连
- 移动端适配:100dvh 动态视口 + safe-area 刘海屏 + 44px 触控目标 + 任务面板抽屉式
- 安全:握手由 gateway 强制 is_admin 验签,Token 全程 HttpOnly Cookie,CSP 合规(本地 markdown-it)
- README 同步页面清单与功能说明
2026-08-01 05:18:30 +08:00
qing
bf2b5d31f7
fix(botops): v1.2 - 彻底修复思考区域与正式回答顺序问题
...
问题根因:之前预创建空 AI widget,思考 widget 挂载在其后,即使动态重排也可能因 Textual 组件树更新时序导致顺序不稳定。
修复方案:
- 移除 prefab 空 AI widget 预创建逻辑
- start_ai() 仅标记状态,不创建任何 widget
- _ensure_ai_widget() 延迟到第一次 chunk 到来时才创建 AI widget
- 按消息到达顺序自然挂载:reasoning_start → reasoning → chunk → end_reasoning/finish_ai
- 思考 widget 必然先于 AI widget 挂载,顺序天然正确
同时:
- 简化 app.py 发送失败处理,不再需要移除空 widget
- 更新 README v1.2 说明
2026-08-01 05:00:56 +08:00
qing
9815ff44af
feat(libhttp): integrate WebSocket client into HttpClient
...
Merge WebSocket client functionality into HttpClient using Boost.Beast,
enabling a single client instance to handle both HTTP (libcurl) and
WebSocket (ws:// and wss://) protocols. Backward-compatible type aliases
(WebSocketClient, WebSocketClientBase) preserve existing code.
Changes:
- Add synchronous WebSocket client: ws_connect/ws_send/ws_recv/ws_close
- Support ws:// (plain TCP) and wss:// (TLS with SNI) connections
- Layered stream architecture with beast::tcp_stream for timeout support
- Binary message support via ws_send_binary()
- Update Makefile to link libcurl (-lcurl)
- Add README.md documenting unified HttpServer + HttpClient API
2026-08-01 04:59:47 +08:00
qing
5edb67b46d
docs(botops): update README with reasoning mode ordering fix and v1.1 changelog
...
- Update reasoning display limit from 2000 to 3000 chars in protocol docs
- Add widget ordering guarantee note (reasoning always before answer)
- Document info message filtering for conversation start notifications
- Add v1.1 changelog section listing reasoning mode features and fixes
2026-08-01 04:56:25 +08:00
qing
039d6acf37
fix(botops): fix reasoning panel appearing after AI response and filter conversation start notification
...
- Add _ai_prefab flag to track pre-created empty AI widget
- start_reasoning() now reorders widgets: remove empty AI widget, mount reasoning first, then remount AI widget
- This ensures reasoning always appears BEFORE the actual answer
- Filter out 'Conversation started'/'对话开始' info notifications (implicit event, no need to show)
- Increase reasoning display limit from 2000 to 3000 chars
2026-08-01 04:55:12 +08:00
qing
ba9a77fe66
feat(libhttp): integrate WebSocket support into HttpServer
...
Merge WebSocketServer functionality into HttpServer so a single port can
serve both HTTP(S) and WebSocket(S) endpoints while preserving full backward
compatibility for existing HTTP interfaces.
Key changes:
- Add WebSocket route registration: ws(), onWsConnect(), onWsDisconnect()
- Add client management: sendToWsClient(), broadcastWs(), disconnectWsClient()
- Rewrite Session class using beast::tcp_stream for unified HTTP/WS handling
- Support automatic ws:// and wss:// upgrades on HTTP/HTTPS ports
- Thread-safe message queue with asio::post for cross-thread sends
- Update Makefile to link OpenSSL and pthread for TLS/WebSocket support
- Add test_server.cpp demonstrating HTTP + WebSocket mixed usage
2026-08-01 04:43:33 +08:00
qing
e007990594
feat(dnfs,static): 新增管理员特殊节点(链接/网页代码/图片/文件)
...
- 信封格式:content 为 {"_sp":...} JSON,普通 Markdown 节点不受影响
- dnfs:add_note/update_note 按 is_admin 强制特殊节点发布权(非管理员 403),
字段与大小校验(url≤2048、code≤512KB、base64≤3.5M 字符),AI 审核剔除 base64 负载
- dnfs:修复存量 bug —— 模块级 _sys.path.insert 未定义导致 import 即 NameError
- static:新增 GET /api/favicon 服务端代理(SSRF 防护:内网地址拦截 + 重定向校验 + 512KB 上限)
- 前端:管理员可见节点类型选择器;链接 favicon 卡片 / 网页可审计可运行 / 图片直显 / 文件下载
- theme.css 补充 select 与特殊节点样式;两个 README 同步更新
2026-08-01 04:34:23 +08:00