@evomap/evolver 1.89.20 → 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.
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 -3586
  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/skills/_meta/SKILL.md +0 -41
  38. package/skills/index.json +0 -14
  39. package/src/adapters/claudeCode.js +0 -194
  40. package/src/adapters/codex.js +0 -216
  41. package/src/adapters/cursor.js +0 -91
  42. package/src/adapters/hookAdapter.js +0 -469
  43. package/src/adapters/kiro.js +0 -195
  44. package/src/adapters/opencode.js +0 -326
  45. package/src/adapters/scripts/_lockPaths.js +0 -74
  46. package/src/adapters/scripts/_memoryFiltering.js +0 -35
  47. package/src/adapters/scripts/_runtimePaths.js +0 -440
  48. package/src/adapters/scripts/evolver-session-end.js +0 -321
  49. package/src/adapters/scripts/evolver-session-start.js +0 -587
  50. package/src/adapters/scripts/evolver-signal-detect.js +0 -98
  51. package/src/adapters/scripts/evolver-task-recall.js +0 -173
  52. package/src/atp/atpExecute.js +0 -283
  53. package/src/atp/atpTaskPickup.js +0 -233
  54. package/src/atp/autoBuyer.js +0 -382
  55. package/src/atp/autoDeliver.js +0 -215
  56. package/src/atp/cli.js +0 -354
  57. package/src/atp/cliAutobuyPrompt.js +0 -154
  58. package/src/atp/consumerAgent.js +0 -157
  59. package/src/atp/defaultHandler.js +0 -69
  60. package/src/atp/heartbeatSignalsHandler.js +0 -254
  61. package/src/atp/hubClient.js +0 -317
  62. package/src/atp/index.js +0 -38
  63. package/src/atp/merchantAgent.js +0 -118
  64. package/src/atp/protocol.js +0 -41
  65. package/src/atp/questionComposer.js +0 -133
  66. package/src/atp/serviceHelper.js +0 -92
  67. package/src/canary.js +0 -13
  68. package/src/config.js +0 -351
  69. package/src/evolve/guards.js +0 -1
  70. package/src/evolve/pipeline/collect.js +0 -1
  71. package/src/evolve/pipeline/dispatch.js +0 -1
  72. package/src/evolve/pipeline/enrich.js +0 -1
  73. package/src/evolve/pipeline/hub.js +0 -1
  74. package/src/evolve/pipeline/select.js +0 -1
  75. package/src/evolve/pipeline/signals.js +0 -1
  76. package/src/evolve/utils.js +0 -1
  77. package/src/evolve.js +0 -1
  78. package/src/experiment/agentRunner.js +0 -229
  79. package/src/experiment/cli.js +0 -159
  80. package/src/experiment/comparison.js +0 -233
  81. package/src/experiment/metrics.js +0 -75
  82. package/src/forceUpdate.js +0 -991
  83. package/src/gep/a2a.js +0 -173
  84. package/src/gep/a2aProtocol.js +0 -1
  85. package/src/gep/analyzer.js +0 -35
  86. package/src/gep/antiAbuseTelemetry.js +0 -1
  87. package/src/gep/assetCallLog.js +0 -197
  88. package/src/gep/assetStore.js +0 -723
  89. package/src/gep/assets.js +0 -36
  90. package/src/gep/autoDistillConv.js +0 -1
  91. package/src/gep/autoDistillLlm.js +0 -1
  92. package/src/gep/bridge.js +0 -138
  93. package/src/gep/candidateEval.js +0 -1
  94. package/src/gep/candidates.js +0 -1
  95. package/src/gep/claimNudge.js +0 -121
  96. package/src/gep/cliContracts.js +0 -1190
  97. package/src/gep/contentHash.js +0 -1
  98. package/src/gep/conversationDistiller.js +0 -1
  99. package/src/gep/conversationSniffer.js +0 -1
  100. package/src/gep/crypto.js +0 -1
  101. package/src/gep/curriculum.js +0 -1
  102. package/src/gep/deviceId.js +0 -1
  103. package/src/gep/directoryClient.js +0 -115
  104. package/src/gep/envFingerprint.js +0 -1
  105. package/src/gep/epigenetics.js +0 -1
  106. package/src/gep/execBridge.js +0 -1
  107. package/src/gep/executionTrace.js +0 -291
  108. package/src/gep/explore.js +0 -1
  109. package/src/gep/featureFlags.js +0 -121
  110. package/src/gep/gitOps.js +0 -265
  111. package/src/gep/hash.js +0 -1
  112. package/src/gep/hostErrorClassifier.js +0 -34
  113. package/src/gep/hubFetch.js +0 -1
  114. package/src/gep/hubReview.js +0 -1
  115. package/src/gep/hubSearch.js +0 -1
  116. package/src/gep/hubVerify.js +0 -1
  117. package/src/gep/idleScheduler.js +0 -400
  118. package/src/gep/issueReporter.js +0 -416
  119. package/src/gep/learningSignals.js +0 -1
  120. package/src/gep/llmReview.js +0 -92
  121. package/src/gep/localStateAwareness.js +0 -243
  122. package/src/gep/mailboxTransport.js +0 -119
  123. package/src/gep/memoryGraph.js +0 -1
  124. package/src/gep/memoryGraphAdapter.js +0 -1
  125. package/src/gep/mutation.js +0 -1
  126. package/src/gep/narrativeMemory.js +0 -1
  127. package/src/gep/oauthLogin.js +0 -181
  128. package/src/gep/openPRRegistry.js +0 -1
  129. package/src/gep/paths.js +0 -522
  130. package/src/gep/personality.js +0 -1
  131. package/src/gep/policyCheck.js +0 -1
  132. package/src/gep/portable.js +0 -103
  133. package/src/gep/privacyClient.js +0 -235
  134. package/src/gep/prompt.js +0 -1
  135. package/src/gep/questionGenerator.js +0 -518
  136. package/src/gep/recallInject.js +0 -1
  137. package/src/gep/recallVerifier.js +0 -1
  138. package/src/gep/reflection.js +0 -1
  139. package/src/gep/sanitize.js +0 -264
  140. package/src/gep/savingsCore.js +0 -1
  141. package/src/gep/schemas/capsule.js +0 -170
  142. package/src/gep/schemas/gene.js +0 -154
  143. package/src/gep/schemas/index.js +0 -8
  144. package/src/gep/schemas/protocol.js +0 -51
  145. package/src/gep/schemas/task.js +0 -74
  146. package/src/gep/selector.js +0 -1
  147. package/src/gep/selfPR.js +0 -469
  148. package/src/gep/signals.js +0 -776
  149. package/src/gep/skill2gep.js +0 -1056
  150. package/src/gep/skill2gepAudit.js +0 -303
  151. package/src/gep/skill2recipes.js +0 -511
  152. package/src/gep/skillDistiller.js +0 -1
  153. package/src/gep/skillPublisher.js +0 -358
  154. package/src/gep/solidify.js +0 -1
  155. package/src/gep/strategy.js +0 -1
  156. package/src/gep/taskReceiver.js +0 -575
  157. package/src/gep/tokenSavings.js +0 -1
  158. package/src/gep/trajectoryExport.js +0 -1
  159. package/src/gep/validationReport.js +0 -55
  160. package/src/gep/validator/index.js +0 -411
  161. package/src/gep/validator/reporter.js +0 -210
  162. package/src/gep/validator/sandboxExecutor.js +0 -480
  163. package/src/gep/validator/stakeBootstrap.js +0 -357
  164. package/src/gep/workspaceKeychain.js +0 -1
  165. package/src/ops/cleanup.js +0 -80
  166. package/src/ops/commentary.js +0 -60
  167. package/src/ops/health_check.js +0 -104
  168. package/src/ops/index.js +0 -11
  169. package/src/ops/innovation.js +0 -67
  170. package/src/ops/lifecycle.js +0 -798
  171. package/src/ops/self_repair.js +0 -76
  172. package/src/ops/skills_monitor.js +0 -147
  173. package/src/ops/trigger.js +0 -33
  174. package/src/proxy/clientSettings.js +0 -405
  175. package/src/proxy/envelope.js +0 -59
  176. package/src/proxy/extensions/dmHandler.js +0 -45
  177. package/src/proxy/extensions/sessionHandler.js +0 -141
  178. package/src/proxy/extensions/skillUpdater.js +0 -64
  179. package/src/proxy/extensions/traceControl.js +0 -1
  180. package/src/proxy/index.js +0 -1395
  181. package/src/proxy/inject.js +0 -1
  182. package/src/proxy/lifecycle/manager.js +0 -1568
  183. package/src/proxy/mailbox/state.js +0 -207
  184. package/src/proxy/mailbox/store.js +0 -590
  185. package/src/proxy/router/cache_passthrough.js +0 -26
  186. package/src/proxy/router/features.js +0 -84
  187. package/src/proxy/router/gemini_route.js +0 -154
  188. package/src/proxy/router/messages_route.js +0 -535
  189. package/src/proxy/router/model_router.js +0 -113
  190. package/src/proxy/router/models_route.js +0 -52
  191. package/src/proxy/router/ollama_route.js +0 -103
  192. package/src/proxy/router/responses_route.js +0 -170
  193. package/src/proxy/router/vertex_route.js +0 -110
  194. package/src/proxy/server/http.js +0 -363
  195. package/src/proxy/server/routes.js +0 -558
  196. package/src/proxy/server/settings.js +0 -115
  197. package/src/proxy/sync/engine.js +0 -179
  198. package/src/proxy/sync/inbound.js +0 -211
  199. package/src/proxy/sync/outbound.js +0 -320
  200. package/src/proxy/task/monitor.js +0 -131
  201. package/src/proxy/trace/extractor.js +0 -1
  202. package/src/proxy/trace/usage.js +0 -1
  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
- };