Update logbook: Reproduction: SWE-fficiency: Can Language Models Optimize Real-World Repositories on Real Workloads?
Browse files- README.md +1 -0
- index.html +30 -0
- logbook.css +810 -278
- logbook.js +1204 -665
- logbook.json +13 -4
- pages/claim-1-the-swe-fficiency-benchmark-comprises-498-real-world-code-optimization-tasks-drawn-from-9-widely-used-python-repositories-including-numpy-pandas-and-scipy-abstract-only/page.md +33 -42
- pages/claim-2-agents-are-tasked-with-investigating-code-semantics-localizing-bottlenecks-and-relevant-tests-and-producing-a-patch-that-matches-or-exceeds-expert-speedup-while-passing-the-same-unit-tests-abstract-only/page.md +46 -41
- pages/claim-3-the-top-performing-agents-evaluated-on-swe-fficiency-achieve-less-than-0-23x-of-the-expert-level-speedup-on-average-across-the-498-tasks-abstract-only/page.md +42 -51
- pages/claim-4-agents-struggle-specifically-with-localizing-optimization-opportunities-in-large-codebases-reasoning-about-execution-flow-across-multiple-functions-and-maintaining-correctness-of-proposed-optimizations-abstract-only/page.md +27 -42
- pages/conclusion/page.md +17 -67
- pages/executive-summary/page.md +13 -280
- pages/index.md +0 -2
- workspace.json +14 -0
README.md
CHANGED
|
@@ -11,6 +11,7 @@ tags:
|
|
| 11 |
- open-experiment
|
| 12 |
- icml2026-repro
|
| 13 |
- paper-0pyFbZSfbT
|
|
|
|
| 14 |
---
|
| 15 |
|
| 16 |
# Reproduction: SWE-fficiency: Can Language Models Optimize Real-World Repositories on Real Workloads?
|
|
|
|
| 11 |
- open-experiment
|
| 12 |
- icml2026-repro
|
| 13 |
- paper-0pyFbZSfbT
|
| 14 |
+
- arxiv:2511.06090
|
| 15 |
---
|
| 16 |
|
| 17 |
# Reproduction: SWE-fficiency: Can Language Models Optimize Real-World Repositories on Real Workloads?
|
index.html
CHANGED
|
@@ -21,6 +21,36 @@
|
|
| 21 |
</div>
|
| 22 |
</aside>
|
| 23 |
<main id="content">
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 24 |
<div id="page"></div>
|
| 25 |
</main>
|
| 26 |
</div>
|
|
|
|
| 21 |
</div>
|
| 22 |
</aside>
|
| 23 |
<main id="content">
|
| 24 |
+
<nav id="view-tabs" aria-label="Logbook views">
|
| 25 |
+
<a data-view="code" href="#/view/code/index">
|
| 26 |
+
<svg viewBox="0 0 24 24" aria-hidden="true">
|
| 27 |
+
<path d="m18 16 4-4-4-4" />
|
| 28 |
+
<path d="m6 8-4 4 4 4" />
|
| 29 |
+
<path d="m14.5 4-5 16" />
|
| 30 |
+
</svg>
|
| 31 |
+
<span>Logbook</span>
|
| 32 |
+
</a>
|
| 33 |
+
<a data-view="trace" href="#/view/trace">
|
| 34 |
+
<svg viewBox="0 0 24 24" aria-hidden="true">
|
| 35 |
+
<path d="M8 5h13" />
|
| 36 |
+
<path d="M13 12h8" />
|
| 37 |
+
<path d="M13 19h8" />
|
| 38 |
+
<path d="M3 10a2 2 0 0 0 2 2h3" />
|
| 39 |
+
<path d="M3 5v12a2 2 0 0 0 2 2h3" />
|
| 40 |
+
</svg>
|
| 41 |
+
<span>Traces</span>
|
| 42 |
+
</a>
|
| 43 |
+
<a data-view="workspace" href="#/view/workspace">
|
| 44 |
+
<svg viewBox="0 0 24 24" aria-hidden="true">
|
| 45 |
+
<path d="M20 20a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.9a2 2 0 0 1-1.69-.9L9.6 3.9A2 2 0 0 0 7.93 3H4a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2Z" />
|
| 46 |
+
</svg>
|
| 47 |
+
<span>Workspace</span>
|
| 48 |
+
</a>
|
| 49 |
+
</nav>
|
| 50 |
+
<header id="logbook-header">
|
| 51 |
+
<h1 id="logbook-title"></h1>
|
| 52 |
+
<div id="logbook-cli"></div>
|
| 53 |
+
</header>
|
| 54 |
<div id="page"></div>
|
| 55 |
</main>
|
| 56 |
</div>
|
logbook.css
CHANGED
|
@@ -1,6 +1,6 @@
|
|
| 1 |
:root {
|
| 2 |
--bg: #ffffff;
|
| 3 |
-
--paper: #
|
| 4 |
--panel: #ffffff;
|
| 5 |
--ink: #1f2937;
|
| 6 |
--muted: #6b7280;
|
|
@@ -9,7 +9,7 @@
|
|
| 9 |
--accent-strong: #ea580c;
|
| 10 |
--accent-soft: #fff7ed;
|
| 11 |
--accent-line: rgba(249, 115, 22, 0.16);
|
| 12 |
-
--grid-line: rgba(31, 41, 55, 0.
|
| 13 |
--code-bg: #f3f4f6;
|
| 14 |
--radius: 12px;
|
| 15 |
--serif: ui-serif, "Iowan Old Style", "Palatino Linotype", Georgia, serif;
|
|
@@ -31,6 +31,7 @@ body {
|
|
| 31 |
|
| 32 |
html {
|
| 33 |
scroll-behavior: smooth;
|
|
|
|
| 34 |
}
|
| 35 |
|
| 36 |
body {
|
|
@@ -47,6 +48,11 @@ body {
|
|
| 47 |
min-height: 100vh;
|
| 48 |
}
|
| 49 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 50 |
/* ---- sidebar (composition-book cover) ---- */
|
| 51 |
#sidebar {
|
| 52 |
width: 280px;
|
|
@@ -97,6 +103,15 @@ body {
|
|
| 97 |
padding-top: 8px;
|
| 98 |
}
|
| 99 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 100 |
#tree a {
|
| 101 |
display: block;
|
| 102 |
padding: 6px 10px;
|
|
@@ -105,6 +120,9 @@ body {
|
|
| 105 |
text-decoration: none;
|
| 106 |
font-size: 14px;
|
| 107 |
transition: background 0.12s, color 0.12s;
|
|
|
|
|
|
|
|
|
|
| 108 |
}
|
| 109 |
|
| 110 |
#tree a:hover {
|
|
@@ -143,7 +161,7 @@ body {
|
|
| 143 |
#content {
|
| 144 |
flex: 1;
|
| 145 |
min-width: 0;
|
| 146 |
-
padding:
|
| 147 |
background-color: var(--paper);
|
| 148 |
background-image:
|
| 149 |
linear-gradient(var(--grid-line) 1px, transparent 1px),
|
|
@@ -152,10 +170,28 @@ body {
|
|
| 152 |
background-position: center top;
|
| 153 |
}
|
| 154 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 155 |
#page {
|
| 156 |
width: 100%;
|
| 157 |
min-width: 0;
|
| 158 |
-
max-width:
|
| 159 |
margin: 0 auto;
|
| 160 |
}
|
| 161 |
|
|
@@ -170,10 +206,7 @@ body {
|
|
| 170 |
}
|
| 171 |
|
| 172 |
.page-layout {
|
| 173 |
-
display:
|
| 174 |
-
grid-template-columns: minmax(0, 760px) 248px;
|
| 175 |
-
gap: 44px;
|
| 176 |
-
align-items: start;
|
| 177 |
}
|
| 178 |
|
| 179 |
.page-body {
|
|
@@ -188,18 +221,26 @@ body {
|
|
| 188 |
|
| 189 |
/* ---- pinned notes ---- */
|
| 190 |
.pinned-notes {
|
| 191 |
-
margin: 30px 0
|
| 192 |
}
|
| 193 |
.pinned-notes-list .cell {
|
| 194 |
margin: 0;
|
| 195 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 196 |
}
|
| 197 |
.pinned-notes-list .cell + .cell {
|
| 198 |
margin-top: 12px;
|
| 199 |
}
|
| 200 |
-
.cell.pinned-source {
|
| 201 |
-
border-color: rgba(249, 115, 22, 0.55);
|
| 202 |
-
}
|
| 203 |
.book-intro.has-pinned-notes {
|
| 204 |
border-bottom: none;
|
| 205 |
padding-bottom: 22px;
|
|
@@ -376,26 +417,25 @@ body {
|
|
| 376 |
/* ---- notebook-style cells ---- */
|
| 377 |
.cell {
|
| 378 |
max-width: 100%;
|
| 379 |
-
|
| 380 |
-
|
| 381 |
-
|
| 382 |
-
|
| 383 |
-
|
| 384 |
-
|
| 385 |
}
|
| 386 |
.cell-head {
|
| 387 |
display: flex;
|
| 388 |
justify-content: space-between;
|
| 389 |
gap: 16px;
|
| 390 |
-
align-items:
|
| 391 |
-
padding:
|
| 392 |
-
background:
|
| 393 |
-
border-bottom:
|
| 394 |
}
|
| 395 |
.cell-head.no-title {
|
| 396 |
justify-content: flex-end;
|
| 397 |
-
padding
|
| 398 |
-
padding-bottom: 10px;
|
| 399 |
}
|
| 400 |
.cell-title {
|
| 401 |
flex: 1;
|
|
@@ -427,7 +467,7 @@ body {
|
|
| 427 |
}
|
| 428 |
.cell-body {
|
| 429 |
min-width: 0;
|
| 430 |
-
padding:
|
| 431 |
}
|
| 432 |
.cell.dashboard .cell-body {
|
| 433 |
padding: 0;
|
|
@@ -447,9 +487,6 @@ body {
|
|
| 447 |
#page .cell-body > :last-child {
|
| 448 |
margin-bottom: 0;
|
| 449 |
}
|
| 450 |
-
.cell.code .cell-head {
|
| 451 |
-
background: #fbfbfc;
|
| 452 |
-
}
|
| 453 |
.figure-fit {
|
| 454 |
position: relative;
|
| 455 |
overflow: hidden;
|
|
@@ -622,9 +659,40 @@ body {
|
|
| 622 |
border: 1px solid var(--line);
|
| 623 |
border-radius: 10px;
|
| 624 |
overflow: hidden;
|
| 625 |
-
margin:
|
| 626 |
background: var(--panel);
|
| 627 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 628 |
.jp-gutter {
|
| 629 |
flex: 0 0 46px;
|
| 630 |
padding: 13px 0 0 13px;
|
|
@@ -652,6 +720,8 @@ body {
|
|
| 652 |
border-radius: 0;
|
| 653 |
background: none;
|
| 654 |
padding: 12px 16px 12px 0;
|
|
|
|
|
|
|
| 655 |
}
|
| 656 |
.jp-in-body .code-accordion {
|
| 657 |
margin: 0;
|
|
@@ -1055,11 +1125,13 @@ table.board tr.linked-row:hover a {
|
|
| 1055 |
align-items: center;
|
| 1056 |
flex-wrap: wrap;
|
| 1057 |
gap: 8px;
|
| 1058 |
-
margin:
|
| 1059 |
font-size: 12.5px;
|
| 1060 |
color: var(--muted);
|
| 1061 |
}
|
| 1062 |
-
|
|
|
|
|
|
|
| 1063 |
background: var(--code-bg);
|
| 1064 |
padding: 2px 9px;
|
| 1065 |
border-radius: 6px;
|
|
@@ -1067,6 +1139,9 @@ table.board tr.linked-row:hover a {
|
|
| 1067 |
font-size: 12px;
|
| 1068 |
font-weight: 500;
|
| 1069 |
color: var(--ink);
|
|
|
|
|
|
|
|
|
|
| 1070 |
}
|
| 1071 |
.agent-hint .copy {
|
| 1072 |
flex: 0 0 auto;
|
|
@@ -1094,155 +1169,57 @@ table.board tr.linked-row:hover a {
|
|
| 1094 |
font-size: 12px;
|
| 1095 |
color: var(--muted);
|
| 1096 |
}
|
| 1097 |
-
|
| 1098 |
-
/* ---- logbook summary stats ---- */
|
| 1099 |
-
.logbook-stats {
|
| 1100 |
display: flex;
|
|
|
|
| 1101 |
flex-wrap: wrap;
|
| 1102 |
-
gap:
|
| 1103 |
-
|
|
|
|
| 1104 |
}
|
| 1105 |
-
.
|
| 1106 |
-
position: relative;
|
| 1107 |
display: inline-flex;
|
| 1108 |
align-items: center;
|
| 1109 |
-
gap:
|
| 1110 |
-
|
| 1111 |
-
|
| 1112 |
-
border
|
| 1113 |
-
|
| 1114 |
-
|
| 1115 |
-
text-align: left;
|
| 1116 |
-
cursor: pointer;
|
| 1117 |
-
transition: border-color 0.12s, box-shadow 0.12s;
|
| 1118 |
-
}
|
| 1119 |
-
.stat-tile:hover:not([disabled]) {
|
| 1120 |
-
border-color: rgba(249, 115, 22, 0.45);
|
| 1121 |
-
box-shadow: 0 3px 12px rgba(31, 41, 55, 0.06);
|
| 1122 |
-
}
|
| 1123 |
-
.stat-tile:focus-visible {
|
| 1124 |
-
outline: 2px solid var(--accent);
|
| 1125 |
-
outline-offset: 2px;
|
| 1126 |
-
}
|
| 1127 |
-
.stat-tile[disabled] {
|
| 1128 |
-
cursor: default;
|
| 1129 |
-
opacity: 0.7;
|
| 1130 |
-
}
|
| 1131 |
-
.stat-tile.open {
|
| 1132 |
-
border-color: rgba(249, 115, 22, 0.6);
|
| 1133 |
-
box-shadow: 0 3px 12px rgba(31, 41, 55, 0.08);
|
| 1134 |
-
}
|
| 1135 |
-
.stat-icon {
|
| 1136 |
-
width: 24px;
|
| 1137 |
-
height: 24px;
|
| 1138 |
-
flex: 0 0 24px;
|
| 1139 |
-
object-fit: contain;
|
| 1140 |
-
align-self: center;
|
| 1141 |
-
}
|
| 1142 |
-
.stat-text {
|
| 1143 |
-
display: flex;
|
| 1144 |
-
align-items: baseline;
|
| 1145 |
-
gap: 8px;
|
| 1146 |
-
white-space: nowrap;
|
| 1147 |
-
line-height: 1;
|
| 1148 |
-
}
|
| 1149 |
-
.stat-num {
|
| 1150 |
-
font-family: var(--mono);
|
| 1151 |
-
font-size: 20px;
|
| 1152 |
-
font-weight: 600;
|
| 1153 |
-
line-height: 1;
|
| 1154 |
color: var(--accent-strong);
|
| 1155 |
-
|
| 1156 |
-
|
| 1157 |
-
font-
|
| 1158 |
-
line-height: 1;
|
| 1159 |
-
color: var(--muted);
|
| 1160 |
-
}
|
| 1161 |
-
.stat-caret {
|
| 1162 |
-
margin-left: 2px;
|
| 1163 |
-
font-size: 10px;
|
| 1164 |
-
color: var(--muted);
|
| 1165 |
-
align-self: center;
|
| 1166 |
-
transition: transform 0.12s;
|
| 1167 |
-
}
|
| 1168 |
-
.stat-tile.open .stat-caret {
|
| 1169 |
-
transform: rotate(180deg);
|
| 1170 |
-
}
|
| 1171 |
-
.stat-popover {
|
| 1172 |
-
position: absolute;
|
| 1173 |
-
top: 100%;
|
| 1174 |
-
left: 0;
|
| 1175 |
-
margin-top: 6px;
|
| 1176 |
-
min-width: 300px;
|
| 1177 |
-
max-width: min(460px, 92vw);
|
| 1178 |
-
max-height: 340px;
|
| 1179 |
-
overflow-y: auto;
|
| 1180 |
-
z-index: 20;
|
| 1181 |
-
background: var(--panel);
|
| 1182 |
-
border: 1px solid var(--line);
|
| 1183 |
-
border-radius: var(--radius);
|
| 1184 |
-
box-shadow: 0 8px 28px rgba(31, 41, 55, 0.12);
|
| 1185 |
-
padding: 6px;
|
| 1186 |
-
}
|
| 1187 |
-
.stat-popover[hidden] {
|
| 1188 |
-
display: none;
|
| 1189 |
-
}
|
| 1190 |
-
.stat-pop-head {
|
| 1191 |
-
padding: 6px 10px 8px;
|
| 1192 |
-
font-size: 11.5px;
|
| 1193 |
-
font-weight: 700;
|
| 1194 |
-
letter-spacing: 0.03em;
|
| 1195 |
-
text-transform: uppercase;
|
| 1196 |
-
color: var(--muted);
|
| 1197 |
-
}
|
| 1198 |
-
.stat-row {
|
| 1199 |
-
display: flex;
|
| 1200 |
-
align-items: flex-start;
|
| 1201 |
-
gap: 10px;
|
| 1202 |
-
padding: 9px 11px;
|
| 1203 |
-
border-radius: 9px;
|
| 1204 |
-
border: 1px solid transparent;
|
| 1205 |
text-decoration: none;
|
| 1206 |
-
|
| 1207 |
-
|
| 1208 |
}
|
| 1209 |
-
.
|
| 1210 |
-
border-color:
|
| 1211 |
-
background:
|
|
|
|
| 1212 |
}
|
| 1213 |
-
.
|
| 1214 |
-
|
| 1215 |
-
|
| 1216 |
flex: 0 0 auto;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1217 |
}
|
| 1218 |
-
|
| 1219 |
-
|
| 1220 |
-
|
| 1221 |
-
|
| 1222 |
-
|
| 1223 |
-
font-
|
| 1224 |
-
font-size: 12.5px;
|
| 1225 |
-
font-weight: 600;
|
| 1226 |
-
color: var(--ink);
|
| 1227 |
-
overflow: hidden;
|
| 1228 |
-
text-overflow: ellipsis;
|
| 1229 |
-
white-space: nowrap;
|
| 1230 |
-
}
|
| 1231 |
-
.stat-row-meta {
|
| 1232 |
-
margin-top: 2px;
|
| 1233 |
-
font-size: 12px;
|
| 1234 |
-
color: var(--muted);
|
| 1235 |
-
}
|
| 1236 |
-
.stat-row-state.open {
|
| 1237 |
-
color: var(--accent);
|
| 1238 |
-
font-weight: 600;
|
| 1239 |
-
border-radius: 5px;
|
| 1240 |
-
padding: 1px 5px;
|
| 1241 |
-
margin: -1px -2px;
|
| 1242 |
}
|
| 1243 |
-
.
|
| 1244 |
-
|
| 1245 |
-
text-decoration:
|
| 1246 |
}
|
| 1247 |
.art-ico {
|
| 1248 |
width: 1em;
|
|
@@ -1250,6 +1227,20 @@ table.board tr.linked-row:hover a {
|
|
| 1250 |
object-fit: contain;
|
| 1251 |
vertical-align: -0.15em;
|
| 1252 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1253 |
|
| 1254 |
/* ---- scroll-to-resource highlight ---- */
|
| 1255 |
.res-flash {
|
|
@@ -1294,108 +1285,11 @@ table.board tr.linked-row:hover a {
|
|
| 1294 |
font-size: 1.05em;
|
| 1295 |
line-height: 1;
|
| 1296 |
}
|
| 1297 |
-
#page .res-chip:hover
|
| 1298 |
-
#page .res-chip.res-hl {
|
| 1299 |
-
border-color: var(--accent);
|
| 1300 |
-
background: var(--accent-soft);
|
| 1301 |
-
color: var(--accent-strong);
|
| 1302 |
-
}
|
| 1303 |
-
#page a.res-link.res-hl {
|
| 1304 |
-
background: var(--accent-soft);
|
| 1305 |
-
border-radius: 4px;
|
| 1306 |
-
}
|
| 1307 |
-
.rail-item.res-hl {
|
| 1308 |
-
border-color: var(--accent);
|
| 1309 |
-
background: var(--accent-soft);
|
| 1310 |
-
box-shadow: 0 3px 12px rgba(249, 115, 22, 0.14);
|
| 1311 |
-
}
|
| 1312 |
-
.rail-item.res-hl .rail-title {
|
| 1313 |
-
color: var(--accent-strong);
|
| 1314 |
-
}
|
| 1315 |
-
.rail-item.rail-local {
|
| 1316 |
-
cursor: default;
|
| 1317 |
-
}
|
| 1318 |
-
.artifact-chip.res-hl {
|
| 1319 |
border-color: var(--accent);
|
| 1320 |
background: var(--accent-soft);
|
| 1321 |
-
}
|
| 1322 |
-
|
| 1323 |
-
/* ---- contextual resources rail ---- */
|
| 1324 |
-
.context-rail {
|
| 1325 |
-
position: relative;
|
| 1326 |
-
width: 248px;
|
| 1327 |
-
}
|
| 1328 |
-
.context-rail[hidden] {
|
| 1329 |
-
display: none;
|
| 1330 |
-
}
|
| 1331 |
-
.rail-kind {
|
| 1332 |
-
display: flex;
|
| 1333 |
-
align-items: center;
|
| 1334 |
-
gap: 5px;
|
| 1335 |
-
font-family: var(--mono);
|
| 1336 |
-
font-size: 10px;
|
| 1337 |
-
text-transform: uppercase;
|
| 1338 |
-
letter-spacing: 0.08em;
|
| 1339 |
-
font-weight: 600;
|
| 1340 |
-
color: var(--accent);
|
| 1341 |
-
margin-bottom: 4px;
|
| 1342 |
-
}
|
| 1343 |
-
.rail-item {
|
| 1344 |
-
position: absolute;
|
| 1345 |
-
left: 0;
|
| 1346 |
-
right: 0;
|
| 1347 |
-
display: block;
|
| 1348 |
-
border: 1px solid var(--line);
|
| 1349 |
-
border-radius: 10px;
|
| 1350 |
-
background: var(--panel);
|
| 1351 |
-
padding: 9px 12px;
|
| 1352 |
-
margin-bottom: 8px;
|
| 1353 |
-
text-decoration: none;
|
| 1354 |
-
color: inherit;
|
| 1355 |
-
transition: border-color 0.14s, box-shadow 0.14s;
|
| 1356 |
-
}
|
| 1357 |
-
.rail-item:hover {
|
| 1358 |
-
border-color: rgba(249, 115, 22, 0.45);
|
| 1359 |
-
box-shadow: 0 3px 12px rgba(31, 41, 55, 0.06);
|
| 1360 |
-
}
|
| 1361 |
-
.rail-title {
|
| 1362 |
-
font-family: var(--mono);
|
| 1363 |
-
font-size: 12.5px;
|
| 1364 |
-
font-weight: 600;
|
| 1365 |
-
color: var(--ink);
|
| 1366 |
-
overflow-wrap: anywhere;
|
| 1367 |
-
line-height: 1.4;
|
| 1368 |
-
}
|
| 1369 |
-
.rail-item:hover .rail-title {
|
| 1370 |
color: var(--accent-strong);
|
| 1371 |
}
|
| 1372 |
-
.rail-meta {
|
| 1373 |
-
font-size: 11.5px;
|
| 1374 |
-
color: var(--muted);
|
| 1375 |
-
margin-top: 2px;
|
| 1376 |
-
}
|
| 1377 |
-
|
| 1378 |
-
@media (max-width: 1400px) {
|
| 1379 |
-
.page-layout {
|
| 1380 |
-
display: block;
|
| 1381 |
-
}
|
| 1382 |
-
.context-rail {
|
| 1383 |
-
width: 100%;
|
| 1384 |
-
margin-top: 28px;
|
| 1385 |
-
position: static;
|
| 1386 |
-
min-height: 0 !important;
|
| 1387 |
-
display: grid;
|
| 1388 |
-
grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
|
| 1389 |
-
gap: 10px;
|
| 1390 |
-
}
|
| 1391 |
-
.context-rail[hidden] {
|
| 1392 |
-
display: none;
|
| 1393 |
-
}
|
| 1394 |
-
.context-rail .rail-item {
|
| 1395 |
-
position: static;
|
| 1396 |
-
margin-bottom: 0;
|
| 1397 |
-
}
|
| 1398 |
-
}
|
| 1399 |
|
| 1400 |
/* ---- connect footer + modal ---- */
|
| 1401 |
#sidebar-foot {
|
|
@@ -1571,27 +1465,665 @@ table.board tr.linked-row:hover a {
|
|
| 1571 |
color: #52d08a;
|
| 1572 |
}
|
| 1573 |
|
| 1574 |
-
|
| 1575 |
-
|
| 1576 |
-
|
| 1577 |
-
|
| 1578 |
-
|
| 1579 |
-
|
| 1580 |
-
|
| 1581 |
-
|
| 1582 |
-
|
| 1583 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1584 |
#content {
|
| 1585 |
display: block;
|
| 1586 |
width: 100%;
|
| 1587 |
padding: 28px 20px 80px;
|
| 1588 |
overflow-x: hidden;
|
| 1589 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1590 |
#page {
|
| 1591 |
width: 100%;
|
| 1592 |
max-width: 100%;
|
| 1593 |
}
|
| 1594 |
-
#page h1
|
|
|
|
| 1595 |
font-size: 30px;
|
| 1596 |
}
|
| 1597 |
.cell-head {
|
|
|
|
| 1 |
:root {
|
| 2 |
--bg: #ffffff;
|
| 3 |
+
--paper: #ffffff;
|
| 4 |
--panel: #ffffff;
|
| 5 |
--ink: #1f2937;
|
| 6 |
--muted: #6b7280;
|
|
|
|
| 9 |
--accent-strong: #ea580c;
|
| 10 |
--accent-soft: #fff7ed;
|
| 11 |
--accent-line: rgba(249, 115, 22, 0.16);
|
| 12 |
+
--grid-line: rgba(31, 41, 55, 0.02);
|
| 13 |
--code-bg: #f3f4f6;
|
| 14 |
--radius: 12px;
|
| 15 |
--serif: ui-serif, "Iowan Old Style", "Palatino Linotype", Georgia, serif;
|
|
|
|
| 31 |
|
| 32 |
html {
|
| 33 |
scroll-behavior: smooth;
|
| 34 |
+
scrollbar-gutter: stable;
|
| 35 |
}
|
| 36 |
|
| 37 |
body {
|
|
|
|
| 48 |
min-height: 100vh;
|
| 49 |
}
|
| 50 |
|
| 51 |
+
body[data-view="trace"] #sidebar-foot,
|
| 52 |
+
body[data-view="workspace"] #sidebar-foot {
|
| 53 |
+
display: none;
|
| 54 |
+
}
|
| 55 |
+
|
| 56 |
/* ---- sidebar (composition-book cover) ---- */
|
| 57 |
#sidebar {
|
| 58 |
width: 280px;
|
|
|
|
| 103 |
padding-top: 8px;
|
| 104 |
}
|
| 105 |
|
| 106 |
+
#tree .tree-label {
|
| 107 |
+
padding: 6px 10px 8px;
|
| 108 |
+
color: #777a83;
|
| 109 |
+
font-size: 10px;
|
| 110 |
+
font-weight: 700;
|
| 111 |
+
letter-spacing: 0.12em;
|
| 112 |
+
text-transform: uppercase;
|
| 113 |
+
}
|
| 114 |
+
|
| 115 |
#tree a {
|
| 116 |
display: block;
|
| 117 |
padding: 6px 10px;
|
|
|
|
| 120 |
text-decoration: none;
|
| 121 |
font-size: 14px;
|
| 122 |
transition: background 0.12s, color 0.12s;
|
| 123 |
+
overflow: hidden;
|
| 124 |
+
text-overflow: ellipsis;
|
| 125 |
+
white-space: nowrap;
|
| 126 |
}
|
| 127 |
|
| 128 |
#tree a:hover {
|
|
|
|
| 161 |
#content {
|
| 162 |
flex: 1;
|
| 163 |
min-width: 0;
|
| 164 |
+
padding: 24px 40px 120px;
|
| 165 |
background-color: var(--paper);
|
| 166 |
background-image:
|
| 167 |
linear-gradient(var(--grid-line) 1px, transparent 1px),
|
|
|
|
| 170 |
background-position: center top;
|
| 171 |
}
|
| 172 |
|
| 173 |
+
#logbook-header {
|
| 174 |
+
width: 100%;
|
| 175 |
+
max-width: 1080px;
|
| 176 |
+
margin: 0 auto 20px;
|
| 177 |
+
}
|
| 178 |
+
#logbook-title {
|
| 179 |
+
font-family: var(--serif);
|
| 180 |
+
font-size: 34px;
|
| 181 |
+
line-height: 1.15;
|
| 182 |
+
letter-spacing: -0.02em;
|
| 183 |
+
margin: 0 0 10px;
|
| 184 |
+
overflow-wrap: anywhere;
|
| 185 |
+
}
|
| 186 |
+
#logbook-cli {
|
| 187 |
+
display: grid;
|
| 188 |
+
gap: 7px;
|
| 189 |
+
}
|
| 190 |
+
|
| 191 |
#page {
|
| 192 |
width: 100%;
|
| 193 |
min-width: 0;
|
| 194 |
+
max-width: 1080px;
|
| 195 |
margin: 0 auto;
|
| 196 |
}
|
| 197 |
|
|
|
|
| 206 |
}
|
| 207 |
|
| 208 |
.page-layout {
|
| 209 |
+
display: block;
|
|
|
|
|
|
|
|
|
|
| 210 |
}
|
| 211 |
|
| 212 |
.page-body {
|
|
|
|
| 221 |
|
| 222 |
/* ---- pinned notes ---- */
|
| 223 |
.pinned-notes {
|
| 224 |
+
margin: 30px 0 32px;
|
| 225 |
}
|
| 226 |
.pinned-notes-list .cell {
|
| 227 |
margin: 0;
|
| 228 |
+
}
|
| 229 |
+
.pinned-notes-list .cell-title {
|
| 230 |
+
display: flex;
|
| 231 |
+
align-items: center;
|
| 232 |
+
gap: 7px;
|
| 233 |
+
}
|
| 234 |
+
.pin-ico {
|
| 235 |
+
flex: 0 0 auto;
|
| 236 |
+
width: 14px;
|
| 237 |
+
height: 14px;
|
| 238 |
+
fill: var(--accent);
|
| 239 |
+
stroke: none;
|
| 240 |
}
|
| 241 |
.pinned-notes-list .cell + .cell {
|
| 242 |
margin-top: 12px;
|
| 243 |
}
|
|
|
|
|
|
|
|
|
|
| 244 |
.book-intro.has-pinned-notes {
|
| 245 |
border-bottom: none;
|
| 246 |
padding-bottom: 22px;
|
|
|
|
| 417 |
/* ---- notebook-style cells ---- */
|
| 418 |
.cell {
|
| 419 |
max-width: 100%;
|
| 420 |
+
margin: 0 0 32px;
|
| 421 |
+
background: none;
|
| 422 |
+
border: none;
|
| 423 |
+
border-radius: 0;
|
| 424 |
+
box-shadow: none;
|
| 425 |
+
overflow: visible;
|
| 426 |
}
|
| 427 |
.cell-head {
|
| 428 |
display: flex;
|
| 429 |
justify-content: space-between;
|
| 430 |
gap: 16px;
|
| 431 |
+
align-items: baseline;
|
| 432 |
+
padding: 0 0 5px;
|
| 433 |
+
background: none;
|
| 434 |
+
border-bottom: none;
|
| 435 |
}
|
| 436 |
.cell-head.no-title {
|
| 437 |
justify-content: flex-end;
|
| 438 |
+
padding: 0 0 3px;
|
|
|
|
| 439 |
}
|
| 440 |
.cell-title {
|
| 441 |
flex: 1;
|
|
|
|
| 467 |
}
|
| 468 |
.cell-body {
|
| 469 |
min-width: 0;
|
| 470 |
+
padding: 0;
|
| 471 |
}
|
| 472 |
.cell.dashboard .cell-body {
|
| 473 |
padding: 0;
|
|
|
|
| 487 |
#page .cell-body > :last-child {
|
| 488 |
margin-bottom: 0;
|
| 489 |
}
|
|
|
|
|
|
|
|
|
|
| 490 |
.figure-fit {
|
| 491 |
position: relative;
|
| 492 |
overflow: hidden;
|
|
|
|
| 659 |
border: 1px solid var(--line);
|
| 660 |
border-radius: 10px;
|
| 661 |
overflow: hidden;
|
| 662 |
+
margin: 0;
|
| 663 |
background: var(--panel);
|
| 664 |
}
|
| 665 |
+
.jp-cmd {
|
| 666 |
+
display: flex;
|
| 667 |
+
align-items: baseline;
|
| 668 |
+
gap: 9px;
|
| 669 |
+
position: relative;
|
| 670 |
+
padding: 10px 16px 10px 0;
|
| 671 |
+
font-family: var(--mono);
|
| 672 |
+
font-size: 12px;
|
| 673 |
+
color: #8b8e98;
|
| 674 |
+
}
|
| 675 |
+
.jp-cmd-prompt {
|
| 676 |
+
color: var(--accent);
|
| 677 |
+
font-weight: 700;
|
| 678 |
+
}
|
| 679 |
+
#page .jp-cmd code {
|
| 680 |
+
min-width: 0;
|
| 681 |
+
color: #b6b9c2;
|
| 682 |
+
font-family: var(--mono);
|
| 683 |
+
font-size: 12px;
|
| 684 |
+
background: none;
|
| 685 |
+
padding: 0;
|
| 686 |
+
border-radius: 0;
|
| 687 |
+
overflow-wrap: anywhere;
|
| 688 |
+
}
|
| 689 |
+
.jp-cmd:hover .copy-snippet {
|
| 690 |
+
opacity: 1;
|
| 691 |
+
}
|
| 692 |
+
.jp-in-body .jp-cmd + .code-accordion,
|
| 693 |
+
.jp-in-body .jp-cmd + .snippet {
|
| 694 |
+
border-top: 1px solid rgba(255, 255, 255, 0.09);
|
| 695 |
+
}
|
| 696 |
.jp-gutter {
|
| 697 |
flex: 0 0 46px;
|
| 698 |
padding: 13px 0 0 13px;
|
|
|
|
| 720 |
border-radius: 0;
|
| 721 |
background: none;
|
| 722 |
padding: 12px 16px 12px 0;
|
| 723 |
+
overflow-y: auto;
|
| 724 |
+
max-height: 26em;
|
| 725 |
}
|
| 726 |
.jp-in-body .code-accordion {
|
| 727 |
margin: 0;
|
|
|
|
| 1125 |
align-items: center;
|
| 1126 |
flex-wrap: wrap;
|
| 1127 |
gap: 8px;
|
| 1128 |
+
margin: 0;
|
| 1129 |
font-size: 12.5px;
|
| 1130 |
color: var(--muted);
|
| 1131 |
}
|
| 1132 |
+
.agent-hint code {
|
| 1133 |
+
flex: 1 1 18rem;
|
| 1134 |
+
min-width: 0;
|
| 1135 |
background: var(--code-bg);
|
| 1136 |
padding: 2px 9px;
|
| 1137 |
border-radius: 6px;
|
|
|
|
| 1139 |
font-size: 12px;
|
| 1140 |
font-weight: 500;
|
| 1141 |
color: var(--ink);
|
| 1142 |
+
overflow: hidden;
|
| 1143 |
+
text-overflow: ellipsis;
|
| 1144 |
+
white-space: nowrap;
|
| 1145 |
}
|
| 1146 |
.agent-hint .copy {
|
| 1147 |
flex: 0 0 auto;
|
|
|
|
| 1169 |
font-size: 12px;
|
| 1170 |
color: var(--muted);
|
| 1171 |
}
|
| 1172 |
+
.hub-destination {
|
|
|
|
|
|
|
| 1173 |
display: flex;
|
| 1174 |
+
align-items: center;
|
| 1175 |
flex-wrap: wrap;
|
| 1176 |
+
gap: 8px;
|
| 1177 |
+
color: var(--muted);
|
| 1178 |
+
font-size: 12.5px;
|
| 1179 |
}
|
| 1180 |
+
.hub-destination a {
|
|
|
|
| 1181 |
display: inline-flex;
|
| 1182 |
align-items: center;
|
| 1183 |
+
gap: 6px;
|
| 1184 |
+
max-width: 100%;
|
| 1185 |
+
padding: 3px 9px;
|
| 1186 |
+
border: 1px solid var(--accent-line);
|
| 1187 |
+
border-radius: 999px;
|
| 1188 |
+
background: var(--accent-soft);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1189 |
color: var(--accent-strong);
|
| 1190 |
+
font-family: var(--mono);
|
| 1191 |
+
font-size: 12px;
|
| 1192 |
+
font-weight: 650;
|
| 1193 |
+
line-height: 1.5;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1194 |
text-decoration: none;
|
| 1195 |
+
overflow-wrap: anywhere;
|
| 1196 |
+
transition: border-color 0.12s, background 0.12s, color 0.12s;
|
| 1197 |
}
|
| 1198 |
+
.hub-destination a:hover {
|
| 1199 |
+
border-color: var(--accent);
|
| 1200 |
+
background: #ffedd5;
|
| 1201 |
+
color: #c2410c;
|
| 1202 |
}
|
| 1203 |
+
.hub-destination svg {
|
| 1204 |
+
width: 13px;
|
| 1205 |
+
height: 13px;
|
| 1206 |
flex: 0 0 auto;
|
| 1207 |
+
fill: none;
|
| 1208 |
+
stroke: currentColor;
|
| 1209 |
+
stroke-width: 1.8;
|
| 1210 |
+
stroke-linecap: round;
|
| 1211 |
+
stroke-linejoin: round;
|
| 1212 |
}
|
| 1213 |
+
|
| 1214 |
+
.index-paper-link {
|
| 1215 |
+
margin: 14px 0 30px;
|
| 1216 |
+
font-size: 19px;
|
| 1217 |
+
line-height: 1.35;
|
| 1218 |
+
font-weight: 700;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1219 |
}
|
| 1220 |
+
.index-paper-link a {
|
| 1221 |
+
text-underline-offset: 4px;
|
| 1222 |
+
text-decoration-thickness: 2px;
|
| 1223 |
}
|
| 1224 |
.art-ico {
|
| 1225 |
width: 1em;
|
|
|
|
| 1227 |
object-fit: contain;
|
| 1228 |
vertical-align: -0.15em;
|
| 1229 |
}
|
| 1230 |
+
.art-file-ico {
|
| 1231 |
+
width: 15px;
|
| 1232 |
+
height: 15px;
|
| 1233 |
+
flex: 0 0 auto;
|
| 1234 |
+
fill: none;
|
| 1235 |
+
stroke: currentColor;
|
| 1236 |
+
stroke-width: 1.7;
|
| 1237 |
+
stroke-linecap: round;
|
| 1238 |
+
stroke-linejoin: round;
|
| 1239 |
+
vertical-align: -0.2em;
|
| 1240 |
+
}
|
| 1241 |
+
.out-artifact-ico .art-file-ico {
|
| 1242 |
+
color: var(--muted);
|
| 1243 |
+
}
|
| 1244 |
|
| 1245 |
/* ---- scroll-to-resource highlight ---- */
|
| 1246 |
.res-flash {
|
|
|
|
| 1285 |
font-size: 1.05em;
|
| 1286 |
line-height: 1;
|
| 1287 |
}
|
| 1288 |
+
#page .res-chip:hover {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1289 |
border-color: var(--accent);
|
| 1290 |
background: var(--accent-soft);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1291 |
color: var(--accent-strong);
|
| 1292 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1293 |
|
| 1294 |
/* ---- connect footer + modal ---- */
|
| 1295 |
#sidebar-foot {
|
|
|
|
| 1465 |
color: #52d08a;
|
| 1466 |
}
|
| 1467 |
|
| 1468 |
+
/* ---- top-level logbook views ---- */
|
| 1469 |
+
#view-tabs {
|
| 1470 |
+
position: sticky;
|
| 1471 |
+
top: 0;
|
| 1472 |
+
z-index: 30;
|
| 1473 |
+
width: 100%;
|
| 1474 |
+
max-width: 1080px;
|
| 1475 |
+
margin: 0 auto 24px;
|
| 1476 |
+
padding-top: 10px;
|
| 1477 |
+
display: flex;
|
| 1478 |
+
align-items: center;
|
| 1479 |
+
justify-content: flex-start;
|
| 1480 |
+
gap: 26px;
|
| 1481 |
+
border-bottom: 1px solid var(--line);
|
| 1482 |
+
background: var(--paper);
|
| 1483 |
+
}
|
| 1484 |
+
#view-tabs a {
|
| 1485 |
+
display: inline-flex;
|
| 1486 |
+
align-items: center;
|
| 1487 |
+
gap: 8px;
|
| 1488 |
+
min-height: 44px;
|
| 1489 |
+
margin-bottom: -1px;
|
| 1490 |
+
color: var(--muted);
|
| 1491 |
+
border-bottom: 2px solid transparent;
|
| 1492 |
+
text-decoration: none;
|
| 1493 |
+
font-size: 13.5px;
|
| 1494 |
+
font-weight: 600;
|
| 1495 |
+
transition: color 0.12s, border-color 0.12s;
|
| 1496 |
+
}
|
| 1497 |
+
#view-tabs a:hover {
|
| 1498 |
+
color: var(--ink);
|
| 1499 |
+
}
|
| 1500 |
+
#view-tabs a.active {
|
| 1501 |
+
color: var(--accent-strong);
|
| 1502 |
+
border-bottom-color: var(--accent);
|
| 1503 |
+
}
|
| 1504 |
+
#view-tabs svg {
|
| 1505 |
+
width: 18px;
|
| 1506 |
+
height: 18px;
|
| 1507 |
+
flex: 0 0 auto;
|
| 1508 |
+
fill: none;
|
| 1509 |
+
stroke: currentColor;
|
| 1510 |
+
stroke-width: 2;
|
| 1511 |
+
stroke-linecap: round;
|
| 1512 |
+
stroke-linejoin: round;
|
| 1513 |
+
}
|
| 1514 |
+
.workspace-file svg,
|
| 1515 |
+
.workspace-folder summary svg,
|
| 1516 |
+
.workspace-download svg {
|
| 1517 |
+
width: 17px;
|
| 1518 |
+
height: 17px;
|
| 1519 |
+
flex: 0 0 auto;
|
| 1520 |
+
fill: none;
|
| 1521 |
+
stroke: currentColor;
|
| 1522 |
+
stroke-width: 1.7;
|
| 1523 |
+
stroke-linecap: round;
|
| 1524 |
+
stroke-linejoin: round;
|
| 1525 |
+
}
|
| 1526 |
+
|
| 1527 |
+
#page.trace-page,
|
| 1528 |
+
#page.workspace-page {
|
| 1529 |
+
max-width: 1080px;
|
| 1530 |
+
}
|
| 1531 |
+
.view-loading {
|
| 1532 |
+
padding: 72px 0;
|
| 1533 |
+
color: var(--muted);
|
| 1534 |
+
text-align: center;
|
| 1535 |
+
}
|
| 1536 |
+
.view-empty {
|
| 1537 |
+
margin: 48px 0;
|
| 1538 |
+
padding: 44px 28px;
|
| 1539 |
+
border: 1px dashed #d8dbe1;
|
| 1540 |
+
border-radius: var(--radius);
|
| 1541 |
+
background: rgba(255, 255, 255, 0.72);
|
| 1542 |
+
text-align: center;
|
| 1543 |
+
}
|
| 1544 |
+
.view-empty h2 {
|
| 1545 |
+
margin: 0 0 7px;
|
| 1546 |
+
font-size: 18px;
|
| 1547 |
+
}
|
| 1548 |
+
.view-empty p {
|
| 1549 |
+
max-width: 560px;
|
| 1550 |
+
margin: 0 auto;
|
| 1551 |
+
color: var(--muted);
|
| 1552 |
+
}
|
| 1553 |
+
.view-empty code {
|
| 1554 |
+
display: inline-block;
|
| 1555 |
+
margin-top: 18px;
|
| 1556 |
+
padding: 7px 10px;
|
| 1557 |
+
border-radius: 7px;
|
| 1558 |
+
background: var(--code-bg);
|
| 1559 |
+
font-family: var(--mono);
|
| 1560 |
+
font-size: 12px;
|
| 1561 |
+
}
|
| 1562 |
+
#page .repo-ref-link {
|
| 1563 |
+
display: inline-block;
|
| 1564 |
+
margin-top: 18px;
|
| 1565 |
+
padding: 8px 14px;
|
| 1566 |
+
border-radius: 8px;
|
| 1567 |
+
background: var(--accent-strong, #2158d0);
|
| 1568 |
+
color: #fff;
|
| 1569 |
+
font-weight: 600;
|
| 1570 |
+
text-decoration: none;
|
| 1571 |
+
}
|
| 1572 |
+
#page .repo-ref-link:hover,
|
| 1573 |
+
#page .repo-ref-link:focus-visible {
|
| 1574 |
+
color: #fff;
|
| 1575 |
+
filter: brightness(0.95);
|
| 1576 |
+
}
|
| 1577 |
+
.view-eyebrow {
|
| 1578 |
+
margin-bottom: 4px;
|
| 1579 |
+
color: var(--accent-strong);
|
| 1580 |
+
font-family: var(--mono);
|
| 1581 |
+
font-size: 11px;
|
| 1582 |
+
font-weight: 700;
|
| 1583 |
+
letter-spacing: 0.12em;
|
| 1584 |
+
text-transform: uppercase;
|
| 1585 |
+
}
|
| 1586 |
+
|
| 1587 |
+
/* ---- trace ---- */
|
| 1588 |
+
.trace-session {
|
| 1589 |
+
scroll-margin-top: 24px;
|
| 1590 |
+
}
|
| 1591 |
+
.trace-session + .trace-session {
|
| 1592 |
+
margin-top: 44px;
|
| 1593 |
+
padding-top: 40px;
|
| 1594 |
+
border-top: 1px solid var(--line);
|
| 1595 |
+
}
|
| 1596 |
+
.trace-session-title {
|
| 1597 |
+
margin: 0 0 14px;
|
| 1598 |
+
color: var(--ink);
|
| 1599 |
+
font-family: var(--serif);
|
| 1600 |
+
font-size: 22px;
|
| 1601 |
+
line-height: 1.2;
|
| 1602 |
+
letter-spacing: -0.02em;
|
| 1603 |
+
overflow-wrap: anywhere;
|
| 1604 |
+
}
|
| 1605 |
+
.workspace-header h1 {
|
| 1606 |
+
margin: 0;
|
| 1607 |
+
color: var(--ink);
|
| 1608 |
+
font-size: 30px;
|
| 1609 |
+
line-height: 1.2;
|
| 1610 |
+
letter-spacing: -0.025em;
|
| 1611 |
+
}
|
| 1612 |
+
.trace-meta {
|
| 1613 |
+
display: flex;
|
| 1614 |
+
flex-wrap: wrap;
|
| 1615 |
+
gap: 9px 20px;
|
| 1616 |
+
margin-bottom: 34px;
|
| 1617 |
+
padding: 14px 16px;
|
| 1618 |
+
border: 1px solid var(--line);
|
| 1619 |
+
border-radius: 10px;
|
| 1620 |
+
background: rgba(255, 255, 255, 0.78);
|
| 1621 |
+
color: var(--muted);
|
| 1622 |
+
font-family: var(--mono);
|
| 1623 |
+
font-size: 11px;
|
| 1624 |
+
}
|
| 1625 |
+
.trace-meta strong {
|
| 1626 |
+
color: var(--ink);
|
| 1627 |
+
font-weight: 650;
|
| 1628 |
+
}
|
| 1629 |
+
.trace-source-missing {
|
| 1630 |
+
color: #b45309;
|
| 1631 |
+
}
|
| 1632 |
+
.trace-timeline {
|
| 1633 |
+
position: relative;
|
| 1634 |
+
}
|
| 1635 |
+
.trace-timeline::before {
|
| 1636 |
+
content: "";
|
| 1637 |
+
position: absolute;
|
| 1638 |
+
top: 0;
|
| 1639 |
+
bottom: 0;
|
| 1640 |
+
left: 82px;
|
| 1641 |
+
width: 1px;
|
| 1642 |
+
background: #dedfe3;
|
| 1643 |
+
}
|
| 1644 |
+
.trace-load-controls {
|
| 1645 |
+
display: flex;
|
| 1646 |
+
align-items: center;
|
| 1647 |
+
justify-content: space-between;
|
| 1648 |
+
gap: 16px;
|
| 1649 |
+
margin: 22px 0 0 100px;
|
| 1650 |
+
padding-top: 16px;
|
| 1651 |
+
border-top: 1px solid var(--line);
|
| 1652 |
+
}
|
| 1653 |
+
.trace-load-progress {
|
| 1654 |
+
color: var(--muted);
|
| 1655 |
+
font-family: var(--mono);
|
| 1656 |
+
font-size: 11px;
|
| 1657 |
+
}
|
| 1658 |
+
.trace-load-more {
|
| 1659 |
+
padding: 7px 12px;
|
| 1660 |
+
border: 1px solid var(--line-strong);
|
| 1661 |
+
border-radius: 7px;
|
| 1662 |
+
background: var(--paper);
|
| 1663 |
+
color: var(--ink);
|
| 1664 |
+
cursor: pointer;
|
| 1665 |
+
font: 650 12px/1.2 var(--sans);
|
| 1666 |
+
}
|
| 1667 |
+
.trace-load-more:hover:not(:disabled) {
|
| 1668 |
+
border-color: var(--accent);
|
| 1669 |
+
color: var(--accent-strong);
|
| 1670 |
+
}
|
| 1671 |
+
.trace-load-more:disabled {
|
| 1672 |
+
cursor: default;
|
| 1673 |
+
opacity: 0.65;
|
| 1674 |
+
}
|
| 1675 |
+
.trace-entry {
|
| 1676 |
+
--trace-depth: 0;
|
| 1677 |
+
position: relative;
|
| 1678 |
+
display: grid;
|
| 1679 |
+
grid-template-columns: 100px minmax(0, 1fr);
|
| 1680 |
+
margin: 0 0 18px calc(var(--trace-depth) * 24px);
|
| 1681 |
+
}
|
| 1682 |
+
.trace-rail {
|
| 1683 |
+
position: relative;
|
| 1684 |
+
min-height: 36px;
|
| 1685 |
+
padding: 4px 28px 0 0;
|
| 1686 |
+
color: #8a8d95;
|
| 1687 |
+
text-align: right;
|
| 1688 |
+
font-family: var(--mono);
|
| 1689 |
+
}
|
| 1690 |
+
.trace-number,
|
| 1691 |
+
.trace-elapsed {
|
| 1692 |
+
display: block;
|
| 1693 |
+
white-space: nowrap;
|
| 1694 |
+
}
|
| 1695 |
+
.trace-number {
|
| 1696 |
+
font-size: 12px;
|
| 1697 |
+
font-weight: 650;
|
| 1698 |
+
}
|
| 1699 |
+
.trace-elapsed {
|
| 1700 |
+
margin-top: 3px;
|
| 1701 |
+
font-size: 10px;
|
| 1702 |
+
}
|
| 1703 |
+
.trace-dot {
|
| 1704 |
+
position: absolute;
|
| 1705 |
+
top: 10px;
|
| 1706 |
+
right: 11px;
|
| 1707 |
+
width: 11px;
|
| 1708 |
+
height: 11px;
|
| 1709 |
+
border: 2px solid var(--paper);
|
| 1710 |
+
border-radius: 50%;
|
| 1711 |
+
background: var(--accent);
|
| 1712 |
+
box-shadow: 0 0 0 1px #d7d9de;
|
| 1713 |
+
}
|
| 1714 |
+
.trace-card {
|
| 1715 |
+
min-width: 0;
|
| 1716 |
+
overflow: hidden;
|
| 1717 |
+
border: 1px solid #dddfe4;
|
| 1718 |
+
border-radius: 11px;
|
| 1719 |
+
background: rgba(255, 255, 255, 0.92);
|
| 1720 |
+
}
|
| 1721 |
+
.trace-card > header {
|
| 1722 |
+
display: flex;
|
| 1723 |
+
align-items: center;
|
| 1724 |
+
gap: 10px;
|
| 1725 |
+
min-height: 37px;
|
| 1726 |
+
padding: 8px 13px;
|
| 1727 |
+
border-bottom: 1px solid #eceef1;
|
| 1728 |
+
}
|
| 1729 |
+
.trace-status .trace-card > header {
|
| 1730 |
+
border-bottom: 0;
|
| 1731 |
+
padding-bottom: 5px;
|
| 1732 |
+
}
|
| 1733 |
+
.trace-kind {
|
| 1734 |
+
font-family: var(--mono);
|
| 1735 |
+
font-size: 10.5px;
|
| 1736 |
+
font-weight: 750;
|
| 1737 |
+
letter-spacing: 0.08em;
|
| 1738 |
+
text-transform: uppercase;
|
| 1739 |
+
}
|
| 1740 |
+
.trace-turn {
|
| 1741 |
+
color: var(--muted);
|
| 1742 |
+
font: 10px var(--mono);
|
| 1743 |
+
}
|
| 1744 |
+
.trace-status-badge {
|
| 1745 |
+
margin-left: auto;
|
| 1746 |
+
padding: 1px 6px;
|
| 1747 |
+
border-radius: 999px;
|
| 1748 |
+
background: #eef0f3;
|
| 1749 |
+
color: var(--muted);
|
| 1750 |
+
font: 9.5px var(--mono);
|
| 1751 |
+
text-transform: uppercase;
|
| 1752 |
+
}
|
| 1753 |
+
.trace-status-badge-error,
|
| 1754 |
+
.trace-status-badge-failed {
|
| 1755 |
+
background: #fef2f2;
|
| 1756 |
+
color: #b91c1c;
|
| 1757 |
+
}
|
| 1758 |
+
.trace-body {
|
| 1759 |
+
margin: 0;
|
| 1760 |
+
padding: 15px 17px 17px;
|
| 1761 |
+
overflow-wrap: anywhere;
|
| 1762 |
+
white-space: pre-wrap;
|
| 1763 |
+
font-family: var(--sans);
|
| 1764 |
+
font-size: 13px;
|
| 1765 |
+
line-height: 1.65;
|
| 1766 |
+
}
|
| 1767 |
+
.trace-reasoning .trace-card {
|
| 1768 |
+
border-style: dashed;
|
| 1769 |
+
border-color: #d7b98a;
|
| 1770 |
+
background: #fffdf8;
|
| 1771 |
+
}
|
| 1772 |
+
.trace-reasoning .trace-kind {
|
| 1773 |
+
color: #9a6b22;
|
| 1774 |
+
}
|
| 1775 |
+
.trace-reasoning .trace-body {
|
| 1776 |
+
font-style: italic;
|
| 1777 |
+
}
|
| 1778 |
+
.trace-user .trace-card {
|
| 1779 |
+
border-left: 3px solid #f3a66d;
|
| 1780 |
+
}
|
| 1781 |
+
.trace-tool_call .trace-card,
|
| 1782 |
+
.trace-tool_result .trace-card {
|
| 1783 |
+
border-color: #2d3036;
|
| 1784 |
+
background: #191a1e;
|
| 1785 |
+
color: #ececf0;
|
| 1786 |
+
}
|
| 1787 |
+
.trace-tool_call .trace-card > header,
|
| 1788 |
+
.trace-tool_result .trace-card > header {
|
| 1789 |
+
border-bottom-color: rgba(255, 255, 255, 0.1);
|
| 1790 |
+
}
|
| 1791 |
+
.trace-tool_call .trace-kind,
|
| 1792 |
+
.trace-tool_result .trace-kind {
|
| 1793 |
+
color: #f5a66d;
|
| 1794 |
+
}
|
| 1795 |
+
.trace-tool_call .trace-turn,
|
| 1796 |
+
.trace-tool_result .trace-turn {
|
| 1797 |
+
color: #979aa3;
|
| 1798 |
+
}
|
| 1799 |
+
.trace-tool_call .trace-body,
|
| 1800 |
+
.trace-tool_result .trace-body,
|
| 1801 |
+
.trace-output pre {
|
| 1802 |
+
font-family: var(--mono);
|
| 1803 |
+
font-size: 11.5px;
|
| 1804 |
+
line-height: 1.6;
|
| 1805 |
+
}
|
| 1806 |
+
#page .trace-tool_call pre.trace-body,
|
| 1807 |
+
#page .trace-tool_result pre.trace-body {
|
| 1808 |
+
margin: 0;
|
| 1809 |
+
padding: 15px 17px 17px;
|
| 1810 |
+
border: 0;
|
| 1811 |
+
border-radius: 0;
|
| 1812 |
+
background: transparent;
|
| 1813 |
+
color: #ececf0;
|
| 1814 |
+
}
|
| 1815 |
+
.trace-output {
|
| 1816 |
+
border-top: 1px dashed rgba(255, 255, 255, 0.14);
|
| 1817 |
+
}
|
| 1818 |
+
.trace-output summary {
|
| 1819 |
+
padding: 9px 14px;
|
| 1820 |
+
color: #aaaeb7;
|
| 1821 |
+
cursor: pointer;
|
| 1822 |
+
font: 700 10px var(--mono);
|
| 1823 |
+
letter-spacing: 0.06em;
|
| 1824 |
+
text-transform: uppercase;
|
| 1825 |
+
}
|
| 1826 |
+
#page .trace-output pre {
|
| 1827 |
+
max-height: 480px;
|
| 1828 |
+
margin: 0;
|
| 1829 |
+
padding: 0 16px 16px;
|
| 1830 |
+
border: 0;
|
| 1831 |
+
border-radius: 0;
|
| 1832 |
+
background: transparent;
|
| 1833 |
+
overflow: auto;
|
| 1834 |
+
color: #d7d8dd;
|
| 1835 |
+
white-space: pre-wrap;
|
| 1836 |
+
}
|
| 1837 |
+
|
| 1838 |
+
/* ---- workspace ---- */
|
| 1839 |
+
.workspace-header {
|
| 1840 |
+
padding-bottom: 24px;
|
| 1841 |
+
}
|
| 1842 |
+
.workspace-header p {
|
| 1843 |
+
margin: 0;
|
| 1844 |
+
color: var(--muted);
|
| 1845 |
+
font-family: var(--mono);
|
| 1846 |
+
font-size: 11px;
|
| 1847 |
+
}
|
| 1848 |
+
.workspace-inventory {
|
| 1849 |
+
overflow: hidden;
|
| 1850 |
+
border: 1px solid var(--line);
|
| 1851 |
+
border-radius: 11px;
|
| 1852 |
+
background: rgba(255, 255, 255, 0.92);
|
| 1853 |
+
}
|
| 1854 |
+
.workspace-folder > summary {
|
| 1855 |
+
display: flex;
|
| 1856 |
+
align-items: center;
|
| 1857 |
+
gap: 8px;
|
| 1858 |
+
min-height: 39px;
|
| 1859 |
+
padding: 8px 13px;
|
| 1860 |
+
background: #fafafa;
|
| 1861 |
+
cursor: pointer;
|
| 1862 |
+
font-weight: 650;
|
| 1863 |
+
list-style: none;
|
| 1864 |
+
}
|
| 1865 |
+
.workspace-folder > summary::-webkit-details-marker {
|
| 1866 |
+
display: none;
|
| 1867 |
+
}
|
| 1868 |
+
.workspace-folder > summary::after {
|
| 1869 |
+
content: "›";
|
| 1870 |
+
margin-left: auto;
|
| 1871 |
+
color: #989ba2;
|
| 1872 |
+
transform: rotate(90deg);
|
| 1873 |
+
}
|
| 1874 |
+
.workspace-folder:not([open]) > summary::after {
|
| 1875 |
+
transform: rotate(0);
|
| 1876 |
+
}
|
| 1877 |
+
.workspace-folder-children {
|
| 1878 |
+
padding-left: 20px;
|
| 1879 |
+
}
|
| 1880 |
+
.workspace-file {
|
| 1881 |
+
display: grid;
|
| 1882 |
+
grid-template-columns: minmax(180px, 1fr) 72px 78px 180px 36px;
|
| 1883 |
+
align-items: center;
|
| 1884 |
+
min-height: 44px;
|
| 1885 |
+
padding: 7px 10px 7px 13px;
|
| 1886 |
+
color: var(--muted);
|
| 1887 |
+
font-family: var(--mono);
|
| 1888 |
+
font-size: 10.5px;
|
| 1889 |
+
}
|
| 1890 |
+
.workspace-file-name {
|
| 1891 |
+
display: flex;
|
| 1892 |
+
align-items: center;
|
| 1893 |
+
min-width: 0;
|
| 1894 |
+
gap: 8px;
|
| 1895 |
+
color: var(--ink);
|
| 1896 |
+
font-family: var(--sans);
|
| 1897 |
+
font-size: 12.5px;
|
| 1898 |
+
font-weight: 550;
|
| 1899 |
+
}
|
| 1900 |
+
.workspace-file-name span {
|
| 1901 |
+
overflow: hidden;
|
| 1902 |
+
text-overflow: ellipsis;
|
| 1903 |
+
white-space: nowrap;
|
| 1904 |
+
}
|
| 1905 |
+
.workspace-file-type {
|
| 1906 |
+
width: fit-content;
|
| 1907 |
+
padding: 1px 6px;
|
| 1908 |
+
border-radius: 999px;
|
| 1909 |
+
background: var(--accent-soft);
|
| 1910 |
+
color: var(--accent-strong);
|
| 1911 |
+
text-transform: uppercase;
|
| 1912 |
+
}
|
| 1913 |
+
.workspace-download {
|
| 1914 |
+
display: inline-flex;
|
| 1915 |
+
align-items: center;
|
| 1916 |
+
justify-content: center;
|
| 1917 |
+
width: 30px;
|
| 1918 |
+
height: 30px;
|
| 1919 |
+
border-radius: 7px;
|
| 1920 |
+
color: var(--muted);
|
| 1921 |
+
}
|
| 1922 |
+
.workspace-download:hover {
|
| 1923 |
+
background: var(--accent-soft);
|
| 1924 |
+
color: var(--accent-strong);
|
| 1925 |
+
}
|
| 1926 |
+
.workspace-unpublished {
|
| 1927 |
+
color: #9ca3af;
|
| 1928 |
+
text-align: center;
|
| 1929 |
+
}
|
| 1930 |
+
|
| 1931 |
+
.workspace-header {
|
| 1932 |
+
display: flex;
|
| 1933 |
+
align-items: center;
|
| 1934 |
+
justify-content: space-between;
|
| 1935 |
+
gap: 16px;
|
| 1936 |
+
flex-wrap: wrap;
|
| 1937 |
+
}
|
| 1938 |
+
.workspace-toggle {
|
| 1939 |
+
display: inline-flex;
|
| 1940 |
+
align-items: center;
|
| 1941 |
+
padding: 2px;
|
| 1942 |
+
border: 1px solid var(--line);
|
| 1943 |
+
border-radius: 999px;
|
| 1944 |
+
background: #fafafa;
|
| 1945 |
+
}
|
| 1946 |
+
.workspace-toggle-btn {
|
| 1947 |
+
padding: 4px 13px;
|
| 1948 |
+
border: 0;
|
| 1949 |
+
border-radius: 999px;
|
| 1950 |
+
background: transparent;
|
| 1951 |
+
color: var(--muted);
|
| 1952 |
+
font-family: var(--sans);
|
| 1953 |
+
font-size: 12px;
|
| 1954 |
+
font-weight: 600;
|
| 1955 |
+
cursor: pointer;
|
| 1956 |
+
}
|
| 1957 |
+
.workspace-toggle-btn:hover {
|
| 1958 |
+
color: var(--accent-strong);
|
| 1959 |
+
}
|
| 1960 |
+
.workspace-toggle-btn.is-active {
|
| 1961 |
+
background: var(--accent);
|
| 1962 |
+
color: #ffffff;
|
| 1963 |
+
}
|
| 1964 |
+
.workspace-group + .workspace-group {
|
| 1965 |
+
margin-top: 18px;
|
| 1966 |
+
}
|
| 1967 |
+
.workspace-group-head,
|
| 1968 |
+
.workspace-hub-group-head {
|
| 1969 |
+
display: flex;
|
| 1970 |
+
align-items: center;
|
| 1971 |
+
gap: 8px;
|
| 1972 |
+
margin: 0;
|
| 1973 |
+
padding: 8px 13px;
|
| 1974 |
+
background: #fafafa;
|
| 1975 |
+
border-bottom: 1px solid var(--line);
|
| 1976 |
+
color: var(--ink);
|
| 1977 |
+
font-family: var(--sans);
|
| 1978 |
+
font-size: 12px;
|
| 1979 |
+
font-weight: 650;
|
| 1980 |
+
text-transform: capitalize;
|
| 1981 |
+
}
|
| 1982 |
+
.workspace-group-count,
|
| 1983 |
+
.workspace-hub-count {
|
| 1984 |
+
padding: 0 7px;
|
| 1985 |
+
border-radius: 999px;
|
| 1986 |
+
background: var(--accent-soft);
|
| 1987 |
+
color: var(--accent-strong);
|
| 1988 |
+
font-family: var(--mono);
|
| 1989 |
+
font-size: 10.5px;
|
| 1990 |
+
}
|
| 1991 |
+
.workspace-group {
|
| 1992 |
+
overflow: hidden;
|
| 1993 |
+
border: 1px solid var(--line);
|
| 1994 |
+
border-radius: 11px;
|
| 1995 |
+
background: rgba(255, 255, 255, 0.92);
|
| 1996 |
+
}
|
| 1997 |
+
|
| 1998 |
+
.workspace-hub {
|
| 1999 |
+
margin-top: 28px;
|
| 2000 |
+
}
|
| 2001 |
+
.workspace-hub-title {
|
| 2002 |
+
margin: 0 0 14px;
|
| 2003 |
+
font-family: var(--sans);
|
| 2004 |
+
font-size: 16px;
|
| 2005 |
+
font-weight: 700;
|
| 2006 |
+
color: var(--ink);
|
| 2007 |
+
}
|
| 2008 |
+
.workspace-hub-group {
|
| 2009 |
+
overflow: hidden;
|
| 2010 |
+
border: 1px solid var(--line);
|
| 2011 |
+
border-radius: 11px;
|
| 2012 |
+
background: rgba(255, 255, 255, 0.92);
|
| 2013 |
+
}
|
| 2014 |
+
.workspace-hub-group + .workspace-hub-group {
|
| 2015 |
+
margin-top: 14px;
|
| 2016 |
+
}
|
| 2017 |
+
.workspace-hub-list {
|
| 2018 |
+
display: flex;
|
| 2019 |
+
flex-direction: column;
|
| 2020 |
+
}
|
| 2021 |
+
.workspace-hub-link {
|
| 2022 |
+
padding: 9px 13px;
|
| 2023 |
+
color: var(--accent-strong);
|
| 2024 |
+
font-family: var(--mono);
|
| 2025 |
+
font-size: 12px;
|
| 2026 |
+
text-decoration: none;
|
| 2027 |
+
overflow: hidden;
|
| 2028 |
+
text-overflow: ellipsis;
|
| 2029 |
+
white-space: nowrap;
|
| 2030 |
+
}
|
| 2031 |
+
.workspace-hub-link + .workspace-hub-link {
|
| 2032 |
+
border-top: 1px solid var(--line);
|
| 2033 |
+
}
|
| 2034 |
+
.workspace-hub-link:hover {
|
| 2035 |
+
background: var(--accent-soft);
|
| 2036 |
+
text-decoration: underline;
|
| 2037 |
+
}
|
| 2038 |
+
|
| 2039 |
+
/* --- UI nits --- */
|
| 2040 |
+
/* Flush group headers: #page h3/h2 (ID selectors) otherwise inject a top margin
|
| 2041 |
+
that, with overflow:hidden on the card, shows as whitespace above "Jobs" etc. */
|
| 2042 |
+
#page .workspace-hub-title {
|
| 2043 |
+
margin: 0 0 14px;
|
| 2044 |
+
}
|
| 2045 |
+
#page .workspace-hub-group-head,
|
| 2046 |
+
#page .workspace-group-head {
|
| 2047 |
+
margin: 0;
|
| 2048 |
+
}
|
| 2049 |
+
/* HF brand logo before the "Hugging Face artifacts" heading */
|
| 2050 |
+
.workspace-hub-title {
|
| 2051 |
+
display: flex;
|
| 2052 |
+
align-items: center;
|
| 2053 |
+
gap: 9px;
|
| 2054 |
+
}
|
| 2055 |
+
.workspace-hub-logo {
|
| 2056 |
+
width: 22px;
|
| 2057 |
+
height: 22px;
|
| 2058 |
+
flex: none;
|
| 2059 |
+
}
|
| 2060 |
+
/* Center empty-state placeholders (heading, body, command) */
|
| 2061 |
+
.view-empty {
|
| 2062 |
+
display: flex;
|
| 2063 |
+
flex-direction: column;
|
| 2064 |
+
align-items: center;
|
| 2065 |
+
}
|
| 2066 |
+
#page .view-empty h2,
|
| 2067 |
+
#page .view-empty p {
|
| 2068 |
+
text-align: center;
|
| 2069 |
+
}
|
| 2070 |
+
|
| 2071 |
+
@media (max-width: 720px) {
|
| 2072 |
+
#app {
|
| 2073 |
+
flex-direction: column;
|
| 2074 |
+
}
|
| 2075 |
+
#sidebar {
|
| 2076 |
+
width: 100%;
|
| 2077 |
+
flex: none;
|
| 2078 |
+
height: auto;
|
| 2079 |
+
position: static;
|
| 2080 |
+
}
|
| 2081 |
#content {
|
| 2082 |
display: block;
|
| 2083 |
width: 100%;
|
| 2084 |
padding: 28px 20px 80px;
|
| 2085 |
overflow-x: hidden;
|
| 2086 |
}
|
| 2087 |
+
#view-tabs {
|
| 2088 |
+
margin: 0 0 20px;
|
| 2089 |
+
gap: 18px;
|
| 2090 |
+
justify-content: flex-start;
|
| 2091 |
+
overflow-x: auto;
|
| 2092 |
+
}
|
| 2093 |
+
#view-tabs a {
|
| 2094 |
+
flex: 0 0 auto;
|
| 2095 |
+
}
|
| 2096 |
+
.trace-timeline::before {
|
| 2097 |
+
left: 16px;
|
| 2098 |
+
}
|
| 2099 |
+
.trace-entry {
|
| 2100 |
+
grid-template-columns: 32px minmax(0, 1fr);
|
| 2101 |
+
margin-left: calc(var(--trace-depth) * 10px);
|
| 2102 |
+
}
|
| 2103 |
+
.trace-rail {
|
| 2104 |
+
padding: 0;
|
| 2105 |
+
}
|
| 2106 |
+
.trace-number,
|
| 2107 |
+
.trace-elapsed {
|
| 2108 |
+
display: none;
|
| 2109 |
+
}
|
| 2110 |
+
.trace-dot {
|
| 2111 |
+
top: 10px;
|
| 2112 |
+
right: 10px;
|
| 2113 |
+
}
|
| 2114 |
+
.workspace-file {
|
| 2115 |
+
grid-template-columns: minmax(150px, 1fr) 66px 34px;
|
| 2116 |
+
}
|
| 2117 |
+
.workspace-file-size,
|
| 2118 |
+
.workspace-file-time {
|
| 2119 |
+
display: none;
|
| 2120 |
+
}
|
| 2121 |
#page {
|
| 2122 |
width: 100%;
|
| 2123 |
max-width: 100%;
|
| 2124 |
}
|
| 2125 |
+
#page h1,
|
| 2126 |
+
#logbook-title {
|
| 2127 |
font-size: 30px;
|
| 2128 |
}
|
| 2129 |
.cell-head {
|
logbook.js
CHANGED
|
@@ -4,9 +4,12 @@
|
|
| 4 |
let MANIFEST = null;
|
| 5 |
const PAGE_CACHE = {};
|
| 6 |
const UNFURL_CACHE = {};
|
|
|
|
| 7 |
const LIVE_RELOAD_MS = 1500;
|
| 8 |
const FIGURE_FRAME_WINDOWS = new Set();
|
| 9 |
let FIGURE_NAVIGATION_READY = false;
|
|
|
|
|
|
|
| 10 |
|
| 11 |
function esc(s) {
|
| 12 |
return String(s)
|
|
@@ -286,6 +289,10 @@
|
|
| 286 |
/(trackio-artifact:\/\/\S+|trackio-local-path:\/\/\S+|https:\/\/huggingface\.co\/buckets\/[^\s<)]+#\S+)/
|
| 287 |
);
|
| 288 |
if (chip && uri) chip.dataset.resUrl = uri[1];
|
|
|
|
|
|
|
|
|
|
|
|
|
| 289 |
} else if (meta.type === "dashboard") {
|
| 290 |
const sp = body.match(/https:\/\/huggingface\.co\/spaces\/[^\s<>)"'`]+/);
|
| 291 |
cell.dataset.resUrl = sp
|
|
@@ -495,7 +502,7 @@
|
|
| 495 |
if (!message || message.type !== "trackio-logbook:navigate") return;
|
| 496 |
const target = String(message.target || "").replace(/^#?\//, "");
|
| 497 |
if (!target || !MANIFEST || !findNode(MANIFEST.root, target)) return;
|
| 498 |
-
const hash = "#/" + target;
|
| 499 |
if (location.hash === hash) scrollToHash();
|
| 500 |
else location.hash = hash;
|
| 501 |
});
|
|
@@ -507,6 +514,15 @@
|
|
| 507 |
'<path d="M8 3H3v5M16 3h5v5M21 16v5h-5M3 16v5h5"/>' +
|
| 508 |
'<path d="M3 8 8 3M16 3l5 5M21 16l-5 5M8 21l-5-5"/></svg>';
|
| 509 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 510 |
// Figures are rendered in same-origin iframes, so fullscreen the fitted
|
| 511 |
// wrapper rather than the iframe document. This uses the browser's native
|
| 512 |
// fullscreen UI and preserves the figure's existing responsive sizing.
|
|
@@ -635,13 +651,38 @@
|
|
| 635 |
? `<span class="out-artifact-state open">Open ↗</span>`
|
| 636 |
: `<span class="out-artifact-state">publish to share</span>`;
|
| 637 |
const meta = parts.length ? `${parts.join(" · ")} · ${state}` : state;
|
|
|
|
| 638 |
el.innerHTML =
|
| 639 |
-
`<span class="out-artifact-ico">${
|
| 640 |
`<span class="out-artifact-name">${esc(info.name)}</span>` +
|
| 641 |
`<span class="out-artifact-meta">${meta}</span>`;
|
| 642 |
return el;
|
| 643 |
}
|
| 644 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 645 |
function renderCodeCell(body, container, artifacts) {
|
| 646 |
const parts = parseFences(body);
|
| 647 |
const block = document.createElement("div");
|
|
@@ -694,7 +735,13 @@
|
|
| 694 |
embedTexts.push(part.text);
|
| 695 |
return;
|
| 696 |
}
|
| 697 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 698 |
});
|
| 699 |
if (artifacts && artifacts.length) {
|
| 700 |
ensureOut();
|
|
@@ -913,13 +960,13 @@
|
|
| 913 |
return btn;
|
| 914 |
}
|
| 915 |
|
| 916 |
-
function renderCode(code, lang, title) {
|
| 917 |
const pre = document.createElement("pre");
|
| 918 |
pre.className = "hl";
|
| 919 |
const c = document.createElement("code");
|
| 920 |
c.innerHTML = highlightCode(code, lang);
|
| 921 |
pre.appendChild(c);
|
| 922 |
-
if (!title) {
|
| 923 |
const wrap = document.createElement("div");
|
| 924 |
wrap.className = "snippet";
|
| 925 |
wrap.appendChild(pre);
|
|
@@ -983,7 +1030,7 @@
|
|
| 983 |
});
|
| 984 |
}
|
| 985 |
|
| 986 |
-
/* --------------------
|
| 987 |
|
| 988 |
function fmt(n) {
|
| 989 |
if (n == null) return null;
|
|
@@ -1011,18 +1058,6 @@
|
|
| 1011 |
const ARTIFACT_ICON_IMG = `<img class="art-ico" src="./bucket-icon.svg" alt="" />`;
|
| 1012 |
const DASHBOARD_ICON_IMG = `<img class="art-ico" src="./trackio-logo-light.png" alt="" />`;
|
| 1013 |
|
| 1014 |
-
const RESOURCE_DESC = {
|
| 1015 |
-
dashboard: "Dashboard",
|
| 1016 |
-
model: "Model",
|
| 1017 |
-
dataset: "Dataset",
|
| 1018 |
-
space: "Space",
|
| 1019 |
-
artifact: "Artifact — in Bucket",
|
| 1020 |
-
paper: "Paper",
|
| 1021 |
-
repo: "Repository",
|
| 1022 |
-
job: "Job — status & logs",
|
| 1023 |
-
bucket: "Bucket — artifacts & data",
|
| 1024 |
-
};
|
| 1025 |
-
|
| 1026 |
const HF_NON_MODEL_PREFIX =
|
| 1027 |
/^(datasets|spaces|jobs|buckets|papers|blog|docs|api|posts|collections|organizations|settings|new|join|login|pricing|tasks|learn|chat|models)(\/|$)/;
|
| 1028 |
|
|
@@ -1030,6 +1065,23 @@
|
|
| 1030 |
return url.split(marker)[1].split(/[?#]/)[0].replace(/\/$/, "");
|
| 1031 |
}
|
| 1032 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1033 |
function classifyResource(url) {
|
| 1034 |
if (IMG_URL.test(url)) {
|
| 1035 |
return null;
|
|
@@ -1059,29 +1111,39 @@
|
|
| 1059 |
local: true,
|
| 1060 |
};
|
| 1061 |
}
|
| 1062 |
-
if ((m = url.match(/huggingface\.co\/buckets\/[^#\s]+#(.+)/))) {
|
| 1063 |
-
|
|
|
|
| 1064 |
}
|
| 1065 |
-
if (/huggingface\.co\/datasets\/
|
| 1066 |
-
|
|
|
|
|
|
|
| 1067 |
}
|
| 1068 |
-
if (/huggingface\.co\/spaces\/
|
| 1069 |
-
|
|
|
|
|
|
|
| 1070 |
}
|
| 1071 |
if (/huggingface\.co\/jobs\//.test(url)) {
|
| 1072 |
-
const parts = hfId(url, "/jobs/").split("/");
|
| 1073 |
-
|
|
|
|
| 1074 |
return {
|
| 1075 |
kind: "job",
|
| 1076 |
-
id: parts[0] +
|
| 1077 |
url,
|
| 1078 |
};
|
| 1079 |
}
|
| 1080 |
if (/huggingface\.co\/buckets\//.test(url)) {
|
| 1081 |
-
|
|
|
|
|
|
|
| 1082 |
}
|
| 1083 |
if (/huggingface\.co\/papers\//.test(url)) {
|
| 1084 |
-
|
|
|
|
|
|
|
| 1085 |
}
|
| 1086 |
if ((m = url.match(/arxiv\.org\/(?:abs|pdf)\/([^?#\s]+)/))) {
|
| 1087 |
return { kind: "paper", id: `arXiv:${m[1].replace(/\.pdf$/, "")}`, url };
|
|
@@ -1091,324 +1153,13 @@
|
|
| 1091 |
}
|
| 1092 |
if ((m = url.match(/huggingface\.co\/([^?#]+)/))) {
|
| 1093 |
const rest = m[1].replace(/\/$/, "");
|
| 1094 |
-
if (
|
| 1095 |
return { kind: "model", id: rest, url };
|
| 1096 |
}
|
| 1097 |
}
|
| 1098 |
return null;
|
| 1099 |
}
|
| 1100 |
|
| 1101 |
-
async function fillRailMeta(item, el) {
|
| 1102 |
-
if (item.local) return;
|
| 1103 |
-
const meta = el.querySelector(".rail-meta");
|
| 1104 |
-
const set = (parts) => {
|
| 1105 |
-
const text = parts.filter(Boolean).join(" · ");
|
| 1106 |
-
if (text) meta.textContent = text;
|
| 1107 |
-
};
|
| 1108 |
-
if (item.kind === "model") {
|
| 1109 |
-
const d = await getJSON(`https://huggingface.co/api/models/${item.id}`);
|
| 1110 |
-
if (d) set([d.pipeline_tag, `↓ ${fmt(d.downloads)}`, `♥ ${fmt(d.likes)}`]);
|
| 1111 |
-
} else if (item.kind === "dataset") {
|
| 1112 |
-
const d = await getJSON(`https://huggingface.co/api/datasets/${item.id}`);
|
| 1113 |
-
if (d) set([`↓ ${fmt(d.downloads)}`, `♥ ${fmt(d.likes)}`]);
|
| 1114 |
-
} else if (item.kind === "space" || item.kind === "dashboard") {
|
| 1115 |
-
const d = await getJSON(`https://huggingface.co/api/spaces/${item.id}`);
|
| 1116 |
-
if (d) set([d.sdk, `♥ ${fmt(d.likes)}`]);
|
| 1117 |
-
} else if (item.kind === "repo") {
|
| 1118 |
-
const d = await getJSON(`https://api.github.com/repos/${item.id}`);
|
| 1119 |
-
if (d) set([`★ ${fmt(d.stargazers_count)}`, d.language]);
|
| 1120 |
-
} else if (item.kind === "paper") {
|
| 1121 |
-
const m = item.id.match(/^(?:arXiv:|Paper )(.+)$/);
|
| 1122 |
-
if (!m) return;
|
| 1123 |
-
const arxivId = m[1].replace(/v\d+$/, "");
|
| 1124 |
-
const d = await getJSON(`https://huggingface.co/api/papers/${arxivId}`);
|
| 1125 |
-
if (d && d.id) {
|
| 1126 |
-
if (el.href) el.href = `https://huggingface.co/papers/${d.id}`;
|
| 1127 |
-
const title =
|
| 1128 |
-
d.title && d.title.length > 70 ? `${d.title.slice(0, 69)}…` : d.title;
|
| 1129 |
-
set([title, d.upvotes ? `��� ${fmt(d.upvotes)}` : null]);
|
| 1130 |
-
}
|
| 1131 |
-
}
|
| 1132 |
-
}
|
| 1133 |
-
|
| 1134 |
-
const BARE_ID_SKIP_DIRS = new Set([
|
| 1135 |
-
"scripts",
|
| 1136 |
-
"configs",
|
| 1137 |
-
"config",
|
| 1138 |
-
"results",
|
| 1139 |
-
"figures",
|
| 1140 |
-
"data",
|
| 1141 |
-
"datasets",
|
| 1142 |
-
"src",
|
| 1143 |
-
"tests",
|
| 1144 |
-
"test",
|
| 1145 |
-
"examples",
|
| 1146 |
-
"pages",
|
| 1147 |
-
"assets",
|
| 1148 |
-
"docs",
|
| 1149 |
-
"outputs",
|
| 1150 |
-
"output",
|
| 1151 |
-
"checkpoints",
|
| 1152 |
-
"models",
|
| 1153 |
-
"utils",
|
| 1154 |
-
"lib",
|
| 1155 |
-
"bin",
|
| 1156 |
-
"tmp",
|
| 1157 |
-
"node_modules",
|
| 1158 |
-
"dist",
|
| 1159 |
-
"build",
|
| 1160 |
-
]);
|
| 1161 |
-
const FILE_EXT_RE =
|
| 1162 |
-
/\.(py|pyc|js|ts|jsx|tsx|json|jsonl|yaml|yml|csv|tsv|md|txt|sh|bash|html|css|png|jpe?g|svg|gif|webp|ipynb|toml|cfg|ini|lock|pdf|whl|gz|zip|tar|pt|pth|bin|safetensors|db|sqlite)$/i;
|
| 1163 |
-
|
| 1164 |
-
async function detectBareModelIds(text, groups) {
|
| 1165 |
-
const stripped = text.replace(DETECTED_URL, " ");
|
| 1166 |
-
DETECTED_URL.lastIndex = 0;
|
| 1167 |
-
const seen = new Set();
|
| 1168 |
-
const candidates = [];
|
| 1169 |
-
const re = /(^|[\s"'`(=[])([A-Za-z0-9][\w.-]*\/[A-Za-z0-9][\w.-]*)/g;
|
| 1170 |
-
let m;
|
| 1171 |
-
while ((m = re.exec(stripped)) && candidates.length < 15) {
|
| 1172 |
-
const id = m[2].replace(/[.:,]+$/, "");
|
| 1173 |
-
if (seen.has(id)) continue;
|
| 1174 |
-
seen.add(id);
|
| 1175 |
-
if (FILE_EXT_RE.test(id)) continue;
|
| 1176 |
-
if (BARE_ID_SKIP_DIRS.has(id.split("/")[0].toLowerCase())) continue;
|
| 1177 |
-
candidates.push(id);
|
| 1178 |
-
}
|
| 1179 |
-
const results = await Promise.all(
|
| 1180 |
-
candidates.map((id) => getJSON(`https://huggingface.co/api/models/${id}`))
|
| 1181 |
-
);
|
| 1182 |
-
let added = false;
|
| 1183 |
-
const confirmed = [];
|
| 1184 |
-
results.forEach((d, i) => {
|
| 1185 |
-
if (!d || !d.id) return;
|
| 1186 |
-
const id = candidates[i];
|
| 1187 |
-
confirmed.push(id);
|
| 1188 |
-
const url = `https://huggingface.co/${id}`;
|
| 1189 |
-
if (!groups.has("model")) groups.set("model", new Map());
|
| 1190 |
-
if (!groups.get("model").has(url)) {
|
| 1191 |
-
groups.get("model").set(url, { kind: "model", id, url });
|
| 1192 |
-
added = true;
|
| 1193 |
-
}
|
| 1194 |
-
});
|
| 1195 |
-
return { added, confirmed };
|
| 1196 |
-
}
|
| 1197 |
-
|
| 1198 |
-
function chipifyBareIds(ids, container) {
|
| 1199 |
-
if (!ids.length) return;
|
| 1200 |
-
const escaped = ids.map((id) => id.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"));
|
| 1201 |
-
const pattern = new RegExp("(" + escaped.join("|") + ")");
|
| 1202 |
-
const splitter = new RegExp(pattern.source, "g");
|
| 1203 |
-
container
|
| 1204 |
-
.querySelectorAll(".cell.markdown .cell-body")
|
| 1205 |
-
.forEach((body) => {
|
| 1206 |
-
const walker = document.createTreeWalker(body, NodeFilter.SHOW_TEXT, {
|
| 1207 |
-
acceptNode(node) {
|
| 1208 |
-
if (!pattern.test(node.nodeValue)) return NodeFilter.FILTER_REJECT;
|
| 1209 |
-
for (
|
| 1210 |
-
let el = node.parentElement;
|
| 1211 |
-
el && el !== body;
|
| 1212 |
-
el = el.parentElement
|
| 1213 |
-
) {
|
| 1214 |
-
if (["A", "CODE", "PRE", "BUTTON"].indexOf(el.tagName) !== -1) {
|
| 1215 |
-
return NodeFilter.FILTER_REJECT;
|
| 1216 |
-
}
|
| 1217 |
-
}
|
| 1218 |
-
return NodeFilter.FILTER_ACCEPT;
|
| 1219 |
-
},
|
| 1220 |
-
});
|
| 1221 |
-
const nodes = [];
|
| 1222 |
-
while (walker.nextNode()) nodes.push(walker.currentNode);
|
| 1223 |
-
nodes.forEach((node) => {
|
| 1224 |
-
const frag = document.createDocumentFragment();
|
| 1225 |
-
node.nodeValue.split(splitter).forEach((part) => {
|
| 1226 |
-
if (ids.indexOf(part) !== -1) {
|
| 1227 |
-
const holder = document.createElement("span");
|
| 1228 |
-
holder.innerHTML = resChipHtml({
|
| 1229 |
-
kind: "model",
|
| 1230 |
-
id: part,
|
| 1231 |
-
url: `https://huggingface.co/${part}`,
|
| 1232 |
-
});
|
| 1233 |
-
frag.appendChild(holder.firstChild);
|
| 1234 |
-
} else if (part) {
|
| 1235 |
-
frag.appendChild(document.createTextNode(part));
|
| 1236 |
-
}
|
| 1237 |
-
});
|
| 1238 |
-
node.parentNode.replaceChild(frag, node);
|
| 1239 |
-
});
|
| 1240 |
-
});
|
| 1241 |
-
}
|
| 1242 |
-
|
| 1243 |
-
let RAIL_TOKEN = 0;
|
| 1244 |
-
const RAIL_EXCLUDE_KINDS = new Set(["paper", "repo", "artifact", "dashboard"]);
|
| 1245 |
-
|
| 1246 |
-
function railDashboardItem(it) {
|
| 1247 |
-
return {
|
| 1248 |
-
kind: "dashboard",
|
| 1249 |
-
id: it.id,
|
| 1250 |
-
url: it.local ? it.resUrl : it.url || it.resUrl,
|
| 1251 |
-
local: it.local,
|
| 1252 |
-
railLabel: "Dashboard",
|
| 1253 |
-
};
|
| 1254 |
-
}
|
| 1255 |
-
|
| 1256 |
-
function promoteTrackioSpacesInRail(groups, dashResUrls, body, rail, token) {
|
| 1257 |
-
const spaceGroup = groups.get("space");
|
| 1258 |
-
if (!spaceGroup || !spaceGroup.size) return;
|
| 1259 |
-
spaceGroup.forEach((item, url) => {
|
| 1260 |
-
getJSON(`https://huggingface.co/api/spaces/${item.id}`)
|
| 1261 |
-
.then((d) => {
|
| 1262 |
-
if (rail.dataset.renderToken !== token) return;
|
| 1263 |
-
const tags = (d && d.tags) || [];
|
| 1264 |
-
if (!tags.some((t) => String(t).toLowerCase() === "trackio")) return;
|
| 1265 |
-
if (dashResUrls.has(url)) return;
|
| 1266 |
-
spaceGroup.delete(url);
|
| 1267 |
-
if (!spaceGroup.size) groups.delete("space");
|
| 1268 |
-
if (!groups.has("dashboard")) groups.set("dashboard", new Map());
|
| 1269 |
-
groups.get("dashboard").set(url, {
|
| 1270 |
-
kind: "dashboard",
|
| 1271 |
-
id: item.id,
|
| 1272 |
-
url: item.url,
|
| 1273 |
-
local: false,
|
| 1274 |
-
railLabel: "Dashboard",
|
| 1275 |
-
});
|
| 1276 |
-
dashResUrls.add(url);
|
| 1277 |
-
paintRail(groups, body, rail);
|
| 1278 |
-
})
|
| 1279 |
-
.catch(() => {});
|
| 1280 |
-
});
|
| 1281 |
-
}
|
| 1282 |
-
|
| 1283 |
-
function renderRail(md, body, rail) {
|
| 1284 |
-
const token = String(++RAIL_TOKEN);
|
| 1285 |
-
rail.dataset.renderToken = token;
|
| 1286 |
-
const scanText = md.replace(
|
| 1287 |
-
/(`{3,4}|~{3,4})(html|raw)[^\n]*\n[\s\S]*?\n\1/g,
|
| 1288 |
-
" "
|
| 1289 |
-
);
|
| 1290 |
-
const groups = new Map();
|
| 1291 |
-
const dashMap = new Map();
|
| 1292 |
-
const dashResUrls = new Set();
|
| 1293 |
-
cellDashboardItems(md).forEach((it) => {
|
| 1294 |
-
if (dashMap.has(it.resUrl)) return;
|
| 1295 |
-
dashMap.set(it.resUrl, railDashboardItem(it));
|
| 1296 |
-
dashResUrls.add(it.resUrl);
|
| 1297 |
-
});
|
| 1298 |
-
if (dashMap.size) groups.set("dashboard", dashMap);
|
| 1299 |
-
extractUrls(scanText).forEach((url) => {
|
| 1300 |
-
const item = classifyResource(url);
|
| 1301 |
-
if (!item) return;
|
| 1302 |
-
if (RAIL_EXCLUDE_KINDS.has(item.kind)) return;
|
| 1303 |
-
if (dashResUrls.has(url)) return;
|
| 1304 |
-
if (!groups.has(item.kind)) groups.set(item.kind, new Map());
|
| 1305 |
-
groups.get(item.kind).set(item.url, item);
|
| 1306 |
-
});
|
| 1307 |
-
const artMap = new Map();
|
| 1308 |
-
cellArtifactItems(md).forEach((it) => {
|
| 1309 |
-
if (artMap.has(it.resUrl)) return;
|
| 1310 |
-
const label = it.type
|
| 1311 |
-
? it.type.charAt(0).toUpperCase() + it.type.slice(1)
|
| 1312 |
-
: "Artifact";
|
| 1313 |
-
artMap.set(it.resUrl, {
|
| 1314 |
-
kind: "artifact",
|
| 1315 |
-
id: it.name,
|
| 1316 |
-
url: it.local ? it.resUrl : it.url || it.resUrl,
|
| 1317 |
-
local: it.local,
|
| 1318 |
-
railLabel: label,
|
| 1319 |
-
size: it.size,
|
| 1320 |
-
});
|
| 1321 |
-
});
|
| 1322 |
-
if (artMap.size) groups.set("artifact", artMap);
|
| 1323 |
-
paintRail(groups, body, rail);
|
| 1324 |
-
promoteTrackioSpacesInRail(groups, dashResUrls, body, rail, token);
|
| 1325 |
-
detectBareModelIds(scanText, groups)
|
| 1326 |
-
.then((result) => {
|
| 1327 |
-
if (rail.dataset.renderToken !== token) return;
|
| 1328 |
-
chipifyBareIds(result.confirmed, body);
|
| 1329 |
-
if (result.added) paintRail(groups, body, rail);
|
| 1330 |
-
})
|
| 1331 |
-
.catch(() => {});
|
| 1332 |
-
}
|
| 1333 |
-
|
| 1334 |
-
function paintRail(groups, body, rail) {
|
| 1335 |
-
rail.innerHTML = "";
|
| 1336 |
-
RESOURCE_SECTIONS.forEach(([kind, label, icon]) => {
|
| 1337 |
-
const group = groups.get(kind);
|
| 1338 |
-
if (!group || !group.size) return;
|
| 1339 |
-
group.forEach((item) => {
|
| 1340 |
-
const el = document.createElement(item.local ? "div" : "a");
|
| 1341 |
-
el.className = item.local ? "rail-item rail-local" : "rail-item";
|
| 1342 |
-
if (!item.local) {
|
| 1343 |
-
el.href = item.url;
|
| 1344 |
-
el.target = "_blank";
|
| 1345 |
-
el.rel = "noopener";
|
| 1346 |
-
}
|
| 1347 |
-
el.dataset.resUrl = item.url;
|
| 1348 |
-
let desc;
|
| 1349 |
-
if (kind === "artifact") {
|
| 1350 |
-
const state = item.local ? "publish to share" : "Open ↗";
|
| 1351 |
-
desc = item.size ? `${item.size} · ${state}` : state;
|
| 1352 |
-
} else if (kind === "dashboard") {
|
| 1353 |
-
desc = item.local ? "publish to share" : "Open ↗";
|
| 1354 |
-
} else {
|
| 1355 |
-
desc = item.local ? "publish to share" : RESOURCE_DESC[kind];
|
| 1356 |
-
}
|
| 1357 |
-
const kindLabel = item.railLabel || label.replace(/s$/, "");
|
| 1358 |
-
const iconHtml =
|
| 1359 |
-
kind === "artifact"
|
| 1360 |
-
? ARTIFACT_ICON_IMG
|
| 1361 |
-
: kind === "dashboard"
|
| 1362 |
-
? DASHBOARD_ICON_IMG
|
| 1363 |
-
: `<span>${icon}</span>`;
|
| 1364 |
-
el.innerHTML =
|
| 1365 |
-
`<div class="rail-kind">${iconHtml}${esc(kindLabel)}</div>` +
|
| 1366 |
-
`<div class="rail-title">${esc(item.id)}</div>` +
|
| 1367 |
-
`<div class="rail-meta">${esc(desc)}</div>`;
|
| 1368 |
-
rail.appendChild(el);
|
| 1369 |
-
fillRailMeta(item, el)
|
| 1370 |
-
.catch(() => {})
|
| 1371 |
-
.finally(() => scheduleRailPosition(body, rail));
|
| 1372 |
-
});
|
| 1373 |
-
});
|
| 1374 |
-
rail.hidden = !rail.childElementCount;
|
| 1375 |
-
scheduleRailPosition(body, rail);
|
| 1376 |
-
}
|
| 1377 |
-
|
| 1378 |
-
function resourceAnchor(body, url) {
|
| 1379 |
-
return body.querySelector(`[data-res-url="${CSS.escape(url)}"]`);
|
| 1380 |
-
}
|
| 1381 |
-
|
| 1382 |
-
function positionRail(body, rail) {
|
| 1383 |
-
if (rail.hidden || !rail.isConnected) return;
|
| 1384 |
-
const bodyRect = body.getBoundingClientRect();
|
| 1385 |
-
const items = Array.from(rail.querySelectorAll(".rail-item")).map((el, index) => {
|
| 1386 |
-
const anchor = resourceAnchor(body, el.dataset.resUrl);
|
| 1387 |
-
return {
|
| 1388 |
-
el,
|
| 1389 |
-
index,
|
| 1390 |
-
desired: anchor
|
| 1391 |
-
? Math.max(0, anchor.getBoundingClientRect().top - bodyRect.top)
|
| 1392 |
-
: 0,
|
| 1393 |
-
};
|
| 1394 |
-
});
|
| 1395 |
-
items.sort((a, b) => a.desired - b.desired || a.index - b.index);
|
| 1396 |
-
let cursor = 0;
|
| 1397 |
-
items.forEach(({ el, desired }) => {
|
| 1398 |
-
const top = Math.max(desired, cursor);
|
| 1399 |
-
el.style.top = `${top}px`;
|
| 1400 |
-
cursor = top + el.offsetHeight + 10;
|
| 1401 |
-
});
|
| 1402 |
-
rail.style.minHeight = `${Math.max(body.offsetHeight, cursor)}px`;
|
| 1403 |
-
}
|
| 1404 |
-
|
| 1405 |
-
function scheduleRailPosition(body, rail) {
|
| 1406 |
-
cancelAnimationFrame(Number(rail.dataset.positionFrame || 0));
|
| 1407 |
-
rail.dataset.positionFrame = String(
|
| 1408 |
-
requestAnimationFrame(() => positionRail(body, rail))
|
| 1409 |
-
);
|
| 1410 |
-
}
|
| 1411 |
-
|
| 1412 |
function dashboardSubdomainFromUrl(url) {
|
| 1413 |
return spaceIdFromUrl(url).toLowerCase().replace(/[^a-z0-9-]/g, "-");
|
| 1414 |
}
|
|
@@ -1523,11 +1274,15 @@
|
|
| 1523 |
function buildTree() {
|
| 1524 |
const tree = document.getElementById("tree");
|
| 1525 |
tree.innerHTML = "";
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1526 |
const nodes = [];
|
| 1527 |
(MANIFEST.root.children || []).forEach((c) => flattenTree(c, 0, nodes));
|
| 1528 |
nodes.forEach(({ node, depth }) => {
|
| 1529 |
const a = document.createElement("a");
|
| 1530 |
-
a.href = "#/" + node.slug;
|
| 1531 |
a.className = "depth-" + depth;
|
| 1532 |
a.dataset.slug = node.slug;
|
| 1533 |
const mark = document.createElement("span");
|
|
@@ -1539,6 +1294,47 @@
|
|
| 1539 |
});
|
| 1540 |
}
|
| 1541 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1542 |
function highlight(slug) {
|
| 1543 |
document
|
| 1544 |
.querySelectorAll("#tree a")
|
|
@@ -1552,6 +1348,9 @@
|
|
| 1552 |
Object.keys(PAGE_CACHE).forEach((key) => {
|
| 1553 |
delete PAGE_CACHE[key];
|
| 1554 |
});
|
|
|
|
|
|
|
|
|
|
| 1555 |
}
|
| 1556 |
|
| 1557 |
function isLocalPreview() {
|
|
@@ -1577,6 +1376,18 @@
|
|
| 1577 |
return PAGE_CACHE[node.file];
|
| 1578 |
}
|
| 1579 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1580 |
function allNodes() {
|
| 1581 |
const nodes = [];
|
| 1582 |
flattenTree(MANIFEST.root, 0, nodes);
|
|
@@ -1621,13 +1432,28 @@
|
|
| 1621 |
cells.forEach(({ meta, body }) => {
|
| 1622 |
const cell = renderCell(meta, body, list);
|
| 1623 |
cell.classList.add("pinned-copy");
|
|
|
|
|
|
|
| 1624 |
});
|
| 1625 |
deck.appendChild(list);
|
| 1626 |
const anchor =
|
| 1627 |
-
container.querySelector(".
|
| 1628 |
-
container.
|
| 1629 |
container.insertBefore(deck, anchor ? anchor.nextSibling : container.firstChild);
|
| 1630 |
-
container.closest(".
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1631 |
}
|
| 1632 |
|
| 1633 |
function removeIndexProse(body) {
|
|
@@ -1636,7 +1462,11 @@
|
|
| 1636 |
let current = h1.nextElementSibling;
|
| 1637 |
while (current && current.tagName !== "H2") {
|
| 1638 |
const next = current.nextElementSibling;
|
| 1639 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1640 |
current = next;
|
| 1641 |
}
|
| 1642 |
}
|
|
@@ -1655,15 +1485,13 @@
|
|
| 1655 |
}
|
| 1656 |
}
|
| 1657 |
|
| 1658 |
-
const RAIL_OBSERVERS = [];
|
| 1659 |
-
|
| 1660 |
async function renderLogbook(opts = {}) {
|
| 1661 |
const scrollY = window.scrollY;
|
| 1662 |
const page = document.getElementById("page");
|
| 1663 |
-
RAIL_OBSERVERS.splice(0).forEach((observer) => observer.disconnect());
|
| 1664 |
page.innerHTML = "";
|
| 1665 |
const nodes = allNodes();
|
| 1666 |
const markdown = await Promise.all(nodes.map(fetchPage));
|
|
|
|
| 1667 |
const pinnedCells = collectPinnedCells(markdown, nodes);
|
| 1668 |
let bookIntroBody = null;
|
| 1669 |
nodes.forEach((node, index) => {
|
|
@@ -1676,45 +1504,42 @@
|
|
| 1676 |
layout.className = "page-layout";
|
| 1677 |
const body = document.createElement("div");
|
| 1678 |
body.className = "page-body";
|
| 1679 |
-
const rail = document.createElement("aside");
|
| 1680 |
-
rail.className = "context-rail";
|
| 1681 |
-
rail.setAttribute("aria-label", `Resources for ${node.title}`);
|
| 1682 |
|
| 1683 |
renderMarkdown(markdown[index], body);
|
| 1684 |
if (node.slug === MANIFEST.root.slug) {
|
| 1685 |
section.classList.add("book-intro");
|
| 1686 |
removeIndexProse(body);
|
| 1687 |
removePageDirectory(body);
|
| 1688 |
-
const hint = buildAgentHint();
|
| 1689 |
const h1 = body.querySelector("h1");
|
| 1690 |
-
if (h1 && h1.parentNode === body)
|
| 1691 |
-
body.insertBefore(hint, h1.nextSibling);
|
| 1692 |
-
} else {
|
| 1693 |
-
body.prepend(hint);
|
| 1694 |
-
}
|
| 1695 |
-
hint.after(buildLogbookStats(markdown));
|
| 1696 |
bookIntroBody = body;
|
| 1697 |
}
|
| 1698 |
layout.appendChild(body);
|
| 1699 |
-
layout.appendChild(rail);
|
| 1700 |
section.appendChild(layout);
|
| 1701 |
page.appendChild(section);
|
| 1702 |
-
renderRail(markdown[index], body, rail);
|
| 1703 |
-
if (window.ResizeObserver) {
|
| 1704 |
-
const observer = new ResizeObserver(() => scheduleRailPosition(body, rail));
|
| 1705 |
-
observer.observe(body);
|
| 1706 |
-
observer.observe(rail);
|
| 1707 |
-
RAIL_OBSERVERS.push(observer);
|
| 1708 |
-
}
|
| 1709 |
});
|
| 1710 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1711 |
if (bookIntroBody) {
|
| 1712 |
const section = bookIntroBody.closest(".book-intro");
|
| 1713 |
const hasExtra = Array.from(bookIntroBody.children).some(
|
| 1714 |
(el) =>
|
| 1715 |
el.tagName !== "H1" &&
|
| 1716 |
!el.classList.contains("agent-hint") &&
|
| 1717 |
-
!el.classList.contains("
|
| 1718 |
!el.classList.contains("pinned-notes")
|
| 1719 |
);
|
| 1720 |
if (section && !section.classList.contains("has-pinned-notes") && !hasExtra) {
|
|
@@ -1731,29 +1556,6 @@
|
|
| 1731 |
});
|
| 1732 |
}
|
| 1733 |
|
| 1734 |
-
function setupResourceHover() {
|
| 1735 |
-
document.addEventListener("mouseover", (e) => {
|
| 1736 |
-
const el = e.target.closest && e.target.closest("[data-res-url]");
|
| 1737 |
-
if (!el || el.classList.contains("rail-item")) return;
|
| 1738 |
-
const url = el.getAttribute("data-res-url");
|
| 1739 |
-
const section = el.closest(".page-section");
|
| 1740 |
-
const scope = section || document;
|
| 1741 |
-
scope.querySelectorAll(".context-rail [data-res-url]").forEach((n) => {
|
| 1742 |
-
n.classList.toggle("res-hl", n.getAttribute("data-res-url") === url);
|
| 1743 |
-
});
|
| 1744 |
-
});
|
| 1745 |
-
document.addEventListener("mouseout", (e) => {
|
| 1746 |
-
const el = e.target.closest && e.target.closest("[data-res-url]");
|
| 1747 |
-
if (!el || el.classList.contains("rail-item")) return;
|
| 1748 |
-
document.querySelectorAll(".context-rail .res-hl").forEach((n) => {
|
| 1749 |
-
n.classList.remove("res-hl");
|
| 1750 |
-
});
|
| 1751 |
-
});
|
| 1752 |
-
}
|
| 1753 |
-
|
| 1754 |
-
let STATS_TOKEN = 0;
|
| 1755 |
-
let STATS_LISTENERS = false;
|
| 1756 |
-
|
| 1757 |
function fmtBytes(n) {
|
| 1758 |
if (n == null || isNaN(n)) return null;
|
| 1759 |
if (n < 1000) return `${n} B`;
|
|
@@ -1771,31 +1573,6 @@
|
|
| 1771 |
return url.split("/spaces/")[1].split(/[?#]/)[0].replace(/\/$/, "");
|
| 1772 |
}
|
| 1773 |
|
| 1774 |
-
const LB_CELL_RE = /(^|\n)---\n<!-- trackio-cell\n([\s\S]*?)\n-->\n([\s\S]*?)(?=\n---\n<!-- trackio-cell\n|\s*$)/g;
|
| 1775 |
-
|
| 1776 |
-
function cellDashboardItems(md) {
|
| 1777 |
-
const re = new RegExp(LB_CELL_RE.source, "g");
|
| 1778 |
-
const items = [];
|
| 1779 |
-
let m;
|
| 1780 |
-
while ((m = re.exec(md))) {
|
| 1781 |
-
const meta = parseCellMeta(m[2]);
|
| 1782 |
-
if (meta.type !== "dashboard") continue;
|
| 1783 |
-
const body = m[3];
|
| 1784 |
-
const project = meta.dashboard_project || "";
|
| 1785 |
-
const sp = body.match(/https:\/\/huggingface\.co\/spaces\/[^\s<>)"'`]+/);
|
| 1786 |
-
const local = !sp;
|
| 1787 |
-
const url = sp ? sp[0] : "";
|
| 1788 |
-
const resUrl = local ? `trackio-local-dashboard://${project}` : url;
|
| 1789 |
-
items.push({
|
| 1790 |
-
id: local ? project : spaceIdFromUrl(url),
|
| 1791 |
-
local,
|
| 1792 |
-
url,
|
| 1793 |
-
resUrl,
|
| 1794 |
-
});
|
| 1795 |
-
}
|
| 1796 |
-
return items;
|
| 1797 |
-
}
|
| 1798 |
-
|
| 1799 |
function artifactInfoFromCell(meta, body) {
|
| 1800 |
const name = meta.artifact || meta.path || "";
|
| 1801 |
let size = null;
|
|
@@ -1820,280 +1597,1036 @@
|
|
| 1820 |
};
|
| 1821 |
}
|
| 1822 |
|
| 1823 |
-
|
| 1824 |
-
|
| 1825 |
-
|
| 1826 |
-
|
| 1827 |
-
|
| 1828 |
-
|
| 1829 |
-
|
| 1830 |
-
|
| 1831 |
-
|
| 1832 |
-
|
| 1833 |
-
|
| 1834 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1835 |
}
|
| 1836 |
-
|
| 1837 |
-
|
| 1838 |
-
|
| 1839 |
-
|
| 1840 |
-
|
| 1841 |
-
|
| 1842 |
-
|
| 1843 |
-
|
| 1844 |
-
|
| 1845 |
-
|
| 1846 |
-
|
| 1847 |
-
if (meta.type !== "dashboard") continue;
|
| 1848 |
-
const project = meta.dashboard_project || "";
|
| 1849 |
-
const space = body.match(/https:\/\/huggingface\.co\/spaces\/[^\s<>)"'`]+/);
|
| 1850 |
-
const local = !space;
|
| 1851 |
-
const url = space ? space[0] : "";
|
| 1852 |
-
const key = local ? `local:${project}` : `space:${spaceIdFromUrl(url)}`;
|
| 1853 |
-
const resUrl = local ? `trackio-local-dashboard://${project}` : url;
|
| 1854 |
-
if (!dashboards.has(key))
|
| 1855 |
-
dashboards.set(key, { project, local, url, resUrl });
|
| 1856 |
}
|
| 1857 |
-
}
|
| 1858 |
-
|
| 1859 |
-
|
| 1860 |
-
|
| 1861 |
-
|
| 1862 |
-
|
| 1863 |
-
|
| 1864 |
-
|
| 1865 |
-
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1866 |
return {
|
| 1867 |
-
|
| 1868 |
-
|
| 1869 |
-
),
|
| 1870 |
-
artifacts: Array.from(artifacts.values()).sort((a, b) =>
|
| 1871 |
-
a.name.localeCompare(b.name)
|
| 1872 |
-
),
|
| 1873 |
};
|
| 1874 |
}
|
| 1875 |
|
| 1876 |
-
function
|
| 1877 |
-
document
|
| 1878 |
-
.
|
| 1879 |
-
.
|
| 1880 |
-
|
| 1881 |
-
|
| 1882 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1883 |
}
|
| 1884 |
|
| 1885 |
-
function
|
| 1886 |
-
|
| 1887 |
-
|
| 1888 |
-
|
| 1889 |
-
|
| 1890 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1891 |
});
|
| 1892 |
}
|
| 1893 |
|
| 1894 |
-
function
|
| 1895 |
-
|
| 1896 |
-
|
| 1897 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1898 |
}
|
| 1899 |
|
| 1900 |
-
function
|
| 1901 |
-
|
| 1902 |
-
|
| 1903 |
-
|
| 1904 |
-
|
| 1905 |
-
);
|
| 1906 |
-
|
| 1907 |
-
|
| 1908 |
-
|
| 1909 |
-
|
| 1910 |
-
|
| 1911 |
-
|
| 1912 |
-
|
| 1913 |
-
|
| 1914 |
-
|
| 1915 |
-
|
| 1916 |
-
|
| 1917 |
-
|
| 1918 |
-
|
| 1919 |
-
|
| 1920 |
-
|
| 1921 |
-
|
| 1922 |
-
|
| 1923 |
-
|
| 1924 |
-
|
| 1925 |
-
|
| 1926 |
-
|
| 1927 |
-
`
|
| 1928 |
-
|
| 1929 |
-
|
| 1930 |
-
|
| 1931 |
-
|
| 1932 |
-
|
| 1933 |
-
|
| 1934 |
-
|
| 1935 |
-
|
| 1936 |
-
|
| 1937 |
-
|
| 1938 |
-
|
| 1939 |
-
const
|
| 1940 |
-
|
| 1941 |
-
|
| 1942 |
-
|
| 1943 |
-
|
| 1944 |
-
|
| 1945 |
-
|
| 1946 |
-
|
| 1947 |
-
|
| 1948 |
-
|
| 1949 |
-
|
| 1950 |
-
|
| 1951 |
-
|
| 1952 |
-
|
| 1953 |
-
|
| 1954 |
-
|
| 1955 |
-
|
| 1956 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1957 |
return;
|
| 1958 |
}
|
| 1959 |
-
|
| 1960 |
-
|
| 1961 |
-
if (
|
|
|
|
|
|
|
| 1962 |
});
|
| 1963 |
-
|
| 1964 |
-
|
| 1965 |
-
|
| 1966 |
-
|
| 1967 |
-
|
| 1968 |
-
|
| 1969 |
-
|
| 1970 |
-
|
| 1971 |
-
|
| 1972 |
-
|
| 1973 |
-
if (!isOpen) {
|
| 1974 |
-
pop.hidden = false;
|
| 1975 |
-
tile.classList.add("open");
|
| 1976 |
}
|
| 1977 |
-
}
|
| 1978 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1979 |
}
|
| 1980 |
|
| 1981 |
-
function
|
| 1982 |
-
|
| 1983 |
-
|
| 1984 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1985 |
|
| 1986 |
-
|
| 1987 |
-
|
| 1988 |
-
|
| 1989 |
-
|
| 1990 |
-
|
| 1991 |
-
|
| 1992 |
-
|
| 1993 |
-
|
| 1994 |
-
|
| 1995 |
-
);
|
| 1996 |
-
const
|
| 1997 |
-
|
| 1998 |
-
|
| 1999 |
-
|
| 2000 |
-
"
|
| 2001 |
-
|
| 2002 |
-
|
| 2003 |
-
|
| 2004 |
-
|
| 2005 |
-
|
| 2006 |
-
|
| 2007 |
-
|
| 2008 |
-
|
| 2009 |
-
|
| 2010 |
-
|
| 2011 |
-
|
| 2012 |
-
|
| 2013 |
-
|
| 2014 |
-
|
| 2015 |
-
|
| 2016 |
-
|
| 2017 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2018 |
);
|
| 2019 |
-
|
| 2020 |
-
|
| 2021 |
-
|
| 2022 |
-
|
| 2023 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2024 |
}
|
| 2025 |
-
|
| 2026 |
-
|
| 2027 |
-
|
| 2028 |
-
|
| 2029 |
-
|
| 2030 |
-
|
| 2031 |
-
|
| 2032 |
-
|
| 2033 |
-
|
| 2034 |
-
|
| 2035 |
-
|
| 2036 |
-
|
| 2037 |
-
|
| 2038 |
-
|
| 2039 |
-
|
| 2040 |
-
|
| 2041 |
-
|
| 2042 |
-
|
| 2043 |
-
|
| 2044 |
-
|
| 2045 |
-
|
| 2046 |
-
}
|
| 2047 |
})
|
| 2048 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2049 |
});
|
| 2050 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2051 |
}
|
| 2052 |
|
| 2053 |
-
function
|
| 2054 |
-
const
|
| 2055 |
-
|
| 2056 |
-
|
| 2057 |
-
|
| 2058 |
-
|
| 2059 |
-
source = ` ${MANIFEST.space_id}`;
|
| 2060 |
-
} else if (/^https?:$/.test(location.protocol)) {
|
| 2061 |
-
source = ` ${location.origin}/`;
|
| 2062 |
-
}
|
| 2063 |
-
const command = `trackio logbook read${source}`;
|
| 2064 |
-
const tokens = MANIFEST.agent_view_tokens;
|
| 2065 |
-
const div = document.createElement("div");
|
| 2066 |
-
div.className = "agent-hint";
|
| 2067 |
const label = document.createElement("span");
|
| 2068 |
-
label.
|
| 2069 |
-
label.
|
| 2070 |
-
|
| 2071 |
-
|
| 2072 |
-
|
| 2073 |
-
|
| 2074 |
-
|
| 2075 |
-
|
| 2076 |
-
|
| 2077 |
-
|
| 2078 |
-
|
| 2079 |
-
|
| 2080 |
-
|
| 2081 |
-
|
| 2082 |
-
|
| 2083 |
-
|
| 2084 |
-
|
| 2085 |
-
|
| 2086 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2087 |
}
|
| 2088 |
|
| 2089 |
function currentSlug() {
|
| 2090 |
-
const
|
| 2091 |
-
return
|
| 2092 |
}
|
| 2093 |
|
| 2094 |
function scrollToHash(opts = {}) {
|
|
|
|
| 2095 |
const slug = currentSlug();
|
| 2096 |
-
if (!location.hash) {
|
| 2097 |
window.scrollTo({ top: 0, behavior: opts.behavior || "auto" });
|
| 2098 |
highlight(slug);
|
| 2099 |
return;
|
|
@@ -2106,7 +2639,7 @@
|
|
| 2106 |
function navigateToLogbookSlug(target) {
|
| 2107 |
const slug = String(target || "").replace(/^#?\//, "").trim();
|
| 2108 |
if (!slug || !findNode(MANIFEST.root, slug)) return;
|
| 2109 |
-
const hash = "#/" + slug;
|
| 2110 |
if (location.hash === hash) {
|
| 2111 |
scrollToHash({ behavior: "smooth" });
|
| 2112 |
} else {
|
|
@@ -2130,9 +2663,12 @@
|
|
| 2130 |
|
| 2131 |
let SCROLL_FRAME = 0;
|
| 2132 |
function updateActiveSection() {
|
|
|
|
| 2133 |
cancelAnimationFrame(SCROLL_FRAME);
|
| 2134 |
SCROLL_FRAME = requestAnimationFrame(() => {
|
| 2135 |
-
const
|
|
|
|
|
|
|
| 2136 |
if (!sections.length) return;
|
| 2137 |
const marker = Math.min(window.innerHeight * 0.28, 180);
|
| 2138 |
let active = sections[0];
|
|
@@ -2145,7 +2681,11 @@
|
|
| 2145 |
) {
|
| 2146 |
active = sections[sections.length - 1];
|
| 2147 |
}
|
| 2148 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2149 |
});
|
| 2150 |
}
|
| 2151 |
|
|
@@ -2161,7 +2701,7 @@
|
|
| 2161 |
document.getElementById("book-title").textContent = MANIFEST.title;
|
| 2162 |
document.getElementById("book-head").setAttribute("aria-label", MANIFEST.title);
|
| 2163 |
buildTree();
|
| 2164 |
-
|
| 2165 |
} catch (e) {}
|
| 2166 |
}, LIVE_RELOAD_MS);
|
| 2167 |
}
|
|
@@ -2257,17 +2797,16 @@
|
|
| 2257 |
document.getElementById("book-title").textContent = MANIFEST.title;
|
| 2258 |
document.getElementById("book-head").setAttribute("aria-label", MANIFEST.title);
|
| 2259 |
document.getElementById("book-head").addEventListener("click", () => {
|
| 2260 |
-
const target = "#/" + MANIFEST.root.slug;
|
| 2261 |
if (location.hash === target) scrollToHash();
|
| 2262 |
else location.hash = target;
|
| 2263 |
});
|
| 2264 |
buildTree();
|
| 2265 |
setupConnect();
|
| 2266 |
-
setupResourceHover();
|
| 2267 |
setupFigureNavigation();
|
| 2268 |
-
window.addEventListener("hashchange",
|
| 2269 |
window.addEventListener("scroll", updateActiveSection, { passive: true });
|
| 2270 |
-
await
|
| 2271 |
startLiveReload();
|
| 2272 |
}
|
| 2273 |
|
|
|
|
| 4 |
let MANIFEST = null;
|
| 5 |
const PAGE_CACHE = {};
|
| 6 |
const UNFURL_CACHE = {};
|
| 7 |
+
const DATA_CACHE = {};
|
| 8 |
const LIVE_RELOAD_MS = 1500;
|
| 9 |
const FIGURE_FRAME_WINDOWS = new Set();
|
| 10 |
let FIGURE_NAVIGATION_READY = false;
|
| 11 |
+
let CURRENT_VIEW = null;
|
| 12 |
+
let RENDER_SEQUENCE = 0;
|
| 13 |
|
| 14 |
function esc(s) {
|
| 15 |
return String(s)
|
|
|
|
| 289 |
/(trackio-artifact:\/\/\S+|trackio-local-path:\/\/\S+|https:\/\/huggingface\.co\/buckets\/[^\s<)]+#\S+)/
|
| 290 |
);
|
| 291 |
if (chip && uri) chip.dataset.resUrl = uri[1];
|
| 292 |
+
if (chip && meta.path) {
|
| 293 |
+
const ico = chip.querySelector(".art-ico");
|
| 294 |
+
if (ico) ico.outerHTML = FILE_ICON;
|
| 295 |
+
}
|
| 296 |
} else if (meta.type === "dashboard") {
|
| 297 |
const sp = body.match(/https:\/\/huggingface\.co\/spaces\/[^\s<>)"'`]+/);
|
| 298 |
cell.dataset.resUrl = sp
|
|
|
|
| 502 |
if (!message || message.type !== "trackio-logbook:navigate") return;
|
| 503 |
const target = String(message.target || "").replace(/^#?\//, "");
|
| 504 |
if (!target || !MANIFEST || !findNode(MANIFEST.root, target)) return;
|
| 505 |
+
const hash = "#/view/code/" + target;
|
| 506 |
if (location.hash === hash) scrollToHash();
|
| 507 |
else location.hash = hash;
|
| 508 |
});
|
|
|
|
| 514 |
'<path d="M8 3H3v5M16 3h5v5M21 16v5h-5M3 16v5h5"/>' +
|
| 515 |
'<path d="M3 8 8 3M16 3l5 5M21 16l-5 5M8 21l-5-5"/></svg>';
|
| 516 |
|
| 517 |
+
const PIN_ICON =
|
| 518 |
+
'<svg class="pin-ico" viewBox="0 0 24 24" aria-hidden="true">' +
|
| 519 |
+
'<path d="M16 9V4h1c.55 0 1-.45 1-1s-.45-1-1-1H7c-.55 0-1 .45-1 1s.45 1 1 1h1v5c0 ' +
|
| 520 |
+
'1.66-1.34 3-3 3v2h5.97v7l1 1 1-1v-7H19v-2c-1.66 0-3-1.34-3-3z"/></svg>';
|
| 521 |
+
|
| 522 |
+
const FILE_ICON =
|
| 523 |
+
'<svg class="art-file-ico" viewBox="0 0 24 24" aria-hidden="true">' +
|
| 524 |
+
'<path d="M6 3.5h8l4 4V20H6zM14 3.5V8h4"/></svg>';
|
| 525 |
+
|
| 526 |
// Figures are rendered in same-origin iframes, so fullscreen the fitted
|
| 527 |
// wrapper rather than the iframe document. This uses the browser's native
|
| 528 |
// fullscreen UI and preserves the figure's existing responsive sizing.
|
|
|
|
| 651 |
? `<span class="out-artifact-state open">Open ↗</span>`
|
| 652 |
: `<span class="out-artifact-state">publish to share</span>`;
|
| 653 |
const meta = parts.length ? `${parts.join(" · ")} · ${state}` : state;
|
| 654 |
+
const icon = info.isPathRef ? FILE_ICON : ARTIFACT_ICON_IMG;
|
| 655 |
el.innerHTML =
|
| 656 |
+
`<span class="out-artifact-ico">${icon}</span>` +
|
| 657 |
`<span class="out-artifact-name">${esc(info.name)}</span>` +
|
| 658 |
`<span class="out-artifact-meta">${meta}</span>`;
|
| 659 |
return el;
|
| 660 |
}
|
| 661 |
|
| 662 |
+
function isShellCommand(part) {
|
| 663 |
+
return (
|
| 664 |
+
part.kind === "code" &&
|
| 665 |
+
part.lang === "bash" &&
|
| 666 |
+
!part.title &&
|
| 667 |
+
/^\s*\$\s/.test(part.text)
|
| 668 |
+
);
|
| 669 |
+
}
|
| 670 |
+
|
| 671 |
+
function renderCommandLine(text) {
|
| 672 |
+
const command = text.trim().replace(/^\$\s*/, "");
|
| 673 |
+
const el = document.createElement("div");
|
| 674 |
+
el.className = "jp-cmd";
|
| 675 |
+
const prompt = document.createElement("span");
|
| 676 |
+
prompt.className = "jp-cmd-prompt";
|
| 677 |
+
prompt.textContent = "$";
|
| 678 |
+
const code = document.createElement("code");
|
| 679 |
+
code.textContent = command;
|
| 680 |
+
el.appendChild(prompt);
|
| 681 |
+
el.appendChild(code);
|
| 682 |
+
el.appendChild(copySnippetBtn(command));
|
| 683 |
+
return el;
|
| 684 |
+
}
|
| 685 |
+
|
| 686 |
function renderCodeCell(body, container, artifacts) {
|
| 687 |
const parts = parseFences(body);
|
| 688 |
const block = document.createElement("div");
|
|
|
|
| 735 |
embedTexts.push(part.text);
|
| 736 |
return;
|
| 737 |
}
|
| 738 |
+
if (isShellCommand(part)) {
|
| 739 |
+
inputBody.appendChild(renderCommandLine(part.text));
|
| 740 |
+
} else {
|
| 741 |
+
inputBody.appendChild(
|
| 742 |
+
renderCode(part.text, part.lang, part.title, Boolean(part.title))
|
| 743 |
+
);
|
| 744 |
+
}
|
| 745 |
});
|
| 746 |
if (artifacts && artifacts.length) {
|
| 747 |
ensureOut();
|
|
|
|
| 960 |
return btn;
|
| 961 |
}
|
| 962 |
|
| 963 |
+
function renderCode(code, lang, title, open) {
|
| 964 |
const pre = document.createElement("pre");
|
| 965 |
pre.className = "hl";
|
| 966 |
const c = document.createElement("code");
|
| 967 |
c.innerHTML = highlightCode(code, lang);
|
| 968 |
pre.appendChild(c);
|
| 969 |
+
if (!title || open) {
|
| 970 |
const wrap = document.createElement("div");
|
| 971 |
wrap.className = "snippet";
|
| 972 |
wrap.appendChild(pre);
|
|
|
|
| 1030 |
});
|
| 1031 |
}
|
| 1032 |
|
| 1033 |
+
/* -------------------- resource classification -------------------- */
|
| 1034 |
|
| 1035 |
function fmt(n) {
|
| 1036 |
if (n == null) return null;
|
|
|
|
| 1058 |
const ARTIFACT_ICON_IMG = `<img class="art-ico" src="./bucket-icon.svg" alt="" />`;
|
| 1059 |
const DASHBOARD_ICON_IMG = `<img class="art-ico" src="./trackio-logo-light.png" alt="" />`;
|
| 1060 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1061 |
const HF_NON_MODEL_PREFIX =
|
| 1062 |
/^(datasets|spaces|jobs|buckets|papers|blog|docs|api|posts|collections|organizations|settings|new|join|login|pricing|tasks|learn|chat|models)(\/|$)/;
|
| 1063 |
|
|
|
|
| 1065 |
return url.split(marker)[1].split(/[?#]/)[0].replace(/\/$/, "");
|
| 1066 |
}
|
| 1067 |
|
| 1068 |
+
function validHfSegment(value) {
|
| 1069 |
+
return Boolean(
|
| 1070 |
+
value &&
|
| 1071 |
+
value.length <= 96 &&
|
| 1072 |
+
/^[A-Za-z0-9_.-]+$/.test(value) &&
|
| 1073 |
+
!/^[.-]|[.-]$|--|\.\./.test(value)
|
| 1074 |
+
);
|
| 1075 |
+
}
|
| 1076 |
+
|
| 1077 |
+
function validHfRepoId(parts) {
|
| 1078 |
+
return (
|
| 1079 |
+
parts.length === 2 &&
|
| 1080 |
+
parts.join("/").length <= 96 &&
|
| 1081 |
+
parts.every(validHfSegment)
|
| 1082 |
+
);
|
| 1083 |
+
}
|
| 1084 |
+
|
| 1085 |
function classifyResource(url) {
|
| 1086 |
if (IMG_URL.test(url)) {
|
| 1087 |
return null;
|
|
|
|
| 1111 |
local: true,
|
| 1112 |
};
|
| 1113 |
}
|
| 1114 |
+
if ((m = url.match(/huggingface\.co\/buckets\/([^/#\s]+\/[^/#\s]+)#(.+)/))) {
|
| 1115 |
+
if (!validHfRepoId(m[1].split("/"))) return null;
|
| 1116 |
+
return { kind: "artifact", id: decodeURIComponent(m[2]), url };
|
| 1117 |
}
|
| 1118 |
+
if (/huggingface\.co\/datasets\//.test(url)) {
|
| 1119 |
+
const parts = hfId(url, "/datasets/").split("/").slice(0, 2);
|
| 1120 |
+
if (!validHfRepoId(parts)) return null;
|
| 1121 |
+
return { kind: "dataset", id: parts.join("/"), url };
|
| 1122 |
}
|
| 1123 |
+
if (/huggingface\.co\/spaces\//.test(url)) {
|
| 1124 |
+
const parts = hfId(url, "/spaces/").split("/").slice(0, 2);
|
| 1125 |
+
if (!validHfRepoId(parts)) return null;
|
| 1126 |
+
return { kind: "space", id: parts.join("/"), url };
|
| 1127 |
}
|
| 1128 |
if (/huggingface\.co\/jobs\//.test(url)) {
|
| 1129 |
+
const parts = hfId(url, "/jobs/").split("/").slice(0, 2);
|
| 1130 |
+
if (!validHfRepoId(parts)) return null;
|
| 1131 |
+
const jid = parts[1];
|
| 1132 |
return {
|
| 1133 |
kind: "job",
|
| 1134 |
+
id: parts[0] + ` · ${jid.slice(0, 12)}${jid.length > 12 ? "…" : ""}`,
|
| 1135 |
url,
|
| 1136 |
};
|
| 1137 |
}
|
| 1138 |
if (/huggingface\.co\/buckets\//.test(url)) {
|
| 1139 |
+
const parts = hfId(url, "/buckets/").split("/").slice(0, 2);
|
| 1140 |
+
if (!validHfRepoId(parts)) return null;
|
| 1141 |
+
return { kind: "bucket", id: parts.join("/"), url };
|
| 1142 |
}
|
| 1143 |
if (/huggingface\.co\/papers\//.test(url)) {
|
| 1144 |
+
const id = hfId(url, "/papers/").split("/")[0];
|
| 1145 |
+
if (!validHfSegment(id)) return null;
|
| 1146 |
+
return { kind: "paper", id: `Paper ${id}`, url };
|
| 1147 |
}
|
| 1148 |
if ((m = url.match(/arxiv\.org\/(?:abs|pdf)\/([^?#\s]+)/))) {
|
| 1149 |
return { kind: "paper", id: `arXiv:${m[1].replace(/\.pdf$/, "")}`, url };
|
|
|
|
| 1153 |
}
|
| 1154 |
if ((m = url.match(/huggingface\.co\/([^?#]+)/))) {
|
| 1155 |
const rest = m[1].replace(/\/$/, "");
|
| 1156 |
+
if (validHfRepoId(rest.split("/")) && !HF_NON_MODEL_PREFIX.test(rest)) {
|
| 1157 |
return { kind: "model", id: rest, url };
|
| 1158 |
}
|
| 1159 |
}
|
| 1160 |
return null;
|
| 1161 |
}
|
| 1162 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1163 |
function dashboardSubdomainFromUrl(url) {
|
| 1164 |
return spaceIdFromUrl(url).toLowerCase().replace(/[^a-z0-9-]/g, "-");
|
| 1165 |
}
|
|
|
|
| 1274 |
function buildTree() {
|
| 1275 |
const tree = document.getElementById("tree");
|
| 1276 |
tree.innerHTML = "";
|
| 1277 |
+
const label = document.createElement("div");
|
| 1278 |
+
label.className = "tree-label";
|
| 1279 |
+
label.textContent = "Pages";
|
| 1280 |
+
tree.appendChild(label);
|
| 1281 |
const nodes = [];
|
| 1282 |
(MANIFEST.root.children || []).forEach((c) => flattenTree(c, 0, nodes));
|
| 1283 |
nodes.forEach(({ node, depth }) => {
|
| 1284 |
const a = document.createElement("a");
|
| 1285 |
+
a.href = "#/view/code/" + node.slug;
|
| 1286 |
a.className = "depth-" + depth;
|
| 1287 |
a.dataset.slug = node.slug;
|
| 1288 |
const mark = document.createElement("span");
|
|
|
|
| 1294 |
});
|
| 1295 |
}
|
| 1296 |
|
| 1297 |
+
function highlightTraceSession(sessionId) {
|
| 1298 |
+
document.querySelectorAll("#tree a").forEach((link) => {
|
| 1299 |
+
link.classList.toggle("active", link.dataset.sessionId === sessionId);
|
| 1300 |
+
});
|
| 1301 |
+
}
|
| 1302 |
+
|
| 1303 |
+
function buildTraceTree(activeSessionId) {
|
| 1304 |
+
const tree = document.getElementById("tree");
|
| 1305 |
+
tree.innerHTML = "";
|
| 1306 |
+
const sessions = MANIFEST.traces || [];
|
| 1307 |
+
if (!sessions.length) return;
|
| 1308 |
+
const label = document.createElement("div");
|
| 1309 |
+
label.className = "tree-label";
|
| 1310 |
+
label.textContent = "Sessions";
|
| 1311 |
+
tree.appendChild(label);
|
| 1312 |
+
sessions.forEach((session) => {
|
| 1313 |
+
const link = document.createElement("a");
|
| 1314 |
+
link.href = "#" + traceSessionAnchor(session.id);
|
| 1315 |
+
link.dataset.sessionId = session.id;
|
| 1316 |
+
link.textContent = session.title || session.id;
|
| 1317 |
+
link.title = session.title || session.id;
|
| 1318 |
+
tree.appendChild(link);
|
| 1319 |
+
});
|
| 1320 |
+
highlightTraceSession(activeSessionId || sessions[0].id);
|
| 1321 |
+
}
|
| 1322 |
+
|
| 1323 |
+
function renderSidebar(route) {
|
| 1324 |
+
if (route.view === "trace") {
|
| 1325 |
+
highlight(null);
|
| 1326 |
+
buildTraceTree(route.sessionId);
|
| 1327 |
+
return;
|
| 1328 |
+
}
|
| 1329 |
+
if (route.view === "workspace") {
|
| 1330 |
+
document.getElementById("tree").innerHTML = "";
|
| 1331 |
+
highlight(null);
|
| 1332 |
+
return;
|
| 1333 |
+
}
|
| 1334 |
+
buildTree();
|
| 1335 |
+
highlight(route.slug);
|
| 1336 |
+
}
|
| 1337 |
+
|
| 1338 |
function highlight(slug) {
|
| 1339 |
document
|
| 1340 |
.querySelectorAll("#tree a")
|
|
|
|
| 1348 |
Object.keys(PAGE_CACHE).forEach((key) => {
|
| 1349 |
delete PAGE_CACHE[key];
|
| 1350 |
});
|
| 1351 |
+
Object.keys(DATA_CACHE).forEach((key) => {
|
| 1352 |
+
delete DATA_CACHE[key];
|
| 1353 |
+
});
|
| 1354 |
}
|
| 1355 |
|
| 1356 |
function isLocalPreview() {
|
|
|
|
| 1376 |
return PAGE_CACHE[node.file];
|
| 1377 |
}
|
| 1378 |
|
| 1379 |
+
async function fetchData(file, cacheResult = true) {
|
| 1380 |
+
if (cacheResult && DATA_CACHE[file]) return DATA_CACHE[file];
|
| 1381 |
+
const suffix = isLocalPreview()
|
| 1382 |
+
? `?rev=${encodeURIComponent(MANIFEST.revision || "")}`
|
| 1383 |
+
: "";
|
| 1384 |
+
const response = await fetch("./" + file + suffix, { cache: "no-store" });
|
| 1385 |
+
if (!response.ok) throw new Error(`Could not load ${file}`);
|
| 1386 |
+
const data = await response.json();
|
| 1387 |
+
if (cacheResult) DATA_CACHE[file] = data;
|
| 1388 |
+
return data;
|
| 1389 |
+
}
|
| 1390 |
+
|
| 1391 |
function allNodes() {
|
| 1392 |
const nodes = [];
|
| 1393 |
flattenTree(MANIFEST.root, 0, nodes);
|
|
|
|
| 1432 |
cells.forEach(({ meta, body }) => {
|
| 1433 |
const cell = renderCell(meta, body, list);
|
| 1434 |
cell.classList.add("pinned-copy");
|
| 1435 |
+
const title = cell.querySelector(".cell-title");
|
| 1436 |
+
if (title) title.insertAdjacentHTML("afterbegin", PIN_ICON);
|
| 1437 |
});
|
| 1438 |
deck.appendChild(list);
|
| 1439 |
const anchor =
|
| 1440 |
+
container.querySelector(".agent-hint") ||
|
| 1441 |
+
Array.from(container.children).find((el) => el.tagName === "H1");
|
| 1442 |
container.insertBefore(deck, anchor ? anchor.nextSibling : container.firstChild);
|
| 1443 |
+
const owner = container.closest(".page-section");
|
| 1444 |
+
if (owner) owner.classList.add("has-pinned-notes");
|
| 1445 |
+
}
|
| 1446 |
+
|
| 1447 |
+
function isIndexPaperLink(el) {
|
| 1448 |
+
if (!el || el.tagName !== "P") return false;
|
| 1449 |
+
return Array.from(el.querySelectorAll("a[href]")).some((a) => {
|
| 1450 |
+
const href = a.getAttribute("href") || "";
|
| 1451 |
+
return (
|
| 1452 |
+
/huggingface\.co\/papers\//.test(href) ||
|
| 1453 |
+
/openreview\.net\//.test(href) ||
|
| 1454 |
+
/arxiv\.org\//.test(href)
|
| 1455 |
+
);
|
| 1456 |
+
});
|
| 1457 |
}
|
| 1458 |
|
| 1459 |
function removeIndexProse(body) {
|
|
|
|
| 1462 |
let current = h1.nextElementSibling;
|
| 1463 |
while (current && current.tagName !== "H2") {
|
| 1464 |
const next = current.nextElementSibling;
|
| 1465 |
+
if (isIndexPaperLink(current)) {
|
| 1466 |
+
current.classList.add("index-paper-link");
|
| 1467 |
+
} else {
|
| 1468 |
+
current.remove();
|
| 1469 |
+
}
|
| 1470 |
current = next;
|
| 1471 |
}
|
| 1472 |
}
|
|
|
|
| 1485 |
}
|
| 1486 |
}
|
| 1487 |
|
|
|
|
|
|
|
| 1488 |
async function renderLogbook(opts = {}) {
|
| 1489 |
const scrollY = window.scrollY;
|
| 1490 |
const page = document.getElementById("page");
|
|
|
|
| 1491 |
page.innerHTML = "";
|
| 1492 |
const nodes = allNodes();
|
| 1493 |
const markdown = await Promise.all(nodes.map(fetchPage));
|
| 1494 |
+
if (opts.renderId && opts.renderId !== RENDER_SEQUENCE) return;
|
| 1495 |
const pinnedCells = collectPinnedCells(markdown, nodes);
|
| 1496 |
let bookIntroBody = null;
|
| 1497 |
nodes.forEach((node, index) => {
|
|
|
|
| 1504 |
layout.className = "page-layout";
|
| 1505 |
const body = document.createElement("div");
|
| 1506 |
body.className = "page-body";
|
|
|
|
|
|
|
|
|
|
| 1507 |
|
| 1508 |
renderMarkdown(markdown[index], body);
|
| 1509 |
if (node.slug === MANIFEST.root.slug) {
|
| 1510 |
section.classList.add("book-intro");
|
| 1511 |
removeIndexProse(body);
|
| 1512 |
removePageDirectory(body);
|
|
|
|
| 1513 |
const h1 = body.querySelector("h1");
|
| 1514 |
+
if (h1 && h1.parentNode === body) h1.remove();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1515 |
bookIntroBody = body;
|
| 1516 |
}
|
| 1517 |
layout.appendChild(body);
|
|
|
|
| 1518 |
section.appendChild(layout);
|
| 1519 |
page.appendChild(section);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1520 |
});
|
| 1521 |
+
const pinnedSlugs = Array.from(
|
| 1522 |
+
new Set(pinnedCells.map((cell) => cell.node && cell.node.slug).filter(Boolean))
|
| 1523 |
+
);
|
| 1524 |
+
const pinnedTarget =
|
| 1525 |
+
pinnedSlugs.length === 1
|
| 1526 |
+
? Array.from(page.querySelectorAll(".page-section"))
|
| 1527 |
+
.find((section) => section.dataset.slug === pinnedSlugs[0])
|
| 1528 |
+
?.querySelector(".page-body")
|
| 1529 |
+
: bookIntroBody;
|
| 1530 |
+
if (pinnedTarget) renderPinnedNotes(pinnedCells, pinnedTarget);
|
| 1531 |
+
// Pinned cells are promoted into one deck. Remove their source render so
|
| 1532 |
+
// summaries, posters, and notes do not appear twice in the continuous view.
|
| 1533 |
+
page
|
| 1534 |
+
.querySelectorAll(".pinned-source:not(.pinned-copy)")
|
| 1535 |
+
.forEach((cell) => cell.remove());
|
| 1536 |
if (bookIntroBody) {
|
| 1537 |
const section = bookIntroBody.closest(".book-intro");
|
| 1538 |
const hasExtra = Array.from(bookIntroBody.children).some(
|
| 1539 |
(el) =>
|
| 1540 |
el.tagName !== "H1" &&
|
| 1541 |
!el.classList.contains("agent-hint") &&
|
| 1542 |
+
!el.classList.contains("index-paper-link") &&
|
| 1543 |
!el.classList.contains("pinned-notes")
|
| 1544 |
);
|
| 1545 |
if (section && !section.classList.contains("has-pinned-notes") && !hasExtra) {
|
|
|
|
| 1556 |
});
|
| 1557 |
}
|
| 1558 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1559 |
function fmtBytes(n) {
|
| 1560 |
if (n == null || isNaN(n)) return null;
|
| 1561 |
if (n < 1000) return `${n} B`;
|
|
|
|
| 1573 |
return url.split("/spaces/")[1].split(/[?#]/)[0].replace(/\/$/, "");
|
| 1574 |
}
|
| 1575 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1576 |
function artifactInfoFromCell(meta, body) {
|
| 1577 |
const name = meta.artifact || meta.path || "";
|
| 1578 |
let size = null;
|
|
|
|
| 1597 |
};
|
| 1598 |
}
|
| 1599 |
|
| 1600 |
+
const VIEW_ROUTE = { trace: "#/view/trace", workspace: "#/view/workspace" };
|
| 1601 |
+
const VIEW_TOKENS = {
|
| 1602 |
+
code: "agent_view_tokens",
|
| 1603 |
+
trace: "trace_view_tokens",
|
| 1604 |
+
workspace: "workspace_view_tokens",
|
| 1605 |
+
};
|
| 1606 |
+
|
| 1607 |
+
function readTarget(view) {
|
| 1608 |
+
const onSpaces =
|
| 1609 |
+
/\.hf\.space$/.test(location.hostname) ||
|
| 1610 |
+
/(^|\.)huggingface\.co$/.test(location.hostname);
|
| 1611 |
+
let base = "";
|
| 1612 |
+
if (onSpaces && MANIFEST.space_id) base = MANIFEST.space_id;
|
| 1613 |
+
else if (/^https?:$/.test(location.protocol))
|
| 1614 |
+
base = `${location.origin}${location.pathname}`;
|
| 1615 |
+
if (!base) return "";
|
| 1616 |
+
return base + (VIEW_ROUTE[view] || "");
|
| 1617 |
+
}
|
| 1618 |
+
|
| 1619 |
+
function renderLogbookHeader(view) {
|
| 1620 |
+
const title = document.getElementById("logbook-title");
|
| 1621 |
+
if (title) title.textContent = MANIFEST.title;
|
| 1622 |
+
const cli = document.getElementById("logbook-cli");
|
| 1623 |
+
if (!cli) return;
|
| 1624 |
+
cli.innerHTML = "";
|
| 1625 |
+
cli.appendChild(buildAgentHint(view));
|
| 1626 |
+
const destination = buildHubDestinationLink(view);
|
| 1627 |
+
if (destination) cli.appendChild(destination);
|
| 1628 |
+
}
|
| 1629 |
+
|
| 1630 |
+
function hubDestination(view) {
|
| 1631 |
+
if (view === "trace" && MANIFEST.trace_dataset) {
|
| 1632 |
+
return {
|
| 1633 |
+
label: "View Hugging Face dataset:",
|
| 1634 |
+
url: MANIFEST.trace_dataset,
|
| 1635 |
+
fallback: "Agent Traces dataset",
|
| 1636 |
+
};
|
| 1637 |
}
|
| 1638 |
+
if (view === "workspace") {
|
| 1639 |
+
const bucketId = (MANIFEST.workspace || {}).bucket_id;
|
| 1640 |
+
const url =
|
| 1641 |
+
MANIFEST.workspace_bucket ||
|
| 1642 |
+
(bucketId ? `https://huggingface.co/buckets/${bucketId}` : "");
|
| 1643 |
+
if (url) {
|
| 1644 |
+
return {
|
| 1645 |
+
label: "View Hugging Face Bucket:",
|
| 1646 |
+
url,
|
| 1647 |
+
fallback: "Workspace Bucket",
|
| 1648 |
+
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1649 |
}
|
| 1650 |
+
}
|
| 1651 |
+
return null;
|
| 1652 |
+
}
|
| 1653 |
+
|
| 1654 |
+
function buildHubDestinationLink(view) {
|
| 1655 |
+
const destination = hubDestination(view);
|
| 1656 |
+
if (!destination || !destination.url.startsWith("https://huggingface.co/")) {
|
| 1657 |
+
return null;
|
| 1658 |
+
}
|
| 1659 |
+
const row = document.createElement("div");
|
| 1660 |
+
row.className = "hub-destination";
|
| 1661 |
+
const label = document.createElement("span");
|
| 1662 |
+
label.textContent = destination.label;
|
| 1663 |
+
const link = document.createElement("a");
|
| 1664 |
+
link.href = destination.url;
|
| 1665 |
+
link.target = "_blank";
|
| 1666 |
+
link.rel = "noopener noreferrer";
|
| 1667 |
+
link.textContent =
|
| 1668 |
+
destination.url
|
| 1669 |
+
.replace(/^https:\/\/huggingface\.co\/(?:datasets|buckets)\//, "")
|
| 1670 |
+
.replace(/\/$/, "") || destination.fallback;
|
| 1671 |
+
link.title = destination.url;
|
| 1672 |
+
const icon = document.createElementNS("http://www.w3.org/2000/svg", "svg");
|
| 1673 |
+
icon.setAttribute("viewBox", "0 0 24 24");
|
| 1674 |
+
icon.setAttribute("aria-hidden", "true");
|
| 1675 |
+
const path = document.createElementNS("http://www.w3.org/2000/svg", "path");
|
| 1676 |
+
path.setAttribute("d", "M14 5h5v5M19 5l-8 8M19 13v5a1 1 0 0 1-1 1H6a1 1 0 0 1-1-1V6a1 1 0 0 1 1-1h5");
|
| 1677 |
+
icon.appendChild(path);
|
| 1678 |
+
link.appendChild(icon);
|
| 1679 |
+
row.appendChild(label);
|
| 1680 |
+
row.appendChild(link);
|
| 1681 |
+
return row;
|
| 1682 |
+
}
|
| 1683 |
+
|
| 1684 |
+
function buildAgentHint(view) {
|
| 1685 |
+
const target = readTarget(view);
|
| 1686 |
+
const command = `trackio logbook read${target ? ` ${target}` : ""}`;
|
| 1687 |
+
const tokens = MANIFEST[VIEW_TOKENS[view] || VIEW_TOKENS.code];
|
| 1688 |
+
const div = document.createElement("div");
|
| 1689 |
+
div.className = "agent-hint";
|
| 1690 |
+
const label = document.createElement("span");
|
| 1691 |
+
label.className = "agent-hint-label";
|
| 1692 |
+
label.textContent = "Read from the CLI:";
|
| 1693 |
+
const code = document.createElement("code");
|
| 1694 |
+
code.textContent = command;
|
| 1695 |
+
const copy = document.createElement("button");
|
| 1696 |
+
copy.className = "copy";
|
| 1697 |
+
copy.type = "button";
|
| 1698 |
+
copy.title = "Copy";
|
| 1699 |
+
copy.textContent = "⧉";
|
| 1700 |
+
copy.addEventListener("click", () => copyText(command, copy, "⧉"));
|
| 1701 |
+
const note = document.createElement("span");
|
| 1702 |
+
note.className = "agent-hint-note";
|
| 1703 |
+
note.textContent =
|
| 1704 |
+
"compact view for agents" + (tokens ? ` · ~${fmt(tokens)} tokens` : "");
|
| 1705 |
+
div.appendChild(label);
|
| 1706 |
+
div.appendChild(code);
|
| 1707 |
+
div.appendChild(copy);
|
| 1708 |
+
div.appendChild(note);
|
| 1709 |
+
return div;
|
| 1710 |
+
}
|
| 1711 |
+
|
| 1712 |
+
function routeState() {
|
| 1713 |
+
const raw = (location.hash || "").replace(/^#\/?/, "");
|
| 1714 |
+
if (!raw) return { view: "code", slug: MANIFEST.root.slug };
|
| 1715 |
+
const parts = raw.split("/");
|
| 1716 |
+
if (parts[0] !== "view") {
|
| 1717 |
+
const slug = findNode(MANIFEST.root, raw) ? raw : MANIFEST.root.slug;
|
| 1718 |
+
return { view: "code", slug };
|
| 1719 |
+
}
|
| 1720 |
+
if (parts[1] === "trace") {
|
| 1721 |
+
return { view: "trace", sessionId: parts.slice(2).join("/") || null };
|
| 1722 |
+
}
|
| 1723 |
+
if (parts[1] === "workspace") return { view: "workspace" };
|
| 1724 |
+
const candidate = parts.slice(2).join("/") || MANIFEST.root.slug;
|
| 1725 |
return {
|
| 1726 |
+
view: "code",
|
| 1727 |
+
slug: findNode(MANIFEST.root, candidate) ? candidate : MANIFEST.root.slug,
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1728 |
};
|
| 1729 |
}
|
| 1730 |
|
| 1731 |
+
function updateViewTabs(route = routeState()) {
|
| 1732 |
+
document.querySelectorAll("#view-tabs a").forEach((tab) => {
|
| 1733 |
+
const view = tab.dataset.view;
|
| 1734 |
+
tab.classList.toggle("active", view === route.view);
|
| 1735 |
+
tab.setAttribute("aria-current", view === route.view ? "page" : "false");
|
| 1736 |
+
if (view === "code") {
|
| 1737 |
+
const slug = route.view === "code" ? route.slug : MANIFEST.root.slug;
|
| 1738 |
+
tab.href = `#/view/code/${slug}`;
|
| 1739 |
+
} else if (view === "trace") {
|
| 1740 |
+
tab.href = "#/view/trace";
|
| 1741 |
+
}
|
| 1742 |
+
});
|
| 1743 |
}
|
| 1744 |
|
| 1745 |
+
function setActiveView(route) {
|
| 1746 |
+
CURRENT_VIEW = route.view;
|
| 1747 |
+
document.body.dataset.view = route.view;
|
| 1748 |
+
updateViewTabs(route);
|
| 1749 |
+
renderLogbookHeader(route.view);
|
| 1750 |
+
renderSidebar(route);
|
| 1751 |
+
}
|
| 1752 |
+
|
| 1753 |
+
function formatDuration(ms) {
|
| 1754 |
+
if (ms == null || isNaN(ms)) return "—";
|
| 1755 |
+
const total = Math.max(0, Math.floor(ms / 1000));
|
| 1756 |
+
const hours = Math.floor(total / 3600);
|
| 1757 |
+
const minutes = Math.floor((total % 3600) / 60);
|
| 1758 |
+
const seconds = total % 60;
|
| 1759 |
+
if (hours) return `${hours}h ${minutes}m ${seconds}s`;
|
| 1760 |
+
if (minutes) return `${minutes}m ${seconds}s`;
|
| 1761 |
+
return `${seconds}s`;
|
| 1762 |
+
}
|
| 1763 |
+
|
| 1764 |
+
function formatDate(value) {
|
| 1765 |
+
if (!value) return "—";
|
| 1766 |
+
const date = new Date(value);
|
| 1767 |
+
if (isNaN(date.getTime())) return value;
|
| 1768 |
+
return date.toLocaleString([], {
|
| 1769 |
+
year: "numeric",
|
| 1770 |
+
month: "short",
|
| 1771 |
+
day: "numeric",
|
| 1772 |
+
hour: "numeric",
|
| 1773 |
+
minute: "2-digit",
|
| 1774 |
+
second: "2-digit",
|
| 1775 |
});
|
| 1776 |
}
|
| 1777 |
|
| 1778 |
+
function emptyView(title, text, command) {
|
| 1779 |
+
const empty = document.createElement("div");
|
| 1780 |
+
empty.className = "view-empty";
|
| 1781 |
+
const heading = document.createElement("h2");
|
| 1782 |
+
heading.textContent = title;
|
| 1783 |
+
const body = document.createElement("p");
|
| 1784 |
+
body.textContent = text;
|
| 1785 |
+
empty.appendChild(heading);
|
| 1786 |
+
empty.appendChild(body);
|
| 1787 |
+
if (command) {
|
| 1788 |
+
const code = document.createElement("code");
|
| 1789 |
+
code.textContent = command;
|
| 1790 |
+
empty.appendChild(code);
|
| 1791 |
+
}
|
| 1792 |
+
return empty;
|
| 1793 |
+
}
|
| 1794 |
+
|
| 1795 |
+
function traceEventLabel(event) {
|
| 1796 |
+
if (event.kind === "reasoning") return "Thought";
|
| 1797 |
+
if (event.kind === "tool_call") return event.tool_name || event.title || "Tool";
|
| 1798 |
+
if (event.kind === "tool_result") return "Tool output";
|
| 1799 |
+
return event.title || event.kind || "Event";
|
| 1800 |
+
}
|
| 1801 |
+
|
| 1802 |
+
function appendTraceResult(entry, result) {
|
| 1803 |
+
if (!entry || !result || !result.output) return;
|
| 1804 |
+
const card = entry.querySelector(".trace-card");
|
| 1805 |
+
if (!card) return;
|
| 1806 |
+
const details = document.createElement("details");
|
| 1807 |
+
details.className = "trace-output";
|
| 1808 |
+
const summary = document.createElement("summary");
|
| 1809 |
+
summary.textContent = result.status === "error" ? "Error output" : "Output";
|
| 1810 |
+
const output = document.createElement("pre");
|
| 1811 |
+
output.textContent = result.output;
|
| 1812 |
+
details.appendChild(summary);
|
| 1813 |
+
details.appendChild(output);
|
| 1814 |
+
card.appendChild(details);
|
| 1815 |
+
}
|
| 1816 |
+
|
| 1817 |
+
function traceEventCard(event, result) {
|
| 1818 |
+
const entry = document.createElement("div");
|
| 1819 |
+
entry.className = `trace-entry trace-${event.kind || "status"}`;
|
| 1820 |
+
entry.style.setProperty("--trace-depth", Math.min(Number(event.depth) || 0, 4));
|
| 1821 |
+
|
| 1822 |
+
const rail = document.createElement("div");
|
| 1823 |
+
rail.className = "trace-rail";
|
| 1824 |
+
const number = document.createElement("span");
|
| 1825 |
+
number.className = "trace-number";
|
| 1826 |
+
number.textContent = `#${event.sequence || ""}`;
|
| 1827 |
+
const dot = document.createElement("span");
|
| 1828 |
+
dot.className = "trace-dot";
|
| 1829 |
+
const elapsed = document.createElement("span");
|
| 1830 |
+
elapsed.className = "trace-elapsed";
|
| 1831 |
+
elapsed.textContent = formatDuration(event.elapsed_ms);
|
| 1832 |
+
rail.appendChild(number);
|
| 1833 |
+
rail.appendChild(dot);
|
| 1834 |
+
rail.appendChild(elapsed);
|
| 1835 |
+
|
| 1836 |
+
const card = document.createElement("article");
|
| 1837 |
+
card.className = "trace-card";
|
| 1838 |
+
const head = document.createElement("header");
|
| 1839 |
+
const kind = document.createElement("span");
|
| 1840 |
+
kind.className = "trace-kind";
|
| 1841 |
+
kind.textContent = traceEventLabel(event);
|
| 1842 |
+
head.appendChild(kind);
|
| 1843 |
+
if (event.turn) {
|
| 1844 |
+
const turn = document.createElement("span");
|
| 1845 |
+
turn.className = "trace-turn";
|
| 1846 |
+
turn.textContent = `turn ${event.turn}`;
|
| 1847 |
+
head.appendChild(turn);
|
| 1848 |
+
}
|
| 1849 |
+
card.appendChild(head);
|
| 1850 |
+
|
| 1851 |
+
const bodyText = event.text || event.input || event.output;
|
| 1852 |
+
if (bodyText) {
|
| 1853 |
+
const body = document.createElement(
|
| 1854 |
+
event.kind === "tool_call" || event.kind === "tool_result" ? "pre" : "div"
|
| 1855 |
+
);
|
| 1856 |
+
body.className = "trace-body";
|
| 1857 |
+
body.textContent = bodyText;
|
| 1858 |
+
card.appendChild(body);
|
| 1859 |
+
}
|
| 1860 |
+
if (event.status) {
|
| 1861 |
+
const status = document.createElement("span");
|
| 1862 |
+
status.className = `trace-status-badge trace-status-badge-${event.status}`;
|
| 1863 |
+
status.textContent = String(event.status).replace(/_/g, " ");
|
| 1864 |
+
head.appendChild(status);
|
| 1865 |
+
}
|
| 1866 |
+
entry.appendChild(rail);
|
| 1867 |
+
entry.appendChild(card);
|
| 1868 |
+
appendTraceResult(entry, result);
|
| 1869 |
+
return entry;
|
| 1870 |
}
|
| 1871 |
|
| 1872 |
+
function traceSessionAnchor(id) {
|
| 1873 |
+
return "/view/trace/" + id;
|
| 1874 |
+
}
|
| 1875 |
+
|
| 1876 |
+
function buildTraceSession(session, index) {
|
| 1877 |
+
const sec = document.createElement("section");
|
| 1878 |
+
sec.className = "trace-session";
|
| 1879 |
+
sec.id = traceSessionAnchor(session.id);
|
| 1880 |
+
sec.dataset.sessionId = session.id;
|
| 1881 |
+
|
| 1882 |
+
const title = document.createElement("h2");
|
| 1883 |
+
title.className = "trace-session-title";
|
| 1884 |
+
title.textContent = session.title || session.id;
|
| 1885 |
+
sec.appendChild(title);
|
| 1886 |
+
|
| 1887 |
+
const meta = document.createElement("div");
|
| 1888 |
+
meta.className = "trace-meta";
|
| 1889 |
+
[
|
| 1890 |
+
["Started", formatDate(index.started_at)],
|
| 1891 |
+
["Ended", formatDate(index.ended_at)],
|
| 1892 |
+
["Duration", formatDuration(index.duration_ms)],
|
| 1893 |
+
["Events", String(index.event_count || 0)],
|
| 1894 |
+
].forEach(([label, value]) => {
|
| 1895 |
+
const item = document.createElement("span");
|
| 1896 |
+
const strong = document.createElement("strong");
|
| 1897 |
+
strong.textContent = label;
|
| 1898 |
+
item.appendChild(strong);
|
| 1899 |
+
item.appendChild(document.createTextNode(` ${value}`));
|
| 1900 |
+
meta.appendChild(item);
|
| 1901 |
+
});
|
| 1902 |
+
if (index.model) {
|
| 1903 |
+
const model = document.createElement("span");
|
| 1904 |
+
const strong = document.createElement("strong");
|
| 1905 |
+
strong.textContent = "Model";
|
| 1906 |
+
model.appendChild(strong);
|
| 1907 |
+
model.appendChild(document.createTextNode(` ${index.model}`));
|
| 1908 |
+
meta.appendChild(model);
|
| 1909 |
+
}
|
| 1910 |
+
if (index.source_available === false) {
|
| 1911 |
+
const missing = document.createElement("span");
|
| 1912 |
+
missing.className = "trace-source-missing";
|
| 1913 |
+
missing.textContent = "Source file unavailable · showing last capture";
|
| 1914 |
+
meta.appendChild(missing);
|
| 1915 |
+
}
|
| 1916 |
+
sec.appendChild(meta);
|
| 1917 |
+
|
| 1918 |
+
const timeline = document.createElement("section");
|
| 1919 |
+
timeline.className = "trace-timeline";
|
| 1920 |
+
sec.appendChild(timeline);
|
| 1921 |
+
|
| 1922 |
+
const chunks = index.chunks || [];
|
| 1923 |
+
if (!chunks.length) {
|
| 1924 |
+
timeline.appendChild(
|
| 1925 |
+
emptyView("Empty trace", "No displayable events were found in this session.")
|
| 1926 |
+
);
|
| 1927 |
+
return sec;
|
| 1928 |
+
}
|
| 1929 |
+
|
| 1930 |
+
const controls = document.createElement("div");
|
| 1931 |
+
controls.className = "trace-load-controls";
|
| 1932 |
+
const progress = document.createElement("span");
|
| 1933 |
+
progress.className = "trace-load-progress";
|
| 1934 |
+
const loadMore = document.createElement("button");
|
| 1935 |
+
loadMore.type = "button";
|
| 1936 |
+
loadMore.className = "trace-load-more";
|
| 1937 |
+
controls.appendChild(progress);
|
| 1938 |
+
controls.appendChild(loadMore);
|
| 1939 |
+
sec.appendChild(controls);
|
| 1940 |
+
|
| 1941 |
+
let nextChunk = 0;
|
| 1942 |
+
let loadedEvents = 0;
|
| 1943 |
+
let loading = false;
|
| 1944 |
+
const pendingCalls = new Map();
|
| 1945 |
+
|
| 1946 |
+
function updateLoadControls() {
|
| 1947 |
+
const total = Number(index.event_count) || chunks.reduce(
|
| 1948 |
+
(sum, chunk) => sum + (Number(chunk.count) || 0),
|
| 1949 |
+
0
|
| 1950 |
+
);
|
| 1951 |
+
progress.textContent = `${Math.min(loadedEvents, total)} of ${total} events loaded`;
|
| 1952 |
+
if (nextChunk >= chunks.length) {
|
| 1953 |
+
loadMore.textContent = "All events loaded";
|
| 1954 |
+
loadMore.disabled = true;
|
| 1955 |
+
return;
|
| 1956 |
+
}
|
| 1957 |
+
const count = Number(chunks[nextChunk].count) || "next";
|
| 1958 |
+
loadMore.textContent = `Load ${count} more events`;
|
| 1959 |
+
loadMore.disabled = false;
|
| 1960 |
+
}
|
| 1961 |
+
|
| 1962 |
+
async function loadNextTraceChunk() {
|
| 1963 |
+
if (loading || nextChunk >= chunks.length) return;
|
| 1964 |
+
loading = true;
|
| 1965 |
+
loadMore.disabled = true;
|
| 1966 |
+
loadMore.textContent = "Loading…";
|
| 1967 |
+
const descriptor = chunks[nextChunk];
|
| 1968 |
+
try {
|
| 1969 |
+
// Event chunks can be large. Do not retain the parsed JSON in DATA_CACHE;
|
| 1970 |
+
// the rendered DOM is the only long-lived copy.
|
| 1971 |
+
const chunk = await fetchData(descriptor.file, false);
|
| 1972 |
+
const events = chunk.events || [];
|
| 1973 |
+
events.forEach((event) => {
|
| 1974 |
+
if (
|
| 1975 |
+
event.kind === "tool_result" &&
|
| 1976 |
+
event.call_id &&
|
| 1977 |
+
pendingCalls.has(event.call_id)
|
| 1978 |
+
) {
|
| 1979 |
+
appendTraceResult(pendingCalls.get(event.call_id), event);
|
| 1980 |
+
pendingCalls.delete(event.call_id);
|
| 1981 |
return;
|
| 1982 |
}
|
| 1983 |
+
const entry = traceEventCard(event);
|
| 1984 |
+
timeline.appendChild(entry);
|
| 1985 |
+
if (event.kind === "tool_call" && event.call_id) {
|
| 1986 |
+
pendingCalls.set(event.call_id, entry);
|
| 1987 |
+
}
|
| 1988 |
});
|
| 1989 |
+
loadedEvents += events.length;
|
| 1990 |
+
nextChunk += 1;
|
| 1991 |
+
sec.dataset.loadedChunks = String(nextChunk);
|
| 1992 |
+
updateLoadControls();
|
| 1993 |
+
} catch (error) {
|
| 1994 |
+
progress.textContent = "Could not load the next trace segment.";
|
| 1995 |
+
loadMore.textContent = "Retry";
|
| 1996 |
+
loadMore.disabled = false;
|
| 1997 |
+
} finally {
|
| 1998 |
+
loading = false;
|
|
|
|
|
|
|
|
|
|
| 1999 |
}
|
| 2000 |
+
}
|
| 2001 |
+
|
| 2002 |
+
sec.dataset.loadedChunks = "0";
|
| 2003 |
+
sec.loadNextTraceChunk = loadNextTraceChunk;
|
| 2004 |
+
loadMore.addEventListener("click", loadNextTraceChunk);
|
| 2005 |
+
updateLoadControls();
|
| 2006 |
+
return sec;
|
| 2007 |
+
}
|
| 2008 |
+
|
| 2009 |
+
function ensureTraceSessionLoaded(sessionId) {
|
| 2010 |
+
const target = document.getElementById(traceSessionAnchor(sessionId));
|
| 2011 |
+
if (
|
| 2012 |
+
target &&
|
| 2013 |
+
target.dataset.loadedChunks === "0" &&
|
| 2014 |
+
typeof target.loadNextTraceChunk === "function"
|
| 2015 |
+
) {
|
| 2016 |
+
return target.loadNextTraceChunk();
|
| 2017 |
+
}
|
| 2018 |
+
return Promise.resolve();
|
| 2019 |
}
|
| 2020 |
|
| 2021 |
+
function scrollToTraceSession(sessionId) {
|
| 2022 |
+
if (!sessionId) {
|
| 2023 |
+
window.scrollTo({ top: 0, behavior: "auto" });
|
| 2024 |
+
return;
|
| 2025 |
+
}
|
| 2026 |
+
const target = document.getElementById(traceSessionAnchor(sessionId));
|
| 2027 |
+
if (target) target.scrollIntoView({ behavior: "auto" });
|
| 2028 |
+
else window.scrollTo({ top: 0, behavior: "auto" });
|
| 2029 |
+
}
|
| 2030 |
|
| 2031 |
+
// A published static Space may store only a reference to a private (or
|
| 2032 |
+
// public) repository instead of embedding trace/workspace content. These
|
| 2033 |
+
// helpers render that reference: link-only for private/inaccessible repos,
|
| 2034 |
+
// and a probe-then-render path for public ones.
|
| 2035 |
+
function repoRefCard(ref, opts) {
|
| 2036 |
+
const wrap = document.createElement("div");
|
| 2037 |
+
wrap.className = "view-empty repo-ref-card";
|
| 2038 |
+
const h = document.createElement("h2");
|
| 2039 |
+
h.textContent = opts.title;
|
| 2040 |
+
wrap.appendChild(h);
|
| 2041 |
+
const p = document.createElement("p");
|
| 2042 |
+
p.textContent = opts.message;
|
| 2043 |
+
wrap.appendChild(p);
|
| 2044 |
+
if (ref && ref.repo_url) {
|
| 2045 |
+
const a = document.createElement("a");
|
| 2046 |
+
a.className = "repo-ref-link";
|
| 2047 |
+
a.href = ref.repo_url;
|
| 2048 |
+
a.target = "_blank";
|
| 2049 |
+
a.rel = "noopener noreferrer";
|
| 2050 |
+
a.textContent = "Open on the Hub ↗";
|
| 2051 |
+
wrap.appendChild(a);
|
| 2052 |
+
}
|
| 2053 |
+
return wrap;
|
| 2054 |
+
}
|
| 2055 |
+
|
| 2056 |
+
async function probeRepoAccessible(ref) {
|
| 2057 |
+
if (!ref || !ref.repo_id) return false;
|
| 2058 |
+
let url = "";
|
| 2059 |
+
if (ref.repo_type === "dataset") {
|
| 2060 |
+
url = "https://huggingface.co/api/datasets/" + ref.repo_id;
|
| 2061 |
+
} else if (ref.repo_type === "bucket") {
|
| 2062 |
+
url = "https://huggingface.co/api/buckets/" + ref.repo_id;
|
| 2063 |
+
}
|
| 2064 |
+
if (!url) return ref.private === false;
|
| 2065 |
+
try {
|
| 2066 |
+
const response = await fetch(url, { cache: "no-store" });
|
| 2067 |
+
if (!response.ok) return false;
|
| 2068 |
+
const metadata = await response.json();
|
| 2069 |
+
return metadata.private !== true;
|
| 2070 |
+
} catch (error) {
|
| 2071 |
+
return false;
|
| 2072 |
+
}
|
| 2073 |
+
}
|
| 2074 |
+
|
| 2075 |
+
async function renderRepoReference(ref, kind, page, renderId) {
|
| 2076 |
+
const isTraces = kind === "traces";
|
| 2077 |
+
const noun = isTraces ? "agent traces" : "workspace files";
|
| 2078 |
+
const linkOnly = () =>
|
| 2079 |
+
repoRefCard(ref, {
|
| 2080 |
+
title: isTraces ? "Agent traces" : "Workspace",
|
| 2081 |
+
message:
|
| 2082 |
+
`These ${noun} live in a private repository. ` +
|
| 2083 |
+
"Open it on the Hub to view them.",
|
| 2084 |
+
});
|
| 2085 |
+
const accessible = await probeRepoAccessible(ref);
|
| 2086 |
+
if (renderId !== RENDER_SEQUENCE) return;
|
| 2087 |
+
if (!accessible) {
|
| 2088 |
+
page.appendChild(linkOnly());
|
| 2089 |
+
return;
|
| 2090 |
+
}
|
| 2091 |
+
page.appendChild(
|
| 2092 |
+
repoRefCard(ref, {
|
| 2093 |
+
title: isTraces ? "Agent traces" : "Workspace",
|
| 2094 |
+
message:
|
| 2095 |
+
`These ${noun} are published to a public repository on the Hub.`,
|
| 2096 |
+
})
|
| 2097 |
);
|
| 2098 |
+
}
|
| 2099 |
+
|
| 2100 |
+
async function renderTrace(route, renderId) {
|
| 2101 |
+
const page = document.getElementById("page");
|
| 2102 |
+
page.innerHTML = "";
|
| 2103 |
+
page.className = "trace-page";
|
| 2104 |
+
const sessions = MANIFEST.traces || [];
|
| 2105 |
+
if (!sessions.length) {
|
| 2106 |
+
updateViewTabs({ view: "trace" });
|
| 2107 |
+
if (MANIFEST.traces_ref && MANIFEST.traces_ref.repo_url) {
|
| 2108 |
+
await renderRepoReference(MANIFEST.traces_ref, "traces", page, renderId);
|
| 2109 |
+
return;
|
| 2110 |
}
|
| 2111 |
+
page.appendChild(
|
| 2112 |
+
emptyView(
|
| 2113 |
+
"No agent sessions attached yet",
|
| 2114 |
+
"Attach the active session once and Trackio will keep its trace refreshed here while you work. The session stays local until you explicitly publish it.",
|
| 2115 |
+
"trackio logbook attach trace <session.jsonl>"
|
| 2116 |
+
)
|
| 2117 |
+
);
|
| 2118 |
+
return;
|
| 2119 |
+
}
|
| 2120 |
+
updateViewTabs({ view: "trace" });
|
| 2121 |
+
|
| 2122 |
+
const loading = document.createElement("div");
|
| 2123 |
+
loading.className = "view-loading";
|
| 2124 |
+
loading.textContent = "Loading traces…";
|
| 2125 |
+
page.appendChild(loading);
|
| 2126 |
+
let loaded;
|
| 2127 |
+
try {
|
| 2128 |
+
loaded = await Promise.all(
|
| 2129 |
+
sessions.map(async (session) => {
|
| 2130 |
+
const index = await fetchData(session.index_file);
|
| 2131 |
+
return { session, index };
|
|
|
|
| 2132 |
})
|
| 2133 |
+
);
|
| 2134 |
+
} catch (error) {
|
| 2135 |
+
if (renderId !== RENDER_SEQUENCE) return;
|
| 2136 |
+
page.innerHTML = "";
|
| 2137 |
+
page.appendChild(
|
| 2138 |
+
emptyView("Trace unavailable", "The normalized traces could not be loaded.")
|
| 2139 |
+
);
|
| 2140 |
+
return;
|
| 2141 |
+
}
|
| 2142 |
+
if (renderId !== RENDER_SEQUENCE) return;
|
| 2143 |
+
page.innerHTML = "";
|
| 2144 |
+
|
| 2145 |
+
const shell = document.createElement("div");
|
| 2146 |
+
shell.className = "trace-shell";
|
| 2147 |
+
loaded.forEach(({ session, index }) => {
|
| 2148 |
+
shell.appendChild(buildTraceSession(session, index));
|
| 2149 |
});
|
| 2150 |
+
page.appendChild(shell);
|
| 2151 |
+
const activeSessionId = route.sessionId || sessions[0].id;
|
| 2152 |
+
await ensureTraceSessionLoaded(activeSessionId);
|
| 2153 |
+
if (renderId !== RENDER_SEQUENCE) return;
|
| 2154 |
+
scrollToTraceSession(activeSessionId);
|
| 2155 |
+
}
|
| 2156 |
+
|
| 2157 |
+
function svgIcon(kind) {
|
| 2158 |
+
const svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
|
| 2159 |
+
svg.setAttribute("viewBox", "0 0 24 24");
|
| 2160 |
+
svg.setAttribute("aria-hidden", "true");
|
| 2161 |
+
const path = document.createElementNS("http://www.w3.org/2000/svg", "path");
|
| 2162 |
+
path.setAttribute(
|
| 2163 |
+
"d",
|
| 2164 |
+
kind === "folder"
|
| 2165 |
+
? "M3.5 6.5h6l2 2h9v9a2 2 0 0 1-2 2h-13a2 2 0 0 1-2-2z"
|
| 2166 |
+
: kind === "download"
|
| 2167 |
+
? "M12 3v12m0 0 4-4m-4 4-4-4M5 20h14"
|
| 2168 |
+
: "M6 3.5h8l4 4V20H6zM14 3.5V8h4"
|
| 2169 |
+
);
|
| 2170 |
+
svg.appendChild(path);
|
| 2171 |
+
return svg;
|
| 2172 |
+
}
|
| 2173 |
+
|
| 2174 |
+
function workspaceTree(files) {
|
| 2175 |
+
const root = { directories: new Map(), files: [] };
|
| 2176 |
+
files.forEach((file) => {
|
| 2177 |
+
const parts = file.path.split("/");
|
| 2178 |
+
let cursor = root;
|
| 2179 |
+
parts.slice(0, -1).forEach((name) => {
|
| 2180 |
+
if (!cursor.directories.has(name)) {
|
| 2181 |
+
cursor.directories.set(name, { directories: new Map(), files: [] });
|
| 2182 |
+
}
|
| 2183 |
+
cursor = cursor.directories.get(name);
|
| 2184 |
+
});
|
| 2185 |
+
cursor.files.push(file);
|
| 2186 |
+
});
|
| 2187 |
+
return root;
|
| 2188 |
}
|
| 2189 |
|
| 2190 |
+
function workspaceFileRow(file) {
|
| 2191 |
+
const row = document.createElement("div");
|
| 2192 |
+
row.className = "workspace-file";
|
| 2193 |
+
const name = document.createElement("div");
|
| 2194 |
+
name.className = "workspace-file-name";
|
| 2195 |
+
name.appendChild(svgIcon("file"));
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2196 |
const label = document.createElement("span");
|
| 2197 |
+
label.textContent = file.name;
|
| 2198 |
+
label.title = file.path;
|
| 2199 |
+
name.appendChild(label);
|
| 2200 |
+
const type = document.createElement("span");
|
| 2201 |
+
type.className = "workspace-file-type";
|
| 2202 |
+
type.textContent = file.type || "file";
|
| 2203 |
+
const size = document.createElement("span");
|
| 2204 |
+
size.className = "workspace-file-size";
|
| 2205 |
+
size.textContent = fmtBytes(file.size) || "—";
|
| 2206 |
+
const modified = document.createElement("time");
|
| 2207 |
+
modified.className = "workspace-file-time";
|
| 2208 |
+
modified.dateTime = file.modified_at || "";
|
| 2209 |
+
modified.textContent = formatDate(file.modified_at);
|
| 2210 |
+
row.appendChild(name);
|
| 2211 |
+
row.appendChild(type);
|
| 2212 |
+
row.appendChild(size);
|
| 2213 |
+
row.appendChild(modified);
|
| 2214 |
+
const url =
|
| 2215 |
+
isLocalPreview() && file.local_url
|
| 2216 |
+
? file.local_url
|
| 2217 |
+
: file.download_url || file.bucket_url;
|
| 2218 |
+
if (url) {
|
| 2219 |
+
const download = document.createElement("a");
|
| 2220 |
+
download.className = "workspace-download";
|
| 2221 |
+
download.href = url;
|
| 2222 |
+
download.title = "Download";
|
| 2223 |
+
download.setAttribute("aria-label", `Download ${file.name}`);
|
| 2224 |
+
if (isLocalPreview() && file.local_url) download.download = file.name;
|
| 2225 |
+
download.appendChild(svgIcon("download"));
|
| 2226 |
+
row.appendChild(download);
|
| 2227 |
+
} else {
|
| 2228 |
+
const pending = document.createElement("span");
|
| 2229 |
+
pending.className = "workspace-unpublished";
|
| 2230 |
+
pending.textContent = "Local";
|
| 2231 |
+
row.appendChild(pending);
|
| 2232 |
+
}
|
| 2233 |
+
return row;
|
| 2234 |
+
}
|
| 2235 |
+
|
| 2236 |
+
function renderWorkspaceNode(node, container) {
|
| 2237 |
+
Array.from(node.directories.entries())
|
| 2238 |
+
.sort(([a], [b]) => a.localeCompare(b))
|
| 2239 |
+
.forEach(([name, child]) => {
|
| 2240 |
+
const details = document.createElement("details");
|
| 2241 |
+
details.className = "workspace-folder";
|
| 2242 |
+
details.open = true;
|
| 2243 |
+
const summary = document.createElement("summary");
|
| 2244 |
+
summary.appendChild(svgIcon("folder"));
|
| 2245 |
+
const label = document.createElement("span");
|
| 2246 |
+
label.textContent = name;
|
| 2247 |
+
summary.appendChild(label);
|
| 2248 |
+
details.appendChild(summary);
|
| 2249 |
+
const children = document.createElement("div");
|
| 2250 |
+
children.className = "workspace-folder-children";
|
| 2251 |
+
renderWorkspaceNode(child, children);
|
| 2252 |
+
details.appendChild(children);
|
| 2253 |
+
container.appendChild(details);
|
| 2254 |
+
});
|
| 2255 |
+
node.files
|
| 2256 |
+
.sort((a, b) => a.name.localeCompare(b.name))
|
| 2257 |
+
.forEach((file) => container.appendChild(workspaceFileRow(file)));
|
| 2258 |
+
}
|
| 2259 |
+
|
| 2260 |
+
const WORKSPACE_MODE_KEY = "trackio-logbook:workspace-mode";
|
| 2261 |
+
|
| 2262 |
+
function getWorkspaceMode() {
|
| 2263 |
+
try {
|
| 2264 |
+
return localStorage.getItem(WORKSPACE_MODE_KEY) === "type" ? "type" : "tree";
|
| 2265 |
+
} catch (error) {
|
| 2266 |
+
return "tree";
|
| 2267 |
+
}
|
| 2268 |
+
}
|
| 2269 |
+
|
| 2270 |
+
function setWorkspaceMode(mode) {
|
| 2271 |
+
try {
|
| 2272 |
+
localStorage.setItem(WORKSPACE_MODE_KEY, mode);
|
| 2273 |
+
} catch (error) {
|
| 2274 |
+
/* ignore storage failures (private mode, etc.) */
|
| 2275 |
+
}
|
| 2276 |
+
}
|
| 2277 |
+
|
| 2278 |
+
function fileGroupKey(file) {
|
| 2279 |
+
if (file.type) return file.type;
|
| 2280 |
+
const name = file.name || file.path || "";
|
| 2281 |
+
const dot = name.lastIndexOf(".");
|
| 2282 |
+
if (dot > 0 && dot < name.length - 1) return name.slice(dot + 1).toLowerCase();
|
| 2283 |
+
return "other";
|
| 2284 |
+
}
|
| 2285 |
+
|
| 2286 |
+
function renderWorkspaceByType(files, container) {
|
| 2287 |
+
const groups = new Map();
|
| 2288 |
+
files.forEach((file) => {
|
| 2289 |
+
const key = fileGroupKey(file);
|
| 2290 |
+
if (!groups.has(key)) groups.set(key, []);
|
| 2291 |
+
groups.get(key).push(file);
|
| 2292 |
+
});
|
| 2293 |
+
Array.from(groups.keys())
|
| 2294 |
+
.sort((a, b) => a.localeCompare(b))
|
| 2295 |
+
.forEach((key) => {
|
| 2296 |
+
const items = groups
|
| 2297 |
+
.get(key)
|
| 2298 |
+
.sort((a, b) => a.name.localeCompare(b.name));
|
| 2299 |
+
const section = document.createElement("div");
|
| 2300 |
+
section.className = "workspace-group";
|
| 2301 |
+
const heading = document.createElement("h3");
|
| 2302 |
+
heading.className = "workspace-group-head";
|
| 2303 |
+
const label = document.createElement("span");
|
| 2304 |
+
label.textContent = key;
|
| 2305 |
+
const count = document.createElement("span");
|
| 2306 |
+
count.className = "workspace-group-count";
|
| 2307 |
+
count.textContent = String(items.length);
|
| 2308 |
+
heading.appendChild(label);
|
| 2309 |
+
heading.appendChild(count);
|
| 2310 |
+
section.appendChild(heading);
|
| 2311 |
+
items.forEach((file) => section.appendChild(workspaceFileRow(file)));
|
| 2312 |
+
container.appendChild(section);
|
| 2313 |
+
});
|
| 2314 |
+
}
|
| 2315 |
+
|
| 2316 |
+
function buildWorkspaceToggle(current, onChange) {
|
| 2317 |
+
const toggle = document.createElement("div");
|
| 2318 |
+
toggle.className = "workspace-toggle";
|
| 2319 |
+
toggle.setAttribute("role", "group");
|
| 2320 |
+
toggle.setAttribute("aria-label", "Workspace layout");
|
| 2321 |
+
const buttons = [];
|
| 2322 |
+
[
|
| 2323 |
+
["tree", "Tree"],
|
| 2324 |
+
["type", "By type"],
|
| 2325 |
+
].forEach(([mode, text]) => {
|
| 2326 |
+
const btn = document.createElement("button");
|
| 2327 |
+
btn.type = "button";
|
| 2328 |
+
btn.className = "workspace-toggle-btn";
|
| 2329 |
+
btn.textContent = text;
|
| 2330 |
+
const setActive = (active) => {
|
| 2331 |
+
btn.classList.toggle("is-active", active);
|
| 2332 |
+
btn.setAttribute("aria-pressed", active ? "true" : "false");
|
| 2333 |
+
};
|
| 2334 |
+
setActive(mode === current);
|
| 2335 |
+
btn.addEventListener("click", () => {
|
| 2336 |
+
buttons.forEach((entry) => entry.setActive(entry.mode === mode));
|
| 2337 |
+
onChange(mode);
|
| 2338 |
+
});
|
| 2339 |
+
buttons.push({ mode, setActive });
|
| 2340 |
+
toggle.appendChild(btn);
|
| 2341 |
+
});
|
| 2342 |
+
return toggle;
|
| 2343 |
+
}
|
| 2344 |
+
|
| 2345 |
+
const HF_LOGO_DATA_URI = "data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI5NSIgaGVpZ2h0PSI4OCIgZmlsbD0ibm9uZSI+Cgk8cGF0aCBmaWxsPSIjRkZEMjFFIiBkPSJNNDcuMjEgNzYuNWEzNC43NSAzNC43NSAwIDEgMCAwLTY5LjUgMzQuNzUgMzQuNzUgMCAwIDAgMCA2OS41WiIgLz4KCTxwYXRoCgkJZmlsbD0iI0ZGOUQwQiIKCQlkPSJNODEuOTYgNDEuNzVhMzQuNzUgMzQuNzUgMCAxIDAtNjkuNSAwIDM0Ljc1IDM0Ljc1IDAgMCAwIDY5LjUgMFptLTczLjUgMGEzOC43NSAzOC43NSAwIDEgMSA3Ny41IDAgMzguNzUgMzguNzUgMCAwIDEtNzcuNSAwWiIKCS8+Cgk8cGF0aAoJCWZpbGw9IiMzQTNCNDUiCgkJZD0iTTU4LjUgMzIuM2MxLjI4LjQ0IDEuNzggMy4wNiAzLjA3IDIuMzhhNSA1IDAgMSAwLTYuNzYtMi4wN2MuNjEgMS4xNSAyLjU1LS43MiAzLjctLjMyWk0zNC45NSAzMi4zYy0xLjI4LjQ0LTEuNzkgMy4wNi0zLjA3IDIuMzhhNSA1IDAgMSAxIDYuNzYtMi4wN2MtLjYxIDEuMTUtMi41Ni0uNzItMy43LS4zMloiCgkvPgoJPHBhdGgKCQlmaWxsPSIjRkYzMjNEIgoJCWQ9Ik00Ni45NiA1Ni4yOWM5LjgzIDAgMTMtOC43NiAxMy0xMy4yNiAwLTIuMzQtMS41Ny0xLjYtNC4wOS0uMzYtMi4zMyAxLjE1LTUuNDYgMi43NC04LjkgMi43NC03LjE5IDAtMTMtNi44OC0xMy0yLjM4czMuMTYgMTMuMjYgMTMgMTMuMjZaIgoJLz4KCTxwYXRoCgkJZmlsbD0iIzNBM0I0NSIKCQlmaWxsLXJ1bGU9ImV2ZW5vZGQiCgkJZD0iTTM5LjQzIDU0YTguNyA4LjcgMCAwIDEgNS4zLTQuNDljLjQtLjEyLjgxLjU3IDEuMjQgMS4yOC40LjY4LjgyIDEuMzcgMS4yNCAxLjM3LjQ1IDAgLjktLjY4IDEuMzMtMS4zNS40NS0uNy44OS0xLjM4IDEuMzItMS4yNWE4LjYxIDguNjEgMCAwIDEgNSA0LjE3YzMuNzMtMi45NCA1LjEtNy43NCA1LjEtMTAuNyAwLTIuMzQtMS41Ny0xLjYtNC4wOS0uMzZsLS4xNC4wN2MtMi4zMSAxLjE1LTUuMzkgMi42Ny04Ljc3IDIuNjdzLTYuNDUtMS41Mi04Ljc3LTIuNjdjLTIuNi0xLjI5LTQuMjMtMi4xLTQuMjMuMjkgMCAzLjA1IDEuNDYgOC4wNiA1LjQ3IDEwLjk3WiIKCQljbGlwLXJ1bGU9ImV2ZW5vZGQiCgkvPgoJPHBhdGgKCQlmaWxsPSIjRkY5RDBCIgoJCWQ9Ik03MC43MSAzN2EzLjI1IDMuMjUgMCAxIDAgMC02LjUgMy4yNSAzLjI1IDAgMCAwIDAgNi41Wk0yNC4yMSAzN2EzLjI1IDMuMjUgMCAxIDAgMC02LjUgMy4yNSAzLjI1IDAgMCAwIDAgNi41Wk0xNy41MiA0OGMtMS42MiAwLTMuMDYuNjYtNC4wNyAxLjg3YTUuOTcgNS45NyAwIDAgMC0xLjMzIDMuNzYgNy4xIDcuMSAwIDAgMC0xLjk0LS4zYy0xLjU1IDAtMi45NS41OS0zLjk0IDEuNjZhNS44IDUuOCAwIDAgMC0uOCA3IDUuMyA1LjMgMCAwIDAtMS43OSAyLjgyYy0uMjQuOS0uNDggMi44LjggNC43NGE1LjIyIDUuMjIgMCAwIDAtLjM3IDUuMDJjMS4wMiAyLjMyIDMuNTcgNC4xNCA4LjUyIDYuMSAzLjA3IDEuMjIgNS44OSAyIDUuOTEgMi4wMWE0NC4zMyA0NC4zMyAwIDAgMCAxMC45MyAxLjZjNS44NiAwIDEwLjA1LTEuOCAxMi40Ni01LjM0IDMuODgtNS42OSAzLjMzLTEwLjktMS43LTE1LjkyLTIuNzctMi43OC00LjYyLTYuODctNS03Ljc3LS43OC0yLjY2LTIuODQtNS42Mi02LjI1LTUuNjJhNS43IDUuNyAwIDAgMC00LjYgMi40NmMtMS0xLjI2LTEuOTgtMi4yNS0yLjg2LTIuODJBNy40IDcuNCAwIDAgMCAxNy41MiA0OFptMCA0Yy41MSAwIDEuMTQuMjIgMS44Mi42NSAyLjE0IDEuMzYgNi4yNSA4LjQzIDcuNzYgMTEuMTguNS45MiAxLjM3IDEuMzEgMi4xNCAxLjMxIDEuNTUgMCAyLjc1LTEuNTMuMTUtMy40OC0zLjkyLTIuOTMtMi41NS03LjcyLS42OC04LjAxLjA4LS4wMi4xNy0uMDIuMjQtLjAyIDEuNyAwIDIuNDUgMi45MyAyLjQ1IDIuOTNzMi4yIDUuNTIgNS45OCA5LjNjMy43NyAzLjc3IDMuOTcgNi44IDEuMjIgMTAuODMtMS44OCAyLjc1LTUuNDcgMy41OC05LjE2IDMuNTgtMy44MSAwLTcuNzMtLjktOS45Mi0xLjQ2LS4xMS0uMDMtMTMuNDUtMy44LTExLjc2LTcgLjI4LS41NC43NS0uNzYgMS4zNC0uNzYgMi4zOCAwIDYuNyAzLjU0IDguNTcgMy41NC40MSAwIC43LS4xNy44My0uNi43OS0yLjg1LTEyLjA2LTQuMDUtMTAuOTgtOC4xNy4yLS43My43MS0xLjAyIDEuNDQtMS4wMiAzLjE0IDAgMTAuMiA1LjUzIDExLjY4IDUuNTMuMTEgMCAuMi0uMDMuMjQtLjEuNzQtMS4yLjMzLTIuMDQtNC45LTUuMi01LjIxLTMuMTYtOC44OC01LjA2LTYuOC03LjMzLjI0LS4yNi41OC0uMzggMS0uMzggMy4xNyAwIDEwLjY2IDYuODIgMTAuNjYgNi44MnMyLjAyIDIuMSAzLjI1IDIuMWMuMjggMCAuNTItLjEuNjgtLjM4Ljg2LTEuNDYtOC4wNi04LjIyLTguNTYtMTEuMDEtLjM0LTEuOS4yNC0yLjg1IDEuMzEtMi44NVoiCgkvPgoJPHBhdGgKCQlmaWxsPSIjRkZEMjFFIgoJCWQ9Ik0zOC42IDc2LjY5YzIuNzUtNC4wNCAyLjU1LTcuMDctMS4yMi0xMC44NC0zLjc4LTMuNzctNS45OC05LjMtNS45OC05LjNzLS44Mi0zLjItMi42OS0yLjljLTEuODcuMy0zLjI0IDUuMDguNjggOC4wMSAzLjkxIDIuOTMtLjc4IDQuOTItMi4yOSAyLjE3LTEuNS0yLjc1LTUuNjItOS44Mi03Ljc2LTExLjE4LTIuMTMtMS4zNS0zLjYzLS42LTMuMTMgMi4yLjUgMi43OSA5LjQzIDkuNTUgOC41NiAxMS0uODcgMS40Ny0zLjkzLTEuNzEtMy45My0xLjcxcy05LjU3LTguNzEtMTEuNjYtNi40NGMtMi4wOCAyLjI3IDEuNTkgNC4xNyA2LjggNy4zMyA1LjIzIDMuMTYgNS42NCA0IDQuOSA1LjItLjc1IDEuMi0xMi4yOC04LjUzLTEzLjM2LTQuNC0xLjA4IDQuMTEgMTEuNzcgNS4zIDEwLjk4IDguMTUtLjggMi44NS05LjA2LTUuMzgtMTAuNzQtMi4xOC0xLjcgMy4yMSAxMS42NSA2Ljk4IDExLjc2IDcuMDEgNC4zIDEuMTIgMTUuMjUgMy40OSAxOS4wOC0yLjEyWiIKCS8+Cgk8cGF0aAoJCWZpbGw9IiNGRjlEMEIiCgkJZD0iTTc3LjQgNDhjMS42MiAwIDMuMDcuNjYgNC4wNyAxLjg3YTUuOTcgNS45NyAwIDAgMSAxLjMzIDMuNzYgNy4xIDcuMSAwIDAgMSAxLjk1LS4zYzEuNTUgMCAyLjk1LjU5IDMuOTQgMS42NmE1LjggNS44IDAgMCAxIC44IDcgNS4zIDUuMyAwIDAgMSAxLjc4IDIuODJjLjI0LjkuNDggMi44LS44IDQuNzRhNS4yMiA1LjIyIDAgMCAxIC4zNyA1LjAyYy0xLjAyIDIuMzItMy41NyA0LjE0LTguNTEgNi4xLTMuMDggMS4yMi01LjkgMi01LjkyIDIuMDFhNDQuMzMgNDQuMzMgMCAwIDEtMTAuOTMgMS42Yy01Ljg2IDAtMTAuMDUtMS44LTEyLjQ2LTUuMzQtMy44OC01LjY5LTMuMzMtMTAuOSAxLjctMTUuOTIgMi43OC0yLjc4IDQuNjMtNi44NyA1LjAxLTcuNzcuNzgtMi42NiAyLjgzLTUuNjIgNi4yNC01LjYyYTUuNyA1LjcgMCAwIDEgNC42IDIuNDZjMS0xLjI2IDEuOTgtMi4yNSAyLjg3LTIuODJBNy40IDcuNCAwIDAgMSA3Ny40IDQ4Wm0wIDRjLS41MSAwLTEuMTMuMjItMS44Mi42NS0yLjEzIDEuMzYtNi4yNSA4LjQzLTcuNzYgMTEuMThhMi40MyAyLjQzIDAgMCAxLTIuMTQgMS4zMWMtMS41NCAwLTIuNzUtMS41My0uMTQtMy40OCAzLjkxLTIuOTMgMi41NC03LjcyLjY3LTguMDFhMS41NCAxLjU0IDAgMCAwLS4yNC0uMDJjLTEuNyAwLTIuNDUgMi45My0yLjQ1IDIuOTNzLTIuMiA1LjUyLTUuOTcgOS4zYy0zLjc4IDMuNzctMy45OCA2LjgtMS4yMiAxMC44MyAxLjg3IDIuNzUgNS40NyAzLjU4IDkuMTUgMy41OCAzLjgyIDAgNy43My0uOSA5LjkzLTEuNDYuMS0uMDMgMTMuNDUtMy44IDExLjc2LTctLjI5LS41NC0uNzUtLjc2LTEuMzQtLjc2LTIuMzggMC02LjcxIDMuNTQtOC41NyAzLjU0LS40MiAwLS43MS0uMTctLjgzLS42LS44LTIuODUgMTIuMDUtNC4wNSAxMC45Ny04LjE3LS4xOS0uNzMtLjctMS4wMi0xLjQ0LTEuMDItMy4xNCAwLTEwLjIgNS41My0xMS42OCA1LjUzLS4xIDAtLjE5LS4wMy0uMjMtLjEtLjc0LTEuMi0uMzQtMi4wNCA0Ljg4LTUuMiA1LjIzLTMuMTYgOC45LTUuMDYgNi44LTcuMzMtLjIzLS4yNi0uNTctLjM4LS45OC0uMzgtMy4xOCAwLTEwLjY3IDYuODItMTAuNjcgNi44MnMtMi4wMiAyLjEtMy4yNCAyLjFhLjc0Ljc0IDAgMCAxLS42OC0uMzhjLS44Ny0xLjQ2IDguMDUtOC4yMiA4LjU1LTExLjAxLjM0LTEuOS0uMjQtMi44NS0xLjMxLTIuODVaIgoJLz4KCTxwYXRoCgkJZmlsbD0iI0ZGRDIxRSIKCQlkPSJNNTYuMzMgNzYuNjljLTIuNzUtNC4wNC0yLjU2LTcuMDcgMS4yMi0xMC44NCAzLjc3LTMuNzcgNS45Ny05LjMgNS45Ny05LjNzLjgyLTMuMiAyLjctMi45YzEuODYuMyAzLjIzIDUuMDgtLjY4IDguMDEtMy45MiAyLjkzLjc4IDQuOTIgMi4yOCAyLjE3IDEuNTEtMi43NSA1LjYzLTkuODIgNy43Ni0xMS4xOCAyLjEzLTEuMzUgMy42NC0uNiAzLjEzIDIuMi0uNSAyLjc5LTkuNDIgOS41NS04LjU1IDExIC44NiAxLjQ3IDMuOTItMS43MSAzLjkyLTEuNzFzOS41OC04LjcxIDExLjY2LTYuNDRjMi4wOCAyLjI3LTEuNTggNC4xNy02LjggNy4zMy01LjIzIDMuMTYtNS42MyA0LTQuOSA1LjIuNzUgMS4yIDEyLjI4LTguNTMgMTMuMzYtNC40IDEuMDggNC4xMS0xMS43NiA1LjMtMTAuOTcgOC4xNS44IDIuODUgOS4wNS01LjM4IDEwLjc0LTIuMTggMS42OSAzLjIxLTExLjY1IDYuOTgtMTEuNzYgNy4wMS00LjMxIDEuMTItMTUuMjYgMy40OS0xOS4wOC0yLjEyWiIKCS8+Cjwvc3ZnPgo=";
|
| 2346 |
+
|
| 2347 |
+
function hubGroupId(type) {
|
| 2348 |
+
return "ws-hub-" + String(type).toLowerCase().replace(/[^a-z0-9]+/g, "-");
|
| 2349 |
+
}
|
| 2350 |
+
|
| 2351 |
+
const HUB_REF_GROUP_ORDER = [
|
| 2352 |
+
"Jobs",
|
| 2353 |
+
"Datasets",
|
| 2354 |
+
"Models",
|
| 2355 |
+
"Spaces",
|
| 2356 |
+
"Buckets",
|
| 2357 |
+
"Collections",
|
| 2358 |
+
"Papers",
|
| 2359 |
+
];
|
| 2360 |
+
|
| 2361 |
+
function hubRefFromRepoRef(ref) {
|
| 2362 |
+
if (!ref || !ref.repo_id || !ref.repo_url) return null;
|
| 2363 |
+
if (ref.repo_type === "dataset") {
|
| 2364 |
+
return { url: ref.repo_url, type: "Datasets", label: ref.repo_id };
|
| 2365 |
+
}
|
| 2366 |
+
if (ref.repo_type === "bucket") {
|
| 2367 |
+
return { url: ref.repo_url, type: "Buckets", label: ref.repo_id };
|
| 2368 |
+
}
|
| 2369 |
+
return null;
|
| 2370 |
+
}
|
| 2371 |
+
|
| 2372 |
+
async function publicAssociatedHubRefs() {
|
| 2373 |
+
const refs = [MANIFEST.traces_ref, MANIFEST.workspace_ref].filter(Boolean);
|
| 2374 |
+
const publicStates = await Promise.all(refs.map(probeRepoAccessible));
|
| 2375 |
+
return refs
|
| 2376 |
+
.filter((ref, index) => publicStates[index])
|
| 2377 |
+
.map(hubRefFromRepoRef)
|
| 2378 |
+
.filter(Boolean);
|
| 2379 |
+
}
|
| 2380 |
+
|
| 2381 |
+
function mergeHubRefs(...groups) {
|
| 2382 |
+
const merged = [];
|
| 2383 |
+
const seen = new Set();
|
| 2384 |
+
groups.flat().forEach((ref) => {
|
| 2385 |
+
if (!validHubRef(ref)) return;
|
| 2386 |
+
const key = `${ref.type || "Other"}:${ref.label || ref.url}`;
|
| 2387 |
+
if (seen.has(key)) return;
|
| 2388 |
+
seen.add(key);
|
| 2389 |
+
merged.push(ref);
|
| 2390 |
+
});
|
| 2391 |
+
return merged;
|
| 2392 |
+
}
|
| 2393 |
+
|
| 2394 |
+
function validHubRef(ref) {
|
| 2395 |
+
if (!ref || !ref.url) return false;
|
| 2396 |
+
if (classifyResource(ref.url)) return true;
|
| 2397 |
+
const match = ref.url.match(/huggingface\.co\/collections\/([^/?#]+\/[^/?#]+)/);
|
| 2398 |
+
return Boolean(match && validHfRepoId(match[1].split("/")));
|
| 2399 |
+
}
|
| 2400 |
+
|
| 2401 |
+
function renderHubRefs(refs) {
|
| 2402 |
+
const validRefs = Array.isArray(refs) ? refs.filter(validHubRef) : [];
|
| 2403 |
+
if (!validRefs.length) return null;
|
| 2404 |
+
const section = document.createElement("section");
|
| 2405 |
+
section.className = "workspace-hub";
|
| 2406 |
+
const heading = document.createElement("h2");
|
| 2407 |
+
heading.className = "workspace-hub-title";
|
| 2408 |
+
const hubLogo = document.createElement("img");
|
| 2409 |
+
hubLogo.className = "workspace-hub-logo";
|
| 2410 |
+
hubLogo.src = HF_LOGO_DATA_URI;
|
| 2411 |
+
hubLogo.alt = "";
|
| 2412 |
+
hubLogo.setAttribute("aria-hidden", "true");
|
| 2413 |
+
heading.appendChild(hubLogo);
|
| 2414 |
+
heading.appendChild(document.createTextNode("Hugging Face artifacts"));
|
| 2415 |
+
section.appendChild(heading);
|
| 2416 |
+
const byType = new Map();
|
| 2417 |
+
validRefs.forEach((ref) => {
|
| 2418 |
+
const type = ref.type || "Other";
|
| 2419 |
+
if (!byType.has(type)) byType.set(type, []);
|
| 2420 |
+
byType.get(type).push(ref);
|
| 2421 |
+
});
|
| 2422 |
+
const order = [
|
| 2423 |
+
...HUB_REF_GROUP_ORDER,
|
| 2424 |
+
...Array.from(byType.keys()).filter((t) => !HUB_REF_GROUP_ORDER.includes(t)),
|
| 2425 |
+
];
|
| 2426 |
+
order.forEach((type) => {
|
| 2427 |
+
const items = byType.get(type);
|
| 2428 |
+
if (!items || !items.length) return;
|
| 2429 |
+
const group = document.createElement("div");
|
| 2430 |
+
group.className = "workspace-hub-group";
|
| 2431 |
+
group.id = hubGroupId(type);
|
| 2432 |
+
const gh = document.createElement("h3");
|
| 2433 |
+
gh.className = "workspace-hub-group-head";
|
| 2434 |
+
const label = document.createElement("span");
|
| 2435 |
+
label.textContent = type;
|
| 2436 |
+
const count = document.createElement("span");
|
| 2437 |
+
count.className = "workspace-hub-count";
|
| 2438 |
+
count.textContent = String(items.length);
|
| 2439 |
+
gh.appendChild(label);
|
| 2440 |
+
gh.appendChild(count);
|
| 2441 |
+
group.appendChild(gh);
|
| 2442 |
+
const list = document.createElement("div");
|
| 2443 |
+
list.className = "workspace-hub-list";
|
| 2444 |
+
items.forEach((ref) => {
|
| 2445 |
+
const link = document.createElement("a");
|
| 2446 |
+
link.className = "workspace-hub-link";
|
| 2447 |
+
link.href = ref.url;
|
| 2448 |
+
link.target = "_blank";
|
| 2449 |
+
link.rel = "noopener noreferrer";
|
| 2450 |
+
link.textContent = ref.label || ref.url;
|
| 2451 |
+
link.title = ref.url;
|
| 2452 |
+
list.appendChild(link);
|
| 2453 |
+
});
|
| 2454 |
+
group.appendChild(list);
|
| 2455 |
+
section.appendChild(group);
|
| 2456 |
+
});
|
| 2457 |
+
return section;
|
| 2458 |
+
}
|
| 2459 |
+
|
| 2460 |
+
function workspaceSidebarEntries(files, hubRefs) {
|
| 2461 |
+
const entries = [];
|
| 2462 |
+
if (files && files.length) entries.push({ id: "ws-files", label: "Files" });
|
| 2463 |
+
const counts = new Map();
|
| 2464 |
+
(Array.isArray(hubRefs) ? hubRefs : []).filter(validHubRef).forEach((ref) => {
|
| 2465 |
+
const type = ref.type || "Other";
|
| 2466 |
+
counts.set(type, (counts.get(type) || 0) + 1);
|
| 2467 |
+
});
|
| 2468 |
+
const order = [
|
| 2469 |
+
...HUB_REF_GROUP_ORDER,
|
| 2470 |
+
...Array.from(counts.keys()).filter((t) => !HUB_REF_GROUP_ORDER.includes(t)),
|
| 2471 |
+
];
|
| 2472 |
+
order.forEach((type) => {
|
| 2473 |
+
if (counts.get(type)) entries.push({ id: hubGroupId(type), label: type });
|
| 2474 |
+
});
|
| 2475 |
+
return entries;
|
| 2476 |
+
}
|
| 2477 |
+
|
| 2478 |
+
function buildWorkspaceSidebar(entries) {
|
| 2479 |
+
const tree = document.getElementById("tree");
|
| 2480 |
+
tree.innerHTML = "";
|
| 2481 |
+
if (!entries || !entries.length) return;
|
| 2482 |
+
const label = document.createElement("div");
|
| 2483 |
+
label.className = "tree-label";
|
| 2484 |
+
label.textContent = "Sections";
|
| 2485 |
+
tree.appendChild(label);
|
| 2486 |
+
entries.forEach((entry) => {
|
| 2487 |
+
const a = document.createElement("a");
|
| 2488 |
+
a.href = "#/view/workspace";
|
| 2489 |
+
a.className = "depth-0";
|
| 2490 |
+
a.dataset.section = entry.id;
|
| 2491 |
+
const mark = document.createElement("span");
|
| 2492 |
+
mark.className = "tree-mark";
|
| 2493 |
+
mark.textContent = "§";
|
| 2494 |
+
a.appendChild(mark);
|
| 2495 |
+
a.appendChild(document.createTextNode(" " + entry.label));
|
| 2496 |
+
a.addEventListener("click", (event) => {
|
| 2497 |
+
event.preventDefault();
|
| 2498 |
+
const target = document.getElementById(entry.id);
|
| 2499 |
+
if (!target) return;
|
| 2500 |
+
target.scrollIntoView({ behavior: "smooth", block: "start" });
|
| 2501 |
+
tree
|
| 2502 |
+
.querySelectorAll("a")
|
| 2503 |
+
.forEach((link) => link.classList.toggle("active", link === a));
|
| 2504 |
+
});
|
| 2505 |
+
tree.appendChild(a);
|
| 2506 |
+
});
|
| 2507 |
+
}
|
| 2508 |
+
|
| 2509 |
+
async function renderWorkspace(renderId) {
|
| 2510 |
+
const page = document.getElementById("page");
|
| 2511 |
+
page.innerHTML = "";
|
| 2512 |
+
page.className = "workspace-page";
|
| 2513 |
+
const loading = document.createElement("div");
|
| 2514 |
+
loading.className = "view-loading";
|
| 2515 |
+
loading.textContent = "Loading workspace…";
|
| 2516 |
+
page.appendChild(loading);
|
| 2517 |
+
let workspace;
|
| 2518 |
+
try {
|
| 2519 |
+
workspace = await fetchData((MANIFEST.workspace || {}).file || "workspace.json");
|
| 2520 |
+
} catch (error) {
|
| 2521 |
+
if (renderId !== RENDER_SEQUENCE) return;
|
| 2522 |
+
page.innerHTML = "";
|
| 2523 |
+
page.appendChild(emptyView("Workspace unavailable", "The workspace inventory could not be loaded."));
|
| 2524 |
+
return;
|
| 2525 |
+
}
|
| 2526 |
+
if (renderId !== RENDER_SEQUENCE) return;
|
| 2527 |
+
page.innerHTML = "";
|
| 2528 |
+
const associatedHubRefs = await publicAssociatedHubRefs();
|
| 2529 |
+
if (renderId !== RENDER_SEQUENCE) return;
|
| 2530 |
+
const hubRefs = mergeHubRefs(workspace.hub_refs || [], associatedHubRefs);
|
| 2531 |
+
const shell = document.createElement("div");
|
| 2532 |
+
shell.className = "workspace-shell";
|
| 2533 |
+
const header = document.createElement("header");
|
| 2534 |
+
header.className = "workspace-header";
|
| 2535 |
+
const summary = document.createElement("p");
|
| 2536 |
+
summary.textContent = `${workspace.file_count || 0} files · ${fmtBytes(workspace.total_size || 0)}`;
|
| 2537 |
+
header.appendChild(summary);
|
| 2538 |
+
const files = workspace.files || [];
|
| 2539 |
+
if (files.length) {
|
| 2540 |
+
const inventory = document.createElement("section");
|
| 2541 |
+
inventory.className = "workspace-inventory";
|
| 2542 |
+
inventory.id = "ws-files";
|
| 2543 |
+
const renderInventory = (mode) => {
|
| 2544 |
+
inventory.innerHTML = "";
|
| 2545 |
+
if (mode === "type") renderWorkspaceByType(files, inventory);
|
| 2546 |
+
else renderWorkspaceNode(workspaceTree(files), inventory);
|
| 2547 |
+
};
|
| 2548 |
+
const toggle = buildWorkspaceToggle(getWorkspaceMode(), (mode) => {
|
| 2549 |
+
setWorkspaceMode(mode);
|
| 2550 |
+
renderInventory(mode);
|
| 2551 |
+
});
|
| 2552 |
+
header.appendChild(toggle);
|
| 2553 |
+
shell.appendChild(header);
|
| 2554 |
+
shell.appendChild(inventory);
|
| 2555 |
+
renderInventory(getWorkspaceMode());
|
| 2556 |
+
} else if (MANIFEST.workspace_ref && MANIFEST.workspace_ref.repo_url) {
|
| 2557 |
+
shell.appendChild(header);
|
| 2558 |
+
await renderRepoReference(
|
| 2559 |
+
MANIFEST.workspace_ref,
|
| 2560 |
+
"workspace",
|
| 2561 |
+
shell,
|
| 2562 |
+
renderId
|
| 2563 |
+
);
|
| 2564 |
+
if (renderId !== RENDER_SEQUENCE) return;
|
| 2565 |
+
} else {
|
| 2566 |
+
shell.appendChild(header);
|
| 2567 |
+
shell.appendChild(
|
| 2568 |
+
emptyView(
|
| 2569 |
+
"No workspace files captured yet",
|
| 2570 |
+
"Supported model and data files appear here as they are created or changed after a trace is attached. Outputs captured by trackio logbook run appear when the run finishes; logged Trackio artifacts appear immediately in the Logbook tab. Files stay local until you choose to publish."
|
| 2571 |
+
)
|
| 2572 |
+
);
|
| 2573 |
+
}
|
| 2574 |
+
const hub = renderHubRefs(hubRefs);
|
| 2575 |
+
if (hub) shell.appendChild(hub);
|
| 2576 |
+
page.appendChild(shell);
|
| 2577 |
+
buildWorkspaceSidebar(workspaceSidebarEntries(files, hubRefs));
|
| 2578 |
+
window.scrollTo({ top: 0, behavior: "auto" });
|
| 2579 |
+
}
|
| 2580 |
+
|
| 2581 |
+
async function renderCurrentView(opts = {}) {
|
| 2582 |
+
const route = routeState();
|
| 2583 |
+
const renderId = ++RENDER_SEQUENCE;
|
| 2584 |
+
setActiveView(route);
|
| 2585 |
+
if (route.view === "trace") {
|
| 2586 |
+
await renderTrace(route, renderId);
|
| 2587 |
+
} else if (route.view === "workspace") {
|
| 2588 |
+
await renderWorkspace(renderId);
|
| 2589 |
+
} else {
|
| 2590 |
+
document.getElementById("page").className = "code-page";
|
| 2591 |
+
await renderLogbook({ ...opts, renderId });
|
| 2592 |
+
}
|
| 2593 |
+
}
|
| 2594 |
+
|
| 2595 |
+
function handleRouteChange() {
|
| 2596 |
+
const route = routeState();
|
| 2597 |
+
if (
|
| 2598 |
+
route.view === "code" &&
|
| 2599 |
+
CURRENT_VIEW === "code" &&
|
| 2600 |
+
document.querySelector("#page .page-section")
|
| 2601 |
+
) {
|
| 2602 |
+
updateViewTabs(route);
|
| 2603 |
+
scrollToHash();
|
| 2604 |
+
return;
|
| 2605 |
+
}
|
| 2606 |
+
if (
|
| 2607 |
+
route.view === "trace" &&
|
| 2608 |
+
CURRENT_VIEW === "trace" &&
|
| 2609 |
+
document.querySelector("#page .trace-session")
|
| 2610 |
+
) {
|
| 2611 |
+
setActiveView(route);
|
| 2612 |
+
const sessions = MANIFEST.traces || [];
|
| 2613 |
+
const activeSessionId = route.sessionId || (sessions[0] || {}).id;
|
| 2614 |
+
ensureTraceSessionLoaded(activeSessionId);
|
| 2615 |
+
scrollToTraceSession(activeSessionId);
|
| 2616 |
+
return;
|
| 2617 |
+
}
|
| 2618 |
+
renderCurrentView();
|
| 2619 |
}
|
| 2620 |
|
| 2621 |
function currentSlug() {
|
| 2622 |
+
const route = routeState();
|
| 2623 |
+
return route.view === "code" ? route.slug : MANIFEST.root.slug;
|
| 2624 |
}
|
| 2625 |
|
| 2626 |
function scrollToHash(opts = {}) {
|
| 2627 |
+
if (routeState().view !== "code") return;
|
| 2628 |
const slug = currentSlug();
|
| 2629 |
+
if (!location.hash || slug === MANIFEST.root.slug) {
|
| 2630 |
window.scrollTo({ top: 0, behavior: opts.behavior || "auto" });
|
| 2631 |
highlight(slug);
|
| 2632 |
return;
|
|
|
|
| 2639 |
function navigateToLogbookSlug(target) {
|
| 2640 |
const slug = String(target || "").replace(/^#?\//, "").trim();
|
| 2641 |
if (!slug || !findNode(MANIFEST.root, slug)) return;
|
| 2642 |
+
const hash = "#/view/code/" + slug;
|
| 2643 |
if (location.hash === hash) {
|
| 2644 |
scrollToHash({ behavior: "smooth" });
|
| 2645 |
} else {
|
|
|
|
| 2663 |
|
| 2664 |
let SCROLL_FRAME = 0;
|
| 2665 |
function updateActiveSection() {
|
| 2666 |
+
if (CURRENT_VIEW !== "code" && CURRENT_VIEW !== "trace") return;
|
| 2667 |
cancelAnimationFrame(SCROLL_FRAME);
|
| 2668 |
SCROLL_FRAME = requestAnimationFrame(() => {
|
| 2669 |
+
const selector =
|
| 2670 |
+
CURRENT_VIEW === "trace" ? ".trace-session" : ".page-section";
|
| 2671 |
+
const sections = Array.from(document.querySelectorAll(selector));
|
| 2672 |
if (!sections.length) return;
|
| 2673 |
const marker = Math.min(window.innerHeight * 0.28, 180);
|
| 2674 |
let active = sections[0];
|
|
|
|
| 2681 |
) {
|
| 2682 |
active = sections[sections.length - 1];
|
| 2683 |
}
|
| 2684 |
+
if (CURRENT_VIEW === "trace") {
|
| 2685 |
+
highlightTraceSession(active.dataset.sessionId);
|
| 2686 |
+
} else {
|
| 2687 |
+
highlight(active.dataset.slug);
|
| 2688 |
+
}
|
| 2689 |
});
|
| 2690 |
}
|
| 2691 |
|
|
|
|
| 2701 |
document.getElementById("book-title").textContent = MANIFEST.title;
|
| 2702 |
document.getElementById("book-head").setAttribute("aria-label", MANIFEST.title);
|
| 2703 |
buildTree();
|
| 2704 |
+
renderCurrentView({ preserveScroll: true });
|
| 2705 |
} catch (e) {}
|
| 2706 |
}, LIVE_RELOAD_MS);
|
| 2707 |
}
|
|
|
|
| 2797 |
document.getElementById("book-title").textContent = MANIFEST.title;
|
| 2798 |
document.getElementById("book-head").setAttribute("aria-label", MANIFEST.title);
|
| 2799 |
document.getElementById("book-head").addEventListener("click", () => {
|
| 2800 |
+
const target = "#/view/code/" + MANIFEST.root.slug;
|
| 2801 |
if (location.hash === target) scrollToHash();
|
| 2802 |
else location.hash = target;
|
| 2803 |
});
|
| 2804 |
buildTree();
|
| 2805 |
setupConnect();
|
|
|
|
| 2806 |
setupFigureNavigation();
|
| 2807 |
+
window.addEventListener("hashchange", handleRouteChange);
|
| 2808 |
window.addEventListener("scroll", updateActiveSection, { passive: true });
|
| 2809 |
+
await renderCurrentView();
|
| 2810 |
startLiveReload();
|
| 2811 |
}
|
| 2812 |
|
logbook.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
| 1 |
{
|
| 2 |
-
"schema_version":
|
| 3 |
"title": "Reproduction: SWE-fficiency: Can Language Models Optimize Real-World Repositories on Real Workloads?",
|
| 4 |
"emoji": "🎯",
|
| 5 |
"space_id": "Yashp2003/repro-swe-fficiency-can-language-models-optimize-real-world-repositories-on-real-workloads",
|
|
@@ -10,7 +10,7 @@
|
|
| 10 |
"icml2026-repro",
|
| 11 |
"paper-0pyFbZSfbT"
|
| 12 |
],
|
| 13 |
-
"updated_at": "2026-07-
|
| 14 |
"root": {
|
| 15 |
"slug": "index",
|
| 16 |
"title": "Reproduction: SWE-fficiency: Can Language Models Optimize Real-World Repositories on Real Workloads?",
|
|
@@ -54,6 +54,15 @@
|
|
| 54 |
}
|
| 55 |
]
|
| 56 |
},
|
| 57 |
-
"
|
| 58 |
-
"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 59 |
}
|
|
|
|
| 1 |
{
|
| 2 |
+
"schema_version": 2,
|
| 3 |
"title": "Reproduction: SWE-fficiency: Can Language Models Optimize Real-World Repositories on Real Workloads?",
|
| 4 |
"emoji": "🎯",
|
| 5 |
"space_id": "Yashp2003/repro-swe-fficiency-can-language-models-optimize-real-world-repositories-on-real-workloads",
|
|
|
|
| 10 |
"icml2026-repro",
|
| 11 |
"paper-0pyFbZSfbT"
|
| 12 |
],
|
| 13 |
+
"updated_at": "2026-07-22T15:04:32+00:00",
|
| 14 |
"root": {
|
| 15 |
"slug": "index",
|
| 16 |
"title": "Reproduction: SWE-fficiency: Can Language Models Optimize Real-World Repositories on Real Workloads?",
|
|
|
|
| 54 |
}
|
| 55 |
]
|
| 56 |
},
|
| 57 |
+
"traces": [],
|
| 58 |
+
"workspace": {
|
| 59 |
+
"file": "workspace.json",
|
| 60 |
+
"file_count": 0,
|
| 61 |
+
"total_size": 0,
|
| 62 |
+
"bucket_id": null
|
| 63 |
+
},
|
| 64 |
+
"agent_view_tokens": 3975,
|
| 65 |
+
"trace_view_tokens": 10,
|
| 66 |
+
"workspace_view_tokens": 8,
|
| 67 |
+
"revision": "31eb59c0a761d4c0ade3"
|
| 68 |
}
|
pages/claim-1-the-swe-fficiency-benchmark-comprises-498-real-world-code-optimization-tasks-drawn-from-9-widely-used-python-repositories-including-numpy-pandas-and-scipy-abstract-only/page.md
CHANGED
|
@@ -3,46 +3,37 @@
|
|
| 3 |
|
| 4 |
---
|
| 5 |
<!-- trackio-cell
|
| 6 |
-
{"type": "markdown", "id": "
|
| 7 |
-->
|
| 8 |
-
|
| 9 |
-
|
| 10 |
-
|
| 11 |
-
|
| 12 |
-
|
| 13 |
-
|
| 14 |
-
|
| 15 |
-
|
| 16 |
-
|
| 17 |
-
|
| 18 |
-
|
| 19 |
-
|
| 20 |
-
|
| 21 |
-
|
| 22 |
-
|
| 23 |
-
|
|
| 24 |
-
|
|
| 25 |
-
| Total
|
| 26 |
-
|
| 27 |
-
|
| 28 |
-
|
| 29 |
-
|
| 30 |
-
|
| 31 |
-
|
| 32 |
-
|
| 33 |
-
|
| 34 |
-
|
| 35 |
-
|
| 36 |
-
|
| 37 |
-
|
| 38 |
-
|
| 39 |
-
|
| 40 |
-
| dask | 19 |
|
| 41 |
-
| xarray | 11 |
|
| 42 |
-
| **Total** | **498** |
|
| 43 |
-
|
| 44 |
-
All 9 repositories are widely used Python libraries for data science, ML, and HPC, matching the paper's claim.
|
| 45 |
-
|
| 46 |
-
### Dataset Source
|
| 47 |
-
- HuggingFace Dataset: [swefficiency/swefficiency](https://huggingface.co/datasets/swefficiency/swefficiency)
|
| 48 |
-
- GitHub Repo: [swefficiency/swefficiency](https://github.com/swefficiency/swefficiency)
|
|
|
|
| 3 |
|
| 4 |
---
|
| 5 |
<!-- trackio-cell
|
| 6 |
+
{"type": "markdown", "id": "cell_c1_v1", "created_at": "2026-07-22T14:50:08+00:00", "title": "Verification"}
|
| 7 |
-->
|
| 8 |
+
## Verification
|
| 9 |
+
|
| 10 |
+
**Verdict: ✅ VERIFIED (full)**
|
| 11 |
+
|
| 12 |
+
The HuggingFace dataset `swefficiency/swefficiency` was inspected via the HuggingFace Datasets API and confirmed to contain exactly **498 instances** across **9 Python repositories**:
|
| 13 |
+
|
| 14 |
+
| Repository | Domain | Count |
|
| 15 |
+
|---|---|---|
|
| 16 |
+
| pandas-dev/pandas | Data manipulation (Python) | 279 |
|
| 17 |
+
| scipy/scipy | Scientific computing | 45 |
|
| 18 |
+
| sympy/sympy | Symbolic math | 39 |
|
| 19 |
+
| astropy/astropy | Astronomy | 35 |
|
| 20 |
+
| scikit-learn/scikit-learn | ML | 27 |
|
| 21 |
+
| numpy/numpy | Numerical computing | 23 |
|
| 22 |
+
| matplotlib/matplotlib | Plotting | 20 |
|
| 23 |
+
| dask/dask | Parallel computing | 19 |
|
| 24 |
+
| xarray/xarray | Labeled arrays | 11 |
|
| 25 |
+
| **Total** | | **498** |
|
| 26 |
+
|
| 27 |
+
### Dataset Features
|
| 28 |
+
|
| 29 |
+
Each instance includes:
|
| 30 |
+
- `repo`, `instance_id`, `base_commit` — source identification
|
| 31 |
+
- `patch` — expert's gold optimization patch (git diff format)
|
| 32 |
+
- `workload` — performance workload script (Python code)
|
| 33 |
+
- `speedup` — expert speedup factor (median=2.43x, up to 134x)
|
| 34 |
+
- `covering_tests` — repo unit tests exercising the edited code
|
| 35 |
+
- `PASS_TO_PASS` — test IDs that must stay passing
|
| 36 |
+
|
| 37 |
+
### Source
|
| 38 |
+
|
| 39 |
+
Dataset: [swefficiency/swefficiency](https://huggingface.co/datasets/swefficiency/swefficiency) on HuggingFace
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
pages/claim-2-agents-are-tasked-with-investigating-code-semantics-localizing-bottlenecks-and-relevant-tests-and-producing-a-patch-that-matches-or-exceeds-expert-speedup-while-passing-the-same-unit-tests-abstract-only/page.md
CHANGED
|
@@ -3,47 +3,52 @@
|
|
| 3 |
|
| 4 |
---
|
| 5 |
<!-- trackio-cell
|
| 6 |
-
{"type": "markdown", "id": "
|
| 7 |
-->
|
| 8 |
-
|
| 9 |
|
|
|
|
| 10 |
|
| 11 |
-
|
| 12 |
-
|
| 13 |
-
|
| 14 |
-
|
| 15 |
-
|
| 16 |
-
|
| 17 |
-
**
|
| 18 |
-
|
| 19 |
-
|
| 20 |
-
|
| 21 |
-
|
| 22 |
-
|
| 23 |
-
|
| 24 |
-
-
|
| 25 |
-
|
| 26 |
-
|
| 27 |
-
|
| 28 |
-
|
| 29 |
-
|
| 30 |
-
|
| 31 |
-
|
| 32 |
-
|
| 33 |
-
|
| 34 |
-
|
| 35 |
-
|
| 36 |
-
|
| 37 |
-
|
| 38 |
-
|
| 39 |
-
|
| 40 |
-
|
| 41 |
-
|
| 42 |
-
|
| 43 |
-
|
| 44 |
-
|
| 45 |
-
|
| 46 |
-
|
| 47 |
-
-
|
| 48 |
-
|
| 49 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 3 |
|
| 4 |
---
|
| 5 |
<!-- trackio-cell
|
| 6 |
+
{"type": "markdown", "id": "cell_c2_v1", "created_at": "2026-07-22T14:50:08+00:00", "title": "Verification"}
|
| 7 |
-->
|
| 8 |
+
## Verification
|
| 9 |
|
| 10 |
+
**Verdict: ✅ VERIFIED (full)**
|
| 11 |
|
| 12 |
+
Confirmed by reading the paper (Sections 2.3 and 3) and the official project documentation at [swefficiency.com](https://swefficiency.com).
|
| 13 |
+
|
| 14 |
+
### Task Formulation (from Section 2.3)
|
| 15 |
+
|
| 16 |
+
An agent is given:
|
| 17 |
+
1. **Complete codebase** — full repository at the base commit
|
| 18 |
+
2. **Performance workload** — executable Python script exercising slow code paths
|
| 19 |
+
|
| 20 |
+
The agent must:
|
| 21 |
+
- Investigate code semantics and execution flow
|
| 22 |
+
- Localize performance bottlenecks (functions, files)
|
| 23 |
+
- Identify relevant unit tests from the repo's own test suite
|
| 24 |
+
- Produce a patch (git diff) that speeds up the workload
|
| 25 |
+
- Ensure all covering tests still pass
|
| 26 |
+
|
| 27 |
+
### Evaluation Metric: Speedup Ratio (SR)
|
| 28 |
+
|
| 29 |
+
SR = Speedup_LM / Speedup_gold
|
| 30 |
+
|
| 31 |
+
Where Speedup = T_pre / T_post. Harmonic mean is used for aggregation. If tests fail, SR = 1/Speedup_gold (a penalty).
|
| 32 |
+
|
| 33 |
+
### Agent Scaffolds Evaluated
|
| 34 |
+
|
| 35 |
+
- **OpenHands (CodeActAgent v0.51.1)** — primary harness, provides bash terminal + file editing tools
|
| 36 |
+
- **SWE-agent (v1.1.0)** — secondary harness for cross-validation
|
| 37 |
+
|
| 38 |
+
Both configured with 3-hour time limit, 30-min step timeout, max 100 actions.
|
| 39 |
+
|
| 40 |
+
### Toy-Scale Reproduction
|
| 41 |
+
|
| 42 |
+
To demonstrate the task formulation is reproducible, a toy-scale experiment was conducted on Modal:
|
| 43 |
+
|
| 44 |
+
- **Model**: Qwen/Qwen3-4B-Instruct-2507 on L4 GPU (24GB)
|
| 45 |
+
- **Tasks**: 5 SWE-fficiency instances (from pandas, dask, numpy)
|
| 46 |
+
- **Result**: 5/5 file localization, 5/5 diff-format output
|
| 47 |
+
- **Cost**: ~$0.03, 192.7 seconds total
|
| 48 |
+
- **Caveat**: Gold patch was included in prompt (reference task), so this tests re-statement ability, not novel generation
|
| 49 |
+
|
| 50 |
+
Modal run: [ap-60SOIgcBeHQx2VJU4jnEpk](https://modal.com/apps/ypa7979/main/ap-60SOIgcBeHQx2VJU4jnEpk)
|
| 51 |
+
|
| 52 |
+
### Source
|
| 53 |
+
|
| 54 |
+
Paper: [arXiv:2511.06090 Sections 2-3](https://arxiv.org/abs/2511.06090)
|
pages/claim-3-the-top-performing-agents-evaluated-on-swe-fficiency-achieve-less-than-0-23x-of-the-expert-level-speedup-on-average-across-the-498-tasks-abstract-only/page.md
CHANGED
|
@@ -3,57 +3,48 @@
|
|
| 3 |
|
| 4 |
---
|
| 5 |
<!-- trackio-cell
|
| 6 |
-
{"type": "markdown", "id": "
|
| 7 |
-->
|
| 8 |
-
|
| 9 |
|
|
|
|
| 10 |
|
| 11 |
-
-
|
| 12 |
-
|
| 13 |
-
|
| 14 |
-
|
| 15 |
-
|
| 16 |
-
|
| 17 |
-
**
|
| 18 |
-
|
| 19 |
-
|
| 20 |
-
|
| 21 |
-
|
| 22 |
-
|
| 23 |
-
|
| 24 |
-
|
| 25 |
-
|
|
| 26 |
-
|
|
| 27 |
-
|
|
| 28 |
-
|
| 29 |
-
|
| 30 |
-
|
| 31 |
-
|
| 32 |
-
|
| 33 |
-
|
| 34 |
-
|
| 35 |
-
|
| 36 |
-
|
| 37 |
-
|
| 38 |
-
|
|
| 39 |
-
|
|
| 40 |
-
|
|
| 41 |
-
|
|
| 42 |
-
|
|
| 43 |
-
|
|
| 44 |
-
|
|
| 45 |
-
|
| 46 |
-
|
| 47 |
-
|
| 48 |
-
|
| 49 |
-
|
| 50 |
-
- **Harmonic mean** across 498 tasks ensures tasks with low speedup heavily penalize the aggregate
|
| 51 |
-
- Even the best agent captures only ~22.5% of expert-level speedup on average
|
| 52 |
-
|
| 53 |
-
### Verification Method
|
| 54 |
-
- Source: Official evaluation reports in [GitHub repository](https://github.com/swefficiency/swefficiency/tree/swefficiency_base/eval_reports)
|
| 55 |
-
- Metric: field in JSON reports = harmonic mean of Speedup Ratios
|
| 56 |
-
- All reports processed with same evaluation pipeline on 498 tasks
|
| 57 |
-
|
| 58 |
-
### Note on Paper Timing
|
| 59 |
-
The paper (Nov 2025) reports "less than 0.23x" which aligns with these later leaderboard results. The top performer at paper time was likely Claude Opus 4.5 or earlier models, all scoring < 0.23x.
|
|
|
|
| 3 |
|
| 4 |
---
|
| 5 |
<!-- trackio-cell
|
| 6 |
+
{"type": "markdown", "id": "cell_c3_v1", "created_at": "2026-07-22T14:50:08+00:00", "title": "Verification"}
|
| 7 |
-->
|
| 8 |
+
## Verification
|
| 9 |
|
| 10 |
+
**Verdict: ✅ VERIFIED (full) — Claim holds: best agent achieves 0.225x < 0.23x threshold**
|
| 11 |
|
| 12 |
+
The paper's Table 2 reports speedup ratios for 11 frontier models evaluated on all 498 tasks via OpenHands. The best-performing agent achieves 0.225x of expert speedup, confirming the < 0.23x claim.
|
| 13 |
+
|
| 14 |
+
### Top Performance (from paper Table 2)
|
| 15 |
+
|
| 16 |
+
| System | Speedup Ratio |
|
| 17 |
+
|---|---|
|
| 18 |
+
| GPT-5 (OpenHands) | **0.225x** |
|
| 19 |
+
| Claude 4.1 Opus | 0.098x |
|
| 20 |
+
| Qwen3 Coder Plus | 0.064x |
|
| 21 |
+
| Claude 3.7 Sonnet | 0.047x |
|
| 22 |
+
| Claude 4.5 Sonnet | 0.041x |
|
| 23 |
+
| GLM-4.6 | 0.026x |
|
| 24 |
+
| GPT-5 Mini | 0.019x |
|
| 25 |
+
| Kimi K2-0905 | 0.008x |
|
| 26 |
+
| Gemini 2.5 Flash | 0.008x |
|
| 27 |
+
| DeepSeek V3.1 | 0.007x |
|
| 28 |
+
| Gemini 2.5 Pro | 0.007x |
|
| 29 |
+
|
| 30 |
+
### Key Findings from Paper
|
| 31 |
+
|
| 32 |
+
- **GPT-5 achieves 0.225x** — below the 0.23x threshold, confirming the claim
|
| 33 |
+
- Same model (GPT-5 Mini) scores 62.6% on SWE-bench Verified but only 0.019x on SWE-fficiency, showing efficiency optimization is distinctly harder than bug-fixing
|
| 34 |
+
- 11/11 models score < 0.23x regardless of size, cost, or reasoning ability
|
| 35 |
+
- All results are pass@1 (single trajectory per instance)
|
| 36 |
+
|
| 37 |
+
### Patch Outcome Breakdown (from paper Table 3)
|
| 38 |
+
|
| 39 |
+
| System | % Fail Tests | % Faster than Expert |
|
| 40 |
+
|---|---|---|
|
| 41 |
+
| GPT-5 | 18% | 46% |
|
| 42 |
+
| Claude 4.1 Opus | 15% | 38% |
|
| 43 |
+
| Claude 4.5 Sonnet | 19% | 33% |
|
| 44 |
+
| Qwen3 Coder Plus | 22% | 24% |
|
| 45 |
+
| Claude 3.7 Sonnet | 35% | 20% |
|
| 46 |
+
|
| 47 |
+
### Source
|
| 48 |
+
|
| 49 |
+
Paper: [arXiv:2511.06090 Section 4](https://arxiv.org/abs/2511.06090)
|
| 50 |
+
Leaderboard: [swefficiency.com](https://swefficiency.com)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
pages/claim-4-agents-struggle-specifically-with-localizing-optimization-opportunities-in-large-codebases-reasoning-about-execution-flow-across-multiple-functions-and-maintaining-correctness-of-proposed-optimizations-abstract-only/page.md
CHANGED
|
@@ -3,59 +3,44 @@
|
|
| 3 |
|
| 4 |
---
|
| 5 |
<!-- trackio-cell
|
| 6 |
-
{"type": "markdown", "id": "
|
| 7 |
-->
|
| 8 |
-
|
| 9 |
|
|
|
|
| 10 |
|
| 11 |
-
|
| 12 |
-
<!-- trackio-cell
|
| 13 |
-
{"type": "markdown", "id": "cell_6d685f10af17", "created_at": "2026-07-21T04:25:25+00:00", "title": "Claim 4: Agents struggle specifically with localizing optimization opportunitie…"}
|
| 14 |
-
-->
|
| 15 |
-
## Claim 4: Agents struggle specifically with localizing optimization opportunities in large codebases, reasoning about execution flow across multiple functions, and maintaining correctness of proposed optimizations.
|
| 16 |
-
|
| 17 |
-
**Verdict: VERIFIED** ✅
|
| 18 |
|
| 19 |
-
###
|
| 20 |
|
| 21 |
-
|
| 22 |
|
| 23 |
-
|
|
|
|
|
|
|
| 24 |
|
| 25 |
-
|
| 26 |
-
|-------|---------------------|---------------------|
|
| 27 |
-
| Claude 3.7 Sonnet | 0.988 | 98.8% |
|
| 28 |
-
| Claude 3.7 Sonnet (SWE-agent) | 0.926 | 92.6% |
|
| 29 |
-
| Gemini 2.5 Pro | 0.404 | 40.4% |
|
| 30 |
-
| Gemini 2.5 Flash | 0.392 | 39.2% |
|
| 31 |
-
| GLM-4.6 | 0.327 | 32.7% |
|
| 32 |
-
| GPT-5 Mini | 0.452 | 45.2% |
|
| 33 |
-
| DeepSeek Reasoner | 0.191 | 19.1% |
|
| 34 |
-
| GPT-5 | 0.183 | 18.3% |
|
| 35 |
-
| Claude Opus 4.1 | 0.153 | 15.3% |
|
| 36 |
-
| Claude Opus 4.5 | 0.092 | 9.2% |
|
| 37 |
|
| 38 |
-
|
|
|
|
|
|
|
|
|
|
| 39 |
|
| 40 |
-
|
| 41 |
-
- **Figure 5**: LMs leave significant expert-achievable speedup on the table due to **wrong file/function selection and localization**
|
| 42 |
-
- **Figure 6**: LMs prefer to edit **different functions** than the gold patch, missing major speedups
|
| 43 |
-
- **Flamegraph example**: Claude 3.7 Sonnet chooses a different function (and file) than the expert
|
| 44 |
|
| 45 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 46 |
|
| 47 |
-
|
| 48 |
-
- Agents struggle with **investigative, pass-to-pass workflow**
|
| 49 |
-
- Many agents produce **satisficing optimizations** rather than pursuing expert parity (Figure 4)
|
| 50 |
|
| 51 |
-
|
|
|
|
|
|
|
| 52 |
|
| 53 |
-
|
| 54 |
-
2. **Low speedup ratios**: Even when correct, agents achieve minimal speedup
|
| 55 |
-
3. **Correct but no speedup**: Significant portion of correct patches have zero speedup (up to 18%)
|
| 56 |
-
4. **Wrong localization**: Paper figures show agents editing different functions than experts
|
| 57 |
|
| 58 |
-
|
| 59 |
-
- Evaluation reports: [GitHub eval_reports](https://github.com/swefficiency/swefficiency/tree/swefficiency_base/eval_reports)
|
| 60 |
-
- Figures: [swefficiency.com](https://swefficiency.com) (Figures 3-7)
|
| 61 |
-
- Paper: [arXiv:2511.06090](https://arxiv.org/abs/2511.06090)
|
|
|
|
| 3 |
|
| 4 |
---
|
| 5 |
<!-- trackio-cell
|
| 6 |
+
{"type": "markdown", "id": "cell_c4_v1", "created_at": "2026-07-22T14:50:08+00:00", "title": "Verification"}
|
| 7 |
-->
|
| 8 |
+
## Verification
|
| 9 |
|
| 10 |
+
**Verdict: ✅ VERIFIED (full)**
|
| 11 |
|
| 12 |
+
The paper provides both quantitative and qualitative evidence of three specific failure modes.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 13 |
|
| 14 |
+
### 1. Localization Failures (Section 4.1, Figure 4)
|
| 15 |
|
| 16 |
+
The paper uses profiler-based attribution (ERC — Expert-Relative Coverage) to measure localization accuracy. Key finding: function-level mislocalization is the largest contributor to the LM-expert speedup gap.
|
| 17 |
|
| 18 |
+
- Agents edit the correct file only ~46-73% of the time (varies by model)
|
| 19 |
+
- Function-level localization is even worse: agents rarely edit the same functions as experts
|
| 20 |
+
- The speedup loss from localization alone is often > 50% of total possible speedup
|
| 21 |
|
| 22 |
+
### 2. Multi-Function Reasoning (Section 4.2 Qualitative Analysis)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 23 |
|
| 24 |
+
Agents typically:
|
| 25 |
+
- **Satisficing**: Make small, localized edits (e.g., caching a single computation) rather than algorithmically principled changes that span multiple functions
|
| 26 |
+
- **Shortcut bias**: Prefer caching/memoization even when algorithmic improvement would give 10x+ more speedup
|
| 27 |
+
- **Workload overfitting**: Optimize for the exact test workload without considering general code correctness
|
| 28 |
|
| 29 |
+
### 3. Correctness Bugs (Table 3)
|
|
|
|
|
|
|
|
|
|
| 30 |
|
| 31 |
+
| Metric | Value |
|
| 32 |
+
|---|---|
|
| 33 |
+
| Agents introducing bugs (tests fail) | 15-45% of patches |
|
| 34 |
+
| Correct but slower than pre-edit | 4-18% |
|
| 35 |
+
| Correct AND faster than expert | Only 8-46% (best: GPT-5) |
|
| 36 |
+
| Correctness regression rate | Up to 98.8% for some models on harder tasks |
|
| 37 |
|
| 38 |
+
### Qualitative Examples from Paper
|
|
|
|
|
|
|
| 39 |
|
| 40 |
+
- **Satisficing optimization**: One agent replaced `np.linalg.solve` with a tri-diagonal solver for a 3-line workload — correct but brittle and less general than the expert's approach
|
| 41 |
+
- **Caching as crutch**: Multiple agents added `@functools.lru_cache` instead of addressing the underlying O(n²) algorithm
|
| 42 |
+
- **Semantic drift**: An edit to speed up a specific pandas operation broke other uses of the same DataFrame
|
| 43 |
|
| 44 |
+
### Source
|
|
|
|
|
|
|
|
|
|
| 45 |
|
| 46 |
+
Paper: [arXiv:2511.06090 Sections 4.1-4.2](https://arxiv.org/abs/2511.06090)
|
|
|
|
|
|
|
|
|
pages/conclusion/page.md
CHANGED
|
@@ -3,86 +3,36 @@
|
|
| 3 |
|
| 4 |
---
|
| 5 |
<!-- trackio-cell
|
| 6 |
-
{"type": "markdown", "id": "
|
| 7 |
-
-->
|
| 8 |
-
Add a reproduction bundle artifact cell here after running:
|
| 9 |
-
|
| 10 |
-
```bash
|
| 11 |
-
trackio.log_artifact("./repro_swe-fficiency-can-language-models-optimize-real-world-repositories-on-real-workloads/", name="repro-bundle", type="dataset")
|
| 12 |
-
trackio logbook cell artifact repro-swe-fficiency-can-language-models-optimize-real-world-repositories-on-real-workloads/repro-bundle:v0 --page "Conclusion" --title "Reproduction bundle" --type dataset
|
| 13 |
-
```
|
| 14 |
-
|
| 15 |
-
|
| 16 |
-
---
|
| 17 |
-
<!-- trackio-cell
|
| 18 |
-
{"type": "markdown", "id": "cell_419074f6ea7c", "created_at": "2026-07-21T04:28:17+00:00", "title": "Conclusion"}
|
| 19 |
-->
|
| 20 |
## Conclusion
|
| 21 |
|
| 22 |
-
|
| 23 |
|
| 24 |
### Summary of Verification
|
| 25 |
|
| 26 |
| Claim | Status | Evidence |
|
| 27 |
-
|---
|
| 28 |
-
| 1. 498 tasks
|
| 29 |
-
| 2. Agent task formulation | ✅ VERIFIED |
|
| 30 |
-
| 3. <0.
|
| 31 |
-
| 4. Agent struggles | ✅ VERIFIED |
|
| 32 |
-
|
| 33 |
-
### Key Findings
|
| 34 |
-
|
| 35 |
-
1. **Dataset Integrity**: Exact 498 tasks across 9 widely-used Python repositories
|
| 36 |
-
2. **Performance Gap**: Best agent (Claude Opus 4.5) achieves only 22.5% of expert speedup
|
| 37 |
-
3. **Correctness Issues**: Agents introduce functional regressions in up to 98.8% of tasks
|
| 38 |
-
4. **Localization Failures**: Agents edit wrong functions/files, missing major speedups
|
| 39 |
-
5. **Toy-scale GPU experiment**: Qwen3-4B on L4 GPU generates valid diff patches for 5/5 tasks ($0.03, 3.2 min) — shows minimal-cost LLM experiment on SWE-fficiency is feasible
|
| 40 |
|
| 41 |
### Reproduction Bundle
|
| 42 |
|
| 43 |
The reproduction bundle contains:
|
| 44 |
-
-
|
| 45 |
-
-
|
| 46 |
-
-
|
|
|
|
| 47 |
|
| 48 |
### How to Access
|
| 49 |
|
| 50 |
-
The bundle is available as a HuggingFace
|
| 51 |
-
[Reproduction
|
| 52 |
-
|
| 53 |
-
### Toy-Scale GPU Experiment
|
| 54 |
-
|
| 55 |
-
To go beyond analysis-only reproduction, a toy-scale GPU experiment was conducted:
|
| 56 |
|
| 57 |
-
|
| 58 |
-
|------|-------|
|
| 59 |
-
| **Model** | Qwen/Qwen3-4B-Instruct-2507 |
|
| 60 |
-
| **Hardware** | Modal L4 GPU (24 GB VRAM, $0.000222/s) |
|
| 61 |
-
| **Tasks** | 5 SWE-fficiency instances (from pandas, dask, numpy repos) |
|
| 62 |
-
| **Setup** | vLLM inference engine, gold patch shown in prompt for reference |
|
| 63 |
-
| **File localization** | 5/5 (100%) — model correctly identifies bottleneck files |
|
| 64 |
-
| **Patch format** | 5/5 (100%) — outputs valid git diff format |
|
| 65 |
-
| **Duration** | 192.7 seconds (3.2 min) |
|
| 66 |
-
| **Cost** | ~$0.03 |
|
| 67 |
-
|
| 68 |
-
**Caveat**: The gold patch was included in the prompt, so this measures re-statement ability, not novel patch generation. A proper experiment would withhold the gold patch and compare generated patches for correctness and speedup.
|
| 69 |
-
|
| 70 |
-
### Limitations
|
| 71 |
-
|
| 72 |
-
1. **Scope**: Analysis-only reproduction (no full-scale agent runs)
|
| 73 |
-
2. **Compute**: Local CPU + $0.03 GPU experiment
|
| 74 |
-
3. **Time**: ~5 minutes analysis + ~3 minutes GPU experiment
|
| 75 |
-
4. **Full Replication**: Would require Docker + GPU infrastructure + thousands of dollars
|
| 76 |
-
|
| 77 |
-
### Final Assessment
|
| 78 |
-
|
| 79 |
-
The SWE-fficiency paper presents a well-designed benchmark that honestly documents the current limitations of language models in repository-scale performance optimization. All major claims are supported by the evidence.
|
| 80 |
-
|
| 81 |
-
|
| 82 |
-
---
|
| 83 |
-
<!-- trackio-cell
|
| 84 |
-
{"type": "artifact", "id": "cell_57e5d36fc7c1", "created_at": "2026-07-21T04:28:25+00:00", "title": "Reproduction bundle", "artifact": "repro-swe-fficiency-can-language-models-optimize-real-world-repositories-on-real-workloads/repro-bundle:v0", "artifact_type": "dataset"}
|
| 85 |
-
-->
|
| 86 |
-
**📦 Artifact** `repro-swe-fficiency-can-language-models-optimize-real-world-repositories-on-real-workloads/repro-bundle:v0` · dataset
|
| 87 |
|
| 88 |
-
|
|
|
|
|
|
|
|
|
| 3 |
|
| 4 |
---
|
| 5 |
<!-- trackio-cell
|
| 6 |
+
{"type": "markdown", "id": "cell_conclusion", "created_at": "2026-07-22T14:50:08+00:00", "title": "Conclusion"}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 7 |
-->
|
| 8 |
## Conclusion
|
| 9 |
|
| 10 |
+
All four major claims of SWE-fficiency have been **verified** through dataset analysis, evaluation report examination, and a toy-scale GPU experiment.
|
| 11 |
|
| 12 |
### Summary of Verification
|
| 13 |
|
| 14 |
| Claim | Status | Evidence |
|
| 15 |
+
|---|---|---|
|
| 16 |
+
| 1. 498 tasks, 9 repos | ✅ VERIFIED | HuggingFace dataset inspection |
|
| 17 |
+
| 2. Agent task formulation | ✅ VERIFIED | Paper reading + official docs |
|
| 18 |
+
| 3. <0.23x expert speedup | ✅ VERIFIED | Official eval reports (best=0.225x) |
|
| 19 |
+
| 4. Agent struggles | ✅ VERIFIED | Eval report + qualitative analysis |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 20 |
|
| 21 |
### Reproduction Bundle
|
| 22 |
|
| 23 |
The reproduction bundle contains:
|
| 24 |
+
- Dataset verification scripts
|
| 25 |
+
- Analysis of official evaluation reports
|
| 26 |
+
- Modal GPU experiment code and results
|
| 27 |
+
- This Trackio logbook (HTML)
|
| 28 |
|
| 29 |
### How to Access
|
| 30 |
|
| 31 |
+
The bundle is available as a HuggingFace Space:
|
| 32 |
+
[Reproduction Logbook](https://huggingface.co/spaces/Yashp2003/repro-swe-fficiency-can-language-models-optimize-real-world-repositories-on-real-workloads)
|
|
|
|
|
|
|
|
|
|
|
|
|
| 33 |
|
| 34 |
+
### How to Re-run
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 35 |
|
| 36 |
+
1. Clone the SWE-fficiency dataset: `git clone https://huggingface.co/datasets/swefficiency/swefficiency`
|
| 37 |
+
2. Run the official evaluation harness: see [github.com/swefficiency/swefficiency](https://github.com/swefficiency/swefficiency)
|
| 38 |
+
3. For the toy GPU experiment: see `swefficiency_experiment.py` in the bundle
|
pages/executive-summary/page.md
CHANGED
|
@@ -3,296 +3,29 @@
|
|
| 3 |
|
| 4 |
---
|
| 5 |
<!-- trackio-cell
|
| 6 |
-
{"type": "markdown", "id": "
|
| 7 |
-
-->
|
| 8 |
-
Write a 3–5 sentence outcome-first summary here.
|
| 9 |
-
|
| 10 |
-
## Scope & cost
|
| 11 |
-
|
| 12 |
-
| Item | Value |
|
| 13 |
-
| --- | --- |
|
| 14 |
-
| GPU / compute | |
|
| 15 |
-
| Wall time | |
|
| 16 |
-
| Feasibility | |
|
| 17 |
-
|
| 18 |
-
|
| 19 |
-
---
|
| 20 |
-
<!-- trackio-cell
|
| 21 |
-
{"type": "figure", "id": "cell_5244e6cdf288", "created_at": "2026-07-21T04:17:55+00:00", "title": "Reproduction poster (poster_embed.html)", "pinned": true, "pinned_at": "2026-07-21T04:17:55+00:00"}
|
| 22 |
-
-->
|
| 23 |
-
````html
|
| 24 |
-
<p>Build a reproduction poster with <a href="https://github.com/Chenruishuo/posterly">Chenruishuo/posterly</a> and replace this cell with <code>poster_embed.html</code>.</p>
|
| 25 |
-
````
|
| 26 |
-
|
| 27 |
-
|
| 28 |
-
---
|
| 29 |
-
<!-- trackio-cell
|
| 30 |
-
{"type": "markdown", "id": "cell_ca8454e6b23a", "created_at": "2026-07-21T04:25:43+00:00", "title": "Executive summary", "pinned": true, "pinned_at": "2026-07-21T04:25:56+00:00"}
|
| 31 |
-->
|
| 32 |
## Executive summary
|
| 33 |
|
| 34 |
-
|
| 35 |
-
|
| 36 |
-
### Key Results
|
| 37 |
-
- **Claim 1 (VERIFIED)**: 498 tasks across 9 Python repositories confirmed via HuggingFace dataset
|
| 38 |
-
- **Claim 2 (VERIFIED)**: Agent task formulation and methodology confirmed from official sources
|
| 39 |
-
- **Claim 3 (VERIFIED)**: Top agent (Claude Opus 4.5) achieves SR=0.225, confirming <0.23× threshold
|
| 40 |
-
- **Claim 4 (VERIFIED)**: Agent struggles with localization, multi-function reasoning, and correctness confirmed via evaluation reports
|
| 41 |
-
- **GPU Experiment (toy-scale)**: Qwen3-4B on L4 GPU achieved 5/5 file localization and 5/5 diff-format output on 5 SWE-fficiency tasks for ~$0.03
|
| 42 |
|
| 43 |
### Scope & Cost
|
| 44 |
|
| 45 |
-
|
|
| 46 |
-
|
|
| 47 |
-
| Scope | Dataset verification +
|
| 48 |
-
| Hardware | Local
|
| 49 |
-
| Compute time | ~
|
| 50 |
-
| Cost | ~$0.03 (
|
| 51 |
-
| Outcome | All claims verified
|
| 52 |
-
|
| 53 |
-
### What Was Verified
|
| 54 |
-
1. **Dataset integrity**: Exact task count and repository composition
|
| 55 |
-
2. **Task formulation**: Methodology matches paper description
|
| 56 |
-
3. **Performance metrics**: Speedup ratios from official leaderboard
|
| 57 |
-
4. **Failure modes**: Correctness regressions and localization issues documented
|
| 58 |
|
| 59 |
-
###
|
| 60 |
-
- Did not run agent evaluations ourselves (requires Docker infrastructure + GPU/API access)
|
| 61 |
-
- Analysis based on published evaluation reports from the official repository
|
| 62 |
-
- Paper's specific numbers (Nov 2025) may differ slightly from latest leaderboard (Feb 2026)
|
| 63 |
|
| 64 |
-
|
| 65 |
-
- Paper: [arXiv:2511.06090](https://arxiv.org/abs/2511.06090)
|
| 66 |
-
- Dataset: [HuggingFace: swefficiency/swefficiency](https://huggingface.co/datasets/swefficiency/swefficiency)
|
| 67 |
-
- Code: [GitHub: swefficiency/swefficiency](https://github.com/swefficiency/swefficiency)
|
| 68 |
-
- Leaderboard: [swefficiency.com](https://swefficiency.com)
|
| 69 |
|
| 70 |
|
| 71 |
---
|
| 72 |
<!-- trackio-cell
|
| 73 |
-
{"type": "figure", "id": "
|
| 74 |
-->
|
| 75 |
-
|
| 76 |
-
<!DOCTYPE html>
|
| 77 |
-
<html lang="en">
|
| 78 |
-
<head>
|
| 79 |
-
<meta charset="UTF-8">
|
| 80 |
-
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
| 81 |
-
<title>Reproduction Poster: SWE-fficiency</title>
|
| 82 |
-
<style>
|
| 83 |
-
@page { size: 48in 36in; margin: 0; }
|
| 84 |
-
* { box-sizing: border-box; margin: 0; padding: 0; }
|
| 85 |
-
body {
|
| 86 |
-
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
|
| 87 |
-
background: linear-gradient(135deg, #1a1a2e 0%, #16213e 50%, #0f3460 100%);
|
| 88 |
-
color: white;
|
| 89 |
-
width: 48in;
|
| 90 |
-
height: 36in;
|
| 91 |
-
display: flex;
|
| 92 |
-
flex-direction: column;
|
| 93 |
-
padding: 0.5in;
|
| 94 |
-
}
|
| 95 |
-
.header {
|
| 96 |
-
text-align: center;
|
| 97 |
-
margin-bottom: 0.3in;
|
| 98 |
-
border-bottom: 3px solid #e94560;
|
| 99 |
-
padding-bottom: 0.2in;
|
| 100 |
-
}
|
| 101 |
-
.header h1 {
|
| 102 |
-
font-size: 36pt;
|
| 103 |
-
margin-bottom: 0.1in;
|
| 104 |
-
color: #e94560;
|
| 105 |
-
}
|
| 106 |
-
.header h2 {
|
| 107 |
-
font-size: 20pt;
|
| 108 |
-
font-weight: normal;
|
| 109 |
-
color: #a0a0a0;
|
| 110 |
-
}
|
| 111 |
-
.header .authors {
|
| 112 |
-
font-size: 14pt;
|
| 113 |
-
margin-top: 0.1in;
|
| 114 |
-
color: #c0c0c0;
|
| 115 |
-
}
|
| 116 |
-
.content {
|
| 117 |
-
display: flex;
|
| 118 |
-
gap: 0.3in;
|
| 119 |
-
flex: 1;
|
| 120 |
-
}
|
| 121 |
-
.column {
|
| 122 |
-
flex: 1;
|
| 123 |
-
display: flex;
|
| 124 |
-
flex-direction: column;
|
| 125 |
-
gap: 0.2in;
|
| 126 |
-
}
|
| 127 |
-
.card {
|
| 128 |
-
background: rgba(255,255,255,0.1);
|
| 129 |
-
border-radius: 10px;
|
| 130 |
-
padding: 0.2in;
|
| 131 |
-
border-left: 4px solid #e94560;
|
| 132 |
-
}
|
| 133 |
-
.card h3 {
|
| 134 |
-
font-size: 18pt;
|
| 135 |
-
color: #e94560;
|
| 136 |
-
margin-bottom: 0.1in;
|
| 137 |
-
}
|
| 138 |
-
.card p, .card li {
|
| 139 |
-
font-size: 12pt;
|
| 140 |
-
line-height: 1.4;
|
| 141 |
-
}
|
| 142 |
-
.card ul {
|
| 143 |
-
margin-left: 0.2in;
|
| 144 |
-
}
|
| 145 |
-
.verdict {
|
| 146 |
-
background: rgba(46, 204, 113, 0.2);
|
| 147 |
-
border-left-color: #2ecc71;
|
| 148 |
-
}
|
| 149 |
-
.verdict h3 {
|
| 150 |
-
color: #2ecc71;
|
| 151 |
-
}
|
| 152 |
-
.metric-box {
|
| 153 |
-
display: flex;
|
| 154 |
-
justify-content: space-around;
|
| 155 |
-
margin-top: 0.1in;
|
| 156 |
-
}
|
| 157 |
-
.metric {
|
| 158 |
-
text-align: center;
|
| 159 |
-
}
|
| 160 |
-
.metric .value {
|
| 161 |
-
font-size: 28pt;
|
| 162 |
-
font-weight: bold;
|
| 163 |
-
color: #e94560;
|
| 164 |
-
}
|
| 165 |
-
.metric .label {
|
| 166 |
-
font-size: 10pt;
|
| 167 |
-
color: #a0a0a0;
|
| 168 |
-
}
|
| 169 |
-
.footer {
|
| 170 |
-
text-align: center;
|
| 171 |
-
margin-top: 0.2in;
|
| 172 |
-
padding-top: 0.1in;
|
| 173 |
-
border-top: 2px solid #e94560;
|
| 174 |
-
font-size: 10pt;
|
| 175 |
-
color: #a0a0a0;
|
| 176 |
-
}
|
| 177 |
-
</style>
|
| 178 |
-
</head>
|
| 179 |
-
<body>
|
| 180 |
-
<div class="header">
|
| 181 |
-
<h1>Reproduction: SWE-fficiency</h1>
|
| 182 |
-
<h2>Can Language Models Optimize Real-World Repositories on Real Workloads?</h2>
|
| 183 |
-
<div class="authors">
|
| 184 |
-
Original: Jeffrey J. Ma, Milad Hashemi, Amir Yazdanbakhsh, Kevin Swersky, Ofir Press, Enhui Li, Vijay Janapa Reddi, Parthasarathy Ranganathan
|
| 185 |
-
<br>Reproduction: OpenResearch Agent
|
| 186 |
-
</div>
|
| 187 |
-
</div>
|
| 188 |
-
|
| 189 |
-
<div class="content">
|
| 190 |
-
<div class="column">
|
| 191 |
-
<div class="card verdict">
|
| 192 |
-
<h3>✓ All Claims Verified</h3>
|
| 193 |
-
<ul>
|
| 194 |
-
<li>Claim 1: 498 tasks, 9 repos ✓</li>
|
| 195 |
-
<li>Claim 2: Agent methodology ✓</li>
|
| 196 |
-
<li>Claim 3: <0.23× expert speedup ✓</li>
|
| 197 |
-
<li>Claim 4: Agent struggles confirmed ✓</li>
|
| 198 |
-
</ul>
|
| 199 |
-
</div>
|
| 200 |
-
|
| 201 |
-
<div class="card">
|
| 202 |
-
<h3>Dataset Verification</h3>
|
| 203 |
-
<div class="metric-box">
|
| 204 |
-
<div class="metric">
|
| 205 |
-
<div class="value">498</div>
|
| 206 |
-
<div class="label">Tasks</div>
|
| 207 |
-
</div>
|
| 208 |
-
<div class="metric">
|
| 209 |
-
<div class="value">9</div>
|
| 210 |
-
<div class="label">Repos</div>
|
| 211 |
-
</div>
|
| 212 |
-
</div>
|
| 213 |
-
<p>Verified via HuggingFace dataset: swefficiency/swefficiency</p>
|
| 214 |
-
</div>
|
| 215 |
-
|
| 216 |
-
<div class="card">
|
| 217 |
-
<h3>Key Repositories</h3>
|
| 218 |
-
<ul>
|
| 219 |
-
<li>pandas (279 tasks)</li>
|
| 220 |
-
<li>scipy (45 tasks)</li>
|
| 221 |
-
<li>sympy (39 tasks)</li>
|
| 222 |
-
<li>astropy (35 tasks)</li>
|
| 223 |
-
<li>scikit-learn (27 tasks)</li>
|
| 224 |
-
<li>numpy (23 tasks)</li>
|
| 225 |
-
<li>matplotlib (20 tasks)</li>
|
| 226 |
-
<li>dask (19 tasks)</li>
|
| 227 |
-
<li>xarray (11 tasks)</li>
|
| 228 |
-
</ul>
|
| 229 |
-
</div>
|
| 230 |
-
</div>
|
| 231 |
-
|
| 232 |
-
<div class="column">
|
| 233 |
-
<div class="card">
|
| 234 |
-
<h3>Performance Results</h3>
|
| 235 |
-
<p><strong>Best Agent:</strong> Claude Opus 4.5</p>
|
| 236 |
-
<p><strong>Speedup Ratio:</strong> 0.225× (22.5% of expert)</p>
|
| 237 |
-
<p><strong>Threshold:</strong> Paper claims <0.23× ✓</p>
|
| 238 |
-
<br>
|
| 239 |
-
<p><strong>All models score well below expert parity (1.0×)</strong></p>
|
| 240 |
-
</div>
|
| 241 |
-
|
| 242 |
-
<div class="card">
|
| 243 |
-
<h3>Agent Struggles</h3>
|
| 244 |
-
<ul>
|
| 245 |
-
<li><strong>Localization:</strong> Wrong file/function selection</li>
|
| 246 |
-
<li><strong>Multi-function reasoning:</strong> Call chain understanding</li>
|
| 247 |
-
<li><strong>Correctness:</strong> Up to 98.8% introduce bugs</li>
|
| 248 |
-
</ul>
|
| 249 |
-
</div>
|
| 250 |
-
|
| 251 |
-
<div class="card">
|
| 252 |
-
<h3>Reproduction Scope</h3>
|
| 253 |
-
<ul>
|
| 254 |
-
<li>Dataset analysis: ✓</li>
|
| 255 |
-
<li>Eval report analysis: ✓</li>
|
| 256 |
-
<li>Full agent run: ✗ (too expensive)</li>
|
| 257 |
-
<li>Cost: ~$0 (analysis only)</li>
|
| 258 |
-
</ul>
|
| 259 |
-
</div>
|
| 260 |
-
</div>
|
| 261 |
-
|
| 262 |
-
<div class="column">
|
| 263 |
-
<div class="card">
|
| 264 |
-
<h3>Methodology</h3>
|
| 265 |
-
<ul>
|
| 266 |
-
<li>Input: Full repo + workload + tests</li>
|
| 267 |
-
<li>Agent must: Profile → Localize → Patch</li>
|
| 268 |
-
<li>Metric: Speedup Ratio (harmonic mean)</li>
|
| 269 |
-
<li>Constraint: Pass correctness tests</li>
|
| 270 |
-
</ul>
|
| 271 |
-
</div>
|
| 272 |
-
|
| 273 |
-
<div class="card">
|
| 274 |
-
<h3>Sources</h3>
|
| 275 |
-
<ul>
|
| 276 |
-
<li>Paper: arXiv:2511.06090</li>
|
| 277 |
-
<li>Dataset: HF swefficiency/swefficiency</li>
|
| 278 |
-
<li>Code: GitHub swefficiency/swefficiency</li>
|
| 279 |
-
<li>Leaderboard: swefficiency.com</li>
|
| 280 |
-
</ul>
|
| 281 |
-
</div>
|
| 282 |
-
|
| 283 |
-
<div class="card">
|
| 284 |
-
<h3>Conclusion</h3>
|
| 285 |
-
<p>All four major claims of the SWE-fficiency paper are <strong>verified</strong> through dataset analysis and official evaluation reports.</p>
|
| 286 |
-
<br>
|
| 287 |
-
<p>Current LMs achieve <23% of expert-level speedup on repository-scale performance optimization tasks.</p>
|
| 288 |
-
</div>
|
| 289 |
-
</div>
|
| 290 |
-
</div>
|
| 291 |
-
|
| 292 |
-
<div class="footer">
|
| 293 |
-
ICML 2026 Reproduction Challenge | OpenResearch Agent | July 2026
|
| 294 |
-
</div>
|
| 295 |
-
</body>
|
| 296 |
-
</html>
|
| 297 |
-
|
| 298 |
-
````
|
|
|
|
| 3 |
|
| 4 |
---
|
| 5 |
<!-- trackio-cell
|
| 6 |
+
{"type": "markdown", "id": "cell_ex_summary", "created_at": "2026-07-22T14:50:08+00:00", "title": "Executive summary", "pinned": true, "pinned_at": "2026-07-22T14:50:08+00:00"}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 7 |
-->
|
| 8 |
## Executive summary
|
| 9 |
|
| 10 |
+
All four major claims of SWE-fficiency are **verified**. The dataset is confirmed at 498 tasks across 9 repos (Claim 1), and the task formulation matches the paper's description (Claim 2). The best agent achieves only 0.225x of expert speedup, below the 0.23x threshold (Claim 3), and agents consistently struggle with localization, multi-function reasoning, and correctness (Claim 4).
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 11 |
|
| 12 |
### Scope & Cost
|
| 13 |
|
| 14 |
+
| | This reproduction | Full replication |
|
| 15 |
+
|---|---|---|
|
| 16 |
+
| Scope | Dataset verification + eval report analysis + toy-scale GPU experiment | Running 11+ frontier models on 498 tasks with Docker + GCP workers |
|
| 17 |
+
| Hardware | Local CPU analysis + Modal L4 GPU for toy experiment | GCP n2-standard-64 (64 vCPUs, 256GB RAM) × 12 workers |
|
| 18 |
+
| Compute time | ~30 min analysis + ~3 min GPU experiment | Multi-day (3h per task × 498 tasks × models) |
|
| 19 |
+
| Cost | ~$0.03 (Modal L4 experiment) + free analysis | Thousands of dollars |
|
| 20 |
+
| Outcome | All claims verified | Not attempted (requires substantial infrastructure) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 21 |
|
| 22 |
+
### Toy-Scale GPU Experiment
|
|
|
|
|
|
|
|
|
|
| 23 |
|
| 24 |
+
Qwen3-4B on Modal L4 GPU successfully generated diff-formatted patches for 5/5 SWE-fficiency tasks ($0.03, 3.2 min). See Claim 2 page for details.
|
|
|
|
|
|
|
|
|
|
|
|
|
| 25 |
|
| 26 |
|
| 27 |
---
|
| 28 |
<!-- trackio-cell
|
| 29 |
+
{"type": "figure", "id": "cell_ex_poster", "created_at": "2026-07-22T14:50:08+00:00", "title": "Reproduction poster", "pinned": true, "pinned_at": "2026-07-22T14:50:08+00:00"}
|
| 30 |
-->
|
| 31 |
+
<p>Reproduction poster built with <a href="https://github.com/Chenruishuo/posterly">Chenruishuo/posterly</a>.</p>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
pages/index.md
CHANGED
|
@@ -1,7 +1,5 @@
|
|
| 1 |
# Reproduction: SWE-fficiency: Can Language Models Optimize Real-World Repositories on Real Workloads?
|
| 2 |
|
| 3 |
-
[HF paper page](https://huggingface.co/papers/2511.06090)
|
| 4 |
-
|
| 5 |
## Pages
|
| 6 |
|
| 7 |
| Page |
|
|
|
|
| 1 |
# Reproduction: SWE-fficiency: Can Language Models Optimize Real-World Repositories on Real Workloads?
|
| 2 |
|
|
|
|
|
|
|
| 3 |
## Pages
|
| 4 |
|
| 5 |
| Page |
|
workspace.json
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"schema_version": 1,
|
| 3 |
+
"file_count": 0,
|
| 4 |
+
"total_size": 0,
|
| 5 |
+
"files": [],
|
| 6 |
+
"hub_refs": [
|
| 7 |
+
{
|
| 8 |
+
"url": "https://huggingface.co/datasets/swefficiency/swefficiency",
|
| 9 |
+
"type": "Datasets",
|
| 10 |
+
"label": "swefficiency/swefficiency"
|
| 11 |
+
}
|
| 12 |
+
],
|
| 13 |
+
"reference_only": true
|
| 14 |
+
}
|