@@ -14,6 +14,7 @@ import '../memory/memory_manager.dart';
1414import '../memory/project_config.dart' ;
1515import '../memory/qdrant_service.dart' ;
1616import '../search/search_capability.dart' ;
17+ import '../skill/skill_model.dart' ;
1718import '../toolshell/agent_loop.dart' ;
1819import '../toolshell/executor.dart' ;
1920import '../../providers/database_provider.dart' ;
@@ -210,9 +211,8 @@ class AgentContextBuilder {
210211 PermissionMiddleware (onPermissionRequest: onPermissionRequest),
211212 ];
212213
213- // ─── 收集 skill 可读路径 ───
214- final skillsState = _ref.read (skillsProvider);
215- final activeSkillPaths = (skillsState.valueOrNull ?? [])
214+ // ─── 收集 skill 可读路径 (全局 + 项目级) ───
215+ final activeSkillPaths = _collectAllSkills ()
216216 .where ((s) => s.isActive && s.path.isNotEmpty)
217217 .map ((s) => s.path)
218218 .toList ();
@@ -291,6 +291,17 @@ class AgentContextBuilder {
291291
292292 Map <String , String > _lastSourceMapping = {};
293293
294+ /// 合并全局技能与项目级临时技能,供 Agent 运行时统一消费。
295+ ///
296+ /// 全局技能来自 [skillsProvider] (技能页可管理),项目技能来自
297+ /// [projectSkillsProvider] (仅扫描工作目录 `.toolshell/skills/` ,恒定激活)。
298+ /// 两者数据源隔离:项目技能只在此处合并挂载,不污染任何全局技能管理 UI。
299+ List <Skill > _collectAllSkills () {
300+ final global = _ref.read (skillsProvider).valueOrNull ?? const [];
301+ final project = _ref.read (projectSkillsProvider).valueOrNull ?? const [];
302+ return [...global, ...project];
303+ }
304+
294305 Future <List <Map <String , dynamic >>> _loadTools () async {
295306 final tools = < Map <String , dynamic >> [];
296307 final sourceMapping = < String , String > {};
@@ -332,10 +343,9 @@ class AgentContextBuilder {
332343 tools.addAll (sysTools);
333344 }
334345
335- // 用户技能
346+ // 用户技能 (全局 + 项目级临时技能)
336347 final registry = _ref.read (skillRegistryProvider);
337- final skillsState = _ref.read (skillsProvider);
338- final skills = skillsState.valueOrNull ?? [];
348+ final skills = _collectAllSkills ();
339349 final allSkillNames = skills
340350 .map ((s) => '${s .name }(${s .isActive ? "激活" : "未启用" })' )
341351 .toList ();
@@ -382,9 +392,9 @@ class AgentContextBuilder {
382392
383393 /// 计算当前激活用户技能的轻量签名。
384394 /// 用于判断会话中途技能集合是否变化,决定是否需要刷新 system prompt。
385- /// 与 [_buildSkillsSection] 的数据来源保持一致。
395+ /// 与 [_buildSkillsSection] 的数据来源保持一致(全局 + 项目级) 。
386396 String computeSkillSignature () {
387- final skills = _ref. read (skillsProvider).valueOrNull ?? [] ;
397+ final skills = _collectAllSkills () ;
388398 final active =
389399 skills
390400 .where ((s) => s.isActive)
@@ -438,8 +448,7 @@ class AgentContextBuilder {
438448 Future <String > _buildSkillsSection () async {
439449 final parts = < String > [];
440450 final registry = _ref.read (skillRegistryProvider);
441- final skillsState = _ref.read (skillsProvider);
442- final skills = skillsState.valueOrNull ?? [];
451+ final skills = _collectAllSkills ();
443452 for (final skill in skills) {
444453 if (! skill.isActive) continue ;
445454 final prompt = await registry.loadSkillPrompt (skill);
0 commit comments