@evomap/evolver 1.89.9 → 1.89.11
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 +2 -1
- package/README.zh-CN.md +1 -1
- package/assets/cover.png +0 -0
- package/index.js +5 -3
- package/package.json +1 -1
- package/src/adapters/scripts/evolver-session-end.js +18 -37
- package/src/atp/atpExecute.js +27 -71
- package/src/atp/serviceHelper.js +28 -36
- package/src/config.js +17 -0
- 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/contentHash.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/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/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/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 +9 -3
- package/src/gep/openPRRegistry.js +1 -1
- package/src/gep/personality.js +1 -1
- package/src/gep/policyCheck.js +1 -1
- package/src/gep/privacyClient.js +10 -9
- 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 +85 -17
- package/src/gep/skillDistiller.js +1 -1
- package/src/gep/solidify.js +1 -1
- package/src/gep/strategy.js +1 -1
- package/src/gep/tokenSavings.js +1 -1
- package/src/gep/workspaceKeychain.js +1 -1
- package/src/proxy/extensions/traceControl.js +1 -1
- package/src/proxy/index.js +369 -20
- package/src/proxy/inject.js +1 -1
- package/src/proxy/router/models_route.js +52 -0
- package/src/proxy/router/ollama_route.js +103 -0
- package/src/proxy/router/vertex_route.js +110 -0
- package/src/proxy/server/routes.js +30 -7
- package/src/proxy/trace/extractor.js +1 -1
- package/src/proxy/trace/usage.js +1 -1
package/README.ja-JP.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# 🧬 Evolver
|
|
2
2
|
|
|
3
|
-
[](https://github.com/EvoMap/evolver/stargazers)
|
|
4
4
|
[](https://opensource.org/licenses/GPL-3.0)
|
|
5
5
|
[](https://nodejs.org/)
|
|
6
6
|
[](https://www.npmjs.com/package/@evomap/evolver)
|
package/README.ko-KR.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# 🧬 Evolver
|
|
2
2
|
|
|
3
|
-
[](https://github.com/EvoMap/evolver/stargazers)
|
|
4
4
|
[](https://opensource.org/licenses/GPL-3.0)
|
|
5
5
|
[](https://nodejs.org/)
|
|
6
6
|
[](https://www.npmjs.com/package/@evomap/evolver)
|
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# 🧬 Evolver
|
|
2
2
|
|
|
3
|
-
[](https://github.com/EvoMap/evolver/stargazers)
|
|
4
4
|
[](https://opensource.org/licenses/GPL-3.0)
|
|
5
5
|
[](https://nodejs.org/)
|
|
6
6
|
[](https://www.npmjs.com/package/@evomap/evolver)
|
|
@@ -416,6 +416,7 @@ Evolver is designed to be **environment-agnostic**.
|
|
|
416
416
|
| `EVOLVE_STRATEGY` | Evolution strategy preset (`balanced` / `innovate` / `harden` / `repair-only`) | `balanced` |
|
|
417
417
|
| `A2A_HUB_URL` | [EvoMap Hub](https://evomap.ai) URL | _(unset, offline mode)_ |
|
|
418
418
|
| `A2A_NODE_ID` | Your node identity on the network | _(auto-generated from device fingerprint)_ |
|
|
419
|
+
| `EVOMAP_HUB_IP_FAMILY` | Hub egress IP-family policy: `ipv4first` tries IPv4 first and falls back to dual-stack, `auto` uses dual-stack as the primary path, `ipv4-only` disables fallback | `ipv4first` |
|
|
419
420
|
| `HEARTBEAT_INTERVAL_MS` | Hub heartbeat interval | `360000` (6 min) |
|
|
420
421
|
| `MEMORY_DIR` | Memory files path | `./memory` |
|
|
421
422
|
| `EVOLVE_REPORT_TOOL` | Tool name for reporting results | `message` |
|
package/README.zh-CN.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# 🧬 Evolver
|
|
2
2
|
|
|
3
|
-
[](https://github.com/EvoMap/evolver/stargazers)
|
|
4
4
|
[](https://opensource.org/licenses/GPL-3.0)
|
|
5
5
|
[](https://nodejs.org/)
|
|
6
6
|
[](https://www.npmjs.com/package/@evomap/evolver)
|
package/assets/cover.png
CHANGED
|
Binary file
|
package/index.js
CHANGED
|
@@ -2042,6 +2042,7 @@ async function main() {
|
|
|
2042
2042
|
}
|
|
2043
2043
|
|
|
2044
2044
|
const { getHubUrl, getNodeId, buildHubHeaders, sendHelloToHub, getHubNodeSecret } = require('./src/gep/a2aProtocol');
|
|
2045
|
+
const { hubFetch } = require('./src/gep/hubFetch');
|
|
2045
2046
|
|
|
2046
2047
|
const hubUrl = getHubUrl();
|
|
2047
2048
|
if (!hubUrl) {
|
|
@@ -2071,7 +2072,7 @@ async function main() {
|
|
|
2071
2072
|
|
|
2072
2073
|
console.log('[fetch] Downloading skill: ' + skillId);
|
|
2073
2074
|
|
|
2074
|
-
const resp = await
|
|
2075
|
+
const resp = await hubFetch(endpoint, {
|
|
2075
2076
|
method: 'POST',
|
|
2076
2077
|
headers: buildHubHeaders(),
|
|
2077
2078
|
body: JSON.stringify({ sender_id: nodeId }),
|
|
@@ -2253,6 +2254,7 @@ async function main() {
|
|
|
2253
2254
|
|
|
2254
2255
|
} else if (command === 'sync') {
|
|
2255
2256
|
const { getHubUrl, getNodeId, buildHubHeaders, sendHelloToHub, getHubNodeSecret } = require('./src/gep/a2aProtocol');
|
|
2257
|
+
const { hubFetch } = require('./src/gep/hubFetch');
|
|
2256
2258
|
const { upsertGene, upsertCapsule, loadGenes, loadCapsules } = require('./src/gep/assetStore');
|
|
2257
2259
|
const { getGepAssetsDir, getMemoryDir } = require('./src/gep/paths');
|
|
2258
2260
|
|
|
@@ -2321,7 +2323,7 @@ async function main() {
|
|
|
2321
2323
|
if (v != null) url += '&' + k + '=' + encodeURIComponent(v);
|
|
2322
2324
|
}
|
|
2323
2325
|
}
|
|
2324
|
-
const resp = await
|
|
2326
|
+
const resp = await hubFetch(url, {
|
|
2325
2327
|
method: 'GET',
|
|
2326
2328
|
headers: buildHubHeaders(),
|
|
2327
2329
|
signal: AbortSignal.timeout(30000),
|
|
@@ -2438,7 +2440,7 @@ async function main() {
|
|
|
2438
2440
|
try {
|
|
2439
2441
|
let payload = asset.payload;
|
|
2440
2442
|
if (!payload) {
|
|
2441
|
-
const detailResp = await
|
|
2443
|
+
const detailResp = await hubFetch(baseUrl + '/a2a/assets/' + encodeURIComponent(assetId) + '?detailed=true', {
|
|
2442
2444
|
method: 'GET',
|
|
2443
2445
|
headers: buildHubHeaders(),
|
|
2444
2446
|
signal: AbortSignal.timeout(15000),
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@evomap/evolver",
|
|
3
|
-
"version": "1.89.
|
|
3
|
+
"version": "1.89.11",
|
|
4
4
|
"description": "A GEP-powered self-evolution engine for AI agents. Features automated log analysis and Genome Evolution Protocol (GEP) for auditable, reusable evolution assets.",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"bin": {
|
|
@@ -8,8 +8,6 @@
|
|
|
8
8
|
const fs = require('fs');
|
|
9
9
|
const path = require('path');
|
|
10
10
|
const os = require('os');
|
|
11
|
-
const https = require('https');
|
|
12
|
-
const http = require('http');
|
|
13
11
|
const { spawnSync } = require('child_process');
|
|
14
12
|
// 10 MB — prevents RangeError on large child process output (e.g. git log/diff
|
|
15
13
|
// on large repos). See GHSA reports / issue #451.
|
|
@@ -113,15 +111,17 @@ function detectSignals(text) {
|
|
|
113
111
|
return [...new Set(signals)];
|
|
114
112
|
}
|
|
115
113
|
|
|
116
|
-
function
|
|
114
|
+
function loadHubFetch() {
|
|
115
|
+
const evolverRoot = findEvolverRoot();
|
|
116
|
+
return require(path.join(evolverRoot, 'src', 'gep', 'hubFetch')).hubFetch;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
async function recordToHub(outcome) {
|
|
117
120
|
const hubUrl = process.env.EVOMAP_HUB_URL || process.env.A2A_HUB_URL;
|
|
118
121
|
const apiKey = process.env.EVOMAP_API_KEY || process.env.A2A_NODE_SECRET;
|
|
119
122
|
const nodeId = process.env.EVOMAP_NODE_ID || process.env.A2A_NODE_ID;
|
|
120
123
|
if (!hubUrl || !apiKey) return false;
|
|
121
124
|
|
|
122
|
-
// Use Node.js built-in http/https instead of curl so this works on all
|
|
123
|
-
// platforms, including Windows where curl may not be available or may be
|
|
124
|
-
// an older, incompatible version bundled with some environments.
|
|
125
125
|
try {
|
|
126
126
|
const payload = JSON.stringify({
|
|
127
127
|
gene_id: outcome.geneId || 'ad_hoc',
|
|
@@ -133,37 +133,18 @@ function recordToHub(outcome) {
|
|
|
133
133
|
});
|
|
134
134
|
|
|
135
135
|
const endpoint = hubUrl.replace(/\/+$/, '') + '/a2a/evolution/record';
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
hostname: parsedUrl.hostname,
|
|
146
|
-
port: parsedUrl.port || (isHttps ? 443 : 80),
|
|
147
|
-
path: parsedUrl.pathname + (parsedUrl.search || ''),
|
|
148
|
-
method: 'POST',
|
|
149
|
-
headers: {
|
|
150
|
-
'Content-Type': 'application/json',
|
|
151
|
-
'Authorization': `Bearer ${apiKey}`,
|
|
152
|
-
'Content-Length': Buffer.byteLength(payload),
|
|
153
|
-
},
|
|
154
|
-
timeout: 8000,
|
|
155
|
-
},
|
|
156
|
-
(res) => {
|
|
157
|
-
// Drain the response to free the socket; we only care about status.
|
|
158
|
-
res.resume();
|
|
159
|
-
resolve(res.statusCode >= 200 && res.statusCode < 300);
|
|
160
|
-
}
|
|
161
|
-
);
|
|
162
|
-
req.on('error', () => resolve(false));
|
|
163
|
-
req.on('timeout', () => { req.destroy(); resolve(false); });
|
|
164
|
-
req.write(payload);
|
|
165
|
-
req.end();
|
|
136
|
+
const hubFetch = loadHubFetch();
|
|
137
|
+
const res = await hubFetch(endpoint, {
|
|
138
|
+
method: 'POST',
|
|
139
|
+
headers: {
|
|
140
|
+
'Content-Type': 'application/json',
|
|
141
|
+
'Authorization': `Bearer ${apiKey}`,
|
|
142
|
+
},
|
|
143
|
+
body: payload,
|
|
144
|
+
signal: AbortSignal.timeout(8000),
|
|
166
145
|
});
|
|
146
|
+
try { await res.text(); } catch (_) {}
|
|
147
|
+
return res.ok;
|
|
167
148
|
} catch {
|
|
168
149
|
return false;
|
|
169
150
|
}
|
|
@@ -250,7 +231,7 @@ function main() {
|
|
|
250
231
|
process.stdin.on('data', chunk => { inputData += chunk; });
|
|
251
232
|
process.stdin.on('end', () => {
|
|
252
233
|
if (handled) return;
|
|
253
|
-
// recordToHub is async (uses
|
|
234
|
+
// recordToHub is async (uses the shared Hub fetch transport); wrap the rest of the
|
|
254
235
|
// handler in an immediately-invoked async function so we can await it
|
|
255
236
|
// while still honouring the watchdog timeout and the `handled` guard.
|
|
256
237
|
(async () => {
|
package/src/atp/atpExecute.js
CHANGED
|
@@ -22,12 +22,10 @@
|
|
|
22
22
|
// idempotent server-side).
|
|
23
23
|
|
|
24
24
|
const fs = require('fs');
|
|
25
|
-
const http = require('http');
|
|
26
|
-
const https = require('https');
|
|
27
25
|
const crypto = require('crypto');
|
|
28
26
|
|
|
29
27
|
const { computeAssetId } = require('../gep/contentHash');
|
|
30
|
-
const {
|
|
28
|
+
const { hubFetch } = require('../gep/hubFetch');
|
|
31
29
|
const {
|
|
32
30
|
getNodeId,
|
|
33
31
|
getHubUrl,
|
|
@@ -126,77 +124,35 @@ function _publishUrl() {
|
|
|
126
124
|
return base + '/a2a/publish';
|
|
127
125
|
}
|
|
128
126
|
|
|
129
|
-
function _postJson(urlStr, body, timeoutMs) {
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
try {
|
|
139
|
-
enforceHubScheme(urlStr);
|
|
140
|
-
} catch (e) {
|
|
141
|
-
resolve({ ok: false, error: 'tls_refused: ' + (e && e.message) });
|
|
142
|
-
return;
|
|
143
|
-
}
|
|
144
|
-
let parsed;
|
|
145
|
-
try {
|
|
146
|
-
parsed = new URL(urlStr);
|
|
147
|
-
} catch (e) {
|
|
148
|
-
resolve({ ok: false, error: 'invalid_url: ' + (e && e.message) });
|
|
149
|
-
return;
|
|
150
|
-
}
|
|
151
|
-
const isHttps = parsed.protocol === 'https:';
|
|
152
|
-
const lib = isHttps ? https : http;
|
|
153
|
-
const payload = JSON.stringify(body || {});
|
|
154
|
-
const headers = Object.assign(
|
|
155
|
-
{ 'Content-Type': 'application/json', 'Content-Length': Buffer.byteLength(payload) },
|
|
156
|
-
buildHubHeaders() || {},
|
|
157
|
-
);
|
|
158
|
-
// Pin TLS cert verification for https calls so a globally-disabled
|
|
159
|
-
// NODE_TLS_REJECT_UNAUTHORIZED=0 cannot weaken the Hub channel
|
|
160
|
-
// (Cursor Security Reviewer #160 Medium). hubFetch enforces the
|
|
161
|
-
// same via its undici dispatcher; this is the Node-native-https
|
|
162
|
-
// equivalent.
|
|
163
|
-
//
|
|
164
|
-
// Skipped under EVOMAP_HUB_ALLOW_INSECURE=1 so local-dev / self-
|
|
165
|
-
// signed mock hubs that legitimately rely on
|
|
166
|
-
// NODE_TLS_REJECT_UNAUTHORIZED=0 still work.
|
|
167
|
-
const requestOpts = {
|
|
168
|
-
hostname: parsed.hostname,
|
|
169
|
-
port: parsed.port || (isHttps ? 443 : 80),
|
|
170
|
-
path: parsed.pathname + (parsed.search || ''),
|
|
127
|
+
async function _postJson(urlStr, body, timeoutMs) {
|
|
128
|
+
const payload = JSON.stringify(body || {});
|
|
129
|
+
const headers = Object.assign(
|
|
130
|
+
{ 'Content-Type': 'application/json' },
|
|
131
|
+
buildHubHeaders() || {},
|
|
132
|
+
);
|
|
133
|
+
|
|
134
|
+
try {
|
|
135
|
+
const res = await hubFetch(urlStr, {
|
|
171
136
|
method: 'POST',
|
|
172
137
|
headers: headers,
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
138
|
+
body: payload,
|
|
139
|
+
signal: AbortSignal.timeout(timeoutMs || PUBLISH_TIMEOUT_MS),
|
|
140
|
+
});
|
|
141
|
+
const text = await res.text();
|
|
142
|
+
let data = null;
|
|
143
|
+
try { data = text ? JSON.parse(text) : null; } catch (e) { data = { raw: text }; }
|
|
144
|
+
if (res.status >= 200 && res.status < 300) {
|
|
145
|
+
return { ok: true, status: res.status, data };
|
|
177
146
|
}
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
if (res.statusCode >= 200 && res.statusCode < 300) {
|
|
188
|
-
resolve({ ok: true, status: res.statusCode, data });
|
|
189
|
-
} else {
|
|
190
|
-
resolve({ ok: false, status: res.statusCode, data, error: 'http_' + res.statusCode });
|
|
191
|
-
}
|
|
192
|
-
});
|
|
193
|
-
},
|
|
194
|
-
);
|
|
195
|
-
req.on('timeout', function () { req.destroy(new Error('timeout')); });
|
|
196
|
-
req.on('error', function (err) { resolve({ ok: false, error: err.message }); });
|
|
197
|
-
req.write(payload);
|
|
198
|
-
req.end();
|
|
199
|
-
});
|
|
147
|
+
return { ok: false, status: res.status, data, error: 'http_' + res.status };
|
|
148
|
+
} catch (err) {
|
|
149
|
+
const msg = (err && err.message) || String(err);
|
|
150
|
+
if (msg.indexOf('[hubFetch]') !== -1) {
|
|
151
|
+
if (/not a valid URL/i.test(msg)) return { ok: false, error: 'invalid_url: ' + msg };
|
|
152
|
+
return { ok: false, error: 'tls_refused: ' + msg };
|
|
153
|
+
}
|
|
154
|
+
return { ok: false, error: msg };
|
|
155
|
+
}
|
|
200
156
|
}
|
|
201
157
|
|
|
202
158
|
async function _ensureNodeSecret() {
|
package/src/atp/serviceHelper.js
CHANGED
|
@@ -1,6 +1,32 @@
|
|
|
1
1
|
// ATP Service Helper -- wraps marketplace service publishing for merchant agents.
|
|
2
2
|
|
|
3
3
|
const { getNodeId, buildHubHeaders, getHubUrl } = require('../gep/a2aProtocol');
|
|
4
|
+
const { hubFetch } = require('../gep/hubFetch');
|
|
5
|
+
const { HTTP_TRANSPORT_TIMEOUT_MS } = require('../config');
|
|
6
|
+
|
|
7
|
+
async function postService(endpoint, body) {
|
|
8
|
+
try {
|
|
9
|
+
const res = await hubFetch(endpoint, {
|
|
10
|
+
method: 'POST',
|
|
11
|
+
headers: Object.assign({ 'Content-Type': 'application/json' }, buildHubHeaders() || {}),
|
|
12
|
+
body: JSON.stringify(body),
|
|
13
|
+
signal: AbortSignal.timeout(HTTP_TRANSPORT_TIMEOUT_MS),
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
if (!res.ok) {
|
|
17
|
+
const t = await res.text();
|
|
18
|
+
return { ok: false, status: res.status, error: t.slice(0, 400) };
|
|
19
|
+
}
|
|
20
|
+
const data = await res.json();
|
|
21
|
+
return { ok: true, data };
|
|
22
|
+
} catch (err) {
|
|
23
|
+
const msg = (err && err.message) || String(err);
|
|
24
|
+
if (msg.indexOf('[hubFetch]') !== -1) {
|
|
25
|
+
return { ok: false, error: 'tls_refused: ' + msg };
|
|
26
|
+
}
|
|
27
|
+
return { ok: false, error: msg };
|
|
28
|
+
}
|
|
29
|
+
}
|
|
4
30
|
|
|
5
31
|
/**
|
|
6
32
|
* Publish a ServiceListing via the Hub marketplace API.
|
|
@@ -21,7 +47,6 @@ async function publishService(svc) {
|
|
|
21
47
|
|
|
22
48
|
const nodeId = getNodeId();
|
|
23
49
|
const endpoint = hubUrl.replace(/\/+$/, '') + '/a2a/service/publish';
|
|
24
|
-
const timeout = require('../config').HTTP_TRANSPORT_TIMEOUT_MS;
|
|
25
50
|
|
|
26
51
|
const body = {
|
|
27
52
|
sender_id: nodeId,
|
|
@@ -35,23 +60,7 @@ async function publishService(svc) {
|
|
|
35
60
|
recipe_id: svc.recipeId,
|
|
36
61
|
};
|
|
37
62
|
|
|
38
|
-
|
|
39
|
-
const res = await fetch(endpoint, {
|
|
40
|
-
method: 'POST',
|
|
41
|
-
headers: buildHubHeaders(),
|
|
42
|
-
body: JSON.stringify(body),
|
|
43
|
-
signal: AbortSignal.timeout(timeout),
|
|
44
|
-
});
|
|
45
|
-
|
|
46
|
-
if (!res.ok) {
|
|
47
|
-
const t = await res.text();
|
|
48
|
-
return { ok: false, status: res.status, error: t.slice(0, 400) };
|
|
49
|
-
}
|
|
50
|
-
const data = await res.json();
|
|
51
|
-
return { ok: true, data };
|
|
52
|
-
} catch (err) {
|
|
53
|
-
return { ok: false, error: err.message };
|
|
54
|
-
}
|
|
63
|
+
return postService(endpoint, body);
|
|
55
64
|
}
|
|
56
65
|
|
|
57
66
|
/**
|
|
@@ -66,7 +75,6 @@ async function updateService(listingId, updates) {
|
|
|
66
75
|
|
|
67
76
|
const nodeId = getNodeId();
|
|
68
77
|
const endpoint = hubUrl.replace(/\/+$/, '') + '/a2a/service/update';
|
|
69
|
-
const timeout = require('../config').HTTP_TRANSPORT_TIMEOUT_MS;
|
|
70
78
|
|
|
71
79
|
const body = {
|
|
72
80
|
sender_id: nodeId,
|
|
@@ -74,23 +82,7 @@ async function updateService(listingId, updates) {
|
|
|
74
82
|
...updates,
|
|
75
83
|
};
|
|
76
84
|
|
|
77
|
-
|
|
78
|
-
const res = await fetch(endpoint, {
|
|
79
|
-
method: 'POST',
|
|
80
|
-
headers: buildHubHeaders(),
|
|
81
|
-
body: JSON.stringify(body),
|
|
82
|
-
signal: AbortSignal.timeout(timeout),
|
|
83
|
-
});
|
|
84
|
-
|
|
85
|
-
if (!res.ok) {
|
|
86
|
-
const t = await res.text();
|
|
87
|
-
return { ok: false, status: res.status, error: t.slice(0, 400) };
|
|
88
|
-
}
|
|
89
|
-
const data = await res.json();
|
|
90
|
-
return { ok: true, data };
|
|
91
|
-
} catch (err) {
|
|
92
|
-
return { ok: false, error: err.message };
|
|
93
|
-
}
|
|
85
|
+
return postService(endpoint, body);
|
|
94
86
|
}
|
|
95
87
|
|
|
96
88
|
module.exports = {
|
package/src/config.js
CHANGED
|
@@ -202,6 +202,20 @@ function reuseAttributionMode() {
|
|
|
202
202
|
return v === 'shadow' ? 'shadow' : 'off';
|
|
203
203
|
}
|
|
204
204
|
|
|
205
|
+
// Opt-in Hub reuse-OUTCOME reporting (P4-a Slice B, client side). When 'on', the
|
|
206
|
+
// evolver POSTs {signals, status, used_asset_ids} to the Hub's /a2a/memory/record
|
|
207
|
+
// so the reuse-reward attribution pipeline (which reads THAT endpoint, not the
|
|
208
|
+
// inert reuse_attribution blob on /a2a/memory/event) finally gets data.
|
|
209
|
+
// MONEY-ADJACENT and charges Hub credits -> default 'off'. The Hub still
|
|
210
|
+
// re-verifies every used_asset_id against its own AssetFetcher rows before
|
|
211
|
+
// crediting. Also requires EVOLVER_REUSE_ATTRIBUTION=shadow, which is what builds
|
|
212
|
+
// the cycle-correlated, timestamp-guarded attribution this report consumes.
|
|
213
|
+
const OUTCOME_REPORT_MODE = envStr('EVOLVER_OUTCOME_REPORT', 'off');
|
|
214
|
+
function outcomeReportMode() {
|
|
215
|
+
const v = String(process.env.EVOLVER_OUTCOME_REPORT || OUTCOME_REPORT_MODE || 'off').toLowerCase().trim();
|
|
216
|
+
return v === 'on' || v === 'enforce' || v === 'true' ? 'on' : 'off';
|
|
217
|
+
}
|
|
218
|
+
|
|
205
219
|
// --- Anti-abuse telemetry (privacy-preserving heartbeat summary) ---
|
|
206
220
|
// Enabled by default. In heartbeat mode, clients attach a small
|
|
207
221
|
// `meta.anti_abuse` envelope with low-sensitive hashes, source-confidence
|
|
@@ -306,6 +320,9 @@ module.exports = {
|
|
|
306
320
|
// Reuse attribution (P4-a Slice A)
|
|
307
321
|
REUSE_ATTRIBUTION_MODE,
|
|
308
322
|
reuseAttributionMode,
|
|
323
|
+
// Reuse-outcome Hub reporting (P4-a Slice B, opt-in)
|
|
324
|
+
OUTCOME_REPORT_MODE,
|
|
325
|
+
outcomeReportMode,
|
|
309
326
|
// Anti-abuse telemetry
|
|
310
327
|
ANTI_ABUSE_TELEMETRY_MODE,
|
|
311
328
|
antiAbuseTelemetryMode,
|