@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.
- 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 -3586
- 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/skills/_meta/SKILL.md +0 -41
- package/skills/index.json +0 -14
- 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 -590
- 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 -320
- 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/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,351 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
exports.interactionsJs = `
|
|
4
|
-
const HUB_ACTIVITY_STATE = { layer: 'all', hideHeartbeats: true, events: [] };
|
|
5
|
-
|
|
6
|
-
function buildHubActivityEvents(calls, atpProofs, atpOrders, lifecycleEvents) {
|
|
7
|
-
const events = [];
|
|
8
|
-
(lifecycleEvents || []).forEach((e) => events.push({
|
|
9
|
-
layer: 'lifecycle',
|
|
10
|
-
time: e.ts,
|
|
11
|
-
kind: e.kind,
|
|
12
|
-
outcome: e.outcome,
|
|
13
|
-
statusCode: e.status_code,
|
|
14
|
-
latencyMs: e.latency_ms,
|
|
15
|
-
error: e.error,
|
|
16
|
-
title: e.kind === 'fetch' && e.extra?.skill_id ? 'skill: ' + e.extra.skill_id : (e.node_id || '-'),
|
|
17
|
-
}));
|
|
18
|
-
(calls || []).forEach((c) => events.push({
|
|
19
|
-
layer: 'asset',
|
|
20
|
-
time: c.timestamp,
|
|
21
|
-
kind: c.action,
|
|
22
|
-
outcome: inferAssetOutcome(c.action),
|
|
23
|
-
title: c.asset_id || c.reason || '-',
|
|
24
|
-
meta: c.run_id ? 'run ' + c.run_id : null,
|
|
25
|
-
score: c.score,
|
|
26
|
-
}));
|
|
27
|
-
(atpProofs || []).forEach((p) => events.push({
|
|
28
|
-
layer: 'atp',
|
|
29
|
-
time: p.created_at || p.timestamp,
|
|
30
|
-
kind: 'proof_' + (p.status || 'pending'),
|
|
31
|
-
outcome: p.status === 'verified' || p.status === 'accepted' ? 'ok' : (p.status || 'pending'),
|
|
32
|
-
title: p.delivery_id || p.order_id || '-',
|
|
33
|
-
meta: (p.role || 'consumer') + (p.amount != null ? ' · ' + p.amount + ' credits' : ''),
|
|
34
|
-
}));
|
|
35
|
-
(atpOrders || []).forEach((o) => events.push({
|
|
36
|
-
layer: 'atp',
|
|
37
|
-
time: o.created_at || o.updated_at,
|
|
38
|
-
kind: 'order_' + (o.status || 'pending'),
|
|
39
|
-
outcome: o.status === 'completed' ? 'ok' : (o.status || 'pending'),
|
|
40
|
-
title: o.order_id || o.id || '-',
|
|
41
|
-
meta: (o.routing || '-') + (o.budget != null ? ' · ' + o.budget + ' credits' : ''),
|
|
42
|
-
}));
|
|
43
|
-
return events.sort((a, b) => new Date(b.time || 0) - new Date(a.time || 0));
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
function inferAssetOutcome(action) {
|
|
47
|
-
if (!action) return 'unknown';
|
|
48
|
-
if (action.endsWith('_hit') || action === 'asset_reuse' || action === 'asset_reference' || action === 'asset_publish') return 'ok';
|
|
49
|
-
if (action.endsWith('_miss') || action.endsWith('_skip')) return 'miss';
|
|
50
|
-
return action;
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
function summarizeHubActivity(events) {
|
|
54
|
-
const now = Date.now();
|
|
55
|
-
const last24h = events.filter((e) => Date.parse(e.time || 0) >= now - 24 * 60 * 60 * 1000);
|
|
56
|
-
const heartbeats = events.filter((e) => e.layer === 'lifecycle' && e.kind === 'heartbeat');
|
|
57
|
-
const heartbeatOk = heartbeats.filter((e) => e.outcome === 'ok' || e.outcome === 'recovered');
|
|
58
|
-
const heartbeatHealthPct = heartbeats.length === 0 ? null : Math.round((heartbeatOk.length / heartbeats.length) * 100);
|
|
59
|
-
const latencies = events.filter((e) => typeof e.latencyMs === 'number').map((e) => e.latencyMs);
|
|
60
|
-
const lastHelloOk = events.find((e) => e.layer === 'lifecycle' && e.kind === 'hello' && e.outcome === 'ok')?.time;
|
|
61
|
-
const lastHeartbeatOk = events.find((e) => e.layer === 'lifecycle' && e.kind === 'heartbeat' && (e.outcome === 'ok' || e.outcome === 'recovered'))?.time;
|
|
62
|
-
const assetEvents = events.filter((e) => e.layer === 'asset');
|
|
63
|
-
const assetHits = assetEvents.filter((e) => e.outcome === 'ok').length;
|
|
64
|
-
const assetHitRate = assetEvents.length === 0 ? null : Math.round((assetHits / assetEvents.length) * 100);
|
|
65
|
-
|
|
66
|
-
return {
|
|
67
|
-
total: events.length,
|
|
68
|
-
last24h: last24h.length,
|
|
69
|
-
heartbeatHealthPct,
|
|
70
|
-
assetHitRate,
|
|
71
|
-
lastHelloOk,
|
|
72
|
-
lastHeartbeatOk,
|
|
73
|
-
latencyP50: percentile(latencies, 50),
|
|
74
|
-
latencyP95: percentile(latencies, 95),
|
|
75
|
-
};
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
function percentile(values, p) {
|
|
79
|
-
if (!values.length) return null;
|
|
80
|
-
const sorted = values.slice().sort((a, b) => a - b);
|
|
81
|
-
return sorted[Math.min(sorted.length - 1, Math.floor((sorted.length * p) / 100))];
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
function renderHubActivity(events, hasProxy) {
|
|
85
|
-
HUB_ACTIVITY_STATE.events = events;
|
|
86
|
-
HUB_ACTIVITY_STATE.hasProxy = !!hasProxy;
|
|
87
|
-
renderHubActivitySummary(summarizeHubActivity(events));
|
|
88
|
-
bindHubActivityFilters();
|
|
89
|
-
renderHubActivityTable();
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
function renderHubActivitySummary(s) {
|
|
93
|
-
const healthCls = s.heartbeatHealthPct == null ? '' : s.heartbeatHealthPct >= 95 ? 'success' : s.heartbeatHealthPct >= 70 ? 'pending' : 'failed';
|
|
94
|
-
const hitCls = s.assetHitRate == null ? '' : s.assetHitRate >= 50 ? 'success' : s.assetHitRate >= 20 ? 'pending' : 'failed';
|
|
95
|
-
$('hub-activity-summary').innerHTML =
|
|
96
|
-
statBox(t('interactions.stat.heartbeatHealth'), s.heartbeatHealthPct == null ? '—' : s.heartbeatHealthPct + '%', healthCls) +
|
|
97
|
-
statBox(t('interactions.stat.assetHitRate'), s.assetHitRate == null ? '—' : s.assetHitRate + '%', hitCls) +
|
|
98
|
-
statBox(t('interactions.stat.events24h'), String(s.last24h ?? 0)) +
|
|
99
|
-
statBox(t('interactions.stat.latency'), s.latencyP50 == null ? '—' : (s.latencyP50 + ' / ' + (s.latencyP95 ?? '—') + ' ms')) +
|
|
100
|
-
statBox(t('interactions.stat.lastHelloOk'), formatTime(s.lastHelloOk)) +
|
|
101
|
-
statBox(t('interactions.stat.lastHeartbeatOk'), formatTime(s.lastHeartbeatOk));
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
function bindHubActivityFilters() {
|
|
105
|
-
const bar = $('hub-activity-filters');
|
|
106
|
-
if (!bar) return;
|
|
107
|
-
bar.style.display = HUB_ACTIVITY_STATE.events.length ? 'flex' : 'none';
|
|
108
|
-
bar.querySelectorAll('[data-filter-layer]').forEach((btn) => {
|
|
109
|
-
if (btn._bound) return;
|
|
110
|
-
btn._bound = true;
|
|
111
|
-
btn.addEventListener('click', () => {
|
|
112
|
-
HUB_ACTIVITY_STATE.layer = btn.getAttribute('data-filter-layer');
|
|
113
|
-
bar.querySelectorAll('[data-filter-layer]').forEach((b) => b.classList.toggle('active', b === btn));
|
|
114
|
-
renderHubActivityTable();
|
|
115
|
-
});
|
|
116
|
-
});
|
|
117
|
-
const cb = $('hide-heartbeats');
|
|
118
|
-
if (cb && !cb._bound) {
|
|
119
|
-
cb._bound = true;
|
|
120
|
-
cb.checked = HUB_ACTIVITY_STATE.hideHeartbeats;
|
|
121
|
-
cb.addEventListener('change', () => {
|
|
122
|
-
HUB_ACTIVITY_STATE.hideHeartbeats = cb.checked;
|
|
123
|
-
renderHubActivityTable();
|
|
124
|
-
});
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
function renderHubActivityTable() {
|
|
129
|
-
const filtered = HUB_ACTIVITY_STATE.events.filter((e) => {
|
|
130
|
-
if (HUB_ACTIVITY_STATE.layer !== 'all' && e.layer !== HUB_ACTIVITY_STATE.layer) return false;
|
|
131
|
-
if (HUB_ACTIVITY_STATE.hideHeartbeats && e.layer === 'lifecycle' && e.kind === 'heartbeat' && (e.outcome === 'ok' || e.outcome === 'recovered')) return false;
|
|
132
|
-
return true;
|
|
133
|
-
}).slice(0, 150);
|
|
134
|
-
|
|
135
|
-
if (!filtered.length) {
|
|
136
|
-
$('hub-activity').innerHTML = HUB_ACTIVITY_STATE.events.length
|
|
137
|
-
? '<p class="muted">' + esc(t('interactions.empty.filtered')) + '</p>'
|
|
138
|
-
: hubEmptyHint(HUB_ACTIVITY_STATE.hasProxy);
|
|
139
|
-
return;
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
const rows = filtered.map((e) => {
|
|
143
|
-
const ok = e.outcome === 'ok' || e.outcome === 'recovered';
|
|
144
|
-
const fail = e.outcome && (String(e.outcome).startsWith('fail') || String(e.outcome).startsWith('auth_failed') || String(e.outcome).startsWith('http_'));
|
|
145
|
-
const cls = ok ? 'ok' : fail ? 'fail' : 'neutral';
|
|
146
|
-
return '<tr class="' + cls + '">' +
|
|
147
|
-
'<td>' + esc(formatTime(e.time)) + '</td>' +
|
|
148
|
-
'<td><span class="pill ' + esc(e.layer) + '">' + esc(tAction(e.layer)) + '</span></td>' +
|
|
149
|
-
'<td><span class="pill ' + esc(e.kind || '-') + '">' + esc(tAction(e.kind) || '-') + '</span></td>' +
|
|
150
|
-
'<td><span class="status-indicator ' + (ok ? 'success' : fail ? 'failed' : 'unknown') + '"></span>' + esc(tStatus(e.outcome) || '-') + '</td>' +
|
|
151
|
-
// statusCode / latencyMs are SHOULD-be-numeric but the producer
|
|
152
|
-
// is the proxy daemon, which has historically leaked string
|
|
153
|
-
// shapes ("timeout", "n/a"). Bugbot caught the asymmetry: every
|
|
154
|
-
// other column on this row is esc()'d. Defensive escape here
|
|
155
|
-
// matches the rest of the renderer instead of trusting the
|
|
156
|
-
// proxy to never inject HTML chars.
|
|
157
|
-
'<td>' + esc(e.statusCode ?? '—') + '</td>' +
|
|
158
|
-
'<td>' + esc(e.latencyMs == null ? '—' : e.latencyMs + ' ms') + '</td>' +
|
|
159
|
-
'<td class="lifecycle-error">' + esc(e.title || '') + (e.meta ? ' <span class="muted small">' + esc(e.meta) + '</span>' : '') + (e.error ? ' <span class="status-failed">' + esc(e.error) + '</span>' : '') + '</td>' +
|
|
160
|
-
'</tr>';
|
|
161
|
-
}).join('');
|
|
162
|
-
|
|
163
|
-
$('hub-activity').innerHTML = '<table class="data-table lifecycle-table">' +
|
|
164
|
-
'<thead><tr>' +
|
|
165
|
-
'<th>' + esc(t('interactions.col.time')) + '</th>' +
|
|
166
|
-
'<th>' + esc(t('interactions.col.layer')) + '</th>' +
|
|
167
|
-
'<th>' + esc(t('interactions.col.kind')) + '</th>' +
|
|
168
|
-
'<th>' + esc(t('interactions.col.outcome')) + '</th>' +
|
|
169
|
-
'<th>' + esc(t('interactions.col.status')) + '</th>' +
|
|
170
|
-
'<th>' + esc(t('interactions.col.latency')) + '</th>' +
|
|
171
|
-
'<th>' + esc(t('interactions.col.detail')) + '</th>' +
|
|
172
|
-
'</tr></thead>' +
|
|
173
|
-
'<tbody>' + rows + '</tbody></table>';
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
function hubEmptyHint(hasProxy) {
|
|
177
|
-
if (hasProxy) {
|
|
178
|
-
return '<p class="muted">' + esc(t('interactions.empty.proxyRunning')) + '</p>';
|
|
179
|
-
}
|
|
180
|
-
return '<p class="muted">' + t('interactions.empty.noProxy') + '</p>';
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
function renderAgentStream(mailbox, sessions, dms) {
|
|
184
|
-
const items = [];
|
|
185
|
-
(mailbox || []).forEach((m) => items.push({
|
|
186
|
-
kind: 'mailbox',
|
|
187
|
-
time: m.timestamp,
|
|
188
|
-
action: 'mb_' + (m.direction || 'msg'),
|
|
189
|
-
title: m.summary || m.type || '-',
|
|
190
|
-
meta: (m.type || '-') + ' · ' + (m.status || '-'),
|
|
191
|
-
detail: m,
|
|
192
|
-
}));
|
|
193
|
-
(sessions || []).forEach((s) => items.push({
|
|
194
|
-
kind: 'session',
|
|
195
|
-
time: s.created_at || s.updated_at,
|
|
196
|
-
action: 'session_' + (s.status || 'active'),
|
|
197
|
-
title: s.session_id || s.id || '-',
|
|
198
|
-
meta: 'with ' + (s.peer || s.peer_node_id || '-'),
|
|
199
|
-
detail: s,
|
|
200
|
-
}));
|
|
201
|
-
(dms || []).forEach((d) => items.push({
|
|
202
|
-
kind: 'dm',
|
|
203
|
-
time: d.created_at,
|
|
204
|
-
action: 'dm_' + (d.direction || 'msg'),
|
|
205
|
-
title: d.title || d.message_id || '-',
|
|
206
|
-
meta: (d.from || '-') + ' → ' + (d.to || '-'),
|
|
207
|
-
detail: d,
|
|
208
|
-
}));
|
|
209
|
-
|
|
210
|
-
if (!items.length) {
|
|
211
|
-
$('agent-stream').innerHTML = '<p class="muted">' + esc(t('interactions.empty.noAgent')) + '</p>';
|
|
212
|
-
return;
|
|
213
|
-
}
|
|
214
|
-
items.sort((a, b) => new Date(b.time || 0) - new Date(a.time || 0));
|
|
215
|
-
$('agent-stream').innerHTML = '<ul class="stream-list">' + items.slice(0, 60).map(streamItem).join('') + '</ul>';
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
function streamItem(item) {
|
|
219
|
-
return '<li class="stream-item">' +
|
|
220
|
-
'<div class="stream-head">' +
|
|
221
|
-
'<span class="pill ' + esc(item.action) + '">' + esc(item.action) + '</span>' +
|
|
222
|
-
'<span class="muted small">' + esc(formatTime(item.time)) + '</span>' +
|
|
223
|
-
'</div>' +
|
|
224
|
-
'<div class="stream-title">' + esc(item.title) + '</div>' +
|
|
225
|
-
'<div class="muted small">' + esc(item.meta) + '</div>' +
|
|
226
|
-
'</li>';
|
|
227
|
-
}
|
|
228
|
-
|
|
229
|
-
function renderInteractionCharts(calls, atpProofs, mailbox) {
|
|
230
|
-
const textColor = chartTextColor();
|
|
231
|
-
const isDark = isDarkMode();
|
|
232
|
-
|
|
233
|
-
const actionCounts = {};
|
|
234
|
-
(calls || []).forEach((c) => { actionCounts[c.action] = (actionCounts[c.action] || 0) + 1; });
|
|
235
|
-
ensureChart('hubActionChart')?.setOption({
|
|
236
|
-
tooltip: { trigger: 'item' },
|
|
237
|
-
series: [{
|
|
238
|
-
type: 'pie', radius: ['40%', '70%'],
|
|
239
|
-
itemStyle: { borderRadius: 4, borderColor: isDark ? '#181b1f' : '#fff', borderWidth: 2 },
|
|
240
|
-
label: { show: false },
|
|
241
|
-
labelLine: { show: false },
|
|
242
|
-
data: Object.keys(actionCounts).length
|
|
243
|
-
? Object.entries(actionCounts).map(([name, value]) => ({ name, value }))
|
|
244
|
-
: [{ name: 'no calls', value: 1, itemStyle: { color: '#444' } }],
|
|
245
|
-
}],
|
|
246
|
-
});
|
|
247
|
-
|
|
248
|
-
const dayBuckets = bucketByDay([...(calls || []), ...(atpProofs || []), ...(mailbox || [])], 30);
|
|
249
|
-
ensureChart('activityChart')?.setOption({
|
|
250
|
-
tooltip: { trigger: 'axis' },
|
|
251
|
-
grid: { left: '3%', right: '4%', bottom: '8%', containLabel: true },
|
|
252
|
-
xAxis: { type: 'category', data: dayBuckets.labels, axisLabel: { color: textColor, fontSize: 10 } },
|
|
253
|
-
yAxis: { type: 'value', axisLabel: { color: textColor }, splitLine: { lineStyle: { color: isDark ? '#2c3235' : '#e4e7eb' } } },
|
|
254
|
-
series: [{
|
|
255
|
-
type: 'line', data: dayBuckets.values, smooth: true, areaStyle: { opacity: 0.18, color: '#3274d9' },
|
|
256
|
-
lineStyle: { color: '#3274d9', width: 2 }, itemStyle: { color: '#3274d9' },
|
|
257
|
-
}],
|
|
258
|
-
});
|
|
259
|
-
|
|
260
|
-
const typeCounts = {};
|
|
261
|
-
(mailbox || []).forEach((m) => { typeCounts[m.type || 'unknown'] = (typeCounts[m.type || 'unknown'] || 0) + 1; });
|
|
262
|
-
ensureChart('mailboxChart')?.setOption({
|
|
263
|
-
tooltip: { trigger: 'axis' },
|
|
264
|
-
grid: { left: '3%', right: '4%', bottom: '5%', containLabel: true },
|
|
265
|
-
xAxis: { type: 'value', axisLabel: { color: textColor }, splitLine: { lineStyle: { color: isDark ? '#2c3235' : '#e4e7eb' } } },
|
|
266
|
-
yAxis: { type: 'category', data: Object.keys(typeCounts).length ? Object.keys(typeCounts) : ['no messages'], axisLabel: { color: textColor } },
|
|
267
|
-
series: [{
|
|
268
|
-
type: 'bar',
|
|
269
|
-
data: Object.keys(typeCounts).length ? Object.values(typeCounts) : [0],
|
|
270
|
-
itemStyle: { color: '#28a745', borderRadius: [0, 4, 4, 0] },
|
|
271
|
-
}],
|
|
272
|
-
});
|
|
273
|
-
}
|
|
274
|
-
|
|
275
|
-
function bucketByDay(items, days) {
|
|
276
|
-
const today = new Date(); today.setHours(0,0,0,0);
|
|
277
|
-
const labels = [], counts = new Array(days).fill(0);
|
|
278
|
-
for (let i = days - 1; i >= 0; i--) {
|
|
279
|
-
const d = new Date(today); d.setDate(d.getDate() - i);
|
|
280
|
-
labels.push((d.getMonth()+1) + '/' + d.getDate());
|
|
281
|
-
}
|
|
282
|
-
items.forEach((it) => {
|
|
283
|
-
const t = new Date(it.timestamp || it.time || it.created_at || 0);
|
|
284
|
-
if (isNaN(t.getTime())) return;
|
|
285
|
-
t.setHours(0,0,0,0);
|
|
286
|
-
const diff = Math.round((today - t) / 86400000);
|
|
287
|
-
if (diff >= 0 && diff < days) counts[days - 1 - diff]++;
|
|
288
|
-
});
|
|
289
|
-
return { labels, values: counts };
|
|
290
|
-
}
|
|
291
|
-
|
|
292
|
-
function renderProxySnapshots(snapshots) {
|
|
293
|
-
if (!snapshots || !Object.keys(snapshots).length) {
|
|
294
|
-
$('proxy-snapshots').innerHTML = '<p class="muted snapshot-empty">' + t('interactions.empty.proxyNotRunning') + '</p>';
|
|
295
|
-
return;
|
|
296
|
-
}
|
|
297
|
-
$('proxy-snapshots').innerHTML = Object.entries(snapshots).map(([key, snap]) => {
|
|
298
|
-
const ok = snap?.ok;
|
|
299
|
-
const dot = '<span class="status-indicator ' + (ok ? 'status-success' : 'status-failed') + '"></span>';
|
|
300
|
-
const detail = ok && snap.body
|
|
301
|
-
? (Array.isArray(snap.body) ? snap.body.length + ' ' + t('interactions.snapshot.items') : Object.keys(snap.body).length + ' ' + t('interactions.snapshot.fields'))
|
|
302
|
-
: (snap?.error || t('interactions.snapshot.unavailable'));
|
|
303
|
-
return '<div class="snapshot-card"><div>' + dot + '<strong>' + esc(key) + '</strong></div>' +
|
|
304
|
-
'<div class="muted small">' + esc(detail) + '</div></div>';
|
|
305
|
-
}).join('');
|
|
306
|
-
}
|
|
307
|
-
|
|
308
|
-
async function loadInteractions() {
|
|
309
|
-
$('hub-activity').innerHTML = '<p class="muted">' + esc(t('common.loading')) + '</p>';
|
|
310
|
-
$('agent-stream').innerHTML = '<p class="muted">' + esc(t('common.loading')) + '</p>';
|
|
311
|
-
try {
|
|
312
|
-
// Lifecycle is optional: not every build ships /webui/lifecycle (the
|
|
313
|
-
// observer-side module is only present when the proxy daemon is wired
|
|
314
|
-
// in). Treat a missing/erroring lifecycle endpoint as "no data" so the
|
|
315
|
-
// rest of the Hub Activity panel still renders instead of failing the
|
|
316
|
-
// whole tab with "Failed: Not found".
|
|
317
|
-
const [callsResult, interactions, lifecycle] = await Promise.all([
|
|
318
|
-
api('/webui/assets/calls?limit=500'),
|
|
319
|
-
api('/webui/interactions?last=200'),
|
|
320
|
-
api('/webui/lifecycle?last=500').catch(() => ({ events: [] })),
|
|
321
|
-
]);
|
|
322
|
-
const calls = callsResult.data || [];
|
|
323
|
-
const proofs = interactions.proxySnapshots?.atpProofs?.body?.proofs || interactions.proxySnapshots?.atpProofs?.body || [];
|
|
324
|
-
const orders = interactions.proxySnapshots?.atpProofs?.body?.orders || [];
|
|
325
|
-
const sessions = interactions.proxySnapshots?.sessions?.body?.sessions || interactions.proxySnapshots?.sessions?.body || [];
|
|
326
|
-
const dms = interactions.proxySnapshots?.dms?.body?.dms || interactions.proxySnapshots?.dms?.body || [];
|
|
327
|
-
const mailbox = interactions.mailbox?.data || [];
|
|
328
|
-
const lifecycleEvents = lifecycle?.events || [];
|
|
329
|
-
|
|
330
|
-
const unified = buildHubActivityEvents(
|
|
331
|
-
calls,
|
|
332
|
-
Array.isArray(proofs) ? proofs : [],
|
|
333
|
-
Array.isArray(orders) ? orders : [],
|
|
334
|
-
lifecycleEvents,
|
|
335
|
-
);
|
|
336
|
-
renderHubActivity(unified, interactions.proxy?.running);
|
|
337
|
-
renderAgentStream(mailbox, Array.isArray(sessions) ? sessions : [], Array.isArray(dms) ? dms : []);
|
|
338
|
-
renderInteractionCharts(calls, Array.isArray(proofs) ? proofs : [], mailbox);
|
|
339
|
-
renderProxySnapshots(interactions.proxySnapshots);
|
|
340
|
-
} catch (err) {
|
|
341
|
-
$('hub-activity').innerHTML = '<p class="status-failed">' + esc(t('common.failedPrefix')) + esc(err.message) + '</p>';
|
|
342
|
-
}
|
|
343
|
-
}
|
|
344
|
-
|
|
345
|
-
function statBox(label, value, cls) {
|
|
346
|
-
return '<div class="stat-box ' + (cls || '') + '">' +
|
|
347
|
-
'<div class="stat-label">' + esc(label) + '</div>' +
|
|
348
|
-
'<div class="stat-value">' + esc(value) + '</div>' +
|
|
349
|
-
'</div>';
|
|
350
|
-
}
|
|
351
|
-
`;
|
|
@@ -1,152 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
exports.overviewJs = `
|
|
4
|
-
function renderStatus(status) {
|
|
5
|
-
const lastRun = status.lastRun || {};
|
|
6
|
-
$('status').innerHTML = kv([
|
|
7
|
-
[t('overview.status.mode'), status.mode],
|
|
8
|
-
[t('overview.status.proxy'), status.proxy?.running ? t('common.running') : t('common.notRunning')],
|
|
9
|
-
[t('overview.status.heartbeat'), status.heartbeat?.phase || t('common.idle')],
|
|
10
|
-
[t('overview.status.lastRun'), lastRun.run_id || '-'],
|
|
11
|
-
[t('overview.status.lastActivity'), formatTime(lastRun.finished_at || lastRun.created_at)],
|
|
12
|
-
]);
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
function renderSafety(safety) {
|
|
16
|
-
const warnings = safety.warnings?.length
|
|
17
|
-
? '<ul style="margin-top:8px;padding-left:20px;color:var(--warning)">' + safety.warnings.map((w) => '<li>' + esc(w) + '</li>').join('') + '</ul>'
|
|
18
|
-
: '<p style="margin-top:8px;color:var(--success)">' + esc(t('overview.safety.noWarnings')) + '</p>';
|
|
19
|
-
$('safety').innerHTML = '<div style="margin-bottom:8px"><span class="status-indicator ' + (safety.safeMode ? 'status-success' : 'status-warning') + '"></span><strong>' + esc(safety.safeMode ? t('overview.safety.safeMode') : t('overview.safety.reviewRequired')) + '</strong></div>' + kv([
|
|
20
|
-
[t('overview.safety.autobuy'), safety.autobuyEnabled],
|
|
21
|
-
[t('overview.safety.autoPublish'), safety.autoPublishEnabled],
|
|
22
|
-
[t('overview.safety.validator'), safety.validatorEnabled],
|
|
23
|
-
[t('overview.safety.traceLevel'), safety.traceLevel],
|
|
24
|
-
]) + warnings;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
function renderInteractions(interactions) {
|
|
28
|
-
$('interactions').innerHTML = kv([
|
|
29
|
-
[t('overview.interactions.proxy'), interactions.proxy?.running ? interactions.proxy.url : t('common.notRunning')],
|
|
30
|
-
[t('overview.interactions.mailbox'), interactions.mailbox?.pagination?.totalItems || 0],
|
|
31
|
-
[t('overview.interactions.taskMetrics'), interactions.proxySnapshots?.taskMetrics?.ok ? t('common.available') : t('common.notAvailable')],
|
|
32
|
-
[t('overview.interactions.sessions'), interactions.proxySnapshots?.sessions?.ok ? t('common.available') : t('common.notAvailable')],
|
|
33
|
-
]);
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
function renderOverviewCharts(assets) {
|
|
37
|
-
const isDark = isDarkMode();
|
|
38
|
-
const textColor = chartTextColor();
|
|
39
|
-
const palette = ['#3274d9', '#28a745', '#ffc107', '#dc3545', '#6f42c1', '#17a2b8'];
|
|
40
|
-
|
|
41
|
-
ensureChart('genesChart')?.setOption({
|
|
42
|
-
color: palette,
|
|
43
|
-
tooltip: { trigger: 'item' },
|
|
44
|
-
legend: { bottom: 0, textStyle: { color: textColor } },
|
|
45
|
-
series: [{
|
|
46
|
-
type: 'pie',
|
|
47
|
-
radius: ['45%', '72%'],
|
|
48
|
-
itemStyle: { borderRadius: 4, borderColor: isDark ? '#181b1f' : '#fff', borderWidth: 2 },
|
|
49
|
-
label: { show: false },
|
|
50
|
-
labelLine: { show: false },
|
|
51
|
-
data: Object.entries(assets.genesByCategory || {}).map(([name, value]) => ({ name, value })),
|
|
52
|
-
}],
|
|
53
|
-
});
|
|
54
|
-
|
|
55
|
-
const capsules = Object.entries(assets.capsulesByOutcome || {});
|
|
56
|
-
ensureChart('capsulesChart')?.setOption({
|
|
57
|
-
color: palette,
|
|
58
|
-
tooltip: { trigger: 'item' },
|
|
59
|
-
legend: { bottom: 0, textStyle: { color: textColor } },
|
|
60
|
-
series: [{
|
|
61
|
-
type: 'pie',
|
|
62
|
-
radius: ['45%', '72%'],
|
|
63
|
-
itemStyle: { borderRadius: 4, borderColor: isDark ? '#181b1f' : '#fff', borderWidth: 2 },
|
|
64
|
-
label: { show: false },
|
|
65
|
-
labelLine: { show: false },
|
|
66
|
-
data: capsules.length ? capsules.map(([name, value]) => ({ name, value })) : [{ name: 'no capsules yet', value: 1, itemStyle: { color: '#444' } }],
|
|
67
|
-
}],
|
|
68
|
-
});
|
|
69
|
-
|
|
70
|
-
const calls = Object.entries(assets.assetCallsByAction || {});
|
|
71
|
-
ensureChart('callsChart')?.setOption({
|
|
72
|
-
color: palette,
|
|
73
|
-
tooltip: { trigger: 'axis', axisPointer: { type: 'shadow' } },
|
|
74
|
-
grid: { left: '3%', right: '4%', bottom: '5%', containLabel: true },
|
|
75
|
-
xAxis: { type: 'value', splitLine: { lineStyle: { color: isDark ? '#2c3235' : '#e4e7eb' } }, axisLabel: { color: textColor } },
|
|
76
|
-
yAxis: { type: 'category', data: calls.length ? calls.map(d => d[0]) : ['no calls'], axisLabel: { color: textColor } },
|
|
77
|
-
series: [{
|
|
78
|
-
type: 'bar',
|
|
79
|
-
data: calls.length ? calls.map(d => d[1]) : [0],
|
|
80
|
-
itemStyle: { color: '#3274d9', borderRadius: [0, 4, 4, 0] },
|
|
81
|
-
}],
|
|
82
|
-
});
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
function renderLatestRun(runs) {
|
|
86
|
-
const list = runs.data || [];
|
|
87
|
-
if (!list.length) {
|
|
88
|
-
$('latest-run').innerHTML = '<p class="muted">' + esc(t('overview.run.empty')) + '</p>';
|
|
89
|
-
return;
|
|
90
|
-
}
|
|
91
|
-
const run = list[0];
|
|
92
|
-
// Build the <dl> manually: only the Status value contains real HTML
|
|
93
|
-
// (the status-indicator span); other values are plain text and go
|
|
94
|
-
// through esc(). Avoids the kv()+partial-replace dance that left
|
|
95
|
-
// " / > un-restored and broke the indicator render. Cursor
|
|
96
|
-
// Bugbot Medium-severity finding on PR #532 -- see test guard for
|
|
97
|
-
// 'kv-then-partial-replace antipattern' in test/webuiServer.test.js.
|
|
98
|
-
const rows = [
|
|
99
|
-
[t('overview.run.id'), esc(run.runId)],
|
|
100
|
-
[t('overview.run.status'), '<span class="status-indicator ' + getStatusClass(run.status) + '"></span>' + esc(tStatus(run.status))],
|
|
101
|
-
[t('overview.run.selectedGene'), esc(run.selectedGeneId || '-')],
|
|
102
|
-
[t('overview.run.validation'), esc(validationDisplay(run))],
|
|
103
|
-
[t('overview.run.updated'), esc(formatTime(run.updatedAt))],
|
|
104
|
-
[t('overview.run.requiresConfirmation'), run.requiresConfirmation ? t('common.yes') : t('common.no')],
|
|
105
|
-
];
|
|
106
|
-
$('latest-run').innerHTML = '<dl>' +
|
|
107
|
-
rows.map(([k, v]) => '<dt>' + esc(k) + '</dt><dd>' + v + '</dd>').join('') +
|
|
108
|
-
'</dl>';
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
function validationDisplay(run) {
|
|
112
|
-
if (run.validationResult === 'pass') return t('overview.validation.pass');
|
|
113
|
-
if (run.validationResult === 'fail') return t('overview.validation.fail');
|
|
114
|
-
if (run.status === 'review_pending') return t('overview.validation.pendingReview');
|
|
115
|
-
if (run.status === 'running' || run.status === 'pending') return t('overview.validation.inProgress');
|
|
116
|
-
if (run.status === 'failed') return t('overview.validation.notRun');
|
|
117
|
-
return t('overview.validation.notRun');
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
function renderSkills(skills) {
|
|
121
|
-
if (!skills.exists || !skills.items.length) {
|
|
122
|
-
$('skills').innerHTML = '<p class="muted">' + esc(t('overview.skills.empty')) + '</p>' +
|
|
123
|
-
'<p class="muted small">' + t('overview.skills.hint') + '</p>';
|
|
124
|
-
return;
|
|
125
|
-
}
|
|
126
|
-
$('skills').innerHTML = '<ul class="skill-list">' + skills.items.map((skill) =>
|
|
127
|
-
'<li><strong>' + esc(skill.name) + '</strong>' +
|
|
128
|
-
(skill.description ? '<p>' + esc(skill.description) + '</p>' : '') +
|
|
129
|
-
'<small class="muted">' + skill.fileCount + ' ' + esc(t('overview.skills.files')) + ' · ' + esc(skill.docFile || t('overview.skills.noDoc')) + '</small></li>'
|
|
130
|
-
).join('') + '</ul>';
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
async function loadOverview() {
|
|
134
|
-
try {
|
|
135
|
-
const [status, runs, assets, interactions, skills] = await Promise.all([
|
|
136
|
-
api('/webui/status'),
|
|
137
|
-
api('/webui/runs?limit=20'),
|
|
138
|
-
api('/webui/assets'),
|
|
139
|
-
api('/webui/interactions?limit=20'),
|
|
140
|
-
api('/webui/skills'),
|
|
141
|
-
]);
|
|
142
|
-
renderStatus(status);
|
|
143
|
-
renderSafety(status.safety || {});
|
|
144
|
-
renderInteractions(interactions);
|
|
145
|
-
renderOverviewCharts(assets);
|
|
146
|
-
renderLatestRun(runs);
|
|
147
|
-
renderSkills(skills);
|
|
148
|
-
} catch (err) {
|
|
149
|
-
console.error(err);
|
|
150
|
-
}
|
|
151
|
-
}
|
|
152
|
-
`;
|