@evomap/evolver 1.89.15 → 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.
- package/README.ja-JP.md +1 -1
- package/README.ko-KR.md +1 -1
- package/README.md +1 -1
- package/README.zh-CN.md +1 -1
- package/index.js +89 -17
- package/package.json +1 -1
- package/src/adapters/claudeCode.js +38 -9
- package/src/adapters/codex.js +2 -2
- package/src/adapters/hookAdapter.js +38 -2
- package/src/adapters/scripts/evolver-session-start.js +182 -2
- package/src/atp/atpExecute.js +3 -1
- package/src/atp/hubClient.js +5 -3
- package/src/atp/serviceHelper.js +3 -2
- package/src/config.js +11 -3
- package/src/evolve/guards.js +1 -1
- package/src/evolve/pipeline/collect.js +1 -1
- package/src/evolve/pipeline/dispatch.js +1 -1
- package/src/evolve/pipeline/enrich.js +1 -1
- package/src/evolve/pipeline/hub.js +1 -1
- package/src/evolve/pipeline/select.js +1 -1
- package/src/evolve/pipeline/signals.js +1 -1
- package/src/evolve/utils.js +1 -1
- package/src/evolve.js +1 -1
- package/src/gep/a2aProtocol.js +1 -1
- package/src/gep/antiAbuseTelemetry.js +1 -1
- package/src/gep/autoDistillConv.js +1 -1
- package/src/gep/autoDistillLlm.js +1 -1
- package/src/gep/candidateEval.js +1 -1
- package/src/gep/candidates.js +1 -1
- package/src/gep/cliContracts.js +37 -1
- package/src/gep/contentHash.js +1 -1
- package/src/gep/conversationDistiller.js +1 -1
- package/src/gep/conversationSniffer.js +1 -1
- package/src/gep/crypto.js +1 -1
- package/src/gep/curriculum.js +1 -1
- package/src/gep/deviceId.js +1 -1
- package/src/gep/directoryClient.js +7 -3
- package/src/gep/envFingerprint.js +1 -1
- package/src/gep/epigenetics.js +1 -1
- package/src/gep/execBridge.js +1 -1
- package/src/gep/explore.js +1 -1
- package/src/gep/hash.js +1 -1
- package/src/gep/hostErrorClassifier.js +34 -0
- package/src/gep/hubFetch.js +1 -1
- package/src/gep/hubReview.js +1 -1
- package/src/gep/hubSearch.js +1 -1
- package/src/gep/hubVerify.js +1 -1
- package/src/gep/issueReporter.js +5 -4
- package/src/gep/learningSignals.js +1 -1
- package/src/gep/memoryGraph.js +1 -1
- package/src/gep/memoryGraphAdapter.js +1 -1
- package/src/gep/mutation.js +1 -1
- package/src/gep/narrativeMemory.js +1 -1
- package/src/gep/oauthLogin.js +3 -5
- package/src/gep/openPRRegistry.js +1 -1
- package/src/gep/paths.js +20 -0
- package/src/gep/personality.js +1 -1
- package/src/gep/policyCheck.js +1 -1
- package/src/gep/privacyClient.js +28 -10
- package/src/gep/prompt.js +1 -1
- package/src/gep/recallInject.js +1 -1
- package/src/gep/recallVerifier.js +1 -1
- package/src/gep/reflection.js +1 -1
- package/src/gep/savingsCore.js +1 -1
- package/src/gep/selector.js +1 -1
- package/src/gep/signals.js +37 -15
- package/src/gep/skillDistiller.js +1 -1
- package/src/gep/skillPublisher.js +8 -3
- package/src/gep/solidify.js +1 -1
- package/src/gep/strategy.js +1 -1
- package/src/gep/taskReceiver.js +3 -2
- package/src/gep/tokenSavings.js +1 -1
- package/src/gep/validator/index.js +7 -2
- package/src/gep/validator/reporter.js +7 -2
- package/src/gep/validator/stakeBootstrap.js +7 -2
- package/src/gep/workspaceKeychain.js +1 -1
- package/src/ops/lifecycle.js +501 -31
- package/src/proxy/clientSettings.js +405 -0
- package/src/proxy/extensions/traceControl.js +1 -1
- package/src/proxy/index.js +10 -5
- package/src/proxy/inject.js +1 -1
- package/src/proxy/lifecycle/manager.js +82 -16
- package/src/proxy/mailbox/state.js +207 -0
- package/src/proxy/mailbox/store.js +164 -64
- package/src/proxy/router/messages_route.js +4 -3
- package/src/proxy/server/http.js +40 -6
- package/src/proxy/sync/inbound.js +31 -12
- package/src/proxy/sync/outbound.js +157 -22
- package/src/proxy/trace/extractor.js +1 -1
- 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
|
-
|
|
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:
|
|
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}: ${
|
|
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}: ${
|
|
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,
|
|
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
|
-
|
|
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,
|
|
306
|
+
this.store.incrementRetry(m.id, errMessage);
|
|
172
307
|
}
|
|
173
|
-
const result = { sent: 0, error:
|
|
308
|
+
const result = { sent: 0, error: errMessage };
|
|
174
309
|
if (dropped > 0) result.dropped = dropped;
|
|
175
310
|
return result;
|
|
176
311
|
}
|