evolcore 0.0.8 → 0.0.10

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 (215) hide show
  1. package/CHANGELOG.md +31 -0
  2. package/README.md +37 -3
  3. package/dist/agents/baseagent.js +111 -19
  4. package/dist/agents/claude-runner.js +30 -2
  5. package/dist/agents/codex-app-server-client.js +31 -0
  6. package/dist/agents/codex-runner.js +3 -0
  7. package/dist/aun/msg/group.js +9 -9
  8. package/dist/aun/msg/p2p.js +11 -6
  9. package/dist/aun/msg/upload.js +43 -29
  10. package/dist/aun/outbox.js +48 -5
  11. package/dist/channels/aun.js +199 -50
  12. package/dist/cli/aun-commands.js +10 -7
  13. package/dist/cli/daemon-commands.js +19 -4
  14. package/dist/cli/index.js +11 -1
  15. package/dist/cli/init.js +103 -4
  16. package/dist/cli/model.js +5 -5
  17. package/dist/config/builtin-role-templates.js +4 -3
  18. package/dist/config/config-field-policy.js +6 -2
  19. package/dist/config/config-manager.js +48 -11
  20. package/dist/config/contact-book-store.js +1 -1
  21. package/dist/config/role-schema.js +18 -3
  22. package/dist/config/role-service.js +3 -3
  23. package/dist/config/role-store.js +4 -3
  24. package/dist/config-store.js +4 -0
  25. package/dist/core/auth/operation-authorizer.js +3 -1
  26. package/dist/core/bootstrap-service.js +0 -12
  27. package/dist/core/channel-loader.js +5 -1
  28. package/dist/core/command/command-handler.js +1 -1
  29. package/dist/core/command/evol-menu-version-gate.js +3 -2
  30. package/dist/core/command/menu-handler.js +33 -22
  31. package/dist/core/command/menu-protocol.js +7 -4
  32. package/dist/core/command/slash-handler.js +4 -4
  33. package/dist/core/data-migration.js +79 -27
  34. package/dist/core/inference/text-inference.js +18 -5
  35. package/dist/core/message/message-bridge.js +17 -6
  36. package/dist/core/message/response-engine.js +22 -3
  37. package/dist/core/model/config-scope.js +3 -3
  38. package/dist/core/permission/tool-policy.js +18 -0
  39. package/dist/index.js +43 -26
  40. package/dist/ipc.js +1 -1
  41. package/dist/product.js +1 -0
  42. package/dist/utils/autostart.js +27 -0
  43. package/dist/utils/ecweb-utils.js +15 -2
  44. package/dist/utils/macos-autostart.js +179 -0
  45. package/dist/utils/windows-autostart.js +130 -0
  46. package/ecagent/dist/agent-loop.d.ts +1 -1
  47. package/ecagent/dist/agent-loop.js +1 -1
  48. package/ecagent/dist/agent.d.ts +1 -1
  49. package/ecagent/dist/agent.js +1 -1
  50. package/ecagent/dist/harness/agent-harness.d.ts +1 -1
  51. package/ecagent/dist/harness/compaction/branch-summarization.d.ts +1 -1
  52. package/ecagent/dist/harness/compaction/compaction.d.ts +1 -1
  53. package/ecagent/dist/harness/compaction/utils.d.ts +1 -1
  54. package/ecagent/dist/harness/messages.d.ts +1 -1
  55. package/ecagent/dist/harness/session/session.d.ts +1 -1
  56. package/ecagent/dist/harness/types.d.ts +1 -1
  57. package/ecagent/dist/proxy.d.ts +1 -1
  58. package/ecagent/dist/proxy.js +1 -1
  59. package/ecagent/dist/types.d.ts +1 -1
  60. package/kits/migrations/migrate-role-config-v5.mjs +27 -2
  61. package/kits/schemas/agent-config.schema.10.json +19 -1
  62. package/kits/schemas/daemon.schema.4.json +4 -0
  63. package/kits/schemas/defaults.schema.4.json +15 -1
  64. package/kits/schemas/relation-config.schema.8.json +22 -1
  65. package/kits/schemas/role-config.schema.1.json +2 -2
  66. package/package.json +2 -4
  67. package/ecagent/dist/agent-loop.d.ts.map +0 -1
  68. package/ecagent/dist/agent-loop.js.map +0 -1
  69. package/ecagent/dist/agent.d.ts.map +0 -1
  70. package/ecagent/dist/agent.js.map +0 -1
  71. package/ecagent/dist/harness/agent-harness.d.ts.map +0 -1
  72. package/ecagent/dist/harness/agent-harness.js.map +0 -1
  73. package/ecagent/dist/harness/compaction/branch-summarization.d.ts.map +0 -1
  74. package/ecagent/dist/harness/compaction/branch-summarization.js.map +0 -1
  75. package/ecagent/dist/harness/compaction/compaction.d.ts.map +0 -1
  76. package/ecagent/dist/harness/compaction/compaction.js.map +0 -1
  77. package/ecagent/dist/harness/compaction/utils.d.ts.map +0 -1
  78. package/ecagent/dist/harness/compaction/utils.js.map +0 -1
  79. package/ecagent/dist/harness/env/nodejs.d.ts.map +0 -1
  80. package/ecagent/dist/harness/env/nodejs.js.map +0 -1
  81. package/ecagent/dist/harness/messages.d.ts.map +0 -1
  82. package/ecagent/dist/harness/messages.js.map +0 -1
  83. package/ecagent/dist/harness/prompt-templates.d.ts.map +0 -1
  84. package/ecagent/dist/harness/prompt-templates.js.map +0 -1
  85. package/ecagent/dist/harness/session/jsonl-repo.d.ts.map +0 -1
  86. package/ecagent/dist/harness/session/jsonl-repo.js.map +0 -1
  87. package/ecagent/dist/harness/session/jsonl-storage.d.ts.map +0 -1
  88. package/ecagent/dist/harness/session/jsonl-storage.js.map +0 -1
  89. package/ecagent/dist/harness/session/memory-repo.d.ts.map +0 -1
  90. package/ecagent/dist/harness/session/memory-repo.js.map +0 -1
  91. package/ecagent/dist/harness/session/memory-storage.d.ts.map +0 -1
  92. package/ecagent/dist/harness/session/memory-storage.js.map +0 -1
  93. package/ecagent/dist/harness/session/repo-utils.d.ts.map +0 -1
  94. package/ecagent/dist/harness/session/repo-utils.js.map +0 -1
  95. package/ecagent/dist/harness/session/session.d.ts.map +0 -1
  96. package/ecagent/dist/harness/session/session.js.map +0 -1
  97. package/ecagent/dist/harness/session/uuid.d.ts.map +0 -1
  98. package/ecagent/dist/harness/session/uuid.js.map +0 -1
  99. package/ecagent/dist/harness/skills.d.ts.map +0 -1
  100. package/ecagent/dist/harness/skills.js.map +0 -1
  101. package/ecagent/dist/harness/system-prompt.d.ts.map +0 -1
  102. package/ecagent/dist/harness/system-prompt.js.map +0 -1
  103. package/ecagent/dist/harness/types.d.ts.map +0 -1
  104. package/ecagent/dist/harness/types.js.map +0 -1
  105. package/ecagent/dist/harness/utils/shell-output.d.ts.map +0 -1
  106. package/ecagent/dist/harness/utils/shell-output.js.map +0 -1
  107. package/ecagent/dist/harness/utils/truncate.d.ts.map +0 -1
  108. package/ecagent/dist/harness/utils/truncate.js.map +0 -1
  109. package/ecagent/dist/index.d.ts.map +0 -1
  110. package/ecagent/dist/index.js.map +0 -1
  111. package/ecagent/dist/node.d.ts.map +0 -1
  112. package/ecagent/dist/node.js.map +0 -1
  113. package/ecagent/dist/proxy.d.ts.map +0 -1
  114. package/ecagent/dist/proxy.js.map +0 -1
  115. package/ecagent/dist/runtime/api/lazy.d.ts.map +0 -1
  116. package/ecagent/dist/runtime/api/lazy.js.map +0 -1
  117. package/ecagent/dist/runtime/api/pi-messages.d.ts.map +0 -1
  118. package/ecagent/dist/runtime/api/pi-messages.js.map +0 -1
  119. package/ecagent/dist/runtime/api/pi-messages.lazy.d.ts.map +0 -1
  120. package/ecagent/dist/runtime/api/pi-messages.lazy.js.map +0 -1
  121. package/ecagent/dist/runtime/auth/context.d.ts.map +0 -1
  122. package/ecagent/dist/runtime/auth/context.js.map +0 -1
  123. package/ecagent/dist/runtime/auth/credential-store.d.ts.map +0 -1
  124. package/ecagent/dist/runtime/auth/credential-store.js.map +0 -1
  125. package/ecagent/dist/runtime/auth/helpers.d.ts.map +0 -1
  126. package/ecagent/dist/runtime/auth/helpers.js.map +0 -1
  127. package/ecagent/dist/runtime/auth/resolve.d.ts.map +0 -1
  128. package/ecagent/dist/runtime/auth/resolve.js.map +0 -1
  129. package/ecagent/dist/runtime/auth/types.d.ts.map +0 -1
  130. package/ecagent/dist/runtime/auth/types.js.map +0 -1
  131. package/ecagent/dist/runtime/compat.d.ts.map +0 -1
  132. package/ecagent/dist/runtime/compat.js.map +0 -1
  133. package/ecagent/dist/runtime/index.d.ts.map +0 -1
  134. package/ecagent/dist/runtime/index.js.map +0 -1
  135. package/ecagent/dist/runtime/models.d.ts.map +0 -1
  136. package/ecagent/dist/runtime/models.js.map +0 -1
  137. package/ecagent/dist/runtime/oauth.d.ts.map +0 -1
  138. package/ecagent/dist/runtime/oauth.js.map +0 -1
  139. package/ecagent/dist/runtime/providers/faux.d.ts.map +0 -1
  140. package/ecagent/dist/runtime/providers/faux.js.map +0 -1
  141. package/ecagent/dist/runtime/types.d.ts.map +0 -1
  142. package/ecagent/dist/runtime/types.js.map +0 -1
  143. package/ecagent/dist/runtime/utils/diagnostics.d.ts.map +0 -1
  144. package/ecagent/dist/runtime/utils/diagnostics.js.map +0 -1
  145. package/ecagent/dist/runtime/utils/event-stream.d.ts.map +0 -1
  146. package/ecagent/dist/runtime/utils/event-stream.js.map +0 -1
  147. package/ecagent/dist/runtime/utils/headers.d.ts.map +0 -1
  148. package/ecagent/dist/runtime/utils/headers.js.map +0 -1
  149. package/ecagent/dist/runtime/utils/json-parse.d.ts.map +0 -1
  150. package/ecagent/dist/runtime/utils/json-parse.js.map +0 -1
  151. package/ecagent/dist/runtime/utils/oauth/types.d.ts.map +0 -1
  152. package/ecagent/dist/runtime/utils/oauth/types.js.map +0 -1
  153. package/ecagent/dist/runtime/utils/overflow.d.ts.map +0 -1
  154. package/ecagent/dist/runtime/utils/overflow.js.map +0 -1
  155. package/ecagent/dist/runtime/utils/provider-env.d.ts.map +0 -1
  156. package/ecagent/dist/runtime/utils/provider-env.js.map +0 -1
  157. package/ecagent/dist/runtime/utils/retry.d.ts.map +0 -1
  158. package/ecagent/dist/runtime/utils/retry.js.map +0 -1
  159. package/ecagent/dist/runtime/utils/typebox-helpers.d.ts.map +0 -1
  160. package/ecagent/dist/runtime/utils/typebox-helpers.js.map +0 -1
  161. package/ecagent/dist/runtime/utils/validation.d.ts.map +0 -1
  162. package/ecagent/dist/runtime/utils/validation.js.map +0 -1
  163. package/ecagent/dist/types.d.ts.map +0 -1
  164. package/ecagent/dist/types.js.map +0 -1
  165. package/ecagent/package.json +0 -93
  166. package/ecagent/src/agent-loop.ts +0 -792
  167. package/ecagent/src/agent.ts +0 -575
  168. package/ecagent/src/harness/agent-harness.ts +0 -1029
  169. package/ecagent/src/harness/compaction/branch-summarization.ts +0 -261
  170. package/ecagent/src/harness/compaction/compaction.ts +0 -753
  171. package/ecagent/src/harness/compaction/utils.ts +0 -144
  172. package/ecagent/src/harness/env/nodejs.ts +0 -569
  173. package/ecagent/src/harness/messages.ts +0 -164
  174. package/ecagent/src/harness/prompt-templates.ts +0 -267
  175. package/ecagent/src/harness/session/jsonl-repo.ts +0 -179
  176. package/ecagent/src/harness/session/jsonl-storage.ts +0 -314
  177. package/ecagent/src/harness/session/memory-repo.ts +0 -50
  178. package/ecagent/src/harness/session/memory-storage.ts +0 -133
  179. package/ecagent/src/harness/session/repo-utils.ts +0 -51
  180. package/ecagent/src/harness/session/session.ts +0 -338
  181. package/ecagent/src/harness/session/uuid.ts +0 -54
  182. package/ecagent/src/harness/skills.ts +0 -375
  183. package/ecagent/src/harness/system-prompt.ts +0 -34
  184. package/ecagent/src/harness/types.ts +0 -838
  185. package/ecagent/src/harness/utils/shell-output.ts +0 -135
  186. package/ecagent/src/harness/utils/truncate.ts +0 -344
  187. package/ecagent/src/index.ts +0 -46
  188. package/ecagent/src/node.ts +0 -2
  189. package/ecagent/src/proxy.ts +0 -367
  190. package/ecagent/src/runtime/api/lazy.ts +0 -70
  191. package/ecagent/src/runtime/api/pi-messages.lazy.ts +0 -4
  192. package/ecagent/src/runtime/api/pi-messages.ts +0 -436
  193. package/ecagent/src/runtime/auth/context.ts +0 -45
  194. package/ecagent/src/runtime/auth/credential-store.ts +0 -47
  195. package/ecagent/src/runtime/auth/helpers.ts +0 -46
  196. package/ecagent/src/runtime/auth/resolve.ts +0 -141
  197. package/ecagent/src/runtime/auth/types.ts +0 -182
  198. package/ecagent/src/runtime/compat.ts +0 -158
  199. package/ecagent/src/runtime/index.ts +0 -31
  200. package/ecagent/src/runtime/models.ts +0 -452
  201. package/ecagent/src/runtime/oauth.ts +0 -1
  202. package/ecagent/src/runtime/providers/faux.ts +0 -538
  203. package/ecagent/src/runtime/types.ts +0 -718
  204. package/ecagent/src/runtime/utils/diagnostics.ts +0 -45
  205. package/ecagent/src/runtime/utils/event-stream.ts +0 -88
  206. package/ecagent/src/runtime/utils/headers.ts +0 -18
  207. package/ecagent/src/runtime/utils/json-parse.ts +0 -124
  208. package/ecagent/src/runtime/utils/oauth/types.ts +0 -79
  209. package/ecagent/src/runtime/utils/overflow.ts +0 -165
  210. package/ecagent/src/runtime/utils/provider-env.ts +0 -52
  211. package/ecagent/src/runtime/utils/retry.ts +0 -101
  212. package/ecagent/src/runtime/utils/typebox-helpers.ts +0 -24
  213. package/ecagent/src/runtime/utils/validation.ts +0 -310
  214. package/ecagent/src/types.ts +0 -430
  215. package/ecagent/tsconfig.build.json +0 -32
@@ -808,7 +808,7 @@ Options:
808
808
  --app <name> 指定应用 slot(独立消费通道,不影响 daemon)
809
809
  --aun-path <path> 指定 AUN keystore 根
810
810
  --format json 输出 JSON 格式
811
- --encrypt 启用端到端加密(密文发送)
811
+ --encrypt 强制端到端加密(未指定时使用 daemon 默认值)
812
812
  --no-encrypt 强制明文发送(优先于 --encrypt)
813
813
  --thread <id> 指定话题 ID(用于多话题路由)
814
814
  --session <latest|all|id> 按 EvolCore 逻辑会话过滤历史(默认 latest)
@@ -1048,9 +1048,10 @@ Options:
1048
1048
  }
1049
1049
  body = { mode: 'text', text };
1050
1050
  }
1051
- // 加密态:--encrypt 密文,--no-encrypt 明文,都不带默认明文(人类终端直用即此)。
1052
- // 模型自主发送时由系统提示规则要求按入站消息加密态显式带参。--no-encrypt 优先于 --encrypt
1053
- const encrypt = args.includes('--encrypt') && !args.includes('--no-encrypt');
1051
+ // 显式 flag 覆盖 daemon 默认值;未指定时保留 undefined。
1052
+ const encrypt = args.includes('--no-encrypt')
1053
+ ? false
1054
+ : args.includes('--encrypt') ? true : undefined;
1054
1055
  const thread = getArgValue(args, '--thread');
1055
1056
  const returnPolicyRaw = getArgValue(args, '--return');
1056
1057
  if (returnPolicyRaw && returnPolicyRaw !== 'required' && returnPolicyRaw !== 'none') {
@@ -1292,7 +1293,7 @@ Options:
1292
1293
  --app <name> 指定应用 slot(独立消费通道,不影响 daemon)
1293
1294
  --aun-path <path> 指定 AUN keystore 根
1294
1295
  --format json 输出 JSON 格式
1295
- --encrypt 启用端到端加密(仅 send)
1296
+ --encrypt 强制端到端加密(未指定时使用 daemon 默认值;仅 send)
1296
1297
  --no-encrypt 强制明文发送(优先于 --encrypt;仅 send)
1297
1298
  --thread <id> 指定话题 ID(仅 send)
1298
1299
  --return <none|required> 跨会话发送必填(仅 send;Trigger 只能使用 none)
@@ -1469,8 +1470,10 @@ Options:
1469
1470
  body = { mode: 'text', text };
1470
1471
  }
1471
1472
  const mentions = collectMentions();
1472
- // --encrypt 密文,--no-encrypt 明文,都不带默认明文。--no-encrypt 优先。
1473
- const encryptGroup = args.includes('--encrypt') && !args.includes('--no-encrypt');
1473
+ // 显式 flag 覆盖 daemon 默认值;未指定时保留 undefined。
1474
+ const encryptGroup = args.includes('--no-encrypt')
1475
+ ? false
1476
+ : args.includes('--encrypt') ? true : undefined;
1474
1477
  const thread = getArgValue(args, '--thread');
1475
1478
  const returnPolicyRaw = getArgValue(args, '--return');
1476
1479
  if (returnPolicyRaw && returnPolicyRaw !== 'required' && returnPolicyRaw !== 'none') {
@@ -15,9 +15,8 @@ import { cmdInit, needsControlAidInit, initTail } from './init.js';
15
15
  import * as platform from '../utils/cross-platform.js';
16
16
  import { EventBus } from '../core/event-bus.js';
17
17
  import { tryUpgrade, tryUpgradeAunSdk, tryUpgradeGlobalPkg, resolveGlobalPkg } from '../utils/npm-ops.js';
18
- import { fetchEcwebPairCode } from '../utils/ecweb-utils.js';
18
+ import { ecwebVersionRequirementError, fetchEcwebPairCode, resolveEcwebLaunchCommand } from '../utils/ecweb-utils.js';
19
19
  import { isHostChinese } from '../utils/locale.js';
20
- import { resolveEcwebLaunchCommand } from '../utils/ecweb-utils.js';
21
20
  import { resolveAunCoreSdkPkg, AUN_CORE_SDK_PKG } from '../aun/aid/client.js';
22
21
  import { scanInstances, cleanupInstances, findOrphanProcesses, killOrphans } from '../utils/instance-registry.js';
23
22
  import { filterLogFiles, deriveLogTypes, computePreChecked, validateLogTypes, shortLogName as shortLogNameLocal } from './watch-logs.js';
@@ -2619,6 +2618,22 @@ export async function startEcwebIfEnabled(p) {
2619
2618
  const cfg = loadDaemonConfig();
2620
2619
  if (!cfg.ecweb?.enabled)
2621
2620
  return false;
2621
+ const installedPkg = resolveGlobalPkg(WEB_PACKAGE_NAME);
2622
+ if (!installedPkg) {
2623
+ console.log(`⚠ EC Web 未安装,跳过启动(运行 npm i -g ${WEB_PACKAGE_NAME}@latest 后可用)`);
2624
+ return false;
2625
+ }
2626
+ const versionError = ecwebVersionRequirementError(installedPkg.version);
2627
+ if (versionError) {
2628
+ try {
2629
+ await stopEcwebIfRunning(p);
2630
+ }
2631
+ catch (error) {
2632
+ console.log(`⚠ EC Web 旧进程未清理干净: ${error instanceof Error ? error.message : String(error)}`);
2633
+ }
2634
+ console.log(`❌ ${versionError}`);
2635
+ return false;
2636
+ }
2622
2637
  let wasRunning = false;
2623
2638
  try {
2624
2639
  wasRunning = await stopEcwebIfRunning(p); // 先停旧进程(有则停),保证加载最新代码
@@ -2629,9 +2644,9 @@ export async function startEcwebIfEnabled(p) {
2629
2644
  }
2630
2645
  const port = cfg.ecweb.port ?? 42705;
2631
2646
  const args = ['--home', p.root, '--port', String(port)];
2632
- const launch = resolveEcwebLaunchCommand(args);
2647
+ const launch = resolveEcwebLaunchCommand(args, { installedPkg });
2633
2648
  if (!launch) {
2634
- console.log(`⚠ EC Web 未安装,跳过启动(运行 npm i -g ${WEB_PACKAGE_NAME} 后可用)`);
2649
+ console.log(`⚠ EC Web 启动入口不存在,请重新安装: npm i -g ${WEB_PACKAGE_NAME}@latest`);
2635
2650
  return false;
2636
2651
  }
2637
2652
  // 防御性检查:确保 command 和 args 有效
package/dist/cli/index.js CHANGED
@@ -113,6 +113,8 @@ export async function main(args) {
113
113
  --baseagent <claude|codex|gemini|ecagent> 可选。默认从 PATH 检测,ecagent 需显式选择
114
114
  --projectpath <abs-path> 可选。默认项目目录(必须绝对路径,自动创建)
115
115
  --ecweb 可选。安装 EC Web 并启用自启动
116
+ --auto-start Windows/macOS 上启用 EvolCore 登录自启动
117
+ --no-auto-start Windows/macOS 上禁用 EvolCore 登录自启动
116
118
  --format json 可选但推荐。stdout 输出 init.result JSON
117
119
  --force 已有不同 owner 时强制覆盖
118
120
 
@@ -162,14 +164,22 @@ export async function main(args) {
162
164
  const { suppressSdkLogs } = await import('../aun/aid/index.js');
163
165
  suppressSdkLogs();
164
166
  const nonInteractive = args.includes('--non-interactive');
167
+ const wantsAutoStart = args.includes('--auto-start');
168
+ const wantsNoAutoStart = args.includes('--no-auto-start');
169
+ if (wantsAutoStart && wantsNoAutoStart) {
170
+ console.error('❌ --auto-start 与 --no-auto-start 不能同时使用');
171
+ process.exitCode = 1;
172
+ break;
173
+ }
165
174
  const initialized = await cmdInit({
166
175
  nonInteractive,
167
176
  baseagent: getArgValue(args, '--baseagent'),
168
177
  force: args.includes('--force'),
169
178
  owner: getArgValue(args, '--owner'),
170
179
  projectpath: getArgValue(args, '--projectpath'),
171
- ecweb: args.includes('--ecweb'),
180
+ ecweb: args.includes('--ecweb') ? true : undefined,
172
181
  format: getArgValue(args, '--format'),
182
+ autoStart: wantsAutoStart ? true : wantsNoAutoStart ? false : undefined,
173
183
  });
174
184
  if (!initialized)
175
185
  process.exitCode = 1;
package/dist/cli/init.js CHANGED
@@ -11,6 +11,7 @@ import { getCodexAppServerAvailability, isCodexAppServerAvailable } from '../age
11
11
  import { resolveEcagentConfig } from '../agents/baseagent.js';
12
12
  import { defaultProjectsRoot } from '../utils/project-path.js';
13
13
  import { WEB_CLI_BIN, WEB_PACKAGE_LATEST } from '../product.js';
14
+ import { autostartInstalled, autostartPlatformLabel, configureAutostart } from '../utils/autostart.js';
14
15
  // ==================== Helpers ====================
15
16
  function ask(rl, question) {
16
17
  return new Promise(resolve => rl.question(question, resolve));
@@ -66,6 +67,40 @@ function buildDefaults(chosen, available, projectsDefaultPath) {
66
67
  function writeDefaults(chosen, available, projectsDefaultPath) {
67
68
  saveDefaultsSafe(buildDefaults(chosen, available, projectsDefaultPath));
68
69
  }
70
+ function hasCompletedInitConfig() {
71
+ const p = resolvePaths();
72
+ const daemon = loadDaemonConfig();
73
+ if (!daemon.aid || !Array.isArray(daemon.owners) || daemon.owners.length === 0)
74
+ return false;
75
+ try {
76
+ const defaults = JSON.parse(fs.readFileSync(p.defaultsConfig, 'utf8'));
77
+ return typeof defaults?.active_baseagent === 'string' && defaults.active_baseagent.trim().length > 0;
78
+ }
79
+ catch {
80
+ return false;
81
+ }
82
+ }
83
+ function isAutostartOnlyRequest(options) {
84
+ return options?.autoStart !== undefined
85
+ && !options.baseagent
86
+ && !options.force
87
+ && !options.owner
88
+ && options.projectpath === undefined
89
+ && options.ecweb === undefined
90
+ && options.format === undefined;
91
+ }
92
+ function applyExplicitAutostart(enabled, runtimeRoot) {
93
+ const result = configureAutostart(enabled, runtimeRoot);
94
+ if (!result.ok) {
95
+ console.log(`❌ ${autostartPlatformLabel() || '登录自启'}配置失败: ${result.error || '未知错误'}`);
96
+ }
97
+ else {
98
+ console.log(enabled
99
+ ? `✓ 已启用 ${autostartPlatformLabel() || '登录'}自启`
100
+ : `✓ 已禁用 ${autostartPlatformLabel() || '登录'}自启`);
101
+ }
102
+ return result.ok;
103
+ }
69
104
  /** 启动门禁判定:缺控制 AID 且处于交互式终端时,应进 init 向导补全。
70
105
  * 非 TTY(restart-monitor/systemd/管道)即使缺 aid 也不进 init(无法交互),由 daemon 侧 warn 兜底。 */
71
106
  export function needsControlAidInit(aid, isTty) {
@@ -128,14 +163,29 @@ export async function cmdInit(options) {
128
163
  ecweb: options.ecweb,
129
164
  force: options.force,
130
165
  format: options.format,
166
+ autoStart: options.autoStart,
131
167
  });
132
168
  return true;
133
169
  }
170
+ if (options?.autoStart === true && !autostartPlatformLabel()) {
171
+ console.log('❌ --auto-start 仅支持 Windows 和 macOS 主机');
172
+ return false;
173
+ }
134
174
  const p = resolvePaths();
135
175
  ensureDataDirs();
176
+ // A bound installation may toggle login autostart independently of the
177
+ // Baseagent setup wizard. This is also the path used by public installers.
178
+ if (isAutostartOnlyRequest(options) && hasCompletedInitConfig()) {
179
+ return applyExplicitAutostart(options.autoStart, p.root);
180
+ }
136
181
  // ── 1. 单进程互斥 ──
137
182
  const aliveMains = scanInstances().mains.filter(m => m.alive);
138
183
  if (aliveMains.length > 0) {
184
+ // Explicit autostart flags only change the login task; they do not need
185
+ // to rewrite init configuration or stop an already running daemon.
186
+ if (isAutostartOnlyRequest(options)) {
187
+ return applyExplicitAutostart(options.autoStart, p.root);
188
+ }
139
189
  const pids = aliveMains.map(m => m.record.pid).join(', ');
140
190
  console.log(`❌ EvolCore 正在运行 (PID: ${pids}),请先执行 ec stop`);
141
191
  return false;
@@ -207,7 +257,11 @@ export async function cmdInit(options) {
207
257
  await runInteractive();
208
258
  }
209
259
  // ── 共享 tail(单一出口):提示创建 agent + 生成控制 AID ──
210
- return initTail({ invokedByStart: options?.invokedByStart });
260
+ return initTail({
261
+ invokedByStart: options?.invokedByStart,
262
+ nonInteractive: options?.nonInteractive,
263
+ autoStart: options?.autoStart,
264
+ });
211
265
  // ── 内部函数 ──
212
266
  async function runInteractive() {
213
267
  const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
@@ -318,6 +372,7 @@ export async function initTail(options = {}) {
318
372
  // 控制 AID:daemon 进程身份。缺失则生成并写回 daemon.json(幂等:已存在则跳过)。
319
373
  const daemonConfig = loadDaemonConfig();
320
374
  let controlAidReady = !!daemonConfig.aid;
375
+ let autoStartReady = true;
321
376
  if (daemonConfig.aid) {
322
377
  console.log(`✓ 控制 AID 已存在: ${daemonConfig.aid}`);
323
378
  }
@@ -335,11 +390,12 @@ export async function initTail(options = {}) {
335
390
  }
336
391
  }
337
392
  // 交互式询问:使用单一 readline 实例避免 stdin 状态混乱
338
- if (process.stdin.isTTY) {
393
+ if (!options.nonInteractive && process.stdin.isTTY) {
339
394
  const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
340
395
  try {
341
396
  await handleOwnersPrompt(rl);
342
397
  await handleEcwebPrompt(rl);
398
+ await handleAutostartPrompt(rl);
343
399
  }
344
400
  finally {
345
401
  try {
@@ -348,6 +404,38 @@ export async function initTail(options = {}) {
348
404
  catch { /* ignore */ }
349
405
  }
350
406
  }
407
+ else if (options.autoStart !== undefined) {
408
+ autoStartReady = applyAutostart(options.autoStart);
409
+ }
410
+ async function handleAutostartPrompt(rl) {
411
+ if (options.autoStart !== undefined) {
412
+ autoStartReady = applyAutostart(options.autoStart);
413
+ return;
414
+ }
415
+ if (!autostartPlatformLabel())
416
+ return;
417
+ if (autostartInstalled()) {
418
+ console.log(`✓ ${autostartPlatformLabel()} 登录自启已启用`);
419
+ return;
420
+ }
421
+ const platform = autostartPlatformLabel();
422
+ const answer = (await ask(rl, `\n是否启用 ${platform} 登录自启?[y/N] `)).trim().toLowerCase();
423
+ if (answer === 'y' || answer === 'yes')
424
+ autoStartReady = applyAutostart(true);
425
+ else
426
+ console.log(` 已跳过 ${platform} 登录自启(可日后重新运行 ec init 开启)`);
427
+ }
428
+ function applyAutostart(enabled) {
429
+ const result = configureAutostart(enabled, resolvePaths().root);
430
+ if (!result.ok) {
431
+ console.log(` ❌ ${autostartPlatformLabel() || '登录自启'}配置失败: ${result.error || '未知错误'}`);
432
+ return false;
433
+ }
434
+ console.log(enabled
435
+ ? ` ✓ 已启用 ${autostartPlatformLabel() || '登录'}自启`
436
+ : ` ✓ 已禁用 ${autostartPlatformLabel() || '登录'}自启`);
437
+ return true;
438
+ }
351
439
  async function handleOwnersPrompt(rl) {
352
440
  const daemonConfigForOwners = loadDaemonConfig();
353
441
  if (daemonConfigForOwners.aid && (!daemonConfigForOwners.owners || daemonConfigForOwners.owners.length === 0)) {
@@ -427,11 +515,13 @@ export async function initTail(options = {}) {
427
515
  }
428
516
  // ec start 会接着启动 daemon,并在其 ready 后给出可用的 Agent 创建入口。
429
517
  if (options.invokedByStart)
430
- return controlAidReady;
518
+ return controlAidReady && autoStartReady;
431
519
  if (!controlAidReady) {
432
520
  console.error('\n❌ EvolCore 初始化未完成:控制 AID 未配置。联网后重新运行 ec init。');
433
521
  return false;
434
522
  }
523
+ if (!autoStartReady)
524
+ return false;
435
525
  // 初始化完成总结
436
526
  console.log('\n✓ EvolCore 初始化完成');
437
527
  const finalCfg = loadDaemonConfig();
@@ -525,6 +615,9 @@ export async function cmdInitNonInteractive(opts, dependencies = {}) {
525
615
  if (format !== undefined && format !== 'json') {
526
616
  fail('INVALID_FORMAT', `--format only supports json: ${format}`, EXIT_USAGE, format);
527
617
  }
618
+ if (opts.autoStart === true && !autostartPlatformLabel()) {
619
+ fail('AUTOSTART_UNSUPPORTED', '--auto-start is supported only on Windows and macOS hosts', EXIT_USAGE, format);
620
+ }
528
621
  // ── 1. owner 校验 ──
529
622
  if (!opts.owner) {
530
623
  fail('MISSING_OWNER', '--owner is required in non-interactive mode', EXIT_USAGE, format);
@@ -649,6 +742,12 @@ export async function cmdInitNonInteractive(opts, dependencies = {}) {
649
742
  catch (e) {
650
743
  fail('IO_ERROR', `failed to write daemon.json: ${e?.message || e}`, EXIT_RUNTIME, format);
651
744
  }
745
+ if (opts.autoStart !== undefined) {
746
+ const autostart = configureAutostart(opts.autoStart, p.root);
747
+ if (!autostart.ok) {
748
+ fail('AUTOSTART_CONFIG_FAILED', autostart.error || 'failed to configure login autostart', EXIT_RUNTIME, format);
749
+ }
750
+ }
652
751
  // ── 10. 输出 init.result ──
653
752
  const result = {
654
753
  type: 'init.result',
@@ -656,7 +755,7 @@ export async function cmdInitNonInteractive(opts, dependencies = {}) {
656
755
  controlAid: controlAid,
657
756
  ownerAid,
658
757
  owners: [ownerAid],
659
- ecwebEnabled: opts.ecweb === true,
758
+ ecwebEnabled: opts.ecweb === true || existingCfg.ecweb?.enabled === true,
660
759
  baseagent: chosenBaseagent,
661
760
  projectsDefaultPath: projectsDefaultPath ?? null,
662
761
  defaultsPath: p.defaultsConfig,
package/dist/cli/model.js CHANGED
@@ -205,7 +205,7 @@ function modelScopeFromSource(source) {
205
205
  return undefined;
206
206
  }
207
207
  function resolveModelConfig(sel, baseagent) {
208
- const effortKey = baseagent === 'codex' ? 'reasoning' : 'effort';
208
+ const effortKey = 'effort';
209
209
  const model = resolveEffectiveFieldWithSource(`baseagents.${baseagent}.model`, sel, { cache: true });
210
210
  const effort = resolveEffectiveFieldWithSource(`baseagents.${baseagent}.${effortKey}`, sel, { cache: true });
211
211
  const modelDecision = sel.role
@@ -448,12 +448,12 @@ async function cmdUse(args, formatJson) {
448
448
  const effortVal = effort === 'auto' ? null : (effort ?? undefined);
449
449
  if (isManagedTargetedWriteEnv(args)) {
450
450
  if (effortVal !== undefined) {
451
- const effortKey = ba === 'codex' ? 'reasoning' : 'effort';
451
+ const effortKey = 'effort';
452
452
  preflightManagedFieldOverride(sel, role, `baseagents.${ba}.${effortKey}`, effortVal, formatJson);
453
453
  }
454
454
  await setManagedModelField(sel, `baseagents.${ba}.model`, modelId, formatJson);
455
455
  if (effortVal !== undefined) {
456
- const effortKey = ba === 'codex' ? 'reasoning' : 'effort';
456
+ const effortKey = 'effort';
457
457
  await setManagedModelField(sel, `baseagents.${ba}.${effortKey}`, effortVal, formatJson);
458
458
  }
459
459
  describeWrite(scope, sel, modelId, effort ?? null, formatJson);
@@ -490,7 +490,7 @@ async function cmdEffort(args, formatJson) {
490
490
  const ba = activeBaseagent(sel.self);
491
491
  const val = level === 'auto' ? null : level;
492
492
  if (isManagedTargetedWriteEnv(args)) {
493
- const effortKey = ba === 'codex' ? 'reasoning' : 'effort';
493
+ const effortKey = 'effort';
494
494
  preflightManagedFieldOverride(sel, explicitOrDerivedRole(args, sel), `baseagents.${ba}.${effortKey}`, val, formatJson);
495
495
  await setManagedModelField(sel, `baseagents.${ba}.${effortKey}`, val, formatJson);
496
496
  describeWrite(scope, sel, null, level, formatJson);
@@ -520,7 +520,7 @@ async function cmdReset(args, formatJson) {
520
520
  const scope = determineWriteScope(sel, formatJson);
521
521
  const ba = activeBaseagent(sel.self);
522
522
  if (isManagedTargetedWriteEnv(args)) {
523
- const effortKey = ba === 'codex' ? 'reasoning' : 'effort';
523
+ const effortKey = 'effort';
524
524
  const role = explicitOrDerivedRole(args, sel);
525
525
  preflightManagedFieldOverride(sel, role, `baseagents.${ba}.model`, null, formatJson);
526
526
  preflightManagedFieldOverride(sel, role, `baseagents.${ba}.${effortKey}`, null, formatJson);
@@ -1,18 +1,19 @@
1
1
  import path from 'path';
2
2
  import { kitsRoleTemplatesDir } from '../paths.js';
3
3
  import { createErrorCapturingReader, fileCache } from '../core/daemon-file-cache.js';
4
- import { validateRoleConfig } from './role-schema.js';
4
+ import { normalizeRoleEffortCompat, validateRoleConfig } from './role-schema.js';
5
5
  import { expectedRoleRank } from './role-ranks.js';
6
6
  export const BUILTIN_ROLE_IDS = ['owner', 'admin', 'member', 'visitor'];
7
7
  export function validateBuiltinRoleTemplateDefinition(roleId, raw) {
8
- const issues = validateRoleConfig(raw);
8
+ const normalizedRaw = normalizeRoleEffortCompat(raw);
9
+ const issues = validateRoleConfig(normalizedRaw);
9
10
  if (issues.length) {
10
11
  return {
11
12
  definition: null,
12
13
  error: `built-in role template failed validation: ${issues.map(issue => `${issue.field} ${issue.message}`).join('; ')}`,
13
14
  };
14
15
  }
15
- const { $schema_version: _schemaVersion, ...definition } = raw;
16
+ const { $schema_version: _schemaVersion, ...definition } = normalizedRaw;
16
17
  if (BUILTIN_ROLE_IDS.includes(roleId)) {
17
18
  const expectedRank = expectedRoleRank(roleId);
18
19
  if (definition.rank !== expectedRank) {
@@ -75,7 +75,7 @@ export function resolveConfigFieldRule(fieldPath) {
75
75
  const [, baseagent, leaf] = parts;
76
76
  if (!SUPPORTED_BASEAGENTS.has(baseagent))
77
77
  return { class: 'unknown' };
78
- const permissionKey = `baseagents.${baseagent}.${leaf}`;
78
+ const permissionKey = `baseagents.${baseagent}.${leaf === 'reasoning' ? 'effort' : leaf}`;
79
79
  if (leaf === 'model' && parts.length === 3)
80
80
  return scalar(permissionKey, 'string');
81
81
  if ((leaf === 'effort' || leaf === 'reasoning') && parts.length === 3)
@@ -178,7 +178,11 @@ export function resolveRoleFieldPermission(permissions, fieldPath) {
178
178
  const rule = resolveConfigFieldRule(fieldPath);
179
179
  if (!rule.rolePermissionKey)
180
180
  return undefined;
181
- return permissions[fieldPath] ?? permissions[rule.rolePermissionKey];
181
+ return permissions[fieldPath]
182
+ ?? permissions[rule.rolePermissionKey]
183
+ ?? (rule.rolePermissionKey === 'baseagents.codex.effort'
184
+ ? permissions['baseagents.codex.reasoning']
185
+ : undefined);
182
186
  }
183
187
  /**
184
188
  * Map relation-scoped config fields back to their public command capability.
@@ -505,10 +505,40 @@ export function read(target, sel, opts = {}) {
505
505
  : target === ConfigTarget.Relation
506
506
  ? foldLegacyProactiveBlock(migrated)
507
507
  : migrated;
508
+ // Agent read compatibility may move the legacy top-level `agents` block to
509
+ // `baseagents`, so canonicalize effort after that structural migration.
510
+ const canonicalized = normalizeBaseagentEffortCompat(normalized);
508
511
  if (!opts.expand)
509
- return normalized;
512
+ return canonicalized;
510
513
  const resolver = buildEnvResolver(envScopeFor(sel));
511
- return expandVars(normalized, resolver);
514
+ return expandVars(canonicalized, resolver);
515
+ }
516
+ /**
517
+ * Canonicalize the legacy Codex `reasoning` config key to the public `effort`
518
+ * key. The runner may still accept `reasoning` as an input alias, but all
519
+ * config scopes resolve and persist the same `effort` field.
520
+ */
521
+ function normalizeBaseagentEffortCompat(value) {
522
+ const rawBaseagents = value?.baseagents;
523
+ if (!rawBaseagents || typeof rawBaseagents !== 'object' || Array.isArray(rawBaseagents))
524
+ return value;
525
+ const baseagents = { ...rawBaseagents };
526
+ let changed = false;
527
+ for (const [name, rawBlock] of Object.entries(baseagents)) {
528
+ if (!rawBlock || typeof rawBlock !== 'object' || Array.isArray(rawBlock))
529
+ continue;
530
+ const block = { ...rawBlock };
531
+ if (Object.prototype.hasOwnProperty.call(block, 'reasoning')) {
532
+ if (block.effort === undefined)
533
+ block.effort = block.reasoning;
534
+ delete block.reasoning;
535
+ baseagents[name] = block;
536
+ changed = true;
537
+ }
538
+ }
539
+ if (!changed)
540
+ return value;
541
+ return { ...value, baseagents };
512
542
  }
513
543
  function normalizeAgentConfigForRead(value, aid) {
514
544
  const config = foldLegacyProactiveBlock(normalizeAgentLifecycle(value));
@@ -549,7 +579,7 @@ function groupFor(target, sel) {
549
579
  return 'config';
550
580
  }
551
581
  function normalizeAgentConfigForWrite(value) {
552
- const mutable = { ...value };
582
+ const mutable = normalizeBaseagentEffortCompat({ ...value });
553
583
  normalizeShowActivitiesCompat(mutable);
554
584
  // AID 格式校验
555
585
  if (mutable.aid && !isValidAid(mutable.aid)) {
@@ -587,7 +617,7 @@ function normalizeProcessConfigForWrite(value) {
587
617
  }
588
618
  }
589
619
  function normalizeRelationConfigForWrite(value) {
590
- const mutable = { ...value };
620
+ const mutable = normalizeBaseagentEffortCompat({ ...value });
591
621
  normalizeShowActivitiesCompat(mutable);
592
622
  return mutable;
593
623
  }
@@ -653,14 +683,15 @@ export function write(target, value, sel, opts = {}) {
653
683
  : loadSchema(TARGET_SCHEMA[target]);
654
684
  const withVer = ensureSchemaVersion(value, schema.version);
655
685
  const migrated = withVer;
686
+ const canonicalized = normalizeBaseagentEffortCompat(migrated);
656
687
  // Agent config 写入规范化(aid 校验、projects 字段清理)
657
688
  const normalized = target === ConfigTarget.Agent
658
- ? normalizeAgentConfigForWrite(migrated)
689
+ ? normalizeAgentConfigForWrite(canonicalized)
659
690
  : target === ConfigTarget.Relation
660
- ? normalizeRelationConfigForWrite(migrated)
691
+ ? normalizeRelationConfigForWrite(canonicalized)
661
692
  : target === ConfigTarget.Process
662
- ? normalizeProcessConfigForWrite(migrated)
663
- : migrated;
693
+ ? normalizeProcessConfigForWrite(canonicalized)
694
+ : canonicalized;
664
695
  // 1. Schema 校验
665
696
  if (!opts.skipValidate) {
666
697
  validateOrThrow(schema, normalized, target);
@@ -870,9 +901,15 @@ function validateOrThrow(schema, value, target) {
870
901
  function validateProcessOnlyFields(target, value) {
871
902
  if (target === ConfigTarget.Process || !value || typeof value !== 'object')
872
903
  return [];
873
- if (!Object.prototype.hasOwnProperty.call(value, 'debug'))
874
- return [];
875
- return ['/debug is only allowed in process config'];
904
+ const errors = [];
905
+ if (Object.prototype.hasOwnProperty.call(value, 'debug')) {
906
+ errors.push('/debug is only allowed in process config');
907
+ }
908
+ const aun = value.aun;
909
+ if (aun && typeof aun === 'object' && Object.prototype.hasOwnProperty.call(aun, 'defaultEncrypt')) {
910
+ errors.push('/aun/defaultEncrypt is only allowed in process config');
911
+ }
912
+ return errors;
876
913
  }
877
914
  function validateProcessAidDomain(target, value) {
878
915
  if (target !== ConfigTarget.Process || !value || typeof value !== 'object')
@@ -566,7 +566,7 @@ function journalFile(selfAid) {
566
566
  return path.join(agentDir(selfAid), JOURNAL_NAME);
567
567
  }
568
568
  function appendAudit(selfAid, request, previousContactRevision, contactRevisionValue) {
569
- const file = path.join(resolvePaths().dataDir, 'contact-book-audit.jsonl');
569
+ const file = path.join(agentDir(selfAid), 'data', 'contact-audit.jsonl');
570
570
  fs.mkdirSync(path.dirname(file), { recursive: true });
571
571
  fs.appendFileSync(file, `${JSON.stringify({
572
572
  timestamp: new Date().toISOString(),
@@ -1,4 +1,18 @@
1
1
  import { loadSchema } from './schema-registry.js';
2
+ const LEGACY_CODEX_EFFORT_FIELD = 'baseagents.codex.reasoning';
3
+ const CODEX_EFFORT_FIELD = 'baseagents.codex.effort';
4
+ /** Convert the legacy flattened Codex role permission key to `effort`. */
5
+ export function normalizeRoleEffortCompat(value) {
6
+ if (!isRecord(value) || !isRecord(value.permissions)
7
+ || !Object.hasOwn(value.permissions, LEGACY_CODEX_EFFORT_FIELD))
8
+ return value;
9
+ const permissions = { ...value.permissions };
10
+ if (!Object.hasOwn(permissions, CODEX_EFFORT_FIELD)) {
11
+ permissions[CODEX_EFFORT_FIELD] = permissions[LEGACY_CODEX_EFFORT_FIELD];
12
+ }
13
+ delete permissions[LEGACY_CODEX_EFFORT_FIELD];
14
+ return { ...value, permissions };
15
+ }
2
16
  export function rolePermissionFields() {
3
17
  const raw = loadSchema('role-config').raw['x-permission-fields'];
4
18
  if (!Array.isArray(raw))
@@ -41,9 +55,10 @@ export function rolePermissionFieldPatterns(field) {
41
55
  }
42
56
  /** Shared RoleService/Menu validation backed by the published role schema. */
43
57
  export function validateRoleConfig(value) {
44
- const normalized = isRecord(value) && !Object.hasOwn(value, '$schema_version')
45
- ? { ...value, $schema_version: 1 }
46
- : value;
58
+ const compatible = normalizeRoleEffortCompat(value);
59
+ const normalized = isRecord(compatible) && !Object.hasOwn(compatible, '$schema_version')
60
+ ? { ...compatible, $schema_version: 1 }
61
+ : compatible;
47
62
  const schema = loadSchema('role-config');
48
63
  if (!schema.validate(normalized)) {
49
64
  return (schema.validate.errors ?? []).map(error => ({
@@ -6,7 +6,7 @@ import { loadSchema } from './schema-registry.js';
6
6
  import { clearRoleStoreCache, getStoredRoleRegistry, isRoleName, readRoleStore, roleRegistryExists, } from './role-store.js';
7
7
  import { expectedRoleRank, isManagementRole } from './builtin-roles.js';
8
8
  import { readBuiltinRoleTemplate } from './builtin-role-templates.js';
9
- import { validateRoleConfig } from './role-schema.js';
9
+ import { normalizeRoleEffortCompat, validateRoleConfig } from './role-schema.js';
10
10
  export class RoleServiceError extends Error {
11
11
  code;
12
12
  data;
@@ -43,7 +43,7 @@ export function writeRoleRegistry(selfAid, value) {
43
43
  export function writeRoleDefinition(selfAid, roleId, value) {
44
44
  if (!isRoleName(roleId))
45
45
  throw new RoleServiceError('INVALID_ROLE_ID', `Invalid role id: ${roleId}`);
46
- const normalized = { ...value, rank: expectedRoleRank(roleId), $schema_version: 1 };
46
+ const normalized = normalizeRoleEffortCompat({ ...value, rank: expectedRoleRank(roleId), $schema_version: 1 });
47
47
  validateRoleDefinition(normalized);
48
48
  const registry = readRoleRegistry(selfAid);
49
49
  if (!registry.roles.includes(roleId)) {
@@ -93,7 +93,7 @@ export function listRoleDiagnostics(selfAid) {
93
93
  return readRoleStore(selfAid).diagnostics;
94
94
  }
95
95
  function writeRoleDefinitionFile(selfAid, roleId, value) {
96
- const normalized = { ...value, rank: expectedRoleRank(roleId), $schema_version: 1 };
96
+ const normalized = normalizeRoleEffortCompat({ ...value, rank: expectedRoleRank(roleId), $schema_version: 1 });
97
97
  validateRoleDefinition(normalized);
98
98
  const file = agentRoleConfig(selfAid, roleId);
99
99
  fs.mkdirSync(path.dirname(file), { recursive: true });
@@ -5,7 +5,7 @@ import { agentRoleConfig, agentRolesDir, agentRolesIndex, kitsRoleTemplatesDir,
5
5
  import { applyManagementRoleCeiling, expectedRoleRank, getManagementRoleDefinition } from './builtin-roles.js';
6
6
  import { readBuiltinRoleTemplate } from './builtin-role-templates.js';
7
7
  import { loadSchema } from './schema-registry.js';
8
- import { validateRoleConfig } from './role-schema.js';
8
+ import { normalizeRoleEffortCompat, validateRoleConfig } from './role-schema.js';
9
9
  const ROLE_NAME_RE = /^[a-z0-9_-]+$/;
10
10
  const BUILTIN_ROLES = ['owner', 'admin', 'member', 'visitor'];
11
11
  const cache = new Map();
@@ -154,9 +154,10 @@ function readDefinition(selfAid, roleId, diagnostics) {
154
154
  }
155
155
  if (raw === null)
156
156
  continue;
157
- const issues = validateRoleConfig(raw);
157
+ const normalizedRaw = normalizeRoleEffortCompat(raw);
158
+ const issues = validateRoleConfig(normalizedRaw);
158
159
  if (issues.length === 0) {
159
- const { $schema_version: _schemaVersion, ...definition } = raw;
160
+ const { $schema_version: _schemaVersion, ...definition } = normalizedRaw;
160
161
  const expectedRank = expectedRoleRank(roleId);
161
162
  if (definition.rank !== undefined && definition.rank !== expectedRank) {
162
163
  diagnostics.push({
@@ -69,6 +69,10 @@ function validateDaemonConfig(value, validateAidDomain) {
69
69
  if (menuTokenRequired !== undefined && typeof menuTokenRequired !== 'boolean') {
70
70
  throw new Error('daemon.json.aun.menuTokenRequired must be a boolean');
71
71
  }
72
+ const defaultEncrypt = value.aun?.defaultEncrypt;
73
+ if (defaultEncrypt !== undefined && typeof defaultEncrypt !== 'boolean') {
74
+ throw new Error('daemon.json.aun.defaultEncrypt must be a boolean');
75
+ }
72
76
  if (validateAidDomain && value.aun?.defaultAidDomain !== undefined) {
73
77
  const defaultAidDomain = normalizeAidDomain(value.aun.defaultAidDomain, 'daemon.json.aun.defaultAidDomain');
74
78
  return { ...value, aun: { ...value.aun, defaultAidDomain } };
@@ -673,7 +673,9 @@ function parseLegacyChannelType(peerKey) {
673
673
  }
674
674
  function checkFieldOverride(ctx, field) {
675
675
  const roleDef = getRoleDefinition(ctx.role, ctx.selfAid);
676
- const fieldPermission = roleDef?.permissions?.[field];
676
+ const fieldPermission = roleDef
677
+ ? resolveRoleFieldPermission(roleDef.permissions || {}, field)
678
+ : undefined;
677
679
  if (!fieldPermission) {
678
680
  return { ok: false, reason: `Role ${ctx.role} has no field permission for ${field}` };
679
681
  }
@@ -74,7 +74,6 @@ export class BootstrapService {
74
74
  agentName: aid,
75
75
  }), { kind: 'result.text', text, isFinal: true });
76
76
  this.eventBus.publish({ type: 'agent:bootstrap-started', aid, channel: channelType || ctx.channelKey, timestamp: Date.now() });
77
- await this.sendAunBindingCredentialIfSupported(ctx.adapter, recipientId, agentName, baseagent);
78
77
  logger.info(`[Bootstrap] Started for ${aid} via ${ctx.channelKey} (${ctx.source})`);
79
78
  return true;
80
79
  }
@@ -154,15 +153,4 @@ export class BootstrapService {
154
153
  logger.warn(`[Bootstrap] Failed to publish agent.md for ${aid}: ${e instanceof Error ? e.message : String(e)}`);
155
154
  }
156
155
  }
157
- async sendAunBindingCredentialIfSupported(adapter, owner, name, baseagent) {
158
- const sendBinding = adapter._sendBindingCredential;
159
- if (typeof sendBinding !== 'function')
160
- return;
161
- try {
162
- await sendBinding(owner, name, baseagent);
163
- }
164
- catch (e) {
165
- logger.warn(`[Bootstrap] Binding credential failed: ${e instanceof Error ? e.message : String(e)}`);
166
- }
167
- }
168
156
  }