evolcore 0.0.2 → 0.0.4

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 (206) hide show
  1. package/CHANGELOG.md +93 -778
  2. package/README.md +45 -10
  3. package/bin/ec-safe-output.js +89 -24
  4. package/dist/agents/baseagent.js +46 -0
  5. package/dist/agents/claude-runner.js +198 -48
  6. package/dist/agents/codex-app-server-client.js +68 -0
  7. package/dist/agents/codex-runner.js +203 -8
  8. package/dist/agents/runner-types.js +2 -2
  9. package/dist/aun/aid/agentmd.js +79 -0
  10. package/dist/aun/aid/encryption-seed-policy.js +29 -0
  11. package/dist/aun/aid/index.js +1 -1
  12. package/dist/aun/aid/store.js +2 -5
  13. package/dist/aun/outbox.js +8 -0
  14. package/dist/channels/aun.js +241 -116
  15. package/dist/channels/daemon.js +18 -4
  16. package/dist/channels/dingtalk.js +1005 -260
  17. package/dist/channels/feishu.js +184 -56
  18. package/dist/channels/qqbot.js +23 -1
  19. package/dist/channels/wechat.js +303 -155
  20. package/dist/channels/wecom.js +1132 -164
  21. package/dist/cli/agent-command.js +2 -1
  22. package/dist/cli/aun-commands.js +98 -43
  23. package/dist/cli/bench.js +2 -2
  24. package/dist/cli/contact.js +71 -0
  25. package/dist/cli/ctl-command.js +2 -2
  26. package/dist/cli/daemon-commands.js +77 -214
  27. package/dist/cli/handoff-command.js +4 -3
  28. package/dist/cli/help.js +9 -5
  29. package/dist/cli/index.js +132 -116
  30. package/dist/cli/init-channel.js +242 -129
  31. package/dist/cli/init.js +70 -31
  32. package/dist/cli/model.js +2 -1
  33. package/dist/cli/net-check.js +2 -2
  34. package/dist/cli/queue-command.js +30 -6
  35. package/dist/cli/raw-key-input.js +25 -0
  36. package/dist/cli/response.js +5 -6
  37. package/dist/cli/restart-monitor.js +25 -1
  38. package/dist/cli/stats.js +6 -4
  39. package/dist/cli/trigger-command.js +146 -25
  40. package/dist/cli/version.js +6 -1
  41. package/dist/config/access-policy-domain.js +38 -0
  42. package/dist/config/access-policy.js +134 -0
  43. package/dist/config/builtin-role-templates.js +42 -17
  44. package/dist/config/builtin-roles.js +31 -6
  45. package/dist/config/config-field-policy.js +17 -5
  46. package/dist/config/config-manager.js +409 -29
  47. package/dist/config/config-operation-service.js +35 -38
  48. package/dist/config/contact-alias.js +68 -0
  49. package/dist/config/contact-bind-code.js +274 -0
  50. package/dist/config/contact-book-store.js +622 -0
  51. package/dist/config/contact-book-v2-startup.js +35 -0
  52. package/dist/config/contact-book.js +185 -300
  53. package/dist/config/contact-operation-service.js +116 -0
  54. package/dist/config/contact-request-service.js +331 -0
  55. package/dist/config/peer-role-resolver.js +136 -55
  56. package/dist/config/role-ranks.js +18 -0
  57. package/dist/config/role-service.js +16 -19
  58. package/dist/config/role-store.js +16 -5
  59. package/dist/config/roles.js +10 -1
  60. package/dist/config/schema-registry.js +49 -24
  61. package/dist/config-store.js +14 -4
  62. package/dist/core/auth/agent-delegation.js +105 -11
  63. package/dist/core/auth/authorization-audit.js +16 -1
  64. package/dist/core/auth/operation-authorizer.js +10 -0
  65. package/dist/core/auth/operation-catalog.js +105 -1
  66. package/dist/core/auth/trigger-authorization.js +15 -0
  67. package/dist/core/bootstrap-service.js +2 -9
  68. package/dist/core/channel-loader.js +6 -2
  69. package/dist/core/command/command-handler.js +113 -21
  70. package/dist/core/command/connect-menu.js +599 -0
  71. package/dist/core/command/evol-menu-version-gate.js +38 -0
  72. package/dist/core/command/group-menu.js +421 -0
  73. package/dist/core/command/menu-handler.js +382 -100
  74. package/dist/core/command/menu-protocol.js +8 -2
  75. package/dist/core/command/menu-token-store.js +102 -0
  76. package/dist/core/command/role-menu.js +128 -29
  77. package/dist/core/command/slash-gate.js +1 -1
  78. package/dist/core/command/slash-handler.js +186 -49
  79. package/dist/core/daemon-file-cache.js +40 -6
  80. package/dist/core/event-catalog.js +99 -0
  81. package/dist/core/evolagent-registry.js +4 -40
  82. package/dist/core/evolagent.js +20 -9
  83. package/dist/core/handoff/runtime.js +162 -37
  84. package/dist/core/handoff/store.js +46 -2
  85. package/dist/core/handoff/types.js +1 -0
  86. package/dist/core/inference/text-inference.js +16 -74
  87. package/dist/core/message/file-markers.js +7 -0
  88. package/dist/core/message/im-renderer.js +20 -14
  89. package/dist/core/message/inbound-admission.js +124 -0
  90. package/dist/core/message/message-bridge.js +670 -57
  91. package/dist/core/message/message-log.js +1 -0
  92. package/dist/core/message/message-queue.js +195 -10
  93. package/dist/core/message/message-utils.js +8 -2
  94. package/dist/core/message/peer-mode.js +7 -8
  95. package/dist/core/message/response-engine.js +642 -96
  96. package/dist/core/message/send-receipt.js +24 -0
  97. package/dist/core/message/stream-debouncer.js +11 -2
  98. package/dist/core/permission/approval-gateway.js +17 -10
  99. package/dist/core/permission/ec-command-parser.js +101 -46
  100. package/dist/core/permission/tool-policy.js +115 -38
  101. package/dist/core/protected-paths.js +38 -11
  102. package/dist/core/session/session-fs-store.js +44 -3
  103. package/dist/core/session/session-manager.js +86 -8
  104. package/dist/core/session/session-mapper.js +2 -0
  105. package/dist/core/session/session-renew.js +125 -69
  106. package/dist/core/session/session-turn-coordinator.js +5 -1
  107. package/dist/eck/kit-renderer.js +12 -1
  108. package/dist/eck/message-renderer.js +79 -1
  109. package/dist/index.js +285 -94
  110. package/dist/ipc.js +114 -8
  111. package/dist/paths.js +3 -0
  112. package/dist/response-system/config-resolver.js +29 -0
  113. package/dist/response-system/coordinator.js +8 -32
  114. package/dist/response-system/engines/v1/proactive-flow.js +1 -1
  115. package/dist/response-system/index.js +1 -0
  116. package/dist/response-system/modes/single-session/index.js +7 -4
  117. package/dist/stats/billing.js +20 -8
  118. package/dist/trigger/manager.js +3 -0
  119. package/dist/trigger/parser.js +126 -11
  120. package/dist/trigger/patch.js +12 -2
  121. package/dist/trigger/scheduler.js +444 -40
  122. package/dist/trigger/validation.js +13 -0
  123. package/dist/utils/aid-bind.js +43 -29
  124. package/dist/utils/error-dict.json +7 -0
  125. package/dist/utils/evolcore-version.js +21 -0
  126. package/dist/utils/instance-registry.js +14 -7
  127. package/dist/utils/log-writer.js +46 -0
  128. package/dist/utils/logger.js +2 -2
  129. package/dist/utils/media-cache.js +4 -1
  130. package/dist/utils/model-prices.jsonl +6 -3
  131. package/dist/utils/restart-safety.js +31 -0
  132. package/dist/utils/stable-semver.js +21 -0
  133. package/dist/utils/stats.js +33 -9
  134. package/dist/utils/system-memory.js +62 -0
  135. package/kits/docs/INDEX.md +2 -1
  136. package/kits/docs/channels/aun.md +4 -13
  137. package/kits/docs/evolcore/INDEX.md +5 -3
  138. package/kits/docs/evolcore/agent.md +9 -1
  139. package/kits/docs/evolcore/aid.md +5 -2
  140. package/kits/docs/evolcore/config.md +47 -2
  141. package/kits/docs/evolcore/contact.md +61 -0
  142. package/kits/docs/evolcore/fs.md +9 -0
  143. package/kits/docs/evolcore/group-rules.md +46 -4
  144. package/kits/docs/evolcore/group.md +15 -6
  145. package/kits/docs/evolcore/model.md +4 -1
  146. package/kits/docs/evolcore/msg.md +12 -6
  147. package/kits/docs/evolcore/response.md +16 -21
  148. package/kits/docs/evolcore/rpc.md +2 -0
  149. package/kits/docs/evolcore/stats.md +15 -2
  150. package/kits/docs/evolcore/storage.md +1 -0
  151. package/kits/docs/evolcore/trigger.md +42 -10
  152. package/kits/docs/path-registry.md +36 -17
  153. package/kits/eck_manifest.json +12 -0
  154. package/kits/eck_message_manifest.json +12 -1
  155. package/kits/migrations/migrate-contact-book-v2.mjs +754 -0
  156. package/kits/rules/01-overview.md +17 -7
  157. package/kits/rules/02-navigation.md +38 -18
  158. package/kits/rules/03-identity.md +28 -24
  159. package/kits/rules/04-relation.md +44 -28
  160. package/kits/rules/05-venue.md +31 -15
  161. package/kits/rules/06-channel.md +11 -7
  162. package/kits/schemas/_meta.json +21 -7
  163. package/kits/schemas/agent-config.schema.6.json +322 -0
  164. package/kits/schemas/agent-config.schema.7.json +303 -0
  165. package/kits/schemas/agent-config.schema.8.json +304 -0
  166. package/kits/schemas/agent-config.schema.9.json +374 -0
  167. package/kits/schemas/contact-book.schema.2.json +43 -0
  168. package/kits/schemas/contact-book.schema.3.json +67 -0
  169. package/kits/schemas/daemon.schema.1.json +3 -2
  170. package/kits/schemas/daemon.schema.2.json +101 -0
  171. package/kits/schemas/daemon.schema.3.json +123 -0
  172. package/kits/schemas/defaults.schema.2.json +85 -0
  173. package/kits/schemas/defaults.schema.3.json +73 -0
  174. package/kits/schemas/relation-config.schema.5.json +47 -0
  175. package/kits/schemas/relation-config.schema.6.json +46 -0
  176. package/kits/schemas/relation-config.schema.7.json +59 -0
  177. package/kits/schemas/role-config.schema.1.json +1 -0
  178. package/kits/schemas/role-registry.schema.1.json +2 -2
  179. package/kits/schemas/single-session.schema.2.json +57 -0
  180. package/kits/templates/message-fragments/handoff-context-to-target.md +9 -0
  181. package/kits/templates/message-fragments/handoff-request-to-target.md +14 -8
  182. package/kits/templates/message-fragments/handoff-response-to-origin.md +5 -6
  183. package/kits/templates/roles/admin.json +47 -0
  184. package/kits/templates/roles/member.json +5 -0
  185. package/kits/templates/roles/owner.json +1 -0
  186. package/kits/templates/roles/visitor.json +5 -0
  187. package/kits/templates/system-fragments/channel.md +12 -2
  188. package/kits/templates/system-fragments/commands.md +3 -1
  189. package/kits/templates/system-fragments/identity.md +3 -1
  190. package/kits/templates/system-fragments/relation.md +1 -1
  191. package/kits/templates/system-fragments/session.md +6 -2
  192. package/package.json +7 -5
  193. package/MIGRATION-0.5.0.md +0 -378
  194. package/ROLE_ACCESS_CONTROL.md +0 -174
  195. package/assets/brand/evolcore/README.md +0 -19
  196. package/assets/brand/evolcore/evolcore-app-icon.png +0 -0
  197. package/assets/brand/evolcore/evolcore-app-icon.svg +0 -13
  198. package/assets/brand/evolcore/evolcore-brand-board.png +0 -0
  199. package/assets/brand/evolcore/evolcore-brand-board.svg +0 -126
  200. package/assets/brand/evolcore/evolcore-logo-kit.zip +0 -0
  201. package/assets/brand/evolcore/evolcore-logo-reverse.png +0 -0
  202. package/assets/brand/evolcore/evolcore-logo-reverse.svg +0 -14
  203. package/assets/brand/evolcore/evolcore-logo.png +0 -0
  204. package/assets/brand/evolcore/evolcore-logo.svg +0 -14
  205. package/assets/brand/evolcore/evolcore-mark.png +0 -0
  206. package/assets/brand/evolcore/evolcore-mark.svg +0 -10
package/dist/ipc.js CHANGED
@@ -8,6 +8,8 @@ import { HANDOFF_QUERY_MAX_LIMIT, HANDOFF_STATES } from './core/handoff/types.js
8
8
  import { resolvePaths } from './paths.js';
9
9
  import { getProcessStartTime, isSameOrOlderProcess } from './utils/process-introspect.js';
10
10
  import { classifyProcessTree, ProcessTreeSampler } from './utils/process-tree-stats.js';
11
+ import { readSystemMemoryUsage } from './utils/system-memory.js';
12
+ import { hashCurrentDelegatedCommand } from './core/auth/agent-delegation.js';
11
13
  const isWindows = process.platform === 'win32';
12
14
  const isNamedPipe = (p) => isWindows && p.startsWith('\\\\.\\pipe\\');
13
15
  export function summarizeMonitorAgents(agents, aids) {
@@ -45,7 +47,12 @@ export class IpcServer {
45
47
  handoffTraceExecutor;
46
48
  bindExecutor;
47
49
  configOperationExecutor;
50
+ contactOperationExecutor;
48
51
  dingtalkContactBindExecutor;
52
+ feishuContactBindExecutor;
53
+ qqbotContactBindExecutor;
54
+ wecomContactBindExecutor;
55
+ wechatContactBindExecutor;
49
56
  // CPU 占用追踪:IPC handler 是一次性同步调用,无法在响应里做 200ms 异步采样,
50
57
  // 故用后台 1s interval 累积 process.cpuUsage() 增量,handler 直接读最近值。
51
58
  // procCpuPercent = 本 daemon 进程占单核的百分比(可 >100% 仅当多核,已 clamp 到 100);
@@ -75,6 +82,9 @@ export class IpcServer {
75
82
  setConfigOperationExecutor(executor) {
76
83
  this.configOperationExecutor = executor;
77
84
  }
85
+ setContactOperationExecutor(executor) {
86
+ this.contactOperationExecutor = executor;
87
+ }
78
88
  /** Inject AUN AID state aggregator for aun-aids IPC handler */
79
89
  setAunAidProvider(provider) {
80
90
  this.aunAidProvider = provider;
@@ -136,6 +146,22 @@ export class IpcServer {
136
146
  setDingtalkContactBindExecutor(executor) {
137
147
  this.dingtalkContactBindExecutor = executor;
138
148
  }
149
+ /** Inject Feishu contact binding-code executor. */
150
+ setFeishuContactBindExecutor(executor) {
151
+ this.feishuContactBindExecutor = executor;
152
+ }
153
+ /** Inject QQ contact binding-code executor. */
154
+ setQQBotContactBindExecutor(executor) {
155
+ this.qqbotContactBindExecutor = executor;
156
+ }
157
+ /** Inject WeCom contact binding-code executor. */
158
+ setWecomContactBindExecutor(executor) {
159
+ this.wecomContactBindExecutor = executor;
160
+ }
161
+ /** Inject WeChat contact binding-code executor. */
162
+ setWechatContactBindExecutor(executor) {
163
+ this.wechatContactBindExecutor = executor;
164
+ }
139
165
  /** Start the 1s background CPU sampling loop (for monitor-snapshot). Call after start(). */
140
166
  startCpuTracking() {
141
167
  if (this.cpuTimer)
@@ -315,12 +341,72 @@ export class IpcServer {
315
341
  if (!this.dingtalkContactBindExecutor) {
316
342
  return { ok: false, error: 'dingtalk contact bind executor not configured' };
317
343
  }
344
+ if (this.dingtalkContactBindExecutor.isChannelReady
345
+ && !this.dingtalkContactBindExecutor.isChannelReady(cmd.channelName)) {
346
+ return { ok: false, error: 'channel instance is not connected' };
347
+ }
318
348
  return this.dingtalkContactBindExecutor.register({
319
349
  selfAid: cmd.selfAid,
320
350
  channelName: cmd.channelName,
321
351
  primaryId: cmd.primaryId,
322
352
  });
323
353
  }
354
+ case 'feishu.contact-bind.register': {
355
+ if (!this.feishuContactBindExecutor) {
356
+ return { ok: false, error: 'feishu contact bind executor not configured' };
357
+ }
358
+ if (this.feishuContactBindExecutor.isChannelReady
359
+ && !this.feishuContactBindExecutor.isChannelReady(cmd.channelName)) {
360
+ return { ok: false, error: 'channel instance is not connected' };
361
+ }
362
+ return this.feishuContactBindExecutor.register({
363
+ selfAid: cmd.selfAid,
364
+ channelName: cmd.channelName,
365
+ primaryId: cmd.primaryId,
366
+ });
367
+ }
368
+ case 'qqbot.contact-bind.register': {
369
+ if (!this.qqbotContactBindExecutor) {
370
+ return { ok: false, error: 'qqbot contact bind executor not configured' };
371
+ }
372
+ if (this.qqbotContactBindExecutor.isChannelReady
373
+ && !this.qqbotContactBindExecutor.isChannelReady(cmd.channelName)) {
374
+ return { ok: false, error: 'channel instance is not connected' };
375
+ }
376
+ return this.qqbotContactBindExecutor.register({
377
+ selfAid: cmd.selfAid,
378
+ channelName: cmd.channelName,
379
+ primaryId: cmd.primaryId,
380
+ });
381
+ }
382
+ case 'wecom.contact-bind.register': {
383
+ if (!this.wecomContactBindExecutor) {
384
+ return { ok: false, error: 'wecom contact bind executor not configured' };
385
+ }
386
+ if (this.wecomContactBindExecutor.isChannelReady
387
+ && !this.wecomContactBindExecutor.isChannelReady(cmd.channelName)) {
388
+ return { ok: false, error: 'channel instance is not connected' };
389
+ }
390
+ return this.wecomContactBindExecutor.register({
391
+ selfAid: cmd.selfAid,
392
+ channelName: cmd.channelName,
393
+ primaryId: cmd.primaryId,
394
+ });
395
+ }
396
+ case 'wechat.contact-bind.register': {
397
+ if (!this.wechatContactBindExecutor) {
398
+ return { ok: false, error: 'wechat contact bind executor not configured' };
399
+ }
400
+ if (this.wechatContactBindExecutor.isChannelReady
401
+ && !this.wechatContactBindExecutor.isChannelReady(cmd.channelName)) {
402
+ return { ok: false, error: 'channel instance is not connected' };
403
+ }
404
+ return this.wechatContactBindExecutor.register({
405
+ selfAid: cmd.selfAid,
406
+ channelName: cmd.channelName,
407
+ primaryId: cmd.primaryId,
408
+ });
409
+ }
324
410
  case 'aun-aids': {
325
411
  const aids = this.aunAidProvider ? this.aunAidProvider() : [];
326
412
  return { ok: true, aids };
@@ -437,6 +523,7 @@ export class IpcServer {
437
523
  originSessionId: typeof cmd.originSessionId === 'string' ? cmd.originSessionId : undefined,
438
524
  originMessageId: typeof cmd.originMessageId === 'string' ? cmd.originMessageId : undefined,
439
525
  delegationToken: typeof cmd.delegationToken === 'string' ? cmd.delegationToken : undefined,
526
+ delegationCommandHash: typeof cmd.delegationCommandHash === 'string' ? cmd.delegationCommandHash : undefined,
440
527
  log,
441
528
  });
442
529
  }
@@ -455,6 +542,7 @@ export class IpcServer {
455
542
  handoffId: typeof cmd.handoffId === 'string' ? cmd.handoffId : undefined,
456
543
  content: cmd.content,
457
544
  delegationToken: typeof cmd.delegationToken === 'string' ? cmd.delegationToken : undefined,
545
+ delegationCommandHash: typeof cmd.delegationCommandHash === 'string' ? cmd.delegationCommandHash : undefined,
458
546
  });
459
547
  }
460
548
  catch (e) {
@@ -513,7 +601,7 @@ export class IpcServer {
513
601
  const { cmd: slashCmd, sessionId } = cmd;
514
602
  if (!slashCmd || !sessionId)
515
603
  return { ok: false, error: 'missing cmd or sessionId' };
516
- return await this.commandExecutor(slashCmd, sessionId, typeof cmd.delegationToken === 'string' ? cmd.delegationToken : undefined);
604
+ return await this.commandExecutor(slashCmd, sessionId, typeof cmd.delegationToken === 'string' ? cmd.delegationToken : undefined, typeof cmd.delegationCommandHash === 'string' ? cmd.delegationCommandHash : undefined);
517
605
  }
518
606
  case 'config.op': {
519
607
  if (!this.configOperationExecutor)
@@ -525,7 +613,19 @@ export class IpcServer {
525
613
  if (delegationToken !== undefined && typeof delegationToken !== 'string') {
526
614
  return { ok: false, code: 'INVALID_DELEGATION', error: 'delegationToken must be a string' };
527
615
  }
528
- return await this.configOperationExecutor(argv, sessionId, delegationToken);
616
+ return await this.configOperationExecutor(argv, sessionId, delegationToken, typeof cmd.delegationCommandHash === 'string' ? cmd.delegationCommandHash : undefined);
617
+ }
618
+ case 'contact.op': {
619
+ if (!this.contactOperationExecutor)
620
+ return { ok: false, code: 'NOT_CONFIGURED', error: 'contact.op not configured' };
621
+ const { argv, sessionId, delegationToken } = cmd;
622
+ if (!Array.isArray(argv) || argv.some(value => typeof value !== 'string') || !sessionId) {
623
+ return { ok: false, code: 'INVALID_REQUEST', error: 'missing argv or sessionId' };
624
+ }
625
+ if (delegationToken !== undefined && typeof delegationToken !== 'string') {
626
+ return { ok: false, code: 'INVALID_DELEGATION', error: 'delegationToken must be a string' };
627
+ }
628
+ return await this.contactOperationExecutor(argv, sessionId, delegationToken, typeof cmd.delegationCommandHash === 'string' ? cmd.delegationCommandHash : undefined);
529
629
  }
530
630
  case 'trigger.list':
531
631
  case 'trigger.show':
@@ -581,6 +681,10 @@ export class IpcServer {
581
681
  return { ok: false, error: `Agent "${name}" not found` };
582
682
  if (!this.agentRegistry.reload)
583
683
  return { ok: false, error: 'EvolAgentRegistry.reload not available' };
684
+ // 'kits' 组(manifest / fragment / schema / 角色模板)走 on-reload 策略,平时不查盘:
685
+ // reload 是它唯一的刷新时机,必须先清再 reload,否则重载出来的 agent 仍用旧模板。
686
+ const { invalidateKitCache } = await import('./eck/kit-renderer.js');
687
+ invalidateKitCache();
584
688
  await this.agentRegistry.reload(name, hooks);
585
689
  return { ok: true, result: `Agent "${name}" reloaded` };
586
690
  }
@@ -633,8 +737,7 @@ export class IpcServer {
633
737
  case 'monitor-snapshot': {
634
738
  // watch web Monitor 页用:进程级 + 系统级运行指标 + 全局 stats + per-agent 汇总。
635
739
  const mem = process.memoryUsage();
636
- const totalMem = os.totalmem();
637
- const freeMem = os.freemem();
740
+ const systemMemory = readSystemMemoryUsage();
638
741
  const aids = this.aunAidProvider ? this.aunAidProvider() : [];
639
742
  const aidStats = this.aunAidStatsProvider ? this.aunAidStatsProvider() : [];
640
743
  const statsMap = new Map(aidStats.map((s) => [s.aid, s]));
@@ -686,9 +789,7 @@ export class IpcServer {
686
789
  processTree: processTreeDetails,
687
790
  // 系统级:整机
688
791
  system: {
689
- memTotal: totalMem,
690
- memUsed: totalMem - freeMem,
691
- memFree: freeMem,
792
+ ...systemMemory,
692
793
  cpuPercent: Math.round(this.sysCpuPercent * 10) / 10,
693
794
  loadAvg: os.loadavg(), // [1m, 5m, 15m](Windows 恒 0)
694
795
  },
@@ -716,6 +817,11 @@ export class IpcServer {
716
817
  * Returns null if the service is not running or the socket is unreachable.
717
818
  */
718
819
  export function ipcQuery(socketPath, cmd, timeoutMs = 3000) {
820
+ const delegationCommandHash = typeof cmd.delegationToken === 'string'
821
+ && typeof cmd.delegationCommandHash !== 'string'
822
+ ? hashCurrentDelegatedCommand()
823
+ : undefined;
824
+ const request = delegationCommandHash ? { ...cmd, delegationCommandHash } : cmd;
719
825
  return new Promise((resolve) => {
720
826
  const conn = net.connect(socketPath);
721
827
  let buf = '';
@@ -724,7 +830,7 @@ export function ipcQuery(socketPath, cmd, timeoutMs = 3000) {
724
830
  resolve(null);
725
831
  }, timeoutMs);
726
832
  conn.on('connect', () => {
727
- conn.write(JSON.stringify(cmd) + '\n');
833
+ conn.write(JSON.stringify(request) + '\n');
728
834
  });
729
835
  conn.on('data', (data) => {
730
836
  buf += data.toString();
package/dist/paths.js CHANGED
@@ -86,6 +86,9 @@ export function agentConfig(aid) {
86
86
  export function agentContactConfig(aid) {
87
87
  return path.join(agentDir(aid), 'contact.json');
88
88
  }
89
+ export function agentContactOperations(aid) {
90
+ return path.join(agentDir(aid), 'contact-operations.jsonl');
91
+ }
89
92
  export function agentPersonalDir(aid) {
90
93
  return path.join(agentDir(aid), 'personal');
91
94
  }
@@ -0,0 +1,29 @@
1
+ import { ResponseModeResolver } from './resolver.js';
2
+ /** Extract mode-specific factory defaults from the registered mode schema. */
3
+ export function responseModeSchemaDefaults(mode) {
4
+ const properties = mode.configSchema?.properties;
5
+ if (!properties)
6
+ return {};
7
+ const defaults = {};
8
+ for (const [key, spec] of Object.entries(properties)) {
9
+ if (spec && typeof spec === 'object' && 'default' in spec) {
10
+ defaults[key] = spec.default;
11
+ }
12
+ }
13
+ return defaults;
14
+ }
15
+ /**
16
+ * Resolve the selected mode and assemble its effective parameter bucket.
17
+ * Response processing and pre-processing consumers such as Session Renew must
18
+ * share this function so they cannot select different mode configurations.
19
+ */
20
+ export function resolveEffectiveResponseModeConfig(registry, config, resolvedChatMode) {
21
+ const resolved = new ResponseModeResolver(registry).resolve(config.responseMode);
22
+ const modeSpecificParams = config.responseModeParams?.[resolved.mode.id] ?? {};
23
+ const modeConfig = {
24
+ ...responseModeSchemaDefaults(resolved.mode),
25
+ ...(resolvedChatMode !== undefined ? { chatmode: resolvedChatMode } : {}),
26
+ ...modeSpecificParams,
27
+ };
28
+ return { ...resolved, modeConfig };
29
+ }
@@ -13,33 +13,13 @@
13
13
  * - 响应模式成为「响应决策的源头」,下游 message-processor 的执行流程原样保留
14
14
  * - 异常不降级(D6):解析/决策失败时回落到安全默认,记 WARN
15
15
  */
16
- import { ResponseModeResolver } from './resolver.js';
17
16
  import { ResponseModeContextBuilder } from './context-builder.js';
18
- /**
19
- * 从模式的 configSchema 提取特有参数出厂默认值:`properties[key].default`。
20
- *
21
- * 模式 schema 是模式特有参数「候选值 + 默认值」的唯一事实源(architecture §五)。
22
- * 宿主组装 modeConfig 时先铺这层默认,再叠用户显式配置——默认来源收敛到 schema,
23
- * flow 不再硬编码 `?? true` 之类的默认。chatMode 无 default(宿主强制注入),跳过。
24
- */
25
- function schemaDefaults(mode) {
26
- const props = mode.configSchema?.properties;
27
- if (!props)
28
- return {};
29
- const out = {};
30
- for (const [key, spec] of Object.entries(props)) {
31
- if (spec && typeof spec === 'object' && 'default' in spec)
32
- out[key] = spec.default;
33
- }
34
- return out;
35
- }
17
+ import { resolveEffectiveResponseModeConfig } from './config-resolver.js';
36
18
  export class ResponseModeCoordinator {
37
19
  registry;
38
- resolver;
39
20
  contextBuilder = new ResponseModeContextBuilder();
40
21
  constructor(registry) {
41
22
  this.registry = registry;
42
- this.resolver = new ResponseModeResolver(registry);
43
23
  }
44
24
  /**
45
25
  * 解析会话该用哪个响应模式 + 构建 context(不调 handleInbound)。
@@ -54,12 +34,11 @@ export class ResponseModeCoordinator {
54
34
  */
55
35
  resolveMode(responseModeId, resolvedChatMode, responseModeParams, contextDeps) {
56
36
  try {
57
- const resolved = this.resolver.resolve(responseModeId);
58
- const mode = resolved.mode;
59
- // 模式特有参数:先铺 schema 出厂默认,再叠用户显式桶(responseModeParams[modeId],显式值优先);
60
- // chatmode 由宿主解析后强制注入(小写,与配置层 chatmode 字典一致)。
61
- const modeSpecificParams = responseModeParams?.[mode.id] ?? {};
62
- const modeConfig = { ...schemaDefaults(mode), chatmode: resolvedChatMode, ...modeSpecificParams };
37
+ const resolved = resolveEffectiveResponseModeConfig(this.registry, {
38
+ responseMode: responseModeId,
39
+ responseModeParams,
40
+ }, resolvedChatMode);
41
+ const { mode, modeConfig } = resolved;
63
42
  contextDeps.logger.debug('[ResponseSystem] resolveMode mode=' + mode.id + ' source=' + resolved.source + ' chatmode=' + (modeConfig.chatmode ?? 'none'));
64
43
  const context = this.contextBuilder.build(mode.id, { ...contextDeps, modeConfig });
65
44
  return { mode, context, source: resolved.source };
@@ -78,11 +57,8 @@ export class ResponseModeCoordinator {
78
57
  async resolveInbound(message, deps, resolvedChatMode) {
79
58
  try {
80
59
  // 解析模式:标量 responseMode(合并后)> 注册表首选。chatMode 不参与选模式。
81
- const resolved = this.resolver.resolve(deps.agentConfig.responseMode);
82
- const mode = resolved.mode;
83
- // 先铺 schema 出厂默认,再叠用户显式桶(显式值优先),chatmode 强制注入。
84
- const modeSpecificParams = deps.agentConfig.responseModeParams?.[mode.id] ?? {};
85
- const modeConfig = { ...schemaDefaults(mode), chatmode: resolvedChatMode, ...modeSpecificParams };
60
+ const resolved = resolveEffectiveResponseModeConfig(this.registry, deps.agentConfig, resolvedChatMode);
61
+ const { mode, modeConfig } = resolved;
86
62
  deps.contextDeps.logger.debug('[ResponseSystem] resolveInbound mode=' + mode.id + ' source=' + resolved.source + ' chatmode=' + (modeConfig.chatmode ?? 'none'));
87
63
  const context = this.contextBuilder.build(mode.id, {
88
64
  ...deps.contextDeps,
@@ -19,7 +19,7 @@ function isHumanFacingMessage(message) {
19
19
  }
20
20
  function buildState(message, cfg) {
21
21
  // 默认值不在此硬编码:候选/出厂默认由模式 schema 声明,宿主组装 modeConfig 时注入
22
- // (coordinator.schemaDefaults)。此处只读注入后的布尔——键缺失即视为关闭。
22
+ // (responseModeSchemaDefaults)。此处只读注入后的布尔——键缺失即视为关闭。
23
23
  const preTool1stMsgChk = cfg.pre_tool_1stmsgchk === true;
24
24
  const toolUseReminder = cfg.tool_use_reminder === true;
25
25
  const humanFacing = isHumanFacingMessage(message);
@@ -4,3 +4,4 @@
4
4
  * 统一导出响应系统的所有公共接口
5
5
  */
6
6
  export { hasAuxiliarySession, hasThreadTracking, hasWorkflow, hasBatchProcessing, hasStatePersistence, } from './extensions.js';
7
+ export { resolveEffectiveResponseModeConfig, responseModeSchemaDefaults, } from './config-resolver.js';
@@ -2,12 +2,15 @@ import { FIFOQueue } from '../../queues/fifo-queue.js';
2
2
  import { flowForChatMode } from '../../engines/v1/index.js';
3
3
  import { loadSchema } from '../../../config/schema-registry.js';
4
4
  /**
5
- * 模式桶 schema —— 候选值与默认值的**唯一事实源**,从 kits/schemas/single-session.schema.1.json
5
+ * 模式桶 schema —— 候选值与默认值的**唯一事实源**,从当前 single-session schema
6
6
  * 读取(随包分发、config schema 子命令可展示、write 时桶专项校验共用同一份)。
7
- * `default` 即运行时出厂默认,由宿主组装 modeConfig 时提取注入(coordinator.schemaDefaults),
7
+ * `default` 即运行时出厂默认,由共享 config resolver 组装 modeConfig 时提取注入,
8
8
  * flow 不再硬编码默认。chatMode 无 default——由宿主按 chatmode 场景表解析后强制注入。
9
+ *
10
+ * 每次现取而非模块初始化时定格:`loadSchema` 自己走 FileCache(读是缓存命中),
11
+ * 定格反而会绕过 invalidateKitCache——schema 改了、registry 已换新,本模式却仍
12
+ * 用旧默认值。
9
13
  */
10
- const CONFIG_SCHEMA = loadSchema('single-session').raw;
11
14
  /**
12
15
  * 单会话响应模式(architecture.md §4.1)—— 合并原 interactive / proactive。
13
16
  *
@@ -21,7 +24,7 @@ export class SingleSessionMode {
21
24
  description = '单会话直接响应,按 chatMode 决定投递方式。';
22
25
  type = 'builtin';
23
26
  applicableScenes = ['private', 'group'];
24
- configSchema = CONFIG_SCHEMA;
27
+ get configSchema() { return loadSchema('single-session').raw; }
25
28
  queue = new FIFOQueue();
26
29
  context;
27
30
  async initialize(context) {
@@ -11,14 +11,20 @@ let _priceCacheTs = 0;
11
11
  const PRICE_CACHE_TTL = 5 * 60 * 1000;
12
12
  /**
13
13
  * 从包路径 + 用户路径合并读取 JSONL 文件。
14
- * 包路径($PACKAGE_ROOT/data/stats/)为基线,用户路径($EVOLCORE_HOME/data/stats/)为追加/覆盖。
14
+ * 包基线随构建产物发布在 dist/utils,源码运行时回退到 src/utils;
15
+ * 用户路径($EVOLCORE_HOME/data/stats/)为追加/覆盖。
15
16
  * 两层合并(append),用户层行追加在包层之后——查价时 effective_from 越大越优先,天然正确。
16
17
  */
17
18
  function _loadJsonlMerged(evolcoreHome, filename) {
18
19
  const results = [];
19
20
  // 1. 包路径(基线)
20
- const pkgFile = path.join(getPackageRoot(), 'data', 'stats', filename);
21
- if (fs.existsSync(pkgFile)) {
21
+ const packageRoot = getPackageRoot();
22
+ const pkgFile = [
23
+ path.join(packageRoot, 'dist', 'utils', filename),
24
+ path.join(packageRoot, 'src', 'utils', filename),
25
+ path.join(packageRoot, 'data', 'stats', filename),
26
+ ].find(candidate => fs.existsSync(candidate));
27
+ if (pkgFile) {
22
28
  try {
23
29
  const lines = fs.readFileSync(pkgFile, 'utf-8').split('\n').filter(Boolean);
24
30
  for (const l of lines)
@@ -28,7 +34,7 @@ function _loadJsonlMerged(evolcoreHome, filename) {
28
34
  }
29
35
  // 2. 用户路径(追加/覆盖)
30
36
  const userFile = path.join(evolcoreHome, 'data', 'stats', filename);
31
- if (fs.existsSync(userFile)) {
37
+ if (fs.existsSync(userFile) && (!pkgFile || path.resolve(userFile) !== path.resolve(pkgFile))) {
32
38
  try {
33
39
  const lines = fs.readFileSync(userFile, 'utf-8').split('\n').filter(Boolean);
34
40
  for (const l of lines)
@@ -81,10 +87,16 @@ export function resolvePriceRow(evolcoreHome, model, ts) {
81
87
  export const BILLING_FNS = {
82
88
  // 通用 per-token(Claude / OpenAI 兼容 / Kimi / MiniMax)
83
89
  per_token_v1: (e, p) => {
84
- const r = (p.price_input ?? 0) * e.input_tokens / 1e6
85
- + (p.price_output ?? 0) * e.output_tokens / 1e6
86
- + (p.price_cache_creation ?? 0) * e.cache_creation_tokens / 1e6
87
- + (p.price_cache_read ?? 0) * e.cache_read_tokens / 1e6;
90
+ const tiers = Array.isArray(p.tiers)
91
+ ? p.tiers
92
+ : [];
93
+ const promptTokens = e.input_tokens + e.cache_creation_tokens + e.cache_read_tokens;
94
+ const tier = tiers.find(t => t.up_to_input_tokens == null || promptTokens <= t.up_to_input_tokens);
95
+ const price = tier ?? p;
96
+ const r = (price.price_input ?? 0) * e.input_tokens / 1e6
97
+ + (price.price_output ?? 0) * e.output_tokens / 1e6
98
+ + (price.price_cache_creation ?? 0) * e.cache_creation_tokens / 1e6
99
+ + (price.price_cache_read ?? 0) * e.cache_read_tokens / 1e6;
88
100
  return p.currency === 'CNY' ? { cny: r } : { usd: r };
89
101
  },
90
102
  // DeepSeek cache_hit / cache_miss 口径
@@ -72,6 +72,9 @@ export class TriggerDefinitionManager {
72
72
  ...(origin ? { origin } : {}),
73
73
  }, { now: Date.now() });
74
74
  this.assertAgent(updated);
75
+ if (existing.execution.baseagent !== updated.execution.baseagent) {
76
+ throw new Error('execution.baseagent is immutable; create a new Trigger to use another baseagent');
77
+ }
75
78
  updated.createdAt = existing.createdAt;
76
79
  updated.updatedAt = Date.now();
77
80
  this.assertUnique(updated, triggerId);