@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 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.0",
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": {
@@ -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(path.join(repoRoot, 'package.json'), 'utf8');
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 (Genome Evolution Protocol).',
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
+ };