Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
47d846d
feat(config): 按功能拆分 embedding 模型配置
69gg Sep 19, 2026
4814a08
docs(config): [prompt.file_includes] 注释拆分到各插槽位置
69gg Sep 19, 2026
e46bd59
feat(webui): 适配 embedding 按功能覆写配置
69gg Sep 19, 2026
f60f01e
fix(cognitive): 修复侧写合并丢失更新并补齐恢复入口与并发上限
69gg Sep 19, 2026
eb98e94
fix(skills): 修复 agent handler 无法加载,并把加载失败暴露出来
69gg Sep 19, 2026
93cad88
fix(config): 热更新失败不再静默,按步骤隔离并回收后台任务异常
69gg Sep 19, 2026
fca4e2b
fix(main): 增加 SIGTERM 优雅停机
69gg Sep 19, 2026
d37ca89
fix(queue): 统一重试上限来源,避免等待方挂到超时
69gg Sep 19, 2026
a7d62d3
chore: 清理确认无引用的死代码
69gg Sep 19, 2026
af7d0ba
fix(scripts): 重嵌入脚本支持维度变化的迁移
69gg Sep 19, 2026
ba2674d
docs: 修复随包化重构后失效的路径与车道教述
69gg Sep 19, 2026
6daa0fb
chore(biome): App 配置改为显式不继承根配置
69gg Sep 19, 2026
c826f9d
refactor(skills): 提供 skills 内共享助手并机械校验导入边界
69gg Sep 19, 2026
b6714cf
chore(ci): 补齐 CI 治理并整理依赖组与必需依赖
69gg Sep 19, 2026
40058d7
docs(skills): 修正 README 与代码不符的 18 处问题
69gg Sep 19, 2026
acd995f
refactor(sender): 收敛 7 处重复的私聊访问控制门禁
69gg Sep 19, 2026
1b68bed
refactor(command): 拆分统计与 bugfix 实现,公开 skills 调用入口
69gg Sep 19, 2026
53e8cfb
test(budget): 为源码字符串断言建立只减不增的预算棘轮
69gg Sep 19, 2026
b5488b4
chore(version): bump version to 3.15.0
69gg Sep 19, 2026
c063e96
fix(chat): 移除 WorkspaceLayout 中多余的 Fragment
69gg Sep 19, 2026
4b4debf
fix(cognitive): 侧写锁的并发首次创建改为 setdefault 原子插入
69gg Sep 19, 2026
0a90683
fix(ai): crawl4ai 初始化失败降级为能力缺失,不再让 Bot 启动崩溃
69gg Sep 19, 2026
8698ef0
docs(historian): 说明在途门控与信号量两层并发约束的分工
69gg Sep 19, 2026
45b79c5
docs(config): 明确指令前缀的空白哨兵语义
69gg Sep 19, 2026
eb12d11
fix(skills): 恢复各工具访问控制文案的原始差异
69gg Sep 19, 2026
dd16dbc
fix(main): 停机信号处理器支持恢复,避免永久劫持
69gg Sep 19, 2026
7737821
fix(scripts): 重嵌入维度迁移改为临时库写入 + 原子换名
69gg Sep 19, 2026
fb9b54a
fix(knowledge): 检索运行时初始化改用 threading.Lock 双检守卫
69gg Sep 19, 2026
62b612e
chore(config): 未知 embedding 功能名警告列出合法值;CHANGELOG 补清理说明
69gg Sep 19, 2026
f6e0f51
docs: 落实复审收尾
69gg Sep 19, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 0 additions & 26 deletions .githooks/pre-tag

This file was deleted.

25 changes: 25 additions & 0 deletions .github/pull_request_template.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
## 变更说明

<!-- 用一两句话说明这个 PR 做了什么、为什么需要 -->

## 影响范围

<!-- 受影响的模块 / 配置项 / 用户可见行为;不涉及请写“无” -->

## 关联 Issue

<!-- Closes #123 / Refs #456;没有可留空 -->

## 自检

- [ ] `uv run ruff check .` 与 `uv run ruff format --check .` 通过
- [ ] `uv run mypy .` 通过
- [ ] `uv run pytest tests/ --cov` 通过(覆盖率不低于 `pyproject.toml` 中的 `fail_under`)
- [ ] 改动 `apps/undefined-console/` 或 `src/Undefined/webui/static/js/`:已跑 `cd apps/undefined-console && npm run check`
- [ ] 改动 `apps/undefined-chat/`:已跑 `cd apps/undefined-chat && npm run check`
- [ ] 涉及配置项:已同步 `config.toml.example` 与 `docs/configuration.md`
- [ ] 涉及 WebUI / Tauri 界面:已附截图

## 备注

<!-- 部署注意事项、需要重启的配置、回滚方式等 -->
49 changes: 46 additions & 3 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,21 @@ on:
pull_request:
branches: [ "main", "develop" ]

permissions:
contents: read

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

env:
NODE_VERSION: "22"
PYTHON_VERSION: "3.12"

jobs:
quality-check:
runs-on: ubuntu-latest
timeout-minutes: 30
steps:
- name: Checkout code
uses: actions/checkout@v4
Expand All @@ -23,8 +32,13 @@ jobs:
enable-cache: true
cache-dependency-glob: "uv.lock"

- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}

- name: Install dependencies
run: uv sync --group ci -p 3.12
run: uv sync --group dev -p ${{ env.PYTHON_VERSION }}

- name: Cache Ruff
uses: actions/cache@v4
Expand All @@ -51,8 +65,8 @@ jobs:
- name: Run Mypy
run: uv run mypy .

- name: Run Tests
run: uv run pytest tests/
- name: Run Tests (with coverage gate)
run: uv run pytest tests/ --cov --cov-report=term

- name: Build wheel
run: uv build --wheel
Expand All @@ -61,9 +75,38 @@ jobs:
run: |
uv run python -c "import glob, zipfile; whl=glob.glob('dist/*.whl')[0]; z=zipfile.ZipFile(whl); names=set(z.namelist()); required={'config.toml.example','res/prompts/undefined.xml','img/xlwy.jpg'}; missing=sorted([p for p in required if p not in names]); assert not missing, f'missing in wheel: {missing}'"

python-compat:
name: Python compat (${{ matrix.python-version }})
runs-on: ubuntu-latest
timeout-minutes: 30
strategy:
fail-fast: false
matrix:
# pyproject 声明 >=3.11,<3.14;主岗位跑 3.12,这里覆盖两端边界
python-version: ["3.11", "3.13"]
steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Install uv
uses: astral-sh/setup-uv@v5
with:
enable-cache: true
cache-dependency-glob: "uv.lock"

- name: Install dependencies
run: uv sync --group dev -p ${{ matrix.python-version }}

- name: Run Mypy
run: uv run mypy .

- name: Run Tests
run: uv run pytest tests/

native-app-quality-check:
name: Native app quality (${{ matrix.app_dir }})
runs-on: ubuntu-latest
timeout-minutes: 45
strategy:
fail-fast: false
matrix:
Expand Down
8 changes: 7 additions & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ jobs:
verify-python:
name: Verify Python package
runs-on: ubuntu-latest
timeout-minutes: 30
environment: release
steps:
- name: Checkout code
Expand All @@ -36,7 +37,7 @@ jobs:
cache-dependency-glob: uv.lock

- name: Install Python dependencies
run: uv sync --group ci -p ${{ env.PYTHON_VERSION }}
run: uv sync --group dev -p ${{ env.PYTHON_VERSION }}

- name: Validate release tag, build versions, and changelog
env:
Expand Down Expand Up @@ -88,6 +89,7 @@ jobs:
verify-native-app:
name: Verify ${{ matrix.product }} app
runs-on: ubuntu-latest
timeout-minutes: 60
environment: release
strategy:
fail-fast: false
Expand Down Expand Up @@ -150,6 +152,7 @@ jobs:
build-tauri-desktop:
name: Build Tauri desktop (${{ matrix.product }} ${{ matrix.label }})
runs-on: ${{ matrix.os }}
timeout-minutes: 90
environment: release
needs:
- verify-python
Expand Down Expand Up @@ -338,6 +341,7 @@ jobs:
build-tauri-android:
name: Build Tauri Android (${{ matrix.product }} ${{ matrix.abi_label }})
runs-on: ubuntu-latest
timeout-minutes: 120
environment: release
needs:
- verify-python
Expand Down Expand Up @@ -646,6 +650,7 @@ jobs:
publish-release:
name: Publish release assets
runs-on: ubuntu-latest
timeout-minutes: 30
needs:
- verify-python
- build-tauri-desktop
Expand Down Expand Up @@ -678,6 +683,7 @@ jobs:
publish-pypi:
name: Publish Python package to PyPI
runs-on: ubuntu-latest
timeout-minutes: 30
needs:
- verify-python
- publish-release
Expand Down
6 changes: 4 additions & 2 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
# Repository Guidelines

## Project Structure & Module Organization
`src/Undefined/` contains the main runtime package. Core areas include `ai/`, `services/`, `skills/`, `cognitive/`, `memes/`, `knowledge/`, `api/`, `webui/`, `config/`, `mcp/`, and `automations/` (`AutomationService` runtime plus JSON storage); media-facing integrations live in `arxiv/`, `bilibili/`, `github/`, and `attachments.py`. `tests/` holds the pytest suite. `apps/undefined-console/` is the Tauri + Vite management client and `apps/undefined-chat/` is the native-first Tauri + React 19 chat client (both connect to the same Management/Runtime services), while `code/NagaAgent/` remains a git submodule and should be updated deliberately, with upstream syncs kept separate from repo-local changes. Runtime and generated state primarily lives under `data/`, `logs/`, and `dist/`; the root `knowledge/` directory stores knowledge-base data rather than application code. Prefer editing source files and docs over generated outputs unless the task is explicitly about runtime state.
`src/Undefined/` contains the main runtime package. Core areas include `ai/`, `services/`, `skills/`, `cognitive/`, `memes/`, `knowledge/`, `api/`, `webui/`, `config/`, `mcp/`, and `automations/` (`AutomationService` runtime plus JSON storage); media-facing integrations live in `arxiv/`, `bilibili/`, `github/`, and `attachments/`. `tests/` holds the pytest suite.

> Single source of truth for the module-level directory tree: [docs/development.md](docs/development.md). This file, `CLAUDE.md`, and `ARCHITECTURE.md` only keep overviews — update the tree first when the layout changes. `apps/undefined-console/` is the Tauri + Vite management client and `apps/undefined-chat/` is the native-first Tauri + React 19 chat client (both connect to the same Management/Runtime services), while `code/NagaAgent/` remains a git submodule and should be updated deliberately, with upstream syncs kept separate from repo-local changes. Runtime and generated state primarily lives under `data/`, `logs/`, and `dist/`; the root `knowledge/` directory stores knowledge-base data rather than application code. Prefer editing source files and docs over generated outputs unless the task is explicitly about runtime state.

## Build, Test, and Development Commands
Use `uv` for the root project:
Expand All @@ -21,7 +23,7 @@ For the console app, run `cd apps/undefined-console && npm ci && npm run check`.
For the native chat client, run `cd apps/undefined-chat && npm ci && npm run check` (Biome + TypeScript + Vitest unit/e2e + `cargo fmt --check`/`cargo check`/`cargo test`). Use `npm run tauri:dev` for the desktop shell.

## Coding Style & Naming Conventions
Use 4-space indentation. Python code must be fully type-annotated and pass strict mypy checks. Disk I/O should go through `src/Undefined/utils/io.py` so writes stay async-safe and atomic. Follow `snake_case` for modules and functions, `PascalCase` for classes, and prefer extending existing services/helpers over introducing one-off abstractions. Skills handlers must not import repo-local modules outside `skills/`; pass dependencies through the execution context instead. WebUI JavaScript in `src/Undefined/webui/static/js/` and both native apps use Biome 2.5.10; keep the two package pins, lockfiles, and three configuration schemas in sync. Nested app configurations use `root: false` without inheriting the WebUI rules. App changes must satisfy Biome, TypeScript, and Cargo checks.
Use 4-space indentation. Python code must be fully type-annotated and pass strict mypy checks. Disk I/O should go through `src/Undefined/utils/io.py` so writes stay async-safe and atomic. Follow `snake_case` for modules and functions, `PascalCase` for classes, and prefer extending existing services/helpers over introducing one-off abstractions. Skills handlers must not import repo-local modules outside `skills/` (only `Undefined.skills.*` and same-directory relative imports are allowed); pass dependencies through the execution context, share helpers via `src/Undefined/skills/shared.py`, and keep `tests/test_skills_import_boundary.py`'s ratchet baseline shrinking. WebUI JavaScript in `src/Undefined/webui/static/js/` and both native apps use Biome 2.5.10; keep the two package pins, lockfiles, and three configuration schemas in sync. Nested app configurations use `extends: []` (explicit no-inherit) plus their own `formatter.indentStyle = "tab"`, so the root WebUI rules never leak into app checks. App changes must satisfy Biome, TypeScript, and Cargo checks.

## Tools & Features

Expand Down
24 changes: 12 additions & 12 deletions ARCHITECTURE.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ graph TB
ConfigLoader["ConfigManager<br/>配置管理器<br/>[config/manager.py + loader.py]"]
ConfigHotReload["ConfigHotReload<br/>热更新应用器<br/>[config/hot_reload.py]"]
ConfigModels["配置模型<br/>[config/models.py]<br/>ChatModelConfig<br/>VisionModelConfig<br/>SecurityModelConfig<br/>AgentModelConfig"]
OneBotClient["OneBotClient<br/>WebSocket 客户端<br/>[onebot/ + onebot.py shim]"]
OneBotClient["OneBotClient<br/>WebSocket 客户端<br/>[onebot/]"]
Context["RequestContext<br/>请求上下文<br/>[context.py]"]
WebUI["webui.py<br/>配置控制台<br/>[src/Undefined/webui.py]"]
end
Expand Down Expand Up @@ -47,10 +47,10 @@ graph TB

CommandDispatcher["CommandDispatcher<br/>命令分发器<br/>• /help /stats /admin<br/>• /bugfix /faq<br/>[services/command.py]"]

MessageBatcher["MessageBatcher<br/>同 sender 短时合并<br/>• 按 (scope, sender_id) 分桶<br/>• T1=window_seconds 结束 batch<br/>• T2=pre_send_seconds 投机预发送<br/>• 拍一拍/buffer 内 @bot 旁路<br/>• 首条 @bot 整批走 mention 队列<br/>[services/message_batcher/ + shim]"]
MessageBatcher["MessageBatcher<br/>同 sender 短时合并<br/>• 按 (scope, sender_id) 分桶<br/>• T1=window_seconds 结束 batch<br/>• T2=pre_send_seconds 投机预发送<br/>• 拍一拍/buffer 内 @bot 旁路<br/>• 首条 @bot 整批走 mention 队列<br/>[services/message_batcher/]"]

subgraph QueueSystem["车站-列车 队列系统 (services/)"]
AICoordinator["AICoordinator<br/>AI 协调器<br/>• Prompt 构建<br/>• 队列管理<br/>• 回复执行<br/>[services/coordinator/ + ai_coordinator.py shim]"]
AICoordinator["AICoordinator<br/>AI 协调器<br/>• Prompt 构建<br/>• 队列管理<br/>• 回复执行<br/>[services/coordinator/]"]
QueueManager["QueueManager<br/>队列管理器<br/>[queue_manager.py]"]

subgraph ModelQueues["ModelQueue 队列组 (按模型隔离)"]
Expand All @@ -66,14 +66,14 @@ graph TB

%% ==================== AI 核心能力层 ====================
subgraph AILayer["AI 核心能力层 (src/Undefined/ai/)"]
AIClient["AIClient<br/>AI 客户端主入口<br/>[ai/client/ + client.py shim]<br/>• 技能热重载 • MCP 初始化<br/>• Agent intro 生成"]
AIClient["AIClient<br/>AI 客户端主入口<br/>[ai/client/]<br/>• 技能热重载 • MCP 初始化<br/>• Agent intro 生成"]

subgraph AIComponents["AI 组件"]
PromptBuilder["PromptBuilder<br/>提示词构建器<br/>[ai/prompts/ + prompts.py shim]"]
PromptBuilder["PromptBuilder<br/>提示词构建器<br/>[ai/prompts/]"]
ToolSearchSession["ToolSearchSession<br/>请求级工具按需投影<br/>[ai/tool_search.py]<br/>• 名称检索 • schema 逐轮扩展"]
ModelRequester["ModelRequester<br/>模型请求器<br/>[ai/llm/ + llm.py shim]<br/>• OpenAI SDK • 工具清理<br/>• Thinking 提取"]
ModelRequester["ModelRequester<br/>模型请求器<br/>[ai/llm/]<br/>• OpenAI SDK • 工具清理<br/>• Thinking 提取"]
ToolManager["ToolManager<br/>工具管理器<br/>[tooling.py]<br/>• 工具执行 • Agent 工具合并<br/>• MCP 工具注入"]
MultimodalAnalyzer["MultimodalAnalyzer<br/>多模态分析器<br/>[ai/multimodal/ + multimodal.py shim]<br/>• 图片/音频/视频"]
MultimodalAnalyzer["MultimodalAnalyzer<br/>多模态分析器<br/>[ai/multimodal/]<br/>• 图片/音频/视频"]
SummaryService["SummaryService<br/>总结服务<br/>[summaries.py]<br/>• 聊天记录总结<br/>• 标题生成"]
TokenCounter["TokenCounter<br/>Token 统计<br/>[tokens.py]"]
Parsing["Parsing<br/>响应解析<br/>[parsing.py]"]
Expand Down Expand Up @@ -663,7 +663,7 @@ graph TB

subgraph Features["特性"]
F1["非阻塞: 即使前一个请求未完成,<br/>新请求也会按时分发"]
F2["优先级: 四级优先级,<br/>确保重要消息优先响应"]
F2["优先级: 六条车道,<br/>确保重要消息优先响应"]
F3["隔离性: 每个模型独立队列,<br/>互不干扰"]
F4["自动修剪: 普通队列超过10条时,<br/>只保留最新2条"]
F5["可配置节奏: 每个模型可独立设置<br/>队列发车间隔"]
Expand Down Expand Up @@ -860,10 +860,10 @@ description: 从 PDF 文件中提取文本和表格,填写表单。当用户
### 8层架构分层

1. **外部实体层**:用户、管理员、OneBot 协议端 (NapCat/Lagrange.Core)、大模型 API 服务商
2. **核心入口层**:main.py 启动入口、配置管理器 (config/loader.py + parsers/ + load_sections/)、热更新应用器 (config/hot_reload.py)、OneBotClient (onebot/ + onebot.py shim)、WeixinService (`weixin/` + `weixin-ilink-client`)、RequestContext (context.py)、Runtime API Server (api/app.py → api/routes/ 路由子模块,含 naga/ 子包)
3. **消息处理层**:MessageHandler (`handlers/`)、统一 DeliveryAddress 路由 (`utils/message_targets.py`)、SecurityService (security.py)、CommandDispatcher (services/command.py + commands/ mixins)、自动处理管线 (skills/pipelines/)、AutomationService (`automations/service.py`,pipeline 之后、对应 AI loop 之前 await,命中可拦截)、MessageBatcher (services/message_batcher/)、AICoordinator (services/coordinator/ + ai_coordinator.py 门面)、QueueManager (queue_manager.py)、Bilibili/arXiv/GitHub 解析与发送模块
2. **核心入口层**(目录级事实来源见 [docs/development.md](docs/development.md)):main.py 启动入口、配置管理器 (config/loader.py + parsers/ + load_sections/)、热更新应用器 (config/hot_reload.py)、OneBotClient (onebot/)、WeixinService (`weixin/` + `weixin-ilink-client`)、RequestContext (context.py)、Runtime API Server (api/app.py → api/routes/ 路由子模块,含 naga/ 子包)
3. **消息处理层**:MessageHandler (`handlers/`)、统一 DeliveryAddress 路由 (`utils/message_targets.py`)、SecurityService (security.py)、CommandDispatcher (services/command.py + services/commands/)、自动处理管线 (skills/pipelines/)、AutomationService (`automations/service.py`,pipeline 之后、对应 AI loop 之前 await,命中可拦截)、MessageBatcher (services/message_batcher/)、AICoordinator (services/coordinator/)、QueueManager (queue_manager.py)、Bilibili/arXiv/GitHub 解析与发送模块
自动提取由 `PipelineRegistry` 并行检测、并行处理全部命中的管线;随后 `await` 自动化工作流,未拦截时再进入 AI 自动回复。
4. **AI 核心能力层**:AIClient (ai/client/ + client.py shim)、PromptBuilder (ai/prompts/ + prompts.py shim)、ModelRequester (ai/llm/ + llm.py shim)、ToolManager (tooling.py)、MultimodalAnalyzer (ai/multimodal/ + multimodal.py shim)、SummaryService (summaries.py)、TokenCounter (tokens.py)。OpenAI Chat Completions / Responses、Anthropic Messages SDK 归一化、CoT 续传与文本 Tool Call 容错见[模型 API 与兼容层](docs/model-compatibility.md)。
4. **AI 核心能力层**:AIClient (ai/client/)、PromptBuilder (ai/prompts/)、ModelRequester (ai/llm/)、ToolManager (tooling.py)、MultimodalAnalyzer (ai/multimodal/)、SummaryService (summaries.py)、TokenCounter (tokens.py)。OpenAI Chat Completions / Responses、Anthropic Messages SDK 归一化、CoT 续传与文本 Tool Call 容错见[模型 API 与兼容层](docs/model-compatibility.md)。
5. **存储与上下文层**:MessageHistoryManager (utils/history.py, 10000条限制)、MemoryStorage (memory.py, 置顶备忘录, 500条上限)、EndSummaryStorage、CognitiveService + JobQueue + HistorianWorker + VectorStore + ProfileStorage、MemeService + MemeWorker + MemeStore + MemeVectorStore (表情包库)、FAQStorage、AutomationStorage (`data/automations.json`;旧 `scheduled_tasks.json` 启动时一次性转为新格式,不删旧文件、不双写)、TokenUsageStorage (自动归档)
6. **技能系统层**:ToolRegistry (registry.py)、AgentRegistry、7个 Agents、13类 Toolsets
7. **异步 IO 层**:统一 IO 工具 (utils/io.py),包含 write_json、read_json、append_line、跨平台文件锁 (flock/msvcrt)
Expand All @@ -880,7 +880,7 @@ description: 从 PDF 文件中提取文本和表格,填写表单。当用户
* **多模型隔离**:每个 AI 模型拥有独立的请求队列组("站台"),互不干扰。
* **非阻塞发车**:实现了可配置节奏的非阻塞调度循环(默认 **1Hz**)。列车按节奏出发,带走一个请求到后台异步处理。
* **高可用性**:即使前一个请求仍在处理(如耗时的网络搜索),新的请求也会按时被分发,不会造成队列堵塞。
* **优先级管理**:支持四级优先级(超级管理员 > 私聊 > 群聊@ > 群聊普通,确保重要消息优先响应。
* **优先级管理**:支持六条车道(超级管理员私聊 > 群聊超级管理员 > 普通私聊 > 群聊@ > 群聊普通 > 后台请求),前两条为严格优先级、中间三条轮转发车,确保重要消息优先响应。
* **关停收敛**:`MessageHandler.close()` 会先 flush `MessageBatcher`,再调用 `QueueManager.drain()` 等待已入队请求和在途请求自然完成,最后才停止队列处理器,避免缓冲消息只入队未执行。

### 7个智能体 Agent
Expand Down
Loading
Loading