@tangle-network/agent-eval 0.120.0 → 0.120.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (171) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/package.json +1 -1
  3. package/dist/analyst/index.d.ts +0 -3111
  4. package/dist/analyst/index.js +0 -403
  5. package/dist/analyst/index.js.map +0 -1
  6. package/dist/authenticity/index.d.ts +0 -161
  7. package/dist/authenticity/index.js +0 -215
  8. package/dist/authenticity/index.js.map +0 -1
  9. package/dist/belief-state/index.d.ts +0 -1301
  10. package/dist/belief-state/index.js +0 -2152
  11. package/dist/belief-state/index.js.map +0 -1
  12. package/dist/benchmarks/index.d.ts +0 -974
  13. package/dist/benchmarks/index.js +0 -60
  14. package/dist/benchmarks/index.js.map +0 -1
  15. package/dist/builder-eval/index.d.ts +0 -695
  16. package/dist/builder-eval/index.js +0 -366
  17. package/dist/builder-eval/index.js.map +0 -1
  18. package/dist/campaign/index.d.ts +0 -7454
  19. package/dist/campaign/index.js +0 -272
  20. package/dist/campaign/index.js.map +0 -1
  21. package/dist/chunk-32BZXMSO.js +0 -3878
  22. package/dist/chunk-32BZXMSO.js.map +0 -1
  23. package/dist/chunk-3A246TSA.js +0 -998
  24. package/dist/chunk-3A246TSA.js.map +0 -1
  25. package/dist/chunk-3RF76KTD.js +0 -84
  26. package/dist/chunk-3RF76KTD.js.map +0 -1
  27. package/dist/chunk-3YYRZDON.js +0 -45
  28. package/dist/chunk-3YYRZDON.js.map +0 -1
  29. package/dist/chunk-4I2E3LLO.js +0 -1030
  30. package/dist/chunk-4I2E3LLO.js.map +0 -1
  31. package/dist/chunk-ARU2PZFM.js +0 -312
  32. package/dist/chunk-ARU2PZFM.js.map +0 -1
  33. package/dist/chunk-BOD4O7OF.js +0 -40
  34. package/dist/chunk-BOD4O7OF.js.map +0 -1
  35. package/dist/chunk-DPZAEKA6.js +0 -880
  36. package/dist/chunk-DPZAEKA6.js.map +0 -1
  37. package/dist/chunk-DTJ6QUQB.js +0 -131
  38. package/dist/chunk-DTJ6QUQB.js.map +0 -1
  39. package/dist/chunk-GGE4NNQT.js +0 -65
  40. package/dist/chunk-GGE4NNQT.js.map +0 -1
  41. package/dist/chunk-H5UD2323.js +0 -286
  42. package/dist/chunk-H5UD2323.js.map +0 -1
  43. package/dist/chunk-HHWE3POT.js +0 -94
  44. package/dist/chunk-HHWE3POT.js.map +0 -1
  45. package/dist/chunk-HKUCJ437.js +0 -787
  46. package/dist/chunk-HKUCJ437.js.map +0 -1
  47. package/dist/chunk-JHCHEVET.js +0 -274
  48. package/dist/chunk-JHCHEVET.js.map +0 -1
  49. package/dist/chunk-JHOJHHU7.js +0 -867
  50. package/dist/chunk-JHOJHHU7.js.map +0 -1
  51. package/dist/chunk-JM2SKQMS.js +0 -750
  52. package/dist/chunk-JM2SKQMS.js.map +0 -1
  53. package/dist/chunk-JN2FCO5W.js +0 -7958
  54. package/dist/chunk-JN2FCO5W.js.map +0 -1
  55. package/dist/chunk-K4DBDHLK.js +0 -158
  56. package/dist/chunk-K4DBDHLK.js.map +0 -1
  57. package/dist/chunk-K6N6XJJX.js +0 -306
  58. package/dist/chunk-K6N6XJJX.js.map +0 -1
  59. package/dist/chunk-MA6HLL3S.js +0 -65
  60. package/dist/chunk-MA6HLL3S.js.map +0 -1
  61. package/dist/chunk-MAZ26DC7.js +0 -99
  62. package/dist/chunk-MAZ26DC7.js.map +0 -1
  63. package/dist/chunk-MOXWMGPC.js +0 -577
  64. package/dist/chunk-MOXWMGPC.js.map +0 -1
  65. package/dist/chunk-NJC7U437.js +0 -626
  66. package/dist/chunk-NJC7U437.js.map +0 -1
  67. package/dist/chunk-NPCTHQIO.js +0 -91
  68. package/dist/chunk-NPCTHQIO.js.map +0 -1
  69. package/dist/chunk-ONWEPEDO.js +0 -57
  70. package/dist/chunk-ONWEPEDO.js.map +0 -1
  71. package/dist/chunk-OYZAPX5G.js +0 -1526
  72. package/dist/chunk-OYZAPX5G.js.map +0 -1
  73. package/dist/chunk-PC4UYEBM.js +0 -166
  74. package/dist/chunk-PC4UYEBM.js.map +0 -1
  75. package/dist/chunk-PICTDURQ.js +0 -766
  76. package/dist/chunk-PICTDURQ.js.map +0 -1
  77. package/dist/chunk-PJQFMIOX.js +0 -1182
  78. package/dist/chunk-PJQFMIOX.js.map +0 -1
  79. package/dist/chunk-PXD6ZFNY.js +0 -1107
  80. package/dist/chunk-PXD6ZFNY.js.map +0 -1
  81. package/dist/chunk-PXE2VKMX.js +0 -140
  82. package/dist/chunk-PXE2VKMX.js.map +0 -1
  83. package/dist/chunk-PZ5AY32C.js +0 -10
  84. package/dist/chunk-PZ5AY32C.js.map +0 -1
  85. package/dist/chunk-QBRSJK47.js +0 -622
  86. package/dist/chunk-QBRSJK47.js.map +0 -1
  87. package/dist/chunk-QWMPPZ3X.js +0 -550
  88. package/dist/chunk-QWMPPZ3X.js.map +0 -1
  89. package/dist/chunk-S3UZOQ5Y.js +0 -328
  90. package/dist/chunk-S3UZOQ5Y.js.map +0 -1
  91. package/dist/chunk-S5TT5R3L.js +0 -2668
  92. package/dist/chunk-S5TT5R3L.js.map +0 -1
  93. package/dist/chunk-T4SQEITX.js +0 -95
  94. package/dist/chunk-T4SQEITX.js.map +0 -1
  95. package/dist/chunk-TT4KNT67.js +0 -124
  96. package/dist/chunk-TT4KNT67.js.map +0 -1
  97. package/dist/chunk-U5CHZ5M3.js +0 -357
  98. package/dist/chunk-U5CHZ5M3.js.map +0 -1
  99. package/dist/chunk-ULOKLHIQ.js +0 -1937
  100. package/dist/chunk-ULOKLHIQ.js.map +0 -1
  101. package/dist/chunk-VI2UW6B6.js +0 -162
  102. package/dist/chunk-VI2UW6B6.js.map +0 -1
  103. package/dist/chunk-VQMK5FMP.js +0 -247
  104. package/dist/chunk-VQMK5FMP.js.map +0 -1
  105. package/dist/chunk-VSMTAMNK.js +0 -53
  106. package/dist/chunk-VSMTAMNK.js.map +0 -1
  107. package/dist/chunk-VZSRQ272.js +0 -149
  108. package/dist/chunk-VZSRQ272.js.map +0 -1
  109. package/dist/chunk-WW2A73HW.js +0 -159
  110. package/dist/chunk-WW2A73HW.js.map +0 -1
  111. package/dist/chunk-X4UCIOTZ.js +0 -136
  112. package/dist/chunk-X4UCIOTZ.js.map +0 -1
  113. package/dist/chunk-XDIRG3TO.js +0 -1266
  114. package/dist/chunk-XDIRG3TO.js.map +0 -1
  115. package/dist/chunk-XJYR7XFV.js +0 -317
  116. package/dist/chunk-XJYR7XFV.js.map +0 -1
  117. package/dist/chunk-ZET2UAYW.js +0 -89
  118. package/dist/chunk-ZET2UAYW.js.map +0 -1
  119. package/dist/chunk-ZZUXHH3R.js +0 -99
  120. package/dist/chunk-ZZUXHH3R.js.map +0 -1
  121. package/dist/cli.d.ts +0 -1
  122. package/dist/cli.js +0 -112
  123. package/dist/cli.js.map +0 -1
  124. package/dist/contract/index.d.ts +0 -4969
  125. package/dist/contract/index.js +0 -1653
  126. package/dist/contract/index.js.map +0 -1
  127. package/dist/control.d.ts +0 -1013
  128. package/dist/control.js +0 -34
  129. package/dist/control.js.map +0 -1
  130. package/dist/fuzz.d.ts +0 -759
  131. package/dist/fuzz.js +0 -714
  132. package/dist/fuzz.js.map +0 -1
  133. package/dist/hosted/index.d.ts +0 -730
  134. package/dist/hosted/index.js +0 -14
  135. package/dist/hosted/index.js.map +0 -1
  136. package/dist/index.d.ts +0 -16780
  137. package/dist/index.js +0 -12168
  138. package/dist/index.js.map +0 -1
  139. package/dist/matrix/index.d.ts +0 -155
  140. package/dist/matrix/index.js +0 -8
  141. package/dist/matrix/index.js.map +0 -1
  142. package/dist/meta-eval/index.d.ts +0 -1030
  143. package/dist/meta-eval/index.js +0 -417
  144. package/dist/meta-eval/index.js.map +0 -1
  145. package/dist/multishot/index.d.ts +0 -579
  146. package/dist/multishot/index.js +0 -589
  147. package/dist/multishot/index.js.map +0 -1
  148. package/dist/openapi.json +0 -992
  149. package/dist/pipelines/index.d.ts +0 -567
  150. package/dist/pipelines/index.js +0 -515
  151. package/dist/pipelines/index.js.map +0 -1
  152. package/dist/reporting.d.ts +0 -1277
  153. package/dist/reporting.js +0 -48
  154. package/dist/reporting.js.map +0 -1
  155. package/dist/rl.d.ts +0 -4092
  156. package/dist/rl.js +0 -1724
  157. package/dist/rl.js.map +0 -1
  158. package/dist/run-campaign-HNFPJET4.js +0 -14
  159. package/dist/run-campaign-HNFPJET4.js.map +0 -1
  160. package/dist/storyboard/index.d.ts +0 -279
  161. package/dist/storyboard/index.js +0 -767
  162. package/dist/storyboard/index.js.map +0 -1
  163. package/dist/trace-attributes.d.ts +0 -52
  164. package/dist/trace-attributes.js +0 -62
  165. package/dist/trace-attributes.js.map +0 -1
  166. package/dist/traces.d.ts +0 -2343
  167. package/dist/traces.js +0 -249
  168. package/dist/traces.js.map +0 -1
  169. package/dist/wire/index.d.ts +0 -1252
  170. package/dist/wire/index.js +0 -81
  171. package/dist/wire/index.js.map +0 -1
@@ -1,767 +0,0 @@
1
- import "../chunk-PZ5AY32C.js";
2
-
3
- // src/storyboard/code-edit.ts
4
- var EDIT_TOOLS = /(edit|write|patch|apply|str_replace|create.*file|save|insert|update.*file|multi_edit)/i;
5
- function languageOf(path) {
6
- const ext = path.includes(".") ? path.split(".").pop()?.toLowerCase() : void 0;
7
- if (!ext) return void 0;
8
- const map = {
9
- ts: "ts",
10
- tsx: "tsx",
11
- js: "js",
12
- jsx: "jsx",
13
- mjs: "js",
14
- cjs: "js",
15
- py: "python",
16
- rs: "rust",
17
- go: "go",
18
- sol: "solidity",
19
- java: "java",
20
- rb: "ruby",
21
- php: "php",
22
- c: "c",
23
- cpp: "cpp",
24
- cs: "csharp",
25
- css: "css",
26
- scss: "scss",
27
- html: "html",
28
- json: "json",
29
- yaml: "yaml",
30
- yml: "yaml",
31
- toml: "toml",
32
- md: "markdown",
33
- sh: "bash",
34
- sql: "sql"
35
- };
36
- return map[ext] ?? ext;
37
- }
38
- function pick(obj, keys) {
39
- if (!obj || typeof obj !== "object") return void 0;
40
- const rec = obj;
41
- for (const k of Object.keys(rec)) {
42
- if (keys.includes(k.toLowerCase())) {
43
- const v = rec[k];
44
- if (typeof v === "string") return v;
45
- }
46
- }
47
- return void 0;
48
- }
49
- function countDiff(diff) {
50
- if (!diff) return { additions: 0, deletions: 0 };
51
- let additions = 0;
52
- let deletions = 0;
53
- for (const line of diff.split("\n")) {
54
- if (line.startsWith("+") && !line.startsWith("+++")) additions++;
55
- else if (line.startsWith("-") && !line.startsWith("---")) deletions++;
56
- }
57
- return { additions, deletions };
58
- }
59
- function codeEditFromSpan(span) {
60
- if (span.kind !== "tool") return void 0;
61
- const tool = span;
62
- if (!EDIT_TOOLS.test(tool.toolName)) return void 0;
63
- const path = pick(tool.args, ["path", "file_path", "filepath", "filename", "file"]);
64
- if (!path) return void 0;
65
- const diff = pick(tool.args, ["diff", "patch"]);
66
- const after = pick(tool.args, ["content", "new_str", "new_string", "newtext", "text", "body"]);
67
- const before = pick(tool.args, ["old_str", "old_string", "oldtext", "original"]);
68
- const counts = countDiff(diff);
69
- return {
70
- spanId: span.spanId,
71
- path,
72
- language: languageOf(path),
73
- diff,
74
- before,
75
- after,
76
- additions: diff ? counts.additions : after ? after.split("\n").length : 0,
77
- deletions: diff ? counts.deletions : 0,
78
- startedAt: span.startedAt
79
- };
80
- }
81
- function extractCodeEdits(spans) {
82
- return spans.map(codeEditFromSpan).filter((e) => e != null).sort((a, b) => a.startedAt - b.startedAt);
83
- }
84
- function codeEditsForStoryboard(storyboard, spans) {
85
- const bySpan = new Map(extractCodeEdits(spans).map((e) => [e.spanId, e]));
86
- const out = [];
87
- for (const scene of storyboard.scenes) {
88
- if (scene.sceneType !== "diff") continue;
89
- const edit = scene.evidenceSpanIds.map((id) => bySpan.get(id)).find((e) => e != null);
90
- if (edit) out.push({ scene, edit });
91
- }
92
- return out;
93
- }
94
- function editAnimationText(edit) {
95
- if (edit.after && edit.after.trim()) return edit.after;
96
- if (edit.diff) {
97
- const added = edit.diff.split("\n").filter((l) => l.startsWith("+") && !l.startsWith("+++")).map((l) => l.slice(1)).join("\n");
98
- if (added.trim()) return added;
99
- }
100
- return `// ${edit.path}
101
- // (${edit.additions} line${edit.additions === 1 ? "" : "s"} written)`;
102
- }
103
- function esc(s) {
104
- return s.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
105
- }
106
- function renderCodeAnimationHtml(source, opts = {}) {
107
- const edits = source.length > 0 && "path" in source[0] ? source : extractCodeEdits(source);
108
- const files = edits.map((e) => ({
109
- path: e.path,
110
- language: e.language ?? "",
111
- additions: e.additions,
112
- deletions: e.deletions,
113
- code: editAnimationText(e)
114
- }));
115
- const title = opts.title ?? "Agent writing code";
116
- const charsPerTick = opts.charsPerTick ?? 4;
117
- const pauseBetweenMs = opts.pauseBetweenMs ?? 900;
118
- const filesJson = JSON.stringify(files);
119
- return `<!doctype html>
120
- <html lang="en">
121
- <head>
122
- <meta charset="utf-8" />
123
- <meta name="viewport" content="width=device-width, initial-scale=1" />
124
- <title>${esc(title)}</title>
125
- <style>
126
- :root { color-scheme: dark; }
127
- * { box-sizing: border-box; }
128
- body { margin: 0; background: #0b0f17; color: #e6edf3;
129
- font: 14px/1.55 ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
130
- display: flex; flex-direction: column; min-height: 100vh; align-items: center; justify-content: center; gap: 14px; }
131
- h1 { font-family: ui-sans-serif, system-ui, sans-serif; font-size: 1rem; font-weight: 600; color: #9aa7b5; margin: 0; }
132
- .editor { width: min(900px, 94vw); background: #0d1320; border: 1px solid #1e2a3a; border-radius: 12px;
133
- overflow: hidden; box-shadow: 0 16px 50px rgba(0,0,0,.5); }
134
- .tabbar { display: flex; align-items: center; gap: 8px; background: #111a29; padding: 9px 14px; border-bottom: 1px solid #1e2a3a; }
135
- .dot { width: 11px; height: 11px; border-radius: 50%; }
136
- .dot.r { background: #ff5f56; } .dot.y { background: #ffbd2e; } .dot.g { background: #27c93f; }
137
- .tab { margin-left: 10px; background: #0d1320; padding: 5px 12px; border-radius: 7px 7px 0 0;
138
- color: #cdd9e5; font-family: ui-sans-serif, system-ui, sans-serif; font-size: .85rem; }
139
- .lang { color: #5b6b7d; font-size: .75rem; margin-left: 6px; }
140
- .adds { margin-left: auto; color: #3fb950; font-size: .78rem; font-family: ui-sans-serif, system-ui, sans-serif; }
141
- .dels { color: #f85149; margin-left: 8px; }
142
- .codewrap { display: flex; max-height: 60vh; overflow: auto; }
143
- .gutter { padding: 14px 10px 14px 14px; text-align: right; color: #3a4757; user-select: none; white-space: pre; }
144
- pre { margin: 0; padding: 14px 18px 14px 6px; white-space: pre; tab-size: 2; flex: 1; }
145
- .cursor { display: inline-block; width: 8px; margin-left: 1px; background: #58a6ff; animation: blink .9s steps(1) infinite; }
146
- @keyframes blink { 50% { opacity: 0; } }
147
- .controls { display: flex; gap: 10px; align-items: center; font-family: ui-sans-serif, system-ui, sans-serif; font-size: .85rem; color: #8b98a6; }
148
- button { background: #1b2636; color: #e6edf3; border: 1px solid #2a3a4f; border-radius: 8px; padding: 6px 12px; cursor: pointer; font: inherit; }
149
- button:hover { background: #243349; }
150
- .empty { padding: 40px; color: #5b6b7d; }
151
- </style>
152
- </head>
153
- <body>
154
- <h1>\u270F\uFE0F ${esc(title)}</h1>
155
- <div class="editor">
156
- <div class="tabbar">
157
- <span class="dot r"></span><span class="dot y"></span><span class="dot g"></span>
158
- <span class="tab" id="tab">\u2014</span><span class="lang" id="lang"></span>
159
- <span class="adds" id="adds"></span>
160
- </div>
161
- <div class="codewrap"><div class="gutter" id="gutter">1</div><pre id="code"></pre></div>
162
- </div>
163
- <div class="controls">
164
- <button id="pp">\u23F8 Pause</button><button id="restart">\u21BB Restart</button>
165
- <span id="counter"></span>
166
- </div>
167
- <script>
168
- const FILES = ${filesJson};
169
- const CPT = ${charsPerTick}, PAUSE = ${pauseBetweenMs};
170
- const codeEl = document.getElementById('code'), gutterEl = document.getElementById('gutter');
171
- const tabEl = document.getElementById('tab'), langEl = document.getElementById('lang');
172
- const addsEl = document.getElementById('adds'), counterEl = document.getElementById('counter');
173
- let fi = 0, ci = 0, playing = true, raf = 0, paused = false;
174
- if (!FILES.length) { codeEl.innerHTML = '<span class="empty">No code edits in this run.</span>'; }
175
- function esc(s){return s.replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;');}
176
- function setHeader(){ const f = FILES[fi]; tabEl.textContent = f.path; langEl.textContent = f.language || '';
177
- addsEl.innerHTML = '+' + f.additions + (f.deletions ? ' <span class="dels">-' + f.deletions + '</span>' : '');
178
- counterEl.textContent = (fi+1) + ' / ' + FILES.length + ' files'; }
179
- function paint(){ const f = FILES[fi]; const shown = f.code.slice(0, ci);
180
- const lines = (shown.match(/\\n/g) || []).length + 1;
181
- gutterEl.textContent = Array.from({length: lines}, (_, k) => k+1).join('\\n');
182
- codeEl.innerHTML = esc(shown) + '<span class="cursor">&nbsp;</span>';
183
- const wrap = codeEl.parentElement; wrap.scrollTop = wrap.scrollHeight; }
184
- function tick(){ if (paused || !FILES.length) return;
185
- const f = FILES[fi];
186
- if (ci < f.code.length){ ci = Math.min(f.code.length, ci + CPT); paint(); raf = requestAnimationFrame(tick); }
187
- else if (fi < FILES.length - 1){ setTimeout(() => { fi++; ci = 0; setHeader(); paint(); raf = requestAnimationFrame(tick); }, PAUSE); }
188
- else { playing = false; document.getElementById('pp').textContent = '\u25B6 Play'; } }
189
- document.getElementById('pp').onclick = () => { if (!playing){ playing = true; paused = false; tick(); } else { paused = !paused; if (!paused) tick(); } document.getElementById('pp').textContent = paused ? '\u25B6 Play' : '\u23F8 Pause'; };
190
- document.getElementById('restart').onclick = () => { fi = 0; ci = 0; playing = true; paused = false; document.getElementById('pp').textContent = '\u23F8 Pause'; setHeader(); paint(); cancelAnimationFrame(raf); tick(); };
191
- if (FILES.length){ setHeader(); paint(); tick(); }
192
- </script>
193
- </body>
194
- </html>
195
- `;
196
- }
197
-
198
- // src/storyboard/index.ts
199
- function str(v) {
200
- return typeof v === "string" && v.length > 0 ? v : void 0;
201
- }
202
- function num(v) {
203
- return typeof v === "number" ? v : void 0;
204
- }
205
- function attr(span, ...keys) {
206
- const a = span.attributes;
207
- if (!a) return void 0;
208
- for (const k of keys) if (a[k] != null) return a[k];
209
- return void 0;
210
- }
211
- function asObj(v) {
212
- return v && typeof v === "object" && !Array.isArray(v) ? v : void 0;
213
- }
214
- function safeJson(v) {
215
- if (v == null) return void 0;
216
- if (typeof v === "string") return v;
217
- try {
218
- return JSON.stringify(v, null, 2);
219
- } catch {
220
- return String(v);
221
- }
222
- }
223
- function isImageSrc(s) {
224
- return !!s && (s.startsWith("data:image") || /^https?:\/\//.test(s));
225
- }
226
- function extractVisual(span) {
227
- const shot = str(attr(span, "screenshot", "screenshotUrl", "image", "frame", "videoFrame")) ?? (span.kind === "tool" ? str(asObj(span.result)?.screenshot) ?? str(asObj(span.result)?.image) : void 0);
228
- if (span.kind === "tool") {
229
- const tn = span.toolName.toLowerCase();
230
- const a = asObj(span.args);
231
- if (/computer|cua|desktop|\bgui\b|xdotool|mouse|keyboard|screen_|pyautogui/.test(tn)) {
232
- return {
233
- type: "browser",
234
- action: str(a?.action) ?? span.toolName,
235
- url: str(a?.target),
236
- screenshot: shot
237
- };
238
- }
239
- if (/browser|playwright|puppeteer|\bpage\b|navigate|goto|\bclick\b|\btype\b|screenshot|dom/.test(
240
- tn
241
- )) {
242
- return {
243
- type: "browser",
244
- url: str(a?.url) ?? str(attr(span, "url")),
245
- action: str(a?.action) ?? str(a?.selector) ?? span.toolName,
246
- screenshot: shot
247
- };
248
- }
249
- const diff = str(attr(span, "diff", "patch")) ?? str(a?.diff) ?? str(a?.patch);
250
- if (diff && /edit|write|patch|apply|str_replace|create|save|file/.test(tn)) {
251
- return {
252
- type: "diff",
253
- path: str(a?.path) ?? str(a?.file) ?? str(attr(span, "path")) ?? "",
254
- patch: truncate(diff, 2e3)
255
- };
256
- }
257
- if (/edit|write|patch|apply|str_replace/.test(tn)) {
258
- const newText = str(a?.new_str) ?? str(a?.content) ?? str(a?.text);
259
- return {
260
- type: "diff",
261
- path: str(a?.path) ?? str(a?.file) ?? "",
262
- patch: newText ? `+ ${truncate(newText, 1600)}` : "(no diff captured)"
263
- };
264
- }
265
- if (/read|\bcat\b|open|view|get_file|load|fetch_file/.test(tn)) {
266
- const content = str(asObj(span.result)?.content) ?? (typeof span.result === "string" ? span.result : void 0) ?? str(attr(span, "content"));
267
- return {
268
- type: "code",
269
- path: str(a?.path) ?? str(a?.file) ?? "",
270
- content: truncate(content ?? "", 1400)
271
- };
272
- }
273
- if (/search|grep|find|glob|query/.test(tn)) {
274
- return {
275
- type: "terminal",
276
- command: `search ${str(a?.query) ?? str(a?.pattern) ?? ""}`.trim(),
277
- output: truncate(safeJson(span.result) ?? "", 1e3)
278
- };
279
- }
280
- const url = str(a?.url) ?? str(attr(span, "url"));
281
- if (url || /http|\bapi\b|fetch|request|webhook|rest|graphql|endpoint/.test(tn)) {
282
- return {
283
- type: "api",
284
- method: str(a?.method) ?? str(attr(span, "method")),
285
- url: url ?? span.toolName,
286
- status: num(attr(span, "status", "statusCode")) ?? num(asObj(span.result)?.status),
287
- request: truncate(str(a?.body) ?? safeJson(span.args) ?? "", 900),
288
- response: truncate(str(attr(span, "response")) ?? safeJson(span.result) ?? "", 900)
289
- };
290
- }
291
- if (/shell|exec|bash|\brun\b|terminal|command|sandbox|process/.test(tn)) {
292
- const command = typeof span.args === "string" ? span.args : str(a?.command) ?? str(a?.cmd) ?? span.toolName;
293
- const output = str(attr(span, "output", "stdout")) ?? (typeof span.result === "string" ? span.result : safeJson(span.result));
294
- return {
295
- type: "terminal",
296
- command: truncate(command, 240),
297
- output: truncate(output ?? "", 1400)
298
- };
299
- }
300
- return {
301
- type: "api",
302
- url: span.toolName,
303
- request: truncate(safeJson(span.args) ?? "", 900),
304
- response: truncate(safeJson(span.result) ?? "", 900)
305
- };
306
- }
307
- if (isImageSrc(shot)) return { type: "screenshot", src: shot };
308
- if (span.kind === "llm") {
309
- const text = str(span.output) ?? str(span.messages?.[span.messages.length - 1]?.content);
310
- return text ? { type: "prose", text: truncate(text, 900) } : { type: "none" };
311
- }
312
- if (span.kind === "sandbox")
313
- return { type: "terminal", command: span.name, output: str(attr(span, "output")) };
314
- return { type: "none" };
315
- }
316
- function toolLabel(span) {
317
- if (span.kind === "tool") {
318
- const a = asObj(span.args);
319
- const arg = typeof span.args === "string" ? span.args : a ? str(a.path) ?? str(a.url) ?? str(a.command) ?? str(a.query) ?? Object.values(a).find((v) => typeof v === "string") : void 0;
320
- return typeof arg === "string" && arg.length > 0 ? `${span.toolName}: ${truncate(arg, 60)}` : span.toolName;
321
- }
322
- return span.name;
323
- }
324
- function classify(span) {
325
- if (span.status === "error" || span.error) {
326
- return { kind: "observed_failure", importance: 5, label: span.error ?? span.name };
327
- }
328
- if (span.kind === "llm" || span.kind === "agent")
329
- return { kind: "reasoned", importance: 2, label: span.name };
330
- if (span.kind === "judge") return { kind: "evaluated", importance: 2, label: span.name };
331
- if (span.kind === "retrieval") return { kind: "searched", importance: 2, label: span.name };
332
- if (span.kind === "sandbox") return { kind: "ran_command", importance: 3, label: span.name };
333
- if (span.kind === "tool") {
334
- const tn = span.toolName.toLowerCase();
335
- const label = toolLabel(span);
336
- if (/computer|cua|desktop|\bgui\b|xdotool|pyautogui/.test(tn))
337
- return { kind: "used_computer", importance: 3, label };
338
- if (/browser|playwright|puppeteer|\bpage\b|navigate|goto|\bclick\b|screenshot|dom/.test(tn))
339
- return { kind: "used_browser", importance: 3, label };
340
- if (/edit|write|patch|apply|str_replace|create.*file|save/.test(tn))
341
- return { kind: "edited_code", importance: 4, label };
342
- if (/read|\bcat\b|open|view|get.*file|load/.test(tn))
343
- return { kind: "read_file", importance: 2, label };
344
- if (/search|grep|find|glob|query/.test(tn)) return { kind: "searched", importance: 2, label };
345
- if (/http|\bapi\b|fetch|request|webhook|rest|graphql|endpoint/.test(tn) || str(asObj(span.args)?.url)) {
346
- return { kind: "called_api", importance: 3, label };
347
- }
348
- if (/shell|exec|bash|\brun\b|terminal|command|process/.test(tn))
349
- return { kind: "ran_command", importance: 3, label };
350
- return { kind: "called_tool", importance: 3, label };
351
- }
352
- return { kind: "called_tool", importance: 2, label: span.name };
353
- }
354
- var KIND_VERB = {
355
- understood_task: "Understood the task",
356
- user_message: "User said",
357
- agent_reply: "Agent replied",
358
- reasoned: "Reasoned",
359
- ran_command: "Ran a command",
360
- read_file: "Read files",
361
- edited_code: "Edited code",
362
- searched: "Searched",
363
- used_browser: "Used the browser",
364
- used_computer: "Controlled the computer",
365
- called_api: "Called an API",
366
- called_tool: "Used a tool",
367
- evaluated: "Evaluated the result",
368
- observed_failure: "Hit a failure",
369
- completed: "Finished"
370
- };
371
- var STANDALONE_KINDS = /* @__PURE__ */ new Set([
372
- "observed_failure",
373
- "understood_task",
374
- "user_message",
375
- "agent_reply"
376
- ]);
377
- function conversationEvents(span, seen, state) {
378
- if (span.kind !== "llm") return [];
379
- const out = [];
380
- const emit = (kind, text, importance) => {
381
- const t = text.trim();
382
- if (!t) return;
383
- const who = kind === "agent_reply" ? "a" : "u";
384
- const key = `${who}
385
- ${t}`;
386
- if (seen.has(key)) return;
387
- seen.add(key);
388
- const speaker = kind === "understood_task" ? "Task" : kind === "user_message" ? "User" : "Agent";
389
- out.push({
390
- kind,
391
- title: `${speaker}: ${truncate(t, 64)}`,
392
- summary: truncate(t, 280),
393
- visual: { type: "prose", text: truncate(t, 1200) },
394
- evidenceSpanIds: [span.spanId],
395
- importance,
396
- startTs: span.startedAt,
397
- endTs: span.endedAt ?? span.startedAt
398
- });
399
- };
400
- for (const m of span.messages ?? []) {
401
- const content = str(m.content);
402
- if (!content) continue;
403
- if (m.role === "user") {
404
- emit(state.sawUser ? "user_message" : "understood_task", content, state.sawUser ? 4 : 5);
405
- state.sawUser = true;
406
- } else if (m.role === "assistant") {
407
- emit("agent_reply", content, 3);
408
- }
409
- }
410
- const reply = str(span.output);
411
- if (reply) emit("agent_reply", reply, 3);
412
- return out;
413
- }
414
- function reduceToSemanticEvents(spans, opts = {}) {
415
- const collapse = opts.collapseAdjacent ?? true;
416
- const ordered = [...spans].sort((a, b) => a.startedAt - b.startedAt);
417
- const seen = /* @__PURE__ */ new Set();
418
- const convState = { sawUser: false };
419
- const raw = [];
420
- for (const s of ordered) {
421
- const conv = conversationEvents(s, seen, convState);
422
- if (conv.length > 0) {
423
- raw.push(...conv);
424
- continue;
425
- }
426
- const c = classify(s);
427
- raw.push({
428
- kind: c.kind,
429
- title: c.label,
430
- summary: `${KIND_VERB[c.kind]} \u2014 ${c.label}`,
431
- visual: extractVisual(s),
432
- evidenceSpanIds: [s.spanId],
433
- importance: c.importance,
434
- startTs: s.startedAt,
435
- endTs: s.endedAt ?? s.startedAt
436
- });
437
- }
438
- if (!collapse) return raw;
439
- const merged = [];
440
- for (const ev of raw) {
441
- const prev = merged[merged.length - 1];
442
- if (prev && prev.kind === ev.kind && !STANDALONE_KINDS.has(ev.kind)) {
443
- prev.evidenceSpanIds.push(...ev.evidenceSpanIds);
444
- prev.endTs = Math.max(prev.endTs, ev.endTs);
445
- if (ev.visual.type !== "none") prev.visual = ev.visual;
446
- const n = prev.evidenceSpanIds.length;
447
- prev.title = `${KIND_VERB[ev.kind]} (${n}\xD7)`;
448
- prev.summary = `${KIND_VERB[ev.kind]} ${n} time${n === 1 ? "" : "s"} \u2014 latest: ${ev.title}`;
449
- } else {
450
- merged.push({ ...ev, evidenceSpanIds: [...ev.evidenceSpanIds] });
451
- }
452
- }
453
- return merged;
454
- }
455
- var KIND_TO_SCENE = {
456
- understood_task: "title_card",
457
- user_message: "prompt",
458
- agent_reply: "reply",
459
- reasoned: "reasoning",
460
- ran_command: "terminal",
461
- read_file: "file",
462
- edited_code: "diff",
463
- searched: "search",
464
- used_browser: "browser",
465
- used_computer: "computer",
466
- called_api: "api",
467
- called_tool: "tool",
468
- evaluated: "eval",
469
- observed_failure: "error",
470
- completed: "summary"
471
- };
472
- var DURATION_BY_IMPORTANCE = {
473
- 1: 2500,
474
- 2: 3e3,
475
- 3: 4e3,
476
- 4: 5e3,
477
- 5: 6e3
478
- };
479
- function compileStoryboard(events, opts = {}) {
480
- const title = opts.title ?? "Agent run";
481
- const maxScenes = opts.maxScenes ?? 16;
482
- const taskEvent = events.find((e) => e.kind === "understood_task");
483
- const indexed = events.filter((ev) => ev.kind !== "understood_task").map((ev, i) => ({ ev, i }));
484
- const mustKeep = indexed.filter(({ ev }) => ev.importance >= 4);
485
- const rest = indexed.filter(({ ev }) => ev.importance < 4).sort((a, b) => b.ev.importance - a.ev.importance || a.i - b.i);
486
- const budget = Math.max(0, maxScenes - mustKeep.length);
487
- const selected = [...mustKeep, ...rest.slice(0, budget)].sort((a, b) => a.i - b.i);
488
- const actionScenes = selected.map(({ ev }) => ({
489
- sceneType: KIND_TO_SCENE[ev.kind],
490
- title: ev.title,
491
- narration: ev.summary,
492
- visual: ev.visual,
493
- durationMs: DURATION_BY_IMPORTANCE[ev.importance],
494
- evidenceSpanIds: ev.evidenceSpanIds
495
- }));
496
- const failures = events.filter((e) => e.kind === "observed_failure").length;
497
- const edits = events.filter((e) => e.kind === "edited_code").length;
498
- const commands = events.filter((e) => e.kind === "ran_command").length;
499
- const summaryNarration = `${events.length} moments \xB7 ${commands} command${commands === 1 ? "" : "s"} \xB7 ${edits} edit${edits === 1 ? "" : "s"} \xB7 ${failures} failure${failures === 1 ? "" : "s"}`;
500
- const scenes = [
501
- {
502
- sceneType: "title_card",
503
- title,
504
- narration: taskEvent ? taskEvent.summary : "The agent receives its task.",
505
- visual: taskEvent ? taskEvent.visual : { type: "none" },
506
- durationMs: 3e3,
507
- evidenceSpanIds: taskEvent ? taskEvent.evidenceSpanIds : []
508
- },
509
- ...actionScenes,
510
- {
511
- sceneType: "summary",
512
- title: failures > 0 ? "Finished \u2014 with failures" : "Finished",
513
- narration: summaryNarration,
514
- visual: { type: "none" },
515
- durationMs: 4e3,
516
- evidenceSpanIds: []
517
- }
518
- ];
519
- return { title, totalMs: scenes.reduce((s, sc) => s + sc.durationMs, 0), scenes };
520
- }
521
- var SCENE_ICON = {
522
- title_card: "\u{1F3AC}",
523
- prompt: "\u{1F4AC}",
524
- reply: "\u{1F916}",
525
- reasoning: "\u{1F9E0}",
526
- terminal: "\u2328\uFE0F",
527
- file: "\u{1F4C4}",
528
- diff: "\u270F\uFE0F",
529
- search: "\u{1F50E}",
530
- browser: "\u{1F310}",
531
- computer: "\u{1F5A5}\uFE0F",
532
- api: "\u{1F50C}",
533
- tool: "\u{1F527}",
534
- eval: "\u2696\uFE0F",
535
- error: "\u274C",
536
- summary: "\u{1F3C1}"
537
- };
538
- function mmss(ms) {
539
- const s = Math.round(ms / 1e3);
540
- return `${Math.floor(s / 60)}:${String(s % 60).padStart(2, "0")}`;
541
- }
542
- function truncate(s, max) {
543
- return s.length <= max ? s : `${s.slice(0, Math.max(0, max - 1))}\u2026`;
544
- }
545
- function escapeHtml(s) {
546
- return s.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;");
547
- }
548
- function visualMarkdown(v) {
549
- switch (v.type) {
550
- case "screenshot":
551
- return `\u{1F5BC} screenshot (${truncate(v.src, 60)})`;
552
- case "browser":
553
- return `\u{1F310} ${v.action ?? "browser"}${v.url ? ` \u2192 ${v.url}` : ""}${v.screenshot ? " [screenshot]" : ""}`;
554
- case "diff":
555
- return `
556
-
557
- \`\`\`diff
558
- ${truncate(v.patch, 600)}
559
- \`\`\`${v.path ? `
560
- _${v.path}_` : ""}`;
561
- case "code":
562
- return `
563
-
564
- \`\`\`
565
- ${truncate(v.content, 500)}
566
- \`\`\`${v.path ? `
567
- _${v.path}_` : ""}`;
568
- case "terminal":
569
- return `
570
-
571
- \`\`\`sh
572
- $ ${v.command}${v.output ? `
573
- ${truncate(v.output, 500)}` : ""}
574
- \`\`\``;
575
- case "api":
576
- return `\u{1F50C} ${v.method ?? "CALL"} ${v.url}${v.status != null ? ` \u2192 ${v.status}` : ""}`;
577
- case "prose":
578
- return `
579
-
580
- > ${truncate(v.text, 400).replace(/\n/g, "\n> ")}`;
581
- default:
582
- return "";
583
- }
584
- }
585
- function visualHtml(v) {
586
- switch (v.type) {
587
- case "screenshot":
588
- return `<img class="shot" src="${escapeHtml(v.src)}" alt="screenshot" loading="lazy"/>`;
589
- case "browser": {
590
- const bar = `<div class="urlbar">${escapeHtml(v.url ?? v.action ?? "browser")}</div>`;
591
- const body = isImageSrc(v.screenshot) ? `<img class="shot" src="${escapeHtml(v.screenshot)}" alt="page" loading="lazy"/>` : `<div class="browser-action">${escapeHtml(v.action ?? "navigated")}</div>`;
592
- return `<div class="browser">${bar}${body}</div>`;
593
- }
594
- case "diff": {
595
- const lines = v.patch.split("\n").map((l) => {
596
- const cls = l.startsWith("+") ? "add" : l.startsWith("-") ? "del" : "";
597
- return `<span class="${cls}">${escapeHtml(l)}</span>`;
598
- });
599
- return `${v.path ? `<div class="pathhdr">${escapeHtml(v.path)}</div>` : ""}<pre class="diff">${lines.join("\n")}</pre>`;
600
- }
601
- case "code":
602
- return `${v.path ? `<div class="pathhdr">${escapeHtml(v.path)}</div>` : ""}<pre class="code">${escapeHtml(v.content)}</pre>`;
603
- case "terminal":
604
- return `<pre class="term"><span class="cmd">$ ${escapeHtml(v.command)}</span>${v.output ? `
605
- ${escapeHtml(v.output)}` : ""}</pre>`;
606
- case "api": {
607
- const badge = `<span class="method">${escapeHtml(v.method ?? "CALL")}</span> <span class="url">${escapeHtml(v.url)}</span>${v.status != null ? ` <span class="status s${Math.floor(v.status / 100)}">${v.status}</span>` : ""}`;
608
- const req = v.request ? `<div class="kv"><b>req</b><pre>${escapeHtml(v.request)}</pre></div>` : "";
609
- const res = v.response ? `<div class="kv"><b>res</b><pre>${escapeHtml(v.response)}</pre></div>` : "";
610
- return `<div class="api"><div class="apihdr">${badge}</div>${req}${res}</div>`;
611
- }
612
- case "prose":
613
- return `<div class="prose">${escapeHtml(v.text)}</div>`;
614
- default:
615
- return "";
616
- }
617
- }
618
- function renderStoryboardMarkdown(storyboard) {
619
- const out = [
620
- `# \u{1F3AC} ${storyboard.title}`,
621
- "",
622
- `_${storyboard.scenes.length} scenes \xB7 ${mmss(storyboard.totalMs)} replay_`,
623
- ""
624
- ];
625
- let elapsed = 0;
626
- for (const sc of storyboard.scenes) {
627
- out.push(`### [${mmss(elapsed)}] ${SCENE_ICON[sc.sceneType]} ${sc.title}`);
628
- out.push("");
629
- out.push(sc.narration);
630
- const vm = visualMarkdown(sc.visual);
631
- if (vm) out.push(vm);
632
- if (sc.evidenceSpanIds.length > 0) {
633
- out.push("");
634
- out.push(`_evidence: ${sc.evidenceSpanIds.length} span(s)_`);
635
- }
636
- out.push("");
637
- elapsed += sc.durationMs;
638
- }
639
- return out.join("\n");
640
- }
641
- function renderStoryboardHtml(storyboard, opts = {}) {
642
- const docTitle = opts.title ?? storyboard.title;
643
- const scenesJson = JSON.stringify(
644
- storyboard.scenes.map((s) => ({
645
- icon: SCENE_ICON[s.sceneType],
646
- type: s.sceneType,
647
- title: s.title,
648
- narration: s.narration,
649
- durationMs: s.durationMs,
650
- evidence: s.evidenceSpanIds.length,
651
- visual: visualHtml(s.visual)
652
- }))
653
- ).replace(/</g, "\\u003c");
654
- return `<!doctype html>
655
- <html lang="en">
656
- <head>
657
- <meta charset="utf-8" />
658
- <meta name="viewport" content="width=device-width, initial-scale=1" />
659
- <title>${escapeHtml(docTitle)}</title>
660
- <style>
661
- :root { color-scheme: dark; }
662
- * { box-sizing: border-box; }
663
- body { margin: 0; font: 16px/1.5 ui-sans-serif, system-ui, -apple-system, sans-serif;
664
- background: #0b0f17; color: #e6edf3; display: flex; min-height: 100vh; align-items: center; justify-content: center; }
665
- .stage { width: min(900px, 95vw); }
666
- h1 { font-size: 1.1rem; font-weight: 600; color: #9aa7b5; margin: 0 0 14px; letter-spacing: .02em; }
667
- .card { background: #111824; border: 1px solid #1e2a3a; border-radius: 14px; padding: 24px 28px;
668
- min-height: 300px; box-shadow: 0 12px 40px rgba(0,0,0,.45); position: relative; overflow: hidden; }
669
- .card::before { content: ""; position: absolute; inset: 0 0 auto 0; height: 3px; background: var(--accent, #3b82f6); }
670
- .head { display: flex; align-items: center; gap: 12px; margin-bottom: 6px; }
671
- .icon { font-size: 2rem; line-height: 1; }
672
- .title { font-size: 1.3rem; font-weight: 650; }
673
- .narration { color: #9fb0c0; font-size: .95rem; margin-bottom: 14px; }
674
- .visual { margin-top: 6px; }
675
- .visual img.shot { max-width: 100%; max-height: 360px; border-radius: 8px; border: 1px solid #1e2a3a; display: block; }
676
- .visual pre { background: #0a0e15; border: 1px solid #1e2a3a; border-radius: 8px; padding: 12px 14px;
677
- overflow: auto; max-height: 340px; font: 13px/1.5 ui-monospace, "SF Mono", Menlo, monospace; white-space: pre-wrap; word-break: break-word; }
678
- .pathhdr { font: 12px ui-monospace, monospace; color: #7d8da0; margin-bottom: 4px; }
679
- .diff .add { color: #56d364; } .diff .del { color: #f85149; }
680
- .term .cmd { color: #eab308; }
681
- .browser { border: 1px solid #1e2a3a; border-radius: 8px; overflow: hidden; }
682
- .urlbar { background: #0a0e15; padding: 7px 12px; font: 12px ui-monospace, monospace; color: #8b98a6; border-bottom: 1px solid #1e2a3a; }
683
- .browser-action { padding: 28px; color: #9fb0c0; text-align: center; }
684
- .api .apihdr { font: 13px ui-monospace, monospace; margin-bottom: 8px; }
685
- .method { background: #1b2636; padding: 2px 8px; border-radius: 5px; color: #79c0ff; }
686
- .status.s2 { color: #56d364; } .status.s4, .status.s5 { color: #f85149; }
687
- .kv { margin-top: 6px; } .kv b { color: #7d8da0; font-weight: 600; font-size: 12px; }
688
- .prose { color: #c9d4e0; font-size: 1rem; white-space: pre-wrap; max-height: 340px; overflow: auto; }
689
- .type-error { --accent: #ef4444; } .type-diff { --accent: #22c55e; } .type-terminal { --accent: #eab308; }
690
- .type-browser { --accent: #06b6d4; } .type-computer { --accent: #14b8a6; } .type-api { --accent: #79c0ff; }
691
- .type-summary { --accent: #a855f7; } .type-title_card { --accent: #3b82f6; }
692
- .type-prompt { --accent: #f59e0b; } .type-reply { --accent: #10b981; }
693
- .scene-enter { animation: pop .45s cubic-bezier(.2,.7,.3,1.2); }
694
- @keyframes pop { from { opacity: 0; transform: translateY(10px) scale(.985); } to { opacity: 1; transform: none; } }
695
- .bar { height: 4px; background: #1e2a3a; border-radius: 4px; margin-top: 14px; overflow: hidden; }
696
- .bar > i { display: block; height: 100%; width: 0; background: var(--accent, #3b82f6); transition: width .1s linear; }
697
- .controls { display: flex; gap: 10px; align-items: center; margin-top: 14px; color: #8b98a6; font-size: .85rem; }
698
- button { background: #1b2636; color: #e6edf3; border: 1px solid #2a3a4f; border-radius: 8px; padding: 6px 12px; cursor: pointer; font: inherit; }
699
- button:hover { background: #243349; }
700
- .dots { display: flex; gap: 5px; margin-left: auto; flex-wrap: wrap; }
701
- .dot { width: 7px; height: 7px; border-radius: 50%; background: #2a3a4f; cursor: pointer; }
702
- .dot.on { background: var(--accent, #3b82f6); }
703
- </style>
704
- </head>
705
- <body>
706
- <div class="stage">
707
- <h1>\u{1F3AC} ${escapeHtml(docTitle)}</h1>
708
- <div class="card" id="card">
709
- <div class="head"><span class="icon" id="icon"></span><span class="title" id="title"></span></div>
710
- <div class="narration" id="narration"></div>
711
- <div class="visual" id="visual"></div>
712
- <div class="bar"><i id="fill"></i></div>
713
- </div>
714
- <div class="controls">
715
- <button id="playPause">\u23F8 Pause</button>
716
- <button id="prev">\u25C0 Prev</button>
717
- <button id="next">Next \u25B6</button>
718
- <span id="counter"></span>
719
- <span class="dots" id="dots"></span>
720
- </div>
721
- </div>
722
- <script>
723
- const SCENES = ${scenesJson};
724
- let i = 0, playing = true, raf = 0, start = 0;
725
- const card = document.getElementById('card'), counter = document.getElementById('counter'), dotsEl = document.getElementById('dots');
726
- SCENES.forEach((_, k) => { const d = document.createElement('span'); d.className = 'dot'; d.onclick = () => go(k); dotsEl.appendChild(d); });
727
- function paint() {
728
- const s = SCENES[i];
729
- card.className = 'card scene-enter type-' + s.type;
730
- document.getElementById('icon').textContent = s.icon;
731
- document.getElementById('title').textContent = s.title;
732
- document.getElementById('narration').textContent = s.narration;
733
- document.getElementById('visual').innerHTML = s.visual || '';
734
- counter.textContent = (i + 1) + ' / ' + SCENES.length;
735
- [...dotsEl.children].forEach((d, k) => d.className = 'dot' + (k === i ? ' on' : ''));
736
- void card.offsetWidth;
737
- }
738
- function tick(t) {
739
- if (!start) start = t;
740
- const s = SCENES[i], p = Math.min(1, (t - start) / s.durationMs);
741
- document.getElementById('fill').style.width = (p * 100) + '%';
742
- if (p >= 1) { if (i < SCENES.length - 1) { go(i + 1); } else { playing = false; updateBtn(); return; } }
743
- if (playing) raf = requestAnimationFrame(tick);
744
- }
745
- function go(n) { i = Math.max(0, Math.min(SCENES.length - 1, n)); start = 0; cancelAnimationFrame(raf); paint(); if (playing) raf = requestAnimationFrame(tick); }
746
- function updateBtn() { document.getElementById('playPause').textContent = playing ? '\u23F8 Pause' : '\u25B6 Play'; }
747
- document.getElementById('playPause').onclick = () => { playing = !playing; updateBtn(); start = 0; if (playing) raf = requestAnimationFrame(tick); else cancelAnimationFrame(raf); };
748
- document.getElementById('next').onclick = () => go(i + 1);
749
- document.getElementById('prev').onclick = () => go(i - 1);
750
- paint(); raf = requestAnimationFrame(tick);
751
- </script>
752
- </body>
753
- </html>
754
- `;
755
- }
756
- export {
757
- codeEditFromSpan,
758
- codeEditsForStoryboard,
759
- compileStoryboard,
760
- editAnimationText,
761
- extractCodeEdits,
762
- reduceToSemanticEvents,
763
- renderCodeAnimationHtml,
764
- renderStoryboardHtml,
765
- renderStoryboardMarkdown
766
- };
767
- //# sourceMappingURL=index.js.map