evolcore 0.0.2 → 0.0.3

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 (124) hide show
  1. package/CHANGELOG.md +44 -793
  2. package/dist/agents/claude-runner.js +197 -17
  3. package/dist/agents/codex-runner.js +46 -3
  4. package/dist/aun/outbox.js +8 -0
  5. package/dist/channels/aun.js +21 -4
  6. package/dist/channels/contact-bind-code.js +134 -0
  7. package/dist/channels/dingtalk.js +979 -149
  8. package/dist/channels/feishu.js +130 -54
  9. package/dist/channels/wecom-card.js +101 -0
  10. package/dist/channels/wecom-onboarding.js +82 -0
  11. package/dist/channels/wecom-state.js +191 -0
  12. package/dist/channels/wecom.js +755 -163
  13. package/dist/cli/agent-command.js +2 -1
  14. package/dist/cli/aun-commands.js +88 -33
  15. package/dist/cli/bench.js +2 -2
  16. package/dist/cli/contact.js +71 -0
  17. package/dist/cli/ctl-command.js +2 -2
  18. package/dist/cli/daemon-commands.js +77 -214
  19. package/dist/cli/handoff-command.js +2 -2
  20. package/dist/cli/help.js +9 -5
  21. package/dist/cli/index.js +132 -116
  22. package/dist/cli/init-channel.js +92 -97
  23. package/dist/cli/init.js +63 -26
  24. package/dist/cli/model.js +2 -1
  25. package/dist/cli/net-check.js +2 -2
  26. package/dist/cli/queue-command.js +30 -6
  27. package/dist/cli/raw-key-input.js +25 -0
  28. package/dist/cli/response.js +5 -6
  29. package/dist/cli/restart-monitor.js +25 -1
  30. package/dist/cli/stats.js +6 -4
  31. package/dist/cli/trigger-command.js +55 -15
  32. package/dist/cli/version.js +6 -1
  33. package/dist/config/builtin-role-templates.js +22 -10
  34. package/dist/config/builtin-roles.js +7 -1
  35. package/dist/config/config-manager.js +221 -17
  36. package/dist/config/contact-alias.js +68 -0
  37. package/dist/config/contact-book-store.js +454 -0
  38. package/dist/config/contact-book-v2-startup.js +35 -0
  39. package/dist/config/contact-book.js +156 -303
  40. package/dist/config/contact-operation-service.js +110 -0
  41. package/dist/config/peer-role-resolver.js +133 -54
  42. package/dist/config/role-ranks.js +18 -0
  43. package/dist/config/role-service.js +16 -19
  44. package/dist/config/role-store.js +16 -5
  45. package/dist/config/roles.js +10 -1
  46. package/dist/config-store.js +0 -2
  47. package/dist/core/auth/authorization-audit.js +10 -1
  48. package/dist/core/auth/operation-authorizer.js +2 -0
  49. package/dist/core/auth/operation-catalog.js +56 -0
  50. package/dist/core/command/command-handler.js +105 -10
  51. package/dist/core/command/connect-menu.js +374 -0
  52. package/dist/core/command/menu-handler.js +114 -16
  53. package/dist/core/command/role-menu.js +128 -29
  54. package/dist/core/command/slash-handler.js +28 -18
  55. package/dist/core/daemon-file-cache.js +12 -6
  56. package/dist/core/event-catalog.js +70 -0
  57. package/dist/core/evolagent-registry.js +0 -1
  58. package/dist/core/evolagent.js +20 -9
  59. package/dist/core/message/im-renderer.js +2 -0
  60. package/dist/core/message/message-bridge.js +79 -8
  61. package/dist/core/message/message-queue.js +10 -0
  62. package/dist/core/message/message-utils.js +8 -2
  63. package/dist/core/message/response-engine.js +269 -25
  64. package/dist/core/message/send-receipt.js +24 -0
  65. package/dist/core/message/stream-debouncer.js +11 -2
  66. package/dist/core/permission/tool-policy.js +47 -15
  67. package/dist/core/protected-paths.js +2 -0
  68. package/dist/core/session/session-fs-store.js +44 -3
  69. package/dist/core/session/session-manager.js +61 -5
  70. package/dist/index.js +62 -6
  71. package/dist/ipc.js +34 -5
  72. package/dist/stats/billing.js +20 -8
  73. package/dist/trigger/manager.js +3 -0
  74. package/dist/trigger/parser.js +77 -2
  75. package/dist/trigger/patch.js +8 -1
  76. package/dist/trigger/scheduler.js +3 -1
  77. package/dist/trigger/validation.js +13 -0
  78. package/dist/utils/aid-bind.js +43 -29
  79. package/dist/utils/instance-registry.js +14 -7
  80. package/dist/utils/log-writer.js +46 -0
  81. package/dist/utils/media-cache.js +4 -1
  82. package/dist/utils/model-prices.jsonl +6 -3
  83. package/dist/utils/restart-safety.js +31 -0
  84. package/dist/utils/system-memory.js +62 -0
  85. package/kits/docs/INDEX.md +2 -1
  86. package/kits/docs/evolcore/INDEX.md +5 -3
  87. package/kits/docs/evolcore/agent.md +9 -1
  88. package/kits/docs/evolcore/aid.md +5 -2
  89. package/kits/docs/evolcore/contact.md +57 -0
  90. package/kits/docs/evolcore/fs.md +9 -0
  91. package/kits/docs/evolcore/group.md +12 -3
  92. package/kits/docs/evolcore/model.md +4 -1
  93. package/kits/docs/evolcore/msg.md +9 -3
  94. package/kits/docs/evolcore/response.md +16 -21
  95. package/kits/docs/evolcore/rpc.md +2 -0
  96. package/kits/docs/evolcore/stats.md +15 -2
  97. package/kits/docs/evolcore/storage.md +1 -0
  98. package/kits/docs/evolcore/trigger.md +17 -2
  99. package/kits/eck_manifest.json +12 -0
  100. package/kits/migrations/migrate-contact-book-v2.mjs +747 -0
  101. package/kits/schemas/_meta.json +7 -4
  102. package/kits/schemas/agent-config.schema.6.json +322 -0
  103. package/kits/schemas/contact-book.schema.2.json +43 -0
  104. package/kits/schemas/relation-config.schema.5.json +47 -0
  105. package/kits/schemas/role-config.schema.1.json +1 -0
  106. package/kits/schemas/role-registry.schema.1.json +2 -2
  107. package/kits/templates/roles/admin.json +1 -0
  108. package/kits/templates/roles/member.json +1 -0
  109. package/kits/templates/roles/owner.json +1 -0
  110. package/kits/templates/roles/visitor.json +1 -0
  111. package/kits/templates/system-fragments/commands.md +3 -1
  112. package/package.json +4 -4
  113. package/assets/brand/evolcore/README.md +0 -19
  114. package/assets/brand/evolcore/evolcore-app-icon.png +0 -0
  115. package/assets/brand/evolcore/evolcore-app-icon.svg +0 -13
  116. package/assets/brand/evolcore/evolcore-brand-board.png +0 -0
  117. package/assets/brand/evolcore/evolcore-brand-board.svg +0 -126
  118. package/assets/brand/evolcore/evolcore-logo-kit.zip +0 -0
  119. package/assets/brand/evolcore/evolcore-logo-reverse.png +0 -0
  120. package/assets/brand/evolcore/evolcore-logo-reverse.svg +0 -14
  121. package/assets/brand/evolcore/evolcore-logo.png +0 -0
  122. package/assets/brand/evolcore/evolcore-logo.svg +0 -14
  123. package/assets/brand/evolcore/evolcore-mark.png +0 -0
  124. package/assets/brand/evolcore/evolcore-mark.svg +0 -10
@@ -0,0 +1,191 @@
1
+ import crypto from 'node:crypto';
2
+ import fs from 'node:fs';
3
+ import path from 'node:path';
4
+ import { agentDataDir } from '../paths.js';
5
+ import { atomicReadJson, atomicWriteJson } from '../utils/atomic-write.js';
6
+ import { logger } from '../utils/logger.js';
7
+ const STORE_VERSION = 1;
8
+ const DEFAULT_DEDUP_TTL_MS = 24 * 60 * 60 * 1000;
9
+ const DEFAULT_CARD_RETENTION_MS = 24 * 60 * 60 * 1000;
10
+ function writePrivateJson(filePath, value) {
11
+ atomicWriteJson(filePath, value);
12
+ try {
13
+ fs.chmodSync(filePath, 0o600);
14
+ }
15
+ catch { /* best effort on non-POSIX filesystems */ }
16
+ }
17
+ export class PersistentWecomDeduper {
18
+ filePath;
19
+ channelKey;
20
+ entries = new Map();
21
+ ttlMs;
22
+ maxEntries;
23
+ constructor(filePath, channelKey, opts) {
24
+ this.filePath = filePath;
25
+ this.channelKey = channelKey;
26
+ this.ttlMs = opts?.ttlMs ?? DEFAULT_DEDUP_TTL_MS;
27
+ this.maxEntries = opts?.maxEntries ?? 20_000;
28
+ this.load();
29
+ }
30
+ checkAndMark(messageId, now = Date.now()) {
31
+ this.evict(now);
32
+ const seenAt = this.entries.get(messageId);
33
+ if (seenAt !== undefined && now - seenAt <= this.ttlMs)
34
+ return true;
35
+ this.entries.set(messageId, now);
36
+ this.trimToLimit();
37
+ this.flush();
38
+ return false;
39
+ }
40
+ get size() {
41
+ return this.entries.size;
42
+ }
43
+ load() {
44
+ if (!this.filePath)
45
+ return;
46
+ try {
47
+ const stored = atomicReadJson(this.filePath);
48
+ if (!stored || stored.version !== STORE_VERSION || stored.channelKey !== this.channelKey)
49
+ return;
50
+ for (const [id, timestamp] of Object.entries(stored.entries ?? {})) {
51
+ if (id && Number.isFinite(timestamp))
52
+ this.entries.set(id, timestamp);
53
+ }
54
+ const before = this.entries.size;
55
+ this.evict(Date.now());
56
+ this.trimToLimit();
57
+ if (this.entries.size !== before)
58
+ this.flush();
59
+ }
60
+ catch (error) {
61
+ logger.warn(`[WeCom] Ignoring unreadable dedup store for ${this.channelKey}: ${String(error)}`);
62
+ this.entries.clear();
63
+ }
64
+ }
65
+ evict(now) {
66
+ for (const [id, timestamp] of this.entries) {
67
+ if (now - timestamp > this.ttlMs)
68
+ this.entries.delete(id);
69
+ }
70
+ }
71
+ trimToLimit() {
72
+ if (this.entries.size <= this.maxEntries)
73
+ return;
74
+ const oldest = [...this.entries.entries()].sort((a, b) => a[1] - b[1]);
75
+ for (let i = 0; i < oldest.length - this.maxEntries; i++) {
76
+ this.entries.delete(oldest[i][0]);
77
+ }
78
+ }
79
+ flush() {
80
+ writePrivateJson(this.filePath, {
81
+ version: STORE_VERSION,
82
+ channelKey: this.channelKey,
83
+ entries: Object.fromEntries(this.entries),
84
+ });
85
+ }
86
+ }
87
+ export class PersistentWecomCardStore {
88
+ filePath;
89
+ channelKey;
90
+ records = new Map();
91
+ constructor(filePath, channelKey) {
92
+ this.filePath = filePath;
93
+ this.channelKey = channelKey;
94
+ if (filePath)
95
+ this.load();
96
+ }
97
+ set(record) {
98
+ this.records.set(record.taskId, record);
99
+ this.cleanup();
100
+ this.flush();
101
+ }
102
+ get(taskId) {
103
+ this.cleanup();
104
+ return this.records.get(taskId);
105
+ }
106
+ findByInteractionId(interactionId) {
107
+ this.cleanup();
108
+ return [...this.records.values()].find(record => record.interaction.id === interactionId);
109
+ }
110
+ listPendingByChat(chatId) {
111
+ this.cleanup();
112
+ return [...this.records.values()].filter(record => (record.chatId === chatId
113
+ && record.status === 'pending'
114
+ && (!record.expiresAt || record.expiresAt >= Date.now())));
115
+ }
116
+ resolve(taskId, action) {
117
+ const record = this.records.get(taskId);
118
+ if (!record)
119
+ return undefined;
120
+ record.status = 'resolved';
121
+ record.resolution = action;
122
+ record.updatedAt = Date.now();
123
+ this.flush();
124
+ return record;
125
+ }
126
+ invalidateByInteractionId(interactionId, reason) {
127
+ const record = this.findByInteractionId(interactionId);
128
+ if (!record || record.status === 'resolved')
129
+ return record;
130
+ record.status = 'invalidated';
131
+ record.invalidationReason = reason;
132
+ record.updatedAt = Date.now();
133
+ this.flush();
134
+ return record;
135
+ }
136
+ load() {
137
+ if (!this.filePath)
138
+ return;
139
+ try {
140
+ const stored = atomicReadJson(this.filePath);
141
+ if (!stored || stored.version !== STORE_VERSION || stored.channelKey !== this.channelKey)
142
+ return;
143
+ for (const record of stored.records ?? []) {
144
+ if (record?.taskId && record?.interaction?.id)
145
+ this.records.set(record.taskId, record);
146
+ }
147
+ this.cleanup(true);
148
+ }
149
+ catch (error) {
150
+ logger.warn(`[WeCom] Ignoring unreadable card store for ${this.channelKey}: ${String(error)}`);
151
+ this.records.clear();
152
+ }
153
+ }
154
+ cleanup(flushWhenChanged = false) {
155
+ const now = Date.now();
156
+ let changed = false;
157
+ for (const [taskId, record] of this.records) {
158
+ const terminalExpiry = record.updatedAt + DEFAULT_CARD_RETENTION_MS;
159
+ const pendingExpiry = (record.expiresAt ?? record.createdAt + 7 * DEFAULT_CARD_RETENTION_MS)
160
+ + DEFAULT_CARD_RETENTION_MS;
161
+ const expiresAt = record.status === 'pending' ? pendingExpiry : terminalExpiry;
162
+ if (now > expiresAt) {
163
+ this.records.delete(taskId);
164
+ changed = true;
165
+ }
166
+ }
167
+ if (changed && flushWhenChanged)
168
+ this.flush();
169
+ }
170
+ flush() {
171
+ if (!this.filePath)
172
+ return;
173
+ writePrivateJson(this.filePath, {
174
+ version: STORE_VERSION,
175
+ channelKey: this.channelKey,
176
+ records: [...this.records.values()],
177
+ });
178
+ }
179
+ }
180
+ export function wecomChannelDataPaths(agentAid, channelKey) {
181
+ const safeKey = encodeURIComponent(channelKey);
182
+ const dir = path.join(agentDataDir(agentAid), 'channels', safeKey);
183
+ return {
184
+ dedupFile: path.join(dir, 'wecom-message-dedup.json'),
185
+ cardFile: path.join(dir, 'wecom-cards.json'),
186
+ };
187
+ }
188
+ export function createWecomCardTaskId(channelKey, interactionId) {
189
+ const hash = crypto.createHash('sha256').update(`${channelKey}\0${interactionId}`).digest('hex').slice(0, 32);
190
+ return `ec_${hash}`;
191
+ }