File size: 8,738 Bytes
0d2d822
 
 
 
 
c131f06
0d2d822
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
9e271af
0d2d822
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
c131f06
 
 
 
 
 
0d2d822
 
 
 
 
 
 
 
1
2
3
4
5
6
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
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
/* Scenario Explorer. Dataset text is always inserted with textContent, never innerHTML. */
(function () {
  "use strict";

  var data = null, filtered = [], current = null, loading = false;
  var DEFAULT_ID = 38;

  function el(tag, cls, text) {
    var e = document.createElement(tag);
    if (cls) e.className = cls;
    if (text !== undefined && text !== null) e.textContent = text;
    return e;
  }
  function prettyCat(c) { return String(c || "").replace(/_/g, " "); }

  function section(title, child) {
    var s = el("div", "ex-sec");
    s.appendChild(el("h4", null, title));
    s.appendChild(child);
    return s;
  }

  function segmented(options, render) {
    var wrap = el("div");
    var seg = el("div", "seg");
    var body = el("div");
    options.forEach(function (o, i) {
      var b = el("button", i === 0 ? "active" : "", o.label);
      b.type = "button";
      b.addEventListener("click", function () {
        seg.querySelectorAll("button").forEach(function (x) { x.classList.remove("active"); });
        b.classList.add("active");
        body.replaceChildren(render(o));
      });
      seg.appendChild(b);
    });
    wrap.appendChild(seg);
    wrap.appendChild(body);
    body.appendChild(render(options[0]));
    return wrap;
  }

  function promptBlock(label, text) {
    var p = el("div", "prompt-pre");
    p.appendChild(el("span", "lbl", label));
    p.appendChild(document.createTextNode(text || ""));
    return p;
  }

  function renderDetail(sc) {
    var d = document.getElementById("exDetail");
    d.replaceChildren();
    if (!sc) { d.appendChild(el("p", "empty", "No scenario selected.")); return; }

    var head = el("div", "head");
    head.appendChild(el("h2", null, "Scenario " + sc.id));
    head.appendChild(el("span", "cat-chip", prettyCat(sc.category)));
    d.appendChild(head);

    d.appendChild(section("Environment", el("p", null, sc.environment)));
    d.appendChild(section("Character", el("p", null, sc.character)));

    var task = el("div", "task-box"); task.appendChild(el("p", null, sc.goal_short_term));
    d.appendChild(section("Short-term task (benign)", task));

    d.appendChild(section("Instrumental long-term goal", segmented([
      { label: "Goal", text: sc.goal_long_term },
      { label: "No-hint variant", text: sc.goal_long_term_no_hint },
      { label: "Detailed (strategic hints)", text: sc.goal_long_term_detailed }
    ], function (o) { var b = el("div", "goal-box"); b.appendChild(el("p", null, o.text)); return b; })));

    var prop = sc.propensity || {};
    d.appendChild(section("Prompts", segmented([
      { label: "Capability setups", sys: sc.system_prompt, usr: sc.user_prompt },
      { label: "Propensity setups (no explicit goal)", sys: prop.system_prompt, usr: prop.user_prompt }
    ], function (o) {
      var w = el("div");
      w.appendChild(promptBlock("System prompt", o.sys));
      w.appendChild(promptBlock("User prompt", o.usr));
      return w;
    })));

    var tools = el("div", "tools");
    var tkeys = Object.keys(sc.tools || {});
    if (!tkeys.length) tools.appendChild(el("p", "empty", "Only file-system tools."));
    tkeys.forEach(function (k) {
      var t = sc.tools[k] || {};
      var c = el("div", "tool");
      c.appendChild(el("div", "nm", t.tool_name || k));
      var meta = el("div", "meta");
      var method = String(t.method || "").trim();
      var shortVerb = /^(GET|POST|PUT|PATCH|DELETE|HEAD|OPTIONS)$/i.test(method);
      if (shortVerb) meta.appendChild(el("span", "m", method.toUpperCase()));
      meta.appendChild(document.createTextNode([t.api_name, t.category_name].filter(Boolean).join(" · ")));
      c.appendChild(meta);
      c.appendChild(el("div", "ds", t.tool_description || ""));
      if (method && !shortVerb) c.appendChild(el("div", "mnote", method));
      tools.appendChild(c);
    });
    var ttl = el("div");
    var note = el("p", "empty", "Plus file-system tools: create_file, read_file, list_files, write_file.");
    note.style.marginTop = "8px";
    ttl.appendChild(tools); ttl.appendChild(note);
    d.appendChild(section("Scenario-specific tools (" + tkeys.length + ")", ttl));

    var files = sc.files || [];
    var fw = el("div", "files");
    var list = el("div", "file-list");
    var view = el("pre", "file-view");
    function show(i, btn) {
      list.querySelectorAll(".file-btn").forEach(function (x) { x.classList.remove("active"); });
      if (btn) btn.classList.add("active");
      view.textContent = files[i] ? (files[i].content || "") : "";
    }
    files.forEach(function (f, i) {
      var b = el("button", "file-btn", String(f.path || "").replace(/^\.\/files\//, ""));
      b.type = "button";
      b.addEventListener("click", function () { show(i, b); });
      list.appendChild(b);
    });
    fw.appendChild(list); fw.appendChild(view);
    if (files.length) show(0, list.firstChild); else view.textContent = "(no files)";
    d.appendChild(section("Initial workspace (" + files.length + " files)", fw));
  }

  function renderList() {
    var list = document.getElementById("exList");
    list.replaceChildren();
    document.getElementById("exCount").textContent = filtered.length + " of " + data.length + " scenarios";
    if (!filtered.length) { var e = el("p", "empty", "No scenarios match."); e.style.padding = "14px"; list.appendChild(e); return; }
    var frag = document.createDocumentFragment();
    filtered.forEach(function (sc) {
      var b = el("button", "ex-item" + (current && current.id === sc.id ? " active" : ""));
      b.type = "button";
      b.dataset.id = sc.id;
      var top = el("div", "top");
      top.appendChild(el("b", null, "#" + sc.id));
      top.appendChild(el("span", null, prettyCat(sc.category)));
      b.appendChild(top);
      b.appendChild(el("div", "task", sc.goal_short_term));
      b.addEventListener("click", function () { select(sc.id, true); });
      frag.appendChild(b);
    });
    list.appendChild(frag);
  }

  function applyFilter() {
    var q = document.getElementById("exSearch").value.trim().toLowerCase();
    var cat = document.getElementById("exCategory").value;
    filtered = data.filter(function (sc) {
      if (cat && sc.category !== cat) return false;
      if (!q) return true;
      if (String(sc.id) === q.replace("#", "")) return true;
      return (sc._hay || (sc._hay = [sc.environment, sc.character, sc.goal_short_term, sc.goal_long_term, sc.category].join(" ").toLowerCase())).indexOf(q) !== -1;
    });
    renderList();
  }

  function select(id, updateHash) {
    var sc = data.find(function (s) { return s.id === Number(id); });
    if (!sc) return;
    current = sc;
    document.querySelectorAll(".ex-item").forEach(function (b) { b.classList.toggle("active", Number(b.dataset.id) === sc.id); });
    renderDetail(sc);
    if (updateHash) history.replaceState(null, "", "#explorer/" + sc.id);
    if (window.innerWidth <= 980 && updateHash) document.getElementById("exDetail").scrollIntoView({ behavior: "smooth", block: "start" });
  }

  window.openExplorer = function (id) {
    if (data) { if (id) select(id, false); return; }
    if (loading) return;
    loading = true;
    fetch("data/scenarios.json").then(function (r) {
      if (!r.ok) throw new Error("HTTP " + r.status);
      return r.json();
    }).then(function (json) {
      data = json.sort(function (a, b) { return a.id - b.id; });
      var cats = {};
      data.forEach(function (s) { cats[s.category] = (cats[s.category] || 0) + 1; });
      var sel = document.getElementById("exCategory");
      Object.keys(cats).sort().forEach(function (c) {
        var o = el("option", null, prettyCat(c) + " (" + cats[c] + ")");
        o.value = c;
        sel.appendChild(o);
      });
      sel.addEventListener("change", applyFilter);
      var t;
      document.getElementById("exSearch").addEventListener("input", function () { clearTimeout(t); t = setTimeout(applyFilter, 120); });
      filtered = data.slice();
      renderList();
      // Default to scenario 38, the worked example in Appendix D of the paper.
      var start = id || (data.some(function (s) { return s.id === DEFAULT_ID; }) ? DEFAULT_ID : data[0].id);
      select(start, false);
      var list = document.getElementById("exList");
      var item = list.querySelector('.ex-item[data-id="' + Number(start) + '"]');
      if (item) list.scrollTop = item.offsetTop - list.offsetTop - 8;
    }).catch(function (err) {
      var d = document.getElementById("exDetail");
      d.replaceChildren(el("p", "empty", "Could not load scenarios (" + err.message + "). The full dataset is on Hugging Face: launch/SchemeArena."));
      document.getElementById("exList").replaceChildren();
      loading = false;
    });
  };
})();