@evomap/evolver 1.90.0 → 2.0.0-beta.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +27 -564
- package/bin/evolver-llm-proxy.js +3 -0
- package/bin/evolver-mcp.js +2 -0
- package/bin/evolver-proxy.js +3 -0
- package/bin/evolver.js +4 -0
- package/index.js +1 -3670
- package/package.json +32 -62
- package/CONTRIBUTING.md +0 -19
- package/LICENSE +0 -641
- package/README.ja-JP.md +0 -521
- package/README.ko-KR.md +0 -520
- package/README.zh-CN.md +0 -531
- package/SKILL.md +0 -365
- package/assets/cover.png +0 -0
- package/assets/gep/genes.seed.json +0 -496
- package/conformance/savings-core/constants.json +0 -30
- package/conformance/savings-core/golden-vectors.json +0 -333
- package/scripts/a2a_export.js +0 -63
- package/scripts/a2a_ingest.js +0 -79
- package/scripts/a2a_promote.js +0 -118
- package/scripts/analyze_by_skill.js +0 -121
- package/scripts/build_binaries.js +0 -479
- package/scripts/check-changelog.js +0 -166
- package/scripts/extract_log.js +0 -85
- package/scripts/generate_history.js +0 -75
- package/scripts/gep_append_event.js +0 -96
- package/scripts/gep_personality_report.js +0 -234
- package/scripts/human_report.js +0 -147
- package/scripts/recall-verify-report.js +0 -234
- package/scripts/recover_loop.js +0 -61
- package/scripts/refresh_stars_badge.js +0 -168
- package/scripts/seed-merchants.js +0 -91
- package/scripts/skill2recipes.js +0 -118
- package/scripts/suggest_version.js +0 -89
- package/scripts/validate-modules.js +0 -38
- package/scripts/validate-suite.js +0 -78
- package/src/adapters/claudeCode.js +0 -194
- package/src/adapters/codex.js +0 -216
- package/src/adapters/cursor.js +0 -91
- package/src/adapters/hookAdapter.js +0 -469
- package/src/adapters/kiro.js +0 -195
- package/src/adapters/opencode.js +0 -326
- package/src/adapters/scripts/_lockPaths.js +0 -74
- package/src/adapters/scripts/_memoryFiltering.js +0 -35
- package/src/adapters/scripts/_runtimePaths.js +0 -440
- package/src/adapters/scripts/evolver-session-end.js +0 -321
- package/src/adapters/scripts/evolver-session-start.js +0 -587
- package/src/adapters/scripts/evolver-signal-detect.js +0 -98
- package/src/adapters/scripts/evolver-task-recall.js +0 -173
- package/src/atp/atpExecute.js +0 -283
- package/src/atp/atpTaskPickup.js +0 -233
- package/src/atp/autoBuyer.js +0 -382
- package/src/atp/autoDeliver.js +0 -215
- package/src/atp/cli.js +0 -354
- package/src/atp/cliAutobuyPrompt.js +0 -154
- package/src/atp/consumerAgent.js +0 -157
- package/src/atp/defaultHandler.js +0 -69
- package/src/atp/heartbeatSignalsHandler.js +0 -254
- package/src/atp/hubClient.js +0 -317
- package/src/atp/index.js +0 -38
- package/src/atp/merchantAgent.js +0 -118
- package/src/atp/protocol.js +0 -41
- package/src/atp/questionComposer.js +0 -133
- package/src/atp/serviceHelper.js +0 -92
- package/src/canary.js +0 -13
- package/src/config.js +0 -351
- package/src/evolve/guards.js +0 -1
- package/src/evolve/pipeline/collect.js +0 -1
- package/src/evolve/pipeline/dispatch.js +0 -1
- package/src/evolve/pipeline/enrich.js +0 -1
- package/src/evolve/pipeline/hub.js +0 -1
- package/src/evolve/pipeline/select.js +0 -1
- package/src/evolve/pipeline/signals.js +0 -1
- package/src/evolve/utils.js +0 -1
- package/src/evolve.js +0 -1
- package/src/experiment/agentRunner.js +0 -229
- package/src/experiment/cli.js +0 -159
- package/src/experiment/comparison.js +0 -233
- package/src/experiment/metrics.js +0 -75
- package/src/forceUpdate.js +0 -991
- package/src/gep/a2a.js +0 -173
- package/src/gep/a2aProtocol.js +0 -1
- package/src/gep/analyzer.js +0 -35
- package/src/gep/antiAbuseTelemetry.js +0 -1
- package/src/gep/assetCallLog.js +0 -197
- package/src/gep/assetStore.js +0 -723
- package/src/gep/assets.js +0 -36
- package/src/gep/autoDistillConv.js +0 -1
- package/src/gep/autoDistillLlm.js +0 -1
- package/src/gep/bridge.js +0 -138
- package/src/gep/candidateEval.js +0 -1
- package/src/gep/candidates.js +0 -1
- package/src/gep/claimNudge.js +0 -121
- package/src/gep/cliContracts.js +0 -1190
- package/src/gep/contentHash.js +0 -1
- package/src/gep/conversationDistiller.js +0 -1
- package/src/gep/conversationSniffer.js +0 -1
- package/src/gep/crypto.js +0 -1
- package/src/gep/curriculum.js +0 -1
- package/src/gep/deviceId.js +0 -1
- package/src/gep/directoryClient.js +0 -115
- package/src/gep/envFingerprint.js +0 -1
- package/src/gep/epigenetics.js +0 -1
- package/src/gep/execBridge.js +0 -1
- package/src/gep/executionTrace.js +0 -291
- package/src/gep/explore.js +0 -1
- package/src/gep/featureFlags.js +0 -121
- package/src/gep/gitOps.js +0 -265
- package/src/gep/hash.js +0 -1
- package/src/gep/hostErrorClassifier.js +0 -34
- package/src/gep/hubFetch.js +0 -1
- package/src/gep/hubReview.js +0 -1
- package/src/gep/hubSearch.js +0 -1
- package/src/gep/hubVerify.js +0 -1
- package/src/gep/idleScheduler.js +0 -400
- package/src/gep/issueReporter.js +0 -416
- package/src/gep/learningSignals.js +0 -1
- package/src/gep/llmReview.js +0 -92
- package/src/gep/localStateAwareness.js +0 -243
- package/src/gep/mailboxTransport.js +0 -119
- package/src/gep/memoryGraph.js +0 -1
- package/src/gep/memoryGraphAdapter.js +0 -1
- package/src/gep/mutation.js +0 -1
- package/src/gep/narrativeMemory.js +0 -1
- package/src/gep/oauthLogin.js +0 -181
- package/src/gep/openPRRegistry.js +0 -1
- package/src/gep/paths.js +0 -522
- package/src/gep/personality.js +0 -1
- package/src/gep/policyCheck.js +0 -1
- package/src/gep/portable.js +0 -103
- package/src/gep/privacyClient.js +0 -235
- package/src/gep/prompt.js +0 -1
- package/src/gep/questionGenerator.js +0 -518
- package/src/gep/recallInject.js +0 -1
- package/src/gep/recallVerifier.js +0 -1
- package/src/gep/reflection.js +0 -1
- package/src/gep/sanitize.js +0 -264
- package/src/gep/savingsCore.js +0 -1
- package/src/gep/schemas/capsule.js +0 -170
- package/src/gep/schemas/gene.js +0 -154
- package/src/gep/schemas/index.js +0 -8
- package/src/gep/schemas/protocol.js +0 -51
- package/src/gep/schemas/task.js +0 -74
- package/src/gep/selector.js +0 -1
- package/src/gep/selfPR.js +0 -469
- package/src/gep/signals.js +0 -776
- package/src/gep/skill2gep.js +0 -1056
- package/src/gep/skill2gepAudit.js +0 -303
- package/src/gep/skill2recipes.js +0 -511
- package/src/gep/skillDistiller.js +0 -1
- package/src/gep/skillPublisher.js +0 -358
- package/src/gep/solidify.js +0 -1
- package/src/gep/strategy.js +0 -1
- package/src/gep/taskReceiver.js +0 -575
- package/src/gep/tokenSavings.js +0 -1
- package/src/gep/trajectoryExport.js +0 -1
- package/src/gep/validationReport.js +0 -55
- package/src/gep/validator/index.js +0 -411
- package/src/gep/validator/reporter.js +0 -210
- package/src/gep/validator/sandboxExecutor.js +0 -480
- package/src/gep/validator/stakeBootstrap.js +0 -357
- package/src/gep/workspaceKeychain.js +0 -1
- package/src/ops/cleanup.js +0 -80
- package/src/ops/commentary.js +0 -60
- package/src/ops/health_check.js +0 -104
- package/src/ops/index.js +0 -11
- package/src/ops/innovation.js +0 -67
- package/src/ops/lifecycle.js +0 -798
- package/src/ops/self_repair.js +0 -76
- package/src/ops/skills_monitor.js +0 -147
- package/src/ops/trigger.js +0 -33
- package/src/proxy/clientSettings.js +0 -405
- package/src/proxy/envelope.js +0 -59
- package/src/proxy/extensions/dmHandler.js +0 -45
- package/src/proxy/extensions/sessionHandler.js +0 -141
- package/src/proxy/extensions/skillUpdater.js +0 -64
- package/src/proxy/extensions/traceControl.js +0 -1
- package/src/proxy/index.js +0 -1395
- package/src/proxy/inject.js +0 -1
- package/src/proxy/lifecycle/manager.js +0 -1568
- package/src/proxy/mailbox/state.js +0 -207
- package/src/proxy/mailbox/store.js +0 -602
- package/src/proxy/router/cache_passthrough.js +0 -26
- package/src/proxy/router/features.js +0 -84
- package/src/proxy/router/gemini_route.js +0 -154
- package/src/proxy/router/messages_route.js +0 -535
- package/src/proxy/router/model_router.js +0 -113
- package/src/proxy/router/models_route.js +0 -52
- package/src/proxy/router/ollama_route.js +0 -103
- package/src/proxy/router/responses_route.js +0 -170
- package/src/proxy/router/vertex_route.js +0 -110
- package/src/proxy/server/http.js +0 -363
- package/src/proxy/server/routes.js +0 -558
- package/src/proxy/server/settings.js +0 -115
- package/src/proxy/sync/engine.js +0 -179
- package/src/proxy/sync/inbound.js +0 -211
- package/src/proxy/sync/outbound.js +0 -361
- package/src/proxy/task/monitor.js +0 -131
- package/src/proxy/trace/extractor.js +0 -1
- package/src/proxy/trace/usage.js +0 -1
- package/src/solo/breaker.js +0 -25
- package/src/solo/gitGuard.js +0 -65
- package/src/webui/client/clientJs/assets.js +0 -111
- package/src/webui/client/clientJs/bootstrap.js +0 -92
- package/src/webui/client/clientJs/common.js +0 -77
- package/src/webui/client/clientJs/i18n.js +0 -366
- package/src/webui/client/clientJs/index.js +0 -35
- package/src/webui/client/clientJs/interactions.js +0 -351
- package/src/webui/client/clientJs/overview.js +0 -152
- package/src/webui/client/clientJs/personality.js +0 -285
- package/src/webui/client/clientJs/pipelines.js +0 -330
- package/src/webui/client/indexHtml.js +0 -221
- package/src/webui/client/static.js +0 -23
- package/src/webui/client/stylesCss.js +0 -639
- package/src/webui/client/vendor/README.md +0 -15
- package/src/webui/client/vendor/echarts.min.js +0 -45
- package/src/webui/index.js +0 -14
- package/src/webui/observer/assets.js +0 -146
- package/src/webui/observer/index.js +0 -37
- package/src/webui/observer/interactions.js +0 -127
- package/src/webui/observer/jsonl.js +0 -75
- package/src/webui/observer/paths.js +0 -46
- package/src/webui/observer/personality.js +0 -43
- package/src/webui/observer/pipelineEvents.js +0 -58
- package/src/webui/observer/redact.js +0 -63
- package/src/webui/observer/runs.js +0 -356
- package/src/webui/observer/safety.js +0 -57
- package/src/webui/observer/skills.js +0 -70
- package/src/webui/observer/status.js +0 -71
- package/src/webui/server/http.js +0 -138
- package/src/webui/server/routes.js +0 -41
|
@@ -1,285 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
exports.personalityJs = `
|
|
4
|
-
function renderPersonality(personality, memoryGraph) {
|
|
5
|
-
const current = personality.current || {};
|
|
6
|
-
const traits = ['rigor', 'creativity', 'risk_tolerance', 'caution', 'curiosity', 'persistence'];
|
|
7
|
-
const indicators = traits.filter((t) => current[t] !== undefined).map((name) => ({ name, max: 1 }));
|
|
8
|
-
const values = indicators.map((ind) => Number(current[ind.name]) || 0);
|
|
9
|
-
|
|
10
|
-
const textColor = chartTextColor();
|
|
11
|
-
if (indicators.length) {
|
|
12
|
-
ensureChart('personalityChart')?.setOption({
|
|
13
|
-
tooltip: {},
|
|
14
|
-
radar: {
|
|
15
|
-
indicator: indicators,
|
|
16
|
-
axisName: { color: textColor },
|
|
17
|
-
splitLine: { lineStyle: { color: isDarkMode() ? '#2c3235' : '#e4e7eb' } },
|
|
18
|
-
splitArea: { areaStyle: { color: ['rgba(50, 116, 217, 0.04)', 'rgba(50, 116, 217, 0.08)'] } },
|
|
19
|
-
},
|
|
20
|
-
series: [{
|
|
21
|
-
type: 'radar',
|
|
22
|
-
data: [{ value: values, name: 'current', areaStyle: { color: 'rgba(50, 116, 217, 0.4)' }, lineStyle: { color: '#3274d9' } }],
|
|
23
|
-
}],
|
|
24
|
-
});
|
|
25
|
-
} else {
|
|
26
|
-
$('personalityChart').innerHTML = '<p class="muted" style="padding:40px;text-align:center">' + esc(t('personality.empty.chart')) + '</p>';
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
$('personality-detail').innerHTML = current && Object.keys(current).length
|
|
30
|
-
? kv(Object.entries(current).slice(0, 12))
|
|
31
|
-
: '<p class="muted">' + esc(t('personality.empty.detail')) + '</p>';
|
|
32
|
-
|
|
33
|
-
renderMemoryGraph(memoryGraph);
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
const MEMORY_GRAPH_KIND_COLORS = {
|
|
37
|
-
signal: '#3274d9',
|
|
38
|
-
hypothesis: '#17a2b8',
|
|
39
|
-
attempt: '#ffc107',
|
|
40
|
-
outcome: '#28a745',
|
|
41
|
-
reflection: '#6f42c1',
|
|
42
|
-
};
|
|
43
|
-
|
|
44
|
-
function memoryGraphCategories() {
|
|
45
|
-
return [
|
|
46
|
-
{ name: t('personality.cat.event') },
|
|
47
|
-
{ name: t('personality.cat.gene') },
|
|
48
|
-
{ name: t('personality.cat.signal') },
|
|
49
|
-
{ name: t('personality.cat.outcome') },
|
|
50
|
-
{ name: t('personality.cat.mutation') },
|
|
51
|
-
];
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
function shortenGeneId(geneId) {
|
|
55
|
-
if (!geneId) return '';
|
|
56
|
-
return String(geneId).replace(/^gene_gep_/, '').replace(/^gene_/, '').slice(0, 18);
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
function shortTime(ts) {
|
|
60
|
-
if (!ts) return '';
|
|
61
|
-
const d = new Date(ts);
|
|
62
|
-
if (isNaN(d.getTime())) return '';
|
|
63
|
-
return d.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit', second: '2-digit' });
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
function buildMemoryGraphData(items) {
|
|
67
|
-
const nodes = new Map();
|
|
68
|
-
const links = [];
|
|
69
|
-
|
|
70
|
-
const upsert = (id, init) => {
|
|
71
|
-
if (!id) return null;
|
|
72
|
-
if (!nodes.has(id)) {
|
|
73
|
-
nodes.set(id, { id, refCount: 1, ...init });
|
|
74
|
-
} else {
|
|
75
|
-
const existing = nodes.get(id);
|
|
76
|
-
existing.refCount += 1;
|
|
77
|
-
existing.symbolSize = Math.min(48, (existing.symbolSize || 20) + 1.5);
|
|
78
|
-
}
|
|
79
|
-
return nodes.get(id);
|
|
80
|
-
};
|
|
81
|
-
|
|
82
|
-
items.forEach((evt) => {
|
|
83
|
-
try {
|
|
84
|
-
addEventNode(evt, upsert, links);
|
|
85
|
-
} catch (_) { /* skip malformed entry */ }
|
|
86
|
-
});
|
|
87
|
-
|
|
88
|
-
return { nodes: Array.from(nodes.values()), links };
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
function addEventNode(evt, upsert, links) {
|
|
92
|
-
const kind = evt.kind || 'event';
|
|
93
|
-
const eventId = 'evt_' + (evt.id || Math.random().toString(36).slice(2, 8));
|
|
94
|
-
const outcomeStatus = evt.outcome && (evt.outcome.status || evt.outcome.predicted_outcome?.status);
|
|
95
|
-
const score = evt.outcome && (evt.outcome.score ?? evt.outcome.predicted_outcome?.score);
|
|
96
|
-
|
|
97
|
-
const eventColor = kind === 'outcome' && outcomeStatus
|
|
98
|
-
? (outcomeStatus === 'success' ? '#28a745' : outcomeStatus === 'failed' ? '#dc3545' : '#ffc107')
|
|
99
|
-
: (MEMORY_GRAPH_KIND_COLORS[kind] || '#3274d9');
|
|
100
|
-
|
|
101
|
-
const tsLabel = shortTime(evt.ts);
|
|
102
|
-
const eventLabel = tsLabel ? kind + ' · ' + tsLabel : kind;
|
|
103
|
-
|
|
104
|
-
upsert(eventId, {
|
|
105
|
-
name: eventLabel,
|
|
106
|
-
symbolSize: kind === 'outcome' ? 30 : 24,
|
|
107
|
-
itemStyle: { color: eventColor, borderColor: 'rgba(255,255,255,0.5)', borderWidth: 1 },
|
|
108
|
-
category: 0,
|
|
109
|
-
nodeKind: 'event',
|
|
110
|
-
info: { kind, ts: evt.ts, eventId: evt.id, outcomeStatus, score, geneId: evt.gene?.id, mutationCategory: evt.mutation?.category, signals: extractSignals(evt) },
|
|
111
|
-
});
|
|
112
|
-
|
|
113
|
-
linkGene(evt, eventId, upsert, links);
|
|
114
|
-
linkSignals(evt, eventId, upsert, links);
|
|
115
|
-
linkOutcome(evt, eventId, upsert, links, outcomeStatus, score);
|
|
116
|
-
linkMutation(evt, eventId, upsert, links);
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
function extractSignals(evt) {
|
|
120
|
-
if (evt.signal && Array.isArray(evt.signal.signals)) return evt.signal.signals;
|
|
121
|
-
if (Array.isArray(evt.signals)) return evt.signals;
|
|
122
|
-
return [];
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
function linkGene(evt, eventId, upsert, links) {
|
|
126
|
-
const geneId = evt.gene && (evt.gene.id || evt.gene);
|
|
127
|
-
if (typeof geneId !== 'string') return;
|
|
128
|
-
const nodeId = 'g_' + geneId;
|
|
129
|
-
upsert(nodeId, {
|
|
130
|
-
name: shortenGeneId(geneId),
|
|
131
|
-
symbolSize: 26,
|
|
132
|
-
itemStyle: { color: '#28a745' },
|
|
133
|
-
category: 1,
|
|
134
|
-
nodeKind: 'gene',
|
|
135
|
-
info: { geneId, category: evt.gene?.category },
|
|
136
|
-
});
|
|
137
|
-
links.push({ source: eventId, target: nodeId });
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
function linkSignals(evt, eventId, upsert, links) {
|
|
141
|
-
const signals = extractSignals(evt);
|
|
142
|
-
signals.slice(0, 4).forEach((sig) => {
|
|
143
|
-
const nodeId = 's_' + sig;
|
|
144
|
-
upsert(nodeId, {
|
|
145
|
-
name: sig,
|
|
146
|
-
symbolSize: 20,
|
|
147
|
-
itemStyle: { color: '#ffc107' },
|
|
148
|
-
category: 2,
|
|
149
|
-
nodeKind: 'signal',
|
|
150
|
-
info: { signal: sig },
|
|
151
|
-
});
|
|
152
|
-
links.push({ source: nodeId, target: eventId, lineStyle: { type: 'dashed' } });
|
|
153
|
-
});
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
function linkOutcome(evt, eventId, upsert, links, outcomeStatus, score) {
|
|
157
|
-
if (typeof outcomeStatus !== 'string') return;
|
|
158
|
-
const nodeId = 'o_' + outcomeStatus;
|
|
159
|
-
const color = outcomeStatus === 'success' ? '#28a745' : outcomeStatus === 'failed' ? '#dc3545' : '#ffc107';
|
|
160
|
-
upsert(nodeId, {
|
|
161
|
-
name: outcomeStatus,
|
|
162
|
-
symbolSize: 24,
|
|
163
|
-
itemStyle: { color },
|
|
164
|
-
category: 3,
|
|
165
|
-
nodeKind: 'outcome',
|
|
166
|
-
info: { status: outcomeStatus, lastScore: score },
|
|
167
|
-
});
|
|
168
|
-
links.push({ source: eventId, target: nodeId });
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
function linkMutation(evt, eventId, upsert, links) {
|
|
172
|
-
const category = evt.mutation && evt.mutation.category;
|
|
173
|
-
if (typeof category !== 'string') return;
|
|
174
|
-
const nodeId = 'm_' + category;
|
|
175
|
-
upsert(nodeId, {
|
|
176
|
-
name: category,
|
|
177
|
-
symbolSize: 22,
|
|
178
|
-
itemStyle: { color: '#dc3545' },
|
|
179
|
-
category: 4,
|
|
180
|
-
nodeKind: 'mutation',
|
|
181
|
-
info: { category },
|
|
182
|
-
});
|
|
183
|
-
links.push({ source: eventId, target: nodeId, lineStyle: { type: 'dotted' } });
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
function memoryGraphTooltip(params) {
|
|
187
|
-
if (params.dataType === 'edge') return '';
|
|
188
|
-
const d = params.data || {};
|
|
189
|
-
const info = d.info || {};
|
|
190
|
-
const refRow = d.refCount > 1 ? mgRow(t('personality.tooltip.referenced'), d.refCount + ' ' + t('personality.tooltip.referencedTimes')) : '';
|
|
191
|
-
const title = '<div style="font-weight:600;margin-bottom:6px">' + esc(d.nodeKind || 'node') + ' · ' + esc(d.name) + '</div>';
|
|
192
|
-
|
|
193
|
-
if (d.nodeKind === 'event') {
|
|
194
|
-
return title + mgTooltipBody([
|
|
195
|
-
[t('personality.tooltip.kind'), info.kind],
|
|
196
|
-
[t('personality.tooltip.time'), formatTime(info.ts)],
|
|
197
|
-
[t('personality.tooltip.eventId'), info.eventId],
|
|
198
|
-
[t('personality.tooltip.gene'), info.geneId ? shortenGeneId(info.geneId) : null],
|
|
199
|
-
[t('personality.tooltip.signals'), info.signals?.length ? info.signals.join(', ') : null],
|
|
200
|
-
[t('personality.tooltip.outcome'), info.outcomeStatus ? tStatus(info.outcomeStatus) : null],
|
|
201
|
-
[t('personality.tooltip.score'), info.score != null ? info.score : null],
|
|
202
|
-
[t('personality.tooltip.mutation'), info.mutationCategory],
|
|
203
|
-
]) + refRow;
|
|
204
|
-
}
|
|
205
|
-
if (d.nodeKind === 'gene') return title + mgTooltipBody([[t('personality.tooltip.geneId'), info.geneId], [t('personality.tooltip.category'), info.category]]) + refRow;
|
|
206
|
-
if (d.nodeKind === 'signal') return title + mgTooltipBody([[t('personality.tooltip.signal'), info.signal]]) + refRow;
|
|
207
|
-
if (d.nodeKind === 'outcome') return title + mgTooltipBody([[t('personality.tooltip.status'), tStatus(info.status)], [t('personality.tooltip.lastScore'), info.lastScore]]) + refRow;
|
|
208
|
-
if (d.nodeKind === 'mutation') return title + mgTooltipBody([[t('personality.tooltip.category'), info.category]]) + refRow;
|
|
209
|
-
return title + refRow;
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
function mgTooltipBody(rows) {
|
|
213
|
-
const filtered = rows.filter(([, v]) => v != null && v !== '');
|
|
214
|
-
if (!filtered.length) return '';
|
|
215
|
-
return '<div style="font-size:12px;line-height:1.5">' +
|
|
216
|
-
filtered.map(([k, v]) => mgRow(k, v)).join('') +
|
|
217
|
-
'</div>';
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
function mgRow(label, value) {
|
|
221
|
-
return '<div><span style="color:#8e99a4">' + esc(label) + ':</span> ' + esc(value) + '</div>';
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
function renderMemoryGraph(graph) {
|
|
225
|
-
const isDark = isDarkMode();
|
|
226
|
-
const textColor = chartTextColor();
|
|
227
|
-
if (!graph.exists || !graph.items.length) {
|
|
228
|
-
$('memory-graph-chart').innerHTML = '<p class="muted" style="padding:40px;text-align:center">' + esc(t('personality.empty.graph')) + '</p>';
|
|
229
|
-
return;
|
|
230
|
-
}
|
|
231
|
-
|
|
232
|
-
const { nodes, links } = buildMemoryGraphData(graph.items.slice(0, 100));
|
|
233
|
-
const categories = memoryGraphCategories();
|
|
234
|
-
|
|
235
|
-
ensureChart('memory-graph-chart')?.setOption({
|
|
236
|
-
tooltip: {
|
|
237
|
-
trigger: 'item',
|
|
238
|
-
enterable: true,
|
|
239
|
-
backgroundColor: isDark ? 'rgba(24,27,31,0.95)' : 'rgba(255,255,255,0.98)',
|
|
240
|
-
borderColor: isDark ? '#2c3235' : '#e4e7eb',
|
|
241
|
-
textStyle: { color: textColor, fontSize: 12 },
|
|
242
|
-
extraCssText: 'max-width: 320px; box-shadow: 0 4px 12px rgba(0,0,0,0.15);',
|
|
243
|
-
formatter: memoryGraphTooltip,
|
|
244
|
-
},
|
|
245
|
-
legend: { data: categories.map((c) => c.name), top: 0, textStyle: { color: textColor } },
|
|
246
|
-
series: [{
|
|
247
|
-
type: 'graph',
|
|
248
|
-
layout: 'force',
|
|
249
|
-
data: nodes,
|
|
250
|
-
links,
|
|
251
|
-
categories,
|
|
252
|
-
roam: true,
|
|
253
|
-
draggable: true,
|
|
254
|
-
cursor: 'grab',
|
|
255
|
-
label: {
|
|
256
|
-
show: true,
|
|
257
|
-
fontSize: 10,
|
|
258
|
-
color: textColor,
|
|
259
|
-
position: 'right',
|
|
260
|
-
formatter: (p) => (p.data?.refCount > 1 ? p.data.name + ' ×' + p.data.refCount : p.data?.name || ''),
|
|
261
|
-
},
|
|
262
|
-
emphasis: {
|
|
263
|
-
focus: 'adjacency',
|
|
264
|
-
scale: 1.1,
|
|
265
|
-
label: { show: true, fontWeight: 'bold' },
|
|
266
|
-
lineStyle: { width: 3 },
|
|
267
|
-
},
|
|
268
|
-
lineStyle: { color: isDark ? '#3a4045' : '#d8dde2', width: 1, curveness: 0.1, opacity: 0.7 },
|
|
269
|
-
force: { repulsion: 180, edgeLength: [60, 120], gravity: 0.06, friction: 0.6 },
|
|
270
|
-
}],
|
|
271
|
-
});
|
|
272
|
-
}
|
|
273
|
-
|
|
274
|
-
async function loadPersonality() {
|
|
275
|
-
try {
|
|
276
|
-
const [personality, graph] = await Promise.all([
|
|
277
|
-
api('/webui/personality'),
|
|
278
|
-
api('/webui/memory-graph?limit=100'),
|
|
279
|
-
]);
|
|
280
|
-
renderPersonality(personality, graph);
|
|
281
|
-
} catch (err) {
|
|
282
|
-
console.error(err);
|
|
283
|
-
}
|
|
284
|
-
}
|
|
285
|
-
`;
|
|
@@ -1,330 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
exports.pipelinesJs = `
|
|
4
|
-
function renderRuns(result) {
|
|
5
|
-
const runs = result.data || [];
|
|
6
|
-
const tbody = document.querySelector('#runsTable tbody');
|
|
7
|
-
if (!runs.length) {
|
|
8
|
-
tbody.innerHTML = '<tr><td colspan="5" style="text-align:center;color:var(--text-muted)">' + esc(t('pipelines.runs.empty')) + '</td></tr>';
|
|
9
|
-
renderScoreTrend([]);
|
|
10
|
-
return;
|
|
11
|
-
}
|
|
12
|
-
tbody.innerHTML = runs.map((run) =>
|
|
13
|
-
'<tr data-run="' + esc(run.runId) + '">' +
|
|
14
|
-
'<td><strong>' + esc(run.runId) + '</strong></td>' +
|
|
15
|
-
'<td><span class="status-indicator ' + getStatusClass(run.status) + '"></span>' + esc(tStatus(run.status)) + '</td>' +
|
|
16
|
-
'<td>' + esc(run.selectedGeneId || '-') + '</td>' +
|
|
17
|
-
'<td>' + scoreBar(run.score) + '</td>' +
|
|
18
|
-
'<td>' + esc(formatTime(run.updatedAt)) + '</td>' +
|
|
19
|
-
'</tr>'
|
|
20
|
-
).join('');
|
|
21
|
-
document.querySelectorAll('#runsTable tbody tr[data-run]').forEach((tr) => {
|
|
22
|
-
tr.addEventListener('click', () => loadRun(tr.getAttribute('data-run')));
|
|
23
|
-
});
|
|
24
|
-
renderScoreTrend(runs);
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
function validationDimensionLabel(d) {
|
|
28
|
-
// Validation dimensions ride on stable enum tokens ('stable_no_error',
|
|
29
|
-
// 'heuristic_delta', etc). Look up a localized label; fall back to the
|
|
30
|
-
// raw token so unknown dimensions still render.
|
|
31
|
-
const key = 'pipelines.dim.' + d;
|
|
32
|
-
return I18N_DICT[key] ? t(key) : d;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
function renderValidationBlock(validation, runStatus) {
|
|
36
|
-
if (!validation) {
|
|
37
|
-
const hint = runStatus === 'review_pending'
|
|
38
|
-
? t('pipelines.detail.validation.hint.reviewPending')
|
|
39
|
-
: runStatus === 'running' || runStatus === 'pending'
|
|
40
|
-
? t('pipelines.detail.validation.hint.running')
|
|
41
|
-
: t('pipelines.detail.validation.hint.none');
|
|
42
|
-
return '<div class="detail-block"><h4>' + esc(t('pipelines.detail.validation.title')) + '</h4><p class="muted small">' + esc(hint) + '</p></div>';
|
|
43
|
-
}
|
|
44
|
-
const score = typeof validation.score === 'number' ? validation.score : null;
|
|
45
|
-
const statusCls = validation.status === 'success' ? 'success' : validation.status === 'failed' ? 'failed' : 'unknown';
|
|
46
|
-
const scoreColor = score === null ? '#888' : score >= 0.7 ? '#28a745' : score >= 0.5 ? '#ffc107' : '#dc3545';
|
|
47
|
-
const dims = (validation.dimensions || []).map((d) =>
|
|
48
|
-
'<span class="pill validation-dim">' + esc(validationDimensionLabel(d)) + '</span>'
|
|
49
|
-
).join('') || '<span class="muted small">' + esc(t('pipelines.detail.validation.noDimensions')) + '</span>';
|
|
50
|
-
|
|
51
|
-
let html = '<div class="detail-block validation-block"><h4>' + esc(t('pipelines.detail.validation.title')) + '</h4>';
|
|
52
|
-
html += '<div class="validation-summary">' +
|
|
53
|
-
'<div class="validation-status"><span class="status-indicator ' + statusCls + '"></span>' +
|
|
54
|
-
'<strong>' + esc(tStatus(validation.status || 'unknown')) + '</strong>' +
|
|
55
|
-
'</div>';
|
|
56
|
-
if (score !== null) {
|
|
57
|
-
html += '<div class="validation-score-wrap">' +
|
|
58
|
-
'<div class="validation-score-label">' + esc(t('pipelines.detail.validation.score')) + '</div>' +
|
|
59
|
-
'<div class="score-bar score-bar-lg">' +
|
|
60
|
-
'<div class="score-bar-fill" style="width:' + (score * 100).toFixed(0) + '%;background:' + scoreColor + '"></div>' +
|
|
61
|
-
'<span class="score-bar-text">' + (score * 100).toFixed(1) + '%</span>' +
|
|
62
|
-
'</div></div>';
|
|
63
|
-
}
|
|
64
|
-
html += '</div>';
|
|
65
|
-
html += '<div class="validation-dims"><span class="muted small">' + esc(t('pipelines.detail.validation.dimensions')) + '</span> ' + dims + '</div>';
|
|
66
|
-
if (validation.observedSignals && validation.observedSignals.length) {
|
|
67
|
-
html += '<div class="validation-observed"><span class="muted small">' + esc(t('pipelines.detail.validation.observed')) + '</span> ' +
|
|
68
|
-
pillList(validation.observedSignals, 'signal') + '</div>';
|
|
69
|
-
}
|
|
70
|
-
if (validation.predictive) {
|
|
71
|
-
const entries = Object.entries(validation.predictive).slice(0, 6);
|
|
72
|
-
html += '<details class="validation-predictive"><summary>' + esc(t('pipelines.detail.validation.predictive')) + '</summary>' + kv(entries) + '</details>';
|
|
73
|
-
}
|
|
74
|
-
if (validation.timestamp) {
|
|
75
|
-
html += '<p class="muted small" style="margin-top:8px">' + esc(t('pipelines.detail.validation.validatedAt')) + esc(formatTime(validation.timestamp)) + '</p>';
|
|
76
|
-
}
|
|
77
|
-
html += '</div>';
|
|
78
|
-
return html;
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
function scoreBar(score) {
|
|
82
|
-
if (typeof score !== 'number') return '<span class="muted small">—</span>';
|
|
83
|
-
const pct = Math.round(score * 100);
|
|
84
|
-
const color = score >= 0.7 ? '#28a745' : score >= 0.5 ? '#ffc107' : '#dc3545';
|
|
85
|
-
return '<div class="score-bar" title="' + score.toFixed(3) + '">' +
|
|
86
|
-
'<div class="score-bar-fill" style="width:' + pct + '%;background:' + color + '"></div>' +
|
|
87
|
-
'<span class="score-bar-text">' + pct + '%</span></div>';
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
function renderScoreTrend(runs) {
|
|
91
|
-
const el = document.getElementById('scoreTrendChart');
|
|
92
|
-
if (!el) return;
|
|
93
|
-
const scored = runs.filter((r) => typeof r.score === 'number')
|
|
94
|
-
.sort((a, b) => new Date(a.finishedAt || a.updatedAt) - new Date(b.finishedAt || b.updatedAt));
|
|
95
|
-
if (!scored.length) {
|
|
96
|
-
// Dispose any prior chart bound to this element so the empty-state
|
|
97
|
-
// innerHTML write doesn't collide with ECharts owning the canvas.
|
|
98
|
-
// Otherwise the next non-empty render would reuse a dead instance
|
|
99
|
-
// and ECharts would warn about re-initializing an active container.
|
|
100
|
-
if (state.charts['scoreTrendChart']) {
|
|
101
|
-
state.charts['scoreTrendChart'].dispose();
|
|
102
|
-
delete state.charts['scoreTrendChart'];
|
|
103
|
-
}
|
|
104
|
-
el.innerHTML = '<p class="muted small" style="padding:24px 0;text-align:center">' + esc(t('pipelines.chart.scoreTrend.empty')) + '</p>';
|
|
105
|
-
return;
|
|
106
|
-
}
|
|
107
|
-
// Transitioning from empty-state to chart: the empty <p> left in the
|
|
108
|
-
// container has to go before ensureChart's first init, otherwise
|
|
109
|
-
// ECharts measures the <p> as its viewport.
|
|
110
|
-
if (!state.charts['scoreTrendChart']) el.innerHTML = '';
|
|
111
|
-
// Use ensureChart so the instance is tracked in state.charts and gets
|
|
112
|
-
// resized on window resize / disposed on theme + locale toggle, same
|
|
113
|
-
// as every other chart on the page.
|
|
114
|
-
const chart = ensureChart('scoreTrendChart');
|
|
115
|
-
const textColor = chartTextColor();
|
|
116
|
-
chart.setOption({
|
|
117
|
-
grid: { left: 50, right: 20, top: 20, bottom: 30 },
|
|
118
|
-
tooltip: {
|
|
119
|
-
trigger: 'axis',
|
|
120
|
-
// ECharts renders the formatter return value as HTML, so every
|
|
121
|
-
// dynamic field that originates from a run record must be esc()'d
|
|
122
|
-
// (run IDs and gene IDs are user/agent-supplied strings that have
|
|
123
|
-
// historically contained '/' and other HTML-meaningful chars).
|
|
124
|
-
formatter: (params) => {
|
|
125
|
-
const p = params[0];
|
|
126
|
-
const r = scored[p.dataIndex];
|
|
127
|
-
return '<strong>' + esc(r.runId) + '</strong><br/>' +
|
|
128
|
-
esc(t('pipelines.col.gene')) + ': ' + esc(r.selectedGeneId || '-') + '<br/>' +
|
|
129
|
-
esc(t('pipelines.col.score')) + ': <strong>' + esc((r.score || 0).toFixed(3)) + '</strong><br/>' +
|
|
130
|
-
esc(formatTime(r.finishedAt || r.updatedAt));
|
|
131
|
-
},
|
|
132
|
-
},
|
|
133
|
-
xAxis: {
|
|
134
|
-
type: 'category',
|
|
135
|
-
data: scored.map((r) => r.runId.slice(-8)),
|
|
136
|
-
axisLabel: { color: textColor, fontSize: 10 },
|
|
137
|
-
},
|
|
138
|
-
yAxis: {
|
|
139
|
-
type: 'value',
|
|
140
|
-
min: 0, max: 1,
|
|
141
|
-
axisLabel: { color: textColor, formatter: (v) => (v * 100).toFixed(0) + '%' },
|
|
142
|
-
splitLine: { lineStyle: { color: isDarkMode() ? '#2a3038' : '#e9ecef' } },
|
|
143
|
-
},
|
|
144
|
-
series: [{
|
|
145
|
-
type: 'line',
|
|
146
|
-
smooth: true,
|
|
147
|
-
data: scored.map((r) => r.score),
|
|
148
|
-
areaStyle: { opacity: 0.2 },
|
|
149
|
-
lineStyle: { width: 2, color: '#3274d9' },
|
|
150
|
-
itemStyle: { color: '#3274d9' },
|
|
151
|
-
markLine: {
|
|
152
|
-
silent: true,
|
|
153
|
-
symbol: 'none',
|
|
154
|
-
lineStyle: { type: 'dashed', color: '#28a745' },
|
|
155
|
-
data: [{ yAxis: 0.7, label: { formatter: t('pipelines.chart.scoreTrend.passLine'), color: '#28a745' } }],
|
|
156
|
-
},
|
|
157
|
-
}],
|
|
158
|
-
});
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
function renderRunDetail(run) {
|
|
162
|
-
const phases = run.phases || [];
|
|
163
|
-
const detail = run.detail || {};
|
|
164
|
-
|
|
165
|
-
let html = '<div class="run-header">' +
|
|
166
|
-
'<h3>' + esc(run.runId) + '</h3>' +
|
|
167
|
-
'<div class="run-meta">' +
|
|
168
|
-
'<span>' + esc(t('pipelines.col.status')) + ': <span class="status-indicator ' + getStatusClass(run.status) + '"></span><strong>' + esc(tStatus(run.status)) + '</strong></span>' +
|
|
169
|
-
'<span>' + esc(t('pipelines.col.gene')) + ': <strong>' + esc(run.selectedGeneId || '-') + '</strong></span>' +
|
|
170
|
-
'<span>' + esc(t('pipelines.col.updated')) + ': <strong>' + esc(formatTime(run.updatedAt)) + '</strong></span>' +
|
|
171
|
-
'</div></div>';
|
|
172
|
-
|
|
173
|
-
html += '<div class="run-body">';
|
|
174
|
-
|
|
175
|
-
html += '<div><h4>' + esc(t('pipelines.timeline')) + '</h4><ul class="timeline">';
|
|
176
|
-
html += phases.map((phase) => {
|
|
177
|
-
const cls = phase.status === 'success' ? 'success' :
|
|
178
|
-
phase.status === 'failed' ? 'failed' :
|
|
179
|
-
phase.status === 'running' || phase.status === 'pending' ? 'running' :
|
|
180
|
-
phase.status === 'blocked' ? 'blocked' : '';
|
|
181
|
-
return '<li class="' + cls + '">' +
|
|
182
|
-
'<div class="timeline-title">' + esc(phase.phase) + ' <span class="muted small">' + esc(tStatus(phase.status)) + '</span></div>' +
|
|
183
|
-
'<p class="timeline-desc">' + esc(phase.summary) + '</p>' +
|
|
184
|
-
'</li>';
|
|
185
|
-
}).join('');
|
|
186
|
-
html += '</ul></div>';
|
|
187
|
-
|
|
188
|
-
html += '<div><h4>' + esc(t('pipelines.runGraph')) + '</h4><div id="runGraph" class="chart-container" style="height: 360px;"></div></div>';
|
|
189
|
-
|
|
190
|
-
html += '</div>';
|
|
191
|
-
|
|
192
|
-
if (detail) {
|
|
193
|
-
html += '<div class="run-detail-grid">';
|
|
194
|
-
html += '<div class="detail-block"><h4>' + esc(t('pipelines.detail.triggerSignals')) + '</h4>' +
|
|
195
|
-
'<p class="muted small" style="margin:-4px 0 8px 0">' + esc(t('pipelines.detail.triggerSignals.desc')) + '</p>' +
|
|
196
|
-
pillList(detail.signals, 'signal') + '</div>';
|
|
197
|
-
if (detail.selector) {
|
|
198
|
-
html += '<div class="detail-block"><h4>' + esc(t('pipelines.detail.selector')) + '</h4>' +
|
|
199
|
-
kv([
|
|
200
|
-
[t('pipelines.detail.selector.selected'), detail.selector.selected],
|
|
201
|
-
[t('pipelines.detail.selector.path'), detail.selector.selectionPath || detail.selector.selection_path],
|
|
202
|
-
[t('pipelines.detail.selector.memoryUsed'), detail.selector.memoryUsed || detail.selector.memory_used],
|
|
203
|
-
]) +
|
|
204
|
-
'<ul class="reason-list">' + (detail.selector.reason || []).map(r => '<li>' + esc(r) + '</li>').join('') + '</ul>' +
|
|
205
|
-
'</div>';
|
|
206
|
-
}
|
|
207
|
-
if (detail.mutation) {
|
|
208
|
-
html += '<div class="detail-block"><h4>' + esc(t('pipelines.detail.mutation')) + '</h4>' + kv([
|
|
209
|
-
[t('pipelines.detail.mutation.id'), detail.mutation.id],
|
|
210
|
-
[t('pipelines.detail.mutation.category'), detail.mutation.category],
|
|
211
|
-
[t('pipelines.detail.mutation.targetType'), detail.mutation.targetType],
|
|
212
|
-
[t('pipelines.detail.mutation.strategySteps'), detail.mutation.strategySteps],
|
|
213
|
-
[t('pipelines.detail.mutation.triggerSignals'), (detail.mutation.triggerSignals || []).join(', ') || '-'],
|
|
214
|
-
]) + '</div>';
|
|
215
|
-
}
|
|
216
|
-
html += renderValidationBlock(detail.validation, run.status);
|
|
217
|
-
if (detail.blastRadius) {
|
|
218
|
-
html += '<div class="detail-block"><h4>' + esc(t('pipelines.detail.blastRadius')) + '</h4>' + kv([
|
|
219
|
-
[t('pipelines.detail.blastRadius.files'), detail.blastRadius.files],
|
|
220
|
-
[t('pipelines.detail.blastRadius.lines'), detail.blastRadius.lines],
|
|
221
|
-
[t('pipelines.detail.blastRadius.risk'), detail.blastRadius.risk_level || detail.blastRadius.risk],
|
|
222
|
-
]) + '</div>';
|
|
223
|
-
}
|
|
224
|
-
if (detail.personalityState) {
|
|
225
|
-
html += '<div class="detail-block"><h4>' + esc(t('pipelines.detail.personalityState')) + '</h4>' + kv(
|
|
226
|
-
Object.entries(detail.personalityState).slice(0, 8)
|
|
227
|
-
) + '</div>';
|
|
228
|
-
}
|
|
229
|
-
if (detail.initialUserPrompt) {
|
|
230
|
-
html += '<div class="detail-block"><h4>' + esc(t('pipelines.detail.initialUserPrompt')) + '</h4><pre class="snippet">' + esc(detail.initialUserPrompt) + '</pre></div>';
|
|
231
|
-
}
|
|
232
|
-
html += '</div>';
|
|
233
|
-
}
|
|
234
|
-
|
|
235
|
-
$('run-detail').innerHTML = html;
|
|
236
|
-
|
|
237
|
-
setTimeout(() => renderRunGraph(run, detail), 0);
|
|
238
|
-
}
|
|
239
|
-
|
|
240
|
-
function renderRunGraph(run, detail) {
|
|
241
|
-
const chartEl = document.getElementById('runGraph');
|
|
242
|
-
if (!chartEl) return;
|
|
243
|
-
// <div id="run-detail"> is rewritten on every loadRun call (see
|
|
244
|
-
// renderRunDetail), which detaches the previous #runGraph DOM. A
|
|
245
|
-
// cached ECharts instance from the previous run is bound to that
|
|
246
|
-
// detached element and would silently render to nothing on
|
|
247
|
-
// setOption. Dispose the stale instance before re-initializing
|
|
248
|
-
// against the fresh #runGraph so disposeAllCharts() on theme
|
|
249
|
-
// toggle and the window-resize handler keep working.
|
|
250
|
-
if (state.charts['runGraph']) {
|
|
251
|
-
state.charts['runGraph'].dispose();
|
|
252
|
-
delete state.charts['runGraph'];
|
|
253
|
-
}
|
|
254
|
-
const chart = ensureChart('runGraph');
|
|
255
|
-
const textColor = chartTextColor();
|
|
256
|
-
const isDark = isDarkMode();
|
|
257
|
-
|
|
258
|
-
const labelRun = t('personality.cat.run');
|
|
259
|
-
const labelGene = t('personality.cat.gene');
|
|
260
|
-
const labelEvent = t('personality.cat.event');
|
|
261
|
-
const nodes = [{ id: 'Run', name: labelRun + '\\n' + run.runId.slice(-8), symbolSize: 56, itemStyle: { color: '#3274d9' }, category: 0 }];
|
|
262
|
-
const edges = [];
|
|
263
|
-
const categories = [
|
|
264
|
-
{ name: labelRun },
|
|
265
|
-
{ name: labelGene },
|
|
266
|
-
{ name: t('personality.cat.signal') },
|
|
267
|
-
{ name: labelEvent },
|
|
268
|
-
{ name: t('personality.cat.asset') },
|
|
269
|
-
];
|
|
270
|
-
|
|
271
|
-
if (run.selectedGeneId) {
|
|
272
|
-
nodes.push({ id: 'Gene', name: labelGene + '\\n' + run.selectedGeneId.replace('gene_gep_', ''), symbolSize: 44, itemStyle: { color: '#28a745' }, category: 1 });
|
|
273
|
-
edges.push({ source: 'Run', target: 'Gene' });
|
|
274
|
-
}
|
|
275
|
-
(detail.signals || []).slice(0, 6).forEach((sig, i) => {
|
|
276
|
-
const id = 'Sig' + i;
|
|
277
|
-
nodes.push({ id, name: sig, symbolSize: 30, itemStyle: { color: '#ffc107' }, category: 2 });
|
|
278
|
-
edges.push({ source: id, target: 'Run' });
|
|
279
|
-
if (run.selectedGeneId) edges.push({ source: id, target: 'Gene', lineStyle: { type: 'dashed' } });
|
|
280
|
-
});
|
|
281
|
-
(run.evidence || []).slice(0, 5).forEach((ev, i) => {
|
|
282
|
-
const id = 'Ev' + i;
|
|
283
|
-
nodes.push({ id, name: labelEvent + '\\n' + (ev.id || '').slice(-6), symbolSize: 28, itemStyle: { color: '#dc3545' }, category: 3 });
|
|
284
|
-
edges.push({ source: 'Run', target: id });
|
|
285
|
-
});
|
|
286
|
-
(run.assets || []).slice(0, 5).forEach((a, i) => {
|
|
287
|
-
const id = 'Ast' + i;
|
|
288
|
-
nodes.push({ id, name: a.action || 'asset', symbolSize: 26, itemStyle: { color: '#6f42c1' }, category: 4 });
|
|
289
|
-
edges.push({ source: 'Run', target: id });
|
|
290
|
-
});
|
|
291
|
-
|
|
292
|
-
chart.setOption({
|
|
293
|
-
tooltip: {},
|
|
294
|
-
legend: { data: categories.map(c => c.name), bottom: 0, textStyle: { color: textColor } },
|
|
295
|
-
series: [{
|
|
296
|
-
type: 'graph',
|
|
297
|
-
layout: 'force',
|
|
298
|
-
data: nodes,
|
|
299
|
-
links: edges,
|
|
300
|
-
categories,
|
|
301
|
-
roam: true,
|
|
302
|
-
draggable: true,
|
|
303
|
-
cursor: 'grab',
|
|
304
|
-
label: { show: true, color: textColor, fontSize: 10 },
|
|
305
|
-
lineStyle: { color: isDark ? '#5c6975' : '#cdd3da', width: 1.5, curveness: 0.15 },
|
|
306
|
-
force: { repulsion: 220, edgeLength: 90 },
|
|
307
|
-
}],
|
|
308
|
-
});
|
|
309
|
-
}
|
|
310
|
-
|
|
311
|
-
async function loadRun(runId) {
|
|
312
|
-
state.selectedRunId = runId;
|
|
313
|
-
$('run-detail').innerHTML = '<p class="muted">' + esc(t('pipelines.runs.loadingTrace')) + '</p>';
|
|
314
|
-
try {
|
|
315
|
-
const run = await api('/webui/runs/' + encodeURIComponent(runId));
|
|
316
|
-
renderRunDetail(run);
|
|
317
|
-
} catch (err) {
|
|
318
|
-
$('run-detail').innerHTML = '<p class="status-failed">' + esc(t('pipelines.runs.failedToLoad')) + esc(err.message) + '</p>';
|
|
319
|
-
}
|
|
320
|
-
}
|
|
321
|
-
|
|
322
|
-
async function loadPipelines() {
|
|
323
|
-
try {
|
|
324
|
-
const runs = await api('/webui/runs?limit=50');
|
|
325
|
-
renderRuns(runs);
|
|
326
|
-
} catch (err) {
|
|
327
|
-
console.error(err);
|
|
328
|
-
}
|
|
329
|
-
}
|
|
330
|
-
`;
|