@evomap/evolver 1.90.0 → 2.0.0-beta.0
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.md +27 -564
- package/bin/evolver-llm-proxy.js +3 -0
- package/bin/evolver-mcp.js +2 -0
- package/bin/evolver-proxy.js +3 -0
- package/bin/evolver.js +4 -0
- package/index.js +1 -3670
- package/package.json +32 -62
- package/CONTRIBUTING.md +0 -19
- package/LICENSE +0 -641
- package/README.ja-JP.md +0 -521
- package/README.ko-KR.md +0 -520
- package/README.zh-CN.md +0 -531
- package/SKILL.md +0 -365
- package/assets/cover.png +0 -0
- package/assets/gep/genes.seed.json +0 -496
- package/conformance/savings-core/constants.json +0 -30
- package/conformance/savings-core/golden-vectors.json +0 -333
- package/scripts/a2a_export.js +0 -63
- package/scripts/a2a_ingest.js +0 -79
- package/scripts/a2a_promote.js +0 -118
- package/scripts/analyze_by_skill.js +0 -121
- package/scripts/build_binaries.js +0 -479
- package/scripts/check-changelog.js +0 -166
- package/scripts/extract_log.js +0 -85
- package/scripts/generate_history.js +0 -75
- package/scripts/gep_append_event.js +0 -96
- package/scripts/gep_personality_report.js +0 -234
- package/scripts/human_report.js +0 -147
- package/scripts/recall-verify-report.js +0 -234
- package/scripts/recover_loop.js +0 -61
- package/scripts/refresh_stars_badge.js +0 -168
- package/scripts/seed-merchants.js +0 -91
- package/scripts/skill2recipes.js +0 -118
- package/scripts/suggest_version.js +0 -89
- package/scripts/validate-modules.js +0 -38
- package/scripts/validate-suite.js +0 -78
- package/src/adapters/claudeCode.js +0 -194
- package/src/adapters/codex.js +0 -216
- package/src/adapters/cursor.js +0 -91
- package/src/adapters/hookAdapter.js +0 -469
- package/src/adapters/kiro.js +0 -195
- package/src/adapters/opencode.js +0 -326
- package/src/adapters/scripts/_lockPaths.js +0 -74
- package/src/adapters/scripts/_memoryFiltering.js +0 -35
- package/src/adapters/scripts/_runtimePaths.js +0 -440
- package/src/adapters/scripts/evolver-session-end.js +0 -321
- package/src/adapters/scripts/evolver-session-start.js +0 -587
- package/src/adapters/scripts/evolver-signal-detect.js +0 -98
- package/src/adapters/scripts/evolver-task-recall.js +0 -173
- package/src/atp/atpExecute.js +0 -283
- package/src/atp/atpTaskPickup.js +0 -233
- package/src/atp/autoBuyer.js +0 -382
- package/src/atp/autoDeliver.js +0 -215
- package/src/atp/cli.js +0 -354
- package/src/atp/cliAutobuyPrompt.js +0 -154
- package/src/atp/consumerAgent.js +0 -157
- package/src/atp/defaultHandler.js +0 -69
- package/src/atp/heartbeatSignalsHandler.js +0 -254
- package/src/atp/hubClient.js +0 -317
- package/src/atp/index.js +0 -38
- package/src/atp/merchantAgent.js +0 -118
- package/src/atp/protocol.js +0 -41
- package/src/atp/questionComposer.js +0 -133
- package/src/atp/serviceHelper.js +0 -92
- package/src/canary.js +0 -13
- package/src/config.js +0 -351
- package/src/evolve/guards.js +0 -1
- package/src/evolve/pipeline/collect.js +0 -1
- package/src/evolve/pipeline/dispatch.js +0 -1
- package/src/evolve/pipeline/enrich.js +0 -1
- package/src/evolve/pipeline/hub.js +0 -1
- package/src/evolve/pipeline/select.js +0 -1
- package/src/evolve/pipeline/signals.js +0 -1
- package/src/evolve/utils.js +0 -1
- package/src/evolve.js +0 -1
- package/src/experiment/agentRunner.js +0 -229
- package/src/experiment/cli.js +0 -159
- package/src/experiment/comparison.js +0 -233
- package/src/experiment/metrics.js +0 -75
- package/src/forceUpdate.js +0 -991
- package/src/gep/a2a.js +0 -173
- package/src/gep/a2aProtocol.js +0 -1
- package/src/gep/analyzer.js +0 -35
- package/src/gep/antiAbuseTelemetry.js +0 -1
- package/src/gep/assetCallLog.js +0 -197
- package/src/gep/assetStore.js +0 -723
- package/src/gep/assets.js +0 -36
- package/src/gep/autoDistillConv.js +0 -1
- package/src/gep/autoDistillLlm.js +0 -1
- package/src/gep/bridge.js +0 -138
- package/src/gep/candidateEval.js +0 -1
- package/src/gep/candidates.js +0 -1
- package/src/gep/claimNudge.js +0 -121
- package/src/gep/cliContracts.js +0 -1190
- package/src/gep/contentHash.js +0 -1
- package/src/gep/conversationDistiller.js +0 -1
- package/src/gep/conversationSniffer.js +0 -1
- package/src/gep/crypto.js +0 -1
- package/src/gep/curriculum.js +0 -1
- package/src/gep/deviceId.js +0 -1
- package/src/gep/directoryClient.js +0 -115
- package/src/gep/envFingerprint.js +0 -1
- package/src/gep/epigenetics.js +0 -1
- package/src/gep/execBridge.js +0 -1
- package/src/gep/executionTrace.js +0 -291
- package/src/gep/explore.js +0 -1
- package/src/gep/featureFlags.js +0 -121
- package/src/gep/gitOps.js +0 -265
- package/src/gep/hash.js +0 -1
- package/src/gep/hostErrorClassifier.js +0 -34
- package/src/gep/hubFetch.js +0 -1
- package/src/gep/hubReview.js +0 -1
- package/src/gep/hubSearch.js +0 -1
- package/src/gep/hubVerify.js +0 -1
- package/src/gep/idleScheduler.js +0 -400
- package/src/gep/issueReporter.js +0 -416
- package/src/gep/learningSignals.js +0 -1
- package/src/gep/llmReview.js +0 -92
- package/src/gep/localStateAwareness.js +0 -243
- package/src/gep/mailboxTransport.js +0 -119
- package/src/gep/memoryGraph.js +0 -1
- package/src/gep/memoryGraphAdapter.js +0 -1
- package/src/gep/mutation.js +0 -1
- package/src/gep/narrativeMemory.js +0 -1
- package/src/gep/oauthLogin.js +0 -181
- package/src/gep/openPRRegistry.js +0 -1
- package/src/gep/paths.js +0 -522
- package/src/gep/personality.js +0 -1
- package/src/gep/policyCheck.js +0 -1
- package/src/gep/portable.js +0 -103
- package/src/gep/privacyClient.js +0 -235
- package/src/gep/prompt.js +0 -1
- package/src/gep/questionGenerator.js +0 -518
- package/src/gep/recallInject.js +0 -1
- package/src/gep/recallVerifier.js +0 -1
- package/src/gep/reflection.js +0 -1
- package/src/gep/sanitize.js +0 -264
- package/src/gep/savingsCore.js +0 -1
- package/src/gep/schemas/capsule.js +0 -170
- package/src/gep/schemas/gene.js +0 -154
- package/src/gep/schemas/index.js +0 -8
- package/src/gep/schemas/protocol.js +0 -51
- package/src/gep/schemas/task.js +0 -74
- package/src/gep/selector.js +0 -1
- package/src/gep/selfPR.js +0 -469
- package/src/gep/signals.js +0 -776
- package/src/gep/skill2gep.js +0 -1056
- package/src/gep/skill2gepAudit.js +0 -303
- package/src/gep/skill2recipes.js +0 -511
- package/src/gep/skillDistiller.js +0 -1
- package/src/gep/skillPublisher.js +0 -358
- package/src/gep/solidify.js +0 -1
- package/src/gep/strategy.js +0 -1
- package/src/gep/taskReceiver.js +0 -575
- package/src/gep/tokenSavings.js +0 -1
- package/src/gep/trajectoryExport.js +0 -1
- package/src/gep/validationReport.js +0 -55
- package/src/gep/validator/index.js +0 -411
- package/src/gep/validator/reporter.js +0 -210
- package/src/gep/validator/sandboxExecutor.js +0 -480
- package/src/gep/validator/stakeBootstrap.js +0 -357
- package/src/gep/workspaceKeychain.js +0 -1
- package/src/ops/cleanup.js +0 -80
- package/src/ops/commentary.js +0 -60
- package/src/ops/health_check.js +0 -104
- package/src/ops/index.js +0 -11
- package/src/ops/innovation.js +0 -67
- package/src/ops/lifecycle.js +0 -798
- package/src/ops/self_repair.js +0 -76
- package/src/ops/skills_monitor.js +0 -147
- package/src/ops/trigger.js +0 -33
- package/src/proxy/clientSettings.js +0 -405
- package/src/proxy/envelope.js +0 -59
- package/src/proxy/extensions/dmHandler.js +0 -45
- package/src/proxy/extensions/sessionHandler.js +0 -141
- package/src/proxy/extensions/skillUpdater.js +0 -64
- package/src/proxy/extensions/traceControl.js +0 -1
- package/src/proxy/index.js +0 -1395
- package/src/proxy/inject.js +0 -1
- package/src/proxy/lifecycle/manager.js +0 -1568
- package/src/proxy/mailbox/state.js +0 -207
- package/src/proxy/mailbox/store.js +0 -602
- package/src/proxy/router/cache_passthrough.js +0 -26
- package/src/proxy/router/features.js +0 -84
- package/src/proxy/router/gemini_route.js +0 -154
- package/src/proxy/router/messages_route.js +0 -535
- package/src/proxy/router/model_router.js +0 -113
- package/src/proxy/router/models_route.js +0 -52
- package/src/proxy/router/ollama_route.js +0 -103
- package/src/proxy/router/responses_route.js +0 -170
- package/src/proxy/router/vertex_route.js +0 -110
- package/src/proxy/server/http.js +0 -363
- package/src/proxy/server/routes.js +0 -558
- package/src/proxy/server/settings.js +0 -115
- package/src/proxy/sync/engine.js +0 -179
- package/src/proxy/sync/inbound.js +0 -211
- package/src/proxy/sync/outbound.js +0 -361
- package/src/proxy/task/monitor.js +0 -131
- package/src/proxy/trace/extractor.js +0 -1
- package/src/proxy/trace/usage.js +0 -1
- package/src/solo/breaker.js +0 -25
- package/src/solo/gitGuard.js +0 -65
- package/src/webui/client/clientJs/assets.js +0 -111
- package/src/webui/client/clientJs/bootstrap.js +0 -92
- package/src/webui/client/clientJs/common.js +0 -77
- package/src/webui/client/clientJs/i18n.js +0 -366
- package/src/webui/client/clientJs/index.js +0 -35
- package/src/webui/client/clientJs/interactions.js +0 -351
- package/src/webui/client/clientJs/overview.js +0 -152
- package/src/webui/client/clientJs/personality.js +0 -285
- package/src/webui/client/clientJs/pipelines.js +0 -330
- package/src/webui/client/indexHtml.js +0 -221
- package/src/webui/client/static.js +0 -23
- package/src/webui/client/stylesCss.js +0 -639
- package/src/webui/client/vendor/README.md +0 -15
- package/src/webui/client/vendor/echarts.min.js +0 -45
- package/src/webui/index.js +0 -14
- package/src/webui/observer/assets.js +0 -146
- package/src/webui/observer/index.js +0 -37
- package/src/webui/observer/interactions.js +0 -127
- package/src/webui/observer/jsonl.js +0 -75
- package/src/webui/observer/paths.js +0 -46
- package/src/webui/observer/personality.js +0 -43
- package/src/webui/observer/pipelineEvents.js +0 -58
- package/src/webui/observer/redact.js +0 -63
- package/src/webui/observer/runs.js +0 -356
- package/src/webui/observer/safety.js +0 -57
- package/src/webui/observer/skills.js +0 -70
- package/src/webui/observer/status.js +0 -71
- package/src/webui/server/http.js +0 -138
- package/src/webui/server/routes.js +0 -41
package/src/gep/portable.js
DELETED
|
@@ -1,103 +0,0 @@
|
|
|
1
|
-
// Portable .gepx archive export (CommonJS).
|
|
2
|
-
// Mirrors @evomap/gep-sdk exportGepx semantics: gzip-tar the local GEP assets
|
|
3
|
-
// (genes / capsules / events / memory graph) plus a manifest and sha256
|
|
4
|
-
// checksums so the archive is self-describing.
|
|
5
|
-
//
|
|
6
|
-
// Kept intentionally minimal (no import path): evolver sync uses this to bundle
|
|
7
|
-
// "everything locally known about this agent" so a user can hand the single
|
|
8
|
-
// file to another machine or keep a point-in-time snapshot.
|
|
9
|
-
const { execFileSync } = require('child_process');
|
|
10
|
-
const fs = require('fs');
|
|
11
|
-
const path = require('path');
|
|
12
|
-
const crypto = require('crypto');
|
|
13
|
-
|
|
14
|
-
function countJsonlLines(filePath) {
|
|
15
|
-
if (!fs.existsSync(filePath)) return 0;
|
|
16
|
-
return fs.readFileSync(filePath, 'utf8').split('\n').filter((l) => l.trim()).length;
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
function countJsonItems(filePath, key) {
|
|
20
|
-
if (!fs.existsSync(filePath)) return 0;
|
|
21
|
-
try {
|
|
22
|
-
const data = JSON.parse(fs.readFileSync(filePath, 'utf8'));
|
|
23
|
-
return Array.isArray(data[key]) ? data[key].length : 0;
|
|
24
|
-
} catch {
|
|
25
|
-
return 0;
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
function exportGepx({ assetsDir, memoryGraphPath, outputPath, agentId, agentName }) {
|
|
30
|
-
if (!assetsDir) throw new Error('exportGepx: assetsDir required');
|
|
31
|
-
if (!outputPath) throw new Error('exportGepx: outputPath required');
|
|
32
|
-
|
|
33
|
-
const outDir = path.dirname(path.resolve(outputPath));
|
|
34
|
-
if (!fs.existsSync(outDir)) fs.mkdirSync(outDir, { recursive: true });
|
|
35
|
-
|
|
36
|
-
const tmpDir = `${outputPath}.tmp`;
|
|
37
|
-
if (fs.existsSync(tmpDir)) fs.rmSync(tmpDir, { recursive: true, force: true });
|
|
38
|
-
fs.mkdirSync(path.join(tmpDir, 'genes'), { recursive: true });
|
|
39
|
-
fs.mkdirSync(path.join(tmpDir, 'capsules'), { recursive: true });
|
|
40
|
-
fs.mkdirSync(path.join(tmpDir, 'events'), { recursive: true });
|
|
41
|
-
fs.mkdirSync(path.join(tmpDir, 'memory'), { recursive: true });
|
|
42
|
-
|
|
43
|
-
const filesToCopy = [
|
|
44
|
-
{ src: path.join(assetsDir, 'genes.json'), dest: path.join(tmpDir, 'genes', 'genes.json') },
|
|
45
|
-
{ src: path.join(assetsDir, 'genes.jsonl'), dest: path.join(tmpDir, 'genes', 'genes.jsonl') },
|
|
46
|
-
{ src: path.join(assetsDir, 'capsules.json'), dest: path.join(tmpDir, 'capsules', 'capsules.json') },
|
|
47
|
-
{ src: path.join(assetsDir, 'capsules.jsonl'), dest: path.join(tmpDir, 'capsules', 'capsules.jsonl') },
|
|
48
|
-
{ src: path.join(assetsDir, 'events.jsonl'), dest: path.join(tmpDir, 'events', 'events.jsonl') },
|
|
49
|
-
];
|
|
50
|
-
if (memoryGraphPath) {
|
|
51
|
-
filesToCopy.push({ src: memoryGraphPath, dest: path.join(tmpDir, 'memory', 'memory_graph.jsonl') });
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
const checksums = [];
|
|
55
|
-
for (const f of filesToCopy) {
|
|
56
|
-
if (!fs.existsSync(f.src)) continue;
|
|
57
|
-
const content = fs.readFileSync(f.src);
|
|
58
|
-
fs.mkdirSync(path.dirname(f.dest), { recursive: true });
|
|
59
|
-
fs.writeFileSync(f.dest, content);
|
|
60
|
-
const hash = crypto.createHash('sha256').update(content).digest('hex');
|
|
61
|
-
checksums.push(`${hash} ${path.relative(tmpDir, f.dest).replace(/\\/g, '/')}`);
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
const stats = {
|
|
65
|
-
total_events: countJsonlLines(path.join(tmpDir, 'events', 'events.jsonl')),
|
|
66
|
-
total_genes: countJsonItems(path.join(tmpDir, 'genes', 'genes.json'), 'genes'),
|
|
67
|
-
total_capsules: countJsonItems(path.join(tmpDir, 'capsules', 'capsules.json'), 'capsules'),
|
|
68
|
-
memory_graph_entries: memoryGraphPath
|
|
69
|
-
? countJsonlLines(path.join(tmpDir, 'memory', 'memory_graph.jsonl'))
|
|
70
|
-
: 0,
|
|
71
|
-
};
|
|
72
|
-
|
|
73
|
-
const manifest = {
|
|
74
|
-
gep_version: '1.0.0',
|
|
75
|
-
created_at: new Date().toISOString(),
|
|
76
|
-
agent_id: agentId || null,
|
|
77
|
-
agent_name: agentName || 'unknown',
|
|
78
|
-
statistics: stats,
|
|
79
|
-
source: { platform: 'evolver', component: 'sync' },
|
|
80
|
-
};
|
|
81
|
-
|
|
82
|
-
fs.writeFileSync(path.join(tmpDir, 'manifest.json'), JSON.stringify(manifest, null, 2) + '\n');
|
|
83
|
-
fs.writeFileSync(path.join(tmpDir, 'checksum.sha256'), checksums.join('\n') + '\n');
|
|
84
|
-
|
|
85
|
-
try {
|
|
86
|
-
// Run tar from inside tmpDir with a relative output path so no absolute
|
|
87
|
-
// Windows paths (e.g. "C:\...") are passed to tar. GNU tar on Windows
|
|
88
|
-
// (Git for Windows) misparses "C:" as a remote hostname when it appears
|
|
89
|
-
// in the -czf argument, causing "Cannot connect to C: resolve failed".
|
|
90
|
-
// Since tmpDir = outputPath + ".tmp" they share the same parent, so the
|
|
91
|
-
// relative output path is always "../<basename>".
|
|
92
|
-
const relOut = path.join('..', path.basename(outputPath));
|
|
93
|
-
execFileSync('tar', ['-czf', relOut, '.'], { cwd: tmpDir, timeout: 60000 });
|
|
94
|
-
} catch (err) {
|
|
95
|
-
fs.rmSync(tmpDir, { recursive: true, force: true });
|
|
96
|
-
throw new Error(`tar failed: ${err.message}. Ensure tar is available on your system.`);
|
|
97
|
-
}
|
|
98
|
-
fs.rmSync(tmpDir, { recursive: true, force: true });
|
|
99
|
-
|
|
100
|
-
return { outputPath, manifest };
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
module.exports = { exportGepx };
|
package/src/gep/privacyClient.js
DELETED
|
@@ -1,235 +0,0 @@
|
|
|
1
|
-
// ---------------------------------------------------------------------------
|
|
2
|
-
// privacyClient -- Hub privacy computing API client.
|
|
3
|
-
// Handles encrypted blob upload, sealed tool registration/execution,
|
|
4
|
-
// status polling, and result retrieval.
|
|
5
|
-
// ---------------------------------------------------------------------------
|
|
6
|
-
|
|
7
|
-
const { getNodeId, buildHubHeaders, buildNodeScopedHubHeaders } = require('./a2aProtocol');
|
|
8
|
-
const { generateKey, encrypt, decrypt, pack, unpack } = require('./crypto');
|
|
9
|
-
const { resolveHubUrl } = require('../config');
|
|
10
|
-
const { hubFetch } = require('./hubFetch');
|
|
11
|
-
|
|
12
|
-
const PRIVACY_TIMEOUT_MS = 15000;
|
|
13
|
-
|
|
14
|
-
function buildPrivacyNodeHeaders() {
|
|
15
|
-
const buildHeaders = buildNodeScopedHubHeaders || buildHubHeaders;
|
|
16
|
-
return buildHeaders();
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
function privacyUrl(path) {
|
|
20
|
-
return `${resolveHubUrl().replace(/\/+$/, '')}/a2a/privacy${path}`;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
function privacyNodeUrl(path) {
|
|
24
|
-
const nodeId = getNodeId();
|
|
25
|
-
if (!nodeId) return null;
|
|
26
|
-
const sep = path.includes('?') ? '&' : '?';
|
|
27
|
-
return privacyUrl(path) + sep + 'node_id=' + encodeURIComponent(nodeId);
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
/**
|
|
31
|
-
* Submit a privacy computing task to Hub.
|
|
32
|
-
* @param {{ title: string, body?: string, signals?: string }} opts
|
|
33
|
-
* @returns {{ taskId: string, status: string } | null}
|
|
34
|
-
*/
|
|
35
|
-
async function submitPrivacyTask(opts) {
|
|
36
|
-
const nodeId = getNodeId();
|
|
37
|
-
if (!nodeId) return null;
|
|
38
|
-
|
|
39
|
-
try {
|
|
40
|
-
const res = await hubFetch(privacyUrl('/submit'), {
|
|
41
|
-
method: 'POST',
|
|
42
|
-
headers: Object.assign({ 'Content-Type': 'application/json' }, buildPrivacyNodeHeaders() || {}),
|
|
43
|
-
body: JSON.stringify({ ...opts, node_id: nodeId }),
|
|
44
|
-
signal: AbortSignal.timeout(PRIVACY_TIMEOUT_MS),
|
|
45
|
-
});
|
|
46
|
-
if (!res.ok) return null;
|
|
47
|
-
return await res.json();
|
|
48
|
-
} catch (err) {
|
|
49
|
-
console.warn('[PrivacyClient] submitPrivacyTask failed:', err?.message || err);
|
|
50
|
-
return null;
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
/**
|
|
55
|
-
* Encrypt data locally and upload the encrypted blob to Hub.
|
|
56
|
-
* Returns the blobId and the local key (caller must store the key).
|
|
57
|
-
* @param {Buffer|string} plaintext
|
|
58
|
-
* @param {{ privacyTaskId: string, label?: string }} opts
|
|
59
|
-
* @returns {{ blobId: string, key: Buffer, iv: Buffer, authTag: Buffer } | null}
|
|
60
|
-
*/
|
|
61
|
-
async function uploadEncryptedBlob(plaintext, opts) {
|
|
62
|
-
const nodeId = getNodeId();
|
|
63
|
-
if (!nodeId || !opts?.privacyTaskId) return null;
|
|
64
|
-
|
|
65
|
-
try {
|
|
66
|
-
const key = generateKey();
|
|
67
|
-
const parts = encrypt(plaintext, key);
|
|
68
|
-
const packed = pack(parts);
|
|
69
|
-
|
|
70
|
-
const body = JSON.stringify({
|
|
71
|
-
node_id: nodeId,
|
|
72
|
-
privacy_task_id: opts.privacyTaskId,
|
|
73
|
-
label: opts.label || 'blob',
|
|
74
|
-
data_base64: packed.toString('base64'),
|
|
75
|
-
encryption: 'aes-256-gcm',
|
|
76
|
-
});
|
|
77
|
-
|
|
78
|
-
const res = await hubFetch(privacyUrl('/blob/upload'), {
|
|
79
|
-
method: 'POST',
|
|
80
|
-
headers: Object.assign({ 'Content-Type': 'application/json' }, buildPrivacyNodeHeaders() || {}),
|
|
81
|
-
body,
|
|
82
|
-
signal: AbortSignal.timeout(PRIVACY_TIMEOUT_MS),
|
|
83
|
-
});
|
|
84
|
-
if (!res.ok) return null;
|
|
85
|
-
const resp = await res.json();
|
|
86
|
-
return {
|
|
87
|
-
blobId: resp.blob_id || resp.blobId,
|
|
88
|
-
key,
|
|
89
|
-
iv: parts.iv,
|
|
90
|
-
authTag: parts.authTag,
|
|
91
|
-
};
|
|
92
|
-
} catch (err) {
|
|
93
|
-
console.warn('[PrivacyClient] uploadEncryptedBlob failed:', err?.message || err);
|
|
94
|
-
return null;
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
/**
|
|
99
|
-
* Execute a sealed tool on a previously uploaded blob.
|
|
100
|
-
* @param {{ toolId: string, blobId: string }} opts
|
|
101
|
-
* @returns {{ resultKey?: string, resultHash?: string, error?: string } | null}
|
|
102
|
-
*/
|
|
103
|
-
async function executeSealedTool(opts) {
|
|
104
|
-
const nodeId = getNodeId();
|
|
105
|
-
if (!nodeId || !opts?.toolId || !opts?.blobId) return null;
|
|
106
|
-
|
|
107
|
-
try {
|
|
108
|
-
const res = await hubFetch(privacyUrl('/tool/execute'), {
|
|
109
|
-
method: 'POST',
|
|
110
|
-
headers: Object.assign({ 'Content-Type': 'application/json' }, buildPrivacyNodeHeaders() || {}),
|
|
111
|
-
body: JSON.stringify({
|
|
112
|
-
toolId: opts.toolId,
|
|
113
|
-
blobId: opts.blobId,
|
|
114
|
-
node_id: nodeId,
|
|
115
|
-
}),
|
|
116
|
-
signal: AbortSignal.timeout(30000),
|
|
117
|
-
});
|
|
118
|
-
if (!res.ok) {
|
|
119
|
-
const errBody = await res.json().catch(() => ({}));
|
|
120
|
-
return { error: errBody.error || `http_${res.status}` };
|
|
121
|
-
}
|
|
122
|
-
return await res.json();
|
|
123
|
-
} catch (err) {
|
|
124
|
-
console.warn('[PrivacyClient] executeSealedTool failed:', err?.message || err);
|
|
125
|
-
return { error: err?.message || 'network_error' };
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
/**
|
|
130
|
-
* Check status of a privacy task.
|
|
131
|
-
* @param {string} taskId
|
|
132
|
-
* @returns {{ status: string, progress?: number } | null}
|
|
133
|
-
*/
|
|
134
|
-
async function getPrivacyStatus(taskId) {
|
|
135
|
-
if (!taskId) return null;
|
|
136
|
-
try {
|
|
137
|
-
const url = privacyNodeUrl(`/status/${encodeURIComponent(taskId)}`);
|
|
138
|
-
if (!url) return null;
|
|
139
|
-
const res = await hubFetch(url, {
|
|
140
|
-
headers: buildPrivacyNodeHeaders(),
|
|
141
|
-
signal: AbortSignal.timeout(PRIVACY_TIMEOUT_MS),
|
|
142
|
-
});
|
|
143
|
-
if (!res.ok) return null;
|
|
144
|
-
return await res.json();
|
|
145
|
-
} catch {
|
|
146
|
-
return null;
|
|
147
|
-
}
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
/**
|
|
151
|
-
* Retrieve the encrypted result of a privacy task and decrypt it locally.
|
|
152
|
-
* @param {string} taskId
|
|
153
|
-
* @param {Buffer} key - the original encryption key
|
|
154
|
-
* @returns {{ plaintext: Buffer, resultHash?: string } | null}
|
|
155
|
-
*/
|
|
156
|
-
async function getPrivacyResult(taskId, key) {
|
|
157
|
-
if (!taskId || !key) return null;
|
|
158
|
-
try {
|
|
159
|
-
const url = privacyNodeUrl(`/result/${encodeURIComponent(taskId)}`);
|
|
160
|
-
if (!url) return null;
|
|
161
|
-
const res = await hubFetch(url, {
|
|
162
|
-
headers: buildPrivacyNodeHeaders(),
|
|
163
|
-
signal: AbortSignal.timeout(PRIVACY_TIMEOUT_MS),
|
|
164
|
-
});
|
|
165
|
-
if (!res.ok) return null;
|
|
166
|
-
const data = await res.json();
|
|
167
|
-
if (!data.encrypted_result_base64) return null;
|
|
168
|
-
|
|
169
|
-
const packed = Buffer.from(data.encrypted_result_base64, 'base64');
|
|
170
|
-
const parts = unpack(packed);
|
|
171
|
-
const plaintext = decrypt(parts.ciphertext, key, parts.iv, parts.authTag);
|
|
172
|
-
return { plaintext, resultHash: data.result_hash };
|
|
173
|
-
} catch (err) {
|
|
174
|
-
console.warn('[PrivacyClient] getPrivacyResult failed:', err?.message || err);
|
|
175
|
-
return null;
|
|
176
|
-
}
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
/**
|
|
180
|
-
* List available sealed tool templates.
|
|
181
|
-
* @returns {Array | null}
|
|
182
|
-
*/
|
|
183
|
-
async function getToolTemplates() {
|
|
184
|
-
try {
|
|
185
|
-
const url = privacyNodeUrl('/tool/templates');
|
|
186
|
-
if (!url) return null;
|
|
187
|
-
const res = await hubFetch(url, {
|
|
188
|
-
headers: buildPrivacyNodeHeaders(),
|
|
189
|
-
signal: AbortSignal.timeout(PRIVACY_TIMEOUT_MS),
|
|
190
|
-
});
|
|
191
|
-
if (!res.ok) return null;
|
|
192
|
-
const data = await res.json();
|
|
193
|
-
return data.templates || data;
|
|
194
|
-
} catch {
|
|
195
|
-
return null;
|
|
196
|
-
}
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
/**
|
|
200
|
-
* Parse [PRIVACY_PARAMS] block from task body.
|
|
201
|
-
* Returns { tool_id, blob_ids[] } or null if no block found.
|
|
202
|
-
* @param {string} body
|
|
203
|
-
* @returns {{ toolId: string, blobIds: string[] } | null}
|
|
204
|
-
*/
|
|
205
|
-
function parsePrivacyParams(body) {
|
|
206
|
-
if (!body || typeof body !== 'string') return null;
|
|
207
|
-
const start = body.indexOf('[PRIVACY_PARAMS]');
|
|
208
|
-
const end = body.indexOf('[/PRIVACY_PARAMS]');
|
|
209
|
-
if (start === -1 || end === -1 || end <= start) return null;
|
|
210
|
-
|
|
211
|
-
const block = body.substring(start + '[PRIVACY_PARAMS]'.length, end).trim();
|
|
212
|
-
const lines = block.split('\n').map(l => l.trim()).filter(Boolean);
|
|
213
|
-
const params = {};
|
|
214
|
-
for (const line of lines) {
|
|
215
|
-
const colon = line.indexOf(':');
|
|
216
|
-
if (colon === -1) continue;
|
|
217
|
-
const key = line.substring(0, colon).trim();
|
|
218
|
-
const val = line.substring(colon + 1).trim();
|
|
219
|
-
params[key] = val;
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
if (!params.tool_id) return null;
|
|
223
|
-
const blobIds = (params.blob_ids || '').split(',').map(s => s.trim()).filter(Boolean);
|
|
224
|
-
return { toolId: params.tool_id, blobIds };
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
module.exports = {
|
|
228
|
-
submitPrivacyTask,
|
|
229
|
-
uploadEncryptedBlob,
|
|
230
|
-
executeSealedTool,
|
|
231
|
-
getPrivacyStatus,
|
|
232
|
-
getPrivacyResult,
|
|
233
|
-
getToolTemplates,
|
|
234
|
-
parsePrivacyParams,
|
|
235
|
-
};
|