Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
3732537
feat(automations): replace crontab tasks with condition-driven workflows
69gg Aug 16, 2026
ba49d85
refactor(automations): replace TaskScheduler with AutomationService
69gg Aug 16, 2026
040dcb1
feat(automations): add detailed runtime logs
69gg Aug 16, 2026
2fc0e3a
feat(webui): replace automation JSON forms with a canvas editor
69gg Aug 16, 2026
98915e1
fix(webui): scroll between automation list and canvas pages
69gg Aug 16, 2026
2d2bf5b
fix(webui): pick LLM allowlists and click-to-connect nodes
69gg Aug 16, 2026
4178665
fix(webui): pin the automations page title at the top
69gg Aug 16, 2026
8473b53
fix(webui): keep automations title flush with other page headers
69gg Aug 16, 2026
583af57
feat(automations): store tool and LLM outputs as named variables
69gg Aug 16, 2026
5a9a706
fix(automations): stream independent DAG branches and bind live sessi…
69gg Aug 16, 2026
ee426c5
fix(automations): inject AI services so cognitive tools see the live …
69gg Aug 16, 2026
cede5b3
fix(webui): return to the automations list and reload it after save
69gg Aug 16, 2026
2f3db19
feat(automations): disable default cooldown and raise runtime limits
69gg Aug 16, 2026
eb96393
feat(automations): run non-blocking graphs in the background
69gg Aug 17, 2026
a370757
feat(automations): extract extra variables from LLM nodes via tools
69gg Aug 17, 2026
62a3292
fix(automations): greet new members by nickname in the welcome preset
69gg Aug 17, 2026
800ed07
fix(automations): enforce workflow runtime contracts
69gg Aug 19, 2026
dfb69e6
chore(version): bump version to 3.13.0
69gg Aug 23, 2026
5dec042
fix(automations): respect message processing gates and default to non…
69gg Aug 23, 2026
8c8bb5d
docs(automations): rewrite docs for users and fix toolset counts
69gg Aug 23, 2026
8ea1f69
feat(automations): remove built-in loop iteration hard cap
69gg Aug 23, 2026
60493fb
fix(automations): harden workflow execution and updates
69gg Aug 23, 2026
210970c
docs(changelog): 调整措辞
69gg Aug 23, 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
2 changes: 1 addition & 1 deletion AGENTS.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# 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/`, and `mcp/`; 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.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.

## Build, Test, and Development Commands
Use `uv` for the root project:
Expand Down
39 changes: 21 additions & 18 deletions ARCHITECTURE.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ graph TB
%% ==================== 消息处理层 ====================
subgraph MessageLayer["消息处理层 (src/Undefined/)"]
MessageHandler["MessageHandler<br/>消息处理器<br/>[handlers/]"]
AutomationService["AutomationService<br/>自动化运行时<br/>[automations/service.py]<br/>• 事件匹配 • DAG 执行<br/>• APScheduler 时间触发"]

subgraph BilibiliModule["Bilibili 模块 (bilibili/)"]
BilibiliParser["parser.py<br/>标识符解析<br/>• BV/AV号 • URL<br/>• b23.tv短链 • 小程序JSON"]
Expand Down Expand Up @@ -99,15 +100,15 @@ graph TB
T_BilibiliVideo["bilibili_video<br/>B站视频下载发送 / UID 获取"]
end

subgraph Toolsets["工具集 (skills/toolsets/, 11大类)"]
subgraph Toolsets["工具集 (skills/toolsets/, 13大类)"]
TS_Group["group.*<br/>• get_member_list<br/>• get_member_info<br/>• get_honor_info<br/>• get_files"]
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/>• 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"]
TS_Automation["automation.*<br/>• list / get / create<br/>• update / delete / set_enabled"]
TS_Cognitive["cognitive.*<br/>• search_events<br/>• get_profile<br/>• search_profiles"]
TS_MCP["mcp.*<br/>MCP 工具集"]
TS_Memes["memes.*<br/>• search_memes<br/>• send_meme_by_uid"]
Expand Down Expand Up @@ -163,13 +164,12 @@ graph TB
CognitiveProfileStorage["ProfileStorage<br/>侧写存储<br/>[cognitive/profile_storage.py]<br/>• users/groups Markdown<br/>• 历史快照"]
MemeSystem["MemeSystem<br/>表情包存储<br/>[memes/]<br/>• worker.py (两阶段识别)<br/>• sqlite+chromadb<br/>• blob 持久化"]
FAQStorage["FAQStorage<br/>FAQ 存储<br/>[faq.py]<br/>• data/faq/{group_id}/"]
ScheduledTaskStorage["ScheduledTaskStorage<br/>定时任务存储<br/>[scheduled_task_storage.py]"]
AutomationStorage["AutomationStorage<br/>自动化存储<br/>[automations/storage.py]"]
TokenUsageStorage["TokenUsageStorage<br/>Token 使用统计<br/>[token_usage_storage.py]<br/>• 自动归档<br/>• gzip 压缩<br/>• 流式可选 TTFT/TPS"]
end

subgraph IOLayer["异步 IO 层 (src/Undefined/utils/)"]
IOUtils["IO 工具<br/>[io.py]<br/>• write_json<br/>• read_json<br/>• append_line<br/>• 文件锁 (flock/msvcrt) + 原子写入"]
SchedulerUtils["调度器工具<br/>[scheduler.py]<br/>• crontab 解析"]
CacheUtils["缓存工具<br/>[cache.py]<br/>• 定期清理"]
SenderUtils["Sender 工具<br/>[sender.py]"]
end
Expand All @@ -183,7 +183,7 @@ graph TB
Dir_Cognitive["cognitive/<br/>• chromadb/<br/>• profiles/<br/>• queues/"]
File_Memory["memory.json<br/>(置顶备忘录)"]
File_EndSummary["end_summaries.json<br/>(短期总结)"]
File_ScheduledTasks["scheduled_tasks.json<br/>(定时任务)"]
File_ScheduledTasks["automations.json<br/>(自动化)"]
Dir_Logs["logs/<br/>• bot.log<br/>• 轮转日志"]
File_Config["config.toml<br/>config.local.json"]
end
Expand Down Expand Up @@ -229,6 +229,10 @@ graph TB
GitHubClient -->|"public仓库信息"| GitHubSender
GitHubSender -->|"发送图片卡片"| OneBotClient

MessageHandler -->|"2.7 自动化"| AutomationService
AutomationService -->|"读写"| AutomationStorage
AutomationStorage -->|"异步读写"| IOUtils

MessageHandler -->|"3. 自动回复"| AICoordinator
AICoordinator -->|"3.1 入桶等待合并"| MessageBatcher
MessageBatcher -->|"3.2 flush 合并批次"| AICoordinator
Expand Down Expand Up @@ -293,7 +297,6 @@ graph TB
MemoryStorage -->|"异步读写"| IOUtils
TokenUsageStorage -->|"异步读写<br/>自动归档"| IOUtils
FAQStorage -->|"异步读写"| IOUtils
ScheduledTaskStorage -->|"异步读写"| IOUtils
CognitiveJobQueue -->|"异步读写"| IOUtils
CognitiveProfileStorage -->|"异步读写"| IOUtils

Expand Down Expand Up @@ -328,11 +331,11 @@ graph TB

class User,Admin,OneBotServer,LLM_API external
class Main,ConfigLoader,ConfigHotReload,ConfigModels,OneBotClient,Context,WebUI core
class MessageHandler,SecurityService,InjectionAgent,CommandDispatcher,MessageBatcher,AICoordinator message
class MessageHandler,AutomationService,SecurityService,InjectionAgent,CommandDispatcher,MessageBatcher,AICoordinator message
class AIClient,PromptBuilder,ModelRequester,ToolManager,MultimodalAnalyzer,SummaryService,TokenCounter,Parsing ai
class ToolRegistry,AgentRegistry,AgentToolRegistry,IntroGenerator skills
class RequestContext,ContextFilter,ResourceRegistry,HistoryManager,MemoryStorage,EndSummaryStorage,CognitiveService,CognitiveJobQueue,CognitiveHistorian,CognitiveVectorStore,CognitiveProfileStorage,FAQStorage,ScheduledTaskStorage,TokenUsageStorage storage
class IOUtils,SchedulerUtils,CacheUtils,SenderUtils io
class RequestContext,ContextFilter,ResourceRegistry,HistoryManager,MemoryStorage,EndSummaryStorage,CognitiveService,CognitiveJobQueue,CognitiveHistorian,CognitiveVectorStore,CognitiveProfileStorage,FAQStorage,AutomationStorage,TokenUsageStorage storage
class IOUtils,CacheUtils,SenderUtils io
class Dir_History,Dir_FAQ,Dir_TokenUsage,Dir_Cognitive,File_Memory,File_EndSummary,File_ScheduledTasks,Dir_Logs,File_Config persistence
class Prompts,Intros resource
class QueueManager,ModelQueues,DispatcherLoop queue
Expand Down Expand Up @@ -486,7 +489,7 @@ graph TB
TGroupAnalysis["group_analysis.*<br/>群分析"]
TNotice["notices.*<br/>公告"]
TRender["render.*<br/>渲染"]
TSched["scheduler.*<br/>定时任务"]
TSched["automation.*<br/>自动化"]
TCognitive["cognitive.*<br/>认知记忆"]
TMCP["mcp.*<br/>MCP 工具集"]
TMemes["memes.*<br/>表情包"]
Expand Down Expand Up @@ -572,7 +575,7 @@ graph LR
CognitiveVector["CognitiveVectorStore<br/>data/cognitive/chromadb/"]
CognitiveProfile["ProfileStorage<br/>data/cognitive/profiles/"]
FAQ["FAQStorage<br/>data/faq/{group_id}/<br/>• ID: YYYYMMDD-NNN"]
Tasks["ScheduledTaskStorage<br/>data/scheduled_tasks.json<br/>• Cron 格式"]
Tasks["AutomationStorage<br/>data/automations.json<br/>• DAG + Cron"]
TokenUsage["TokenUsageStorage<br/>data/token_usage.jsonl<br/>• 自动归档<br/>• gzip 压缩<br/>• 流式可选 TTFT/TPS"]
end

Expand Down Expand Up @@ -858,17 +861,17 @@ description: 从 PDF 文件中提取文本和表格,填写表单。当用户

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)、MessageBatcher (services/message_batcher/)、AICoordinator (services/coordinator/ + ai_coordinator.py 门面)、QueueManager (queue_manager.py)、自动处理管线 (skills/pipelines/)、Bilibili/arXiv/GitHub 解析与发送模块
自动提取由 `PipelineRegistry` 并行检测、并行处理全部命中的管线;发送结果写入历史后继续进入 AI 自动回复。
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 解析与发送模块
自动提取由 `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)。
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、7个 Agents、11类 Toolsets
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)
8. **数据持久化层**:历史数据目录、FAQ 目录、Token 归档目录、记忆文件、总结文件、定时任务文件、微信绑定/游标/隔离/审计状态
8. **数据持久化层**:历史数据目录、FAQ 目录、Token 归档目录、记忆文件、总结文件、自动化文件、微信绑定/游标/隔离/审计状态

### 微信 iLink 路由边界

微信接入由主进程独立管理,不依赖 OneBot 是否在线。`WeixinService` 先校验帐号与 peer,再把已绑定来源映射为逻辑 QQ 私聊交给 `MessageHandler`;未知来源在写历史或调用 AI 之前进入隔离存储。`DeliveryAddress` 将逻辑身份与物理通道分离:`qq:<id>` 和 `wechat:<id>` 可共享同一个用户历史、认知记忆与权限,但发送器、消息合并 scope 和 transport 元数据保持通道隔离。定时任务同样持久化规范 `address`,旧 `target_type + target_id` 在加载时转换为 `group:` 或 `qq:` 地址。
微信接入由主进程独立管理,不依赖 OneBot 是否在线。`WeixinService` 先校验帐号与 peer,再把已绑定来源映射为逻辑 QQ 私聊交给 `MessageHandler`;未知来源在写历史或调用 AI 之前进入隔离存储。`DeliveryAddress` 将逻辑身份与物理通道分离:`qq:<id>` 和 `wechat:<id>` 可共享同一个用户历史、认知记忆与权限,但发送器、消息合并 scope 和 transport 元数据保持通道隔离。自动化同样持久化规范 `address`,旧 `target_type + target_id` 在加载时转换为 `group:` 或 `qq:` 地址。

### "车站-列车" 队列模型

Expand All @@ -895,7 +898,7 @@ description: 从 PDF 文件中提取文本和表格,填写表单。当用户
### Skills 插件系统

- **Tools (基础工具)**:原子化的功能单元,如 `send_message`, `get_history`, `bilibili_video`, `arxiv_paper`。
- **Toolsets (复合工具集)**:11大类工具集 (group, messages, memory, contacts, group_analysis, notices, render, scheduler, cognitive, mcp, memes)。
- **Toolsets (复合工具集)**:13大类工具集 (attachments, group, messages, memory, contacts, group_analysis, music, notices, render, automation, cognitive, mcp, memes)。
- **注册表延迟导入 + 热重载**:启动时读取 `config.json` 建立本地 schema,`handler.py` 仅在首次执行工具时导入;当 `skills/` 下的 `config.json`/`handler.py` 发生变更时会自动重新加载。
- **模型 schema 按需投影**:启用 `skills.tool_search_enabled` 后,主 AI 的请求级 `ToolSearchSession` 只投影配置为始终加载的工具、虚拟 `tool_search` 和本轮已检索工具的 schema,其余工具仅注入规范名称;搜索命中的 schema 从下一模型轮开始可用,新 `ask()` 会重置。该机制不改变本地完整注册表、handler 导入时机或子 Agent 工具集。
- **Agent 自我介绍自动生成**:启动时按 Agent 代码/配置 hash 生成 `intro.generated.md` 并与 `intro.md` 合并。
Expand Down
15 changes: 15 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,18 @@
## v3.13.0 条件驱动的自动化工作流

本版本将「定时任务」整体升级为条件驱动的「自动化 / Automations」工作流:消息与时间事件命中后按 DAG 执行工具、模板与 LLM 节点,可选择接管本轮 AI;WebUI 配套 Dify 式画布编辑器,旧定时任务数据在启动时自动迁移。

- 新的工作流引擎 `src/Undefined/automations/`:支持场景多选与 @ 专项消费,节点覆盖 tool / template / 三种 LLM,可自动派生 if-else 与 LLM 分支(分支选项即工具调用),循环次数默认上限 25 且可配置调大。运行时只写 `data/automations.json`;启动时若发现旧 `scheduled_tasks.json` 则自动转为新格式写入新文件,旧文件保留、不双写。
- 运行时由 `AutomationService` 取代原调度服务,时间 job 只携带 `task_id`;`/api/v1/schedules` 与 `scheduler.*` 随之下线,对外只剩 `/api/v1/automations` 与 `automation.*` 的增删改查加启停共六个工具。
- 工作流接入群聊、QQ 私聊、微信、拍一拍、入退群五类消息入口,都在 pipeline 之后、对应 AI loop 之前触发;`consume_ai_loop=true` 时等工作流完成并拦截该入口的 AI 回复,否则后台执行、立刻放行主 AI。core 的「是否处理消息」开关是硬前提:未过群聊 / 私聊门控或 `process_poke_message` 关闭时事件直接跳过,不做自动化匹配,拍一拍也不再写历史。
- 执行模型面向实时对话优化:无相互依赖的分支依赖就绪即并行,不再整波等齐(多上游仍 AND join);消息触发的工具与 LLM 直接使用当前会话上下文,`send_message` 只填 `message` 即发往当前会话;工具节点自动注入认知记忆、知识库、表情包与附件注册表,避免已启用能力被误报未启用。
- 统一的变量系统:节点输出可存成命名变量供下游以 `{{名称}}` 引用;三种 LLM 还支持 `extract_vars`,把待抽取变量变成 `extract_<名称>` 工具由模型调用后写入;入退群事件会解析群名片 / QQ 昵称写入 `{{trigger.nickname}}`,入群欢迎预设直接可用。
- 管理能力完整开放:新增 catalog 端点与 CRUD,`POST /api/v1/automations/validate` 一次性返回全部问题;配置节 `[automations]` 支持热更新。
- WebUI 自动化页重做为 Dify 式画布编辑器:节点盘添加节点,先点出点再点目标即可连线,类型化检查器编辑参数;列表与画布上下两屏滚动切换,布局随任务保存;空白 LLM 白名单改为搜索点选。
- 运行默认放宽且全程可观测:事件类工作流默认不再冷却(`default_cooldown_seconds = 0`),并发与节点 / 工作流超时上限提高,空白 LLM 迭代上限放宽到 100;自动化各项配置只保留下限,不再有内置硬顶(如 `loop_max_iterations` 可任意调大);自动化默认不拦截主 AI(`consume_ai_loop` 默认 `false`,新建与旧数据缺省一致),WebUI 新建同样默认不自动发送终值;事件匹配、时间触发、节点执行、出站发送与超时均有详细日志。

---

## v3.12.0 斜杠命令查询、四段侧写与对外发言边界

本版本让主 AI 能查询斜杠命令并按视角过滤,把用户/群侧写拆成评价、正文、锐评并改进 `/profile` 出图;同时收紧对外说话方式,避免客服腔、内部工具名和假装能改实现。安全模型在可重试 HTTP 错误时沿用现有重试次数。
Expand Down
Loading
Loading