@warlock.js/ai-panoptic 4.8.1 → 4.9.0
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.
- package/CHANGELOG.md +12 -0
- package/cjs/index.cjs +340 -42
- package/cjs/index.cjs.map +1 -1
- package/esm/collector/collector.d.mts +1 -1
- package/esm/collector/collector.d.mts.map +1 -1
- package/esm/collector/collector.mjs +1 -1
- package/esm/collector/collector.mjs.map +1 -1
- package/esm/collector/content-capture.type.d.mts +1 -1
- package/esm/collector/content-capture.type.d.mts.map +1 -1
- package/esm/collector/extract-span-attributes.d.mts +1 -1
- package/esm/collector/extract-span-attributes.d.mts.map +1 -1
- package/esm/collector/extract-span-attributes.mjs +1 -1
- package/esm/collector/extract-span-attributes.mjs.map +1 -1
- package/esm/collector/normalize-error.d.mts +1 -1
- package/esm/collector/normalize-error.d.mts.map +1 -1
- package/esm/collector/normalize-error.mjs +1 -1
- package/esm/collector/normalize-error.mjs.map +1 -1
- package/esm/collector/report-to-span.d.mts +1 -1
- package/esm/collector/report-to-span.d.mts.map +1 -1
- package/esm/collector/report-to-span.mjs +1 -1
- package/esm/collector/report-to-span.mjs.map +1 -1
- package/esm/collector/report-to-trace.d.mts +1 -1
- package/esm/collector/report-to-trace.d.mts.map +1 -1
- package/esm/collector/report-to-trace.mjs +1 -1
- package/esm/collector/report-to-trace.mjs.map +1 -1
- package/esm/config/apply-panoptic-config.d.mts +1 -1
- package/esm/config/apply-panoptic-config.d.mts.map +1 -1
- package/esm/config/apply-panoptic-config.mjs +4 -2
- package/esm/config/apply-panoptic-config.mjs.map +1 -1
- package/esm/config/panoptic-config.type.d.mts +12 -1
- package/esm/config/panoptic-config.type.d.mts.map +1 -1
- package/esm/contracts/collector.contract.d.mts +1 -1
- package/esm/contracts/collector.contract.d.mts.map +1 -1
- package/esm/contracts/exporter.contract.d.mts +1 -1
- package/esm/contracts/exporter.contract.d.mts.map +1 -1
- package/esm/contracts/trace.type.d.mts +1 -1
- package/esm/contracts/trace.type.d.mts.map +1 -1
- package/esm/dashboard/dashboard.d.mts +1 -1
- package/esm/dashboard/dashboard.d.mts.map +1 -1
- package/esm/dashboard/dashboard.mjs +3 -2
- package/esm/dashboard/dashboard.mjs.map +1 -1
- package/esm/dashboard/dashboard.type.d.mts +16 -3
- package/esm/dashboard/dashboard.type.d.mts.map +1 -1
- package/esm/dashboard/index.mjs +7 -0
- package/esm/dashboard/parse-query.mjs +1 -1
- package/esm/dashboard/parse-query.mjs.map +1 -1
- package/esm/dashboard/serve.mjs +124 -9
- package/esm/dashboard/serve.mjs.map +1 -1
- package/esm/dashboard/trace-filter.d.mts +1 -1
- package/esm/dashboard/trace-filter.d.mts.map +1 -1
- package/esm/dashboard/trace-filter.mjs +1 -1
- package/esm/dashboard/trace-filter.mjs.map +1 -1
- package/esm/dashboard/ui.html.mjs +134 -5
- package/esm/dashboard/ui.html.mjs.map +1 -1
- package/esm/dashboard/warlock-logo.mjs +1 -1
- package/esm/dashboard/warlock-logo.mjs.map +1 -1
- package/esm/evaluate/evaluate-system-prompt.d.mts +19 -0
- package/esm/evaluate/evaluate-system-prompt.d.mts.map +1 -0
- package/esm/evaluate/evaluate-system-prompt.mjs +22 -0
- package/esm/evaluate/evaluate-system-prompt.mjs.map +1 -0
- package/esm/evaluate/evaluate.type.d.mts +47 -0
- package/esm/evaluate/evaluate.type.d.mts.map +1 -0
- package/esm/evaluate/extract-last-system-prompt.d.mts +19 -0
- package/esm/evaluate/extract-last-system-prompt.d.mts.map +1 -0
- package/esm/evaluate/extract-last-system-prompt.mjs +24 -0
- package/esm/evaluate/extract-last-system-prompt.mjs.map +1 -0
- package/esm/evaluate/find-span-by-id.d.mts +8 -0
- package/esm/evaluate/find-span-by-id.d.mts.map +1 -0
- package/esm/evaluate/find-span-by-id.mjs +13 -0
- package/esm/evaluate/find-span-by-id.mjs.map +1 -0
- package/esm/evaluate/index.d.mts +4 -0
- package/esm/evaluate/index.mjs +5 -0
- package/esm/exporters/console/console-exporter.d.mts +1 -1
- package/esm/exporters/console/console-exporter.d.mts.map +1 -1
- package/esm/exporters/console/console-exporter.mjs +1 -1
- package/esm/exporters/console/console-exporter.mjs.map +1 -1
- package/esm/exporters/console/console-exporter.type.d.mts +1 -1
- package/esm/exporters/console/console-exporter.type.d.mts.map +1 -1
- package/esm/exporters/console/format-span-io.d.mts +1 -1
- package/esm/exporters/console/format-span-io.d.mts.map +1 -1
- package/esm/exporters/console/format-span-io.mjs +1 -1
- package/esm/exporters/console/format-span-io.mjs.map +1 -1
- package/esm/exporters/console/format-span-line.d.mts +1 -1
- package/esm/exporters/console/format-span-line.d.mts.map +1 -1
- package/esm/exporters/console/format-span-line.mjs +1 -1
- package/esm/exporters/console/format-span-line.mjs.map +1 -1
- package/esm/exporters/file/file-exporter.d.mts +1 -1
- package/esm/exporters/file/file-exporter.d.mts.map +1 -1
- package/esm/exporters/file/file-exporter.mjs +1 -1
- package/esm/exporters/file/file-exporter.mjs.map +1 -1
- package/esm/exporters/file/file-exporter.type.d.mts +1 -1
- package/esm/exporters/file/file-exporter.type.d.mts.map +1 -1
- package/esm/exporters/langfuse/langfuse-exporter.d.mts +1 -1
- package/esm/exporters/langfuse/langfuse-exporter.d.mts.map +1 -1
- package/esm/exporters/langfuse/langfuse-exporter.mjs +1 -1
- package/esm/exporters/langfuse/langfuse-exporter.mjs.map +1 -1
- package/esm/exporters/langfuse/langfuse-exporter.type.d.mts +1 -1
- package/esm/exporters/langfuse/langfuse-exporter.type.d.mts.map +1 -1
- package/esm/exporters/otel/otel-api.shim.type.d.mts +1 -1
- package/esm/exporters/otel/otel-api.shim.type.d.mts.map +1 -1
- package/esm/exporters/otel/otel-exporter.d.mts +1 -1
- package/esm/exporters/otel/otel-exporter.d.mts.map +1 -1
- package/esm/exporters/otel/otel-exporter.mjs +1 -1
- package/esm/exporters/otel/otel-exporter.mjs.map +1 -1
- package/esm/exporters/otel/otel-exporter.type.d.mts +1 -1
- package/esm/exporters/otel/otel-exporter.type.d.mts.map +1 -1
- package/esm/exporters/utils/gen-ai-attributes.d.mts +1 -1
- package/esm/exporters/utils/gen-ai-attributes.d.mts.map +1 -1
- package/esm/exporters/utils/gen-ai-attributes.mjs +1 -1
- package/esm/exporters/utils/gen-ai-attributes.mjs.map +1 -1
- package/esm/exporters/utils/total-cost.d.mts +1 -1
- package/esm/exporters/utils/total-cost.d.mts.map +1 -1
- package/esm/exporters/utils/total-cost.mjs +1 -1
- package/esm/exporters/utils/total-cost.mjs.map +1 -1
- package/esm/exporters/utils/walk-spans.d.mts +1 -1
- package/esm/exporters/utils/walk-spans.d.mts.map +1 -1
- package/esm/exporters/utils/walk-spans.mjs +1 -1
- package/esm/exporters/utils/walk-spans.mjs.map +1 -1
- package/esm/index.d.mts +5 -1
- package/esm/index.mjs +6 -1
- package/esm/panoptic/panoptic-middleware.d.mts +1 -1
- package/esm/panoptic/panoptic-middleware.d.mts.map +1 -1
- package/esm/panoptic/panoptic-middleware.mjs +1 -1
- package/esm/panoptic/panoptic-middleware.mjs.map +1 -1
- package/esm/panoptic/panoptic-target.type.d.mts +1 -1
- package/esm/panoptic/panoptic-target.type.d.mts.map +1 -1
- package/esm/panoptic/panoptic.d.mts +1 -1
- package/esm/panoptic/panoptic.d.mts.map +1 -1
- package/esm/panoptic/panoptic.mjs +1 -1
- package/esm/panoptic/panoptic.mjs.map +1 -1
- package/esm/panoptic/panoptic.type.d.mts +1 -1
- package/esm/panoptic/panoptic.type.d.mts.map +1 -1
- package/esm/register.mjs +1 -1
- package/esm/register.mjs.map +1 -1
- package/esm/store/cache-trace-store.d.mts +1 -1
- package/esm/store/cache-trace-store.d.mts.map +1 -1
- package/esm/store/cache-trace-store.mjs +1 -1
- package/esm/store/cache-trace-store.mjs.map +1 -1
- package/esm/store/in-memory-trace-store.d.mts +1 -1
- package/esm/store/in-memory-trace-store.d.mts.map +1 -1
- package/esm/store/in-memory-trace-store.mjs +1 -1
- package/esm/store/in-memory-trace-store.mjs.map +1 -1
- package/esm/store/match-trace.d.mts +1 -1
- package/esm/store/match-trace.d.mts.map +1 -1
- package/esm/store/match-trace.mjs +1 -1
- package/esm/store/match-trace.mjs.map +1 -1
- package/esm/store/sum-usage.d.mts +1 -1
- package/esm/store/sum-usage.d.mts.map +1 -1
- package/esm/store/sum-usage.mjs +1 -1
- package/esm/store/sum-usage.mjs.map +1 -1
- package/esm/store/trace-aggregate.type.d.mts +1 -1
- package/esm/store/trace-aggregate.type.d.mts.map +1 -1
- package/esm/store/trace-query.type.d.mts +1 -1
- package/esm/store/trace-query.type.d.mts.map +1 -1
- package/esm/store/trace-store.contract.d.mts +1 -1
- package/esm/store/trace-store.contract.d.mts.map +1 -1
- package/llms-full.txt +95 -3
- package/llms.txt +1 -0
- package/package.json +4 -3
- package/skills/README.md +4 -0
- package/skills/evaluate-system-prompt/SKILL.md +86 -0
- package/skills/use-local-dashboard/SKILL.md +5 -3
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { WARLOCK_LOGO_DATA_URI } from "./warlock-logo.mjs";
|
|
2
2
|
|
|
3
|
-
//#region
|
|
3
|
+
//#region ../ai-panoptic/src/dashboard/ui.html.ts
|
|
4
4
|
/**
|
|
5
5
|
* Build the single self-contained dashboard HTML page. No external
|
|
6
6
|
* assets, no bundler, no framework — one inlined string that polls the
|
|
@@ -40,7 +40,7 @@ import { WARLOCK_LOGO_DATA_URI } from "./warlock-logo.mjs";
|
|
|
40
40
|
* @param basePath Normalized mount path ending in `/` (e.g. `"/"`).
|
|
41
41
|
* @param title Header title shown in the page.
|
|
42
42
|
*/
|
|
43
|
-
function dashboardHtml(basePath, title) {
|
|
43
|
+
function dashboardHtml(basePath, title, evaluateEnabled = false, evaluateDefaultInstructions = "") {
|
|
44
44
|
const apiBase = `${basePath}api`;
|
|
45
45
|
const safeTitle = escapeHtml(title);
|
|
46
46
|
return `<!doctype html>
|
|
@@ -221,6 +221,18 @@ function dashboardHtml(basePath, title) {
|
|
|
221
221
|
.legend { margin-left: auto; display: flex; align-items: center; gap: 6px; font-size: 11px; color: var(--dim); }
|
|
222
222
|
.legend .grad { width: 64px; height: 8px; border-radius: 4px; background: linear-gradient(90deg, var(--surface2), var(--cost)); border: 1px solid var(--border); }
|
|
223
223
|
.gantt { padding: 8px 10px; }
|
|
224
|
+
|
|
225
|
+
/* Evaluate — the drawer's one write action (config-gated). */
|
|
226
|
+
.eval-btn { background: transparent; border: 1px solid var(--border); color: var(--text2); cursor: pointer; font-size: 12px; padding: 4px 10px; border-radius: 6px; margin: 10px 0 0; }
|
|
227
|
+
.eval-btn:hover:not(:disabled) { color: var(--text); border-color: var(--border2); }
|
|
228
|
+
.eval-btn:disabled { opacity: .6; cursor: default; }
|
|
229
|
+
.eval-panel { margin-top: 8px; padding: 10px; border: 1px solid var(--border); border-radius: 8px; background: var(--surface2); }
|
|
230
|
+
.eval-panel textarea { width: 100%; min-height: 64px; background: var(--panel); color: var(--text); border: 1px solid var(--border); border-radius: 6px; padding: 8px; font: 12px/1.5 ui-sans-serif, system-ui, sans-serif; resize: vertical; }
|
|
231
|
+
.eval-actions { display: flex; align-items: center; gap: 8px; margin-top: 8px; }
|
|
232
|
+
.eval-error { color: var(--fail); font-size: 12px; }
|
|
233
|
+
.eval-result { margin-top: 10px; padding-top: 10px; border-top: 1px solid var(--border); font-size: 12px; }
|
|
234
|
+
.eval-score { font-weight: 600; }
|
|
235
|
+
.eval-issues { margin: 6px 0 0; padding-left: 18px; }
|
|
224
236
|
.grow { display: flex; align-items: center; gap: 8px; padding: 2px 0; font-size: 12px; cursor: pointer; border-radius: 4px; }
|
|
225
237
|
.grow:hover { background: var(--surface); }
|
|
226
238
|
.grow.selected { background: var(--sel-bg); }
|
|
@@ -285,7 +297,21 @@ function dashboardHtml(basePath, title) {
|
|
|
285
297
|
<script>
|
|
286
298
|
(function () {
|
|
287
299
|
var API = ${JSON.stringify(apiBase)};
|
|
300
|
+
var EVALUATE_ENABLED = ${JSON.stringify(evaluateEnabled)};
|
|
288
301
|
var BT = String.fromCharCode(96);
|
|
302
|
+
var EVALUATE_DEFAULT_INSTRUCTIONS = ${encodeForInlineScript(evaluateDefaultInstructions)};
|
|
303
|
+
|
|
304
|
+
// Carry the ?token= the page itself was loaded with onto every
|
|
305
|
+
// subsequent poll — otherwise the API calls below inherit no auth and
|
|
306
|
+
// 401 forever once authToken is configured (the initial page load is
|
|
307
|
+
// the only request the URL's query string naturally reaches).
|
|
308
|
+
var TOKEN = new URLSearchParams(window.location.search).get("token");
|
|
309
|
+
function fetchAuthed(url, options) {
|
|
310
|
+
var opts = options || {};
|
|
311
|
+
var headers = opts.headers || {};
|
|
312
|
+
if (TOKEN) headers = Object.assign({}, headers, { Authorization: "Bearer " + TOKEN });
|
|
313
|
+
return fetch(url, Object.assign({}, opts, { headers: headers }));
|
|
314
|
+
}
|
|
289
315
|
|
|
290
316
|
var state = {
|
|
291
317
|
traces: [], selectedId: null, selectedSpanId: null, collapsed: {}, sig: null,
|
|
@@ -297,7 +323,8 @@ function dashboardHtml(basePath, title) {
|
|
|
297
323
|
showStats: false, // per-type aggregate-stats panel toggle (independent of grouping)
|
|
298
324
|
collapsedGroups: {}, // collapsed group headers (session, prompt, or type)
|
|
299
325
|
view: "tree", // drawer left pane: "tree" | "timeline"
|
|
300
|
-
hashApplied: false
|
|
326
|
+
hashApplied: false, // guards one-time deep-link open on load
|
|
327
|
+
evaluate: {} // per-span evaluate UI state, keyed by spanId
|
|
301
328
|
};
|
|
302
329
|
|
|
303
330
|
var STATUS_FILTERS = ["completed", "failed", "cancelled"];
|
|
@@ -1006,6 +1033,80 @@ function dashboardHtml(basePath, title) {
|
|
|
1006
1033
|
return '<div class="meta-sec"><div class="meta-title">metadata</div><div class="kv">' + kv + "</div></div>";
|
|
1007
1034
|
}
|
|
1008
1035
|
|
|
1036
|
+
// --- Evaluate: grade a span's last captured system prompt -------------
|
|
1037
|
+
// Config-gated (EVALUATE_ENABLED) — the drawer's only write action, POSTing
|
|
1038
|
+
// to a route that itself only exists when the server was configured with
|
|
1039
|
+
// evaluate. UI state lives in state.evaluate, keyed by spanId, so it
|
|
1040
|
+
// survives a re-render (e.g. switching to a sibling span and back).
|
|
1041
|
+
function extractLastSystemPrompt(span) {
|
|
1042
|
+
if (!Array.isArray(span.input)) return null;
|
|
1043
|
+
for (var i = span.input.length - 1; i >= 0; i--) {
|
|
1044
|
+
var m = span.input[i];
|
|
1045
|
+
if (m && typeof m === "object" && m.role === "system" && typeof m.content === "string") return m.content;
|
|
1046
|
+
}
|
|
1047
|
+
return null;
|
|
1048
|
+
}
|
|
1049
|
+
function evalState(spanId) {
|
|
1050
|
+
return state.evaluate[spanId] || (state.evaluate[spanId] = {
|
|
1051
|
+
open: false, instructions: EVALUATE_DEFAULT_INSTRUCTIONS, status: "idle", result: null, error: null
|
|
1052
|
+
});
|
|
1053
|
+
}
|
|
1054
|
+
function evalResultHtml(result) {
|
|
1055
|
+
var score = typeof result.score === "number" ? Math.round(result.score * 100) + "%" : "n/a";
|
|
1056
|
+
var issues = (result.issues || []).map(function (i) { return "<li>" + esc(i) + "</li>"; }).join("");
|
|
1057
|
+
return '<div class="eval-result"><span class="eval-score">Score: ' + score + "</span>"
|
|
1058
|
+
+ (issues ? '<ul class="eval-issues">' + issues + "</ul>" : "") + "</div>";
|
|
1059
|
+
}
|
|
1060
|
+
function evalSectionHtml(span) {
|
|
1061
|
+
if (!EVALUATE_ENABLED) return "";
|
|
1062
|
+
var sysPrompt = extractLastSystemPrompt(span);
|
|
1063
|
+
if (!sysPrompt) return "";
|
|
1064
|
+
var st = evalState(span.spanId);
|
|
1065
|
+
var btn = '<button type="button" class="eval-btn" data-evaluate-toggle="' + esc(span.spanId) + '">'
|
|
1066
|
+
+ (st.open ? "Hide evaluate" : "Evaluate system prompt") + "</button>";
|
|
1067
|
+
if (!st.open) return btn;
|
|
1068
|
+
var running = st.status === "running";
|
|
1069
|
+
return btn + '<div class="eval-panel">'
|
|
1070
|
+
+ '<textarea id="eval-instructions" placeholder="Grading instructions (optional — falls back to the configured default)"' + (running ? " disabled" : "") + ">" + esc(st.instructions || "") + "</textarea>"
|
|
1071
|
+
+ '<div class="eval-actions">'
|
|
1072
|
+
+ '<button type="button" class="eval-btn" data-evaluate-run="' + esc(span.spanId) + '"' + (running ? " disabled" : "") + ">" + (running ? "Evaluating…" : "Run") + "</button>"
|
|
1073
|
+
+ (st.error ? '<span class="eval-error">' + esc(st.error) + "</span>" : "")
|
|
1074
|
+
+ "</div>"
|
|
1075
|
+
+ (st.result ? evalResultHtml(st.result) : "")
|
|
1076
|
+
+ "</div>";
|
|
1077
|
+
}
|
|
1078
|
+
function rerenderDetail() {
|
|
1079
|
+
var t = findTrace(state.selectedId);
|
|
1080
|
+
if (!t) return;
|
|
1081
|
+
var sel = findSpan(t.root, state.selectedSpanId) || t.root;
|
|
1082
|
+
document.getElementById("drawer-detail").innerHTML = renderDetail(sel, t);
|
|
1083
|
+
}
|
|
1084
|
+
function toggleEvalPanel(spanId) {
|
|
1085
|
+
evalState(spanId).open = !evalState(spanId).open;
|
|
1086
|
+
rerenderDetail();
|
|
1087
|
+
}
|
|
1088
|
+
function runEvaluate(traceId, spanId) {
|
|
1089
|
+
var st = evalState(spanId);
|
|
1090
|
+
var textarea = document.getElementById("eval-instructions");
|
|
1091
|
+
if (textarea) st.instructions = textarea.value;
|
|
1092
|
+
st.status = "running"; st.error = null;
|
|
1093
|
+
rerenderDetail();
|
|
1094
|
+
fetchAuthed(API + "/traces/" + encodeURIComponent(traceId) + "/spans/" + encodeURIComponent(spanId) + "/evaluate", {
|
|
1095
|
+
method: "POST",
|
|
1096
|
+
headers: { "content-type": "application/json" },
|
|
1097
|
+
body: JSON.stringify({ instructions: st.instructions })
|
|
1098
|
+
}).then(function (r) {
|
|
1099
|
+
return r.json().then(function (data) { return { ok: r.ok, data: data }; });
|
|
1100
|
+
}).then(function (res) {
|
|
1101
|
+
if (res.ok) { st.status = "done"; st.result = res.data; st.error = null; }
|
|
1102
|
+
else { st.status = "error"; st.error = (res.data && (res.data.message || res.data.error)) || "evaluate failed"; st.result = null; }
|
|
1103
|
+
rerenderDetail();
|
|
1104
|
+
}).catch(function () {
|
|
1105
|
+
st.status = "error"; st.error = "network error"; st.result = null;
|
|
1106
|
+
rerenderDetail();
|
|
1107
|
+
});
|
|
1108
|
+
}
|
|
1109
|
+
|
|
1009
1110
|
function renderDetail(span, trace) {
|
|
1010
1111
|
var path = findPath(trace.root, span.spanId) || [span];
|
|
1011
1112
|
var crumb = path.map(function (p, i) { return (i ? '<span class="sep"> › </span>' : "") + "<span>" + esc(p.name) + "</span>"; }).join("");
|
|
@@ -1028,6 +1129,7 @@ function dashboardHtml(basePath, title) {
|
|
|
1028
1129
|
+ '<span class="dim">· ' + dur(span.duration) + "</span></div>"
|
|
1029
1130
|
+ metaLine
|
|
1030
1131
|
+ io
|
|
1132
|
+
+ evalSectionHtml(span, trace)
|
|
1031
1133
|
+ renderMeta(span, trace);
|
|
1032
1134
|
}
|
|
1033
1135
|
|
|
@@ -1190,9 +1292,20 @@ function dashboardHtml(basePath, title) {
|
|
|
1190
1292
|
if (vb) { setView(vb.getAttribute("data-view")); return; }
|
|
1191
1293
|
var tog = e.target.closest ? e.target.closest("[data-toggle]") : null;
|
|
1192
1294
|
if (tog) { toggleSpan(tog.getAttribute("data-toggle")); return; }
|
|
1295
|
+
var evalToggle = e.target.closest ? e.target.closest("[data-evaluate-toggle]") : null;
|
|
1296
|
+
if (evalToggle) { toggleEvalPanel(evalToggle.getAttribute("data-evaluate-toggle")); return; }
|
|
1297
|
+
var evalRun = e.target.closest ? e.target.closest("[data-evaluate-run]") : null;
|
|
1298
|
+
if (evalRun && state.selectedId) { runEvaluate(state.selectedId, evalRun.getAttribute("data-evaluate-run")); return; }
|
|
1193
1299
|
var node = e.target.closest ? e.target.closest(".tnode[data-span], .grow[data-span]") : null;
|
|
1194
1300
|
if (node) selectSpan(node.getAttribute("data-span"));
|
|
1195
1301
|
});
|
|
1302
|
+
// Track the instructions textarea live (no re-render on keystroke, so
|
|
1303
|
+
// typing never loses focus/cursor position).
|
|
1304
|
+
document.getElementById("drawer-body").addEventListener("input", function (e) {
|
|
1305
|
+
if (e.target && e.target.id === "eval-instructions" && state.selectedSpanId) {
|
|
1306
|
+
evalState(state.selectedSpanId).instructions = e.target.value;
|
|
1307
|
+
}
|
|
1308
|
+
});
|
|
1196
1309
|
document.getElementById("backdrop").addEventListener("click", closeDrawer);
|
|
1197
1310
|
document.addEventListener("keydown", function (e) { if (e.key === "Escape" || e.keyCode === 27) closeDrawer(); });
|
|
1198
1311
|
|
|
@@ -1288,8 +1401,8 @@ function dashboardHtml(basePath, title) {
|
|
|
1288
1401
|
|
|
1289
1402
|
function poll() {
|
|
1290
1403
|
Promise.all([
|
|
1291
|
-
|
|
1292
|
-
|
|
1404
|
+
fetchAuthed(API + "/aggregate").then(function (r) { return r.json(); }),
|
|
1405
|
+
fetchAuthed(API + "/traces").then(function (r) { return r.json(); })
|
|
1293
1406
|
]).then(function (res) {
|
|
1294
1407
|
renderStats(res[0]);
|
|
1295
1408
|
state.traces = res[1] || [];
|
|
@@ -1324,6 +1437,22 @@ function dashboardHtml(basePath, title) {
|
|
|
1324
1437
|
function escapeHtml(value) {
|
|
1325
1438
|
return value.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
|
1326
1439
|
}
|
|
1440
|
+
/**
|
|
1441
|
+
* Encode free-form text (e.g. `evaluate.instructions`, which an operator
|
|
1442
|
+
* could type anything into) as a JS EXPRESSION that reconstructs it at
|
|
1443
|
+
* runtime, WITHOUT ever emitting a literal backtick into the served page —
|
|
1444
|
+
* the client script is itself built from a TS template literal, so a raw
|
|
1445
|
+
* backtick in the output would be a real syntax hazard (see the `BT =
|
|
1446
|
+
* String.fromCharCode(96)` construction already in the client script for
|
|
1447
|
+
* the same reason). `JSON.stringify` alone doesn't escape backticks (they
|
|
1448
|
+
* aren't JSON-significant), so a value containing one is split around it
|
|
1449
|
+
* and rejoined with the client's own `BT` constant. No backticks in the
|
|
1450
|
+
* input ⇒ a single plain `JSON.stringify(value)` — no unnecessary
|
|
1451
|
+
* concatenation in the common case.
|
|
1452
|
+
*/
|
|
1453
|
+
function encodeForInlineScript(value) {
|
|
1454
|
+
return value.split("`").map((part) => JSON.stringify(part)).join(" + BT + ");
|
|
1455
|
+
}
|
|
1327
1456
|
|
|
1328
1457
|
//#endregion
|
|
1329
1458
|
export { dashboardHtml };
|