@evomap/evolver 1.90.0 → 2.0.0-beta.1

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.
Files changed (231) hide show
  1. package/README.md +27 -564
  2. package/bin/evolver-llm-proxy.js +3 -0
  3. package/bin/evolver-mcp.js +2 -0
  4. package/bin/evolver-proxy.js +3 -0
  5. package/bin/evolver.js +4 -0
  6. package/index.js +1 -3670
  7. package/package.json +32 -62
  8. package/CONTRIBUTING.md +0 -19
  9. package/LICENSE +0 -641
  10. package/README.ja-JP.md +0 -521
  11. package/README.ko-KR.md +0 -520
  12. package/README.zh-CN.md +0 -531
  13. package/SKILL.md +0 -365
  14. package/assets/cover.png +0 -0
  15. package/assets/gep/genes.seed.json +0 -496
  16. package/conformance/savings-core/constants.json +0 -30
  17. package/conformance/savings-core/golden-vectors.json +0 -333
  18. package/scripts/a2a_export.js +0 -63
  19. package/scripts/a2a_ingest.js +0 -79
  20. package/scripts/a2a_promote.js +0 -118
  21. package/scripts/analyze_by_skill.js +0 -121
  22. package/scripts/build_binaries.js +0 -479
  23. package/scripts/check-changelog.js +0 -166
  24. package/scripts/extract_log.js +0 -85
  25. package/scripts/generate_history.js +0 -75
  26. package/scripts/gep_append_event.js +0 -96
  27. package/scripts/gep_personality_report.js +0 -234
  28. package/scripts/human_report.js +0 -147
  29. package/scripts/recall-verify-report.js +0 -234
  30. package/scripts/recover_loop.js +0 -61
  31. package/scripts/refresh_stars_badge.js +0 -168
  32. package/scripts/seed-merchants.js +0 -91
  33. package/scripts/skill2recipes.js +0 -118
  34. package/scripts/suggest_version.js +0 -89
  35. package/scripts/validate-modules.js +0 -38
  36. package/scripts/validate-suite.js +0 -78
  37. package/src/adapters/claudeCode.js +0 -194
  38. package/src/adapters/codex.js +0 -216
  39. package/src/adapters/cursor.js +0 -91
  40. package/src/adapters/hookAdapter.js +0 -469
  41. package/src/adapters/kiro.js +0 -195
  42. package/src/adapters/opencode.js +0 -326
  43. package/src/adapters/scripts/_lockPaths.js +0 -74
  44. package/src/adapters/scripts/_memoryFiltering.js +0 -35
  45. package/src/adapters/scripts/_runtimePaths.js +0 -440
  46. package/src/adapters/scripts/evolver-session-end.js +0 -321
  47. package/src/adapters/scripts/evolver-session-start.js +0 -587
  48. package/src/adapters/scripts/evolver-signal-detect.js +0 -98
  49. package/src/adapters/scripts/evolver-task-recall.js +0 -173
  50. package/src/atp/atpExecute.js +0 -283
  51. package/src/atp/atpTaskPickup.js +0 -233
  52. package/src/atp/autoBuyer.js +0 -382
  53. package/src/atp/autoDeliver.js +0 -215
  54. package/src/atp/cli.js +0 -354
  55. package/src/atp/cliAutobuyPrompt.js +0 -154
  56. package/src/atp/consumerAgent.js +0 -157
  57. package/src/atp/defaultHandler.js +0 -69
  58. package/src/atp/heartbeatSignalsHandler.js +0 -254
  59. package/src/atp/hubClient.js +0 -317
  60. package/src/atp/index.js +0 -38
  61. package/src/atp/merchantAgent.js +0 -118
  62. package/src/atp/protocol.js +0 -41
  63. package/src/atp/questionComposer.js +0 -133
  64. package/src/atp/serviceHelper.js +0 -92
  65. package/src/canary.js +0 -13
  66. package/src/config.js +0 -351
  67. package/src/evolve/guards.js +0 -1
  68. package/src/evolve/pipeline/collect.js +0 -1
  69. package/src/evolve/pipeline/dispatch.js +0 -1
  70. package/src/evolve/pipeline/enrich.js +0 -1
  71. package/src/evolve/pipeline/hub.js +0 -1
  72. package/src/evolve/pipeline/select.js +0 -1
  73. package/src/evolve/pipeline/signals.js +0 -1
  74. package/src/evolve/utils.js +0 -1
  75. package/src/evolve.js +0 -1
  76. package/src/experiment/agentRunner.js +0 -229
  77. package/src/experiment/cli.js +0 -159
  78. package/src/experiment/comparison.js +0 -233
  79. package/src/experiment/metrics.js +0 -75
  80. package/src/forceUpdate.js +0 -991
  81. package/src/gep/a2a.js +0 -173
  82. package/src/gep/a2aProtocol.js +0 -1
  83. package/src/gep/analyzer.js +0 -35
  84. package/src/gep/antiAbuseTelemetry.js +0 -1
  85. package/src/gep/assetCallLog.js +0 -197
  86. package/src/gep/assetStore.js +0 -723
  87. package/src/gep/assets.js +0 -36
  88. package/src/gep/autoDistillConv.js +0 -1
  89. package/src/gep/autoDistillLlm.js +0 -1
  90. package/src/gep/bridge.js +0 -138
  91. package/src/gep/candidateEval.js +0 -1
  92. package/src/gep/candidates.js +0 -1
  93. package/src/gep/claimNudge.js +0 -121
  94. package/src/gep/cliContracts.js +0 -1190
  95. package/src/gep/contentHash.js +0 -1
  96. package/src/gep/conversationDistiller.js +0 -1
  97. package/src/gep/conversationSniffer.js +0 -1
  98. package/src/gep/crypto.js +0 -1
  99. package/src/gep/curriculum.js +0 -1
  100. package/src/gep/deviceId.js +0 -1
  101. package/src/gep/directoryClient.js +0 -115
  102. package/src/gep/envFingerprint.js +0 -1
  103. package/src/gep/epigenetics.js +0 -1
  104. package/src/gep/execBridge.js +0 -1
  105. package/src/gep/executionTrace.js +0 -291
  106. package/src/gep/explore.js +0 -1
  107. package/src/gep/featureFlags.js +0 -121
  108. package/src/gep/gitOps.js +0 -265
  109. package/src/gep/hash.js +0 -1
  110. package/src/gep/hostErrorClassifier.js +0 -34
  111. package/src/gep/hubFetch.js +0 -1
  112. package/src/gep/hubReview.js +0 -1
  113. package/src/gep/hubSearch.js +0 -1
  114. package/src/gep/hubVerify.js +0 -1
  115. package/src/gep/idleScheduler.js +0 -400
  116. package/src/gep/issueReporter.js +0 -416
  117. package/src/gep/learningSignals.js +0 -1
  118. package/src/gep/llmReview.js +0 -92
  119. package/src/gep/localStateAwareness.js +0 -243
  120. package/src/gep/mailboxTransport.js +0 -119
  121. package/src/gep/memoryGraph.js +0 -1
  122. package/src/gep/memoryGraphAdapter.js +0 -1
  123. package/src/gep/mutation.js +0 -1
  124. package/src/gep/narrativeMemory.js +0 -1
  125. package/src/gep/oauthLogin.js +0 -181
  126. package/src/gep/openPRRegistry.js +0 -1
  127. package/src/gep/paths.js +0 -522
  128. package/src/gep/personality.js +0 -1
  129. package/src/gep/policyCheck.js +0 -1
  130. package/src/gep/portable.js +0 -103
  131. package/src/gep/privacyClient.js +0 -235
  132. package/src/gep/prompt.js +0 -1
  133. package/src/gep/questionGenerator.js +0 -518
  134. package/src/gep/recallInject.js +0 -1
  135. package/src/gep/recallVerifier.js +0 -1
  136. package/src/gep/reflection.js +0 -1
  137. package/src/gep/sanitize.js +0 -264
  138. package/src/gep/savingsCore.js +0 -1
  139. package/src/gep/schemas/capsule.js +0 -170
  140. package/src/gep/schemas/gene.js +0 -154
  141. package/src/gep/schemas/index.js +0 -8
  142. package/src/gep/schemas/protocol.js +0 -51
  143. package/src/gep/schemas/task.js +0 -74
  144. package/src/gep/selector.js +0 -1
  145. package/src/gep/selfPR.js +0 -469
  146. package/src/gep/signals.js +0 -776
  147. package/src/gep/skill2gep.js +0 -1056
  148. package/src/gep/skill2gepAudit.js +0 -303
  149. package/src/gep/skill2recipes.js +0 -511
  150. package/src/gep/skillDistiller.js +0 -1
  151. package/src/gep/skillPublisher.js +0 -358
  152. package/src/gep/solidify.js +0 -1
  153. package/src/gep/strategy.js +0 -1
  154. package/src/gep/taskReceiver.js +0 -575
  155. package/src/gep/tokenSavings.js +0 -1
  156. package/src/gep/trajectoryExport.js +0 -1
  157. package/src/gep/validationReport.js +0 -55
  158. package/src/gep/validator/index.js +0 -411
  159. package/src/gep/validator/reporter.js +0 -210
  160. package/src/gep/validator/sandboxExecutor.js +0 -480
  161. package/src/gep/validator/stakeBootstrap.js +0 -357
  162. package/src/gep/workspaceKeychain.js +0 -1
  163. package/src/ops/cleanup.js +0 -80
  164. package/src/ops/commentary.js +0 -60
  165. package/src/ops/health_check.js +0 -104
  166. package/src/ops/index.js +0 -11
  167. package/src/ops/innovation.js +0 -67
  168. package/src/ops/lifecycle.js +0 -798
  169. package/src/ops/self_repair.js +0 -76
  170. package/src/ops/skills_monitor.js +0 -147
  171. package/src/ops/trigger.js +0 -33
  172. package/src/proxy/clientSettings.js +0 -405
  173. package/src/proxy/envelope.js +0 -59
  174. package/src/proxy/extensions/dmHandler.js +0 -45
  175. package/src/proxy/extensions/sessionHandler.js +0 -141
  176. package/src/proxy/extensions/skillUpdater.js +0 -64
  177. package/src/proxy/extensions/traceControl.js +0 -1
  178. package/src/proxy/index.js +0 -1395
  179. package/src/proxy/inject.js +0 -1
  180. package/src/proxy/lifecycle/manager.js +0 -1568
  181. package/src/proxy/mailbox/state.js +0 -207
  182. package/src/proxy/mailbox/store.js +0 -602
  183. package/src/proxy/router/cache_passthrough.js +0 -26
  184. package/src/proxy/router/features.js +0 -84
  185. package/src/proxy/router/gemini_route.js +0 -154
  186. package/src/proxy/router/messages_route.js +0 -535
  187. package/src/proxy/router/model_router.js +0 -113
  188. package/src/proxy/router/models_route.js +0 -52
  189. package/src/proxy/router/ollama_route.js +0 -103
  190. package/src/proxy/router/responses_route.js +0 -170
  191. package/src/proxy/router/vertex_route.js +0 -110
  192. package/src/proxy/server/http.js +0 -363
  193. package/src/proxy/server/routes.js +0 -558
  194. package/src/proxy/server/settings.js +0 -115
  195. package/src/proxy/sync/engine.js +0 -179
  196. package/src/proxy/sync/inbound.js +0 -211
  197. package/src/proxy/sync/outbound.js +0 -361
  198. package/src/proxy/task/monitor.js +0 -131
  199. package/src/proxy/trace/extractor.js +0 -1
  200. package/src/proxy/trace/usage.js +0 -1
  201. package/src/solo/breaker.js +0 -25
  202. package/src/solo/gitGuard.js +0 -65
  203. package/src/webui/client/clientJs/assets.js +0 -111
  204. package/src/webui/client/clientJs/bootstrap.js +0 -92
  205. package/src/webui/client/clientJs/common.js +0 -77
  206. package/src/webui/client/clientJs/i18n.js +0 -366
  207. package/src/webui/client/clientJs/index.js +0 -35
  208. package/src/webui/client/clientJs/interactions.js +0 -351
  209. package/src/webui/client/clientJs/overview.js +0 -152
  210. package/src/webui/client/clientJs/personality.js +0 -285
  211. package/src/webui/client/clientJs/pipelines.js +0 -330
  212. package/src/webui/client/indexHtml.js +0 -221
  213. package/src/webui/client/static.js +0 -23
  214. package/src/webui/client/stylesCss.js +0 -639
  215. package/src/webui/client/vendor/README.md +0 -15
  216. package/src/webui/client/vendor/echarts.min.js +0 -45
  217. package/src/webui/index.js +0 -14
  218. package/src/webui/observer/assets.js +0 -146
  219. package/src/webui/observer/index.js +0 -37
  220. package/src/webui/observer/interactions.js +0 -127
  221. package/src/webui/observer/jsonl.js +0 -75
  222. package/src/webui/observer/paths.js +0 -46
  223. package/src/webui/observer/personality.js +0 -43
  224. package/src/webui/observer/pipelineEvents.js +0 -58
  225. package/src/webui/observer/redact.js +0 -63
  226. package/src/webui/observer/runs.js +0 -356
  227. package/src/webui/observer/safety.js +0 -57
  228. package/src/webui/observer/skills.js +0 -70
  229. package/src/webui/observer/status.js +0 -71
  230. package/src/webui/server/http.js +0 -138
  231. package/src/webui/server/routes.js +0 -41
@@ -1,356 +0,0 @@
1
- 'use strict';
2
-
3
- const { getObserverPaths } = require('./paths');
4
- const { readJsonSafe, readJsonl, paginate } = require('./jsonl');
5
- const { redactValue } = require('./redact');
6
- const { readPipelineEvents } = require('./pipelineEvents');
7
-
8
- const PHASE_ORDER = [
9
- 'detect_signals',
10
- 'select_gene',
11
- 'asset_search',
12
- 'mutate_strategy',
13
- 'validate',
14
- 'solidify',
15
- 'confirmation',
16
- ];
17
-
18
- // A run that wrote `attempt` but never produced an `outcome` is stuck. We
19
- // can't tell apart "still running" from "never going to finish" purely from
20
- // memory_graph alone, so we use a wall-clock threshold: anything older than
21
- // this with no outcome is reclassified `abandoned`. This stops phantom
22
- // "running" rows piling up after crashes, kills, or selectors that bailed
23
- // out early (e.g. no matching gene found). Override via env if needed.
24
- const STUCK_THRESHOLD_MS = parseInt(process.env.EVOLVER_RUN_STUCK_THRESHOLD_MS, 10) || (30 * 60 * 1000);
25
-
26
- function listRuns(query = {}) {
27
- const runs = buildRuns().sort((a, b) => timestampOf(b.updatedAt) - timestampOf(a.updatedAt));
28
- return paginate(runs, query);
29
- }
30
-
31
- function getRun(runId) {
32
- const runs = buildRuns();
33
- const run = runs.find((entry) => entry.runId === runId);
34
- if (!run) return null;
35
- const paths = getObserverPaths();
36
- const events = readJsonl(paths.eventsPath).map(redactValue).filter((e) => belongsToRun(e, runId));
37
- const assetCalls = readJsonl(paths.assetCallLogPath).map(redactValue).filter((e) => belongsToRun(e, runId));
38
- const pipelineEvents = readPipelineEvents().filter((e) => belongsToRun(e, runId));
39
- const detail = buildRunDetail(runId);
40
- return {
41
- ...run,
42
- detail,
43
- phases: buildPhases(run, pipelineEvents, events, assetCalls),
44
- evidence: events,
45
- assets: assetCalls,
46
- pipelineEvents,
47
- };
48
- }
49
-
50
- function buildRunDetail(runId) {
51
- const paths = getObserverPaths();
52
- const solidify = readJsonSafe(paths.solidifyStatePath, null);
53
- const last = solidify && solidify.last_run;
54
- if (!last || String(last.run_id) !== String(runId)) return null;
55
- const safe = redactValue(last);
56
- return {
57
- parentEventId: safe.parent_event_id || null,
58
- selectedCapsuleId: safe.selected_capsule_id || null,
59
- signals: safe.signals || [],
60
- initialUserPrompt: safe.initial_user_prompt || null,
61
- activeTaskId: safe.active_task_id || null,
62
- activeTaskTitle: safe.active_task_title || null,
63
- blastRadius: safe.blast_radius_estimate || null,
64
- selector: safe.selector || null,
65
- mutation: safe.mutation ? simplifyMutation(safe.mutation) : null,
66
- personalityState: safe.personality_state || null,
67
- drift: safe.drift || null,
68
- appliedLessons: safe.applied_lessons || [],
69
- hubLessons: safe.hub_lessons || [],
70
- sourceType: safe.source_type || null,
71
- reusedAssetId: safe.reused_asset_id || null,
72
- baselineGitHead: safe.baseline_git_head || null,
73
- };
74
- }
75
-
76
- function simplifyMutation(mutation) {
77
- if (!mutation || typeof mutation !== 'object') return null;
78
- return {
79
- id: mutation.id || null,
80
- category: mutation.category || null,
81
- triggerSignals: mutation.trigger_signals || [],
82
- targetType: mutation.target_type || null,
83
- summary: mutation.summary || null,
84
- strategySteps: Array.isArray(mutation.strategy) ? mutation.strategy.length : null,
85
- constraints: mutation.constraints || null,
86
- };
87
- }
88
-
89
- function buildRuns() {
90
- const paths = getObserverPaths();
91
- const cycle = readJsonSafe(paths.cycleProgressPath, null);
92
- const solidify = readJsonSafe(paths.solidifyStatePath, null);
93
- const events = readJsonl(paths.eventsPath).map(redactValue);
94
- const assetCalls = readJsonl(paths.assetCallLogPath).map(redactValue);
95
- const pipelineEvents = readPipelineEvents();
96
- const runs = new Map();
97
-
98
- addCycleRun(runs, cycle, solidify);
99
- for (const event of events) mergeRun(runs, summaryFromEvent(event));
100
- for (const call of assetCalls) mergeRun(runs, summaryFromAssetCall(call));
101
- for (const event of pipelineEvents) mergeRun(runs, summaryFromPipelineEvent(event));
102
-
103
- const now = Date.now();
104
- return Array.from(runs.values()).map((run) => ({
105
- ...run,
106
- status: maybeAbandon(run, now),
107
- requiresConfirmation: Boolean(run.requiresConfirmation),
108
- }));
109
- }
110
-
111
- function maybeAbandon(run, now) {
112
- if (run.status !== 'running' || run.finishedAt) return run.status;
113
- const t = timestampOf(run.updatedAt);
114
- if (!t) return run.status;
115
- return now - t > STUCK_THRESHOLD_MS ? 'abandoned' : 'running';
116
- }
117
-
118
- function addCycleRun(runs, cycle, solidify) {
119
- if (!cycle && !(solidify && solidify.last_run)) return;
120
- const last = solidify && solidify.last_run || {};
121
- const lastSolidify = solidify && solidify.last_solidify || null;
122
- const pending = isPending(last, lastSolidify);
123
- const runId = String(cycle && (cycle.run_id || cycle.outer_cycle) || last.run_id || last.mutation_id || 'current');
124
- mergeRun(runs, {
125
- runId,
126
- cycleId: cycle && String(cycle.outer_cycle || cycle.cycle_id || last.cycleId || ''),
127
- status: deriveCycleStatus(cycle, last, lastSolidify, pending),
128
- startedAt: toIso(cycle && cycle.started_at || last.started_at || last.created_at),
129
- updatedAt: toIso(cycle && cycle.updated_at || lastSolidify && lastSolidify.timestamp || last.finished_at || last.created_at),
130
- finishedAt: toIso(last.finished_at || lastSolidify && lastSolidify.timestamp),
131
- activeTaskTitle: last.active_task_title || null,
132
- selectedGeneId: last.selected_gene_id || null,
133
- outcome: last.outcome || (lastSolidify && lastSolidify.rejected ? { status: 'failed', reason: lastSolidify.reason } : null),
134
- validationResult: validationResult(last),
135
- requiresConfirmation: pending,
136
- });
137
- }
138
-
139
- function isPending(lastRun, lastSolidify) {
140
- if (!lastRun || !lastRun.run_id) return false;
141
- if (!lastSolidify || !lastSolidify.run_id) return true;
142
- return String(lastSolidify.run_id) !== String(lastRun.run_id);
143
- }
144
-
145
- function deriveCycleStatus(cycle, lastRun, lastSolidify, pending) {
146
- if (cycle && cycle.phase && isCycleFresh(cycle)) return 'running';
147
- if (lastSolidify && String(lastSolidify.run_id) === String(lastRun.run_id)) {
148
- if (lastSolidify.rejected) return 'failed';
149
- if (lastSolidify.success || lastSolidify.solidified) return 'completed';
150
- }
151
- if (pending) return 'review_pending';
152
- if (lastRun.outcome) return inferOutcome(lastRun.outcome);
153
- if (lastRun.selected_gene_id) return 'selected';
154
- return 'unknown';
155
- }
156
-
157
- function isCycleFresh(cycle) {
158
- const t = Number(cycle && cycle.updated_at);
159
- if (!Number.isFinite(t)) return false;
160
- return Date.now() - t < 5 * 60 * 1000;
161
- }
162
-
163
- function summaryFromEvent(event) {
164
- const runId = event.run_id || event.mutation_id || event.id;
165
- if (!runId) return null;
166
- const eventTime = event.started_at || event.timestamp || event.created_at;
167
- return {
168
- runId: String(runId),
169
- status: inferOutcome(event.outcome),
170
- startedAt: toIso(eventTime),
171
- updatedAt: toIso(event.finished_at || eventTime),
172
- finishedAt: toIso(event.finished_at),
173
- selectedGeneId: firstGene(event.genes_used),
174
- outcome: event.outcome || null,
175
- validationResult: validationResult(event),
176
- requiresConfirmation: Boolean(event.requires_confirmation),
177
- };
178
- }
179
-
180
- function summaryFromAssetCall(call) {
181
- if (!call.run_id) return null;
182
- // Asset-call entries are historical evidence and do not carry a definitive
183
- // run status. Authoritative status comes from cycle/event/pipelineEvent
184
- // sources; leaving status undefined here lets mergeRun keep whatever those
185
- // sources set (or 'unknown' if this is the only source for the run).
186
- return {
187
- runId: String(call.run_id),
188
- updatedAt: toIso(call.timestamp),
189
- requiresConfirmation: isConfirmationAction(call.action),
190
- };
191
- }
192
-
193
- function summaryFromPipelineEvent(event) {
194
- const runId = event.run_id || event.cycle_id;
195
- if (!runId) return null;
196
- return {
197
- runId: String(runId),
198
- cycleId: event.cycle_id,
199
- status: phaseStatusToRunStatus(event.status),
200
- startedAt: toIso(event.started_at || event.timestamp),
201
- updatedAt: toIso(event.finished_at || event.timestamp),
202
- finishedAt: toIso(event.finished_at),
203
- requiresConfirmation: Boolean(event.requires_confirmation),
204
- };
205
- }
206
-
207
- function mergeRun(runs, next) {
208
- if (!next || !next.runId) return;
209
- const current = runs.get(next.runId) || { runId: next.runId, status: 'unknown' };
210
- runs.set(next.runId, {
211
- ...current,
212
- ...emptyFiltered(next),
213
- startedAt: earliest(current.startedAt, next.startedAt),
214
- updatedAt: latest(current.updatedAt, next.updatedAt),
215
- finishedAt: latest(current.finishedAt, next.finishedAt),
216
- requiresConfirmation: current.requiresConfirmation || next.requiresConfirmation,
217
- });
218
- }
219
-
220
- function buildPhases(run, pipelineEvents, events, assetCalls) {
221
- if (pipelineEvents.length > 0) return pipelineEvents.map(eventToPhase);
222
- return PHASE_ORDER.map((phase) => inferPhase(phase, run, events, assetCalls));
223
- }
224
-
225
- function eventToPhase(event) {
226
- return {
227
- phase: event.phase,
228
- status: event.status,
229
- startedAt: event.started_at,
230
- finishedAt: event.finished_at,
231
- summary: event.summary,
232
- evidenceRefs: event.evidence_refs || [],
233
- assetRefs: event.asset_refs || [],
234
- validationRefs: event.validation_refs || [],
235
- requiresConfirmation: Boolean(event.requires_confirmation),
236
- };
237
- }
238
-
239
- function inferPhase(phase, run, events, assetCalls) {
240
- const status = inferPhaseStatus(phase, run, events, assetCalls);
241
- return {
242
- phase,
243
- status,
244
- startedAt: run.startedAt || null,
245
- finishedAt: status === 'success' ? run.finishedAt || run.updatedAt || null : null,
246
- summary: summaryForPhase(phase, run, events, assetCalls),
247
- evidenceRefs: events.map((event) => ({ type: 'event', id: event.id })).filter((e) => e.id),
248
- assetRefs: assetCalls.map((call) => ({ type: call.asset_type || 'asset', id: call.asset_id, action: call.action })).filter((a) => a.id || a.action),
249
- validationRefs: validationRefs(events),
250
- requiresConfirmation: phase === 'confirmation' && run.requiresConfirmation,
251
- };
252
- }
253
-
254
- function inferPhaseStatus(phase, run, events, assetCalls) {
255
- if (phase === 'asset_search') return assetCalls.length ? 'success' : 'skipped';
256
- if (phase === 'confirmation') return run.requiresConfirmation ? 'blocked' : 'skipped';
257
- if (phase === 'validate') return run.validationResult === 'fail' ? 'failed' : run.validationResult === 'pass' ? 'success' : 'skipped';
258
- if (phase === 'solidify') {
259
- if (events.length) return 'success';
260
- if (run.status === 'review_pending') return 'blocked';
261
- if (run.status === 'running' || run.status === 'selected') return 'pending';
262
- return 'skipped';
263
- }
264
- if (phase === 'detect_signals' || phase === 'select_gene') {
265
- return run.selectedGeneId ? 'success' : run.status === 'running' ? 'running' : 'skipped';
266
- }
267
- if (phase === 'mutate_strategy') {
268
- return run.selectedGeneId ? 'success' : 'skipped';
269
- }
270
- return run.status === 'running' ? 'running' : 'success';
271
- }
272
-
273
- function summaryForPhase(phase, run, events, assetCalls) {
274
- if (phase === 'select_gene') return run.selectedGeneId ? `Selected ${run.selectedGeneId}` : 'No selected Gene recorded yet.';
275
- if (phase === 'asset_search') return assetCalls.length ? `${assetCalls.length} asset call(s) recorded.` : 'No asset calls recorded.';
276
- if (phase === 'solidify') return events.length ? `${events.length} EvolutionEvent record(s) found.` : 'No solidified event recorded.';
277
- if (phase === 'confirmation') return run.requiresConfirmation ? 'Human confirmation is required.' : 'No confirmation required.';
278
- return phase.replace(/_/g, ' ');
279
- }
280
-
281
- function belongsToRun(entry, runId) {
282
- if (!entry || runId == null || runId === '') return false;
283
- const target = String(runId);
284
- return [entry.run_id, entry.mutation_id, entry.id, entry.cycle_id]
285
- .filter((value) => value != null && value !== '')
286
- .map(String)
287
- .includes(target);
288
- }
289
-
290
- function validationRefs(events) {
291
- return events.flatMap((event) => event.validation || event.validation_results || []).filter(Boolean);
292
- }
293
-
294
- function validationResult(entry) {
295
- if (!entry) return 'unknown';
296
- if (entry.validation_result) return entry.validation_result;
297
- if (entry.validation && entry.validation.ok === true) return 'pass';
298
- if (entry.validation && entry.validation.ok === false) return 'fail';
299
- return 'unknown';
300
- }
301
-
302
- function phaseStatusToRunStatus(status) {
303
- if (status === 'failed') return 'failed';
304
- if (status === 'blocked') return 'blocked';
305
- if (status === 'success') return 'completed';
306
- return 'running';
307
- }
308
-
309
- function inferOutcome(outcome) {
310
- const value = typeof outcome === 'string' ? outcome : outcome && outcome.status;
311
- if (value === 'success') return 'completed';
312
- if (value === 'failed') return 'failed';
313
- return 'unknown';
314
- }
315
-
316
- function firstGene(genes) {
317
- return Array.isArray(genes) && genes.length ? genes[0] : null;
318
- }
319
-
320
- function isConfirmationAction(action) {
321
- return ['asset_publish', 'asset_fetch', 'task_claim', 'validator_stake'].includes(action);
322
- }
323
-
324
- function toIso(value) {
325
- if (!value) return null;
326
- if (typeof value === 'string') return value;
327
- const n = Number(value);
328
- return Number.isFinite(n) ? new Date(n).toISOString() : null;
329
- }
330
-
331
- function timestampOf(value) {
332
- const t = Date.parse(value || '');
333
- return Number.isFinite(t) ? t : 0;
334
- }
335
-
336
- function emptyFiltered(obj) {
337
- return Object.fromEntries(Object.entries(obj).filter(([, value]) => value !== null && value !== undefined && value !== ''));
338
- }
339
-
340
- function earliest(a, b) {
341
- if (!a) return b || null;
342
- if (!b) return a;
343
- return timestampOf(a) <= timestampOf(b) ? a : b;
344
- }
345
-
346
- function latest(a, b) {
347
- if (!a) return b || null;
348
- if (!b) return a;
349
- return timestampOf(a) >= timestampOf(b) ? a : b;
350
- }
351
-
352
- module.exports = {
353
- listRuns,
354
- getRun,
355
- buildRuns,
356
- };
@@ -1,57 +0,0 @@
1
- 'use strict';
2
-
3
- function getSafetyState() {
4
- return {
5
- autobuyEnabled: isEnabled(process.env.EVOLVER_ATP_AUTOBUY) || isEnabled(process.env.ATP_AUTOBUY),
6
- dailyCreditCap: numberEnv('ATP_AUTOBUY_DAILY_CAP_CREDITS', 0),
7
- perOrderCreditCap: numberEnv('ATP_AUTOBUY_PER_ORDER_CAP_CREDITS', 0),
8
- autoPublishEnabled: isEnabled(process.env.EVOLVER_AUTO_PUBLISH),
9
- validatorEnabled: isEnabled(process.env.EVOLVER_VALIDATOR_ENABLED),
10
- traceLevel: String(process.env.EVOLVER_TRACE_LEVEL || 'minimal'),
11
- defaultVisibility: process.env.EVOLVER_DEFAULT_VISIBILITY || 'private',
12
- safeMode: isSafeMode(),
13
- warnings: getWarnings(),
14
- };
15
- }
16
-
17
- function isSafeMode() {
18
- const state = {
19
- autobuyEnabled: isEnabled(process.env.EVOLVER_ATP_AUTOBUY) || isEnabled(process.env.ATP_AUTOBUY),
20
- dailyCreditCap: numberEnv('ATP_AUTOBUY_DAILY_CAP_CREDITS', 0),
21
- perOrderCreditCap: numberEnv('ATP_AUTOBUY_PER_ORDER_CAP_CREDITS', 0),
22
- autoPublishEnabled: isEnabled(process.env.EVOLVER_AUTO_PUBLISH),
23
- validatorEnabled: isEnabled(process.env.EVOLVER_VALIDATOR_ENABLED),
24
- };
25
- return !state.autobuyEnabled &&
26
- state.dailyCreditCap === 0 &&
27
- state.perOrderCreditCap === 0 &&
28
- !state.autoPublishEnabled &&
29
- !state.validatorEnabled;
30
- }
31
-
32
- function getWarnings() {
33
- const warnings = [];
34
- if (isEnabled(process.env.EVOLVER_ATP_AUTOBUY) || isEnabled(process.env.ATP_AUTOBUY)) {
35
- warnings.push('ATP autobuy is enabled.');
36
- }
37
- if (numberEnv('ATP_AUTOBUY_DAILY_CAP_CREDITS', 0) > 0) {
38
- warnings.push('Daily ATP autobuy credit cap is above zero.');
39
- }
40
- if (numberEnv('ATP_AUTOBUY_PER_ORDER_CAP_CREDITS', 0) > 0) {
41
- warnings.push('Per-order ATP autobuy credit cap is above zero.');
42
- }
43
- if (isEnabled(process.env.EVOLVER_AUTO_PUBLISH)) warnings.push('Auto-publish is enabled.');
44
- if (isEnabled(process.env.EVOLVER_VALIDATOR_ENABLED)) warnings.push('Validator daemon is enabled.');
45
- return warnings;
46
- }
47
-
48
- function isEnabled(value) {
49
- return ['1', 'true', 'yes', 'on'].includes(String(value || '').toLowerCase());
50
- }
51
-
52
- function numberEnv(key, fallback) {
53
- const n = Number(process.env[key]);
54
- return Number.isFinite(n) ? n : fallback;
55
- }
56
-
57
- module.exports = { getSafetyState };
@@ -1,70 +0,0 @@
1
- 'use strict';
2
-
3
- const fs = require('fs');
4
- const path = require('path');
5
- const { getSkillsDir } = require('../../gep/paths');
6
-
7
- function listSkills() {
8
- const dir = getSkillsDir();
9
- if (!fs.existsSync(dir)) return { exists: false, items: [] };
10
-
11
- const entries = safeReaddir(dir).filter((entry) => entry.isDirectory());
12
- const items = entries.map((entry) => buildSkillSummary(path.join(dir, entry.name), entry.name));
13
- return { exists: true, items };
14
- }
15
-
16
- function buildSkillSummary(skillPath, name) {
17
- const skillFile = findFirstExisting(skillPath, ['SKILL.md', 'skill.md', 'README.md']);
18
- let description = '';
19
- let bytes = 0;
20
- if (skillFile) {
21
- try {
22
- const stat = fs.statSync(skillFile);
23
- bytes = stat.size;
24
- description = extractDescription(skillFile);
25
- } catch {
26
- // ignore
27
- }
28
- }
29
- const fileCount = safeReaddir(skillPath).length;
30
- return {
31
- name,
32
- description,
33
- docFile: skillFile ? path.basename(skillFile) : null,
34
- docBytes: bytes,
35
- fileCount,
36
- };
37
- }
38
-
39
- function extractDescription(filePath) {
40
- try {
41
- const raw = fs.readFileSync(filePath, 'utf8');
42
- const frontmatter = raw.match(/^---\s*\n([\s\S]*?)\n---/);
43
- if (frontmatter) {
44
- const desc = frontmatter[1].match(/description\s*:\s*([^\n]+)/);
45
- if (desc) return desc[1].trim().replace(/^['"]|['"]$/g, '');
46
- }
47
- const firstParagraph = raw.replace(/^---[\s\S]*?---/, '').trim().split(/\n\s*\n/)[0];
48
- return firstParagraph.replace(/^#+\s*/, '').slice(0, 240);
49
- } catch {
50
- return '';
51
- }
52
- }
53
-
54
- function safeReaddir(dir) {
55
- try {
56
- return fs.readdirSync(dir, { withFileTypes: true });
57
- } catch {
58
- return [];
59
- }
60
- }
61
-
62
- function findFirstExisting(dir, names) {
63
- for (const name of names) {
64
- const candidate = path.join(dir, name);
65
- if (fs.existsSync(candidate)) return candidate;
66
- }
67
- return null;
68
- }
69
-
70
- module.exports = { listSkills };
@@ -1,71 +0,0 @@
1
- 'use strict';
2
-
3
- const fs = require('fs');
4
- const { getObserverPaths } = require('./paths');
5
- const { readJsonSafe } = require('./jsonl');
6
- const { getSafetyState } = require('./safety');
7
- const { redactValue } = require('./redact');
8
-
9
- function getStatus() {
10
- const paths = getObserverPaths();
11
- const cycle = readJsonSafe(paths.cycleProgressPath, null);
12
- const solidify = readJsonSafe(paths.solidifyStatePath, null);
13
- const evolution = readJsonSafe(paths.evolutionStatePath, null);
14
- const proxy = getProxySettings();
15
- // Everything observer-derived may carry prompt / task context with
16
- // embedded credentials. Every other observer endpoint (runs.js,
17
- // assets.js, interactions.js, ...) already pipes its payload through
18
- // redactValue; /webui/status is the one that skipped it, so it became
19
- // the easy exfiltration path. Funnel the three readJsonSafe outputs
20
- // through the same redaction filter before they leave the process.
21
- return {
22
- mode: inferMode(cycle, solidify, proxy),
23
- heartbeat: redactValue(cycle),
24
- lastRun: redactValue(solidify && solidify.last_run ? solidify.last_run : null),
25
- evolutionState: redactValue(evolution),
26
- proxy,
27
- filesPresent: filesPresent(paths),
28
- safety: getSafetyState(),
29
- };
30
- }
31
-
32
- function inferMode(cycle, solidify, proxy) {
33
- if (cycle && isFresh(cycle.updated_at, 120_000)) return 'running';
34
- if (solidify && solidify.pending) return 'review_pending';
35
- if (proxy && proxy.running) return 'proxy_only';
36
- return 'idle';
37
- }
38
-
39
- function isFresh(timestamp, maxAgeMs) {
40
- const t = Number(timestamp);
41
- return Number.isFinite(t) && Date.now() - t < maxAgeMs;
42
- }
43
-
44
- function getProxySettings() {
45
- try {
46
- const { readSettings, isStaleProxy } = require('../../proxy/server/settings');
47
- const settings = readSettings();
48
- const proxy = settings.proxy || null;
49
- if (!proxy) return { running: false, url: null };
50
- return {
51
- running: !isStaleProxy(),
52
- url: proxy.url || null,
53
- pid: proxy.pid || null,
54
- started_at: proxy.started_at || null,
55
- };
56
- } catch {
57
- return { running: false, url: null };
58
- }
59
- }
60
-
61
- function filesPresent(paths) {
62
- return {
63
- cycleProgress: fs.existsSync(paths.cycleProgressPath),
64
- solidifyState: fs.existsSync(paths.solidifyStatePath),
65
- events: fs.existsSync(paths.eventsPath),
66
- assetCallLog: fs.existsSync(paths.assetCallLogPath),
67
- pipelineEvents: fs.existsSync(paths.pipelineEventsPath),
68
- };
69
- }
70
-
71
- module.exports = { getStatus, getProxySettings };
@@ -1,138 +0,0 @@
1
- 'use strict';
2
-
3
- const http = require('http');
4
- const { buildWebUiRoutes } = require('./routes');
5
- const { getIndexHtml, getClientJs, getStylesCss, getVendorEcharts } = require('../client/static');
6
-
7
- const DEFAULT_WEBUI_PORT = 19821;
8
- const MAX_PORT_ATTEMPTS = 50;
9
-
10
- class WebUiServer {
11
- constructor(opts = {}) {
12
- this.port = opts.port || Number(process.env.EVOLVER_WEBUI_PORT) || DEFAULT_WEBUI_PORT;
13
- this.logger = opts.logger || console;
14
- this.routes = opts.routes || buildWebUiRoutes();
15
- this.server = null;
16
- this.actualPort = null;
17
- }
18
-
19
- async start() {
20
- this.server = http.createServer((req, res) => this._handle(req, res));
21
- let port = this.port;
22
- for (let i = 0; i < MAX_PORT_ATTEMPTS; i++) {
23
- const ok = await tryListen(this.server, port);
24
- if (ok) {
25
- this.actualPort = port;
26
- const url = `http://127.0.0.1:${port}`;
27
- this.logger.log(`[webui] listening on ${url}`);
28
- return { port, url };
29
- }
30
- port++;
31
- }
32
- throw new Error(`Could not find free Web UI port after ${MAX_PORT_ATTEMPTS} attempts`);
33
- }
34
-
35
- async stop() {
36
- if (!this.server) return;
37
- await new Promise((resolve) => this.server.close(resolve));
38
- this.server = null;
39
- }
40
-
41
- async _handle(req, res) {
42
- const url = new URL(req.url, `http://127.0.0.1:${this.actualPort || this.port}`);
43
- if (req.method === 'GET' && url.pathname === '/') return sendText(res, 200, 'text/html; charset=utf-8', getIndexHtml());
44
- if (req.method === 'GET' && url.pathname === '/app.js') return sendText(res, 200, 'application/javascript; charset=utf-8', getClientJs());
45
- if (req.method === 'GET' && url.pathname === '/app.css') return sendText(res, 200, 'text/css; charset=utf-8', getStylesCss());
46
- if (req.method === 'GET' && url.pathname === '/vendor/echarts.min.js') return sendText(res, 200, 'application/javascript; charset=utf-8', getVendorEcharts());
47
-
48
- const matched = matchRoute(this.routes, req.method, url.pathname);
49
- if (!matched) return sendJson(res, 404, { error: { code: 'NOT_FOUND', message: 'Not found', details: { path: url.pathname } } });
50
-
51
- try {
52
- const query = Object.fromEntries(url.searchParams);
53
- const result = await matched.handler({ query, params: matched.params });
54
- return sendJson(res, result.status || 200, result.body || result);
55
- } catch (err) {
56
- this.logger.error('[webui] request failed:', err && err.message || err);
57
- return sendJson(res, err.statusCode || 500, {
58
- error: {
59
- code: err.code || 'READ_FAILED',
60
- message: err.message || 'Internal error',
61
- details: err.details || {},
62
- },
63
- });
64
- }
65
- }
66
- }
67
-
68
- function matchRoute(routes, method, pathname) {
69
- for (const [pattern, handler] of Object.entries(routes)) {
70
- const [routeMethod, routePath] = pattern.split(' ');
71
- if (routeMethod !== method) continue;
72
- const params = matchPath(routePath, pathname);
73
- if (params) return { handler, params };
74
- }
75
- return null;
76
- }
77
-
78
- function matchPath(pattern, pathname) {
79
- const patternParts = pattern.split('/');
80
- const pathParts = pathname.split('/');
81
- if (patternParts.length !== pathParts.length) return null;
82
- const params = {};
83
- for (let i = 0; i < patternParts.length; i++) {
84
- if (patternParts[i].startsWith(':')) {
85
- // decodeURIComponent throws URIError on malformed percent escapes
86
- // (e.g. /webui/runs/%E0%A4%A). matchPath runs outside _handle's
87
- // try/catch, so an unhandled rejection would crash the request and
88
- // depending on the Node version's unhandled-rejection policy could
89
- // tip the local WebUI into a denial-of-service. Treat a malformed
90
- // segment as "no route matches" so the request falls through to a
91
- // clean 404.
92
- try {
93
- params[patternParts[i].slice(1)] = decodeURIComponent(pathParts[i]);
94
- } catch (_) {
95
- return null;
96
- }
97
- } else if (patternParts[i] !== pathParts[i]) {
98
- return null;
99
- }
100
- }
101
- return params;
102
- }
103
-
104
- function tryListen(server, port) {
105
- return new Promise((resolve, reject) => {
106
- const onError = (err) => {
107
- server.removeListener('listening', onListening);
108
- if (err.code === 'EADDRINUSE') return resolve(false);
109
- reject(err);
110
- };
111
- const onListening = () => {
112
- server.removeListener('error', onError);
113
- resolve(true);
114
- };
115
- server.once('error', onError);
116
- server.once('listening', onListening);
117
- server.listen(port, '127.0.0.1');
118
- });
119
- }
120
-
121
- function sendJson(res, status, body) {
122
- const payload = JSON.stringify(body);
123
- sendText(res, status, 'application/json; charset=utf-8', payload);
124
- }
125
-
126
- function sendText(res, status, contentType, text) {
127
- res.writeHead(status, {
128
- 'Content-Type': contentType,
129
- 'Content-Length': Buffer.byteLength(text),
130
- });
131
- res.end(text);
132
- }
133
-
134
- module.exports = {
135
- WebUiServer,
136
- DEFAULT_WEBUI_PORT,
137
- matchPath,
138
- };