Skip to content

Commit 244708c

Browse files
committed
UI bug fix: Graceful handling of migrated programs -- different artificial program IDs are assigned, new Clones tab shows relations
1 parent 4dba30d commit 244708c

File tree

2 files changed

+72
-0
lines changed

2 files changed

+72
-0
lines changed

scripts/static/js/sidebar.js

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,15 @@ export function showSidebarContent(d, fromHover = false) {
3535
if ((d.prompts && typeof d.prompts === 'object' && Object.keys(d.prompts).length > 0) || (d.artifacts_json && typeof d.artifacts_json === 'object' && Object.keys(d.artifacts_json).length > 0)) tabNames.push('Prompts');
3636
const children = allNodeData.filter(n => n.parent_id === d.id);
3737
if (children.length > 0) tabNames.push('Children');
38+
39+
// --- CLONES TAB LOGIC ---
40+
function getBaseId(id) {
41+
return id.includes('-copy') ? id.split('-copy')[0] : id;
42+
}
43+
const baseId = getBaseId(d.id);
44+
const clones = allNodeData.filter(n => getBaseId(n.id) === baseId && n.id !== d.id);
45+
if (clones.length > 0) tabNames.push('Clones');
46+
3847
let activeTab = lastSidebarTab && tabNames.includes(lastSidebarTab) ? lastSidebarTab : tabNames[0];
3948

4049
// Helper to render tab content
@@ -99,6 +108,13 @@ export function showSidebarContent(d, fromHover = false) {
99108
}).join('') +
100109
`</ul></div>`;
101110
}
111+
if (tabName === 'Clones') {
112+
return `<div><ul style='margin:0.5em 0 0 1em;padding:0;'>` +
113+
clones.map(clone =>
114+
`<li style='margin-bottom:0.3em;'><a href="#" class="clone-link" data-clone="${clone.id}">${clone.id}</a></li>`
115+
).join('') +
116+
`</ul></div>`;
117+
}
102118
return '';
103119
}
104120

@@ -178,6 +194,25 @@ export function showSidebarContent(d, fromHover = false) {
178194
}
179195
};
180196
});
197+
document.querySelectorAll('.clone-link').forEach(link => {
198+
link.onclick = function(e) {
199+
e.preventDefault();
200+
const cloneNode = allNodeData.find(n => n.id == link.dataset.clone);
201+
if (cloneNode) {
202+
window._lastSelectedNodeData = cloneNode;
203+
const perfTabBtn = document.getElementById('tab-performance');
204+
const perfTabView = document.getElementById('view-performance');
205+
if ((perfTabBtn && perfTabBtn.classList.contains('active')) || (perfTabView && perfTabView.classList.contains('active'))) {
206+
import('./performance.js').then(mod => {
207+
mod.selectPerformanceNodeById(cloneNode.id);
208+
showSidebar();
209+
});
210+
} else {
211+
scrollAndSelectNodeById(cloneNode.id);
212+
}
213+
}
214+
};
215+
});
181216
}, 0);
182217
};
183218
});
@@ -204,6 +239,25 @@ export function showSidebarContent(d, fromHover = false) {
204239
}
205240
};
206241
});
242+
document.querySelectorAll('.clone-link').forEach(link => {
243+
link.onclick = function(e) {
244+
e.preventDefault();
245+
const cloneNode = allNodeData.find(n => n.id == link.dataset.clone);
246+
if (cloneNode) {
247+
window._lastSelectedNodeData = cloneNode;
248+
const perfTabBtn = document.getElementById('tab-performance');
249+
const perfTabView = document.getElementById('view-performance');
250+
if ((perfTabBtn && perfTabBtn.classList.contains('active')) || (perfTabView && perfTabView.classList.contains('active'))) {
251+
import('./performance.js').then(mod => {
252+
mod.selectPerformanceNodeById(cloneNode.id);
253+
showSidebar();
254+
});
255+
} else {
256+
scrollAndSelectNodeById(cloneNode.id);
257+
}
258+
}
259+
};
260+
});
207261
}, 0);
208262
const closeBtnEl = document.getElementById('sidebar-close-btn');
209263
if (closeBtnEl) closeBtnEl.onclick = function() {

scripts/visualizer.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,12 +37,30 @@ def load_evolution_data(checkpoint_folder):
3737

3838
nodes = []
3939
id_to_program = {}
40+
pids = set()
4041
for island_idx, id_list in enumerate(meta.get("islands", [])):
4142
for pid in id_list:
4243
prog_path = os.path.join(programs_dir, f"{pid}.json")
44+
45+
# Keep track of PIDs and if one is double, append "-copyN" to the PID
46+
if pid in pids:
47+
base_pid = pid
48+
49+
# If base_pid already has a "-copyN" suffix, strip it
50+
if "-copy" in base_pid:
51+
base_pid = base_pid.rsplit("-copy", 1)[0]
52+
53+
# Find the next available copy number
54+
copy_num = 1
55+
while f"{base_pid}-copy{copy_num}" in pids:
56+
copy_num += 1
57+
pid = f"{base_pid}-copy{copy_num}"
58+
pids.add(pid)
59+
4360
if os.path.exists(prog_path):
4461
with open(prog_path) as pf:
4562
prog = json.load(pf)
63+
prog["id"] = pid
4664
prog["island"] = island_idx
4765
nodes.append(prog)
4866
id_to_program[pid] = prog

0 commit comments

Comments
 (0)