Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
52 commits
Select commit Hold shift + click to select a range
c1d62b9
feat(models): add per-model upstream streaming toggle
69gg Apr 25, 2026
4ec65fa
docs: refresh repository guidance
69gg Apr 25, 2026
0512132
docs: simplify stream_enabled comments
69gg Apr 25, 2026
355bb27
feat: 用户识别指导与昵称查询增强
69gg May 1, 2026
eff29c5
feat: 统一附件标签语法 & 新增 get_avatar 工具
69gg May 1, 2026
eed8321
docs: 更新 AGENTS.md 与 CLAUDE.md
69gg May 1, 2026
ca32f13
feat(memes): add OCR/image text content instructions to describe prompt
69gg May 1, 2026
0ab8afd
feat(prompt): allow inferring task object from context before asking
69gg May 1, 2026
6edc414
fix(commands): profile usage uses canonical name; help auto-appends s…
69gg May 1, 2026
3f79187
refactor(commands): merge lsfaq/viewfaq/searchfaq/delfaq into /faq wi…
69gg May 1, 2026
7b62af1
feat(commands): declarative subcommand registration with inference, r…
69gg May 1, 2026
121eb73
fix(tests): update assertions to use <attachment> tag instead of <pic>
69gg May 1, 2026
572e9ab
feat(commands): support @-mention for QQ-id arguments
69gg May 1, 2026
a90b4e5
feat(commands): render help details as image
69gg May 1, 2026
f1f1ab0
docs(commands): clarify help detail rendering
69gg May 1, 2026
2c89342
feat(commands): render help list as image
69gg May 1, 2026
4a8faca
refactor(toolsets): consolidate group analysis tools
69gg May 1, 2026
eb29dc4
feat(github): add repository auto cards
69gg May 1, 2026
5c039d3
feat(profile): render profile view by default
69gg May 1, 2026
5ec4c9f
docs: sync profile and github changes
69gg May 1, 2026
dc4b41c
fix(group): align brief member and avatar tools
69gg May 1, 2026
0897072
docs: refine v3.3.3 changelog to be more conversational
69gg May 1, 2026
cc4ad5b
docs: refine v3.3.3 changelog to match previous technical narrative s…
69gg May 1, 2026
308b7b0
fix(github): route auto extract through configured proxy
69gg May 1, 2026
dfcb0c7
fix(profile): fall back to merged forward on render failure in group …
69gg May 1, 2026
3c3d67d
chore(version): bump version to 3.3.3
69gg May 1, 2026
f5d5503
fix(render): make browser concurrency configurable
69gg May 1, 2026
ab38942
feat(skills): add auto extraction pipeline
69gg May 1, 2026
324ed1b
fix(pipeline): record auto outputs with attachments
69gg May 1, 2026
531c780
fix(pipeline): centralize auto output recording
69gg May 1, 2026
eb0bcdc
fix(commands): record command outputs in history
69gg May 1, 2026
0b2ff79
feat(attachments): cap remote downloads
69gg May 1, 2026
bfb96a3
docs(changelog): mention remote attachment cap
69gg May 1, 2026
4a45663
fix(review): address async render pipeline issues
69gg May 1, 2026
8a53eb0
fix(github): avoid numeric bare repo false positives
69gg May 1, 2026
df499e8
test(repeat): ensure repeat skips auto pipeline
69gg May 1, 2026
34af653
fix(commands): merge subcommand rate limits
69gg May 1, 2026
029f44d
perf(history): coalesce async history saves
69gg May 1, 2026
a8901de
fix(llm): preserve streaming output whitespace
69gg May 2, 2026
18b248d
fix(review): address remaining Devin flags
69gg May 2, 2026
6e51c5d
fix(render): close context on page creation failure
69gg May 2, 2026
f3c7072
fix(review): refine hot reload and naga dispatch
69gg May 2, 2026
ecd2ee0
fix(review): narrow streaming fallback errors
69gg May 2, 2026
506a270
fix(review): async auto pipeline startup load
69gg May 2, 2026
8b97859
fix(review): handle rewritten naga subcommand args
69gg May 2, 2026
ee762c7
fix(review): address full code review findings
69gg May 2, 2026
b6b455f
fix(review): initialize auto pipeline fallback
69gg May 2, 2026
ee80276
fix(review): tighten model pool and github parsing
69gg May 2, 2026
8a21a3c
fix(review): address follow-up review flags
69gg May 2, 2026
40d5323
docs(prompts): delay meme lookup after text replies
69gg May 2, 2026
8dad000
fix(review): refresh summary hot reload state
69gg May 2, 2026
2d29a65
fix(review): retain history saves on write failure
69gg May 2, 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
36 changes: 28 additions & 8 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -1,26 +1,46 @@
# Repository Guidelines

## Project Structure & Module Organization
`src/Undefined/` contains the main Python package. Core areas include `ai/`, `cognitive/`, `services/`, `skills/`, and `webui/`. `tests/` holds the pytest suite; add new tests close to the behavior they cover with `test_*.py` names. `apps/undefined-console/` is the Tauri + Vite management client. `code/NagaAgent/` is a Git submodule, so keep upstream syncs and local patches as clearly separated changes. Packaged assets live in `res/`, `img/`, and `config/`; generated outputs like `dist/` and runtime data under `logs/` are not primary edit targets.
`src/Undefined/` contains the main runtime package. Core areas include `ai/`, `services/`, `skills/`, `cognitive/`, `memes/`, `knowledge/`, `api/`, `webui/`, `config/`, and `mcp/`; media-facing integrations live in `arxiv/`, `bilibili/`, `github/`, and `attachments.py`. `tests/` holds the pytest suite. `apps/undefined-console/` is the primary Tauri + Vite management client, 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:

- `uv sync` installs Python dependencies.
- `uv run playwright install` installs browser runtimes used by screenshot features.
- `uv run Undefined-webui` starts the recommended local management entrypoint.
- `uv run playwright install` installs browser runtimes used by screenshot and web tooling features.
- `uv run Undefined-webui` starts the recommended Management-first local entrypoint.
- `uv run Undefined` starts the bot directly.
- `uv run pytest tests/` runs the backend test suite.
- `uv run ruff check .` and `uv run ruff format --check .` enforce Python linting and formatting.
- `uv run mypy .` runs strict type checks.
- `uv build --wheel` validates packaging and resource inclusion.
- `uv build --wheel` validates packaging and bundled resources.
- `bash scripts/install_git_hooks.sh` enables the repository-managed git hooks.

For the desktop console app, run `cd apps/undefined-console && npm ci && npm run check`. Use `npm run tauri:dev` for local desktop development.
For the console app, run `cd apps/undefined-console && npm ci && npm run check`. Use `npm run dev` for the Vite shell and `npm run tauri:dev` for the desktop shell.

## Coding Style & Naming Conventions
Use 4-space indentation. Python code should be type-annotated and Ruff-formatted; follow `snake_case` for modules and functions, `PascalCase` for classes, and keep modules focused. WebUI JavaScript in `src/Undefined/webui/static/js/` is formatted with Biome using 4-space indents. `code/NagaAgent/frontend/` follows Vue/TypeScript conventions enforced by ESLint.
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/` is formatted with Biome, and `apps/undefined-console/` changes must satisfy Biome, TypeScript, and Cargo checks.

## Tools & Features

### `group.get_member_info` — brief parameter
The tool supports a `brief` boolean parameter (`default: false`). When `brief: true`, it returns only the current nickname (group card or QQ nickname) in a single line, suitable for quick queries where the AI needs to address a user by their latest name.

### `group.get_avatar` — fetch user avatar
`group.get_avatar` accepts `user_id` (required) and optional `size` (40, 100, 140, 640, default 100). It downloads the QQ avatar and registers it as an attachment, returning an `<attachment uid="..."/>` tag that can be embedded in messages.

### Unified attachment tag
Use `<attachment uid="..."/>` for both images and files. The legacy `<pic uid="..."/>` tag is still supported for backward compatibility but `attachment` is the recommended unified syntax. The system distinguishes image vs file based on the UID prefix (`pic_`/`file_`).
Remote attachments are cached only up to `[attachments].remote_download_max_size_mb`; larger items, or all remote items when the value is `0`, are registered as URL references with `source_ref` instead of downloaded file content.

### Auto processing pipelines
Automatic extraction pipelines live under `src/Undefined/skills/auto_pipeline/pipelines/<name>/` and use `config.json + handler.py`. Slash commands have higher priority; when a command is dispatched, automatic pipelines and AI auto-reply are skipped. Command inputs and command outputs should be recorded in message history so later AI turns can see the result. For non-command messages, all pipelines detect in parallel and all matches process in parallel before AI auto-reply. Outputs should go through `MessageSender`, which writes history and automatically registers local CQ media or uploaded files as session attachment UIDs.

### User identification in prompts
The system prompt now includes a rule: **recognize and address users by their QQ ID (`sender_id`)** because nicknames can change. When needing to address a user, use the latest nickname obtained via `group.get_member_info(brief=true)`. Observations recorded in cognitive memory should always include the QQ ID, e.g., “QQ号12345678(昵称张三)做了某事”.

## Testing Guidelines
Write tests as `tests/test_<feature>.py`. Async tests are supported through `pytest-asyncio`. Add or update tests for behavior changes in APIs, config loading, cognitive memory, and WebUI routes. CI runs the full Python suite plus console checks on pushes and pull requests; no explicit coverage threshold is configured, so use judgment and cover touched paths well.
Write tests as `tests/test_<feature>.py`. Async tests use `pytest-asyncio`. Add or update coverage for behavior changes in APIs, config loading/hot reload, cognitive memory, meme or knowledge flows, and WebUI/runtime routes. If you touch `apps/undefined-console/` or `src/Undefined/webui/static/js/`, run `npm run check` in `apps/undefined-console/` in addition to the Python checks. No fixed coverage threshold is configured, so cover touched paths well.

## Commit & Pull Request Guidelines
Recent history follows Conventional Commits with optional scopes, for example `fix(webui): refine launcher return flow` and `docs(build): document linux no-strip workaround`. Keep subjects imperative and concise. For pull requests, include a short impact summary, linked issues, and the commands you ran. Attach screenshots for WebUI or Tauri UI changes. If you change versioned release files, keep `pyproject.toml` and `src/Undefined/__init__.py` in sync. To mirror local checks, enable repo hooks with `git config core.hooksPath .githooks`.
Recent history follows Conventional Commits with optional scopes, for example `fix(webui): refine launcher return flow` and `feat(commands): add /version (/v) slash command`. Keep commit subjects imperative and concise. Keep `code/NagaAgent/` syncs separate from local feature work when possible. If you are bumping release versions, prefer `uv run python scripts/bump_version.py <version>` so `pyproject.toml`, `src/Undefined/__init__.py`, `apps/undefined-console/package.json`, and the Tauri config stay in sync. For pull requests, include a short impact summary, linked issues, and the commands you ran; attach screenshots for WebUI or Tauri UI changes.
50 changes: 31 additions & 19 deletions ARCHITECTURE.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,18 @@ graph TB
BilibiliSender["sender.py<br/>视频发送<br/>• 视频消息 • 降级信息卡片"]
end

subgraph GitHubModule["GitHub 模块 (github/)"]
GitHubParser["parser.py<br/>仓库标识解析<br/>• URL • SSH • owner/repo • JSON"]
GitHubClient["client.py<br/>public API 获取<br/>• 仓库信息 • contributors"]
GitHubSender["sender.py<br/>图片卡片发送<br/>• 头像 • 简介 • 统计"]
end

subgraph SecurityLayer["安全防线 (services/)"]
SecurityService["SecurityService<br/>安全服务<br/>• 注入攻击检测<br/>• 速率限制<br/>[security.py]"]
InjectionAgent["InjectionResponseAgent<br/>注入响应生成<br/>[injection_response_agent.py]"]
end

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

subgraph QueueSystem["车站-列车 队列系统 (services/)"]
AICoordinator["AICoordinator<br/>AI 协调器<br/>• Prompt 构建<br/>• 队列管理<br/>• 回复执行<br/>[ai_coordinator.py]"]
Expand Down Expand Up @@ -95,7 +101,7 @@ graph TB
TS_Messages["messages.*<br/>• send_message<br/>• get_recent_messages<br/>• get_forward_msg"]
TS_Memory["memory.*<br/>• add / delete<br/>• list / update"]
TS_Contacts["contacts.*<br/>• query_friends<br/>• query_groups"]
TS_GroupAnalysis["group_analysis.*<br/>• analyze_member_messages<br/>• analyze_join_statistics<br/>• analyze_new_member_activity"]
TS_GroupAnalysis["group_analysis.*<br/>• member_structure<br/>• message_mix<br/>• member_activity<br/>• activity_trend<br/>• inactive_risk<br/>• member_messages<br/>• join_statistics<br/>• new_member_activity"]
TS_Notices["notices.*<br/>• list / get / stats"]
TS_Render["render.*<br/>• render_html<br/>• render_latex<br/>• render_markdown"]
TS_Scheduler["scheduler.*<br/>• create_schedule_task<br/>• delete_schedule_task<br/>• list_schedule_tasks"]
Expand All @@ -116,7 +122,7 @@ graph TB
subgraph CommandsLayer["平台指令 (skills/commands/)"]
Cmd_Core["核心指令<br/>• help • stats"]
Cmd_Admin["管理指令<br/>• addadmin<br/>• rmadmin • lsadmin"]
Cmd_FAQ["FAQ 指令<br/>• lsfaq • viewfaq<br/>• searchfaq • delfaq"]
Cmd_FAQ["FAQ 指令<br/>• faq (ls/view/search/del)"]
Cmd_Fun["娱乐指令<br/>• bugfix"]
end

Expand Down Expand Up @@ -208,13 +214,16 @@ graph TB
SecurityService -.->|"API 调用"| LLM_API
SecurityService -->|"注入攻击"| InjectionAgent

MessageHandler -->|"1.5 Bilibili检测"| BilibiliParser
MessageHandler -->|"2. 指令?"| CommandDispatcher
CommandDispatcher -->|"执行结果经统一发送层写历史"| OneBotClient
MessageHandler -->|"2.5 非命令自动管线"| BilibiliParser
BilibiliParser -->|"BV号"| BilibiliDownloader
BilibiliDownloader -->|"视频文件"| BilibiliSender
BilibiliSender -->|"发送"| OneBotClient

MessageHandler -->|"2. 指令?"| CommandDispatcher
CommandDispatcher -->|"执行结果"| OneBotClient
MessageHandler -->|"2.6 非命令自动管线"| GitHubParser
GitHubParser -->|"仓库ID"| GitHubClient
GitHubClient -->|"public仓库信息"| GitHubSender
GitHubSender -->|"发送图片卡片"| OneBotClient

MessageHandler -->|"3. 自动回复"| AICoordinator
AICoordinator -->|"创建上下文"| RequestContext
Expand Down Expand Up @@ -353,21 +362,22 @@ sequenceDiagram
alt 检测到注入
SS->>MH: 拦截并响应
else 安全
%% Bilibili 自动提取
alt 消息包含B站链接/BV号
MH->>MH: extract_bilibili_ids()
MH->>MH: download_video()
MH->>OH: 发送视频/信息卡片
OH->>OB: WebSocket API
OB->>U: 显示视频
else 非B站内容
%% 指令处理
MH->>CD: 解析斜杠命令
%% 指令处理
MH->>CD: 解析斜杠命令
alt 是命令
CD->>ST: FAQ/管理员操作
CD->>ST: 写入命令输出历史
CD-->>OB: 返回结果
OB->>U: 发送响应
else 是AI消息
else 非命令消息
MH->>MH: 并行检测 skills/auto_pipeline 管线
opt 命中自动提取管线
MH->>MH: 并行处理全部命中的自动提取
MH->>OH: 发送视频/卡片/PDF
OH->>OB: WebSocket API
OB->>U: 显示自动提取结果
MH->>ST: 写入自动提取结果历史和附件 UID
end
%% AI处理流程
MH->>AC: handle_auto_reply()

Expand Down Expand Up @@ -810,6 +820,7 @@ description: 从 PDF 文件中提取文本和表格,填写表单。当用户
| **认知记忆** | `cognitive.enabled`, `cognitive.query.*`, `models.embedding.*` | 事件检索、时间衰减加权、侧写与后台史官 |
| **Bilibili** | `bilibili.auto_extract_enabled`, `bilibili.cookie`, `bilibili.prefer_quality` | B站视频自动提取与下载 |
| **arXiv** | `arxiv.auto_extract_enabled`, `arxiv.max_file_size`, `arxiv.auto_extract_max_items` | arXiv 论文自动提取、搜索与 PDF 发送 |
| **GitHub** | `github.auto_extract_enabled`, `github.request_timeout_seconds`, `github.auto_extract_max_items` | GitHub public 仓库自动提取与图片卡片发送 |
| **思考链** | `*.thinking_enabled` | 思维链支持 |
| **思维链兼容** | `*.thinking_tool_call_compat` | 思维链 + 工具调用兼容 |
| **WebUI** | `webui.url`, `webui.port`, `webui.password` | 配置控制台 |
Expand All @@ -820,7 +831,8 @@ description: 从 PDF 文件中提取文本和表格,填写表单。当用户

1. **外部实体层**:用户、管理员、OneBot 协议端 (NapCat/Lagrange.Core)、大模型 API 服务商
2. **核心入口层**:main.py 启动入口、配置管理器 (config/loader.py)、热更新应用器 (config/hot_reload.py)、OneBotClient (onebot.py)、RequestContext (context.py)、Runtime API Server (api/app.py → api/routes/ 路由子模块)
3. **消息处理层**:MessageHandler (handlers.py)、SecurityService (security.py)、CommandDispatcher (services/command.py)、AICoordinator (ai_coordinator.py)、QueueManager (queue_manager.py)、Bilibili 自动提取 (bilibili/)
3. **消息处理层**:MessageHandler (handlers.py)、SecurityService (security.py)、CommandDispatcher (services/command.py)、AICoordinator (ai_coordinator.py)、QueueManager (queue_manager.py)、自动处理管线 (skills/auto_pipeline/)、Bilibili/arXiv/GitHub 解析与发送模块
自动提取由 `AutoPipelineRegistry` 并行检测、并行处理全部命中的管线;发送结果写入历史后继续进入 AI 自动回复。
4. **AI 核心能力层**:AIClient (client.py)、PromptBuilder (prompts.py)、ModelRequester (llm.py)、ToolManager (tooling.py)、MultimodalAnalyzer (multimodal.py)、SummaryService (summaries.py)、TokenCounter (tokens.py)
5. **存储与上下文层**:MessageHistoryManager (utils/history.py, 10000条限制)、MemoryStorage (memory.py, 置顶备忘录, 500条上限)、EndSummaryStorage、CognitiveService + JobQueue + HistorianWorker + VectorStore + ProfileStorage、MemeService + MemeWorker + MemeStore + MemeVectorStore (表情包库)、FAQStorage、ScheduledTaskStorage、TokenUsageStorage (自动归档)
6. **技能系统层**:ToolRegistry (registry.py)、AgentRegistry、6个 Agents、11类 Toolsets
Expand Down
Loading
Loading