evolcore 0.0.32 → 0.0.34

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 (214) hide show
  1. package/CHANGELOG.md +61 -0
  2. package/bin/ec.js +3 -2
  3. package/bin/install-codex-managed-hooks.mjs +135 -37
  4. package/dist/agents/baseagent-availability.js +20 -36
  5. package/dist/agents/claude-runner.js +111 -15
  6. package/dist/agents/codex/app-server-client.js +3 -0
  7. package/dist/agents/codex/diagnostics.js +112 -54
  8. package/dist/agents/codex-runner.js +241 -63
  9. package/dist/agents/ecagent-runner.js +78 -33
  10. package/dist/agents/runner-types.js +5 -6
  11. package/dist/aun/aid/identity.js +1 -1
  12. package/dist/aun/group/operations.js +0 -1
  13. package/dist/aun/msg/history.js +1 -0
  14. package/dist/aun/msg/p2p.js +0 -1
  15. package/dist/aun/outbox.js +50 -1
  16. package/dist/channels/aun.js +44 -8
  17. package/dist/channels/daemon.js +261 -3
  18. package/dist/cli/agent-command.js +58 -24
  19. package/dist/cli/agent.js +1 -1
  20. package/dist/cli/aun-commands.js +368 -31
  21. package/dist/cli/contact.js +8 -2
  22. package/dist/cli/ctl-command.js +3 -1
  23. package/dist/cli/daemon-commands.js +197 -27
  24. package/dist/cli/debug-mode.js +154 -0
  25. package/dist/cli/fs-command.js +2 -1
  26. package/dist/cli/handoff-command.js +3 -0
  27. package/dist/cli/index.js +98 -67
  28. package/dist/cli/init.js +2 -2
  29. package/dist/cli/integrity-command.js +196 -0
  30. package/dist/cli/managed-command-guard.js +5 -0
  31. package/dist/cli/memory-command.js +166 -146
  32. package/dist/cli/queue-command.js +9 -4
  33. package/dist/cli/session-command.js +194 -0
  34. package/dist/cli/skill-command.js +78 -2
  35. package/dist/cli/task-context.js +1 -0
  36. package/dist/cli/thread-command.js +622 -0
  37. package/dist/cli/trigger-command.js +10 -3
  38. package/dist/config/builtin-roles.js +1 -0
  39. package/dist/config/config-field-policy.js +6 -3
  40. package/dist/config/config-manager.js +26 -2
  41. package/dist/config/contact-book-store.js +5 -0
  42. package/dist/config/resolved-config-op.js +3 -0
  43. package/dist/config/role-service.js +13 -0
  44. package/dist/config/runtime-env.js +16 -0
  45. package/dist/config-store.js +45 -0
  46. package/dist/core/audit/log-integrity.js +3 -1
  47. package/dist/core/auth/agent-delegation.js +133 -36
  48. package/dist/core/auth/debug-context.js +139 -0
  49. package/dist/core/auth/delegation-diagnostics.js +414 -0
  50. package/dist/core/auth/operation-authorizer.js +25 -2
  51. package/dist/core/auth/operation-catalog.js +49 -0
  52. package/dist/core/background-session/session-cleanup.js +212 -0
  53. package/dist/core/background-session/types.js +10 -0
  54. package/dist/core/bootstrap-messages.js +1 -1
  55. package/dist/core/bootstrap-service.js +6 -3
  56. package/dist/core/command/agent-control.js +18 -26
  57. package/dist/core/command/command-handler.js +197 -27
  58. package/dist/core/command/daemon-diagnostics.js +1 -0
  59. package/dist/core/command/memory-slash.js +6 -2
  60. package/dist/core/command/menu-catalog.js +51 -1
  61. package/dist/core/command/menu-handler.js +114 -23
  62. package/dist/core/command/menu-protocol.js +25 -1
  63. package/dist/core/command/skill-slash.js +322 -0
  64. package/dist/core/command/slash-gate.js +6 -4
  65. package/dist/core/command/slash-handler.js +195 -13
  66. package/dist/core/command/topic-slash.js +528 -0
  67. package/dist/core/daemon-bootstrap.js +4 -7
  68. package/dist/core/evolagent-registry.js +20 -5
  69. package/dist/core/file-integrity/read.js +61 -0
  70. package/dist/core/file-integrity/store.js +262 -0
  71. package/dist/core/handoff/runtime.js +5 -11
  72. package/dist/core/handoff/store.js +5 -0
  73. package/dist/core/ipc-registration.js +175 -3
  74. package/dist/core/memory/batch-meta.js +132 -0
  75. package/dist/core/memory/consolidation-context.js +83 -29
  76. package/dist/core/memory/consolidation-ops-records.js +49 -16
  77. package/dist/core/memory/consolidation-queue-format.js +21 -0
  78. package/dist/core/memory/consolidation.js +264 -205
  79. package/dist/core/memory/index-manager.js +19 -28
  80. package/dist/core/memory/memory-admin.js +19 -14
  81. package/dist/core/memory/memory-document.js +53 -9
  82. package/dist/core/memory/memory-writer.js +30 -15
  83. package/dist/core/message/aun-ipc-sender.js +161 -6
  84. package/dist/core/message/im-renderer.js +169 -10
  85. package/dist/core/message/message-bridge.js +15 -4
  86. package/dist/core/message/message-log.js +1 -0
  87. package/dist/core/message/peer-mode.js +6 -1
  88. package/dist/core/message/response-engine.js +929 -110
  89. package/dist/core/message/subtask-tool-projection.js +140 -0
  90. package/dist/core/model/catalog-service.js +17 -12
  91. package/dist/core/permission/ec-command-parser.js +217 -9
  92. package/dist/core/permission/protected-paths.js +5 -1
  93. package/dist/core/permission/readonly-shell-query.js +43 -5
  94. package/dist/core/permission/session-path-grants.js +334 -0
  95. package/dist/core/permission/tool-canonical.js +226 -0
  96. package/dist/core/permission/tool-policy.js +30 -62
  97. package/dist/core/role/runtime-policy.js +21 -10
  98. package/dist/core/session/session-fs-store.js +123 -8
  99. package/dist/core/session/session-idle-monitor.js +249 -22
  100. package/dist/core/session/session-manager.js +129 -14
  101. package/dist/core/skill/command-parser.js +13 -0
  102. package/dist/core/skill/index-generator.js +21 -4
  103. package/dist/core/skill/startup.js +41 -0
  104. package/dist/core/skill/switch-resolver.js +55 -29
  105. package/dist/core/system-session/grants.js +40 -0
  106. package/dist/core/system-session/memory.js +222 -0
  107. package/dist/core/system-session/registry.js +74 -0
  108. package/dist/core/system-session/types.js +14 -0
  109. package/dist/core/thread/command-parser.js +125 -0
  110. package/dist/core/thread/index.js +1 -0
  111. package/dist/core/thread/ipc-operation.js +95 -0
  112. package/dist/core/thread/thread-context-storage.js +131 -0
  113. package/dist/core/thread/thread-operation.js +258 -0
  114. package/dist/core/thread/thread-route.js +33 -0
  115. package/dist/core/thread/thread-service.js +770 -0
  116. package/dist/core/thread/types.js +1 -0
  117. package/dist/eck/kit-renderer.js +7 -2
  118. package/dist/eck/manifest-engine.js +24 -4
  119. package/dist/eck/message-renderer.js +35 -0
  120. package/dist/index.js +19 -7
  121. package/dist/ipc.js +140 -50
  122. package/dist/paths.js +93 -0
  123. package/dist/response-system/engines/v1/proactive-flow.js +169 -80
  124. package/dist/stats/billing.js +20 -8
  125. package/dist/trigger/authorization.js +57 -28
  126. package/dist/trigger/feedback.js +13 -2
  127. package/dist/trigger/parser.js +70 -1
  128. package/dist/trigger/system-definitions.js +3 -3
  129. package/dist/trigger/validation.js +14 -0
  130. package/dist/utils/cross-platform.js +11 -2
  131. package/dist/utils/error-dict.json +18 -4
  132. package/dist/utils/error-utils.js +143 -1
  133. package/dist/utils/instance-registry.js +13 -8
  134. package/dist/utils/log-writer.js +12 -0
  135. package/dist/utils/process-introspect.js +11 -0
  136. package/kits/docs/context-assembly.md +1 -1
  137. package/kits/docs/evolcore/INDEX.md +1 -0
  138. package/kits/docs/evolcore/agent-create.md +40 -28
  139. package/kits/docs/evolcore/agent.md +21 -6
  140. package/kits/docs/evolcore/config.md +2 -2
  141. package/kits/docs/evolcore/ctl.md +2 -2
  142. package/kits/docs/evolcore/ec-capabilities.md +5 -1
  143. package/kits/docs/evolcore/fs-architecture.md +4 -5
  144. package/kits/docs/evolcore/fs.md +1 -1
  145. package/kits/docs/evolcore/group-collaboration.md +4 -6
  146. package/kits/docs/evolcore/group.md +11 -12
  147. package/kits/docs/evolcore/memory-architecture.md +4 -5
  148. package/kits/docs/evolcore/memory-consolidation.md +19 -15
  149. package/kits/docs/evolcore/memory-tags.md +3 -1
  150. package/kits/docs/evolcore/memory.md +24 -12
  151. package/kits/docs/evolcore/menu-exec-schema-commands.md +2 -2
  152. package/kits/docs/evolcore/menu-protocol.md +7 -0
  153. package/kits/docs/evolcore/model.md +16 -0
  154. package/kits/docs/evolcore/msg.md +8 -11
  155. package/kits/docs/evolcore/thread-chain.md +267 -0
  156. package/kits/docs/prompt-loading-architecture.md +1 -1
  157. package/kits/eck_manifest.json +55 -40
  158. package/kits/eck_manifest.memory.json +0 -12
  159. package/kits/eck_message_manifest.json +169 -10
  160. package/kits/rules/01-overview.md +11 -0
  161. package/kits/rules/03-identity.md +6 -3
  162. package/kits/rules/05-venue.md +1 -1
  163. package/kits/rules/06-channel.md +1 -1
  164. package/kits/rules/07-memory-and-thread.md +199 -0
  165. package/kits/schemas/_meta.json +7 -1
  166. package/kits/schemas/agent-config.schema.13.json +1 -1
  167. package/kits/schemas/daemon.schema.7.json +140 -0
  168. package/kits/schemas/relation-config.schema.9.json +18 -3
  169. package/kits/schemas/role-config.schema.1.json +6 -6
  170. package/kits/schemas/single-session.schema.1.json +6 -6
  171. package/kits/schemas/single-session.schema.2.json +6 -6
  172. package/kits/schemas/single-session.schema.3.json +6 -6
  173. package/kits/skills/.switches.json +12 -1
  174. package/kits/skills/ec-group/SKILL.md +234 -0
  175. package/kits/skills/ec-skill/SKILL.md +10 -1
  176. package/kits/skills/ec-skill/scripts/cli.mjs +16 -2
  177. package/kits/skills/ec-skill/scripts/skill.mjs +1 -1
  178. package/kits/skills/scrapling-article-fetch/SKILL.md +128 -0
  179. package/kits/skills/scrapling-article-fetch/scripts/check_python_env.py +54 -0
  180. package/kits/skills/scrapling-article-fetch/scripts/render_markdown_reply.py +35 -0
  181. package/kits/skills/scrapling-article-fetch/scripts/run_pipeline.sh +16 -0
  182. package/kits/skills/scrapling-article-fetch/scripts/scrapling_fetch.py +344 -0
  183. package/kits/skills/thread-ops/SKILL.md +492 -0
  184. package/kits/skills/wechat-article-media-download/SKILL.md +65 -0
  185. package/kits/skills/wechat-article-media-download/scripts/download.py +163 -0
  186. package/kits/skills/wechat-article-reader/SKILL.md +97 -0
  187. package/kits/skills/wechat-article-reader/scripts/fetch.mjs +256 -0
  188. package/kits/templates/bootstrap-welcome.md +7 -7
  189. package/kits/templates/memory-consolidation/forget.md +7 -2
  190. package/kits/templates/memory-consolidation/generalize.md +9 -4
  191. package/kits/templates/memory-consolidation/notes.md +11 -11
  192. package/kits/templates/memory-consolidation/profile.md +8 -3
  193. package/kits/templates/memory-consolidation/promote.md +8 -3
  194. package/kits/templates/memory-consolidation/workflow.md +6 -6
  195. package/kits/templates/message-fragments/handoff-request-to-target.md +1 -1
  196. package/kits/templates/message-fragments/item.md +2 -1
  197. package/kits/templates/message-fragments/thread-context.md +6 -0
  198. package/kits/templates/message-fragments/trigger-session.md +2 -0
  199. package/kits/templates/message-fragments/trigger-thread-check.md +2 -0
  200. package/kits/templates/roles/member.json +2 -0
  201. package/kits/templates/roles/visitor.json +2 -0
  202. package/kits/templates/system-fragments/bootstrap.md +67 -72
  203. package/kits/templates/system-fragments/channel.md +3 -6
  204. package/kits/templates/system-fragments/commands.md +1 -0
  205. package/kits/templates/system-fragments/managed-runtime.md +15 -0
  206. package/kits/templates/system-fragments/memory.md +16 -9
  207. package/kits/templates/system-fragments/reply.md +7 -6
  208. package/kits/templates/system-fragments/session.md +5 -14
  209. package/package.json +6 -3
  210. package/dist/core/memory/memory-session-policy.js +0 -41
  211. package/dist/core/memory/memory-signature.js +0 -257
  212. package/kits/docs/evolcore/group-fs.md +0 -17
  213. package/kits/docs/venues/aun-group.md +0 -45
  214. package/kits/docs/venues/group.md +0 -43
@@ -0,0 +1,212 @@
1
+ /**
2
+ * session-cleanup.ts — 独立后台会话(bg-session)和 trigger 会话的清理机制
3
+ *
4
+ * 三种自动清理模式:
5
+ * immediate — 会话结束时同步清理
6
+ * on_next_launch — 下次同 kind 会话启动时清理上一次的残留(默认)
7
+ * expire — 会话结束时写登记表,启动时扫描到期条目清理
8
+ *
9
+ * 登记表路径:$EVOLCORE_HOME/data/session-cleanup/expire-<YYYYMMDD>.jsonl
10
+ * 详见 docs/background-session/session-cleanup-policy.md
11
+ */
12
+ import fs from 'fs';
13
+ import path from 'path';
14
+ import { resolveRoot } from '../../paths.js';
15
+ import { logger } from '../../utils/logger.js';
16
+ // ── 登记表工具 ──────────────────────────────────────────────────────────────
17
+ function cleanupDir() {
18
+ return path.join(resolveRoot(), 'data', 'session-cleanup');
19
+ }
20
+ function expireFilePath(date) {
21
+ const y = date.getFullYear();
22
+ const m = String(date.getMonth() + 1).padStart(2, '0');
23
+ const d = String(date.getDate()).padStart(2, '0');
24
+ return path.join(cleanupDir(), `expire-${y}${m}${d}.jsonl`);
25
+ }
26
+ function doneFilePath(expirePath) {
27
+ return expirePath.replace(/\.jsonl$/, '.done.jsonl');
28
+ }
29
+ /**
30
+ * 把一条超期记录写进今天的登记表。
31
+ * 幂等:同一 channelId 写多次无害,runExpireCleanup 会逐条处理。
32
+ */
33
+ export function appendExpireEntry(entry) {
34
+ try {
35
+ const dir = cleanupDir();
36
+ fs.mkdirSync(dir, { recursive: true });
37
+ const filePath = expireFilePath(new Date(entry.expireAt));
38
+ fs.appendFileSync(filePath, JSON.stringify(entry) + '\n', 'utf-8');
39
+ }
40
+ catch (e) {
41
+ logger.warn(`[SessionCleanup] 写入超期登记表失败: ${e?.message}`);
42
+ }
43
+ }
44
+ /**
45
+ * 清理一条 evolcore session 记录(移入 _trash/)。
46
+ * runner 侧日志不在这里处理(runner 接口尚未提供 deleteSession)。
47
+ */
48
+ export async function cleanupSessionRecord(target, cleaner) {
49
+ try {
50
+ await cleaner.softDeleteSession(target.channelId);
51
+ logger.debug(`[SessionCleanup] 已清理 session 记录: channelId=${target.channelId}` +
52
+ `${target.agentAid ? ` aid=${target.agentAid}` : ''}`);
53
+ }
54
+ catch (e) {
55
+ logger.warn(`[SessionCleanup] 清理 session 记录失败 channelId=${target.channelId}: ${e?.message}`);
56
+ }
57
+ }
58
+ // ── expire 模式:启动时扫描 ──────────────────────────────────────────────────
59
+ /**
60
+ * 扫描 data/session-cleanup/ 下所有登记表,清理已到期的条目。
61
+ * 在任意 bg-session 或 trigger 会话启动时调用,成本低(只读少量小文件)。
62
+ */
63
+ export async function runExpireCleanup(cleaner, now = Date.now()) {
64
+ const dir = cleanupDir();
65
+ if (!fs.existsSync(dir))
66
+ return;
67
+ let files;
68
+ try {
69
+ files = fs.readdirSync(dir).filter(f => /^expire-\d{8}\.jsonl$/.test(f));
70
+ }
71
+ catch {
72
+ return;
73
+ }
74
+ const todayStr = (() => {
75
+ const d = new Date(now);
76
+ const y = d.getFullYear();
77
+ const m = String(d.getMonth() + 1).padStart(2, '0');
78
+ const day = String(d.getDate()).padStart(2, '0');
79
+ return `expire-${y}${m}${day}.jsonl`;
80
+ })();
81
+ for (const file of files) {
82
+ // 跳过未来日期的文件(expireAt 不可能到期)
83
+ const fileDate = file.slice(7, 15); // expire-YYYYMMDD.jsonl → YYYYMMDD
84
+ const todayDate = todayStr.slice(7, 15);
85
+ if (fileDate > todayDate)
86
+ continue;
87
+ const filePath = path.join(dir, file);
88
+ const donePath = doneFilePath(filePath);
89
+ let lines;
90
+ try {
91
+ lines = fs.readFileSync(filePath, 'utf-8').split('\n').filter(l => l.trim());
92
+ }
93
+ catch {
94
+ continue;
95
+ }
96
+ // 读取已处理的 channelId 集合
97
+ const doneIds = new Set();
98
+ if (fs.existsSync(donePath)) {
99
+ try {
100
+ for (const line of fs.readFileSync(donePath, 'utf-8').split('\n').filter(l => l.trim())) {
101
+ const entry = JSON.parse(line);
102
+ if (entry.channelId)
103
+ doneIds.add(entry.channelId);
104
+ }
105
+ }
106
+ catch { /* 损坏的 done 文件,跳过去重,重复清理幂等 */ }
107
+ }
108
+ let processedCount = 0;
109
+ // 文件里是否还有未到期条目;有则保留文件,下次再扫
110
+ let hasPending = false;
111
+ for (const line of lines) {
112
+ let entry;
113
+ try {
114
+ entry = JSON.parse(line);
115
+ }
116
+ catch {
117
+ continue;
118
+ }
119
+ if (!entry.channelId || !entry.expireAt)
120
+ continue;
121
+ if (entry.expireAt > now) {
122
+ hasPending = true;
123
+ continue;
124
+ } // 未到期
125
+ if (doneIds.has(entry.channelId))
126
+ continue; // 已处理
127
+ await cleanupSessionRecord({ sessionId: entry.sessionId, channelId: entry.channelId, agentAid: entry.agentAid }, cleaner);
128
+ // 标记已处理
129
+ try {
130
+ fs.appendFileSync(donePath, JSON.stringify({ channelId: entry.channelId, ts: now }) + '\n', 'utf-8');
131
+ }
132
+ catch { /* 写失败无妨,下次会重复处理,cleanupSessionRecord 幂等 */ }
133
+ doneIds.add(entry.channelId);
134
+ processedCount++;
135
+ }
136
+ if (processedCount > 0) {
137
+ logger.debug(`[SessionCleanup] expire 扫描:清理 ${processedCount} 条到期记录(${file})`);
138
+ }
139
+ // 整天文件全部处理完时,删除两个文件。
140
+ // 不能用 doneIds.size 与行数比较:同一 channelId 重复登记时两者永远不等,文件会残留。
141
+ if (!hasPending) {
142
+ try {
143
+ fs.unlinkSync(filePath);
144
+ }
145
+ catch { /* ignore */ }
146
+ try {
147
+ fs.unlinkSync(donePath);
148
+ }
149
+ catch { /* ignore */ }
150
+ }
151
+ }
152
+ }
153
+ // ── on_next_launch 模式:按 kind 清理历史会话 ────────────────────────────────
154
+ /**
155
+ * 记录一条 on_next_launch 清理登记,供下次启动时使用。
156
+ * 存在一个独立的 JSONL 文件中,按 kind 分文件存储。
157
+ */
158
+ function nextLaunchFilePath(kind) {
159
+ const safeKind = kind.replace(/[^a-zA-Z0-9\-_]/g, '_');
160
+ return path.join(cleanupDir(), `next-launch-${safeKind}.jsonl`);
161
+ }
162
+ /**
163
+ * 记录一条「下次启动时清理」的会话信息。
164
+ * 在会话正常或异常结束时调用。
165
+ */
166
+ export function recordNextLaunchCleanup(kind, entry) {
167
+ try {
168
+ const dir = cleanupDir();
169
+ fs.mkdirSync(dir, { recursive: true });
170
+ const filePath = nextLaunchFilePath(kind);
171
+ fs.appendFileSync(filePath, JSON.stringify(entry) + '\n', 'utf-8');
172
+ }
173
+ catch (e) {
174
+ logger.warn(`[SessionCleanup] 写入 on_next_launch 登记失败 kind=${kind}: ${e?.message}`);
175
+ }
176
+ }
177
+ /**
178
+ * 清理同 kind 的所有历史会话记录,然后清空登记文件。
179
+ * 在新会话启动前调用(on_next_launch 模式)。
180
+ */
181
+ export async function cleanupPreviousByKind(kind, cleaner) {
182
+ const filePath = nextLaunchFilePath(kind);
183
+ if (!fs.existsSync(filePath))
184
+ return;
185
+ let lines;
186
+ try {
187
+ lines = fs.readFileSync(filePath, 'utf-8').split('\n').filter(l => l.trim());
188
+ }
189
+ catch {
190
+ return;
191
+ }
192
+ for (const line of lines) {
193
+ let entry;
194
+ try {
195
+ entry = JSON.parse(line);
196
+ }
197
+ catch {
198
+ continue;
199
+ }
200
+ if (!entry.channelId)
201
+ continue;
202
+ await cleanupSessionRecord({ sessionId: entry.sessionId, channelId: entry.channelId, agentAid: entry.agentAid }, cleaner);
203
+ }
204
+ // 清空登记文件(下一次重新积累)
205
+ try {
206
+ fs.unlinkSync(filePath);
207
+ }
208
+ catch { /* ignore */ }
209
+ if (lines.length > 0) {
210
+ logger.debug(`[SessionCleanup] on_next_launch:已清理 ${lines.length} 条历史记录(kind=${kind})`);
211
+ }
212
+ }
@@ -0,0 +1,10 @@
1
+ /**
2
+ * background-session/types.ts — 独立后台会话的接口定义
3
+ *
4
+ * 独立后台会话(bg-session)是由 daemon 内部逻辑主动拉起的 AI 会话,
5
+ * 不属于用户交互,也不挂在 trigger 调度系统下。
6
+ * 整理会话、话题总结会话等都通过这套接口拉起。
7
+ *
8
+ * 详细机制见 docs/background-session/background-session-launcher.md
9
+ */
10
+ export {};
@@ -53,7 +53,7 @@ export function renderPostBootstrapWelcome(aid, owner, ownerName) {
53
53
  }
54
54
  const config = loadAgent(aid);
55
55
  if (config && resolveAgentLifecycle(config) === 'bootstrapping' && config.initialization?.mode !== 'supplied') {
56
- throw new Error('WELCOME_REQUIRED: Owner-confirmed welcome.md is required before activation');
56
+ throw new Error('WELCOME_REQUIRED: Agent-prepared welcome.md is required before activation');
57
57
  }
58
58
  return generateWelcomeMessage({
59
59
  channelType: 'aun',
@@ -25,14 +25,17 @@ export async function completeBootstrapWithWelcome(service, aid, welcome, sessio
25
25
  }
26
26
  if (lifecycle === 'bootstrapping') {
27
27
  // Existing per-Owner records are immutable retry snapshots. New interactive
28
- // Bootstrap completions require the text saved after Owner confirmation.
28
+ // Bootstrap completions require the welcome text prepared by the Agent.
29
29
  const config = loadAgent(aid);
30
30
  const deliveries = config?.owners?.length ? postBootstrapWelcomeStatus(aid, config.owners).deliveries : [];
31
31
  const alreadyPrepared = deliveries.length > 0 && deliveries.every(delivery => delivery.status !== 'not_prepared');
32
32
  if (config?.initialization?.mode !== 'supplied' && !alreadyPrepared) {
33
33
  try {
34
34
  if (readAgentWelcomeTemplate(aid) === null) {
35
- return { ok: false, code: 'WELCOME_REQUIRED', error: '请先在 Bootstrap 对话中生成欢迎文案,经 Owner 确认后保存 welcome.md', reloaded: false };
35
+ return {
36
+ ok: false, code: 'WELCOME_REQUIRED', reloaded: false,
37
+ error: '请先自主生成正式欢迎文案并保存 welcome.md,无需 Owner 确认',
38
+ };
36
39
  }
37
40
  }
38
41
  catch (error) {
@@ -446,7 +449,7 @@ export class BootstrapService {
446
449
  const templatePath = path.join(kitsTemplatesDir(), 'bootstrap-welcome.md');
447
450
  const template = fs.existsSync(templatePath)
448
451
  ? fs.readFileSync(templatePath, 'utf-8')
449
- : '你好,我是 {{agentName}}。请帮我确认显示名、简介和标签。';
452
+ : '你好,我是 {{agentName}}。已有的有效基础信息会直接沿用;请补充缺失的显示名、简介或标签。persona 和头像可选,之后也可以完善。';
450
453
  return renderTemplate(template, vars).trim();
451
454
  }
452
455
  resolveAgentDisplayName(aid) {
@@ -583,9 +583,24 @@ export async function execAgentUpdate(args, subject) {
583
583
  if (p.channels !== undefined && p.channelOwners !== undefined) {
584
584
  return { error: 'channels 与 channelOwners 不能同时提交', code: 'INVALID_ARGS' };
585
585
  }
586
- const config = cfgRead(ConfigTarget.Agent, { self: a.aid });
586
+ const config = cfgRead(ConfigTarget.Agent, { self: a.aid }, { cache: false });
587
587
  if (!config)
588
588
  return { error: `Agent "${a.aid}" not found`, code: 'NOT_FOUND' };
589
+ if (p.fullaccess !== undefined) {
590
+ if (!p.fullaccess || typeof p.fullaccess !== 'object' || Array.isArray(p.fullaccess)) {
591
+ return { error: 'fullaccess 必须是对象', code: 'INVALID_ARGS' };
592
+ }
593
+ const fullaccess = p.fullaccess;
594
+ if (Object.keys(fullaccess).some(key => key !== 'enabled')) {
595
+ return { error: 'fullaccess 只支持 enabled 字段', code: 'INVALID_ARGS' };
596
+ }
597
+ if (typeof fullaccess.enabled !== 'boolean') {
598
+ return { error: 'fullaccess.enabled 必须是布尔值', code: 'INVALID_ARGS' };
599
+ }
600
+ const denied = agentFullAccessWriteError(a.aid, subject);
601
+ if (denied)
602
+ return { error: denied, code: 'FORBIDDEN' };
603
+ }
589
604
  // Legacy App requests share the canonical validation, storage and agent.md publication flow.
590
605
  if (Object.hasOwn(p, 'avatar'))
591
606
  return execAidAvatar({ aid: a.aid, data: p.avatar });
@@ -640,27 +655,7 @@ export async function execAgentUpdate(args, subject) {
640
655
  touched = true;
641
656
  }
642
657
  if (p.fullaccess !== undefined) {
643
- if (!p.fullaccess || typeof p.fullaccess !== 'object' || Array.isArray(p.fullaccess)) {
644
- return { error: 'fullaccess 必须是对象', code: 'INVALID_ARGS' };
645
- }
646
- const fullaccess = p.fullaccess;
647
- if (Object.keys(fullaccess).some(key => key !== 'enabled')) {
648
- return { error: 'fullaccess 只支持 enabled 字段', code: 'INVALID_ARGS' };
649
- }
650
- if (fullaccess.enabled !== undefined && typeof fullaccess.enabled !== 'boolean') {
651
- return { error: 'fullaccess.enabled 必须是布尔值', code: 'INVALID_ARGS' };
652
- }
653
- if (typeof fullaccess.enabled !== 'boolean')
654
- return { error: 'fullaccess.enabled is required', code: 'INVALID_ARGS' };
655
- const denied = agentFullAccessWriteError({
656
- daemonOwner: subject?.isDaemonOwner === true,
657
- ecwebManagement: subject?.ecwebManagement === true,
658
- delegated: subject?.canApprovePersistentFullAccess === false || subject?.chatType === 'group',
659
- enabled: fullaccess.enabled,
660
- });
661
- if (denied)
662
- return { error: denied, code: 'FORBIDDEN' };
663
- config.fullaccess = { enabled: fullaccess.enabled };
658
+ config.fullaccess = { enabled: p.fullaccess.enabled };
664
659
  touched = true;
665
660
  }
666
661
  if (p.chatmode !== undefined) {
@@ -747,10 +742,7 @@ export async function execAgentQuery(args, service, subject) {
747
742
  safeConfig,
748
743
  fullaccessStatus: {
749
744
  ...fullaccessStatus,
750
- canConfigure: subject?.ecwebManagement === true
751
- && subject?.isDaemonOwner === true
752
- && subject.canApprovePersistentFullAccess !== false
753
- && subject.chatType !== 'group',
745
+ canConfigure: agentFullAccessWriteError(aid, subject) === undefined,
754
746
  },
755
747
  };
756
748
  // 叠加构建进度(create 受理后、ready 前可见;ready 后文件仍在,可反映软失败 warn)