evolcore 0.0.28 → 0.0.29

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (183) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/bin/ec-safe-output.js +270 -54
  3. package/dist/agents/baseagent-availability.js +37 -1
  4. package/dist/agents/baseagent.js +19 -9
  5. package/dist/agents/claude-runner.js +171 -13
  6. package/dist/agents/codex/app-server-client.js +6 -2
  7. package/dist/agents/codex/diagnostics.js +4 -3
  8. package/dist/agents/codex-runner.js +396 -95
  9. package/dist/agents/gemini-runner.js +35 -17
  10. package/dist/aun/group/history.js +130 -90
  11. package/dist/aun/group/operations.js +1 -3
  12. package/dist/aun/menu/transport.js +5 -3
  13. package/dist/aun/msg/managed-operation.js +70 -0
  14. package/dist/aun/msg/p2p.js +1 -3
  15. package/dist/aun/msg/upload.js +2 -2
  16. package/dist/aun/outbox.js +1 -37
  17. package/dist/channels/aun.js +249 -89
  18. package/dist/channels/daemon.js +18 -1
  19. package/dist/channels/feishu.js +1 -2
  20. package/dist/cli/agent-command.js +23 -3
  21. package/dist/cli/agent-create.js +68 -2
  22. package/dist/cli/agent.js +12 -2
  23. package/dist/cli/aun-commands.js +87 -13
  24. package/dist/cli/cli-argv.js +26 -0
  25. package/dist/cli/daemon-commands.js +40 -10
  26. package/dist/cli/data-command.js +4 -4
  27. package/dist/cli/handoff-command.js +2 -0
  28. package/dist/cli/index.js +18 -1
  29. package/dist/cli/managed-command-guard.js +10 -0
  30. package/dist/cli/memory-command.js +441 -0
  31. package/dist/cli/restart-monitor.js +62 -6
  32. package/dist/cli/skill-command.js +41 -0
  33. package/dist/cli/task-context.js +2 -23
  34. package/dist/cli/trigger-command.js +9 -1
  35. package/dist/cli/watch-msg-diag.js +209 -0
  36. package/dist/config/config-field-policy.js +52 -3
  37. package/dist/config/config-manager.js +17 -4
  38. package/dist/config/contact-book-store.js +2 -2
  39. package/dist/config/mention-mode.js +7 -2
  40. package/dist/config/merge.js +28 -9
  41. package/dist/config/resolved-config-op.js +1 -1
  42. package/dist/config/runtime-env.js +137 -0
  43. package/dist/config/schema-registry.js +11 -1
  44. package/dist/config-store.js +10 -10
  45. package/dist/core/audit/event-key.js +3 -1
  46. package/dist/core/audit/log-integrity.js +4 -0
  47. package/dist/core/auth/agent-delegation.js +2 -1
  48. package/dist/core/auth/auth-gateway.js +13 -6
  49. package/dist/core/auth/authorization-audit.js +54 -19
  50. package/dist/core/auth/operation-authorizer.js +17 -0
  51. package/dist/core/auth/operation-catalog.js +9 -0
  52. package/dist/core/causation/context.js +5 -1
  53. package/dist/core/command/agent-control.js +1 -2
  54. package/dist/core/command/command-handler.js +51 -23
  55. package/dist/core/command/memory-slash.js +270 -0
  56. package/dist/core/command/menu-catalog.js +1 -0
  57. package/dist/core/command/menu-handler.js +315 -60
  58. package/dist/core/command/menu-protocol.js +42 -4
  59. package/dist/core/command/slash-gate.js +10 -10
  60. package/dist/core/command/slash-handler.js +206 -64
  61. package/dist/core/data-migration.js +282 -505
  62. package/dist/core/event-catalog.js +26 -0
  63. package/dist/core/evolagent-registry.js +6 -0
  64. package/dist/core/evolagent.js +0 -10
  65. package/dist/core/handoff/store.js +1 -20
  66. package/dist/core/inference/text-inference.js +57 -1
  67. package/dist/core/memory/consolidation-context.js +505 -0
  68. package/dist/core/memory/consolidation-ops-records.js +124 -0
  69. package/dist/core/memory/consolidation-trigger.js +394 -0
  70. package/dist/core/memory/index-manager.js +308 -0
  71. package/dist/core/memory/launch-consolidation.js +395 -0
  72. package/dist/core/memory/memory-admin.js +234 -0
  73. package/dist/core/memory/memory-document.js +100 -0
  74. package/dist/core/memory/memory-session-policy.js +41 -0
  75. package/dist/core/memory/memory-signature.js +257 -0
  76. package/dist/core/memory/memory-writer.js +432 -0
  77. package/dist/core/memory/staleness.js +117 -0
  78. package/dist/core/message/auto-mention-gate.js +454 -0
  79. package/dist/core/message/im-renderer.js +69 -16
  80. package/dist/core/message/message-bridge.js +287 -21
  81. package/dist/core/message/message-log.js +1 -0
  82. package/dist/core/message/message-queue.js +114 -27
  83. package/dist/core/message/pending-hints.js +329 -161
  84. package/dist/core/message/response-engine.js +567 -80
  85. package/dist/core/permission/ec-command-parser.js +1029 -80
  86. package/dist/core/permission/protected-paths.js +376 -126
  87. package/dist/core/permission/sandbox-runtime.js +40 -12
  88. package/dist/core/permission/tool-error-code.js +96 -13
  89. package/dist/core/permission/tool-policy.js +276 -23
  90. package/dist/core/role/runtime-policy.js +3 -7
  91. package/dist/core/session/{runner-task-history.js → runner-event-summary.js} +1 -1
  92. package/dist/core/session/session-fs-store.js +0 -76
  93. package/dist/core/session/session-idle-monitor.js +355 -0
  94. package/dist/core/session/session-manager.js +478 -17
  95. package/dist/core/session/session-mapper.js +33 -16
  96. package/dist/core/session/session-renew.js +217 -155
  97. package/dist/core/session/{session-turns.js → session-transcript.js} +35 -6
  98. package/dist/core/skill/global-watcher.js +282 -0
  99. package/dist/core/skill/index-generator.js +84 -0
  100. package/dist/core/skill/startup.js +73 -0
  101. package/dist/core/skill/switch-resolver.js +115 -0
  102. package/dist/core/task/task-activity-store.js +219 -0
  103. package/dist/eck/kit-renderer.js +30 -3
  104. package/dist/eck/manifest-engine.js +26 -4
  105. package/dist/index.js +708 -18
  106. package/dist/ipc.js +564 -2
  107. package/dist/paths.js +30 -9
  108. package/dist/response-system/engines/v1/proactive-flow.js +116 -15
  109. package/dist/response-system/modes/single-session/index.js +3 -0
  110. package/dist/trigger/feedback.js +1 -0
  111. package/dist/trigger/manager.js +0 -10
  112. package/dist/trigger/scheduler.js +11 -0
  113. package/dist/trigger/validation.js +22 -0
  114. package/dist/utils/avatar-upload.js +59 -18
  115. package/dist/utils/error-dict.json +6 -3
  116. package/dist/utils/error-utils.js +27 -0
  117. package/dist/utils/logger.js +32 -10
  118. package/dist/utils/media-cache.js +84 -0
  119. package/dist/utils/msg-diag.js +97 -0
  120. package/dist/utils/welcome.js +37 -8
  121. package/kits/docs/AUTHORING.md +314 -0
  122. package/kits/docs/GUIDE.md +2 -0
  123. package/kits/docs/INDEX.md +2 -0
  124. package/kits/docs/aun/CHEATSHEET.md +4 -0
  125. package/kits/docs/aun/SDK.md +60 -0
  126. package/kits/docs/context-assembly.md +10 -6
  127. package/kits/docs/evolcore/INDEX.md +17 -3
  128. package/kits/docs/evolcore/agent-create.md +24 -0
  129. package/kits/docs/evolcore/agent.md +5 -2
  130. package/kits/docs/evolcore/config.md +1 -1
  131. package/kits/docs/evolcore/ec-capabilities.md +364 -0
  132. package/kits/docs/evolcore/group.md +34 -18
  133. package/kits/docs/evolcore/memory-architecture.md +78 -0
  134. package/kits/docs/evolcore/memory-consolidation-batches.md +133 -0
  135. package/kits/docs/evolcore/memory-consolidation.md +263 -0
  136. package/kits/docs/evolcore/memory-tags.md +63 -0
  137. package/kits/docs/evolcore/memory.md +110 -0
  138. package/kits/docs/evolcore/menu-client.md +27 -11
  139. package/kits/{schemas → docs/evolcore}/menu-exec-schema-commands.md +12 -6
  140. package/kits/docs/evolcore/menu-protocol.md +213 -0
  141. package/kits/docs/evolcore/msg.md +2 -0
  142. package/kits/docs/evolcore/trigger.md +7 -5
  143. package/kits/docs/path-registry.md +6 -8
  144. package/kits/docs/prompt-loading-architecture.md +5 -3
  145. package/kits/docs/venues/group.md +5 -4
  146. package/kits/eck_manifest.json +294 -88
  147. package/kits/eck_manifest.memory.json +257 -0
  148. package/kits/rules/03-identity.md +8 -8
  149. package/kits/rules/05-venue.md +4 -2
  150. package/kits/rules/06-channel.md +1 -1
  151. package/kits/schemas/_meta.json +276 -47
  152. package/kits/schemas/agent-config.schema.12.json +38 -2
  153. package/kits/schemas/agent-config.schema.13.json +591 -0
  154. package/kits/schemas/daemon.schema.6.json +9 -9
  155. package/kits/schemas/defaults.schema.5.json +29 -0
  156. package/kits/schemas/relation-config.schema.8.json +14 -1
  157. package/kits/schemas/relation-config.schema.9.json +129 -0
  158. package/kits/schemas/role-config.schema.1.json +3 -3
  159. package/kits/skills/.switches.json +3 -0
  160. package/kits/skills/ec-skill/SKILL.md +217 -0
  161. package/kits/skills/ec-skill/scripts/cli.mjs +128 -0
  162. package/kits/skills/ec-skill/scripts/deps.mjs +107 -0
  163. package/kits/skills/ec-skill/scripts/frontmatter.mjs +104 -0
  164. package/kits/skills/ec-skill/scripts/skill.mjs +629 -0
  165. package/kits/skills/ec-skill/scripts/template/SKILL.md.tmpl +30 -0
  166. package/kits/templates/decision/auto-mention.md +25 -0
  167. package/kits/templates/decision/session-renew.md +22 -0
  168. package/kits/templates/memory-consolidation/forget.md +104 -0
  169. package/kits/templates/memory-consolidation/generalize.md +76 -0
  170. package/kits/templates/memory-consolidation/notes.md +133 -0
  171. package/kits/templates/memory-consolidation/profile.md +58 -0
  172. package/kits/templates/memory-consolidation/promote.md +72 -0
  173. package/kits/templates/memory-consolidation/workflow.md +75 -0
  174. package/kits/templates/system-fragments/bootstrap.md +14 -5
  175. package/kits/templates/system-fragments/commands.md +1 -0
  176. package/kits/templates/system-fragments/group-history.md +6 -0
  177. package/kits/templates/system-fragments/identity.md +0 -3
  178. package/kits/templates/system-fragments/memory.md +79 -0
  179. package/kits/templates/system-fragments/reply.md +1 -0
  180. package/kits/templates/system-fragments/venue.md +1 -1
  181. package/package.json +4 -6
  182. package/dist/trigger/legacy-session-history.js +0 -19
  183. package/kits/templates/system-fragments/group-unread-history.md +0 -7
@@ -97,12 +97,40 @@
97
97
  }
98
98
  }
99
99
  },
100
+ "decision_model": {
101
+ "type": "object",
102
+ "description": "Session Renew 和群聊 auto 注意力分类使用的 Decision Model 配置;base_url 为完整请求地址,运行时直接 POST。",
103
+ "x-merge": "dict",
104
+ "additionalProperties": false,
105
+ "properties": {
106
+ "model": { "type": "string", "minLength": 1 },
107
+ "base_url": { "type": "string", "minLength": 1 },
108
+ "apikey": { "type": "string", "minLength": 1 },
109
+ "headers": {
110
+ "type": "object",
111
+ "propertyNames": { "pattern": "^[!#$%&'*+.^_`|~0-9A-Za-z-]+$" },
112
+ "additionalProperties": { "type": "string", "pattern": "^[^\\u0000\\r\\n]*$" }
113
+ },
114
+ "queryParams": {
115
+ "type": "object",
116
+ "propertyNames": { "minLength": 1 },
117
+ "additionalProperties": { "type": "string" }
118
+ }
119
+ }
120
+ },
100
121
  "responseMode": { "type": "string", "x-merge": "scalar" },
101
122
  "responseModeParams": {
102
123
  "type": "object",
103
124
  "x-merge": "dict",
104
125
  "description": "响应模式特有参数的全局默认字典,按模式 id 分桶:{ [modeId]: {...} }"
105
126
  },
127
+ "autoMentionQuietWindowMs": {
128
+ "type": "number",
129
+ "minimum": 0,
130
+ "default": 3000,
131
+ "x-merge": "scalar",
132
+ "description": "群聊 auto 注意力分类的静默等待窗口,单位为毫秒;默认 3000"
133
+ },
106
134
  "config": { "type": "object", "x-merge": "dict" },
107
135
  "session_renew": {
108
136
  "type": "object",
@@ -113,6 +141,7 @@
113
141
  "enabled": { "type": "boolean", "default": false, "description": "是否启用超时后的会话连续性判定" },
114
142
  "after_hours": { "type": "number", "exclusiveMinimum": 0, "default": 24, "description": "距最后一条有效对话超过该小时数才触发判定" },
115
143
  "fallback_action": { "type": "string", "enum": ["continue", "new"], "default": "continue", "description": "无法判定时的兜底动作", "x-enumDescriptions": { "continue": "继续沿用当前会话", "new": "开启新会话" } }
144
+ ,"new_probability_threshold": { "type": "number", "minimum": 0, "maximum": 1, "default": 0.85, "description": "noul 达到该概率后开启新会话" }
116
145
  }
117
146
  }
118
147
  }
@@ -64,7 +64,19 @@
64
64
  }
65
65
  },
66
66
  "chatmode": { "type": "object", "x-merge": "dict", "properties": { "private": { "enum": ["interactive", "proactive"] }, "group": { "enum": ["interactive", "proactive"] }, "nothuman": { "enum": ["interactive", "proactive"] } }, "additionalProperties": false },
67
- "mentionMode": { "type": "string", "enum": ["disabled", "mention-only"], "x-merge": "scalar" },
67
+ "mentionMode": { "type": "string", "enum": ["disabled", "mention-only", "auto"], "x-merge": "scalar" },
68
+ "autoMentionQuietWindowMs": {
69
+ "type": "number",
70
+ "minimum": 0,
71
+ "default": 3000,
72
+ "x-merge": "scalar",
73
+ "description": "群聊 auto 注意力分类的静默等待窗口,单位为毫秒;默认 3000"
74
+ },
75
+ "sessionIdleSec": {
76
+ "type": "number",
77
+ "x-merge": "scalar",
78
+ "description": "会话闲置周期,单位为秒;缺省或小于等于 0 关闭,正值小于 30 秒按 30 秒处理"
79
+ },
68
80
  "model": { "type": "string", "x-merge": "scalar" },
69
81
  "responseMode": { "type": "string", "x-merge": "scalar" },
70
82
  "responseModeParams": { "type": "object", "x-merge": "dict" },
@@ -80,6 +92,7 @@
80
92
  "enabled": { "type": "boolean" },
81
93
  "after_hours": { "type": "number", "exclusiveMinimum": 0 },
82
94
  "fallback_action": { "type": "string", "enum": ["continue", "new"] }
95
+ ,"new_probability_threshold": { "type": "number", "minimum": 0, "maximum": 1 }
83
96
  }
84
97
  },
85
98
  "group_venue_sync": { "type": "object", "x-merge": "dict" },
@@ -0,0 +1,129 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-07/schema#",
3
+ "$id": "relation-config.schema.9.json",
4
+ "title": "RelationConfig v9 (agents/{aid}/relations/{peerKey}/config.json)",
5
+ "x-logical-name": "relation-config",
6
+ "x-scope": "relation",
7
+ "type": "object",
8
+ "additionalProperties": true,
9
+ "not": {
10
+ "anyOf": [
11
+ { "required": ["permissionMode"] },
12
+ { "required": ["roles"] },
13
+ {
14
+ "required": ["aun"],
15
+ "properties": {
16
+ "aun": {
17
+ "type": "object",
18
+ "required": ["defaultEncrypt"]
19
+ }
20
+ }
21
+ }
22
+ ]
23
+ },
24
+ "properties": {
25
+ "$schema_version": { "type": "number", "const": 9, "default": 9, "x-merge": "scalar" },
26
+ "targetKind": { "type": "string", "enum": ["private", "group"], "x-merge": "scalar" },
27
+ "role": { "type": ["string", "null"], "pattern": "^(?!owner$)[a-z0-9_-]+$", "x-merge": "scalar", "description": "关系角色;允许 admin/member/visitor/自定义角色,禁止 owner" },
28
+ "active_baseagent": { "type": "string", "x-merge": "scalar" },
29
+ "models": { "type": "object", "x-merge": "dict" },
30
+ "baseagents": {
31
+ "type": "object",
32
+ "x-merge": "dict",
33
+ "description": "关系级模型覆盖;备用模型链只能在 defaults.json 配置。",
34
+ "additionalProperties": {
35
+ "not": {
36
+ "type": "object",
37
+ "required": ["fallbackModels"]
38
+ },
39
+ "properties": {
40
+ "headers": {
41
+ "type": "object",
42
+ "propertyNames": { "pattern": "^[!#$%&'*+.^_`|~0-9A-Za-z-]+$" },
43
+ "additionalProperties": { "type": "string", "pattern": "^[^\\u0000\\r\\n]*$" }
44
+ },
45
+ "queryParams": {
46
+ "type": "object",
47
+ "propertyNames": { "minLength": 1 },
48
+ "additionalProperties": { "type": "string" }
49
+ },
50
+ "auxiliaryModel": {
51
+ "type": "string",
52
+ "minLength": 1,
53
+ "description": "Session Renew 语义连续性判断使用的 direct 辅助模型。"
54
+ },
55
+ "auxiliaryEffort": {
56
+ "type": "string",
57
+ "enum": ["low", "medium", "high", "xhigh", "max"],
58
+ "description": "Session Renew 辅助模型的可选推理强度。"
59
+ }
60
+ },
61
+ "dependencies": {
62
+ "auxiliaryEffort": ["auxiliaryModel"]
63
+ }
64
+ }
65
+ },
66
+ "chatmode": { "type": "object", "x-merge": "dict", "properties": { "private": { "enum": ["interactive", "proactive"] }, "group": { "enum": ["interactive", "proactive"] }, "nothuman": { "enum": ["interactive", "proactive"] } }, "additionalProperties": false },
67
+ "mentionMode": { "type": "string", "enum": ["disabled", "mention-only", "auto"], "x-merge": "scalar" },
68
+ "autoMentionQuietWindowMs": {
69
+ "type": "number",
70
+ "minimum": 0,
71
+ "default": 3000,
72
+ "x-merge": "scalar",
73
+ "description": "群聊 auto 注意力分类的静默等待窗口,单位为毫秒;默认 3000"
74
+ },
75
+ "sessionIdleSeconds": {
76
+ "type": "number",
77
+ "x-merge": "scalar",
78
+ "description": "会话闲置周期,单位为秒;缺省或小于等于 0 关闭,正值小于 30 秒按 30 秒处理"
79
+ },
80
+ "model": { "type": "string", "x-merge": "scalar" },
81
+ "responseMode": { "type": "string", "x-merge": "scalar" },
82
+ "responseModeParams": { "type": "object", "x-merge": "dict" },
83
+ "flush_delay": { "type": "number", "x-merge": "scalar" },
84
+ "debounce": { "type": "number", "x-merge": "scalar" },
85
+ "show_activities": { "type": "string", "enum": ["all", "text", "none"], "x-merge": "scalar" },
86
+ "enable_rich_content": { "type": "boolean", "x-merge": "scalar" },
87
+ "session_renew": {
88
+ "type": "object",
89
+ "x-merge": "dict",
90
+ "additionalProperties": false,
91
+ "properties": {
92
+ "enabled": { "type": "boolean" },
93
+ "after_hours": { "type": "number", "exclusiveMinimum": 0 },
94
+ "fallback_action": { "type": "string", "enum": ["continue", "new"] },
95
+ "new_probability_threshold": { "type": "number", "minimum": 0, "maximum": 1 }
96
+ }
97
+ },
98
+ "memory": {
99
+ "type": "object",
100
+ "x-merge": "dict",
101
+ "additionalProperties": false,
102
+ "description": "关系级记忆开关;enableRelation 由对端自主配置,与 agent 级 memory.enableRelation 做 AND 合并(任意层为 false 则关闭)。",
103
+ "properties": {
104
+ "enableRelation": {
105
+ "type": "boolean",
106
+ "x-merge-logic": "AND",
107
+ "description": "对端自主控制本关系的 relation 作用域记忆是否启用;与 agent 级 enableRelation 做 AND 合并。"
108
+ }
109
+ }
110
+ },
111
+ "group_venue_sync": { "type": "object", "x-merge": "dict" },
112
+ "groupRules": {
113
+ "type": "object",
114
+ "x-merge": "dict",
115
+ "additionalProperties": false,
116
+ "properties": {
117
+ "mode": {
118
+ "type": "string",
119
+ "enum": ["load", "ignore"],
120
+ "default": "load",
121
+ "description": "是否读取并注入当前 AUN 群已发布的 /rules.md;默认 load。"
122
+ }
123
+ }
124
+ },
125
+ "render": { "type": "object", "x-merge": "dict" },
126
+ "sessionManifests": { "type": "object", "x-merge": "dict" },
127
+ "extra_backup": { "type": "array", "items": { "type": "object" }, "x-merge": "list" }
128
+ }
129
+ }
@@ -9,7 +9,7 @@
9
9
  { "value": "permissionMode", "label": "Permission Mode", "description": "角色的工具调用审批模式;只能由角色策略决定,关系级不可覆盖。", "valueType": "enum", "hasOptions": true, "relationOverrideApplied": false, "constraintsApplied": true, "editable": true, "x-runtimeApplied": true, "x-optionsSource": "static-enum", "options": [{ "value": "readonly", "label": "Readonly" }, { "value": "auto", "label": "Auto" }, { "value": "request", "label": "Request" }, { "value": "bypass", "label": "Bypass" }] },
10
10
  { "value": "chatmode.private", "label": "Private Chat Mode", "description": "角色在私聊场景中的响应方式策略。", "valueType": "enum", "hasOptions": true, "relationOverrideApplied": true, "constraintsApplied": true, "editable": true, "x-runtimeApplied": true, "x-optionsSource": "static-enum", "options": [{ "value": "interactive", "label": "Interactive" }, { "value": "proactive", "label": "Proactive" }] },
11
11
  { "value": "chatmode.group", "label": "Group Chat Mode", "description": "角色在群聊场景中的响应方式策略。", "valueType": "enum", "hasOptions": true, "relationOverrideApplied": true, "constraintsApplied": true, "editable": true, "x-runtimeApplied": true, "x-optionsSource": "static-enum", "options": [{ "value": "interactive", "label": "Interactive" }, { "value": "proactive", "label": "Proactive" }] },
12
- { "value": "mentionMode", "label": "Group Mention Mode", "description": "角色在群聊场景中的提及响应策略。", "valueType": "enum", "hasOptions": true, "relationOverrideApplied": true, "constraintsApplied": true, "editable": true, "x-runtimeApplied": true, "x-optionsSource": "static-enum", "options": [{ "value": "disabled", "label": "Disabled" }, { "value": "mention-only", "label": "Mention Only" }] },
12
+ { "value": "mentionMode", "label": "Group Mention Mode", "description": "角色在群聊场景中的提及响应策略。", "valueType": "enum", "hasOptions": true, "relationOverrideApplied": true, "constraintsApplied": true, "editable": true, "x-runtimeApplied": true, "x-optionsSource": "static-enum", "options": [{ "value": "disabled", "label": "Disabled" }, { "value": "mention-only", "label": "Mention Only" }, { "value": "auto", "label": "Auto" }] },
13
13
  { "value": "baseagents.claude.model", "label": "Claude Model", "description": "角色可使用的 Claude 默认模型和模型白名单。", "valueType": "model", "hasOptions": true, "relationOverrideApplied": true, "constraintsApplied": true, "editable": true, "x-runtimeApplied": true, "x-optionsSource": "model-catalog", "patterns": [{ "value": "*", "label": "All Claude models" }, { "value": "claude-opus-*", "label": "Claude Opus family" }, { "value": "claude-sonnet-*", "label": "Claude Sonnet family" }, { "value": "claude-haiku-*", "label": "Claude Haiku family" }] },
14
14
  { "value": "baseagents.claude.effort", "label": "Claude Effort", "description": "角色使用 Claude 时的默认推理强度及可覆盖范围。", "valueType": "enum", "hasOptions": true, "relationOverrideApplied": true, "constraintsApplied": true, "editable": true, "x-runtimeApplied": true, "x-optionsSource": "static-enum", "options": [{ "value": "auto", "label": "Auto" }, { "value": "low", "label": "Low" }, { "value": "medium", "label": "Medium" }, { "value": "high", "label": "High" }, { "value": "xhigh", "label": "Xhigh" }, { "value": "max", "label": "Max" }] },
15
15
  { "value": "baseagents.codex.model", "label": "Codex Model", "description": "角色可使用的 Codex 默认模型和模型白名单。", "valueType": "model", "hasOptions": true, "relationOverrideApplied": true, "constraintsApplied": true, "editable": true, "x-runtimeApplied": true, "x-optionsSource": "model-catalog", "patterns": [{ "value": "*", "label": "All Codex models" }, { "value": "gpt-5.4*", "label": "GPT-5.4 family" }, { "value": "gpt-5.3-codex*", "label": "GPT-5.3 Codex family" }] },
@@ -73,9 +73,9 @@
73
73
  "additionalProperties": false,
74
74
  "description": "该角色在群聊场景中的提及响应策略。",
75
75
  "properties": {
76
- "default": { "type": "string", "enum": ["disabled", "mention-only"], "description": "未设置有效关系级覆盖时使用的群聊提及响应策略。", "x-enumDescriptions": { "disabled": "不要求被提及即可响应", "mention-only": "仅在被明确提及时响应" } },
76
+ "default": { "type": "string", "enum": ["disabled", "mention-only", "auto"], "description": "未设置有效关系级覆盖时使用的群聊提及响应策略。", "x-enumDescriptions": { "disabled": "不要求被提及即可响应", "mention-only": "仅在被明确提及时响应", "auto": "按群内上下文自动判断" } },
77
77
  "allowOverride": { "type": "boolean", "default": false, "description": "是否允许该角色在关系级覆盖群聊提及响应策略;缺省为 false。" },
78
- "allowedValues": { "type": "array", "items": { "type": "string", "enum": ["disabled", "mention-only"], "description": "一个可用于群聊提及响应策略覆盖的值。", "x-enumDescriptions": { "disabled": "不要求被提及即可响应", "mention-only": "仅在被明确提及时响应" } }, "uniqueItems": true, "description": "允许关系级覆盖到的群聊提及响应策略白名单;若提供,必须包含 default。" },
78
+ "allowedValues": { "type": "array", "items": { "type": "string", "enum": ["disabled", "mention-only", "auto"], "description": "一个可用于群聊提及响应策略覆盖的值。", "x-enumDescriptions": { "disabled": "不要求被提及即可响应", "mention-only": "仅在被明确提及时响应", "auto": "按群内上下文自动判断" } }, "uniqueItems": true, "description": "允许关系级覆盖到的群聊提及响应策略白名单;若提供,必须包含 default。" },
79
79
  "reason": { "type": "string", "description": "采用该群聊提及响应策略的可审计原因或管理备注。" }
80
80
  }
81
81
  },
@@ -0,0 +1,3 @@
1
+ {
2
+ "ec-skill": { "enabled": true, "locked": true }
3
+ }
@@ -0,0 +1,217 @@
1
+ ---
2
+ name: ec-skill
3
+ description: >-
4
+ EC 技能系统的说明与工具。用于新建、安装、删除、启用、禁用、查看和校验 EC 技能。
5
+ 当用户要求"创建技能""新建 skill""安装技能""装个 skill""删除/禁用/启用技能"
6
+ "看看有哪些技能""这个技能为什么没生效",或询问技能系统怎么工作、
7
+ SKILL.md 怎么写、技能放在哪里时使用。
8
+ 不适用于 base agent(Claude Code / Codex)自己的技能——那些由各自的工具管理。
9
+ license: MIT
10
+ ---
11
+
12
+ # EC Skill 管理
13
+
14
+ EC 的技能系统:**一组可加载的能力单元**,每个技能是一个目录,里面放 `SKILL.md`。
15
+ 本技能既是这套系统的说明书,也是操作它的工具。
16
+
17
+ ## 先读文档
18
+
19
+ **机制概要(随包发布,推荐先读)**:
20
+
21
+ ```
22
+ <包根>/kits/docs/evolcore/ec-capabilities.md
23
+ ```
24
+
25
+ > 文件名不叫 `skills.md`——`package.json` 的 `files` 里有 `!skills/` 规则,
26
+ > 任何名字含 `skills` 的文件在打包时会被一并排除。这个坑别再踩。
27
+
28
+ 涵盖:三级目录、开关覆盖链、`locked` 正交语义、渐进式披露、`description` 写法、
29
+ 路径拼接约定、依赖声明、权限取交集、边界情况与常见坑。本文只列操作要点,细节以那份为准。
30
+
31
+ 改写技能正文、排查「技能为什么没生效」、判断某个做法是否合规时,**先读它**。
32
+
33
+ **开发设计文档(仅源码仓库,不随包发布)**:
34
+
35
+ 如果你手上是 evolcore 源码仓库(`<仓库根>/docs/skills/` 存在),以下四份讲的是
36
+ 机制**为什么这么设计**:
37
+
38
+ | 文档 | 内容 |
39
+ |---|---|
40
+ | `docs/skills/skill-md-spec-and-loading.md` | `SKILL.md` 规范、frontmatter 字段语义、渐进式披露、三家对照 |
41
+ | `docs/skills/ec-skill-system-design.md` | 三级目录、开关模型、覆盖链、`locked` 正交语义、前端展示 |
42
+ | `docs/skills/ec-skill-injection.md` | 索引怎么生成、防抖、文件格式、manifest 注入段位 |
43
+ | `docs/skills/skill-script-execution.md` | 脚本执行、路径解析、依赖检查、权限闸门、隔离与 8 个待澄清问题 |
44
+
45
+ **不要假设这些文档存在**——npm 包只发布 `kits/`,`docs/` 被排除。先确认目录再读。
46
+
47
+ ## 系统怎么工作
48
+
49
+ ### 三级目录
50
+
51
+ | 级别 | 位置 | 谁维护 |
52
+ |---|---|---|
53
+ | 内置级 | `<包根>/kits/skills/` | 随包发布,用户不应改 |
54
+ | 本机级 | `$EVOLCORE_HOME/skills/` | 用户安装,本机所有 agent 共享 |
55
+ | Agent 级 | `$EVOLCORE_AGENT_DIR/skills/` | 只放开关,不放 SKILL.md |
56
+
57
+ 用 `ec skill where` 可打印这三条路径的**实际值**,不要凭记忆猜。
58
+
59
+ ### 开关:每级一个 `.switches.json`
60
+
61
+ 开关**不是**每技能一个文件,而是每级一个字典:
62
+
63
+ ```json
64
+ {
65
+ "my-skill": { "enabled": true },
66
+ "core-guard": { "enabled": true, "locked": true }
67
+ }
68
+ ```
69
+
70
+ - **技能名不在字典里 → 禁用**(开关字典是显式白名单,缺省即关)
71
+ - `enabled: true` 才启用;字段缺失或写成其它值都按禁用处理
72
+ - `locked` 只在**内置级**有意义,表示"任何级别都关不掉"
73
+ - 覆盖链:**Agent 级 > 本机级 > 内置级**(由近及远,谁有声明谁说了算)
74
+
75
+ `locked: true` 与 `enabled` 是独立维度:`locked` 只表达"不可覆盖",不表达"强制开"。
76
+ 所以 `{"enabled": false, "locked": true}` 是"关着且谁都打不开"。
77
+
78
+ > 缺省即禁用是刻意设计:**安装不写开关文件**,兄弟技能不会因为"忘了关"而悄悄生效,
79
+ > 只有显式 `enable` 过的技能才进索引。
80
+
81
+ ### 索引:渐进式披露
82
+
83
+ 技能正文**不常驻上下文**。常驻的只有每个技能的 `name` + `description`,写在
84
+ `<Agent 目录>/skills/.index-builtin.md` 与 `.index-local.md` 两个文件里,
85
+ 由 ECK manifest 注入。
86
+
87
+ 模型看到索引 → 按 description 判断相关性 → 命中才 Read 完整 `SKILL.md`。
88
+ 所以 **description 是路由器**,不是介绍文案:写得含糊,技能永远不会被选中。
89
+
90
+ 索引在技能变更后由监控器约 2 秒内标记待更新,下一条消息处理时重建,不需要手工触发。
91
+
92
+ ### 路径:模型自己拼绝对路径
93
+
94
+ EC 不会把 cwd 设到技能目录,所以 `SKILL.md` 里写裸相对路径(`scripts/foo.mjs`)时,
95
+ **必须由模型自己拼成绝对路径再执行**。索引文件里给了根目录和拼法。
96
+
97
+ 配套硬要求:**脚本内部要用自身位置定位资源**,不能依赖 cwd:
98
+
99
+ ```js
100
+ // 好:从脚本自身推
101
+ const SKILL_DIR = path.resolve(import.meta.dirname, '..');
102
+
103
+ // 差:依赖 cwd,cwd 不对就挂
104
+ fs.readFileSync('assets/template.csv');
105
+ ```
106
+
107
+ ## 怎么写一个技能
108
+
109
+ 一个技能一个目录,目录名 = `SKILL.md` 里 `name` 字段(kebab-case):
110
+
111
+ ```
112
+ my-skill/
113
+ ├── SKILL.md 必须。frontmatter + Markdown 正文
114
+ ├── references/ 可选。大块资料,按需读取,不进默认上下文
115
+ ├── scripts/ 可选。确定性脚本
116
+ └── assets/ 可选。模板、样例数据
117
+ ```
118
+
119
+ frontmatter 必填两项:
120
+
121
+ ```yaml
122
+ ---
123
+ name: my-skill # 必须与目录名一致
124
+ description: >- # 最关键:写清做什么 + 触发场景 + 不适用场景
125
+ 一句话说清能力。当用户要求……时使用。不适用于……
126
+ ---
127
+ ```
128
+
129
+ 正文建议结构:**目标 → 步骤(编号、祈使句)→ 输出契约 → 边界情况 → 参考资料指引**。
130
+ 超过 500 行就把细节挪到 `references/`。
131
+
132
+ ## 工具
133
+
134
+ 脚本自定位,**执行时必须写完整绝对路径**(不要依赖 cwd):
135
+
136
+ ```bash
137
+ node "<技能目录>/scripts/cli.mjs" <子命令>
138
+ ```
139
+
140
+ | 子命令 | 作用 |
141
+ |---|---|
142
+ | `list [--json]` | 列出所有技能:名称、来源、最终状态 |
143
+ | `info <name> [--json]` | 单技能详情:路径、描述、三级开关、生效依据、校验问题 |
144
+ | `create <name> [--desc "..."] [--force] [--enable]` | 新建技能骨架到本机级(默认禁用) |
145
+ | `install <源> [--force] [--enable]` | 安装技能(目录 / `.zip` / `.md`)到本机级(默认禁用) |
146
+ | `remove <name>` | 删除本机技能(内置技能不能删) |
147
+ | `enable <name> [--level agent\|local]` | 启用(默认 agent 级) |
148
+ | `disable <name> [--level agent\|local]` | 禁用(默认 agent 级) |
149
+ | `validate <name\|路径>` | 校验 SKILL.md 是否合规 |
150
+ | `where` | 打印三级根目录的实际路径 |
151
+
152
+ ### 常见任务
153
+
154
+ **新建一个技能**:
155
+
156
+ ```bash
157
+ node "<技能目录>/scripts/cli.mjs" create my-analyzer --desc "分析日志并汇总。当用户要求分析日志时使用。"
158
+ ```
159
+
160
+ 生成后**必须补全 description**——它是技能被选中的唯一依据。
161
+
162
+ **安装**:支持目录、`.zip`、单个 `.md`。安装前会校验 `SKILL.md`,
163
+ 不合规直接拒绝。`.zip` 首次使用会自动装解压依赖(需要联网,之后离线可用)。
164
+
165
+ **装完默认禁用**:`install`(和 `create`)**不写开关文件**——开关字典里没有该技能
166
+ 就等于禁用,技能不进索引、不会被模型选中。确认要用之后显式启用:
167
+
168
+ ```bash
169
+ node "<技能目录>/scripts/cli.mjs" enable <name>
170
+ ```
171
+
172
+ 需要装完即启用时加 `--enable`(此时才写入 `{"enabled": true}`):
173
+ `install <源> --enable`。这是刻意设计——陌生技能不应在未经确认时自动生效。
174
+
175
+ > **装完必须问一句**:`install` 成功后,**主动询问用户是否启用**,别默认替用户开。
176
+ > 用户确认后再跑 `enable <name>`(本机级全机生效要 `--level local`);
177
+ > 用户明确说"启用"时也可直接用 `install <源> --enable` 一步到位。
178
+ > 询问话术一句话即可,不要展开成选项清单。
179
+
180
+ **为什么某个技能没生效**:用 `info <name>` 看 `生效依据` 那一行,
181
+ 它会指出是 Agent 级 / 本机级 / 内置级 / 默认值决定了当前状态。
182
+
183
+ ### 权限:写入类子命令不是谁都能跑
184
+
185
+ 写入类子命令(`create` / `install` / `remove` / `enable` / `disable`)有权限门禁,
186
+ 判据取自当前会话的角色与场景:
187
+
188
+ | 情形 | 结果 |
189
+ |------|------|
190
+ | 群聊里(**含 owner 本人**) | 一律拒绝 |
191
+ | 私聊 + Agent 级写(`--level agent`,默认) | 需本 Agent 的 **owner** |
192
+ | 私聊 + 本机级写(`install` / `remove` / `create` / `--level local`) | 需 **daemonowner** |
193
+ | 宿主终端直连(无会话上下文) | 放行 |
194
+
195
+ **在群里被拒时不要重试、不要换参数绕过**:这是设计使然——技能开关是 agent 自身配置,
196
+ 不该被群里的对话推动。直接把结论告诉对方,请其私聊提出或由管理员在终端执行。
197
+
198
+ 本机级目录是**整机所有 agent 共享**的,所以装/删/建和本机级开关同档,都要 daemonowner。
199
+
200
+ 只读子命令(`list` / `info` / `where` / `validate`)不受限制。
201
+
202
+ ## 边界情况
203
+
204
+ - **装完默认禁用**:`install` / `create` 不写开关文件,缺省即禁用,
205
+ 技能不进索引、不被选中,等确认后再 `enable`。加 `--enable` 可装完即启用。
206
+ - **开关是显式白名单**:字典里没有该技能 = 关。手改 `.switches.json` 时别写 `false` 当"关"——
207
+ 删掉条目才是缺省关。
208
+ - **内置技能不可删**:随包发布,`remove` 会拒绝。要停用请用 `disable`。
209
+ - **Agent 级不能装技能**:那一级只有 `.switches.json`。想让某技能只对单个 agent 生效,
210
+ 先装到本机级,再对其他 agent `disable`。
211
+ - **`locked` 技能关不掉**:`enable/disable` 会拒绝,并说明原因。
212
+ - **离线环境**:`install` 用目录方式不受影响;`.zip` 需要联网装一次解压依赖。
213
+
214
+ ## 依赖说明
215
+
216
+ `scripts/deps.mjs` 负责按需把第三方包装到 `$EVOLCORE_HOME/skills/.deps/`,
217
+ 版本在文件里锁死。装过一次后**离线可用**——每次都先查该目录,命中就不再联网。
@@ -0,0 +1,128 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * ec-skill 命令行入口。
4
+ *
5
+ * 这是薄壳:解析参数 → 调用 skill.mjs 的导出函数。
6
+ * 逻辑一律不写在这里,避免和模型侧的用法产生两份实现。
7
+ */
8
+
9
+ import * as S from './skill.mjs';
10
+
11
+ const USAGE = `ec skill —— EC 技能管理
12
+
13
+ 用法:
14
+ ec skill list [--json] 列出所有技能
15
+ ec skill info <name> [--json] 查看单个技能详情
16
+ ec skill create <name> [--desc "..."] [--force] [--enable]
17
+ 新建技能骨架(默认禁用)
18
+ ec skill install <源> [--force] [--enable] 安装技能(目录 / .zip / .md,默认禁用)
19
+ ec skill remove <name> 删除本机技能
20
+ ec skill enable <name> [--level agent|local]
21
+ 启用技能(默认 agent 级)
22
+ ec skill disable <name> [--level agent|local]
23
+ 禁用技能(默认 agent 级)
24
+ ec skill validate <name|路径> 校验 SKILL.md 是否合规
25
+ ec skill where 打印三级根目录路径
26
+
27
+ 说明:
28
+ - 安装目标只能是本机级(Agent 级只放开关,不放 SKILL.md)
29
+ - create / install 装完默认**禁用**,确认后再用 enable 启用(--enable 可一步到位)
30
+ - 内置级(随包发布)不可写、不可删
31
+ - 改动后约 2 秒内标记待更新,下一条消息处理时重建索引
32
+ `;
33
+
34
+ function parseArgs(argv) {
35
+ const flags = {};
36
+ const positional = [];
37
+ for (let i = 0; i < argv.length; i++) {
38
+ const a = argv[i];
39
+ if (a === '--json') flags.json = true;
40
+ else if (a === '--force') flags.force = true;
41
+ else if (a === '--enable') flags.enable = true;
42
+ else if (a === '--help' || a === '-h') flags.help = true;
43
+ else if (a.startsWith('--')) {
44
+ const key = a.slice(2);
45
+ const val = argv[i + 1];
46
+ if (val === undefined || val.startsWith('--')) { flags[key] = true; }
47
+ else { flags[key] = val; i++; }
48
+ } else positional.push(a);
49
+ }
50
+ return { flags, positional };
51
+ }
52
+
53
+ async function main() {
54
+ const argv = process.argv.slice(2);
55
+ if (argv.length === 0 || argv[0] === 'help' || argv[0] === '--help' || argv[0] === '-h') {
56
+ console.log(USAGE);
57
+ return 0;
58
+ }
59
+
60
+ const sub = argv[0];
61
+ const { flags, positional } = parseArgs(argv.slice(1));
62
+
63
+ if (flags.help) { console.log(USAGE); return 0; }
64
+
65
+ const asJson = Boolean(flags.json);
66
+ const emit = (result) => {
67
+ if (asJson) console.log(JSON.stringify(result, null, 2));
68
+ else if (typeof result === 'string') console.log(result);
69
+ else console.log(JSON.stringify(result, null, 2));
70
+ };
71
+
72
+ switch (sub) {
73
+ case 'list':
74
+ emit(S.cmdList({ json: asJson }));
75
+ return 0;
76
+
77
+ case 'info':
78
+ emit(S.cmdInfo(positional[0], { json: asJson }));
79
+ return 0;
80
+
81
+ case 'create':
82
+ emit(S.cmdCreate(positional[0], { desc: flags.desc || '', force: Boolean(flags.force), enable: Boolean(flags.enable), json: asJson }));
83
+ return 0;
84
+
85
+ case 'install':
86
+ emit(S.cmdInstall(positional[0], { force: Boolean(flags.force), enable: Boolean(flags.enable), json: asJson }));
87
+ return 0;
88
+
89
+ case 'remove':
90
+ emit(S.cmdRemove(positional[0], { json: asJson }));
91
+ return 0;
92
+
93
+ case 'enable':
94
+ emit(S.cmdEnableDisable(positional[0], true, { level: flags.level || 'agent', json: asJson }));
95
+ return 0;
96
+
97
+ case 'disable':
98
+ emit(S.cmdEnableDisable(positional[0], false, { level: flags.level || 'agent', json: asJson }));
99
+ return 0;
100
+
101
+ case 'validate': {
102
+ const result = S.cmdValidate(positional[0], { json: asJson });
103
+ // 校验失败必须以非零退出,否则调用方(模型/脚本)无法判断结果
104
+ if (result && result.__isText) {
105
+ console.log(result.output);
106
+ return result.valid ? 0 : 1;
107
+ }
108
+ emit(result);
109
+ return result && result.valid === false ? 1 : 0;
110
+ }
111
+
112
+ case 'where':
113
+ emit(S.cmdWhere({ json: asJson }));
114
+ return 0;
115
+
116
+ default:
117
+ console.error(`未知子命令: ${sub}\n`);
118
+ console.error(USAGE);
119
+ return 1;
120
+ }
121
+ }
122
+
123
+ main()
124
+ .then(code => process.exit(code ?? 0))
125
+ .catch(err => {
126
+ console.error(`❌ ${err instanceof Error ? err.message : String(err)}`);
127
+ process.exit(1);
128
+ });