Spaces:
Running
Running
Sync from GitHub
Browse files- assets/js/demo.js +22 -13
- index.html +1 -1
assets/js/demo.js
CHANGED
|
@@ -9,6 +9,15 @@
|
|
| 9 |
|| window.PICON_API_URL
|
| 10 |
|| '';
|
| 11 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 12 |
// ===== Leaderboard Data (paper baselines) =====
|
| 13 |
// IC = Internal Consistency, EC = External Consistency, RC = Retest Consistency
|
| 14 |
// Area = normalized triangle area on IC-EC-RC radar chart
|
|
@@ -69,7 +78,7 @@
|
|
| 69 |
|
| 70 |
function fetchCommunityEntries() {
|
| 71 |
if (!API_BASE) return;
|
| 72 |
-
|
| 73 |
.then(function (res) { return res.json(); })
|
| 74 |
.then(function (data) {
|
| 75 |
publishedEntries = (data.entries || []).map(function (e) {
|
|
@@ -187,7 +196,7 @@
|
|
| 187 |
async function downloadEvalFile(runId) {
|
| 188 |
if (!runId || !API_BASE) return;
|
| 189 |
try {
|
| 190 |
-
var res = await
|
| 191 |
if (!res.ok) {
|
| 192 |
var err = await res.json().catch(function () { return {}; });
|
| 193 |
alert('Could not download eval file: ' + (err.detail || ('HTTP ' + res.status)));
|
|
@@ -263,7 +272,7 @@
|
|
| 263 |
addMessage(expMessages, 'info', 'Starting interview for ' + name + ' (' + turns + ' turns chosen)...');
|
| 264 |
|
| 265 |
try {
|
| 266 |
-
var res = await
|
| 267 |
method: 'POST',
|
| 268 |
headers: { 'Content-Type': 'application/json' },
|
| 269 |
body: JSON.stringify({ name: name, num_turns: turns })
|
|
@@ -294,7 +303,7 @@
|
|
| 294 |
// Heartbeat: periodically ping the server so it knows we're still here
|
| 295 |
expHeartbeat = setInterval(function () {
|
| 296 |
if (!expSessionId) { clearInterval(expHeartbeat); return; }
|
| 297 |
-
|
| 298 |
}, 30000); // every 30s
|
| 299 |
} catch (err) {
|
| 300 |
addMessage(expMessages, 'info', 'Error: ' + err.message);
|
|
@@ -306,7 +315,7 @@
|
|
| 306 |
while (true) {
|
| 307 |
await new Promise(function (r) { setTimeout(r, 2000); });
|
| 308 |
try {
|
| 309 |
-
var res = await
|
| 310 |
if (!res.ok) return null;
|
| 311 |
var data = await res.json();
|
| 312 |
|
|
@@ -338,7 +347,7 @@
|
|
| 338 |
var typing = showTyping(expMessages);
|
| 339 |
|
| 340 |
try {
|
| 341 |
-
var res = await
|
| 342 |
method: 'POST',
|
| 343 |
headers: { 'Content-Type': 'application/json' },
|
| 344 |
body: JSON.stringify({
|
|
@@ -364,7 +373,7 @@
|
|
| 364 |
var waited = 0;
|
| 365 |
while (waited < maxWait) {
|
| 366 |
try {
|
| 367 |
-
var rRes = await
|
| 368 |
if (rRes.ok) {
|
| 369 |
var results = await rRes.json();
|
| 370 |
if (results.status === 'complete' && results.results && results.results.eval_scores) {
|
|
@@ -525,7 +534,7 @@
|
|
| 525 |
|
| 526 |
(async function () {
|
| 527 |
try {
|
| 528 |
-
var res = await
|
| 529 |
method: 'POST',
|
| 530 |
headers: { 'Content-Type': 'application/json' },
|
| 531 |
body: JSON.stringify(payload)
|
|
@@ -721,7 +730,7 @@
|
|
| 721 |
if (fetchingLogs) return; // prevent overlapping polls from re-rendering the same slice
|
| 722 |
fetchingLogs = true;
|
| 723 |
try {
|
| 724 |
-
var res = await
|
| 725 |
if (!res.ok) return;
|
| 726 |
var data = await res.json();
|
| 727 |
if (data.lines && data.lines.length > 0) {
|
|
@@ -754,7 +763,7 @@
|
|
| 754 |
// Logs are best-effort (its own try/catch); failures here are swallowed.
|
| 755 |
await fetchAgentLogs(sessionId);
|
| 756 |
|
| 757 |
-
var res = await
|
| 758 |
if (!res.ok) {
|
| 759 |
consecutiveFailures++;
|
| 760 |
if (consecutiveFailures >= MAX_CONSECUTIVE_FAILURES) {
|
|
@@ -820,7 +829,7 @@
|
|
| 820 |
var results = null;
|
| 821 |
for (var attempt = 0; attempt < 5; attempt++) {
|
| 822 |
try {
|
| 823 |
-
var rRes = await
|
| 824 |
if (rRes.ok) {
|
| 825 |
results = await rRes.json();
|
| 826 |
break;
|
|
@@ -886,7 +895,7 @@
|
|
| 886 |
if (!q || !agentSessionId) return;
|
| 887 |
manualSendBtn.disabled = true;
|
| 888 |
try {
|
| 889 |
-
var res = await
|
| 890 |
method: 'POST',
|
| 891 |
headers: { 'Content-Type': 'application/json' },
|
| 892 |
body: JSON.stringify({ session_id: agentSessionId, question: q })
|
|
@@ -935,7 +944,7 @@
|
|
| 935 |
var sid = agentSessionId;
|
| 936 |
if (sid && API_BASE) {
|
| 937 |
// Fire-and-forget
|
| 938 |
-
|
| 939 |
.catch(function () { /* ignore */ });
|
| 940 |
}
|
| 941 |
document.getElementById('agent-log').style.display = 'none';
|
|
|
|
| 9 |
|| window.PICON_API_URL
|
| 10 |
|| '';
|
| 11 |
|
| 12 |
+
// All backend calls go through apiFetch. ngrok's free tier returns an HTML
|
| 13 |
+
// interstitial to browser requests unless this header is present, which would
|
| 14 |
+
// break every JSON response below.
|
| 15 |
+
function apiFetch(path, opts) {
|
| 16 |
+
opts = opts || {};
|
| 17 |
+
var headers = Object.assign({ 'ngrok-skip-browser-warning': 'true' }, opts.headers || {});
|
| 18 |
+
return fetch(API_BASE + path, Object.assign({}, opts, { headers: headers }));
|
| 19 |
+
}
|
| 20 |
+
|
| 21 |
// ===== Leaderboard Data (paper baselines) =====
|
| 22 |
// IC = Internal Consistency, EC = External Consistency, RC = Retest Consistency
|
| 23 |
// Area = normalized triangle area on IC-EC-RC radar chart
|
|
|
|
| 78 |
|
| 79 |
function fetchCommunityEntries() {
|
| 80 |
if (!API_BASE) return;
|
| 81 |
+
apiFetch('/api/leaderboard')
|
| 82 |
.then(function (res) { return res.json(); })
|
| 83 |
.then(function (data) {
|
| 84 |
publishedEntries = (data.entries || []).map(function (e) {
|
|
|
|
| 196 |
async function downloadEvalFile(runId) {
|
| 197 |
if (!runId || !API_BASE) return;
|
| 198 |
try {
|
| 199 |
+
var res = await apiFetch('/api/eval-file/' + runId);
|
| 200 |
if (!res.ok) {
|
| 201 |
var err = await res.json().catch(function () { return {}; });
|
| 202 |
alert('Could not download eval file: ' + (err.detail || ('HTTP ' + res.status)));
|
|
|
|
| 272 |
addMessage(expMessages, 'info', 'Starting interview for ' + name + ' (' + turns + ' turns chosen)...');
|
| 273 |
|
| 274 |
try {
|
| 275 |
+
var res = await apiFetch('/api/start', {
|
| 276 |
method: 'POST',
|
| 277 |
headers: { 'Content-Type': 'application/json' },
|
| 278 |
body: JSON.stringify({ name: name, num_turns: turns })
|
|
|
|
| 303 |
// Heartbeat: periodically ping the server so it knows we're still here
|
| 304 |
expHeartbeat = setInterval(function () {
|
| 305 |
if (!expSessionId) { clearInterval(expHeartbeat); return; }
|
| 306 |
+
apiFetch('/api/experience/status/' + expSessionId).catch(function () {});
|
| 307 |
}, 30000); // every 30s
|
| 308 |
} catch (err) {
|
| 309 |
addMessage(expMessages, 'info', 'Error: ' + err.message);
|
|
|
|
| 315 |
while (true) {
|
| 316 |
await new Promise(function (r) { setTimeout(r, 2000); });
|
| 317 |
try {
|
| 318 |
+
var res = await apiFetch('/api/experience/status/' + sessionId);
|
| 319 |
if (!res.ok) return null;
|
| 320 |
var data = await res.json();
|
| 321 |
|
|
|
|
| 347 |
var typing = showTyping(expMessages);
|
| 348 |
|
| 349 |
try {
|
| 350 |
+
var res = await apiFetch('/api/respond', {
|
| 351 |
method: 'POST',
|
| 352 |
headers: { 'Content-Type': 'application/json' },
|
| 353 |
body: JSON.stringify({
|
|
|
|
| 373 |
var waited = 0;
|
| 374 |
while (waited < maxWait) {
|
| 375 |
try {
|
| 376 |
+
var rRes = await apiFetch('/api/results/' + expSessionId);
|
| 377 |
if (rRes.ok) {
|
| 378 |
var results = await rRes.json();
|
| 379 |
if (results.status === 'complete' && results.results && results.results.eval_scores) {
|
|
|
|
| 534 |
|
| 535 |
(async function () {
|
| 536 |
try {
|
| 537 |
+
var res = await apiFetch('/api/agent/start', {
|
| 538 |
method: 'POST',
|
| 539 |
headers: { 'Content-Type': 'application/json' },
|
| 540 |
body: JSON.stringify(payload)
|
|
|
|
| 730 |
if (fetchingLogs) return; // prevent overlapping polls from re-rendering the same slice
|
| 731 |
fetchingLogs = true;
|
| 732 |
try {
|
| 733 |
+
var res = await apiFetch('/api/agent/logs/' + sessionId + '?since=' + agentLogIndex);
|
| 734 |
if (!res.ok) return;
|
| 735 |
var data = await res.json();
|
| 736 |
if (data.lines && data.lines.length > 0) {
|
|
|
|
| 763 |
// Logs are best-effort (its own try/catch); failures here are swallowed.
|
| 764 |
await fetchAgentLogs(sessionId);
|
| 765 |
|
| 766 |
+
var res = await apiFetch('/api/agent/status/' + sessionId);
|
| 767 |
if (!res.ok) {
|
| 768 |
consecutiveFailures++;
|
| 769 |
if (consecutiveFailures >= MAX_CONSECUTIVE_FAILURES) {
|
|
|
|
| 829 |
var results = null;
|
| 830 |
for (var attempt = 0; attempt < 5; attempt++) {
|
| 831 |
try {
|
| 832 |
+
var rRes = await apiFetch('/api/agent/results/' + sessionId);
|
| 833 |
if (rRes.ok) {
|
| 834 |
results = await rRes.json();
|
| 835 |
break;
|
|
|
|
| 895 |
if (!q || !agentSessionId) return;
|
| 896 |
manualSendBtn.disabled = true;
|
| 897 |
try {
|
| 898 |
+
var res = await apiFetch('/api/agent/question', {
|
| 899 |
method: 'POST',
|
| 900 |
headers: { 'Content-Type': 'application/json' },
|
| 901 |
body: JSON.stringify({ session_id: agentSessionId, question: q })
|
|
|
|
| 944 |
var sid = agentSessionId;
|
| 945 |
if (sid && API_BASE) {
|
| 946 |
// Fire-and-forget
|
| 947 |
+
apiFetch('/api/agent/cancel/' + sid, { method: 'DELETE' })
|
| 948 |
.catch(function () { /* ignore */ });
|
| 949 |
}
|
| 950 |
document.getElementById('agent-log').style.display = 'none';
|
index.html
CHANGED
|
@@ -5,7 +5,7 @@
|
|
| 5 |
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
| 6 |
<title>Demo | PICon</title>
|
| 7 |
<meta name="description" content="Try PICon — experience the interrogation yourself or test your own persona agent">
|
| 8 |
-
<meta name="demo-api-url" content="https://
|
| 9 |
<link rel="stylesheet" href="/assets/css/style.css">
|
| 10 |
<link rel="preconnect" href="https://fonts.googleapis.com">
|
| 11 |
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500&display=swap" rel="stylesheet">
|
|
|
|
| 5 |
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
| 6 |
<title>Demo | PICon</title>
|
| 7 |
<meta name="description" content="Try PICon — experience the interrogation yourself or test your own persona agent">
|
| 8 |
+
<meta name="demo-api-url" content="https://exponent-glimmer-leverage.ngrok-free.dev">
|
| 9 |
<link rel="stylesheet" href="/assets/css/style.css">
|
| 10 |
<link rel="preconnect" href="https://fonts.googleapis.com">
|
| 11 |
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500&display=swap" rel="stylesheet">
|