evolcore 0.0.23 → 0.0.25

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 (245) hide show
  1. package/CHANGELOG.md +583 -516
  2. package/LICENSE +21 -21
  3. package/README.md +455 -453
  4. package/bin/codex-managed-acl.ps1 +160 -155
  5. package/bin/codex-managed-hook.mjs +209 -92
  6. package/bin/ec-safe-output.js +327 -245
  7. package/bin/ec.js +29 -29
  8. package/bin/install-codex-managed-hooks.mjs +555 -544
  9. package/dist/agents/baseagent-availability.js +4 -4
  10. package/dist/agents/baseagent.js +29 -1
  11. package/dist/agents/claude-runner.js +152 -14
  12. package/dist/agents/codex/app-server-client.js +18 -8
  13. package/dist/agents/codex/catalog.js +1 -1
  14. package/dist/agents/codex/diagnostics.js +215 -0
  15. package/dist/agents/codex-runner.js +445 -63
  16. package/dist/agents/ecagent-runner.js +31 -16
  17. package/dist/agents/gemini-runner.js +82 -4
  18. package/dist/agents/runner-types.js +1 -1
  19. package/dist/aun/aid/agentmd.js +56 -4
  20. package/dist/aun/aid/index.js +1 -0
  21. package/dist/aun/aid/managed-operation.js +80 -6
  22. package/dist/aun/aid/store.js +41 -0
  23. package/dist/aun/msg/managed-operation.js +6 -1
  24. package/dist/aun/outbox.js +56 -18
  25. package/dist/aun/rpc/client.js +4 -5
  26. package/dist/aun/storage/client.js +4 -1
  27. package/dist/aun/storage/index.js +1 -1
  28. package/dist/channels/aun.js +147 -76
  29. package/dist/channels/daemon.js +7 -1
  30. package/dist/channels/dingtalk.js +1 -0
  31. package/dist/channels/feishu.js +10 -4
  32. package/dist/channels/wecom.js +2 -1
  33. package/dist/cli/agent-command.js +214 -89
  34. package/dist/cli/agent-create.js +576 -0
  35. package/dist/cli/agent.js +129 -676
  36. package/dist/cli/aun-commands.js +419 -313
  37. package/dist/cli/bench.js +20 -20
  38. package/dist/cli/config.js +20 -20
  39. package/dist/cli/contact.js +10 -10
  40. package/dist/cli/ctl-command.js +22 -20
  41. package/dist/cli/daemon-commands.js +163 -32
  42. package/dist/cli/fs-command.js +67 -67
  43. package/dist/cli/handoff-command.js +7 -7
  44. package/dist/cli/index.js +79 -79
  45. package/dist/cli/link-rules.js +21 -21
  46. package/dist/cli/managed-command-guard.js +3 -0
  47. package/dist/cli/menu-client.js +11 -11
  48. package/dist/cli/net-check.js +22 -22
  49. package/dist/cli/queue-command.js +29 -29
  50. package/dist/cli/response.js +30 -30
  51. package/dist/cli/restart-monitor.js +462 -38
  52. package/dist/cli/stats.js +161 -51
  53. package/dist/cli/trigger-command.js +56 -56
  54. package/dist/config/builtin-roles.js +3 -0
  55. package/dist/config/config-manager.js +15 -0
  56. package/dist/config/config-operation-service.js +20 -3
  57. package/dist/config/resolved-config-op.js +39 -1
  58. package/dist/core/auth/auth-gateway.js +3 -2
  59. package/dist/core/auth/authorization-audit.js +72 -19
  60. package/dist/core/auth/operation-authorizer.js +125 -7
  61. package/dist/core/auth/operation-catalog.js +26 -2
  62. package/dist/core/auth/remote-access-store.js +3 -2
  63. package/dist/core/baseagent-loader.js +4 -4
  64. package/dist/core/bootstrap-messages.js +39 -18
  65. package/dist/core/bootstrap-service.js +32 -26
  66. package/dist/core/capability/capability-manager.js +8 -4
  67. package/dist/core/capability/providers/codex-capability-provider.js +1 -1
  68. package/dist/core/command/agent-control.js +60 -26
  69. package/dist/core/command/cli-intent-parser.js +18 -0
  70. package/dist/core/command/command-handler.js +173 -36
  71. package/dist/core/command/menu-catalog.js +4 -1
  72. package/dist/core/command/menu-handler.js +315 -75
  73. package/dist/core/command/menu-protocol.js +7 -2
  74. package/dist/core/command/slash-gate.js +1 -3
  75. package/dist/core/command/slash-handler.js +166 -57
  76. package/dist/core/data-migration.js +5 -15
  77. package/dist/core/event-catalog.js +8 -0
  78. package/dist/core/evolagent.js +3 -3
  79. package/dist/core/handoff/runtime.js +3 -1
  80. package/dist/core/handoff/store.js +7 -1
  81. package/dist/core/message/im-renderer.js +13 -6
  82. package/dist/core/message/message-bridge.js +5 -36
  83. package/dist/core/message/message-utils.js +6 -3
  84. package/dist/core/message/response-engine.js +85 -27
  85. package/dist/core/model/catalog-service.js +3 -1
  86. package/dist/core/model/model-catalog.js +10 -0
  87. package/dist/core/model/model-permission.js +4 -1
  88. package/dist/core/permission/approval-gateway.js +169 -33
  89. package/dist/core/permission/tool-policy.js +56 -10
  90. package/dist/core/session/adapters/codex-session-file-adapter.js +71 -3
  91. package/dist/core/session/session-manager.js +49 -13
  92. package/dist/core/session/session-renew.js +1 -0
  93. package/dist/index.js +327 -134
  94. package/dist/ipc.js +68 -21
  95. package/dist/paths.js +23 -1
  96. package/dist/stats/billing.js +18 -4
  97. package/dist/stats/db.js +159 -159
  98. package/dist/stats/eck-vars.js +9 -9
  99. package/dist/stats/query.js +139 -139
  100. package/dist/stats/role-budget.js +6 -6
  101. package/dist/stats/writer.js +51 -51
  102. package/dist/utils/atomic-write.js +26 -2
  103. package/dist/utils/avatar-upload.js +282 -23
  104. package/dist/utils/cross-platform.js +436 -1
  105. package/dist/utils/error-dict.json +160 -160
  106. package/dist/utils/error-utils.js +11 -4
  107. package/dist/utils/macos-autostart.js +22 -22
  108. package/dist/utils/model-prices.jsonl +23 -20
  109. package/dist/utils/npm-ops.js +24 -1
  110. package/dist/utils/welcome.js +22 -22
  111. package/dist/utils/windows-autostart.js +1 -1
  112. package/ecagent/LICENSE +21 -21
  113. package/ecagent/NOTICE +11 -11
  114. package/ecagent/README.md +61 -61
  115. package/ecagent/dist/harness/compaction/branch-summarization.js +30 -30
  116. package/ecagent/dist/harness/compaction/compaction.js +83 -83
  117. package/ecagent/dist/harness/messages.js +7 -7
  118. package/kits/docs/GUIDE.md +20 -20
  119. package/kits/docs/INDEX.md +66 -66
  120. package/kits/docs/aun/CHEATSHEET.md +19 -19
  121. package/kits/docs/aun/SYNC_PROTOCOL.md +15 -15
  122. package/kits/docs/channels/aun.md +56 -56
  123. package/kits/docs/channels/feishu.md +56 -56
  124. package/kits/docs/context-assembly.md +365 -364
  125. package/kits/docs/eck_templates/GUIDE.template.md +22 -22
  126. package/kits/docs/eck_templates/INDEX.template.md +28 -28
  127. package/kits/docs/eck_templates/path-registry.template.md +33 -33
  128. package/kits/docs/eck_templates/runtime.template.md +19 -19
  129. package/kits/docs/evolcore/INDEX.md +71 -69
  130. package/kits/docs/evolcore/agent-create.md +170 -156
  131. package/kits/docs/evolcore/agent.md +83 -73
  132. package/kits/docs/evolcore/aid.md +64 -62
  133. package/kits/docs/evolcore/codex-windows-sandbox.md +146 -0
  134. package/kits/docs/evolcore/config.md +195 -195
  135. package/kits/docs/evolcore/contact.md +68 -68
  136. package/kits/docs/evolcore/ctl.md +46 -46
  137. package/kits/docs/evolcore/event.md +216 -216
  138. package/kits/docs/evolcore/fs-architecture.md +1215 -1215
  139. package/kits/docs/evolcore/fs.md +110 -110
  140. package/kits/docs/evolcore/group-collaboration.md +243 -243
  141. package/kits/docs/evolcore/group-fs.md +17 -17
  142. package/kits/docs/evolcore/group-rules.md +251 -251
  143. package/kits/docs/evolcore/group.md +152 -152
  144. package/kits/docs/evolcore/menu-client.md +34 -34
  145. package/kits/docs/evolcore/model.md +50 -50
  146. package/kits/docs/evolcore/msg.md +165 -165
  147. package/kits/docs/evolcore/response.md +75 -75
  148. package/kits/docs/evolcore/rpc.md +37 -37
  149. package/kits/docs/evolcore/self-summary.md +29 -29
  150. package/kits/docs/evolcore/stats.md +83 -83
  151. package/kits/docs/evolcore/storage.md +50 -50
  152. package/kits/docs/evolcore/trigger.md +575 -575
  153. package/kits/docs/identity/AID_PROFILE_SPEC.md +26 -26
  154. package/kits/docs/identity/PATH_OPS.md +16 -16
  155. package/kits/docs/identity/ROLE_DETAIL.md +25 -25
  156. package/kits/docs/identity/identity-tools.md +26 -26
  157. package/kits/docs/path-registry.md +62 -62
  158. package/kits/docs/prompt-loading-architecture.md +270 -269
  159. package/kits/docs/venues/aun-group.md +45 -45
  160. package/kits/docs/venues/aun-private.md +10 -10
  161. package/kits/docs/venues/client-desktop.md +10 -10
  162. package/kits/docs/venues/client-mobile.md +10 -10
  163. package/kits/docs/venues/feishu-group.md +13 -13
  164. package/kits/docs/venues/feishu-private.md +9 -9
  165. package/kits/docs/venues/group.md +25 -25
  166. package/kits/docs/venues/private.md +10 -10
  167. package/kits/eck_manifest.auxiliary.json +43 -43
  168. package/kits/eck_manifest.json +195 -183
  169. package/kits/eck_message_manifest.json +74 -74
  170. package/kits/migrations/README-role-config-v4.md +32 -32
  171. package/kits/migrations/migrate-contact-book-v2.mjs +748 -748
  172. package/kits/migrations/migrate-role-config-v4.mjs +614 -614
  173. package/kits/migrations/migrate-role-config-v5.mjs +365 -365
  174. package/kits/migrations/rename-config-file.mjs +99 -99
  175. package/kits/rules/01-overview.md +162 -162
  176. package/kits/rules/02-navigation.md +96 -96
  177. package/kits/rules/03-identity.md +39 -37
  178. package/kits/rules/04-relation.md +75 -75
  179. package/kits/rules/05-venue.md +60 -60
  180. package/kits/rules/06-channel.md +63 -63
  181. package/kits/schemas/_meta.json +53 -53
  182. package/kits/schemas/agent-config.schema.1.json +177 -177
  183. package/kits/schemas/agent-config.schema.10.json +395 -395
  184. package/kits/schemas/agent-config.schema.11.json +421 -421
  185. package/kits/schemas/agent-config.schema.12.json +427 -427
  186. package/kits/schemas/agent-config.schema.2.json +239 -239
  187. package/kits/schemas/agent-config.schema.3.json +119 -119
  188. package/kits/schemas/agent-config.schema.4.json +208 -208
  189. package/kits/schemas/agent-config.schema.5.json +326 -326
  190. package/kits/schemas/agent-config.schema.6.json +322 -322
  191. package/kits/schemas/agent-config.schema.7.json +303 -303
  192. package/kits/schemas/agent-config.schema.8.json +304 -304
  193. package/kits/schemas/agent-config.schema.9.json +364 -364
  194. package/kits/schemas/contact-book.schema.1.json +36 -36
  195. package/kits/schemas/contact-book.schema.2.json +43 -43
  196. package/kits/schemas/contact-book.schema.3.json +67 -67
  197. package/kits/schemas/daemon.schema.1.json +91 -91
  198. package/kits/schemas/daemon.schema.2.json +101 -101
  199. package/kits/schemas/daemon.schema.3.json +123 -123
  200. package/kits/schemas/daemon.schema.4.json +136 -136
  201. package/kits/schemas/daemon.schema.5.json +135 -135
  202. package/kits/schemas/daemon.schema.6.json +131 -131
  203. package/kits/schemas/defaults.schema.1.json +81 -81
  204. package/kits/schemas/defaults.schema.2.json +85 -85
  205. package/kits/schemas/defaults.schema.3.json +73 -73
  206. package/kits/schemas/defaults.schema.4.json +107 -107
  207. package/kits/schemas/defaults.schema.5.json +119 -119
  208. package/kits/schemas/menu-exec-schema-commands.md +208 -208
  209. package/kits/schemas/migrations/README.md +30 -30
  210. package/kits/schemas/relation-config.schema.1.json +158 -158
  211. package/kits/schemas/relation-config.schema.2.json +73 -73
  212. package/kits/schemas/relation-config.schema.3.json +50 -50
  213. package/kits/schemas/relation-config.schema.4.json +47 -47
  214. package/kits/schemas/relation-config.schema.5.json +47 -47
  215. package/kits/schemas/relation-config.schema.6.json +46 -46
  216. package/kits/schemas/relation-config.schema.7.json +59 -59
  217. package/kits/schemas/relation-config.schema.8.json +103 -103
  218. package/kits/schemas/role-config.schema.1.json +201 -201
  219. package/kits/schemas/role-registry.schema.1.json +35 -35
  220. package/kits/schemas/single-session.schema.1.json +31 -31
  221. package/kits/schemas/single-session.schema.2.json +57 -57
  222. package/kits/schemas/single-session.schema.3.json +32 -32
  223. package/kits/templates/bootstrap-welcome.md +17 -17
  224. package/kits/templates/message-fragments/handoff-context-to-target.md +9 -9
  225. package/kits/templates/message-fragments/handoff-request-to-target.md +19 -19
  226. package/kits/templates/message-fragments/handoff-response-to-origin.md +9 -9
  227. package/kits/templates/message-fragments/inject-default.md +2 -2
  228. package/kits/templates/message-fragments/item.md +2 -2
  229. package/kits/templates/roles/admin.json +96 -82
  230. package/kits/templates/roles/member.json +97 -96
  231. package/kits/templates/roles/owner.json +9 -9
  232. package/kits/templates/roles/visitor.json +86 -85
  233. package/kits/templates/system-fragments/baseagent.md +14 -14
  234. package/kits/templates/system-fragments/bootstrap.md +38 -29
  235. package/kits/templates/system-fragments/channel.md +64 -64
  236. package/kits/templates/system-fragments/commands.md +28 -28
  237. package/kits/templates/system-fragments/identity.md +13 -13
  238. package/kits/templates/system-fragments/relation.md +19 -19
  239. package/kits/templates/system-fragments/session.md +59 -59
  240. package/kits/templates/system-fragments/venue.md +31 -31
  241. package/package.json +98 -94
  242. package/AGENTS.md +0 -62
  243. package/dist/utils/codex-cli.js +0 -43
  244. package/skills/eclink/SKILL.md +0 -84
  245. package/skills/eclink/agents/openai.yaml +0 -4
package/dist/index.js CHANGED
@@ -100,6 +100,7 @@ import { MAIN_PACKAGE_NAME } from './product.js';
100
100
  import fs from 'fs';
101
101
  import crypto from 'crypto';
102
102
  import { fileURLToPath } from 'url';
103
+ import * as platform from './utils/cross-platform.js';
103
104
  const controlMenuDeduper = new MenuRequestDeduper();
104
105
  /** 出站 payload 摘要(用于 channel-out.log) */
105
106
  function summarizeOutboundPayload(payload) {
@@ -134,6 +135,7 @@ function summarizeOutboundPayload(payload) {
134
135
  break;
135
136
  case 'status.started':
136
137
  case 'status.progress':
138
+ case 'status.notice':
137
139
  case 'status.requires_action':
138
140
  case 'status.queued':
139
141
  case 'status.completed':
@@ -326,102 +328,158 @@ function seedUpgradeCheckTrigger(manager, owner) {
326
328
  const cliPath = path.join(packageRoot, 'dist', 'cli', 'index.js');
327
329
  const packageJsonPath = path.join(packageRoot, 'package.json');
328
330
  const devMode = fs.existsSync(path.join(packageRoot, 'src', 'index.ts'));
329
- fs.writeFileSync(scriptPath, `#!/usr/bin/env node
330
- const { existsSync, readFileSync } = require('node:fs');
331
- const { spawn } = require('node:child_process');
332
-
333
- const CLI_PATH = ${JSON.stringify(cliPath)};
334
- const PACKAGE_JSON = ${JSON.stringify(packageJsonPath)};
335
- const PACKAGE_NAME = ${JSON.stringify(MAIN_PACKAGE_NAME)};
336
- const DEV_MODE = ${devMode ? 'true' : 'false'};
337
-
338
- function emit(outcome, text) {
339
- process.stdout.write(JSON.stringify({ outcome, text, files: [] }));
340
- }
341
-
342
- function compareVersions(a, b) {
343
- const pa = a.split('-')[0].split('.').map(Number);
344
- const pb = b.split('-')[0].split('.').map(Number);
345
- const count = Math.max(pa.length, pb.length);
346
- for (let i = 0; i < count; i += 1) {
347
- const av = Number.isFinite(pa[i]) ? pa[i] : 0;
348
- const bv = Number.isFinite(pb[i]) ? pb[i] : 0;
349
- if (av < bv) return -1;
350
- if (av > bv) return 1;
351
- }
352
- return 0;
353
- }
354
-
355
- async function latestVersion() {
356
- const controller = new AbortController();
357
- const timer = setTimeout(() => controller.abort(), 10_000);
358
- try {
359
- const response = await fetch('https://registry.npmjs.org/' + encodeURIComponent(PACKAGE_NAME) + '/latest', {
360
- signal: controller.signal,
361
- headers: { Accept: 'application/json' },
362
- });
363
- if (!response.ok) return null;
364
- const data = await response.json();
365
- return typeof data.version === 'string' ? data.version : null;
366
- } finally {
367
- clearTimeout(timer);
368
- }
369
- }
370
-
371
- async function main() {
372
- if (DEV_MODE) {
373
- emit('noop', 'upgrade check skipped in dev mode');
374
- return;
375
- }
376
-
377
- let localVersion;
378
- try {
379
- localVersion = JSON.parse(readFileSync(PACKAGE_JSON, 'utf8')).version;
380
- } catch {
381
- emit('error', 'failed to read local ec version');
382
- return;
383
- }
384
- if (typeof localVersion !== 'string' || !localVersion) {
385
- emit('error', 'failed to read local ec version');
386
- return;
387
- }
388
-
389
- let remoteVersion;
390
- try {
391
- remoteVersion = await latestVersion();
392
- } catch {
393
- remoteVersion = null;
394
- }
395
- if (!remoteVersion) {
396
- emit('error', 'failed to check evolcore latest version');
397
- return;
398
- }
399
- if (compareVersions(localVersion, remoteVersion) >= 0) {
400
- emit('noop', 'evolcore is already up to date (' + localVersion + '; latest ' + remoteVersion + ')');
401
- return;
402
- }
403
- if (!existsSync(CLI_PATH)) {
404
- emit('error', 'restart-monitor entry not found: ' + CLI_PATH);
405
- return;
406
- }
407
-
408
- try {
409
- const child = spawn(process.execPath, [CLI_PATH, 'restart-monitor'], {
410
- detached: true,
411
- stdio: 'ignore',
412
- windowsHide: process.platform === 'win32',
413
- env: { ...process.env },
414
- });
415
- child.unref();
416
- emit('success', 'evolcore upgrade available: ' + localVersion + ' -> ' + remoteVersion + '; restart-monitor started');
417
- } catch (error) {
418
- emit('error', 'failed to start restart-monitor: ' + (error && error.message ? error.message : String(error)));
419
- }
420
- }
421
-
422
- main().catch((error) => {
423
- emit('error', 'upgrade check failed: ' + (error && error.message ? error.message : String(error)));
424
- });
331
+ // Resolve the launch argv at generation time: in a checkout this points the
332
+ // monitor at src/ through tsx, so a `npm run build` that wipes dist/ cannot
333
+ // take the watchdog down with it.
334
+ const monitorEntry = platform.resolveCliEntry(packageRoot);
335
+ const stageParent = path.join(resolvePaths().root, 'data', 'monitor-stage');
336
+ fs.writeFileSync(scriptPath, `#!/usr/bin/env node
337
+ const fs = require('node:fs');
338
+ const path = require('node:path');
339
+ const { existsSync, readFileSync } = fs;
340
+ const { spawn } = require('node:child_process');
341
+
342
+ const CLI_PATH = ${JSON.stringify(monitorEntry.entry)};
343
+ const CLI_ARGS = ${JSON.stringify(monitorEntry.args)};
344
+ const PACKAGE_ROOT = ${JSON.stringify(packageRoot)};
345
+ const STAGE_PARENT = ${JSON.stringify(stageParent)};
346
+ const PACKAGE_JSON = ${JSON.stringify(packageJsonPath)};
347
+ const PACKAGE_NAME = ${JSON.stringify(MAIN_PACKAGE_NAME)};
348
+ const DEV_MODE = ${devMode ? 'true' : 'false'};
349
+
350
+ function emit(outcome, text) {
351
+ process.stdout.write(JSON.stringify({ outcome, text, files: [] }));
352
+ }
353
+
354
+ function compareVersions(a, b) {
355
+ const pa = a.split('-')[0].split('.').map(Number);
356
+ const pb = b.split('-')[0].split('.').map(Number);
357
+ const count = Math.max(pa.length, pb.length);
358
+ for (let i = 0; i < count; i += 1) {
359
+ const av = Number.isFinite(pa[i]) ? pa[i] : 0;
360
+ const bv = Number.isFinite(pb[i]) ? pb[i] : 0;
361
+ if (av < bv) return -1;
362
+ if (av > bv) return 1;
363
+ }
364
+ return 0;
365
+ }
366
+
367
+ async function latestVersion() {
368
+ const controller = new AbortController();
369
+ const timer = setTimeout(() => controller.abort(), 10_000);
370
+ try {
371
+ const response = await fetch('https://registry.npmjs.org/' + encodeURIComponent(PACKAGE_NAME) + '/latest', {
372
+ signal: controller.signal,
373
+ headers: { Accept: 'application/json' },
374
+ });
375
+ if (!response.ok) return null;
376
+ const data = await response.json();
377
+ return typeof data.version === 'string' ? data.version : null;
378
+ } finally {
379
+ clearTimeout(timer);
380
+ }
381
+ }
382
+
383
+ async function main() {
384
+ if (DEV_MODE) {
385
+ emit('noop', 'upgrade check skipped in dev mode');
386
+ return;
387
+ }
388
+
389
+ let localVersion;
390
+ try {
391
+ localVersion = JSON.parse(readFileSync(PACKAGE_JSON, 'utf8')).version;
392
+ } catch {
393
+ emit('error', 'failed to read local ec version');
394
+ return;
395
+ }
396
+ if (typeof localVersion !== 'string' || !localVersion) {
397
+ emit('error', 'failed to read local ec version');
398
+ return;
399
+ }
400
+
401
+ let remoteVersion;
402
+ try {
403
+ remoteVersion = await latestVersion();
404
+ } catch {
405
+ remoteVersion = null;
406
+ }
407
+ if (!remoteVersion) {
408
+ emit('error', 'failed to check evolcore latest version');
409
+ return;
410
+ }
411
+ if (compareVersions(localVersion, remoteVersion) >= 0) {
412
+ emit('noop', 'evolcore is already up to date (' + localVersion + '; latest ' + remoteVersion + ')');
413
+ return;
414
+ }
415
+ if (!existsSync(CLI_PATH)) {
416
+ emit('error', 'restart-monitor entry not found: ' + CLI_PATH);
417
+ return;
418
+ }
419
+
420
+ // Installed mode: copy the monitor out of the package before it upgrades that
421
+ // same package. Mirrors prepareMonitorStage(); kept inline because this file
422
+ // is generated standalone CJS. Any failure degrades to launching in place —
423
+ // losing upgrade isolation beats losing the upgrade.
424
+ let launchArgs = CLI_ARGS;
425
+ const launchEnv = { ...process.env };
426
+ if (!DEV_MODE && STAGE_PARENT) {
427
+ try {
428
+ const stageDir = path.join(STAGE_PARENT, 'upgrade-' + process.pid + '-' + Date.now());
429
+ fs.mkdirSync(stageDir, { recursive: true });
430
+ fs.cpSync(path.join(PACKAGE_ROOT, 'dist'), path.join(stageDir, 'dist'), { recursive: true });
431
+ if (existsSync(PACKAGE_JSON)) fs.copyFileSync(PACKAGE_JSON, path.join(stageDir, 'package.json'));
432
+ const modulesSource = path.join(PACKAGE_ROOT, 'node_modules');
433
+ if (existsSync(modulesSource)) {
434
+ const staged = path.join(stageDir, 'node_modules');
435
+ try {
436
+ // junction works unelevated on Windows; dir symlink elsewhere.
437
+ fs.symlinkSync(modulesSource, staged, process.platform === 'win32' ? 'junction' : 'dir');
438
+ fs.readdirSync(staged);
439
+ } catch (linkError) {
440
+ fs.rmSync(staged, { recursive: true, force: true });
441
+ fs.cpSync(modulesSource, staged, { recursive: true });
442
+ }
443
+ }
444
+ const stagedEntry = path.join(stageDir, 'dist', 'cli', 'index.js');
445
+ if (existsSync(stagedEntry)) {
446
+ launchArgs = [stagedEntry];
447
+ launchEnv.EVOLCORE_TARGET_PACKAGE_ROOT = PACKAGE_ROOT;
448
+ launchEnv.EVOLCORE_MONITOR_STAGE = stageDir;
449
+ }
450
+ } catch (stageError) {
451
+ // Fall through with the in-place entry.
452
+ }
453
+ }
454
+
455
+ try {
456
+ const child = spawn(process.execPath, [...launchArgs, 'restart-monitor'], {
457
+ detached: true,
458
+ stdio: 'ignore',
459
+ windowsHide: process.platform === 'win32',
460
+ env: launchEnv,
461
+ });
462
+ child.unref();
463
+ const pid = child.pid;
464
+ // The daemon is still running here — the monitor is what stops it. So a
465
+ // monitor that dies on load costs the upgrade, not the service; still,
466
+ // report it accurately instead of claiming success.
467
+ await new Promise(resolve => setTimeout(resolve, 3000));
468
+ let alive = false;
469
+ try { process.kill(pid, 0); alive = true; } catch (e) { alive = false; }
470
+ if (!alive) {
471
+ emit('error', 'restart-monitor exited during startup; upgrade to ' + remoteVersion + ' not applied');
472
+ return;
473
+ }
474
+ emit('success', 'evolcore upgrade available: ' + localVersion + ' -> ' + remoteVersion + '; restart-monitor started');
475
+ } catch (error) {
476
+ emit('error', 'failed to start restart-monitor: ' + (error && error.message ? error.message : String(error)));
477
+ }
478
+ }
479
+
480
+ main().catch((error) => {
481
+ emit('error', 'upgrade check failed: ' + (error && error.message ? error.message : String(error)));
482
+ });
425
483
  `);
426
484
  // Remove the pre-Node script left by older installations so it cannot be
427
485
  // selected by a stale trigger definition or run manually by accident.
@@ -1066,7 +1124,7 @@ async function main() {
1066
1124
  agentLoader.register(new GeminiAgentPlugin());
1067
1125
  agentLoader.register(new EcagentAgentPlugin());
1068
1126
  const creationErrors = [];
1069
- const agentInstances = agentLoader.createAll(agentRegistry, {
1127
+ const agentInstances = await agentLoader.createAll(agentRegistry, {
1070
1128
  onSessionIdUpdate: async (sessionId, agentSessionId, context) => {
1071
1129
  return await sessionManager.updateAgentSessionIdBySessionId(sessionId, agentSessionId, context?.turn);
1072
1130
  },
@@ -1493,8 +1551,9 @@ async function main() {
1493
1551
  }
1494
1552
  if (definition.execution.effort && !actor.daemonPrivileged) {
1495
1553
  const baseagent = definition.execution.baseagent
1496
- ?? agentRegistry.get(definition.agentAid)?.baseagent
1497
- ?? 'claude';
1554
+ ?? agentRegistry.get(definition.agentAid)?.baseagent;
1555
+ if (!baseagent)
1556
+ throw new Error('cannot determine Trigger baseagent');
1498
1557
  const effortDecision = validateRuntimeStringFieldOverride({
1499
1558
  selfAid: definition.agentAid,
1500
1559
  role: actor.role,
@@ -2154,6 +2213,7 @@ async function main() {
2154
2213
  const pendingRouteContext = restartDelivery.delivery ? { delivery: restartDelivery.delivery } : {};
2155
2214
  const replyContext = {
2156
2215
  ...(pendingRouteContext ?? {}),
2216
+ ...(pending.threadId ? { threadId: pending.threadId } : {}),
2157
2217
  ...(pending.rootId ? { replyToMessageId: pending.rootId, replyInThread: !!pending.threadId } : {}),
2158
2218
  };
2159
2219
  const owningAgent = agentRegistry.resolveByChannel(adapter.channelKey);
@@ -2165,10 +2225,23 @@ async function main() {
2165
2225
  ...(restartDelivery.delivery ? { delivery: restartDelivery.delivery } : {}),
2166
2226
  replyContext: Object.keys(replyContext).length > 0 ? replyContext : undefined,
2167
2227
  });
2228
+ // restart-monitor 会在回滚/升级时写入 outcome:必须如实告诉发起方这次跑的是
2229
+ // 哪个版本,否则 agent 会以为自己的改动或升级已经生效。
2230
+ const restartNotice = pending.outcome === 'rolled-back'
2231
+ ? {
2232
+ text: `⚠️ 服务已重启,但运行的是上一个版本。${pending.outcomeReason ? `原因:${pending.outcomeReason}。` : ''}本次改动未生效,请检查后重试。`,
2233
+ subtype: 'restarted-rolled-back',
2234
+ }
2235
+ : pending.outcome === 'upgraded'
2236
+ ? {
2237
+ text: `✅ 服务重启成功!${pending.outcomeReason ? `${pending.outcomeReason}` : ''}`,
2238
+ subtype: 'restarted-upgraded',
2239
+ }
2240
+ : { text: '✅ 服务重启成功!', subtype: 'restarted' };
2168
2241
  await sendSystemPayload(adapter, envelope, {
2169
2242
  kind: 'system.notice',
2170
- text: '✅ 服务重启成功!',
2171
- subtype: 'restarted',
2243
+ text: restartNotice.text,
2244
+ subtype: restartNotice.subtype,
2172
2245
  });
2173
2246
  pendingRestartNoticeSent = true;
2174
2247
  fs.rmSync(pendingFile, { force: true });
@@ -2658,9 +2731,18 @@ async function main() {
2658
2731
  continue;
2659
2732
  }
2660
2733
  const evolName = owningAgent.aid;
2661
- const baseagentName = session.baseagent || primaryBaseagent;
2662
- const agent = agentMap.get(`${evolName}::${baseagentName}`) || agentMap.get(primaryRunnerKey);
2734
+ const baseagentName = typeof session.baseagent === 'string' ? session.baseagent.trim() : '';
2735
+ if (!baseagentName) {
2736
+ logger.error(`[Resume] session ${session.id}: missing baseagent binding, refusing implicit runner fallback`);
2737
+ sessionManager.clearProcessing(session.id);
2738
+ continue;
2739
+ }
2740
+ // Recovery must resume on the exact Agent × baseagent runner recorded by
2741
+ // the Session. Never fall back to the primary runner: doing so can bind
2742
+ // an in-flight session to a different backend.
2743
+ const agent = agentMap.get(`${evolName}::${baseagentName}`);
2663
2744
  if (!agent) {
2745
+ logger.error(`[Resume] session ${session.id}: runner unavailable for ${evolName}::${baseagentName}; refusing fallback`);
2664
2746
  sessionManager.clearProcessing(session.id);
2665
2747
  continue;
2666
2748
  }
@@ -2727,11 +2809,12 @@ async function main() {
2727
2809
  return owner?.aid === aid;
2728
2810
  });
2729
2811
  const welcome = aunInstance?.channel;
2730
- const ownerAid = getFirstStaticAgentOwner(aid);
2731
2812
  const owningAgent = agentRegistry.get(aid);
2732
- const sessions = aunInstance && ownerAid && owningAgent
2813
+ const firstOwnerAid = getFirstStaticAgentOwner(aid);
2814
+ const sessions = aunInstance && firstOwnerAid && owningAgent
2733
2815
  ? {
2734
- ensurePostBootstrapMainSession: async () => {
2816
+ ensurePostBootstrapMainSession: async (owner) => {
2817
+ const ownerAid = owner || firstOwnerAid;
2735
2818
  const channel = aunInstance.adapter.channelName;
2736
2819
  const active = await sessionManager.getActiveSession(channel, ownerAid);
2737
2820
  const ensured = await sessionManager.ensureNewMainSessionForOperation({
@@ -2739,7 +2822,7 @@ async function main() {
2739
2822
  channelId: ownerAid,
2740
2823
  projectPath: active?.projectPath || owningAgent.projectPath || defaultProjectPath,
2741
2824
  baseagent: owningAgent.baseagent || active?.baseagent || primaryBaseagent,
2742
- operationId: postBootstrapWelcomeOperationId(aid),
2825
+ operationId: postBootstrapWelcomeOperationId(aid, ownerAid),
2743
2826
  identityMetadata: {
2744
2827
  ...(active?.metadata ?? {}),
2745
2828
  channelKey: aunInstance.adapter.channelKey,
@@ -2851,15 +2934,18 @@ async function main() {
2851
2934
  for (const runner of new Set(agentMap.values())) {
2852
2935
  if (typeof runner?.evaluatePreToolUse !== 'function')
2853
2936
  continue;
2854
- const result = await runner.evaluatePreToolUse(params.threadId, params.toolName, params.toolInput, params.signal, params.callId);
2937
+ const result = await runner.evaluatePreToolUse(params.threadId, params.toolName, params.toolInput, params.signal, params.callId, params.sessionToken);
2855
2938
  if (result.applicable)
2856
2939
  return result;
2857
2940
  }
2941
+ // A credential that no runner issued is forged or belongs to a thread
2942
+ // whose rollout is gone. Never allow it; uncredentialed calls were
2943
+ // already allowed by the IPC layer before reaching this executor.
2858
2944
  return {
2859
2945
  ok: false,
2860
2946
  applicable: true,
2861
2947
  decision: 'deny',
2862
- reason: 'No active EvolCore Codex runner accepted this managed hook request',
2948
+ reason: 'No active EvolCore Codex runner accepted this managed hook credential',
2863
2949
  };
2864
2950
  });
2865
2951
  const resolveManagedHandoffScope = async (params, operation) => {
@@ -3192,7 +3278,7 @@ async function main() {
3192
3278
  const creationErrors = [];
3193
3279
  const staged = candidate.config.enabled === false
3194
3280
  ? []
3195
- : agentLoader.createForAgent(candidate, {
3281
+ : await agentLoader.createForAgent(candidate, {
3196
3282
  onSessionIdUpdate: async (sessionId, agentSessionId, context) => {
3197
3283
  return await sessionManager.updateAgentSessionIdBySessionId(sessionId, agentSessionId, context?.turn);
3198
3284
  },
@@ -3292,7 +3378,7 @@ async function main() {
3292
3378
  throw new Error(agentRuntimeError);
3293
3379
  }
3294
3380
  const creationErrors = [];
3295
- const newAgentInstances = agentLoader.createForAgent(agent, {
3381
+ const newAgentInstances = await agentLoader.createForAgent(agent, {
3296
3382
  onSessionIdUpdate: async (sessionId, agentSessionId, context) => {
3297
3383
  return await sessionManager.updateAgentSessionIdBySessionId(sessionId, agentSessionId, context?.turn);
3298
3384
  },
@@ -3483,7 +3569,7 @@ async function main() {
3483
3569
  hotLoad: coreHotLoadAgent,
3484
3570
  resync: coreResyncAgents,
3485
3571
  create: async (options) => {
3486
- const { agentCreateNonInteractive } = await import('./cli/agent.js');
3572
+ const { agentCreateNonInteractive } = await import('./cli/agent-create.js');
3487
3573
  return await agentCreateNonInteractive(options, { hotLoadAgent: coreHotLoadAgent });
3488
3574
  },
3489
3575
  aunAids: () => channelInstances.flatMap((inst) => {
@@ -3577,7 +3663,8 @@ async function main() {
3577
3663
  });
3578
3664
  if (params.targetAid
3579
3665
  && params.targetAid !== delegation.grant.selfAid
3580
- && subject.dataScope !== 'daemon') {
3666
+ && subject.dataScope !== 'daemon'
3667
+ && !(operation === 'agent.show' && isManagementRole(subject.role))) {
3581
3668
  return { ok: false, code: 'SCOPE_MISMATCH', error: 'only the current Agent can be targeted' };
3582
3669
  }
3583
3670
  const decision = authorizeOperation({
@@ -3624,18 +3711,21 @@ async function main() {
3624
3711
  const taskAid = delegation.grant.selfAid;
3625
3712
  const targetAid = sub === 'list'
3626
3713
  ? undefined
3627
- : sub === 'show'
3628
- ? (argv[2] && !argv[2].startsWith('--') ? argv[2] : taskAid)
3629
- : sub === 'reload'
3630
- ? (argv[2] && !argv[2].startsWith('--') ? argv[2] : undefined)
3631
- : (argv[2] && !argv[2].startsWith('--') ? argv[2] : undefined);
3714
+ : sub === 'persona'
3715
+ ? taskAid
3716
+ : sub === 'show'
3717
+ ? (argv[2] && !argv[2].startsWith('--') ? argv[2] : taskAid)
3718
+ : sub === 'reload'
3719
+ ? (argv[2] && !argv[2].startsWith('--') ? argv[2] : undefined)
3720
+ : (argv[2] && !argv[2].startsWith('--') ? argv[2] : undefined);
3632
3721
  const operation = sub === 'list' ? 'agent.list'
3633
3722
  : sub === 'show' ? 'agent.show'
3634
- : sub === 'new' ? 'agent.create'
3635
- : sub === 'enable' ? 'agent.enable'
3636
- : sub === 'disable' ? 'agent.disable'
3637
- : sub === 'reload' ? 'agent.reload'
3638
- : sub === 'delete' ? 'agent.delete' : undefined;
3723
+ : sub === 'persona' ? 'agent.persona'
3724
+ : sub === 'new' ? 'agent.create'
3725
+ : sub === 'enable' ? 'agent.enable'
3726
+ : sub === 'disable' ? 'agent.disable'
3727
+ : sub === 'reload' ? 'agent.reload'
3728
+ : sub === 'delete' ? 'agent.delete' : undefined;
3639
3729
  if (!operation)
3640
3730
  return fail('INVALID_ARGS', `unsupported managed agent command: ${sub}`);
3641
3731
  if (sub === 'new' && !argv.includes('--non-interactive')) {
@@ -3667,7 +3757,7 @@ async function main() {
3667
3757
  subject,
3668
3758
  intent: {
3669
3759
  operation,
3670
- scope: operation === 'agent.show'
3760
+ scope: operation === 'agent.show' || operation === 'agent.persona'
3671
3761
  ? 'agent'
3672
3762
  : operation === 'agent.reload' && targetAid
3673
3763
  ? 'agent'
@@ -3723,45 +3813,148 @@ async function main() {
3723
3813
  },
3724
3814
  connection: agent.connection ?? null,
3725
3815
  sessions: agent.sessions ?? { active: 0, last_activity: null },
3726
- paths: { config: null, agent_md: null, project: null, data: null },
3727
- redacted: true,
3816
+ paths: subject.dataScope === 'daemon'
3817
+ ? (agent.paths ?? { config: null, agent_md: null, project: null, data: null })
3818
+ : { config: null, agent_md: null, project: null, data: null },
3819
+ ...(subject.dataScope === 'daemon' ? {} : { redacted: true }),
3728
3820
  ...(agent.createProgress ? { createProgress: agent.createProgress } : {}),
3729
3821
  } };
3730
3822
  }
3823
+ if (operation === 'agent.persona') {
3824
+ const rawPersonaArgs = argv.slice(2);
3825
+ const hasFormatSuffix = rawPersonaArgs.length >= 2
3826
+ && rawPersonaArgs.at(-2) === '--format'
3827
+ && rawPersonaArgs.at(-1) === 'json';
3828
+ const personaArgs = hasFormatSuffix ? rawPersonaArgs.slice(0, -2) : rawPersonaArgs;
3829
+ if (!hasFormatSuffix && rawPersonaArgs.includes('--format')) {
3830
+ return fail('INVALID_ARGS', 'persona 仅支持末尾的 --format json');
3831
+ }
3832
+ if (personaArgs.length === 2 && personaArgs[0] === '--file') {
3833
+ return fail('INVALID_ARGS', '托管 persona --file 必须由 CLI 读取后作为文本提交');
3834
+ }
3835
+ const wantsShow = personaArgs.length === 1 && personaArgs[0] === 'show';
3836
+ const text = personaArgs.length === 2 && personaArgs[0] === '--text'
3837
+ ? personaArgs[1]
3838
+ : undefined;
3839
+ if (!wantsShow && !(personaArgs.length === 2 && personaArgs[0] === '--text')) {
3840
+ return fail('INVALID_ARGS', '用法: ec agent persona show | --text <text>');
3841
+ }
3842
+ if (text === undefined && !wantsShow)
3843
+ return fail('INVALID_ARGS', 'persona --text 缺少参数');
3844
+ const { agentPersona } = await import('./cli/agent.js');
3845
+ const result = await agentPersona(taskAid, wantsShow ? { trustedLocal: true } : { text, trustedLocal: true });
3846
+ if (!result.ok)
3847
+ return fail(result.code ?? 'INTERNAL', result.error);
3848
+ return { ok: true, result: {
3849
+ ok: true,
3850
+ aid: taskAid,
3851
+ content: result.content,
3852
+ ...(result.saved ? { saved: true } : {}),
3853
+ } };
3854
+ }
3731
3855
  if (operation === 'agent.create') {
3732
3856
  const aid = argv[2] && !argv[2].startsWith('--') ? argv[2] : undefined;
3733
3857
  if (!aid)
3734
3858
  return fail('INVALID_ARGS', 'ec agent new requires an AID');
3735
- const { agentCreateNonInteractive, resolveAgentCreatePlan, validateAgentCreatePlan } = await import('./cli/agent.js');
3859
+ const { agentCreateNonInteractive, resolveAgentCreatePlan, validateAgentCreatePlan, parseAgentOwnerArgs, parseAgentTags } = await import('./cli/agent-create.js');
3860
+ let ownerOptions;
3861
+ try {
3862
+ ownerOptions = parseAgentOwnerArgs(argv);
3863
+ }
3864
+ catch (error) {
3865
+ return fail('INVALID_ARGS', error instanceof Error ? error.message : String(error));
3866
+ }
3867
+ let tags;
3868
+ try {
3869
+ tags = parseAgentTags(value('--tags'));
3870
+ }
3871
+ catch (error) {
3872
+ return fail('INVALID_ARGS', error instanceof Error ? error.message : String(error));
3873
+ }
3736
3874
  const plan = resolveAgentCreatePlan({
3737
3875
  aid,
3738
3876
  project: value('--project'),
3739
3877
  baseagent: value('--baseagent'),
3740
- owner: value('--owner'),
3878
+ ...ownerOptions,
3879
+ handoff: value('--handoff'),
3741
3880
  name: value('--name'),
3742
3881
  description: value('--description'),
3882
+ tags,
3743
3883
  force: argv.includes('--force'),
3744
3884
  });
3745
3885
  const validationError = validateAgentCreatePlan(plan);
3746
3886
  if (validationError)
3747
3887
  return fail('INVALID_ARGS', validationError);
3888
+ if (argv.includes('--handoff')) {
3889
+ if (!delegation.grant.messageId)
3890
+ return fail('INVALID_ARGS', '--handoff requires an originating message');
3891
+ if (!plan.handoff?.trim())
3892
+ return fail('INVALID_ARGS', '--handoff requires non-empty context');
3893
+ if ((plan.owners?.[0] ?? plan.owner) !== taskAid) {
3894
+ return fail('INVALID_ARGS', '--handoff requires the creating Agent to be the first Owner');
3895
+ }
3896
+ if (plan.configExists)
3897
+ return fail('INVALID_ARGS', '--handoff requires a new Agent');
3898
+ }
3748
3899
  if (argv.includes('--dry-run'))
3749
3900
  return { ok: true, result: { ok: true, dryRun: true, plan } };
3901
+ let handoffId;
3902
+ if (plan.handoff) {
3903
+ try {
3904
+ const created = await handoffRuntime.createOutbound({
3905
+ selfAid: taskAid,
3906
+ to: aid,
3907
+ originSessionId: sessionId,
3908
+ originMessageId: delegation.grant.messageId,
3909
+ payload: { type: 'text', text: plan.handoff },
3910
+ encrypt: true,
3911
+ targetChatType: 'private',
3912
+ explicitReturnPolicy: 'required',
3913
+ contextOnly: true,
3914
+ originAuthorization: {
3915
+ actorId: delegation.grant.actorId,
3916
+ channelKey: delegation.grant.channel,
3917
+ channelType: delegation.grant.channelType,
3918
+ chatType: delegation.grant.chatType,
3919
+ peerKey: delegation.grant.peerKey,
3920
+ },
3921
+ causation: responseEngine.getTaskRuntimeContext(sessionId)?.causation,
3922
+ });
3923
+ handoffId = created.handoff?.handoff_id;
3924
+ if (!handoffId)
3925
+ return fail('INVALID_ARGS', '--handoff requires a different target session');
3926
+ }
3927
+ catch (error) {
3928
+ return fail('HANDOFF_PREPARE_FAILED', error instanceof Error ? error.message : String(error));
3929
+ }
3930
+ }
3750
3931
  const createOptions = {
3751
3932
  aid: plan.aid,
3752
3933
  project: plan.project,
3753
3934
  baseagent: plan.baseagent,
3754
3935
  owner: plan.owner,
3936
+ owners: plan.owners,
3755
3937
  name: plan.name,
3756
3938
  description: plan.description,
3939
+ tags: plan.tags,
3757
3940
  force: argv.includes('--force'),
3758
3941
  };
3759
- const result = agentApplicationService
3760
- ? await agentApplicationService.create(createOptions)
3761
- : await agentCreateNonInteractive(createOptions);
3762
- return !result.ok
3763
- ? fail(result.code ?? 'INTERNAL', result.error)
3764
- : { ok: true, result: { ...result, configPath: '[redacted]' } };
3942
+ try {
3943
+ const result = agentApplicationService
3944
+ ? await agentApplicationService.create(createOptions)
3945
+ : await agentCreateNonInteractive(createOptions);
3946
+ if (!result.ok) {
3947
+ if (handoffId)
3948
+ handoffRuntime.store.discard(taskAid, handoffId, 'operation_failed');
3949
+ return fail(result.code ?? 'INTERNAL', result.error);
3950
+ }
3951
+ return { ok: true, result: { ...result, configPath: '[redacted]', ...(handoffId ? { handoff_id: handoffId } : {}) } };
3952
+ }
3953
+ catch (error) {
3954
+ if (handoffId)
3955
+ handoffRuntime.store.discard(taskAid, handoffId, 'operation_failed');
3956
+ return fail('INTERNAL', error instanceof Error ? error.message : String(error));
3957
+ }
3765
3958
  }
3766
3959
  if (operation === 'agent.delete') {
3767
3960
  const result = agentApplicationService