@evomap/evolver 1.29.0 → 1.29.2
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/index.js +51 -0
- package/package.json +1 -1
- package/src/gep/a2aProtocol.js +8 -5
- package/src/gep/envFingerprint.js +16 -1
- package/src/gep/skillDistiller.js +17 -1
- package/src/gep/skillPublisher.js +158 -0
package/index.js
CHANGED
|
@@ -24,6 +24,37 @@ function readJsonSafe(p) {
|
|
|
24
24
|
}
|
|
25
25
|
}
|
|
26
26
|
|
|
27
|
+
function rejectPendingRun(statePath) {
|
|
28
|
+
try {
|
|
29
|
+
const { getRepoRoot } = require('./src/gep/paths');
|
|
30
|
+
const { execSync } = require('child_process');
|
|
31
|
+
const repoRoot = getRepoRoot();
|
|
32
|
+
|
|
33
|
+
execSync('git checkout -- .', { cwd: repoRoot, encoding: 'utf8', timeout: 30000 });
|
|
34
|
+
execSync('git clean -fd', { cwd: repoRoot, encoding: 'utf8', timeout: 30000 });
|
|
35
|
+
} catch (e) {
|
|
36
|
+
console.warn('[Loop] Pending run rollback failed: ' + (e.message || e));
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
try {
|
|
40
|
+
const state = readJsonSafe(statePath);
|
|
41
|
+
if (state && state.last_run && state.last_run.run_id) {
|
|
42
|
+
state.last_solidify = {
|
|
43
|
+
run_id: state.last_run.run_id,
|
|
44
|
+
rejected: true,
|
|
45
|
+
reason: 'loop_bridge_disabled_autoreject',
|
|
46
|
+
timestamp: new Date().toISOString(),
|
|
47
|
+
};
|
|
48
|
+
fs.writeFileSync(statePath, JSON.stringify(state, null, 2) + '\n', 'utf8');
|
|
49
|
+
return true;
|
|
50
|
+
}
|
|
51
|
+
} catch (e) {
|
|
52
|
+
console.warn('[Loop] Failed to clear pending run state: ' + (e.message || e));
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
return false;
|
|
56
|
+
}
|
|
57
|
+
|
|
27
58
|
function isPendingSolidify(state) {
|
|
28
59
|
const lastRun = state && state.last_run ? state.last_run : null;
|
|
29
60
|
const lastSolid = state && state.last_solidify ? state.last_solidify : null;
|
|
@@ -80,6 +111,16 @@ async function main() {
|
|
|
80
111
|
const isLoop = args.includes('--loop') || args.includes('--mad-dog');
|
|
81
112
|
|
|
82
113
|
if (command === 'run' || command === '/evolve' || isLoop) {
|
|
114
|
+
if (isLoop) {
|
|
115
|
+
const originalLog = console.log;
|
|
116
|
+
const originalWarn = console.warn;
|
|
117
|
+
const originalError = console.error;
|
|
118
|
+
function ts() { return '[' + new Date().toISOString() + ']'; }
|
|
119
|
+
console.log = (...args) => { originalLog.call(console, ts(), ...args); };
|
|
120
|
+
console.warn = (...args) => { originalWarn.call(console, ts(), ...args); };
|
|
121
|
+
console.error = (...args) => { originalError.call(console, ts(), ...args); };
|
|
122
|
+
}
|
|
123
|
+
|
|
83
124
|
console.log('Starting capability evolver...');
|
|
84
125
|
|
|
85
126
|
if (isLoop) {
|
|
@@ -137,6 +178,16 @@ async function main() {
|
|
|
137
178
|
try {
|
|
138
179
|
await evolve.run();
|
|
139
180
|
ok = true;
|
|
181
|
+
|
|
182
|
+
if (String(process.env.EVOLVE_BRIDGE || '').toLowerCase() === 'false') {
|
|
183
|
+
const stAfterRun = readJsonSafe(solidifyStatePath);
|
|
184
|
+
if (isPendingSolidify(stAfterRun)) {
|
|
185
|
+
const cleared = rejectPendingRun(solidifyStatePath);
|
|
186
|
+
if (cleared) {
|
|
187
|
+
console.warn('[Loop] Auto-rejected pending run because bridge is disabled in loop mode.');
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
}
|
|
140
191
|
} catch (error) {
|
|
141
192
|
const msg = error && error.message ? String(error.message) : String(error);
|
|
142
193
|
console.error(`Evolution cycle failed: ${msg}`);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@evomap/evolver",
|
|
3
|
-
"version": "1.29.
|
|
3
|
+
"version": "1.29.2",
|
|
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": {
|
package/src/gep/a2aProtocol.js
CHANGED
|
@@ -172,20 +172,23 @@ function buildPublishBundle(opts) {
|
|
|
172
172
|
if (!capsule || capsule.type !== 'Capsule' || !capsule.id) {
|
|
173
173
|
throw new Error('publishBundle: capsule must be a valid Capsule with type and id');
|
|
174
174
|
}
|
|
175
|
-
var geneAssetId = gene.asset_id || computeAssetId(gene);
|
|
176
|
-
var capsuleAssetId = capsule.asset_id || computeAssetId(capsule);
|
|
177
|
-
var nodeSecret = process.env.A2A_NODE_SECRET || getNodeId();
|
|
178
|
-
var signatureInput = [geneAssetId, capsuleAssetId].sort().join('|');
|
|
179
|
-
var signature = crypto.createHmac('sha256', nodeSecret).update(signatureInput).digest('hex');
|
|
180
175
|
if (o.modelName && typeof o.modelName === 'string') {
|
|
181
176
|
gene.model_name = o.modelName;
|
|
182
177
|
capsule.model_name = o.modelName;
|
|
183
178
|
}
|
|
179
|
+
gene.asset_id = computeAssetId(gene);
|
|
180
|
+
capsule.asset_id = computeAssetId(capsule);
|
|
181
|
+
var geneAssetId = gene.asset_id;
|
|
182
|
+
var capsuleAssetId = capsule.asset_id;
|
|
183
|
+
var nodeSecret = process.env.A2A_NODE_SECRET || getNodeId();
|
|
184
|
+
var signatureInput = [geneAssetId, capsuleAssetId].sort().join('|');
|
|
185
|
+
var signature = crypto.createHmac('sha256', nodeSecret).update(signatureInput).digest('hex');
|
|
184
186
|
var assets = [gene, capsule];
|
|
185
187
|
if (event && event.type === 'EvolutionEvent') {
|
|
186
188
|
if (o.modelName && typeof o.modelName === 'string') {
|
|
187
189
|
event.model_name = o.modelName;
|
|
188
190
|
}
|
|
191
|
+
event.asset_id = computeAssetId(event);
|
|
189
192
|
assets.push(event);
|
|
190
193
|
}
|
|
191
194
|
var publishPayload = {
|
|
@@ -15,13 +15,28 @@ function captureEnvFingerprint() {
|
|
|
15
15
|
const repoRoot = getRepoRoot();
|
|
16
16
|
let pkgVersion = null;
|
|
17
17
|
let pkgName = null;
|
|
18
|
+
|
|
19
|
+
// Read evolver's own package.json via __dirname so that npm-installed
|
|
20
|
+
// deployments report the correct evolver version. getRepoRoot() walks
|
|
21
|
+
// up to the nearest .git directory, which resolves to the HOST project
|
|
22
|
+
// when evolver is an npm dependency -- producing a wrong name/version.
|
|
23
|
+
const ownPkgPath = path.resolve(__dirname, '..', '..', 'package.json');
|
|
18
24
|
try {
|
|
19
|
-
const raw = fs.readFileSync(
|
|
25
|
+
const raw = fs.readFileSync(ownPkgPath, 'utf8');
|
|
20
26
|
const pkg = JSON.parse(raw);
|
|
21
27
|
pkgVersion = pkg && pkg.version ? String(pkg.version) : null;
|
|
22
28
|
pkgName = pkg && pkg.name ? String(pkg.name) : null;
|
|
23
29
|
} catch (e) {}
|
|
24
30
|
|
|
31
|
+
if (!pkgVersion) {
|
|
32
|
+
try {
|
|
33
|
+
const raw = fs.readFileSync(path.join(repoRoot, 'package.json'), 'utf8');
|
|
34
|
+
const pkg = JSON.parse(raw);
|
|
35
|
+
pkgVersion = pkg && pkg.version ? String(pkg.version) : null;
|
|
36
|
+
pkgName = pkg && pkg.name ? String(pkg.name) : null;
|
|
37
|
+
} catch (e) {}
|
|
38
|
+
}
|
|
39
|
+
|
|
25
40
|
const region = (process.env.EVOLVER_REGION || '').trim().toLowerCase().slice(0, 5) || undefined;
|
|
26
41
|
|
|
27
42
|
return {
|
|
@@ -223,7 +223,7 @@ function buildDistillationPrompt(analysis, existingGenes, sampleCapsules) {
|
|
|
223
223
|
});
|
|
224
224
|
|
|
225
225
|
return [
|
|
226
|
-
'You are a Gene synthesis engine for the GEP (
|
|
226
|
+
'You are a Gene synthesis engine for the GEP (Gene Expression Protocol).',
|
|
227
227
|
'',
|
|
228
228
|
'Analyze the following successful evolution capsules and extract a reusable Gene.',
|
|
229
229
|
'',
|
|
@@ -476,6 +476,22 @@ function completeDistillation(responseText) {
|
|
|
476
476
|
try { if (request.prompt_path) fs.unlinkSync(request.prompt_path); } catch (e) {}
|
|
477
477
|
|
|
478
478
|
console.log('[Distiller] Distillation complete. New gene: ' + gene.id);
|
|
479
|
+
|
|
480
|
+
if (process.env.SKILL_AUTO_PUBLISH !== '0') {
|
|
481
|
+
try {
|
|
482
|
+
var skillPublisher = require('./skillPublisher');
|
|
483
|
+
skillPublisher.publishSkillToHub(gene).then(function (res) {
|
|
484
|
+
if (res.ok) {
|
|
485
|
+
console.log('[Distiller] Skill published to Hub: ' + (res.result?.skill_id || gene.id));
|
|
486
|
+
} else {
|
|
487
|
+
console.warn('[Distiller] Skill publish failed: ' + (res.error || 'unknown'));
|
|
488
|
+
}
|
|
489
|
+
}).catch(function () {});
|
|
490
|
+
} catch (e) {
|
|
491
|
+
console.warn('[Distiller] Skill publisher unavailable: ' + e.message);
|
|
492
|
+
}
|
|
493
|
+
}
|
|
494
|
+
|
|
479
495
|
return { ok: true, gene: gene };
|
|
480
496
|
}
|
|
481
497
|
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var { getHubUrl, buildHubHeaders, getNodeId } = require('./a2aProtocol');
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Convert a Gene object into SKILL.md format (Claude/Anthropic style).
|
|
7
|
+
*
|
|
8
|
+
* @param {object} gene - Gene asset
|
|
9
|
+
* @returns {string} SKILL.md content
|
|
10
|
+
*/
|
|
11
|
+
function geneToSkillMd(gene) {
|
|
12
|
+
var name = (gene.id || 'unnamed-skill').replace(/^gene_distilled_/, '').replace(/_/g, '-');
|
|
13
|
+
var desc = gene.summary || 'AI agent skill distilled from evolution experience.';
|
|
14
|
+
|
|
15
|
+
var lines = [
|
|
16
|
+
'---',
|
|
17
|
+
'name: ' + name,
|
|
18
|
+
'description: ' + desc,
|
|
19
|
+
'---',
|
|
20
|
+
'',
|
|
21
|
+
'# ' + name,
|
|
22
|
+
'',
|
|
23
|
+
];
|
|
24
|
+
|
|
25
|
+
if (gene.signals_match && gene.signals_match.length > 0) {
|
|
26
|
+
lines.push('## Trigger Signals');
|
|
27
|
+
lines.push('');
|
|
28
|
+
gene.signals_match.forEach(function (s) {
|
|
29
|
+
lines.push('- `' + s + '`');
|
|
30
|
+
});
|
|
31
|
+
lines.push('');
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
if (gene.preconditions && gene.preconditions.length > 0) {
|
|
35
|
+
lines.push('## Preconditions');
|
|
36
|
+
lines.push('');
|
|
37
|
+
gene.preconditions.forEach(function (p) {
|
|
38
|
+
lines.push('- ' + p);
|
|
39
|
+
});
|
|
40
|
+
lines.push('');
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
if (gene.strategy && gene.strategy.length > 0) {
|
|
44
|
+
lines.push('## Strategy');
|
|
45
|
+
lines.push('');
|
|
46
|
+
gene.strategy.forEach(function (step, i) {
|
|
47
|
+
lines.push((i + 1) + '. ' + step);
|
|
48
|
+
});
|
|
49
|
+
lines.push('');
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
if (gene.constraints) {
|
|
53
|
+
lines.push('## Constraints');
|
|
54
|
+
lines.push('');
|
|
55
|
+
if (gene.constraints.max_files) {
|
|
56
|
+
lines.push('- Max files: ' + gene.constraints.max_files);
|
|
57
|
+
}
|
|
58
|
+
if (gene.constraints.forbidden_paths && gene.constraints.forbidden_paths.length > 0) {
|
|
59
|
+
lines.push('- Forbidden paths: ' + gene.constraints.forbidden_paths.join(', '));
|
|
60
|
+
}
|
|
61
|
+
lines.push('');
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
if (gene.validation && gene.validation.length > 0) {
|
|
65
|
+
lines.push('## Validation');
|
|
66
|
+
lines.push('');
|
|
67
|
+
gene.validation.forEach(function (cmd) {
|
|
68
|
+
lines.push('```bash');
|
|
69
|
+
lines.push(cmd);
|
|
70
|
+
lines.push('```');
|
|
71
|
+
lines.push('');
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
return lines.join('\n');
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Publish a Gene as a Skill to the Hub skill store.
|
|
80
|
+
*
|
|
81
|
+
* @param {object} gene - Gene asset
|
|
82
|
+
* @param {object} [opts] - { category, tags }
|
|
83
|
+
* @returns {Promise<{ok: boolean, result?: object, error?: string}>}
|
|
84
|
+
*/
|
|
85
|
+
function publishSkillToHub(gene, opts) {
|
|
86
|
+
opts = opts || {};
|
|
87
|
+
var hubUrl = getHubUrl();
|
|
88
|
+
if (!hubUrl) return Promise.resolve({ ok: false, error: 'no_hub_url' });
|
|
89
|
+
|
|
90
|
+
var content = geneToSkillMd(gene);
|
|
91
|
+
var nodeId = getNodeId();
|
|
92
|
+
var skillId = 'skill_' + (gene.id || 'unnamed').replace(/^gene_/, '');
|
|
93
|
+
|
|
94
|
+
var body = {
|
|
95
|
+
sender_id: nodeId,
|
|
96
|
+
skill_id: skillId,
|
|
97
|
+
content: content,
|
|
98
|
+
category: opts.category || gene.category || null,
|
|
99
|
+
tags: opts.tags || gene.signals_match || [],
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
var endpoint = hubUrl.replace(/\/+$/, '') + '/a2a/skill/store/publish';
|
|
103
|
+
|
|
104
|
+
return fetch(endpoint, {
|
|
105
|
+
method: 'POST',
|
|
106
|
+
headers: buildHubHeaders(),
|
|
107
|
+
body: JSON.stringify(body),
|
|
108
|
+
signal: AbortSignal.timeout(15000),
|
|
109
|
+
})
|
|
110
|
+
.then(function (res) { return res.json().then(function (data) { return { status: res.status, data: data }; }); })
|
|
111
|
+
.then(function (result) {
|
|
112
|
+
if (result.status === 201 || result.status === 200) {
|
|
113
|
+
return { ok: true, result: result.data };
|
|
114
|
+
}
|
|
115
|
+
if (result.status === 409) {
|
|
116
|
+
return updateSkillOnHub(nodeId, skillId, content, opts, gene);
|
|
117
|
+
}
|
|
118
|
+
return { ok: false, error: result.data?.error || 'publish_failed', status: result.status };
|
|
119
|
+
})
|
|
120
|
+
.catch(function (err) {
|
|
121
|
+
return { ok: false, error: err.message };
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* Update an existing Skill on the Hub (new version).
|
|
127
|
+
*/
|
|
128
|
+
function updateSkillOnHub(nodeId, skillId, content, opts, gene) {
|
|
129
|
+
var hubUrl = getHubUrl();
|
|
130
|
+
if (!hubUrl) return Promise.resolve({ ok: false, error: 'no_hub_url' });
|
|
131
|
+
|
|
132
|
+
var body = {
|
|
133
|
+
sender_id: nodeId,
|
|
134
|
+
skill_id: skillId,
|
|
135
|
+
content: content,
|
|
136
|
+
category: opts.category || gene.category || null,
|
|
137
|
+
tags: opts.tags || gene.signals_match || [],
|
|
138
|
+
changelog: 'Iterative evolution update',
|
|
139
|
+
};
|
|
140
|
+
|
|
141
|
+
var endpoint = hubUrl.replace(/\/+$/, '') + '/a2a/skill/store/update';
|
|
142
|
+
|
|
143
|
+
return fetch(endpoint, {
|
|
144
|
+
method: 'PUT',
|
|
145
|
+
headers: buildHubHeaders(),
|
|
146
|
+
body: JSON.stringify(body),
|
|
147
|
+
signal: AbortSignal.timeout(15000),
|
|
148
|
+
})
|
|
149
|
+
.then(function (res) { return res.json(); })
|
|
150
|
+
.then(function (data) { return { ok: true, result: data }; })
|
|
151
|
+
.catch(function (err) { return { ok: false, error: err.message }; });
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
module.exports = {
|
|
155
|
+
geneToSkillMd: geneToSkillMd,
|
|
156
|
+
publishSkillToHub: publishSkillToHub,
|
|
157
|
+
updateSkillOnHub: updateSkillOnHub,
|
|
158
|
+
};
|