@evomap/evolver 1.89.17 → 1.89.18

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 (82) hide show
  1. package/README.ja-JP.md +1 -1
  2. package/README.ko-KR.md +1 -1
  3. package/README.md +1 -1
  4. package/README.zh-CN.md +1 -1
  5. package/index.js +89 -17
  6. package/package.json +1 -1
  7. package/src/adapters/claudeCode.js +36 -7
  8. package/src/adapters/hookAdapter.js +24 -0
  9. package/src/atp/atpExecute.js +3 -1
  10. package/src/atp/hubClient.js +5 -3
  11. package/src/atp/serviceHelper.js +3 -2
  12. package/src/evolve/guards.js +1 -1
  13. package/src/evolve/pipeline/collect.js +1 -1
  14. package/src/evolve/pipeline/dispatch.js +1 -1
  15. package/src/evolve/pipeline/enrich.js +1 -1
  16. package/src/evolve/pipeline/hub.js +1 -1
  17. package/src/evolve/pipeline/select.js +1 -1
  18. package/src/evolve/pipeline/signals.js +1 -1
  19. package/src/evolve/utils.js +1 -1
  20. package/src/evolve.js +1 -1
  21. package/src/gep/a2aProtocol.js +1 -1
  22. package/src/gep/antiAbuseTelemetry.js +1 -1
  23. package/src/gep/autoDistillConv.js +1 -1
  24. package/src/gep/autoDistillLlm.js +1 -1
  25. package/src/gep/candidateEval.js +1 -1
  26. package/src/gep/candidates.js +1 -1
  27. package/src/gep/cliContracts.js +37 -1
  28. package/src/gep/contentHash.js +1 -1
  29. package/src/gep/conversationDistiller.js +1 -1
  30. package/src/gep/conversationSniffer.js +1 -1
  31. package/src/gep/crypto.js +1 -1
  32. package/src/gep/curriculum.js +1 -1
  33. package/src/gep/deviceId.js +1 -1
  34. package/src/gep/directoryClient.js +7 -3
  35. package/src/gep/envFingerprint.js +1 -1
  36. package/src/gep/epigenetics.js +1 -1
  37. package/src/gep/execBridge.js +1 -1
  38. package/src/gep/explore.js +1 -1
  39. package/src/gep/hash.js +1 -1
  40. package/src/gep/hubFetch.js +1 -1
  41. package/src/gep/hubReview.js +1 -1
  42. package/src/gep/hubSearch.js +1 -1
  43. package/src/gep/hubVerify.js +1 -1
  44. package/src/gep/learningSignals.js +1 -1
  45. package/src/gep/memoryGraph.js +1 -1
  46. package/src/gep/memoryGraphAdapter.js +1 -1
  47. package/src/gep/mutation.js +1 -1
  48. package/src/gep/narrativeMemory.js +1 -1
  49. package/src/gep/oauthLogin.js +3 -5
  50. package/src/gep/openPRRegistry.js +1 -1
  51. package/src/gep/personality.js +1 -1
  52. package/src/gep/policyCheck.js +1 -1
  53. package/src/gep/privacyClient.js +28 -10
  54. package/src/gep/prompt.js +1 -1
  55. package/src/gep/recallInject.js +1 -1
  56. package/src/gep/recallVerifier.js +1 -1
  57. package/src/gep/reflection.js +1 -1
  58. package/src/gep/savingsCore.js +1 -1
  59. package/src/gep/selector.js +1 -1
  60. package/src/gep/skillDistiller.js +1 -1
  61. package/src/gep/skillPublisher.js +8 -3
  62. package/src/gep/solidify.js +1 -1
  63. package/src/gep/strategy.js +1 -1
  64. package/src/gep/taskReceiver.js +3 -2
  65. package/src/gep/tokenSavings.js +1 -1
  66. package/src/gep/validator/index.js +7 -2
  67. package/src/gep/validator/reporter.js +7 -2
  68. package/src/gep/validator/stakeBootstrap.js +7 -2
  69. package/src/gep/workspaceKeychain.js +1 -1
  70. package/src/proxy/clientSettings.js +405 -0
  71. package/src/proxy/extensions/traceControl.js +1 -1
  72. package/src/proxy/index.js +10 -5
  73. package/src/proxy/inject.js +1 -1
  74. package/src/proxy/lifecycle/manager.js +82 -16
  75. package/src/proxy/mailbox/state.js +207 -0
  76. package/src/proxy/mailbox/store.js +164 -64
  77. package/src/proxy/router/messages_route.js +4 -3
  78. package/src/proxy/server/http.js +40 -6
  79. package/src/proxy/sync/inbound.js +31 -12
  80. package/src/proxy/sync/outbound.js +157 -22
  81. package/src/proxy/trace/extractor.js +1 -1
  82. package/src/proxy/trace/usage.js +1 -1
@@ -12,9 +12,107 @@ const {
12
12
  sanitizeHubResponseForLog,
13
13
  throwIfHubUnreachableResponse,
14
14
  } = require('../../gep/hubFetch');
15
+ const { redactString } = require('../../gep/sanitize');
15
16
 
16
17
  const MAX_BATCH = 50;
17
18
  const MAX_RETRIES = 10;
19
+ const DEFAULT_MAX_OUTBOUND_BODY_BYTES = 4 * 1024 * 1024;
20
+ const MIN_ADAPTIVE_OUTBOUND_BODY_BYTES = 16 * 1024;
21
+ const OUTBOUND_BODY_BYTES_STATE_KEY = 'outbound_sync_max_body_bytes';
22
+
23
+ function sanitizeHubErrorMessage(value) {
24
+ if (typeof sanitizeHubResponseForLog === 'function') {
25
+ return sanitizeHubResponseForLog(value);
26
+ }
27
+
28
+ let text;
29
+ if (typeof value === 'string') {
30
+ text = value;
31
+ } else if (value && typeof value.message === 'string') {
32
+ text = value.message;
33
+ } else {
34
+ try { text = JSON.stringify(value); } catch { text = String(value || ''); }
35
+ }
36
+ return redactString(String(text || ''));
37
+ }
38
+
39
+ function resolveHardOutboundBodyBytes(env = process.env) {
40
+ const raw = Number(env.EVOMAP_OUTBOUND_SYNC_MAX_BODY_BYTES || env.EVOMAP_MAILBOX_OUTBOUND_MAX_BODY_BYTES);
41
+ const max = Number.isFinite(raw) && raw > 0
42
+ ? Math.floor(raw)
43
+ : DEFAULT_MAX_OUTBOUND_BODY_BYTES;
44
+ return Math.max(1, max);
45
+ }
46
+
47
+ function resolveMaxOutboundBodyBytes(env = process.env, store = null) {
48
+ let max = resolveHardOutboundBodyBytes(env);
49
+ try {
50
+ const adaptive = Number(store && typeof store.getState === 'function'
51
+ ? store.getState(OUTBOUND_BODY_BYTES_STATE_KEY)
52
+ : null);
53
+ if (Number.isFinite(adaptive) && adaptive > 0) max = Math.min(max, Math.floor(adaptive));
54
+ } catch { /* adaptive state is best-effort */ }
55
+ return Math.max(1, max);
56
+ }
57
+
58
+ function hubMessage(m) {
59
+ return {
60
+ id: m.id,
61
+ type: m.type,
62
+ payload: m.payload,
63
+ priority: m.priority,
64
+ ref_id: m.ref_id,
65
+ created_at: m.created_at,
66
+ };
67
+ }
68
+
69
+ function serializeOutboundBody(senderId, messages) {
70
+ return JSON.stringify({
71
+ sender_id: senderId,
72
+ proxy_protocol_version: PROXY_PROTOCOL_VERSION,
73
+ messages: messages.map(hubMessage),
74
+ });
75
+ }
76
+
77
+ function outboundBodyBytes(senderId, messages) {
78
+ return Buffer.byteLength(serializeOutboundBody(senderId, messages), 'utf8');
79
+ }
80
+
81
+ function buildSizedOutboundBatch(senderId, messages, maxBodyBytes, hardMaxBodyBytes = maxBodyBytes) {
82
+ const selected = [];
83
+ const rejected = [];
84
+ let body = serializeOutboundBody(senderId, selected);
85
+ let bodyBytes = Buffer.byteLength(body, 'utf8');
86
+
87
+ for (const m of messages) {
88
+ const singleBytes = outboundBodyBytes(senderId, [m]);
89
+ if (singleBytes > hardMaxBodyBytes) {
90
+ rejected.push({
91
+ id: m.id,
92
+ status: 'rejected',
93
+ error: `outbound message exceeds max body bytes (${singleBytes} > ${hardMaxBodyBytes})`,
94
+ });
95
+ continue;
96
+ }
97
+ if (selected.length === 0 && singleBytes > maxBodyBytes) {
98
+ selected.push(m);
99
+ body = serializeOutboundBody(senderId, selected);
100
+ bodyBytes = Buffer.byteLength(body, 'utf8');
101
+ break;
102
+ }
103
+
104
+ const candidate = selected.concat(m);
105
+ const candidateBody = serializeOutboundBody(senderId, candidate);
106
+ const candidateBytes = Buffer.byteLength(candidateBody, 'utf8');
107
+ if (candidateBytes > maxBodyBytes) break;
108
+
109
+ selected.push(m);
110
+ body = candidateBody;
111
+ bodyBytes = candidateBytes;
112
+ }
113
+
114
+ return { selected, rejected, body, bodyBytes, maxBodyBytes };
115
+ }
18
116
 
19
117
  class OutboundSync {
20
118
  constructor({ store, hubUrl, getHeaders, logger }) {
@@ -81,41 +179,76 @@ class OutboundSync {
81
179
  pending = pendingBatch.filter(m => !rejectedIds.has(m.id));
82
180
  if (pending.length === 0) return { sent: 0, dropped: rejectedTraceUploads.length };
83
181
  }
84
- const dropped = rejectedTraceUploads.length;
182
+ let dropped = rejectedTraceUploads.length;
85
183
 
86
184
  const endpoint = `${this.hubUrl}/a2a/mailbox/outbound`;
87
185
 
88
186
  try {
89
187
  const senderId = this.store.getState('node_id');
188
+ const prepared = buildSizedOutboundBatch(
189
+ senderId,
190
+ pending,
191
+ resolveMaxOutboundBodyBytes(process.env, this.store),
192
+ resolveHardOutboundBodyBytes(process.env)
193
+ );
194
+ if (prepared.rejected.length > 0) {
195
+ this.store.updateStatusBatch(prepared.rejected);
196
+ dropped += prepared.rejected.length;
197
+ }
198
+ pending = prepared.selected;
199
+ if (pending.length === 0) return { sent: 0, dropped };
200
+
90
201
  const res = await hubFetch(endpoint, {
91
202
  method: 'POST',
92
203
  headers: this.getHeaders(),
93
- body: JSON.stringify({
94
- sender_id: senderId,
95
- proxy_protocol_version: PROXY_PROTOCOL_VERSION,
96
- messages: pending.map(m => ({
97
- id: m.id,
98
- type: m.type,
99
- payload: m.payload,
100
- priority: m.priority,
101
- ref_id: m.ref_id,
102
- created_at: m.created_at,
103
- })),
104
- }),
204
+ body: prepared.body,
105
205
  signal: AbortSignal.timeout(30_000),
106
206
  });
107
207
 
208
+ if (res.status === 413) {
209
+ const errText = sanitizeHubErrorMessage(
210
+ await readHubResponseText(res).catch(() => 'request entity too large')
211
+ );
212
+ const error = `Hub 413 outbound payload too large: ${errText}`;
213
+ if (pending.length <= 1) {
214
+ this.store.updateStatusBatch(pending.map(m => ({
215
+ id: m.id,
216
+ status: 'rejected',
217
+ error,
218
+ })));
219
+ const result = {
220
+ sent: 0,
221
+ error: 'hub_payload_too_large',
222
+ payloadTooLarge: true,
223
+ dropped: dropped + pending.length,
224
+ };
225
+ return result;
226
+ }
227
+ const currentCeiling = Math.min(prepared.maxBodyBytes, Math.max(1, prepared.bodyBytes - 1));
228
+ const nextMax = currentCeiling > MIN_ADAPTIVE_OUTBOUND_BODY_BYTES
229
+ ? Math.max(MIN_ADAPTIVE_OUTBOUND_BODY_BYTES, Math.floor(currentCeiling / 2))
230
+ : Math.max(1, Math.floor(currentCeiling / 2));
231
+ try { this.store.setState(OUTBOUND_BODY_BYTES_STATE_KEY, nextMax); } catch { /* best effort */ }
232
+ this.logger.warn?.(
233
+ `[outbound] Hub 413 for ${pending.length} messages (${prepared.bodyBytes} bytes); ` +
234
+ `reducing outbound batch budget to ${nextMax} bytes`
235
+ );
236
+ const result = { sent: 0, error: 'hub_payload_too_large', payloadTooLarge: true };
237
+ if (dropped > 0) result.dropped = dropped;
238
+ return result;
239
+ }
240
+
108
241
  await throwIfHubUnreachableResponse(res, 'outbound flush');
109
242
  this._recordHubReachable();
110
243
 
111
244
  if (res.status === 403 || res.status === 401) {
112
- const errText = await readHubResponseText(res).catch(() => 'unknown');
113
- throw new AuthError(`Hub ${res.status}: ${sanitizeHubResponseForLog(errText)}`, res.status);
245
+ const errText = sanitizeHubErrorMessage(await readHubResponseText(res).catch(() => 'unknown'));
246
+ throw new AuthError(`Hub ${res.status}: ${errText}`, res.status);
114
247
  }
115
248
 
116
249
  if (!res.ok) {
117
- const errText = await readHubResponseText(res).catch(() => 'unknown');
118
- throw new Error(`Hub returned ${res.status}: ${sanitizeHubResponseForLog(errText)}`);
250
+ const errText = sanitizeHubErrorMessage(await readHubResponseText(res).catch(() => 'unknown'));
251
+ throw new Error(`Hub returned ${res.status}: ${errText}`);
119
252
  }
120
253
 
121
254
  const data = await readHubResponseJson(res);
@@ -129,10 +262,11 @@ class OutboundSync {
129
262
  updates.push({ id: r.id, status: 'synced' });
130
263
  } else if (r.status === 'failed' || r.status === 'rejected') {
131
264
  const msg = pending.find(m => m.id === r.id);
265
+ const error = sanitizeHubErrorMessage(r.error || 'rejected by hub');
132
266
  if (msg && msg.retry_count < MAX_RETRIES) {
133
- this.store.incrementRetry(r.id, r.error || 'rejected by hub');
267
+ this.store.incrementRetry(r.id, error);
134
268
  } else {
135
- updates.push({ id: r.id, status: 'failed', error: r.error || 'max retries' });
269
+ updates.push({ id: r.id, status: 'failed', error: sanitizeHubErrorMessage(r.error || 'max retries') });
136
270
  }
137
271
  }
138
272
 
@@ -166,11 +300,12 @@ class OutboundSync {
166
300
  if (dropped > 0) result.dropped = dropped;
167
301
  return result;
168
302
  }
169
- this.logger.error(`[outbound] flush failed: ${err.message}`);
303
+ const errMessage = sanitizeHubErrorMessage(err);
304
+ this.logger.error(`[outbound] flush failed: ${errMessage}`);
170
305
  for (const m of pending) {
171
- this.store.incrementRetry(m.id, err.message);
306
+ this.store.incrementRetry(m.id, errMessage);
172
307
  }
173
- const result = { sent: 0, error: err.message };
308
+ const result = { sent: 0, error: errMessage };
174
309
  if (dropped > 0) result.dropped = dropped;
175
310
  return result;
176
311
  }