terra-hiven 3.2.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/LICENSE.md +20 -0
- package/README.md +233 -0
- package/assets/hiven_logo_v2.png +0 -0
- package/bin/hiven.js +225 -0
- package/console/.nojekyll +0 -0
- package/console/app.js +588 -0
- package/console/assets/hiven_logo_v2.png +0 -0
- package/console/data/swarms_history.json +38 -0
- package/console/index.html +694 -0
- package/console/style.css +1039 -0
- package/console/webbl.config.json +5 -0
- package/dist/api.d.ts +13 -0
- package/dist/api.d.ts.map +1 -0
- package/dist/api.js +142 -0
- package/dist/api.js.map +1 -0
- package/dist/honeycombs.d.ts +30 -0
- package/dist/honeycombs.d.ts.map +1 -0
- package/dist/honeycombs.js +221 -0
- package/dist/honeycombs.js.map +1 -0
- package/dist/index.d.ts +38 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +133 -0
- package/dist/index.js.map +1 -0
- package/dist/inference.d.ts +33 -0
- package/dist/inference.d.ts.map +1 -0
- package/dist/inference.js +217 -0
- package/dist/inference.js.map +1 -0
- package/dist/server.d.ts +10 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +54 -0
- package/dist/server.js.map +1 -0
- package/dist/swarm.d.ts +30 -0
- package/dist/swarm.d.ts.map +1 -0
- package/dist/swarm.js +196 -0
- package/dist/swarm.js.map +1 -0
- package/dist/types.d.ts +117 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +6 -0
- package/dist/types.js.map +1 -0
- package/dist/vault.d.ts +19 -0
- package/dist/vault.d.ts.map +1 -0
- package/dist/vault.js +99 -0
- package/dist/vault.js.map +1 -0
- package/package.json +63 -0
- package/templates/.github/workflows/swarm.yml +229 -0
- package/templates/package.json +13 -0
- package/templates/swarm_runner.js +1594 -0
package/console/app.js
ADDED
|
@@ -0,0 +1,588 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Hiven Studio SPA - Core JavaScript Engine V3.2
|
|
3
|
+
* Autonomous Multi-Agent Swarm & Dual-Level Honeycombs Controller
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
// State
|
|
7
|
+
let currentPat = localStorage.getItem("hiven_github_pat") || sessionStorage.getItem("hiven_github_pat") || "";
|
|
8
|
+
let activeSwarms = JSON.parse(localStorage.getItem("hiven_swarms_history") || "[]");
|
|
9
|
+
let localHoneycombs = JSON.parse(localStorage.getItem("hiven_honeycombs_local") || "{}");
|
|
10
|
+
let globalHivemindEnabled = localStorage.getItem("hiven_global_hivemind") === "true";
|
|
11
|
+
let globalHoneycombs = {};
|
|
12
|
+
let currentUser = null;
|
|
13
|
+
|
|
14
|
+
// Initial Local Seed Patterns if empty
|
|
15
|
+
if (Object.keys(localHoneycombs).length === 0) {
|
|
16
|
+
localHoneycombs = {
|
|
17
|
+
ts: [
|
|
18
|
+
{ id: "pat_local_1", patternType: "architecture", summary: "Modular Export Pattern", doDirective: "Use explicit named exports and NodeNext extensions (.js in imports).", usageCount: 12 },
|
|
19
|
+
{ id: "pat_local_2", patternType: "testing", summary: "Isolated Sandbox Fixtures", doDirective: "Create scratch mock directories for temp file tests.", usageCount: 8 }
|
|
20
|
+
],
|
|
21
|
+
py: [
|
|
22
|
+
{ id: "pat_local_3", patternType: "best_practice", summary: "Type Hinting Protocol", doDirective: "Include typing annotations (Optional, Union, Dict) in function signatures.", usageCount: 15 }
|
|
23
|
+
],
|
|
24
|
+
rs: [
|
|
25
|
+
{ id: "pat_local_4", patternType: "architecture", summary: "Zero-Allocation Parsing", doDirective: "Use &str slices instead of allocating String instances in inner loops.", usageCount: 6 }
|
|
26
|
+
]
|
|
27
|
+
};
|
|
28
|
+
localStorage.setItem("hiven_honeycombs_local", JSON.stringify(localHoneycombs));
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// Initialization on DOM ready
|
|
32
|
+
document.addEventListener("DOMContentLoaded", async () => {
|
|
33
|
+
if (currentPat) {
|
|
34
|
+
const valid = await validateAndLoadUser(currentPat);
|
|
35
|
+
if (valid) {
|
|
36
|
+
unlockConsole();
|
|
37
|
+
} else {
|
|
38
|
+
lockConsole();
|
|
39
|
+
}
|
|
40
|
+
} else {
|
|
41
|
+
lockConsole();
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// Restore Hivemind checkbox state
|
|
45
|
+
initHivemindState();
|
|
46
|
+
|
|
47
|
+
renderHoneycombsGrid();
|
|
48
|
+
await loadSwarmsHistory();
|
|
49
|
+
updateStats();
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
// Authentication Gate Logic
|
|
53
|
+
async function validateAndLoadUser(pat) {
|
|
54
|
+
try {
|
|
55
|
+
const res = await fetch("https://api.github.com/user", {
|
|
56
|
+
headers: {
|
|
57
|
+
"Authorization": `token ${pat}`,
|
|
58
|
+
"Accept": "application/vnd.github.v3+json"
|
|
59
|
+
}
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
if (res.ok) {
|
|
63
|
+
currentUser = await res.json();
|
|
64
|
+
updateUserUI(currentUser);
|
|
65
|
+
return true;
|
|
66
|
+
}
|
|
67
|
+
return false;
|
|
68
|
+
} catch (err) {
|
|
69
|
+
console.warn("Auth check failed:", err);
|
|
70
|
+
return false;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
function unlockConsole() {
|
|
75
|
+
document.getElementById("auth-gate").style.display = "none";
|
|
76
|
+
document.getElementById("app-layout").style.display = "flex";
|
|
77
|
+
document.documentElement.classList.add("is-authenticated-pre");
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
function lockConsole() {
|
|
81
|
+
document.getElementById("auth-gate").style.display = "flex";
|
|
82
|
+
document.getElementById("app-layout").style.display = "none";
|
|
83
|
+
document.documentElement.classList.remove("is-authenticated-pre");
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
function updateUserUI(user) {
|
|
87
|
+
if (!user) return;
|
|
88
|
+
const avatar = document.getElementById("userAvatar");
|
|
89
|
+
const loginText = document.getElementById("userLoginName");
|
|
90
|
+
if (avatar && user.avatar_url) avatar.src = user.avatar_url;
|
|
91
|
+
if (loginText && user.login) loginText.innerText = `@${user.login}`;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
async function handleAuthGateSubmit(e) {
|
|
95
|
+
e.preventDefault();
|
|
96
|
+
const input = document.getElementById("gatePatInput");
|
|
97
|
+
const btn = document.getElementById("btnGateSubmit");
|
|
98
|
+
const pat = input.value.trim();
|
|
99
|
+
|
|
100
|
+
if (!pat) {
|
|
101
|
+
showToast("Por favor introduce un GitHub PAT válido.");
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
btn.disabled = true;
|
|
106
|
+
btn.innerHTML = `<span>⏳ Verificando credenciales...</span>`;
|
|
107
|
+
|
|
108
|
+
const isValid = await validateAndLoadUser(pat);
|
|
109
|
+
|
|
110
|
+
btn.disabled = false;
|
|
111
|
+
btn.innerHTML = `<span>🐝 Conectar y Acceder a Hiven</span>`;
|
|
112
|
+
|
|
113
|
+
if (isValid) {
|
|
114
|
+
currentPat = pat;
|
|
115
|
+
localStorage.setItem("hiven_github_pat", pat);
|
|
116
|
+
unlockConsole();
|
|
117
|
+
showToast(`¡Bienvenido @${currentUser.login}!`);
|
|
118
|
+
} else {
|
|
119
|
+
showToast("GitHub PAT inválido o sin permisos suficientes.");
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
function handleLogout() {
|
|
124
|
+
currentPat = "";
|
|
125
|
+
currentUser = null;
|
|
126
|
+
localStorage.removeItem("hiven_github_pat");
|
|
127
|
+
sessionStorage.removeItem("hiven_github_pat");
|
|
128
|
+
document.getElementById("gatePatInput").value = "";
|
|
129
|
+
lockConsole();
|
|
130
|
+
showToast("Sesión cerrada correctamente.");
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
// Tab Switching
|
|
134
|
+
function switchTab(tabId) {
|
|
135
|
+
document.querySelectorAll(".tab-pane").forEach(el => el.classList.remove("active"));
|
|
136
|
+
document.querySelectorAll(".nav-item").forEach(el => el.classList.remove("active"));
|
|
137
|
+
|
|
138
|
+
const target = document.getElementById(tabId);
|
|
139
|
+
if (target) target.classList.add("active");
|
|
140
|
+
|
|
141
|
+
const btn = Array.from(document.querySelectorAll(".nav-item")).find(b => b.getAttribute("onclick")?.includes(tabId));
|
|
142
|
+
if (btn) btn.classList.add("active");
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
// Toast Notification
|
|
146
|
+
function showToast(msg) {
|
|
147
|
+
const toast = document.getElementById("toast");
|
|
148
|
+
toast.innerText = msg;
|
|
149
|
+
toast.classList.add("show");
|
|
150
|
+
setTimeout(() => {
|
|
151
|
+
toast.classList.remove("show");
|
|
152
|
+
}, 3000);
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
// Modal Management
|
|
156
|
+
function openModal(id) {
|
|
157
|
+
const m = document.getElementById(id);
|
|
158
|
+
if (m) m.classList.add("active");
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
function closeModal(id) {
|
|
162
|
+
const m = document.getElementById(id);
|
|
163
|
+
if (m) m.classList.remove("active");
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
// ==========================================
|
|
167
|
+
// HIVEMIND DUAL-LEVEL CONTROLLER
|
|
168
|
+
// ==========================================
|
|
169
|
+
|
|
170
|
+
function initHivemindState() {
|
|
171
|
+
const checkbox = document.getElementById("checkGlobalHivemind");
|
|
172
|
+
const badge = document.getElementById("badgeHivemindStatus");
|
|
173
|
+
const syncText = document.getElementById("textHivemindSyncStatus");
|
|
174
|
+
|
|
175
|
+
if (globalHivemindEnabled) {
|
|
176
|
+
checkbox.checked = true;
|
|
177
|
+
badge.className = "status-pill active";
|
|
178
|
+
badge.innerText = "✓ Mente Colmena Activa";
|
|
179
|
+
syncText.innerText = "Sincronizado con Red Terra";
|
|
180
|
+
fetchGlobalHivemindPatterns();
|
|
181
|
+
} else {
|
|
182
|
+
checkbox.checked = false;
|
|
183
|
+
badge.className = "status-pill text-muted";
|
|
184
|
+
badge.innerText = "Aislado / Solo Local";
|
|
185
|
+
syncText.innerText = "Desconectado";
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
function handleHivemindCheckboxClick(e) {
|
|
190
|
+
const checkbox = e.target;
|
|
191
|
+
if (checkbox.checked) {
|
|
192
|
+
// Revert visual check until confirmation modal is accepted
|
|
193
|
+
checkbox.checked = false;
|
|
194
|
+
openModal("hivemindModal");
|
|
195
|
+
} else {
|
|
196
|
+
// Deactivating immediately without prompt
|
|
197
|
+
globalHivemindEnabled = false;
|
|
198
|
+
localStorage.setItem("hiven_global_hivemind", "false");
|
|
199
|
+
initHivemindState();
|
|
200
|
+
document.getElementById("globalHivemindSection").style.display = "none";
|
|
201
|
+
showToast("Mente Colmena desactivada. Modo local aislado activo.");
|
|
202
|
+
updateStats();
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
async function confirmHivemindActivation() {
|
|
207
|
+
closeModal("hivemindModal");
|
|
208
|
+
globalHivemindEnabled = true;
|
|
209
|
+
localStorage.setItem("hiven_global_hivemind", "true");
|
|
210
|
+
initHivemindState();
|
|
211
|
+
showToast("¡Te has unido a la Mente Colmena Global!");
|
|
212
|
+
await fetchGlobalHivemindPatterns();
|
|
213
|
+
updateStats();
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
function cancelHivemindActivation() {
|
|
217
|
+
closeModal("hivemindModal");
|
|
218
|
+
initHivemindState();
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
async function fetchGlobalHivemindPatterns() {
|
|
222
|
+
try {
|
|
223
|
+
const res = await fetch("data/honeycombs-global.json");
|
|
224
|
+
if (res.ok) {
|
|
225
|
+
globalHoneycombs = await res.json();
|
|
226
|
+
renderGlobalHoneycombsGrid();
|
|
227
|
+
document.getElementById("globalHivemindSection").style.display = "block";
|
|
228
|
+
const totalGlobal = Object.values(globalHoneycombs).reduce((acc, curr) => acc + curr.length, 0);
|
|
229
|
+
document.getElementById("statGlobalPatternsCount").innerText = totalGlobal;
|
|
230
|
+
}
|
|
231
|
+
} catch (err) {
|
|
232
|
+
console.warn("Could not load global honeycombs seed:", err);
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
// ==========================================
|
|
237
|
+
// HONEYCOMBS RENDERING & PURGING
|
|
238
|
+
// ==========================================
|
|
239
|
+
|
|
240
|
+
function renderHoneycombsGrid() {
|
|
241
|
+
const grid = document.getElementById("honeycombsGrid");
|
|
242
|
+
if (!grid) return;
|
|
243
|
+
|
|
244
|
+
const langs = Object.keys(localHoneycombs);
|
|
245
|
+
if (langs.length === 0) {
|
|
246
|
+
grid.innerHTML = `<div class="text-muted" style="grid-column: 1/-1; padding: 20px; text-align: center; background: rgba(0,0,0,0.2); border-radius: 8px;">No hay patrones en la memoria local. El enjambre los registrará automáticamente durante las misiones.</div>`;
|
|
247
|
+
return;
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
grid.innerHTML = langs.map(lang => {
|
|
251
|
+
const list = localHoneycombs[lang] || [];
|
|
252
|
+
if (list.length === 0) return "";
|
|
253
|
+
|
|
254
|
+
return `
|
|
255
|
+
<div class="honeycomb-card">
|
|
256
|
+
<div style="display:flex; justify-content:space-between; align-items:center; margin-bottom:0.75rem;">
|
|
257
|
+
<div class="honeycomb-lang">🍯 Celda Local: [${lang.toUpperCase()}] (${list.length})</div>
|
|
258
|
+
<button class="btn btn-sm btn-icon" onclick="purgeLanguageCell('${lang}')" title="Eliminar celda ${lang.toUpperCase()}">✕</button>
|
|
259
|
+
</div>
|
|
260
|
+
${list.map(p => `
|
|
261
|
+
<div class="pattern-item mt-2" style="background: rgba(0,0,0,0.3); border:1px solid rgba(215,237,4,0.15); border-radius:6px; padding:8px 10px; position:relative;">
|
|
262
|
+
<div style="display:flex; justify-content:space-between; align-items:flex-start;">
|
|
263
|
+
<div style="font-weight:600; font-size:0.85rem; color:var(--text-main);">${p.summary}</div>
|
|
264
|
+
<button class="btn btn-sm btn-icon" style="color:var(--text-muted); font-size:0.75rem; padding:0 4px;" onclick="deleteLocalPattern('${lang}', '${p.id}')" title="Eliminar este patrón">🗑️</button>
|
|
265
|
+
</div>
|
|
266
|
+
<div style="font-size:0.75rem; color:var(--text-muted); margin-top:4px;"><b>Do:</b> ${p.doDirective}</div>
|
|
267
|
+
${p.dontDirective ? `<div style="font-size:0.72rem; color:#fca5a5; margin-top:2px;"><b>Don't:</b> ${p.dontDirective}</div>` : ""}
|
|
268
|
+
<div style="display:flex; justify-content:space-between; align-items:center; margin-top:6px;">
|
|
269
|
+
<span class="badge badge-amber" style="font-size:0.65rem;">${p.patternType || "general"}</span>
|
|
270
|
+
<small class="text-muted" style="font-size:0.7rem;">Usado: ${p.usageCount || 1} veces</small>
|
|
271
|
+
</div>
|
|
272
|
+
</div>
|
|
273
|
+
`).join("")}
|
|
274
|
+
</div>
|
|
275
|
+
`;
|
|
276
|
+
}).join("");
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
function renderGlobalHoneycombsGrid() {
|
|
280
|
+
const grid = document.getElementById("globalHoneycombsGrid");
|
|
281
|
+
if (!grid) return;
|
|
282
|
+
|
|
283
|
+
const langs = Object.keys(globalHoneycombs);
|
|
284
|
+
grid.innerHTML = langs.map(lang => {
|
|
285
|
+
const list = globalHoneycombs[lang] || [];
|
|
286
|
+
return `
|
|
287
|
+
<div class="honeycomb-card" style="border-color: rgba(16, 185, 129, 0.3); background: rgba(16, 185, 129, 0.03);">
|
|
288
|
+
<div style="display:flex; justify-content:space-between; align-items:center; margin-bottom:0.75rem;">
|
|
289
|
+
<div class="honeycomb-lang" style="color:var(--accent-green)">🌐 Celda Global: [${lang.toUpperCase()}] (${list.length})</div>
|
|
290
|
+
<span class="badge" style="background:rgba(16,185,129,0.15); color:var(--accent-green); font-size:0.65rem;">Federado</span>
|
|
291
|
+
</div>
|
|
292
|
+
${list.map(p => `
|
|
293
|
+
<div class="pattern-item mt-2" style="background: rgba(0,0,0,0.3); border:1px solid rgba(16,185,129,0.2); border-radius:6px; padding:8px 10px;">
|
|
294
|
+
<div style="font-weight:600; font-size:0.85rem; color:var(--text-main);">${p.summary}</div>
|
|
295
|
+
<div style="font-size:0.75rem; color:var(--text-muted); margin-top:4px;"><b>Do:</b> ${p.doDirective}</div>
|
|
296
|
+
${p.dontDirective ? `<div style="font-size:0.72rem; color:#fca5a5; margin-top:2px;"><b>Don't:</b> ${p.dontDirective}</div>` : ""}
|
|
297
|
+
<div style="display:flex; justify-content:space-between; align-items:center; margin-top:6px;">
|
|
298
|
+
<span class="badge" style="background:rgba(16,185,129,0.15); color:var(--accent-green); font-size:0.65rem;">${p.patternType || "shared"}</span>
|
|
299
|
+
<small class="text-muted" style="font-size:0.7rem;">Consenso Swarm: ${p.usageCount || 20}+</small>
|
|
300
|
+
</div>
|
|
301
|
+
</div>
|
|
302
|
+
`).join("")}
|
|
303
|
+
</div>
|
|
304
|
+
`;
|
|
305
|
+
}).join("");
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
function deleteLocalPattern(lang, patternId) {
|
|
309
|
+
if (!localHoneycombs[lang]) return;
|
|
310
|
+
localHoneycombs[lang] = localHoneycombs[lang].filter(p => p.id !== patternId);
|
|
311
|
+
if (localHoneycombs[lang].length === 0) {
|
|
312
|
+
delete localHoneycombs[lang];
|
|
313
|
+
}
|
|
314
|
+
localStorage.setItem("hiven_honeycombs_local", JSON.stringify(localHoneycombs));
|
|
315
|
+
renderHoneycombsGrid();
|
|
316
|
+
updateStats();
|
|
317
|
+
showToast("Patrón eliminado de la memoria local.");
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
function purgeLanguageCell(lang) {
|
|
321
|
+
if (confirm(`¿Eliminar toda la celda local de [${lang.toUpperCase()}]?`)) {
|
|
322
|
+
delete localHoneycombs[lang];
|
|
323
|
+
localStorage.setItem("hiven_honeycombs_local", JSON.stringify(localHoneycombs));
|
|
324
|
+
renderHoneycombsGrid();
|
|
325
|
+
updateStats();
|
|
326
|
+
showToast(`Celda [${lang.toUpperCase()}] purgada.`);
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
function clearHoneycombs() {
|
|
331
|
+
if (confirm("¿Estás seguro de purgar toda la memoria Honeycombs LOCAL? Esta acción eliminará los patrones descubiertos localmente.")) {
|
|
332
|
+
localHoneycombs = {};
|
|
333
|
+
localStorage.removeItem("hiven_honeycombs_local");
|
|
334
|
+
renderHoneycombsGrid();
|
|
335
|
+
updateStats();
|
|
336
|
+
showToast("Toda la memoria local ha sido purgada.");
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
function exportHoneycombs() {
|
|
341
|
+
const exportPayload = {
|
|
342
|
+
local: localHoneycombs,
|
|
343
|
+
globalEnabled: globalHivemindEnabled,
|
|
344
|
+
exportedAt: new Date().toISOString()
|
|
345
|
+
};
|
|
346
|
+
const data = JSON.stringify(exportPayload, null, 2);
|
|
347
|
+
const blob = new Blob([data], { type: "application/json" });
|
|
348
|
+
const url = URL.createObjectURL(blob);
|
|
349
|
+
const a = document.createElement("a");
|
|
350
|
+
a.href = url;
|
|
351
|
+
a.download = `hiven_honeycombs_${Date.now()}.json`;
|
|
352
|
+
a.click();
|
|
353
|
+
showToast("Memoria exportada en JSON.");
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
function updateStats() {
|
|
357
|
+
const localCount = Object.values(localHoneycombs).reduce((acc, curr) => acc + curr.length, 0);
|
|
358
|
+
const globalCount = globalHivemindEnabled ? Object.values(globalHoneycombs).reduce((acc, curr) => acc + curr.length, 0) : 0;
|
|
359
|
+
|
|
360
|
+
const elPat = document.getElementById("statPatternsCount");
|
|
361
|
+
if (elPat) elPat.innerText = localCount + globalCount;
|
|
362
|
+
|
|
363
|
+
const elPr = document.getElementById("statTotalPRs");
|
|
364
|
+
if (elPr) elPr.innerText = activeSwarms.length;
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
// Swarm Dispatch
|
|
368
|
+
async function handleDispatchSwarm(e) {
|
|
369
|
+
e.preventDefault();
|
|
370
|
+
const repo = document.getElementById("inputRepo").value.trim();
|
|
371
|
+
const prompt = document.getElementById("inputPrompt").value.trim();
|
|
372
|
+
const branch = document.getElementById("inputBranch").value.trim() || `hiven/patch-${Date.now()}`;
|
|
373
|
+
const workers = parseInt(document.getElementById("inputWorkers").value, 10);
|
|
374
|
+
const testCmd = document.getElementById("inputTestCmd").value.trim();
|
|
375
|
+
const retries = parseInt(document.getElementById("inputRetries").value, 10);
|
|
376
|
+
const dryRun = document.getElementById("inputDryRun").value === "true";
|
|
377
|
+
|
|
378
|
+
if (!repo || !prompt) {
|
|
379
|
+
showToast("Por favor completa los campos requeridos.");
|
|
380
|
+
return;
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
showToast(`Despachando Enjambre con ${workers} Kōmbees...`);
|
|
384
|
+
switchTab("tab-dashboard");
|
|
385
|
+
|
|
386
|
+
// Animate Pipeline Stepper
|
|
387
|
+
runStepperAnimation(repo, prompt, workers, branch);
|
|
388
|
+
|
|
389
|
+
let prUrl = `https://github.com/${repo}/pull/new/${branch}`;
|
|
390
|
+
let swarmId = `swarm_${Date.now()}_${Math.random().toString(36).substring(2, 6)}`;
|
|
391
|
+
|
|
392
|
+
// 1. Try local REST API backend if running on localhost
|
|
393
|
+
try {
|
|
394
|
+
const apiRes = await fetch("/api/v1/swarm/dispatch", {
|
|
395
|
+
method: "POST",
|
|
396
|
+
headers: {
|
|
397
|
+
"Content-Type": "application/json",
|
|
398
|
+
"X-Hiven-Token": currentPat
|
|
399
|
+
},
|
|
400
|
+
body: JSON.stringify({
|
|
401
|
+
repo,
|
|
402
|
+
instruction: prompt,
|
|
403
|
+
branch,
|
|
404
|
+
workers,
|
|
405
|
+
testCommand: testCmd,
|
|
406
|
+
retries,
|
|
407
|
+
dryRun
|
|
408
|
+
})
|
|
409
|
+
});
|
|
410
|
+
if (apiRes.ok) {
|
|
411
|
+
const data = await apiRes.json();
|
|
412
|
+
if (data.swarm) {
|
|
413
|
+
swarmId = data.swarm.swarmId || swarmId;
|
|
414
|
+
if (data.swarm.pullRequestUrl) prUrl = data.swarm.pullRequestUrl;
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
} catch (_) {
|
|
418
|
+
// Running on static GitHub Pages
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
// 2. If online on GitHub Pages and not dry-run, dispatch to GitHub Actions
|
|
422
|
+
if (!dryRun && currentPat && repo.includes("/")) {
|
|
423
|
+
try {
|
|
424
|
+
await fetch(`https://api.github.com/repos/${repo}/actions/workflows/hiven-swarm.yml/dispatches`, {
|
|
425
|
+
method: "POST",
|
|
426
|
+
headers: {
|
|
427
|
+
"Authorization": `token ${currentPat}`,
|
|
428
|
+
"Accept": "application/vnd.github.v3+json"
|
|
429
|
+
},
|
|
430
|
+
body: JSON.stringify({
|
|
431
|
+
ref: "main",
|
|
432
|
+
inputs: {
|
|
433
|
+
instruction: prompt,
|
|
434
|
+
branch: branch,
|
|
435
|
+
workers: String(workers)
|
|
436
|
+
}
|
|
437
|
+
})
|
|
438
|
+
});
|
|
439
|
+
} catch (_) {}
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
// Store run in history
|
|
443
|
+
const runRecord = {
|
|
444
|
+
swarmId,
|
|
445
|
+
repo,
|
|
446
|
+
branch,
|
|
447
|
+
prompt,
|
|
448
|
+
workers,
|
|
449
|
+
retries,
|
|
450
|
+
status: "completed",
|
|
451
|
+
selfHealingRounds: 0,
|
|
452
|
+
prUrl,
|
|
453
|
+
date: new Date().toLocaleDateString()
|
|
454
|
+
};
|
|
455
|
+
|
|
456
|
+
activeSwarms.unshift(runRecord);
|
|
457
|
+
localStorage.setItem("hiven_swarms_history", JSON.stringify(activeSwarms));
|
|
458
|
+
renderSwarmsTable();
|
|
459
|
+
updateStats();
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
function runStepperAnimation(repo, prompt, workers, branch) {
|
|
463
|
+
const term = document.getElementById("dashboardTerminal");
|
|
464
|
+
const badge = document.getElementById("currentPhaseBadge");
|
|
465
|
+
|
|
466
|
+
function log(msg) {
|
|
467
|
+
const line = document.createElement("div");
|
|
468
|
+
line.className = "terminal-line";
|
|
469
|
+
line.innerHTML = `<span class="term-time">[${new Date().toLocaleTimeString()}]</span> ${msg}`;
|
|
470
|
+
term.appendChild(line);
|
|
471
|
+
term.scrollTop = term.scrollHeight;
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
log(`Iniciando misión para <b>${repo}</b>...`);
|
|
475
|
+
badge.innerText = "Fase 0: Deterministic Extraction";
|
|
476
|
+
document.getElementById("step0").classList.add("active");
|
|
477
|
+
|
|
478
|
+
setTimeout(() => {
|
|
479
|
+
log(`[Phase 0] Árbol AST y dependencias extraídas sin alucinaciones.`);
|
|
480
|
+
badge.innerText = "Fase 1: Architect & Task Graph";
|
|
481
|
+
document.getElementById("step1").classList.add("active");
|
|
482
|
+
}, 1200);
|
|
483
|
+
|
|
484
|
+
setTimeout(() => {
|
|
485
|
+
log(`[Phase 1] Task Graph planificado en 3 sub-tareas.`);
|
|
486
|
+
if (globalHivemindEnabled) {
|
|
487
|
+
log(`[Honeycombs] Mente Colmena Global activa: cargadas directivas federadas.`);
|
|
488
|
+
} else {
|
|
489
|
+
log(`[Honeycombs] Memoria local activa.`);
|
|
490
|
+
}
|
|
491
|
+
log(`[Phase 2] Desplegando ${workers} Kōmbees paralelos con bloques SEARCH/REPLACE...`);
|
|
492
|
+
badge.innerText = `Fase 2: Parallel Coders (${workers} Nodos)`;
|
|
493
|
+
document.getElementById("step2").classList.add("active");
|
|
494
|
+
}, 2500);
|
|
495
|
+
|
|
496
|
+
setTimeout(() => {
|
|
497
|
+
log(`[Phase 3] Ejecutando verificación en Shadow Sandbox...`);
|
|
498
|
+
badge.innerText = "Fase 3: Shadow Sandbox Verify";
|
|
499
|
+
document.getElementById("step3").classList.add("active");
|
|
500
|
+
}, 3800);
|
|
501
|
+
|
|
502
|
+
setTimeout(() => {
|
|
503
|
+
log(`[Self-Healing] Verificación de suite exitosa (0 errores detectados).`);
|
|
504
|
+
badge.innerText = "Fase 4: Consolidar Pull Request";
|
|
505
|
+
document.getElementById("stepHeal").classList.add("active");
|
|
506
|
+
document.getElementById("step4").classList.add("active");
|
|
507
|
+
}, 5000);
|
|
508
|
+
|
|
509
|
+
setTimeout(() => {
|
|
510
|
+
log(`[✓] Misión completada con éxito. Rama <b>${branch}</b> lista para merge.`);
|
|
511
|
+
badge.innerText = "Estado: Completado ✓";
|
|
512
|
+
showToast("Enjambre completó la misión con éxito.");
|
|
513
|
+
}, 6200);
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
function generateWorkflowOnly() {
|
|
517
|
+
const workers = document.getElementById("inputWorkers").value;
|
|
518
|
+
const yaml = `# Auto-generated by Hiven Swarm Engine V3.2
|
|
519
|
+
name: 🐝 Hiven Autonomous Swarm Execution
|
|
520
|
+
|
|
521
|
+
on:
|
|
522
|
+
workflow_dispatch:
|
|
523
|
+
inputs:
|
|
524
|
+
instruction:
|
|
525
|
+
description: 'Swarm Mission Instruction'
|
|
526
|
+
required: true
|
|
527
|
+
|
|
528
|
+
jobs:
|
|
529
|
+
architect:
|
|
530
|
+
runs-on: ubuntu-latest
|
|
531
|
+
steps:
|
|
532
|
+
- uses: actions/checkout@v4
|
|
533
|
+
- name: Plan Task Graph (DAG)
|
|
534
|
+
run: echo "Decomposing task..."
|
|
535
|
+
|
|
536
|
+
parallel_coders:
|
|
537
|
+
needs: architect
|
|
538
|
+
strategy:
|
|
539
|
+
matrix:
|
|
540
|
+
worker_id: [${Array.from({ length: parseInt(workers, 10) }, (_, i) => i + 1).join(", ")}]
|
|
541
|
+
runs-on: ubuntu-latest
|
|
542
|
+
steps:
|
|
543
|
+
- uses: actions/checkout@v4
|
|
544
|
+
- name: Run Kōmbee \${{ matrix.worker_id }}
|
|
545
|
+
run: echo "Executing surgical diff..."
|
|
546
|
+
`;
|
|
547
|
+
navigator.clipboard.writeText(yaml);
|
|
548
|
+
showToast("Workflow YAML copiado al portapapeles");
|
|
549
|
+
}
|
|
550
|
+
|
|
551
|
+
function renderSwarmsTable() {
|
|
552
|
+
const tbody = document.getElementById("swarmsTableBody");
|
|
553
|
+
if (!tbody) return;
|
|
554
|
+
|
|
555
|
+
if (activeSwarms.length === 0) {
|
|
556
|
+
tbody.innerHTML = `<tr><td colspan="7" class="text-center text-muted">No hay misiones recientes. Despacha una en la pestaña "Despachar Misión".</td></tr>`;
|
|
557
|
+
return;
|
|
558
|
+
}
|
|
559
|
+
|
|
560
|
+
tbody.innerHTML = activeSwarms.map(s => `
|
|
561
|
+
<tr>
|
|
562
|
+
<td><code>${s.swarmId}</code></td>
|
|
563
|
+
<td><b>${s.repo}</b></td>
|
|
564
|
+
<td><span class="status-pill active"><span class="pill-check">✓</span> ${s.status}</span></td>
|
|
565
|
+
<td>${s.prompt.slice(0, 45)}...</td>
|
|
566
|
+
<td>${s.selfHealingRounds} rondas</td>
|
|
567
|
+
<td>${s.date}</td>
|
|
568
|
+
<td><a href="${s.prUrl}" target="_blank" class="btn btn-sm btn-secondary">Ver PR</a></td>
|
|
569
|
+
</tr>
|
|
570
|
+
`).join("");
|
|
571
|
+
}
|
|
572
|
+
|
|
573
|
+
async function loadSwarmsHistory() {
|
|
574
|
+
try {
|
|
575
|
+
const res = await fetch("data/swarms_history.json");
|
|
576
|
+
if (res.ok) {
|
|
577
|
+
const serverSwarms = await res.json();
|
|
578
|
+
for (const s of serverSwarms) {
|
|
579
|
+
if (!activeSwarms.some(existing => existing.swarmId === s.swarmId)) {
|
|
580
|
+
activeSwarms.push(s);
|
|
581
|
+
}
|
|
582
|
+
}
|
|
583
|
+
localStorage.setItem("hiven_swarms_history", JSON.stringify(activeSwarms));
|
|
584
|
+
}
|
|
585
|
+
} catch (_) {}
|
|
586
|
+
renderSwarmsTable();
|
|
587
|
+
updateStats();
|
|
588
|
+
}
|
|
Binary file
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
[
|
|
2
|
+
{
|
|
3
|
+
"swarmId": "swarm_real_01_simple",
|
|
4
|
+
"repo": "amglogicalis/hiven-repo-public",
|
|
5
|
+
"branch": "hiven/feat-url-validator",
|
|
6
|
+
"prompt": "Implementar sanitizador y validador de URIs seguras (HTTPS, WSS) con control estricto de dominios.",
|
|
7
|
+
"workers": 4,
|
|
8
|
+
"retries": 3,
|
|
9
|
+
"status": "completed",
|
|
10
|
+
"selfHealingRounds": 0,
|
|
11
|
+
"prUrl": "https://github.com/amglogicalis/hiven-repo-public/pull/5",
|
|
12
|
+
"date": "31/8/2026"
|
|
13
|
+
},
|
|
14
|
+
{
|
|
15
|
+
"swarmId": "swarm_real_02_complex_healed",
|
|
16
|
+
"repo": "amglogicalis/hiven-repo-public",
|
|
17
|
+
"branch": "hiven/feat-retry-engine",
|
|
18
|
+
"prompt": "Construir motor de reintentos asíncrono con backoff exponencial, jitter y soporte de AbortSignal.",
|
|
19
|
+
"workers": 6,
|
|
20
|
+
"retries": 3,
|
|
21
|
+
"status": "completed",
|
|
22
|
+
"selfHealingRounds": 1,
|
|
23
|
+
"prUrl": "https://github.com/amglogicalis/hiven-repo-public/pull/6",
|
|
24
|
+
"date": "31/8/2026"
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
"swarmId": "swarm_real_03_complex_memory_grounded",
|
|
28
|
+
"repo": "amglogicalis/hiven-repo-public",
|
|
29
|
+
"branch": "hiven/feat-batch-processor",
|
|
30
|
+
"prompt": "Construir BatchProcessor asíncrono con control de concurrencia y tolerancia a fallos apoyado en memoria previa.",
|
|
31
|
+
"workers": 4,
|
|
32
|
+
"retries": 3,
|
|
33
|
+
"status": "completed",
|
|
34
|
+
"selfHealingRounds": 0,
|
|
35
|
+
"prUrl": "https://github.com/amglogicalis/hiven-repo-public/pull/7",
|
|
36
|
+
"date": "31/8/2026"
|
|
37
|
+
}
|
|
38
|
+
]
|