@meridianlabs/log-viewer 0.3.247 → 0.3.248
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/lib/index.js +1805 -891
- package/lib/index.js.map +1 -1
- package/lib/src/app/App.d.ts.map +1 -1
- package/lib/src/app/log-list/grid/LogListGrid.d.ts.map +1 -1
- package/lib/src/app/log-list/grid/columns/hooks.d.ts +3 -3
- package/lib/src/app/log-list/grid/columns/hooks.d.ts.map +1 -1
- package/lib/src/app/log-list/grid/useLogListData.d.ts.map +1 -1
- package/lib/src/app/log-view/LogViewLayout.d.ts.map +1 -1
- package/lib/src/app/log-view/tabs/SamplesTab.d.ts.map +1 -1
- package/lib/src/app/routing/url.d.ts +10 -1
- package/lib/src/app/routing/url.d.ts.map +1 -1
- package/lib/src/app/samples/SampleDetailComponent.d.ts.map +1 -1
- package/lib/src/app/samples/SampleDisplay.d.ts.map +1 -1
- package/lib/src/app/samples/sample-tools/filters.d.ts.map +1 -1
- package/lib/src/app/samples/transcript/TranscriptPanel.d.ts.map +1 -1
- package/lib/src/app/samples-panel/SamplesPanel.d.ts.map +1 -1
- package/lib/src/app_config/appConfig.d.ts.map +1 -1
- package/lib/src/client/api/client-api.d.ts.map +1 -1
- package/lib/src/client/api/static-http/api-static-http.d.ts.map +1 -1
- package/lib/src/client/api/types.d.ts +46 -2
- package/lib/src/client/api/types.d.ts.map +1 -1
- package/lib/src/client/database/index.d.ts +3 -3
- package/lib/src/client/database/index.d.ts.map +1 -1
- package/lib/src/client/database/manager.d.ts +4 -19
- package/lib/src/client/database/manager.d.ts.map +1 -1
- package/lib/src/client/database/schema.d.ts +26 -4
- package/lib/src/client/database/schema.d.ts.map +1 -1
- package/lib/src/client/database/service.d.ts +35 -19
- package/lib/src/client/database/service.d.ts.map +1 -1
- package/lib/src/client/utils/derive.d.ts +20 -0
- package/lib/src/client/utils/derive.d.ts.map +1 -0
- package/lib/src/client/utils/type-utils.d.ts +19 -2
- package/lib/src/client/utils/type-utils.d.ts.map +1 -1
- package/lib/src/log_data/fetchEngine.d.ts +3 -0
- package/lib/src/log_data/fetchEngine.d.ts.map +1 -1
- package/lib/src/log_data/logsContent.d.ts.map +1 -1
- package/lib/src/log_data/replicationControl.d.ts.map +1 -1
- package/lib/src/log_data/samplesListing.d.ts +5 -3
- package/lib/src/log_data/samplesListing.d.ts.map +1 -1
- package/lib/src/log_data/scoreSchema.d.ts +4 -4
- package/lib/src/log_data/scoreSchema.d.ts.map +1 -1
- package/lib/styles/index.css +125 -60
- package/package.json +3 -2
- package/lib/src/components/FindBand.d.ts +0 -8
- package/lib/src/components/FindBand.d.ts.map +0 -1
- package/lib/src/components/FindBandUI.d.ts +0 -18
- package/lib/src/components/FindBandUI.d.ts.map +0 -1
- package/lib/src/utils/dom.d.ts +0 -29
- package/lib/src/utils/dom.d.ts.map +0 -1
package/lib/index.js
CHANGED
|
@@ -3,7 +3,6 @@ import React3, { Children, Component, Fragment, Suspense, createContext, createE
|
|
|
3
3
|
import * as ReactDOM from "react-dom";
|
|
4
4
|
import xo, { createPortal, flushSync } from "react-dom";
|
|
5
5
|
import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
|
|
6
|
-
import markdownitMathjax3 from "markdown-it-mathjax3";
|
|
7
6
|
//#region \0rolldown/runtime.js
|
|
8
7
|
var __create = Object.create;
|
|
9
8
|
var __defProp = Object.defineProperty;
|
|
@@ -23274,6 +23273,7 @@ var ExtendedFindContext = createContext(null);
|
|
|
23274
23273
|
var ExtendedFindProvider = ({ children }) => {
|
|
23275
23274
|
const virtualLists = useRef(/* @__PURE__ */ new Map());
|
|
23276
23275
|
const matchCounters = useRef(/* @__PURE__ */ new Map());
|
|
23276
|
+
const matchCountersVersion = useRef(0);
|
|
23277
23277
|
const contextValue = {
|
|
23278
23278
|
extendedFindTerm: useCallback(async (term, direction) => {
|
|
23279
23279
|
for (const [, searchFn] of virtualLists.current) if (await new Promise((resolve) => {
|
|
@@ -23311,10 +23311,13 @@ var ExtendedFindProvider = ({ children }) => {
|
|
|
23311
23311
|
}, []),
|
|
23312
23312
|
registerMatchCounter: useCallback((id, countFn) => {
|
|
23313
23313
|
matchCounters.current.set(id, countFn);
|
|
23314
|
+
matchCountersVersion.current++;
|
|
23314
23315
|
return () => {
|
|
23315
23316
|
matchCounters.current.delete(id);
|
|
23317
|
+
matchCountersVersion.current++;
|
|
23316
23318
|
};
|
|
23317
|
-
}, [])
|
|
23319
|
+
}, []),
|
|
23320
|
+
getMatchCountersVersion: useCallback(() => matchCountersVersion.current, [])
|
|
23318
23321
|
};
|
|
23319
23322
|
return /* @__PURE__ */ jsx(ExtendedFindContext.Provider, {
|
|
23320
23323
|
value: contextValue,
|
|
@@ -23465,7 +23468,7 @@ function isRegExp$1(value) {
|
|
|
23465
23468
|
}
|
|
23466
23469
|
//#endregion
|
|
23467
23470
|
//#region ../../node_modules/.pnpm/arquero@8.0.3/node_modules/arquero/src/util/is-object.js
|
|
23468
|
-
function isObject$
|
|
23471
|
+
function isObject$2(value) {
|
|
23469
23472
|
return value === Object(value);
|
|
23470
23473
|
}
|
|
23471
23474
|
//#endregion
|
|
@@ -23479,7 +23482,7 @@ function isObject$1(value) {
|
|
|
23479
23482
|
* @return {boolean} True if equal, false if not.
|
|
23480
23483
|
*/
|
|
23481
23484
|
function equal(a, b) {
|
|
23482
|
-
return a == null || b == null || a !== a || b !== b ? false : a === b ? true : isDate(a) || isDate(b) ? +a === +b : isRegExp$1(a) && isRegExp$1(b) ? a + "" === b + "" : isObject$
|
|
23485
|
+
return a == null || b == null || a !== a || b !== b ? false : a === b ? true : isDate(a) || isDate(b) ? +a === +b : isRegExp$1(a) && isRegExp$1(b) ? a + "" === b + "" : isObject$2(a) && isObject$2(b) ? deepEqual(a, b) : false;
|
|
23483
23486
|
}
|
|
23484
23487
|
function deepEqual(a, b) {
|
|
23485
23488
|
if (Object.getPrototypeOf(a) !== Object.getPrototypeOf(b)) return false;
|
|
@@ -23774,7 +23777,7 @@ var date_exports = /* @__PURE__ */ __exportAll({
|
|
|
23774
23777
|
milliseconds: () => milliseconds,
|
|
23775
23778
|
minutes: () => minutes,
|
|
23776
23779
|
month: () => month,
|
|
23777
|
-
now: () => now,
|
|
23780
|
+
now: () => now$1,
|
|
23778
23781
|
quarter: () => quarter,
|
|
23779
23782
|
seconds: () => seconds,
|
|
23780
23783
|
timestamp: () => timestamp$2,
|
|
@@ -23833,7 +23836,7 @@ function format_utcdate(date, shorten) {
|
|
|
23833
23836
|
* 1970 Universal Coordinated Time (UTC).
|
|
23834
23837
|
* @return {number} The timestamp for now.
|
|
23835
23838
|
*/
|
|
23836
|
-
function now() {
|
|
23839
|
+
function now$1() {
|
|
23837
23840
|
return Date.now();
|
|
23838
23841
|
}
|
|
23839
23842
|
/**
|
|
@@ -24165,7 +24168,7 @@ var math_exports = /* @__PURE__ */ __exportAll({
|
|
|
24165
24168
|
is_finite: () => is_finite,
|
|
24166
24169
|
is_nan: () => is_nan,
|
|
24167
24170
|
least: () => least,
|
|
24168
|
-
log: () => log$
|
|
24171
|
+
log: () => log$8,
|
|
24169
24172
|
log10: () => log10,
|
|
24170
24173
|
log1p: () => log1p,
|
|
24171
24174
|
log2: () => log2,
|
|
@@ -24305,7 +24308,7 @@ function least(...values) {
|
|
|
24305
24308
|
* @param {number} value The input number value.
|
|
24306
24309
|
* @return {number} The base-e log value.
|
|
24307
24310
|
*/
|
|
24308
|
-
function log$
|
|
24311
|
+
function log$8(value) {
|
|
24309
24312
|
return Math.log(value);
|
|
24310
24313
|
}
|
|
24311
24314
|
/**
|
|
@@ -24944,16 +24947,16 @@ function bins(min, max, maxbins = 15, nice = true, minstep = 0, step) {
|
|
|
24944
24947
|
}
|
|
24945
24948
|
//#endregion
|
|
24946
24949
|
//#region ../../node_modules/.pnpm/arquero@8.0.3/node_modules/arquero/src/util/key-function.js
|
|
24947
|
-
function key$
|
|
24950
|
+
function key$6(value) {
|
|
24948
24951
|
const type = typeof value;
|
|
24949
|
-
return type === "string" ? `"${value}"` : type !== "object" || !value ? value : isDate(value) ? +value : isArray$2(value) || isTypedArray(value) ? `[${value.map(key$
|
|
24952
|
+
return type === "string" ? `"${value}"` : type !== "object" || !value ? value : isDate(value) ? +value : isArray$2(value) || isTypedArray(value) ? `[${value.map(key$6)}]` : isRegExp$1(value) ? value + "" : objectKey(value);
|
|
24950
24953
|
}
|
|
24951
24954
|
function objectKey(value) {
|
|
24952
24955
|
let s = "{";
|
|
24953
24956
|
let i = -1;
|
|
24954
24957
|
for (const k in value) {
|
|
24955
24958
|
if (++i > 0) s += ",";
|
|
24956
|
-
s += `"${k}":${key$
|
|
24959
|
+
s += `"${k}":${key$6(value[k])}`;
|
|
24957
24960
|
}
|
|
24958
24961
|
s += "}";
|
|
24959
24962
|
return s;
|
|
@@ -24970,7 +24973,7 @@ function distinctMap() {
|
|
|
24970
24973
|
return Array.from(map.values(), (_) => _.v);
|
|
24971
24974
|
},
|
|
24972
24975
|
increment(v) {
|
|
24973
|
-
const k = key$
|
|
24976
|
+
const k = key$6(v);
|
|
24974
24977
|
const e = map.get(k);
|
|
24975
24978
|
e ? ++e.n : map.set(k, {
|
|
24976
24979
|
v,
|
|
@@ -24978,7 +24981,7 @@ function distinctMap() {
|
|
|
24978
24981
|
});
|
|
24979
24982
|
},
|
|
24980
24983
|
decrement(v) {
|
|
24981
|
-
const k = key$
|
|
24984
|
+
const k = key$6(v);
|
|
24982
24985
|
const e = map.get(k);
|
|
24983
24986
|
e.n === 1 ? map.delete(k) : --e.n;
|
|
24984
24987
|
},
|
|
@@ -26937,10 +26940,10 @@ function nextLineBreak(code, from, end) {
|
|
|
26937
26940
|
var nonASCIIwhitespace = /[\u1680\u2000-\u200a\u202f\u205f\u3000\ufeff]/;
|
|
26938
26941
|
var skipWhiteSpace = /(?:\s|\/\/.*|\/\*[^]*?\*\/)*/g;
|
|
26939
26942
|
var ref = Object.prototype;
|
|
26940
|
-
var hasOwnProperty$
|
|
26943
|
+
var hasOwnProperty$2 = ref.hasOwnProperty;
|
|
26941
26944
|
var toString$1 = ref.toString;
|
|
26942
26945
|
var hasOwn = Object.hasOwn || (function(obj, propName) {
|
|
26943
|
-
return hasOwnProperty$
|
|
26946
|
+
return hasOwnProperty$2.call(obj, propName);
|
|
26944
26947
|
});
|
|
26945
26948
|
var isArray$1 = Array.isArray || (function(obj) {
|
|
26946
26949
|
return toString$1.call(obj) === "[object Array]";
|
|
@@ -31545,6 +31548,16 @@ var clearDocumentSelection = () => {
|
|
|
31545
31548
|
}
|
|
31546
31549
|
};
|
|
31547
31550
|
/**
|
|
31551
|
+
* The focused element, pierced through shadow roots. document.activeElement
|
|
31552
|
+
* only returns the shadow host, so walk down to the real focused element
|
|
31553
|
+
* (e.g. the textarea inside a <vscode-textarea>).
|
|
31554
|
+
*/
|
|
31555
|
+
function deepActiveElement() {
|
|
31556
|
+
let active = document.activeElement;
|
|
31557
|
+
while (active?.shadowRoot?.activeElement) active = active.shadowRoot.activeElement;
|
|
31558
|
+
return active;
|
|
31559
|
+
}
|
|
31560
|
+
/**
|
|
31548
31561
|
* True if the element accepts text input (input/textarea/select/contentEditable).
|
|
31549
31562
|
* Use to skip global keyboard handlers when focus is in a form field.
|
|
31550
31563
|
*/
|
|
@@ -33475,7 +33488,7 @@ function throttle(func, wait, options = {}) {
|
|
|
33475
33488
|
* Creates a debounced version of a function that delays invoking the function
|
|
33476
33489
|
* until after `wait` milliseconds have passed since the last time it was invoked.
|
|
33477
33490
|
*/
|
|
33478
|
-
function debounce$
|
|
33491
|
+
function debounce$3(func, wait, options = {}) {
|
|
33479
33492
|
let timeout = null;
|
|
33480
33493
|
let args;
|
|
33481
33494
|
let result;
|
|
@@ -37824,7 +37837,7 @@ function _class(obj) {
|
|
|
37824
37837
|
function isString(obj) {
|
|
37825
37838
|
return _class(obj) === "[object String]";
|
|
37826
37839
|
}
|
|
37827
|
-
function isObject(obj) {
|
|
37840
|
+
function isObject$1(obj) {
|
|
37828
37841
|
return _class(obj) === "[object Object]";
|
|
37829
37842
|
}
|
|
37830
37843
|
function isRegExp(obj) {
|
|
@@ -37916,7 +37929,7 @@ function compile(self) {
|
|
|
37916
37929
|
link: null
|
|
37917
37930
|
};
|
|
37918
37931
|
self.__compiled__[name] = compiled;
|
|
37919
|
-
if (isObject(val)) {
|
|
37932
|
+
if (isObject$1(val)) {
|
|
37920
37933
|
if (isRegExp(val.validate)) compiled.validate = createValidator(val.validate);
|
|
37921
37934
|
else if (isFunction$2(val.validate)) compiled.validate = val.validate;
|
|
37922
37935
|
else schemaError(name, val);
|
|
@@ -39123,6 +39136,18 @@ MarkdownIt.prototype.renderInline = function(src, env) {
|
|
|
39123
39136
|
* Pure functions for the markdown rendering pipeline.
|
|
39124
39137
|
* Extracted for testability (no CSS/React imports).
|
|
39125
39138
|
*/
|
|
39139
|
+
var mathjaxPluginPromise = null;
|
|
39140
|
+
var getMathjaxPlugin = () => {
|
|
39141
|
+
if (!mathjaxPluginPromise) {
|
|
39142
|
+
const loading = import("markdown-it-mathjax3").then((m) => m.default);
|
|
39143
|
+
loading.catch(() => {
|
|
39144
|
+
if (mathjaxPluginPromise === loading) mathjaxPluginPromise = null;
|
|
39145
|
+
});
|
|
39146
|
+
mathjaxPluginPromise = loading;
|
|
39147
|
+
}
|
|
39148
|
+
return mathjaxPluginPromise;
|
|
39149
|
+
};
|
|
39150
|
+
var hasMathContent = (text) => text.includes("$") || text.includes("\\(") || text.includes("\\[");
|
|
39126
39151
|
var mdInstanceCache = {};
|
|
39127
39152
|
var defaultMarkdownRenderer = "full";
|
|
39128
39153
|
/** Unescape HTML entities within math token content before MathJax processing.
|
|
@@ -39130,15 +39155,17 @@ var defaultMarkdownRenderer = "full";
|
|
|
39130
39155
|
var unescapeHtmlForMath = (content) => {
|
|
39131
39156
|
return content.replace(/</g, "<").replace(/>/g, ">").replace(/&/g, "&").replace(/'/g, "'").replace(/"/g, "\"");
|
|
39132
39157
|
};
|
|
39133
|
-
var getMarkdownInstance = (renderer) => {
|
|
39134
|
-
const
|
|
39158
|
+
var getMarkdownInstance = async (renderer, contentHasMath) => {
|
|
39159
|
+
const useMath = (renderer === "full" || renderer === "fragment") && !!contentHasMath;
|
|
39160
|
+
const cacheKey = `${renderer}:${useMath ? "1" : "0"}`;
|
|
39161
|
+
const cached = mdInstanceCache[cacheKey];
|
|
39135
39162
|
if (cached) return cached;
|
|
39136
39163
|
if (renderer === "textOnly") {
|
|
39137
39164
|
const md = new MarkdownIt("zero", {
|
|
39138
39165
|
breaks: true,
|
|
39139
39166
|
html: false
|
|
39140
39167
|
}).enable(["emphasis", "newline"]);
|
|
39141
|
-
mdInstanceCache[
|
|
39168
|
+
mdInstanceCache[cacheKey] = md;
|
|
39142
39169
|
return md;
|
|
39143
39170
|
}
|
|
39144
39171
|
const md = new MarkdownIt({
|
|
@@ -39158,8 +39185,9 @@ var getMarkdownInstance = (renderer) => {
|
|
|
39158
39185
|
if (!href) return escapedLabel;
|
|
39159
39186
|
return `<a href="${md.utils.escapeHtml(href)}" target="_blank" rel="noopener noreferrer">${escapedLabel}</a>`;
|
|
39160
39187
|
};
|
|
39161
|
-
if (
|
|
39162
|
-
|
|
39188
|
+
if (useMath) {
|
|
39189
|
+
const mathjaxPlugin = await getMathjaxPlugin();
|
|
39190
|
+
md.use(mathjaxPlugin);
|
|
39163
39191
|
const origInline = md.renderer.rules.math_inline;
|
|
39164
39192
|
const origBlock = md.renderer.rules.math_block;
|
|
39165
39193
|
if (origInline) md.renderer.rules.math_inline = (tokens, idx, options, env, self) => {
|
|
@@ -39173,7 +39201,7 @@ var getMarkdownInstance = (renderer) => {
|
|
|
39173
39201
|
return origBlock(tokens, idx, options, env, self);
|
|
39174
39202
|
};
|
|
39175
39203
|
}
|
|
39176
|
-
mdInstanceCache[
|
|
39204
|
+
mdInstanceCache[cacheKey] = md;
|
|
39177
39205
|
return md;
|
|
39178
39206
|
};
|
|
39179
39207
|
var escapeHtmlCharacters$1 = (content) => {
|
|
@@ -39262,20 +39290,20 @@ function unescapeCodeHtmlEntities(str) {
|
|
|
39262
39290
|
return starttag + content.replace(/&(?:amp|lt|gt|quot|#39|#x2F|#x5C|#96);/g, (entity) => htmlEntities[entity] || entity) + endtag;
|
|
39263
39291
|
});
|
|
39264
39292
|
}
|
|
39265
|
-
var renderFullPipelineMarkdown = (markdown, renderer) => {
|
|
39293
|
+
var renderFullPipelineMarkdown = async (markdown, renderer) => {
|
|
39266
39294
|
const preparedForMarkdown = restoreBackslashesForLatex(protectMarkdown(preRenderText(escapeHtmlCharacters$1(protectBackslashesInLatex(markdown)))));
|
|
39267
39295
|
let html = preparedForMarkdown;
|
|
39268
39296
|
try {
|
|
39269
|
-
html = getMarkdownInstance(renderer).render(preparedForMarkdown);
|
|
39297
|
+
html = (await getMarkdownInstance(renderer, hasMathContent(markdown))).render(preparedForMarkdown);
|
|
39270
39298
|
} catch (ex) {
|
|
39271
39299
|
console.log("Unable to markdown render content");
|
|
39272
39300
|
console.error(ex);
|
|
39273
39301
|
}
|
|
39274
39302
|
return unescapeSupHtmlEntities(unescapeCodeHtmlEntities(unprotectMarkdown(html)));
|
|
39275
39303
|
};
|
|
39276
|
-
var renderTextOnlyMarkdown = (markdown) => {
|
|
39304
|
+
var renderTextOnlyMarkdown = async (markdown) => {
|
|
39277
39305
|
try {
|
|
39278
|
-
return getMarkdownInstance("textOnly").render(markdown);
|
|
39306
|
+
return (await getMarkdownInstance("textOnly")).render(markdown);
|
|
39279
39307
|
} catch (ex) {
|
|
39280
39308
|
console.log("Unable to markdown render content");
|
|
39281
39309
|
console.error(ex);
|
|
@@ -39365,7 +39393,7 @@ var booleanToString = unapply(Boolean.prototype.toString);
|
|
|
39365
39393
|
var bigintToString = typeof BigInt === "undefined" ? null : unapply(BigInt.prototype.toString);
|
|
39366
39394
|
var symbolToString = typeof Symbol === "undefined" ? null : unapply(Symbol.prototype.toString);
|
|
39367
39395
|
var objectHasOwnProperty = unapply(Object.prototype.hasOwnProperty);
|
|
39368
|
-
var objectToString = unapply(Object.prototype.toString);
|
|
39396
|
+
var objectToString$1 = unapply(Object.prototype.toString);
|
|
39369
39397
|
var regExpTest = unapply(RegExp.prototype.test);
|
|
39370
39398
|
var typeErrorCreate = unconstruct(TypeError);
|
|
39371
39399
|
/**
|
|
@@ -39460,19 +39488,19 @@ function stringifyValue(value) {
|
|
|
39460
39488
|
case "boolean": return booleanToString(value);
|
|
39461
39489
|
case "bigint": return bigintToString ? bigintToString(value) : "0";
|
|
39462
39490
|
case "symbol": return symbolToString ? symbolToString(value) : "Symbol()";
|
|
39463
|
-
case "undefined": return objectToString(value);
|
|
39491
|
+
case "undefined": return objectToString$1(value);
|
|
39464
39492
|
case "function":
|
|
39465
39493
|
case "object": {
|
|
39466
|
-
if (value === null) return objectToString(value);
|
|
39494
|
+
if (value === null) return objectToString$1(value);
|
|
39467
39495
|
const valueAsRecord = value;
|
|
39468
39496
|
const valueToString = lookupGetter(valueAsRecord, "toString");
|
|
39469
39497
|
if (typeof valueToString === "function") {
|
|
39470
39498
|
const stringified = valueToString(valueAsRecord);
|
|
39471
|
-
return typeof stringified === "string" ? stringified : objectToString(stringified);
|
|
39499
|
+
return typeof stringified === "string" ? stringified : objectToString$1(stringified);
|
|
39472
39500
|
}
|
|
39473
|
-
return objectToString(value);
|
|
39501
|
+
return objectToString$1(value);
|
|
39474
39502
|
}
|
|
39475
|
-
default: return objectToString(value);
|
|
39503
|
+
default: return objectToString$1(value);
|
|
39476
39504
|
}
|
|
39477
39505
|
}
|
|
39478
39506
|
/**
|
|
@@ -41609,8 +41637,8 @@ var MarkdownDivComponent = forwardRef(({ markdown, renderer, style, className, p
|
|
|
41609
41637
|
useEffect(() => {
|
|
41610
41638
|
if (cachedHtml) {
|
|
41611
41639
|
const finalHtml = applyPostProcess(cachedHtml);
|
|
41612
|
-
|
|
41613
|
-
setRenderedHtml(finalHtml);
|
|
41640
|
+
startTransition(() => {
|
|
41641
|
+
setRenderedHtml((prev) => prev === finalHtml ? prev : finalHtml);
|
|
41614
41642
|
});
|
|
41615
41643
|
return;
|
|
41616
41644
|
}
|
|
@@ -41623,9 +41651,8 @@ var MarkdownDivComponent = forwardRef(({ markdown, renderer, style, className, p
|
|
|
41623
41651
|
}
|
|
41624
41652
|
const sanitizedResult = sanitizeRenderedHtml(result);
|
|
41625
41653
|
renderCache.set(cacheKey, sanitizedResult);
|
|
41626
|
-
const finalHtml = applyPostProcess(sanitizedResult);
|
|
41627
41654
|
startTransition(() => {
|
|
41628
|
-
setRenderedHtml(
|
|
41655
|
+
setRenderedHtml(applyPostProcess(sanitizedResult));
|
|
41629
41656
|
});
|
|
41630
41657
|
}).catch((error) => {
|
|
41631
41658
|
console.error("Markdown rendering error:", error);
|
|
@@ -41637,7 +41664,6 @@ var MarkdownDivComponent = forwardRef(({ markdown, renderer, style, className, p
|
|
|
41637
41664
|
markdown,
|
|
41638
41665
|
rendererName,
|
|
41639
41666
|
cachedHtml,
|
|
41640
|
-
renderedHtml,
|
|
41641
41667
|
cacheKey,
|
|
41642
41668
|
applyPostProcess
|
|
41643
41669
|
]);
|
|
@@ -41662,6 +41688,7 @@ var MarkdownRenderQueue = class {
|
|
|
41662
41688
|
}
|
|
41663
41689
|
enqueue(task) {
|
|
41664
41690
|
let cancelled = false;
|
|
41691
|
+
let queueTask;
|
|
41665
41692
|
const promise = new Promise((resolve, reject) => {
|
|
41666
41693
|
const wrappedTask = async () => {
|
|
41667
41694
|
if (cancelled) return;
|
|
@@ -41672,7 +41699,7 @@ var MarkdownRenderQueue = class {
|
|
|
41672
41699
|
if (!cancelled) reject(error instanceof Error ? error : new Error(String(error)));
|
|
41673
41700
|
}
|
|
41674
41701
|
};
|
|
41675
|
-
|
|
41702
|
+
queueTask = {
|
|
41676
41703
|
task: wrappedTask,
|
|
41677
41704
|
cancelled: false
|
|
41678
41705
|
};
|
|
@@ -41681,8 +41708,7 @@ var MarkdownRenderQueue = class {
|
|
|
41681
41708
|
});
|
|
41682
41709
|
const cancel = () => {
|
|
41683
41710
|
cancelled = true;
|
|
41684
|
-
|
|
41685
|
-
if (index !== -1 && this.queue[index]) this.queue[index].cancelled = true;
|
|
41711
|
+
if (queueTask) queueTask.cancelled = true;
|
|
41686
41712
|
};
|
|
41687
41713
|
return {
|
|
41688
41714
|
promise,
|
|
@@ -42891,7 +42917,7 @@ function orderModifiers(modifiers) {
|
|
|
42891
42917
|
}
|
|
42892
42918
|
//#endregion
|
|
42893
42919
|
//#region ../../node_modules/.pnpm/@popperjs+core@2.11.8/node_modules/@popperjs/core/lib/utils/debounce.js
|
|
42894
|
-
function debounce$
|
|
42920
|
+
function debounce$2(fn) {
|
|
42895
42921
|
var pending;
|
|
42896
42922
|
return function() {
|
|
42897
42923
|
if (!pending) pending = new Promise(function(resolve) {
|
|
@@ -42995,7 +43021,7 @@ function popperGenerator(generatorOptions) {
|
|
|
42995
43021
|
}) || state;
|
|
42996
43022
|
}
|
|
42997
43023
|
},
|
|
42998
|
-
update: debounce$
|
|
43024
|
+
update: debounce$2(function() {
|
|
42999
43025
|
return new Promise(function(resolve) {
|
|
43000
43026
|
instance.forceUpdate();
|
|
43001
43027
|
resolve(state);
|
|
@@ -43961,6 +43987,433 @@ function useMapAsyncData(input, transform, errorTransform) {
|
|
|
43961
43987
|
]);
|
|
43962
43988
|
}
|
|
43963
43989
|
//#endregion
|
|
43990
|
+
//#region ../../node_modules/.pnpm/lodash-es@4.18.1/node_modules/lodash-es/_freeGlobal.js
|
|
43991
|
+
/** Detect free variable `global` from Node.js. */
|
|
43992
|
+
var freeGlobal = typeof global == "object" && global && global.Object === Object && global;
|
|
43993
|
+
//#endregion
|
|
43994
|
+
//#region ../../node_modules/.pnpm/lodash-es@4.18.1/node_modules/lodash-es/_root.js
|
|
43995
|
+
/** Detect free variable `self`. */
|
|
43996
|
+
var freeSelf = typeof self == "object" && self && self.Object === Object && self;
|
|
43997
|
+
/** Used as a reference to the global object. */
|
|
43998
|
+
var root$5 = freeGlobal || freeSelf || Function("return this")();
|
|
43999
|
+
//#endregion
|
|
44000
|
+
//#region ../../node_modules/.pnpm/lodash-es@4.18.1/node_modules/lodash-es/_Symbol.js
|
|
44001
|
+
/** Built-in value references. */
|
|
44002
|
+
var Symbol$1 = root$5.Symbol;
|
|
44003
|
+
//#endregion
|
|
44004
|
+
//#region ../../node_modules/.pnpm/lodash-es@4.18.1/node_modules/lodash-es/_getRawTag.js
|
|
44005
|
+
/** Used for built-in method references. */
|
|
44006
|
+
var objectProto = Object.prototype;
|
|
44007
|
+
/** Used to check objects for own properties. */
|
|
44008
|
+
var hasOwnProperty$1 = objectProto.hasOwnProperty;
|
|
44009
|
+
/**
|
|
44010
|
+
* Used to resolve the
|
|
44011
|
+
* [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring)
|
|
44012
|
+
* of values.
|
|
44013
|
+
*/
|
|
44014
|
+
var nativeObjectToString$1 = objectProto.toString;
|
|
44015
|
+
/** Built-in value references. */
|
|
44016
|
+
var symToStringTag$1 = Symbol$1 ? Symbol$1.toStringTag : void 0;
|
|
44017
|
+
/**
|
|
44018
|
+
* A specialized version of `baseGetTag` which ignores `Symbol.toStringTag` values.
|
|
44019
|
+
*
|
|
44020
|
+
* @private
|
|
44021
|
+
* @param {*} value The value to query.
|
|
44022
|
+
* @returns {string} Returns the raw `toStringTag`.
|
|
44023
|
+
*/
|
|
44024
|
+
function getRawTag(value) {
|
|
44025
|
+
var isOwn = hasOwnProperty$1.call(value, symToStringTag$1), tag = value[symToStringTag$1];
|
|
44026
|
+
try {
|
|
44027
|
+
value[symToStringTag$1] = void 0;
|
|
44028
|
+
var unmasked = true;
|
|
44029
|
+
} catch (e) {}
|
|
44030
|
+
var result = nativeObjectToString$1.call(value);
|
|
44031
|
+
if (unmasked) if (isOwn) value[symToStringTag$1] = tag;
|
|
44032
|
+
else delete value[symToStringTag$1];
|
|
44033
|
+
return result;
|
|
44034
|
+
}
|
|
44035
|
+
//#endregion
|
|
44036
|
+
//#region ../../node_modules/.pnpm/lodash-es@4.18.1/node_modules/lodash-es/_objectToString.js
|
|
44037
|
+
/**
|
|
44038
|
+
* Used to resolve the
|
|
44039
|
+
* [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring)
|
|
44040
|
+
* of values.
|
|
44041
|
+
*/
|
|
44042
|
+
var nativeObjectToString = Object.prototype.toString;
|
|
44043
|
+
/**
|
|
44044
|
+
* Converts `value` to a string using `Object.prototype.toString`.
|
|
44045
|
+
*
|
|
44046
|
+
* @private
|
|
44047
|
+
* @param {*} value The value to convert.
|
|
44048
|
+
* @returns {string} Returns the converted string.
|
|
44049
|
+
*/
|
|
44050
|
+
function objectToString(value) {
|
|
44051
|
+
return nativeObjectToString.call(value);
|
|
44052
|
+
}
|
|
44053
|
+
//#endregion
|
|
44054
|
+
//#region ../../node_modules/.pnpm/lodash-es@4.18.1/node_modules/lodash-es/_baseGetTag.js
|
|
44055
|
+
/** `Object#toString` result references. */
|
|
44056
|
+
var nullTag = "[object Null]", undefinedTag = "[object Undefined]";
|
|
44057
|
+
/** Built-in value references. */
|
|
44058
|
+
var symToStringTag = Symbol$1 ? Symbol$1.toStringTag : void 0;
|
|
44059
|
+
/**
|
|
44060
|
+
* The base implementation of `getTag` without fallbacks for buggy environments.
|
|
44061
|
+
*
|
|
44062
|
+
* @private
|
|
44063
|
+
* @param {*} value The value to query.
|
|
44064
|
+
* @returns {string} Returns the `toStringTag`.
|
|
44065
|
+
*/
|
|
44066
|
+
function baseGetTag(value) {
|
|
44067
|
+
if (value == null) return value === void 0 ? undefinedTag : nullTag;
|
|
44068
|
+
return symToStringTag && symToStringTag in Object(value) ? getRawTag(value) : objectToString(value);
|
|
44069
|
+
}
|
|
44070
|
+
//#endregion
|
|
44071
|
+
//#region ../../node_modules/.pnpm/lodash-es@4.18.1/node_modules/lodash-es/isObjectLike.js
|
|
44072
|
+
/**
|
|
44073
|
+
* Checks if `value` is object-like. A value is object-like if it's not `null`
|
|
44074
|
+
* and has a `typeof` result of "object".
|
|
44075
|
+
*
|
|
44076
|
+
* @static
|
|
44077
|
+
* @memberOf _
|
|
44078
|
+
* @since 4.0.0
|
|
44079
|
+
* @category Lang
|
|
44080
|
+
* @param {*} value The value to check.
|
|
44081
|
+
* @returns {boolean} Returns `true` if `value` is object-like, else `false`.
|
|
44082
|
+
* @example
|
|
44083
|
+
*
|
|
44084
|
+
* _.isObjectLike({});
|
|
44085
|
+
* // => true
|
|
44086
|
+
*
|
|
44087
|
+
* _.isObjectLike([1, 2, 3]);
|
|
44088
|
+
* // => true
|
|
44089
|
+
*
|
|
44090
|
+
* _.isObjectLike(_.noop);
|
|
44091
|
+
* // => false
|
|
44092
|
+
*
|
|
44093
|
+
* _.isObjectLike(null);
|
|
44094
|
+
* // => false
|
|
44095
|
+
*/
|
|
44096
|
+
function isObjectLike(value) {
|
|
44097
|
+
return value != null && typeof value == "object";
|
|
44098
|
+
}
|
|
44099
|
+
//#endregion
|
|
44100
|
+
//#region ../../node_modules/.pnpm/lodash-es@4.18.1/node_modules/lodash-es/isSymbol.js
|
|
44101
|
+
/** `Object#toString` result references. */
|
|
44102
|
+
var symbolTag = "[object Symbol]";
|
|
44103
|
+
/**
|
|
44104
|
+
* Checks if `value` is classified as a `Symbol` primitive or object.
|
|
44105
|
+
*
|
|
44106
|
+
* @static
|
|
44107
|
+
* @memberOf _
|
|
44108
|
+
* @since 4.0.0
|
|
44109
|
+
* @category Lang
|
|
44110
|
+
* @param {*} value The value to check.
|
|
44111
|
+
* @returns {boolean} Returns `true` if `value` is a symbol, else `false`.
|
|
44112
|
+
* @example
|
|
44113
|
+
*
|
|
44114
|
+
* _.isSymbol(Symbol.iterator);
|
|
44115
|
+
* // => true
|
|
44116
|
+
*
|
|
44117
|
+
* _.isSymbol('abc');
|
|
44118
|
+
* // => false
|
|
44119
|
+
*/
|
|
44120
|
+
function isSymbol(value) {
|
|
44121
|
+
return typeof value == "symbol" || isObjectLike(value) && baseGetTag(value) == symbolTag;
|
|
44122
|
+
}
|
|
44123
|
+
//#endregion
|
|
44124
|
+
//#region ../../node_modules/.pnpm/lodash-es@4.18.1/node_modules/lodash-es/_trimmedEndIndex.js
|
|
44125
|
+
/** Used to match a single whitespace character. */
|
|
44126
|
+
var reWhitespace = /\s/;
|
|
44127
|
+
/**
|
|
44128
|
+
* Used by `_.trim` and `_.trimEnd` to get the index of the last non-whitespace
|
|
44129
|
+
* character of `string`.
|
|
44130
|
+
*
|
|
44131
|
+
* @private
|
|
44132
|
+
* @param {string} string The string to inspect.
|
|
44133
|
+
* @returns {number} Returns the index of the last non-whitespace character.
|
|
44134
|
+
*/
|
|
44135
|
+
function trimmedEndIndex(string) {
|
|
44136
|
+
var index = string.length;
|
|
44137
|
+
while (index-- && reWhitespace.test(string.charAt(index)));
|
|
44138
|
+
return index;
|
|
44139
|
+
}
|
|
44140
|
+
//#endregion
|
|
44141
|
+
//#region ../../node_modules/.pnpm/lodash-es@4.18.1/node_modules/lodash-es/_baseTrim.js
|
|
44142
|
+
/** Used to match leading whitespace. */
|
|
44143
|
+
var reTrimStart = /^\s+/;
|
|
44144
|
+
/**
|
|
44145
|
+
* The base implementation of `_.trim`.
|
|
44146
|
+
*
|
|
44147
|
+
* @private
|
|
44148
|
+
* @param {string} string The string to trim.
|
|
44149
|
+
* @returns {string} Returns the trimmed string.
|
|
44150
|
+
*/
|
|
44151
|
+
function baseTrim(string) {
|
|
44152
|
+
return string ? string.slice(0, trimmedEndIndex(string) + 1).replace(reTrimStart, "") : string;
|
|
44153
|
+
}
|
|
44154
|
+
//#endregion
|
|
44155
|
+
//#region ../../node_modules/.pnpm/lodash-es@4.18.1/node_modules/lodash-es/isObject.js
|
|
44156
|
+
/**
|
|
44157
|
+
* Checks if `value` is the
|
|
44158
|
+
* [language type](http://www.ecma-international.org/ecma-262/7.0/#sec-ecmascript-language-types)
|
|
44159
|
+
* of `Object`. (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`)
|
|
44160
|
+
*
|
|
44161
|
+
* @static
|
|
44162
|
+
* @memberOf _
|
|
44163
|
+
* @since 0.1.0
|
|
44164
|
+
* @category Lang
|
|
44165
|
+
* @param {*} value The value to check.
|
|
44166
|
+
* @returns {boolean} Returns `true` if `value` is an object, else `false`.
|
|
44167
|
+
* @example
|
|
44168
|
+
*
|
|
44169
|
+
* _.isObject({});
|
|
44170
|
+
* // => true
|
|
44171
|
+
*
|
|
44172
|
+
* _.isObject([1, 2, 3]);
|
|
44173
|
+
* // => true
|
|
44174
|
+
*
|
|
44175
|
+
* _.isObject(_.noop);
|
|
44176
|
+
* // => true
|
|
44177
|
+
*
|
|
44178
|
+
* _.isObject(null);
|
|
44179
|
+
* // => false
|
|
44180
|
+
*/
|
|
44181
|
+
function isObject(value) {
|
|
44182
|
+
var type = typeof value;
|
|
44183
|
+
return value != null && (type == "object" || type == "function");
|
|
44184
|
+
}
|
|
44185
|
+
//#endregion
|
|
44186
|
+
//#region ../../node_modules/.pnpm/lodash-es@4.18.1/node_modules/lodash-es/toNumber.js
|
|
44187
|
+
/** Used as references for various `Number` constants. */
|
|
44188
|
+
var NAN = NaN;
|
|
44189
|
+
/** Used to detect bad signed hexadecimal string values. */
|
|
44190
|
+
var reIsBadHex = /^[-+]0x[0-9a-f]+$/i;
|
|
44191
|
+
/** Used to detect binary string values. */
|
|
44192
|
+
var reIsBinary = /^0b[01]+$/i;
|
|
44193
|
+
/** Used to detect octal string values. */
|
|
44194
|
+
var reIsOctal = /^0o[0-7]+$/i;
|
|
44195
|
+
/** Built-in method references without a dependency on `root`. */
|
|
44196
|
+
var freeParseInt = parseInt;
|
|
44197
|
+
/**
|
|
44198
|
+
* Converts `value` to a number.
|
|
44199
|
+
*
|
|
44200
|
+
* @static
|
|
44201
|
+
* @memberOf _
|
|
44202
|
+
* @since 4.0.0
|
|
44203
|
+
* @category Lang
|
|
44204
|
+
* @param {*} value The value to process.
|
|
44205
|
+
* @returns {number} Returns the number.
|
|
44206
|
+
* @example
|
|
44207
|
+
*
|
|
44208
|
+
* _.toNumber(3.2);
|
|
44209
|
+
* // => 3.2
|
|
44210
|
+
*
|
|
44211
|
+
* _.toNumber(Number.MIN_VALUE);
|
|
44212
|
+
* // => 5e-324
|
|
44213
|
+
*
|
|
44214
|
+
* _.toNumber(Infinity);
|
|
44215
|
+
* // => Infinity
|
|
44216
|
+
*
|
|
44217
|
+
* _.toNumber('3.2');
|
|
44218
|
+
* // => 3.2
|
|
44219
|
+
*/
|
|
44220
|
+
function toNumber(value) {
|
|
44221
|
+
if (typeof value == "number") return value;
|
|
44222
|
+
if (isSymbol(value)) return NAN;
|
|
44223
|
+
if (isObject(value)) {
|
|
44224
|
+
var other = typeof value.valueOf == "function" ? value.valueOf() : value;
|
|
44225
|
+
value = isObject(other) ? other + "" : other;
|
|
44226
|
+
}
|
|
44227
|
+
if (typeof value != "string") return value === 0 ? value : +value;
|
|
44228
|
+
value = baseTrim(value);
|
|
44229
|
+
var isBinary = reIsBinary.test(value);
|
|
44230
|
+
return isBinary || reIsOctal.test(value) ? freeParseInt(value.slice(2), isBinary ? 2 : 8) : reIsBadHex.test(value) ? NAN : +value;
|
|
44231
|
+
}
|
|
44232
|
+
//#endregion
|
|
44233
|
+
//#region ../../node_modules/.pnpm/lodash-es@4.18.1/node_modules/lodash-es/now.js
|
|
44234
|
+
/**
|
|
44235
|
+
* Gets the timestamp of the number of milliseconds that have elapsed since
|
|
44236
|
+
* the Unix epoch (1 January 1970 00:00:00 UTC).
|
|
44237
|
+
*
|
|
44238
|
+
* @static
|
|
44239
|
+
* @memberOf _
|
|
44240
|
+
* @since 2.4.0
|
|
44241
|
+
* @category Date
|
|
44242
|
+
* @returns {number} Returns the timestamp.
|
|
44243
|
+
* @example
|
|
44244
|
+
*
|
|
44245
|
+
* _.defer(function(stamp) {
|
|
44246
|
+
* console.log(_.now() - stamp);
|
|
44247
|
+
* }, _.now());
|
|
44248
|
+
* // => Logs the number of milliseconds it took for the deferred invocation.
|
|
44249
|
+
*/
|
|
44250
|
+
var now = function() {
|
|
44251
|
+
return root$5.Date.now();
|
|
44252
|
+
};
|
|
44253
|
+
//#endregion
|
|
44254
|
+
//#region ../../node_modules/.pnpm/lodash-es@4.18.1/node_modules/lodash-es/debounce.js
|
|
44255
|
+
/** Error message constants. */
|
|
44256
|
+
var FUNC_ERROR_TEXT = "Expected a function";
|
|
44257
|
+
var nativeMax = Math.max, nativeMin = Math.min;
|
|
44258
|
+
/**
|
|
44259
|
+
* Creates a debounced function that delays invoking `func` until after `wait`
|
|
44260
|
+
* milliseconds have elapsed since the last time the debounced function was
|
|
44261
|
+
* invoked. The debounced function comes with a `cancel` method to cancel
|
|
44262
|
+
* delayed `func` invocations and a `flush` method to immediately invoke them.
|
|
44263
|
+
* Provide `options` to indicate whether `func` should be invoked on the
|
|
44264
|
+
* leading and/or trailing edge of the `wait` timeout. The `func` is invoked
|
|
44265
|
+
* with the last arguments provided to the debounced function. Subsequent
|
|
44266
|
+
* calls to the debounced function return the result of the last `func`
|
|
44267
|
+
* invocation.
|
|
44268
|
+
*
|
|
44269
|
+
* **Note:** If `leading` and `trailing` options are `true`, `func` is
|
|
44270
|
+
* invoked on the trailing edge of the timeout only if the debounced function
|
|
44271
|
+
* is invoked more than once during the `wait` timeout.
|
|
44272
|
+
*
|
|
44273
|
+
* If `wait` is `0` and `leading` is `false`, `func` invocation is deferred
|
|
44274
|
+
* until to the next tick, similar to `setTimeout` with a timeout of `0`.
|
|
44275
|
+
*
|
|
44276
|
+
* See [David Corbacho's article](https://css-tricks.com/debouncing-throttling-explained-examples/)
|
|
44277
|
+
* for details over the differences between `_.debounce` and `_.throttle`.
|
|
44278
|
+
*
|
|
44279
|
+
* @static
|
|
44280
|
+
* @memberOf _
|
|
44281
|
+
* @since 0.1.0
|
|
44282
|
+
* @category Function
|
|
44283
|
+
* @param {Function} func The function to debounce.
|
|
44284
|
+
* @param {number} [wait=0] The number of milliseconds to delay.
|
|
44285
|
+
* @param {Object} [options={}] The options object.
|
|
44286
|
+
* @param {boolean} [options.leading=false]
|
|
44287
|
+
* Specify invoking on the leading edge of the timeout.
|
|
44288
|
+
* @param {number} [options.maxWait]
|
|
44289
|
+
* The maximum time `func` is allowed to be delayed before it's invoked.
|
|
44290
|
+
* @param {boolean} [options.trailing=true]
|
|
44291
|
+
* Specify invoking on the trailing edge of the timeout.
|
|
44292
|
+
* @returns {Function} Returns the new debounced function.
|
|
44293
|
+
* @example
|
|
44294
|
+
*
|
|
44295
|
+
* // Avoid costly calculations while the window size is in flux.
|
|
44296
|
+
* jQuery(window).on('resize', _.debounce(calculateLayout, 150));
|
|
44297
|
+
*
|
|
44298
|
+
* // Invoke `sendMail` when clicked, debouncing subsequent calls.
|
|
44299
|
+
* jQuery(element).on('click', _.debounce(sendMail, 300, {
|
|
44300
|
+
* 'leading': true,
|
|
44301
|
+
* 'trailing': false
|
|
44302
|
+
* }));
|
|
44303
|
+
*
|
|
44304
|
+
* // Ensure `batchLog` is invoked once after 1 second of debounced calls.
|
|
44305
|
+
* var debounced = _.debounce(batchLog, 250, { 'maxWait': 1000 });
|
|
44306
|
+
* var source = new EventSource('/stream');
|
|
44307
|
+
* jQuery(source).on('message', debounced);
|
|
44308
|
+
*
|
|
44309
|
+
* // Cancel the trailing debounced invocation.
|
|
44310
|
+
* jQuery(window).on('popstate', debounced.cancel);
|
|
44311
|
+
*/
|
|
44312
|
+
function debounce$1(func, wait, options) {
|
|
44313
|
+
var lastArgs, lastThis, maxWait, result, timerId, lastCallTime, lastInvokeTime = 0, leading = false, maxing = false, trailing = true;
|
|
44314
|
+
if (typeof func != "function") throw new TypeError(FUNC_ERROR_TEXT);
|
|
44315
|
+
wait = toNumber(wait) || 0;
|
|
44316
|
+
if (isObject(options)) {
|
|
44317
|
+
leading = !!options.leading;
|
|
44318
|
+
maxing = "maxWait" in options;
|
|
44319
|
+
maxWait = maxing ? nativeMax(toNumber(options.maxWait) || 0, wait) : maxWait;
|
|
44320
|
+
trailing = "trailing" in options ? !!options.trailing : trailing;
|
|
44321
|
+
}
|
|
44322
|
+
function invokeFunc(time) {
|
|
44323
|
+
var args = lastArgs, thisArg = lastThis;
|
|
44324
|
+
lastArgs = lastThis = void 0;
|
|
44325
|
+
lastInvokeTime = time;
|
|
44326
|
+
result = func.apply(thisArg, args);
|
|
44327
|
+
return result;
|
|
44328
|
+
}
|
|
44329
|
+
function leadingEdge(time) {
|
|
44330
|
+
lastInvokeTime = time;
|
|
44331
|
+
timerId = setTimeout(timerExpired, wait);
|
|
44332
|
+
return leading ? invokeFunc(time) : result;
|
|
44333
|
+
}
|
|
44334
|
+
function remainingWait(time) {
|
|
44335
|
+
var timeSinceLastCall = time - lastCallTime, timeSinceLastInvoke = time - lastInvokeTime, timeWaiting = wait - timeSinceLastCall;
|
|
44336
|
+
return maxing ? nativeMin(timeWaiting, maxWait - timeSinceLastInvoke) : timeWaiting;
|
|
44337
|
+
}
|
|
44338
|
+
function shouldInvoke(time) {
|
|
44339
|
+
var timeSinceLastCall = time - lastCallTime, timeSinceLastInvoke = time - lastInvokeTime;
|
|
44340
|
+
return lastCallTime === void 0 || timeSinceLastCall >= wait || timeSinceLastCall < 0 || maxing && timeSinceLastInvoke >= maxWait;
|
|
44341
|
+
}
|
|
44342
|
+
function timerExpired() {
|
|
44343
|
+
var time = now();
|
|
44344
|
+
if (shouldInvoke(time)) return trailingEdge(time);
|
|
44345
|
+
timerId = setTimeout(timerExpired, remainingWait(time));
|
|
44346
|
+
}
|
|
44347
|
+
function trailingEdge(time) {
|
|
44348
|
+
timerId = void 0;
|
|
44349
|
+
if (trailing && lastArgs) return invokeFunc(time);
|
|
44350
|
+
lastArgs = lastThis = void 0;
|
|
44351
|
+
return result;
|
|
44352
|
+
}
|
|
44353
|
+
function cancel() {
|
|
44354
|
+
if (timerId !== void 0) clearTimeout(timerId);
|
|
44355
|
+
lastInvokeTime = 0;
|
|
44356
|
+
lastArgs = lastCallTime = lastThis = timerId = void 0;
|
|
44357
|
+
}
|
|
44358
|
+
function flush() {
|
|
44359
|
+
return timerId === void 0 ? result : trailingEdge(now());
|
|
44360
|
+
}
|
|
44361
|
+
function debounced() {
|
|
44362
|
+
var time = now(), isInvoking = shouldInvoke(time);
|
|
44363
|
+
lastArgs = arguments;
|
|
44364
|
+
lastThis = this;
|
|
44365
|
+
lastCallTime = time;
|
|
44366
|
+
if (isInvoking) {
|
|
44367
|
+
if (timerId === void 0) return leadingEdge(lastCallTime);
|
|
44368
|
+
if (maxing) {
|
|
44369
|
+
clearTimeout(timerId);
|
|
44370
|
+
timerId = setTimeout(timerExpired, wait);
|
|
44371
|
+
return invokeFunc(lastCallTime);
|
|
44372
|
+
}
|
|
44373
|
+
}
|
|
44374
|
+
if (timerId === void 0) timerId = setTimeout(timerExpired, wait);
|
|
44375
|
+
return result;
|
|
44376
|
+
}
|
|
44377
|
+
debounced.cancel = cancel;
|
|
44378
|
+
debounced.flush = flush;
|
|
44379
|
+
return debounced;
|
|
44380
|
+
}
|
|
44381
|
+
//#endregion
|
|
44382
|
+
//#region ../../packages/react/src/hooks/useDebouncedCallback.ts
|
|
44383
|
+
/**
|
|
44384
|
+
* Creates a debounced version of a callback that always calls the latest version.
|
|
44385
|
+
*
|
|
44386
|
+
* Unlike `useMemo(() => debounce(fn), [])`, this hook ensures the debounced function
|
|
44387
|
+
* always invokes the most recent callback, eliminating the need for refs to access
|
|
44388
|
+
* current state values.
|
|
44389
|
+
*
|
|
44390
|
+
* @param callback - The function to debounce. Can close over current state/props.
|
|
44391
|
+
* @param delay - Debounce delay in milliseconds
|
|
44392
|
+
* @returns A stable debounced function that calls the latest callback
|
|
44393
|
+
*
|
|
44394
|
+
* @example
|
|
44395
|
+
* const debouncedSave = useDebouncedCallback(() => {
|
|
44396
|
+
* // Access current state directly - no refs needed
|
|
44397
|
+
* if (!workingCase) return;
|
|
44398
|
+
* mutation.mutate({ data: workingCase });
|
|
44399
|
+
* }, 600);
|
|
44400
|
+
*/
|
|
44401
|
+
function useDebouncedCallback(callback, delay) {
|
|
44402
|
+
const callbackRef = useRef(callback);
|
|
44403
|
+
useLayoutEffect(() => {
|
|
44404
|
+
callbackRef.current = callback;
|
|
44405
|
+
});
|
|
44406
|
+
const debouncedFn = useMemo(() => debounce$1((...args) => {
|
|
44407
|
+
callbackRef.current(...args);
|
|
44408
|
+
}, delay), [delay]);
|
|
44409
|
+
useEffect(() => {
|
|
44410
|
+
return () => {
|
|
44411
|
+
debouncedFn.cancel();
|
|
44412
|
+
};
|
|
44413
|
+
}, [debouncedFn]);
|
|
44414
|
+
return debouncedFn;
|
|
44415
|
+
}
|
|
44416
|
+
//#endregion
|
|
43964
44417
|
//#region ../../packages/react/src/hooks/useAsyncDataFromQuery.ts
|
|
43965
44418
|
/**
|
|
43966
44419
|
* Custom hook that retrieves data using `useQuery` from the `@tanstack/react-query`
|
|
@@ -44288,7 +44741,7 @@ var useCollapsibleIds = (key) => {
|
|
|
44288
44741
|
};
|
|
44289
44742
|
//#endregion
|
|
44290
44743
|
//#region ../../packages/react/src/hooks/useStatefulScrollPosition.ts
|
|
44291
|
-
var log$
|
|
44744
|
+
var log$7 = createLogger("scrolling");
|
|
44292
44745
|
function useStatefulScrollPosition(elementRef, elementKey, delay = 1e3, scrollable = true) {
|
|
44293
44746
|
const [scrollPosition, setScrollPosition] = useProperty("scrollPosition", elementKey);
|
|
44294
44747
|
const scrollPositionRef = useRef(scrollPosition);
|
|
@@ -44297,10 +44750,10 @@ function useStatefulScrollPosition(elementRef, elementKey, delay = 1e3, scrollab
|
|
|
44297
44750
|
}, [scrollPosition]);
|
|
44298
44751
|
const handleScrollInner = useCallback((e) => {
|
|
44299
44752
|
const position = e.target.scrollTop;
|
|
44300
|
-
log$
|
|
44753
|
+
log$7.debug(`Storing scroll position`, elementKey, position);
|
|
44301
44754
|
setScrollPosition(position);
|
|
44302
44755
|
}, [elementKey, setScrollPosition]);
|
|
44303
|
-
const handleScroll = useMemo(() => debounce$
|
|
44756
|
+
const handleScroll = useMemo(() => debounce$3(handleScrollInner, delay), [handleScrollInner, delay]);
|
|
44304
44757
|
const restoreScrollPosition = useCallback(() => {
|
|
44305
44758
|
const element = elementRef.current;
|
|
44306
44759
|
const savedPosition = scrollPositionRef.current;
|
|
@@ -44314,15 +44767,15 @@ function useStatefulScrollPosition(elementRef, elementKey, delay = 1e3, scrollab
|
|
|
44314
44767
|
useEffect(() => {
|
|
44315
44768
|
const element = elementRef.current;
|
|
44316
44769
|
if (!element || !scrollable) return;
|
|
44317
|
-
log$
|
|
44770
|
+
log$7.debug(`Restore Scroll Hook`, elementKey);
|
|
44318
44771
|
const savedPosition = scrollPositionRef.current;
|
|
44319
44772
|
if (savedPosition !== void 0) {
|
|
44320
|
-
log$
|
|
44773
|
+
log$7.debug(`Restoring scroll position`, savedPosition);
|
|
44321
44774
|
const tryRestoreScroll = () => {
|
|
44322
44775
|
if (element.scrollHeight > element.clientHeight) {
|
|
44323
44776
|
if (element.scrollTop !== savedPosition) {
|
|
44324
44777
|
element.scrollTop = savedPosition;
|
|
44325
|
-
log$
|
|
44778
|
+
log$7.debug(`Scroll position restored to ${savedPosition}`);
|
|
44326
44779
|
}
|
|
44327
44780
|
return true;
|
|
44328
44781
|
}
|
|
@@ -44333,7 +44786,7 @@ function useStatefulScrollPosition(elementRef, elementKey, delay = 1e3, scrollab
|
|
|
44333
44786
|
const maxAttempts = 20;
|
|
44334
44787
|
const pollForRender = () => {
|
|
44335
44788
|
if (tryRestoreScroll() || attempts >= maxAttempts) {
|
|
44336
|
-
if (attempts >= maxAttempts) log$
|
|
44789
|
+
if (attempts >= maxAttempts) log$7.debug(`Failed to restore scroll after ${maxAttempts} attempts`);
|
|
44337
44790
|
return;
|
|
44338
44791
|
}
|
|
44339
44792
|
attempts++;
|
|
@@ -44343,10 +44796,10 @@ function useStatefulScrollPosition(elementRef, elementKey, delay = 1e3, scrollab
|
|
|
44343
44796
|
}
|
|
44344
44797
|
}
|
|
44345
44798
|
if (element.addEventListener) element.addEventListener("scroll", handleScroll);
|
|
44346
|
-
else log$
|
|
44799
|
+
else log$7.warn("Element has no way to add event listener", element);
|
|
44347
44800
|
return () => {
|
|
44348
44801
|
if (element.removeEventListener) element.removeEventListener("scroll", handleScroll);
|
|
44349
|
-
else log$
|
|
44802
|
+
else log$7.warn("Element has no way to remove event listener", element);
|
|
44350
44803
|
};
|
|
44351
44804
|
}, [
|
|
44352
44805
|
elementKey,
|
|
@@ -44543,7 +44996,7 @@ function useListKeyboardNavigation({ listHandle, scrollRef, itemCount }) {
|
|
|
44543
44996
|
const isUp = event.key === "ArrowUp" && hasModifier || event.key === "Home" && hasModifier;
|
|
44544
44997
|
const isDown = event.key === "ArrowDown" && hasModifier || event.key === "End" && hasModifier;
|
|
44545
44998
|
if (!isUp && !isDown) return;
|
|
44546
|
-
if (isEditableTarget(
|
|
44999
|
+
if (isEditableTarget(deepActiveElement())) return;
|
|
44547
45000
|
event.preventDefault();
|
|
44548
45001
|
event.stopImmediatePropagation();
|
|
44549
45002
|
const handle = listHandle.current;
|
|
@@ -44878,6 +45331,56 @@ var ToolDropdownButton = forwardRef(({ label, icon, className, items, dropdownAl
|
|
|
44878
45331
|
})] }), document.body)] });
|
|
44879
45332
|
});
|
|
44880
45333
|
ToolDropdownButton.displayName = "ToolDropdownButton";
|
|
45334
|
+
var NavPills_module_default = {
|
|
45335
|
+
visible: "_visible_tm52u_1",
|
|
45336
|
+
hidden: "_hidden_tm52u_5",
|
|
45337
|
+
pills: "_pills_tm52u_9",
|
|
45338
|
+
pill: "_pill_tm52u_9"
|
|
45339
|
+
};
|
|
45340
|
+
//#endregion
|
|
45341
|
+
//#region ../../packages/react/src/components/NavPills.tsx
|
|
45342
|
+
var NavPills = ({ id, children }) => {
|
|
45343
|
+
const [activeItem, setActiveItem] = useProperty(id, "active", { defaultValue: children ? children?.[0]?.props["title"] : "" });
|
|
45344
|
+
if (!activeItem || !children) return;
|
|
45345
|
+
const navPills = children.map((nav, idx) => {
|
|
45346
|
+
return /* @__PURE__ */ jsx(NavPill, {
|
|
45347
|
+
title: typeof nav === "object" ? nav["props"]?.title || `Tab ${idx}` : `Tab ${idx}`,
|
|
45348
|
+
activeItem,
|
|
45349
|
+
setActiveItem
|
|
45350
|
+
}, `nav-pill-contents-${idx}`);
|
|
45351
|
+
});
|
|
45352
|
+
const navBodies = children.map((child, idx) => {
|
|
45353
|
+
return /* @__PURE__ */ jsx("div", {
|
|
45354
|
+
className: child["props"]?.title === activeItem ? NavPills_module_default.visible : NavPills_module_default.hidden,
|
|
45355
|
+
children: child
|
|
45356
|
+
}, `nav-pill-container-${idx}`);
|
|
45357
|
+
});
|
|
45358
|
+
return /* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx("ul", {
|
|
45359
|
+
className: clsx("nav", "nav-pills", NavPills_module_default.pills),
|
|
45360
|
+
role: "tablist",
|
|
45361
|
+
"aria-orientation": "horizontal",
|
|
45362
|
+
children: navPills
|
|
45363
|
+
}), navBodies] });
|
|
45364
|
+
};
|
|
45365
|
+
var NavPill = ({ title, activeItem, setActiveItem, children }) => {
|
|
45366
|
+
const active = activeItem === title;
|
|
45367
|
+
const handleClick = useCallback((e) => {
|
|
45368
|
+
const target = e.currentTarget.dataset.target;
|
|
45369
|
+
if (target) setActiveItem(target);
|
|
45370
|
+
}, [setActiveItem]);
|
|
45371
|
+
return /* @__PURE__ */ jsxs("li", {
|
|
45372
|
+
className: "nav-item",
|
|
45373
|
+
children: [/* @__PURE__ */ jsx("button", {
|
|
45374
|
+
type: "button",
|
|
45375
|
+
role: "tab",
|
|
45376
|
+
"aria-selected": active,
|
|
45377
|
+
className: clsx("nav-link", "text-style-label", active ? "active " : "", NavPills_module_default.pill),
|
|
45378
|
+
"data-target": title,
|
|
45379
|
+
onClick: handleClick,
|
|
45380
|
+
children: title
|
|
45381
|
+
}), children]
|
|
45382
|
+
});
|
|
45383
|
+
};
|
|
44881
45384
|
var TabSet_module_default = {
|
|
44882
45385
|
tabs: "_tabs_1792l_1",
|
|
44883
45386
|
tabContents: "_tabContents_1792l_5",
|
|
@@ -45324,6 +45827,503 @@ var useComponentNavigation = () => {
|
|
|
45324
45827
|
if (!navigation) throw new Error("useComponentNavigation must be used within a ComponentNavigationProvider");
|
|
45325
45828
|
return navigation;
|
|
45326
45829
|
};
|
|
45830
|
+
//#endregion
|
|
45831
|
+
//#region ../../packages/react/src/components/findBandDom.ts
|
|
45832
|
+
/**
|
|
45833
|
+
* Finds the nearest scrollable ancestor with enough overflow to benefit from
|
|
45834
|
+
* programmatic scrolling.
|
|
45835
|
+
*/
|
|
45836
|
+
function findScrollableParent(element, options) {
|
|
45837
|
+
const minBuffer = options?.minScrollBuffer ?? 100;
|
|
45838
|
+
let current = element instanceof HTMLElement ? element : element?.parentElement;
|
|
45839
|
+
while (current && current !== document.body) {
|
|
45840
|
+
const style = getComputedStyle(current);
|
|
45841
|
+
if ((style.overflowY === "auto" || style.overflowY === "scroll") && current.scrollHeight > current.clientHeight + minBuffer) return current;
|
|
45842
|
+
current = current.parentElement;
|
|
45843
|
+
}
|
|
45844
|
+
return null;
|
|
45845
|
+
}
|
|
45846
|
+
/**
|
|
45847
|
+
* Centers the selected text range rather than its containing element, which
|
|
45848
|
+
* keeps matches in large elements such as code blocks correctly positioned.
|
|
45849
|
+
*/
|
|
45850
|
+
function scrollRangeToCenter(range, options) {
|
|
45851
|
+
const { behavior = "auto", fallbackToScrollIntoView = true } = options ?? {};
|
|
45852
|
+
const rects = range.getClientRects();
|
|
45853
|
+
if (rects.length === 0) return;
|
|
45854
|
+
const selectionRect = rects[0];
|
|
45855
|
+
if (selectionRect === void 0) return;
|
|
45856
|
+
const scrollableParent = findScrollableParent(range.startContainer.parentElement);
|
|
45857
|
+
if (scrollableParent) {
|
|
45858
|
+
const parentRect = scrollableParent.getBoundingClientRect();
|
|
45859
|
+
const targetScrollTop = selectionRect.top - parentRect.top + scrollableParent.scrollTop - scrollableParent.clientHeight / 2;
|
|
45860
|
+
scrollableParent.scrollTo({
|
|
45861
|
+
top: Math.max(0, targetScrollTop),
|
|
45862
|
+
behavior
|
|
45863
|
+
});
|
|
45864
|
+
} else if (fallbackToScrollIntoView) range.startContainer.parentElement?.scrollIntoView({
|
|
45865
|
+
behavior,
|
|
45866
|
+
block: "center"
|
|
45867
|
+
});
|
|
45868
|
+
}
|
|
45869
|
+
//#endregion
|
|
45870
|
+
//#region ../../packages/react/src/components/FindBandUI.tsx
|
|
45871
|
+
var FindBandUI = ({ onClose, onNext, onPrevious, onKeyDown, onChange, onBeforeInput, value, matchCount, matchIndex, noResults = false, disableNav, inputRef: externalRef }) => {
|
|
45872
|
+
const icons = useComponentIcons();
|
|
45873
|
+
const internalRef = useRef(null);
|
|
45874
|
+
const inputRef = externalRef ?? internalRef;
|
|
45875
|
+
const inputProps = {
|
|
45876
|
+
type: "text",
|
|
45877
|
+
placeholder: "Find",
|
|
45878
|
+
onKeyDown,
|
|
45879
|
+
onBeforeInput,
|
|
45880
|
+
onChange
|
|
45881
|
+
};
|
|
45882
|
+
if (value !== void 0) inputProps.value = value;
|
|
45883
|
+
const hasCount = matchCount !== void 0 && matchIndex !== void 0;
|
|
45884
|
+
const showStatus = noResults || hasCount && matchCount > 0;
|
|
45885
|
+
const statusText = !noResults && hasCount && matchCount > 0 ? `${matchIndex + 1} of ${matchCount}` : "No results";
|
|
45886
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
45887
|
+
"data-unsearchable": "true",
|
|
45888
|
+
className: clsx("findBand"),
|
|
45889
|
+
children: [
|
|
45890
|
+
/* @__PURE__ */ jsx("input", {
|
|
45891
|
+
ref: inputRef,
|
|
45892
|
+
...inputProps
|
|
45893
|
+
}),
|
|
45894
|
+
/* @__PURE__ */ jsx("span", {
|
|
45895
|
+
className: clsx("findBand-match-count", noResults && "findBand-no-results"),
|
|
45896
|
+
style: { visibility: showStatus ? "visible" : "hidden" },
|
|
45897
|
+
children: statusText
|
|
45898
|
+
}),
|
|
45899
|
+
/* @__PURE__ */ jsx("button", {
|
|
45900
|
+
type: "button",
|
|
45901
|
+
title: "Previous match",
|
|
45902
|
+
className: "btn prev",
|
|
45903
|
+
onClick: onPrevious,
|
|
45904
|
+
disabled: disableNav,
|
|
45905
|
+
children: /* @__PURE__ */ jsx("i", { className: icons.arrowUp })
|
|
45906
|
+
}),
|
|
45907
|
+
/* @__PURE__ */ jsx("button", {
|
|
45908
|
+
type: "button",
|
|
45909
|
+
title: "Next match",
|
|
45910
|
+
className: "btn next",
|
|
45911
|
+
onClick: onNext,
|
|
45912
|
+
disabled: disableNav,
|
|
45913
|
+
children: /* @__PURE__ */ jsx("i", { className: icons.arrowDown })
|
|
45914
|
+
}),
|
|
45915
|
+
/* @__PURE__ */ jsx("button", {
|
|
45916
|
+
type: "button",
|
|
45917
|
+
title: "Close",
|
|
45918
|
+
className: "btn close",
|
|
45919
|
+
onClick: onClose,
|
|
45920
|
+
children: /* @__PURE__ */ jsx("i", { className: icons.close })
|
|
45921
|
+
})
|
|
45922
|
+
]
|
|
45923
|
+
});
|
|
45924
|
+
};
|
|
45925
|
+
//#endregion
|
|
45926
|
+
//#region ../../packages/react/src/components/findShortcuts.ts
|
|
45927
|
+
function isFindShortcut(e) {
|
|
45928
|
+
return (e.ctrlKey || e.metaKey) && !e.shiftKey && e.key.toLowerCase() === "f";
|
|
45929
|
+
}
|
|
45930
|
+
function isFindNextShortcut(e) {
|
|
45931
|
+
return (e.ctrlKey || e.metaKey) && e.key.toLowerCase() === "g";
|
|
45932
|
+
}
|
|
45933
|
+
//#endregion
|
|
45934
|
+
//#region ../../packages/react/src/components/FindBand.tsx
|
|
45935
|
+
var findConfig = {
|
|
45936
|
+
caseSensitive: false,
|
|
45937
|
+
wrapAround: false,
|
|
45938
|
+
wholeWord: false,
|
|
45939
|
+
searchInFrames: false,
|
|
45940
|
+
showDialog: false
|
|
45941
|
+
};
|
|
45942
|
+
var FindBand = ({ onClose, debounceMs = 100 }) => {
|
|
45943
|
+
const searchBoxRef = useRef(null);
|
|
45944
|
+
const { extendedFindTerm, countAllMatches, getMatchCountersVersion } = useExtendedFind();
|
|
45945
|
+
const setFindTarget = useFindTargetSetter();
|
|
45946
|
+
const lastFoundItem = useRef(null);
|
|
45947
|
+
const currentSearchTerm = useRef("");
|
|
45948
|
+
const needsCursorRestoreRef = useRef(false);
|
|
45949
|
+
const scrollTimeoutRef = useRef(null);
|
|
45950
|
+
const focusTimeoutRef = useRef(null);
|
|
45951
|
+
const searchIdRef = useRef(0);
|
|
45952
|
+
const cachedCount = useRef({
|
|
45953
|
+
term: "",
|
|
45954
|
+
version: -1,
|
|
45955
|
+
count: 0
|
|
45956
|
+
});
|
|
45957
|
+
const lastNoResult = useRef(null);
|
|
45958
|
+
const [matchCount, setMatchCount] = useState(null);
|
|
45959
|
+
const [currentMatchIndex, setCurrentMatchIndex] = useState(0);
|
|
45960
|
+
const [noResults, setNoResults] = useState(false);
|
|
45961
|
+
const handleSearch = useCallback(async (back = false, skipKnownMiss = false) => {
|
|
45962
|
+
const thisSearchId = ++searchIdRef.current;
|
|
45963
|
+
const searchTerm = searchBoxRef.current?.value ?? "";
|
|
45964
|
+
if (!searchTerm) {
|
|
45965
|
+
setMatchCount(null);
|
|
45966
|
+
setCurrentMatchIndex(0);
|
|
45967
|
+
setNoResults(false);
|
|
45968
|
+
setFindTarget(null);
|
|
45969
|
+
return;
|
|
45970
|
+
}
|
|
45971
|
+
const countersVersion = getMatchCountersVersion();
|
|
45972
|
+
if (skipKnownMiss && lastNoResult.current && lastNoResult.current.version === countersVersion && searchTerm.startsWith(lastNoResult.current.term)) {
|
|
45973
|
+
setMatchCount(null);
|
|
45974
|
+
setNoResults(true);
|
|
45975
|
+
return;
|
|
45976
|
+
}
|
|
45977
|
+
const termChanged = currentSearchTerm.current !== searchTerm;
|
|
45978
|
+
if (termChanged) {
|
|
45979
|
+
lastFoundItem.current = null;
|
|
45980
|
+
currentSearchTerm.current = searchTerm;
|
|
45981
|
+
setCurrentMatchIndex(0);
|
|
45982
|
+
}
|
|
45983
|
+
let total;
|
|
45984
|
+
if (cachedCount.current.term === searchTerm && cachedCount.current.version === countersVersion) total = cachedCount.current.count;
|
|
45985
|
+
else {
|
|
45986
|
+
total = countAllMatches(searchTerm);
|
|
45987
|
+
cachedCount.current = {
|
|
45988
|
+
term: searchTerm,
|
|
45989
|
+
version: countersVersion,
|
|
45990
|
+
count: total
|
|
45991
|
+
};
|
|
45992
|
+
}
|
|
45993
|
+
setMatchCount(total > 0 ? total : null);
|
|
45994
|
+
const focusedElement = document.activeElement;
|
|
45995
|
+
const selection = window.getSelection();
|
|
45996
|
+
let savedRange = null;
|
|
45997
|
+
if (selection && selection.rangeCount > 0) savedRange = selection.getRangeAt(0).cloneRange();
|
|
45998
|
+
const savedScrollParent = savedRange ? findScrollableParent(savedRange.startContainer.parentElement) : null;
|
|
45999
|
+
const savedScrollTop = savedScrollParent?.scrollTop ?? 0;
|
|
46000
|
+
const result = await findExtendedInDOM(searchTerm, back, lastFoundItem.current, extendedFindTerm);
|
|
46001
|
+
if (searchIdRef.current !== thisSearchId) return;
|
|
46002
|
+
setNoResults(!result);
|
|
46003
|
+
lastNoResult.current = result ? null : {
|
|
46004
|
+
term: searchTerm,
|
|
46005
|
+
version: countersVersion
|
|
46006
|
+
};
|
|
46007
|
+
if (!result && savedRange) {
|
|
46008
|
+
const sel = window.getSelection();
|
|
46009
|
+
if (sel) {
|
|
46010
|
+
sel.removeAllRanges();
|
|
46011
|
+
sel.addRange(savedRange);
|
|
46012
|
+
}
|
|
46013
|
+
if (savedScrollParent) savedScrollParent.scrollTop = savedScrollTop;
|
|
46014
|
+
}
|
|
46015
|
+
if (result) {
|
|
46016
|
+
const selection = window.getSelection();
|
|
46017
|
+
if (selection && selection.rangeCount > 0) {
|
|
46018
|
+
const range = selection.getRangeAt(0);
|
|
46019
|
+
const parentElement = range.startContainer.parentElement || range.commonAncestorContainer;
|
|
46020
|
+
const isNewMatch = !isLastFoundItem(range, lastFoundItem.current);
|
|
46021
|
+
lastFoundItem.current = {
|
|
46022
|
+
text: range.toString(),
|
|
46023
|
+
offset: range.startOffset,
|
|
46024
|
+
parentElement
|
|
46025
|
+
};
|
|
46026
|
+
if (termChanged) setFindTarget({
|
|
46027
|
+
term: searchTerm,
|
|
46028
|
+
eventId: ""
|
|
46029
|
+
});
|
|
46030
|
+
if (isNewMatch) setCurrentMatchIndex((prev) => {
|
|
46031
|
+
if (back) return prev <= 1 ? total : prev - 1;
|
|
46032
|
+
else return prev >= total ? 1 : prev + 1;
|
|
46033
|
+
});
|
|
46034
|
+
if (scrollTimeoutRef.current !== null) window.clearTimeout(scrollTimeoutRef.current);
|
|
46035
|
+
scrollTimeoutRef.current = window.setTimeout(() => {
|
|
46036
|
+
scrollRangeToCenter(range);
|
|
46037
|
+
}, 100);
|
|
46038
|
+
}
|
|
46039
|
+
}
|
|
46040
|
+
focusedElement?.focus();
|
|
46041
|
+
}, [
|
|
46042
|
+
setFindTarget,
|
|
46043
|
+
extendedFindTerm,
|
|
46044
|
+
countAllMatches,
|
|
46045
|
+
getMatchCountersVersion
|
|
46046
|
+
]);
|
|
46047
|
+
useEffect(() => {
|
|
46048
|
+
focusTimeoutRef.current = window.setTimeout(() => {
|
|
46049
|
+
searchBoxRef.current?.focus();
|
|
46050
|
+
searchBoxRef.current?.select();
|
|
46051
|
+
}, 10);
|
|
46052
|
+
const focusTimeout = focusTimeoutRef.current;
|
|
46053
|
+
return () => {
|
|
46054
|
+
if (scrollTimeoutRef.current !== null) window.clearTimeout(scrollTimeoutRef.current);
|
|
46055
|
+
if (focusTimeout !== null) window.clearTimeout(focusTimeout);
|
|
46056
|
+
setFindTarget(null);
|
|
46057
|
+
};
|
|
46058
|
+
}, [setFindTarget]);
|
|
46059
|
+
const handleKeyDown = useCallback((e) => {
|
|
46060
|
+
if (e.key === "Escape") onClose();
|
|
46061
|
+
else if (e.key === "Enter") handleSearch(e.shiftKey);
|
|
46062
|
+
else if (isFindNextShortcut(e)) {
|
|
46063
|
+
e.preventDefault();
|
|
46064
|
+
handleSearch(e.shiftKey);
|
|
46065
|
+
} else if (isFindShortcut(e)) {
|
|
46066
|
+
searchBoxRef.current?.focus();
|
|
46067
|
+
searchBoxRef.current?.select();
|
|
46068
|
+
}
|
|
46069
|
+
}, [onClose, handleSearch]);
|
|
46070
|
+
const findPrevious = useCallback(() => {
|
|
46071
|
+
handleSearch(true);
|
|
46072
|
+
}, [handleSearch]);
|
|
46073
|
+
const findNext = useCallback(() => {
|
|
46074
|
+
handleSearch(false);
|
|
46075
|
+
}, [handleSearch]);
|
|
46076
|
+
const restoreCursor = useCallback(() => {
|
|
46077
|
+
if (!needsCursorRestoreRef.current) return;
|
|
46078
|
+
needsCursorRestoreRef.current = false;
|
|
46079
|
+
const input = searchBoxRef.current;
|
|
46080
|
+
if (input) {
|
|
46081
|
+
const len = input.value.length;
|
|
46082
|
+
input.setSelectionRange(len, len);
|
|
46083
|
+
}
|
|
46084
|
+
}, []);
|
|
46085
|
+
const handleInputChange = useDebouncedCallback(useCallback(async () => {
|
|
46086
|
+
if (!searchBoxRef.current) return;
|
|
46087
|
+
await handleSearch(false, true);
|
|
46088
|
+
needsCursorRestoreRef.current = true;
|
|
46089
|
+
}, [handleSearch]), debounceMs);
|
|
46090
|
+
const restoreCursorIfNeeded = useCallback(() => {
|
|
46091
|
+
const input = searchBoxRef.current;
|
|
46092
|
+
if (!input) return;
|
|
46093
|
+
if (input.selectionStart === 0 && input.selectionEnd === 0 && input.value.length > 0) restoreCursor();
|
|
46094
|
+
else needsCursorRestoreRef.current = false;
|
|
46095
|
+
}, [restoreCursor]);
|
|
46096
|
+
const handleBeforeInput = useCallback(() => {
|
|
46097
|
+
restoreCursorIfNeeded();
|
|
46098
|
+
}, [restoreCursorIfNeeded]);
|
|
46099
|
+
useEffect(() => {
|
|
46100
|
+
const handleGlobalKeyDown = (e) => {
|
|
46101
|
+
if (e.key === "F3") {
|
|
46102
|
+
e.preventDefault();
|
|
46103
|
+
handleSearch(e.shiftKey);
|
|
46104
|
+
return;
|
|
46105
|
+
}
|
|
46106
|
+
if (isFindShortcut(e)) {
|
|
46107
|
+
e.preventDefault();
|
|
46108
|
+
e.stopPropagation();
|
|
46109
|
+
searchBoxRef.current?.focus();
|
|
46110
|
+
searchBoxRef.current?.select();
|
|
46111
|
+
return;
|
|
46112
|
+
}
|
|
46113
|
+
if (isFindNextShortcut(e)) {
|
|
46114
|
+
e.preventDefault();
|
|
46115
|
+
e.stopPropagation();
|
|
46116
|
+
handleSearch(e.shiftKey);
|
|
46117
|
+
return;
|
|
46118
|
+
}
|
|
46119
|
+
if (e.ctrlKey || e.metaKey || e.altKey) return;
|
|
46120
|
+
if (e.key.length !== 1 && e.key !== "Backspace" && e.key !== "Delete") return;
|
|
46121
|
+
const input = searchBoxRef.current;
|
|
46122
|
+
if (!input) return;
|
|
46123
|
+
if (document.activeElement !== input) {
|
|
46124
|
+
if (isEditableTarget(deepActiveElement())) return;
|
|
46125
|
+
restoreCursor();
|
|
46126
|
+
input.focus();
|
|
46127
|
+
} else restoreCursorIfNeeded();
|
|
46128
|
+
};
|
|
46129
|
+
document.addEventListener("keydown", handleGlobalKeyDown, true);
|
|
46130
|
+
return () => {
|
|
46131
|
+
document.removeEventListener("keydown", handleGlobalKeyDown, true);
|
|
46132
|
+
};
|
|
46133
|
+
}, [
|
|
46134
|
+
handleSearch,
|
|
46135
|
+
restoreCursor,
|
|
46136
|
+
restoreCursorIfNeeded
|
|
46137
|
+
]);
|
|
46138
|
+
return /* @__PURE__ */ jsx(FindBandUI, {
|
|
46139
|
+
inputRef: searchBoxRef,
|
|
46140
|
+
onClose,
|
|
46141
|
+
onNext: findNext,
|
|
46142
|
+
onPrevious: findPrevious,
|
|
46143
|
+
onKeyDown: handleKeyDown,
|
|
46144
|
+
onBeforeInput: handleBeforeInput,
|
|
46145
|
+
onChange: handleInputChange,
|
|
46146
|
+
noResults,
|
|
46147
|
+
matchCount: matchCount ?? void 0,
|
|
46148
|
+
matchIndex: matchCount !== null && matchCount > 0 ? currentMatchIndex - 1 : void 0
|
|
46149
|
+
});
|
|
46150
|
+
};
|
|
46151
|
+
function windowFind(searchTerm, back) {
|
|
46152
|
+
return window.find?.(searchTerm, findConfig.caseSensitive, back, findConfig.wrapAround, findConfig.wholeWord, findConfig.searchInFrames, findConfig.showDialog) ?? false;
|
|
46153
|
+
}
|
|
46154
|
+
function positionSelectionForWrap(back) {
|
|
46155
|
+
if (!back) return;
|
|
46156
|
+
const sel = window.getSelection();
|
|
46157
|
+
if (sel) {
|
|
46158
|
+
const range = document.createRange();
|
|
46159
|
+
range.selectNodeContents(document.body);
|
|
46160
|
+
range.collapse(false);
|
|
46161
|
+
sel.removeAllRanges();
|
|
46162
|
+
sel.addRange(range);
|
|
46163
|
+
}
|
|
46164
|
+
}
|
|
46165
|
+
async function findExtendedInDOM(searchTerm, back, lastFoundItem, extendedFindTerm) {
|
|
46166
|
+
let result = false;
|
|
46167
|
+
let hasTriedExtendedSearch = false;
|
|
46168
|
+
let extendedSearchSucceeded = false;
|
|
46169
|
+
const maxAttempts = 25;
|
|
46170
|
+
for (let attempts = 0; attempts < maxAttempts; attempts++) {
|
|
46171
|
+
result = windowFind(searchTerm, back);
|
|
46172
|
+
if (result) {
|
|
46173
|
+
const selection = window.getSelection();
|
|
46174
|
+
if (selection && selection.rangeCount > 0) {
|
|
46175
|
+
const range = selection.getRangeAt(0);
|
|
46176
|
+
const isUnsearchable = inUnsearchableElement(range);
|
|
46177
|
+
const isSameAsLast = isLastFoundItem(range, lastFoundItem);
|
|
46178
|
+
if (!isUnsearchable && !isSameAsLast) break;
|
|
46179
|
+
if (isSameAsLast) {
|
|
46180
|
+
if (!hasTriedExtendedSearch) {
|
|
46181
|
+
hasTriedExtendedSearch = true;
|
|
46182
|
+
window.getSelection()?.removeAllRanges();
|
|
46183
|
+
if (await extendedFindTerm(searchTerm, back ? "backward" : "forward")) {
|
|
46184
|
+
extendedSearchSucceeded = true;
|
|
46185
|
+
await waitForTextInDOM(searchTerm);
|
|
46186
|
+
continue;
|
|
46187
|
+
}
|
|
46188
|
+
}
|
|
46189
|
+
if (extendedSearchSucceeded) {
|
|
46190
|
+
const sel = window.getSelection();
|
|
46191
|
+
if (sel?.rangeCount) sel.getRangeAt(0).collapse(!back);
|
|
46192
|
+
} else {
|
|
46193
|
+
window.getSelection()?.removeAllRanges();
|
|
46194
|
+
positionSelectionForWrap(back);
|
|
46195
|
+
}
|
|
46196
|
+
result = windowFind(searchTerm, back);
|
|
46197
|
+
if (result) {
|
|
46198
|
+
const sel = window.getSelection();
|
|
46199
|
+
if (sel && sel.rangeCount > 0) {
|
|
46200
|
+
if (inUnsearchableElement(sel.getRangeAt(0))) continue;
|
|
46201
|
+
}
|
|
46202
|
+
}
|
|
46203
|
+
break;
|
|
46204
|
+
}
|
|
46205
|
+
}
|
|
46206
|
+
} else if (!hasTriedExtendedSearch) {
|
|
46207
|
+
hasTriedExtendedSearch = true;
|
|
46208
|
+
window.getSelection()?.removeAllRanges();
|
|
46209
|
+
if (await extendedFindTerm(searchTerm, back ? "backward" : "forward")) {
|
|
46210
|
+
extendedSearchSucceeded = true;
|
|
46211
|
+
await waitForTextInDOM(searchTerm);
|
|
46212
|
+
continue;
|
|
46213
|
+
}
|
|
46214
|
+
positionSelectionForWrap(back);
|
|
46215
|
+
result = windowFind(searchTerm, back);
|
|
46216
|
+
if (result) {
|
|
46217
|
+
const sel = window.getSelection();
|
|
46218
|
+
if (sel && sel.rangeCount > 0) {
|
|
46219
|
+
if (inUnsearchableElement(sel.getRangeAt(0))) continue;
|
|
46220
|
+
}
|
|
46221
|
+
}
|
|
46222
|
+
break;
|
|
46223
|
+
} else break;
|
|
46224
|
+
}
|
|
46225
|
+
if (result) {
|
|
46226
|
+
const sel = window.getSelection();
|
|
46227
|
+
if (sel?.rangeCount && inUnsearchableElement(sel.getRangeAt(0))) {
|
|
46228
|
+
sel.removeAllRanges();
|
|
46229
|
+
result = false;
|
|
46230
|
+
}
|
|
46231
|
+
}
|
|
46232
|
+
return result;
|
|
46233
|
+
}
|
|
46234
|
+
function isLastFoundItem(range, lastFoundItem) {
|
|
46235
|
+
if (!lastFoundItem) return false;
|
|
46236
|
+
const currentText = range.toString();
|
|
46237
|
+
const currentOffset = range.startOffset;
|
|
46238
|
+
const currentParentElement = range.startContainer.parentElement || range.commonAncestorContainer;
|
|
46239
|
+
return currentText === lastFoundItem.text && currentOffset === lastFoundItem.offset && currentParentElement === lastFoundItem.parentElement;
|
|
46240
|
+
}
|
|
46241
|
+
function inUnsearchableElement(range) {
|
|
46242
|
+
let element = selectionParentElement(range);
|
|
46243
|
+
let isUnsearchable = false;
|
|
46244
|
+
while (element) {
|
|
46245
|
+
if (element.hasAttribute("data-unsearchable") || getComputedStyle(element).userSelect === "none") {
|
|
46246
|
+
isUnsearchable = true;
|
|
46247
|
+
break;
|
|
46248
|
+
}
|
|
46249
|
+
element = element.parentElement;
|
|
46250
|
+
}
|
|
46251
|
+
return isUnsearchable;
|
|
46252
|
+
}
|
|
46253
|
+
function selectionParentElement(range) {
|
|
46254
|
+
let element = null;
|
|
46255
|
+
if (range.startContainer.nodeType === Node.ELEMENT_NODE) element = range.startContainer;
|
|
46256
|
+
else element = range.startContainer.parentElement;
|
|
46257
|
+
if (!element && range.commonAncestorContainer.nodeType === Node.ELEMENT_NODE) element = range.commonAncestorContainer;
|
|
46258
|
+
else if (!element && range.commonAncestorContainer.parentElement) element = range.commonAncestorContainer.parentElement;
|
|
46259
|
+
return element;
|
|
46260
|
+
}
|
|
46261
|
+
/**
|
|
46262
|
+
* Polls until the search term appears in a searchable (non-unsearchable) DOM
|
|
46263
|
+
* text node. After Virtuoso scrolls a virtual list item into view, the
|
|
46264
|
+
* onContentReady callback may fire before the content is actually rendered,
|
|
46265
|
+
* especially for large scroll distances. This ensures we wait for the text
|
|
46266
|
+
* to be present before calling window.find().
|
|
46267
|
+
*/
|
|
46268
|
+
function waitForTextInDOM(searchTerm, timeoutMs = 2e3) {
|
|
46269
|
+
const lowerTerm = searchTerm.toLowerCase();
|
|
46270
|
+
const isTextInSearchableDOM = () => {
|
|
46271
|
+
const walker = document.createTreeWalker(document.body, NodeFilter.SHOW_TEXT, { acceptNode: (node) => {
|
|
46272
|
+
let el = node.parentElement;
|
|
46273
|
+
while (el) {
|
|
46274
|
+
if (el.hasAttribute("data-unsearchable")) return NodeFilter.FILTER_REJECT;
|
|
46275
|
+
el = el.parentElement;
|
|
46276
|
+
}
|
|
46277
|
+
return NodeFilter.FILTER_ACCEPT;
|
|
46278
|
+
} });
|
|
46279
|
+
while (walker.nextNode()) if (walker.currentNode.textContent?.toLowerCase().includes(lowerTerm)) return true;
|
|
46280
|
+
return false;
|
|
46281
|
+
};
|
|
46282
|
+
return new Promise((resolve) => {
|
|
46283
|
+
const interval = 50;
|
|
46284
|
+
let elapsed = 0;
|
|
46285
|
+
const check = () => {
|
|
46286
|
+
if (isTextInSearchableDOM()) {
|
|
46287
|
+
resolve(true);
|
|
46288
|
+
return;
|
|
46289
|
+
}
|
|
46290
|
+
elapsed += interval;
|
|
46291
|
+
if (elapsed >= timeoutMs) {
|
|
46292
|
+
resolve(false);
|
|
46293
|
+
return;
|
|
46294
|
+
}
|
|
46295
|
+
setTimeout(check, interval);
|
|
46296
|
+
};
|
|
46297
|
+
check();
|
|
46298
|
+
});
|
|
46299
|
+
}
|
|
46300
|
+
//#endregion
|
|
46301
|
+
//#region ../../packages/react/src/components/useFindBandShortcut.ts
|
|
46302
|
+
/**
|
|
46303
|
+
* Global Ctrl/Cmd+F shortcut companion to `FindBand`: opens the band
|
|
46304
|
+
* (blocking the browser's own find dialog) and optionally closes it on
|
|
46305
|
+
* Escape. Pass stable callbacks — they are effect dependencies.
|
|
46306
|
+
*/
|
|
46307
|
+
function useFindBandShortcut(onOpen, options) {
|
|
46308
|
+
const { onClose, isOpen = false, enabled = true } = options ?? {};
|
|
46309
|
+
useEffect(() => {
|
|
46310
|
+
if (!enabled) return;
|
|
46311
|
+
const handleKeyDown = (e) => {
|
|
46312
|
+
if (isFindShortcut(e)) {
|
|
46313
|
+
e.preventDefault();
|
|
46314
|
+
e.stopPropagation();
|
|
46315
|
+
onOpen();
|
|
46316
|
+
} else if (e.key === "Escape" && isOpen && onClose) onClose();
|
|
46317
|
+
};
|
|
46318
|
+
document.addEventListener("keydown", handleKeyDown, true);
|
|
46319
|
+
return () => document.removeEventListener("keydown", handleKeyDown, true);
|
|
46320
|
+
}, [
|
|
46321
|
+
enabled,
|
|
46322
|
+
onOpen,
|
|
46323
|
+
onClose,
|
|
46324
|
+
isOpen
|
|
46325
|
+
]);
|
|
46326
|
+
}
|
|
45327
46327
|
var MarkdownDivWithReferences_module_default = { cite: "_cite_1t1bm_1" };
|
|
45328
46328
|
//#endregion
|
|
45329
46329
|
//#region ../../packages/react/src/components/MarkdownDivWithReferences.tsx
|
|
@@ -45645,6 +46645,165 @@ var TreeNode$2 = memo(({ name, value, defaultExpanded = false }) => {
|
|
|
45645
46645
|
});
|
|
45646
46646
|
TreeNode$2.displayName = "TreeNode";
|
|
45647
46647
|
//#endregion
|
|
46648
|
+
//#region ../../packages/inspect-common/src/utils/expandEvents.ts
|
|
46649
|
+
/**
|
|
46650
|
+
* Expand range-encoded refs against a pool.
|
|
46651
|
+
* Each ref is [start, endExclusive] → pool.slice(start, endExclusive).
|
|
46652
|
+
*/
|
|
46653
|
+
function expandRefs$1(refs, pool) {
|
|
46654
|
+
return refs.flatMap(([start, end]) => pool.slice(start, end));
|
|
46655
|
+
}
|
|
46656
|
+
function isModelEvent(event) {
|
|
46657
|
+
return event.event === "model";
|
|
46658
|
+
}
|
|
46659
|
+
/**
|
|
46660
|
+
* Expand condensed ModelEvent input/call refs back to inline data.
|
|
46661
|
+
*
|
|
46662
|
+
* Pure function — returns a new array; input is not mutated.
|
|
46663
|
+
* Non-ModelEvents and ModelEvents without refs pass through unchanged.
|
|
46664
|
+
*/
|
|
46665
|
+
function expandEvents(events, eventsData) {
|
|
46666
|
+
if (!eventsData) return events;
|
|
46667
|
+
const { messages, calls } = eventsData;
|
|
46668
|
+
const hasMessages = messages.length > 0;
|
|
46669
|
+
const hasCalls = calls.length > 0;
|
|
46670
|
+
if (!hasMessages && !hasCalls) return events;
|
|
46671
|
+
return events.map((event) => {
|
|
46672
|
+
if (!isModelEvent(event)) return event;
|
|
46673
|
+
let changed = false;
|
|
46674
|
+
let input = event.input;
|
|
46675
|
+
let call = event.call;
|
|
46676
|
+
if (event.input_refs != null && hasMessages) {
|
|
46677
|
+
input = expandRefs$1(event.input_refs, messages);
|
|
46678
|
+
changed = true;
|
|
46679
|
+
}
|
|
46680
|
+
if (call?.call_refs != null && hasCalls) {
|
|
46681
|
+
const key = call.call_key ?? "messages";
|
|
46682
|
+
const expandedMsgs = expandRefs$1(call.call_refs, calls);
|
|
46683
|
+
call = {
|
|
46684
|
+
...call,
|
|
46685
|
+
request: {
|
|
46686
|
+
...call.request,
|
|
46687
|
+
[key]: expandedMsgs
|
|
46688
|
+
},
|
|
46689
|
+
call_refs: null,
|
|
46690
|
+
call_key: null
|
|
46691
|
+
};
|
|
46692
|
+
changed = true;
|
|
46693
|
+
}
|
|
46694
|
+
return changed ? {
|
|
46695
|
+
...event,
|
|
46696
|
+
input,
|
|
46697
|
+
input_refs: null,
|
|
46698
|
+
call
|
|
46699
|
+
} : event;
|
|
46700
|
+
});
|
|
46701
|
+
}
|
|
46702
|
+
//#endregion
|
|
46703
|
+
//#region ../../packages/inspect-common/src/utils/inputString.ts
|
|
46704
|
+
/**
|
|
46705
|
+
* Gets a string for a sample input.
|
|
46706
|
+
*/
|
|
46707
|
+
var inputString = (input) => {
|
|
46708
|
+
if (typeof input === "string") return [input];
|
|
46709
|
+
else return input.map((inp) => {
|
|
46710
|
+
if (typeof inp === "string") return inp;
|
|
46711
|
+
else {
|
|
46712
|
+
const content = inp.content;
|
|
46713
|
+
if (typeof content === "string") return content;
|
|
46714
|
+
else return content.map((con) => {
|
|
46715
|
+
if (con.type === "text") return con.text;
|
|
46716
|
+
else return "";
|
|
46717
|
+
}).join("\n");
|
|
46718
|
+
}
|
|
46719
|
+
});
|
|
46720
|
+
};
|
|
46721
|
+
//#endregion
|
|
46722
|
+
//#region ../../packages/inspect-common/src/utils/modelFallbacks.ts
|
|
46723
|
+
/**
|
|
46724
|
+
* Total generate calls served via fallback across a sample's rollup.
|
|
46725
|
+
*/
|
|
46726
|
+
var totalModelFallbacks = (fallbacks) => (fallbacks ?? []).reduce((sum, f) => sum + (f.count ?? 1), 0);
|
|
46727
|
+
/**
|
|
46728
|
+
* One "requested → served (×N)" line per fallback rollup entry.
|
|
46729
|
+
*/
|
|
46730
|
+
var modelFallbackLines = (fallbacks) => (fallbacks ?? []).map((f) => `${f.model} → ${f.fallback_model}${(f.count ?? 1) > 1 ? ` (×${f.count})` : ""}`);
|
|
46731
|
+
//#endregion
|
|
46732
|
+
//#region src/client/utils/derive.ts
|
|
46733
|
+
var deriveLogFields = (header) => {
|
|
46734
|
+
let total_tokens;
|
|
46735
|
+
if (header.stats?.model_usage) {
|
|
46736
|
+
total_tokens = 0;
|
|
46737
|
+
for (const usage of Object.values(header.stats.model_usage)) total_tokens += usage.total_tokens;
|
|
46738
|
+
}
|
|
46739
|
+
let duration;
|
|
46740
|
+
if (header.stats?.started_at && header.stats?.completed_at) {
|
|
46741
|
+
const start = new Date(header.stats.started_at).getTime();
|
|
46742
|
+
const end = new Date(header.stats.completed_at).getTime();
|
|
46743
|
+
if (start && end && end > start) duration = (end - start) / 1e3;
|
|
46744
|
+
}
|
|
46745
|
+
const taskArgsSource = header.eval.task_args_passed ?? header.eval.task_args;
|
|
46746
|
+
let task_args;
|
|
46747
|
+
if (taskArgsSource) {
|
|
46748
|
+
const entries = Object.entries(taskArgsSource);
|
|
46749
|
+
if (entries.length > 0) task_args = entries.map(([k, v]) => `${k}=${JSON.stringify(v)}`).join(", ");
|
|
46750
|
+
}
|
|
46751
|
+
let percent_completed;
|
|
46752
|
+
const total = header.results?.total_samples;
|
|
46753
|
+
const completed = header.results?.completed_samples;
|
|
46754
|
+
if (total && total > 0 && completed !== void 0) percent_completed = completed / total * 100;
|
|
46755
|
+
const sample_limits = header.sampleLimits.length > 0 ? header.sampleLimits.join(", ") : void 0;
|
|
46756
|
+
let scores;
|
|
46757
|
+
if (header.results?.scores) {
|
|
46758
|
+
for (const evalScore of header.results.scores) if (evalScore.metrics) for (const [metricName, metric] of Object.entries(evalScore.metrics)) {
|
|
46759
|
+
scores ??= {};
|
|
46760
|
+
(scores[evalScore.name] ??= {})[metricName] = metric.value;
|
|
46761
|
+
}
|
|
46762
|
+
}
|
|
46763
|
+
return {
|
|
46764
|
+
total_tokens,
|
|
46765
|
+
duration,
|
|
46766
|
+
task_args,
|
|
46767
|
+
percent_completed,
|
|
46768
|
+
sample_limits,
|
|
46769
|
+
scores
|
|
46770
|
+
};
|
|
46771
|
+
};
|
|
46772
|
+
/** The sample facts baked onto the stored `LogHeader` by `toLogHeader` —
|
|
46773
|
+
* persisted derivation like the fields above, so it lives under
|
|
46774
|
+
* `DERIVE_VERSION` with them. */
|
|
46775
|
+
var deriveSampleFacts = (summaries) => {
|
|
46776
|
+
const limits = /* @__PURE__ */ new Set();
|
|
46777
|
+
let errorCount = 0;
|
|
46778
|
+
for (const sample of summaries) {
|
|
46779
|
+
if (sample.error) errorCount += 1;
|
|
46780
|
+
if (sample.limit) limits.add(sample.limit);
|
|
46781
|
+
}
|
|
46782
|
+
return {
|
|
46783
|
+
sampleCount: summaries.length,
|
|
46784
|
+
sampleErrorCount: errorCount,
|
|
46785
|
+
sampleLimits: [...limits].sort()
|
|
46786
|
+
};
|
|
46787
|
+
};
|
|
46788
|
+
/** A sample's total token spend across models (undefined before any usage).
|
|
46789
|
+
* The single home for this sum — the stored `derived.tokens` column and
|
|
46790
|
+
* read-time consumers (filter variables, sample rows) must agree. */
|
|
46791
|
+
var totalSampleTokens = (modelUsage) => modelUsage ? Object.values(modelUsage).reduce((sum, u) => sum + (u.total_tokens ?? 0), 0) : void 0;
|
|
46792
|
+
var deriveSampleFields = (summary) => {
|
|
46793
|
+
let scores;
|
|
46794
|
+
if (summary.scores) {
|
|
46795
|
+
scores = {};
|
|
46796
|
+
for (const [scoreName, score] of Object.entries(summary.scores)) scores[scoreName] = score.value;
|
|
46797
|
+
}
|
|
46798
|
+
return {
|
|
46799
|
+
tokens: totalSampleTokens(summary.model_usage),
|
|
46800
|
+
input: summary.input !== void 0 ? inputString(summary.input).join("\n") : "",
|
|
46801
|
+
target: arrayToString(summary.target ?? ""),
|
|
46802
|
+
fallbacks: totalModelFallbacks(summary.model_fallbacks) || void 0,
|
|
46803
|
+
scores
|
|
46804
|
+
};
|
|
46805
|
+
};
|
|
46806
|
+
//#endregion
|
|
45648
46807
|
//#region src/client/utils/type-utils.ts
|
|
45649
46808
|
var kDepthOrder = {
|
|
45650
46809
|
listed: 0,
|
|
@@ -45671,27 +46830,31 @@ var previewTier = (preview) => ({
|
|
|
45671
46830
|
primary_metric: preview.primary_metric
|
|
45672
46831
|
});
|
|
45673
46832
|
/** The detailed-tier attributes: the flat columns re-derived from the header
|
|
45674
|
-
* plus the header itself. */
|
|
46833
|
+
* plus the header itself and the derived listing columns. */
|
|
45675
46834
|
var detailTier = (header) => ({
|
|
45676
46835
|
...previewTier(toLogPreview(header)),
|
|
45677
46836
|
depth: "detailed",
|
|
45678
|
-
header
|
|
46837
|
+
header,
|
|
46838
|
+
derived: deriveLogFields(header)
|
|
45679
46839
|
});
|
|
45680
46840
|
/** Split a details payload into its stored header form: everything but the
|
|
45681
46841
|
* sample summaries, plus the sample facts derived from them. */
|
|
45682
46842
|
var toLogHeader = (details) => {
|
|
45683
46843
|
const { sampleSummaries, ...header } = details;
|
|
45684
|
-
const limits = /* @__PURE__ */ new Set();
|
|
45685
|
-
let errorCount = 0;
|
|
45686
|
-
for (const sample of sampleSummaries) {
|
|
45687
|
-
if (sample.error) errorCount += 1;
|
|
45688
|
-
if (sample.limit) limits.add(sample.limit);
|
|
45689
|
-
}
|
|
45690
46844
|
return {
|
|
45691
46845
|
...header,
|
|
45692
|
-
|
|
45693
|
-
|
|
45694
|
-
|
|
46846
|
+
...deriveSampleFacts(sampleSummaries)
|
|
46847
|
+
};
|
|
46848
|
+
};
|
|
46849
|
+
var prepareLogDetails = (details) => {
|
|
46850
|
+
const header = toLogHeader(details);
|
|
46851
|
+
return {
|
|
46852
|
+
header,
|
|
46853
|
+
patch: detailTier(header),
|
|
46854
|
+
summaries: details.sampleSummaries.map((summary) => ({
|
|
46855
|
+
summary,
|
|
46856
|
+
derived: deriveSampleFields(summary)
|
|
46857
|
+
}))
|
|
45695
46858
|
};
|
|
45696
46859
|
};
|
|
45697
46860
|
var toLogPreview = (header) => {
|
|
@@ -46153,7 +47316,7 @@ var FetchEngine = class {
|
|
|
46153
47316
|
this.stop();
|
|
46154
47317
|
this._deps = deps;
|
|
46155
47318
|
if (!deps.database) return;
|
|
46156
|
-
const rows = await deps.database.readLogs();
|
|
47319
|
+
const rows = await deps.database.readLogs({ prefix: deps.logDir });
|
|
46157
47320
|
if (!rows) return;
|
|
46158
47321
|
deps.sink.seedRows(rows);
|
|
46159
47322
|
this._handles = rows;
|
|
@@ -46456,10 +47619,11 @@ var FetchEngine = class {
|
|
|
46456
47619
|
}
|
|
46457
47620
|
}
|
|
46458
47621
|
async updateDbStats() {
|
|
46459
|
-
const
|
|
46460
|
-
|
|
47622
|
+
const deps = this._deps;
|
|
47623
|
+
const database = deps?.database;
|
|
47624
|
+
if (deps === void 0 || !database?.opened()) return;
|
|
46461
47625
|
try {
|
|
46462
|
-
const stats = await database.getCacheStats();
|
|
47626
|
+
const stats = await database.getCacheStats({ prefix: deps.logDir });
|
|
46463
47627
|
this.setStatus({ dbStats: {
|
|
46464
47628
|
logCount: stats.logFiles,
|
|
46465
47629
|
previewCount: stats.logSummaries,
|
|
@@ -50296,26 +51460,29 @@ var fromLogRecord = (record) => {
|
|
|
50296
51460
|
name: file_path
|
|
50297
51461
|
};
|
|
50298
51462
|
};
|
|
50299
|
-
|
|
50300
|
-
|
|
50301
|
-
|
|
51463
|
+
var DB_VERSION = 1301;
|
|
51464
|
+
var DB_NAME = "InspectAI";
|
|
51465
|
+
/** The boundary-safe prefix for scoping `file_path` queries to a dir:
|
|
51466
|
+
* `/logs/important` must not match `/logs/important-2`. */
|
|
51467
|
+
var scopePrefix = (dir) => dir.endsWith("/") ? dir : `${dir}/`;
|
|
50302
51468
|
var AppDatabase = class extends Dexie {
|
|
50303
51469
|
logs;
|
|
50304
51470
|
sample_summaries;
|
|
51471
|
+
sync_scopes;
|
|
50305
51472
|
/**
|
|
50306
51473
|
* Check if an existing database needs to be recreated due to version mismatch.
|
|
50307
51474
|
* Returns true if the database should be deleted and recreated.
|
|
50308
51475
|
*/
|
|
50309
|
-
static async checkVersionMismatch(
|
|
50310
|
-
const dbName =
|
|
51476
|
+
static async checkVersionMismatch() {
|
|
51477
|
+
const dbName = DB_NAME;
|
|
50311
51478
|
try {
|
|
50312
51479
|
if (!await Dexie.exists(dbName)) return false;
|
|
50313
51480
|
const tempDb = new Dexie(dbName);
|
|
50314
51481
|
await tempDb.open();
|
|
50315
51482
|
const currentVersion = tempDb.verno;
|
|
50316
51483
|
tempDb.close();
|
|
50317
|
-
if (currentVersion !==
|
|
50318
|
-
console.log(`Database version mismatch (found v${currentVersion}, expected
|
|
51484
|
+
if (currentVersion !== DB_VERSION) {
|
|
51485
|
+
console.log(`Database version mismatch (found v${currentVersion}, expected v${DB_VERSION})`);
|
|
50319
51486
|
return true;
|
|
50320
51487
|
}
|
|
50321
51488
|
return false;
|
|
@@ -50323,52 +51490,61 @@ var AppDatabase = class extends Dexie {
|
|
|
50323
51490
|
return false;
|
|
50324
51491
|
}
|
|
50325
51492
|
}
|
|
50326
|
-
constructor(
|
|
50327
|
-
super(
|
|
50328
|
-
this.version(
|
|
50329
|
-
logs: "++id, &file_path, mtime, task, task_id, depth, cached_at",
|
|
51493
|
+
constructor() {
|
|
51494
|
+
super(DB_NAME);
|
|
51495
|
+
this.version(DB_VERSION).stores({
|
|
51496
|
+
logs: "++id, &file_path, mtime, task, task_id, depth, cached_at, [depth+file_path]",
|
|
50330
51497
|
sample_summaries: "[file_path+id+epoch], file_path, summary.completed_at",
|
|
51498
|
+
sync_scopes: "prefix",
|
|
50331
51499
|
log_previews: null,
|
|
50332
51500
|
log_details: null,
|
|
50333
51501
|
log_fetch_state: null
|
|
50334
|
-
}).upgrade((tx) => Promise.all([
|
|
51502
|
+
}).upgrade((tx) => Promise.all([
|
|
51503
|
+
"logs",
|
|
51504
|
+
"sample_summaries",
|
|
51505
|
+
"sync_scopes"
|
|
51506
|
+
].map((table) => tx.table(table).clear())));
|
|
50335
51507
|
}
|
|
50336
51508
|
};
|
|
51509
|
+
/**
|
|
51510
|
+
* Delete pre-unification per-dir databases (`InspectAI_<sanitized dir>`).
|
|
51511
|
+
* Best-effort: `indexedDB.databases()` is not universally available and a
|
|
51512
|
+
* database held open by another (older) tab may survive until it closes.
|
|
51513
|
+
*/
|
|
51514
|
+
var deleteLegacyDatabases = async () => {
|
|
51515
|
+
try {
|
|
51516
|
+
const databases = await indexedDB.databases();
|
|
51517
|
+
await Promise.all(databases.map((info) => info.name).filter((name) => !!name?.startsWith(`${DB_NAME}_`)).map((name) => Dexie.delete(name).catch(() => {})));
|
|
51518
|
+
} catch {}
|
|
51519
|
+
};
|
|
50337
51520
|
//#endregion
|
|
50338
51521
|
//#region src/client/database/manager.ts
|
|
50339
|
-
var log$
|
|
51522
|
+
var log$6 = createLogger("DatabaseManager");
|
|
50340
51523
|
/**
|
|
50341
|
-
* Manages database
|
|
50342
|
-
*
|
|
51524
|
+
* Manages the (single, per-origin) database connection. Log dirs are query
|
|
51525
|
+
* scopes over the unified database, not separate databases.
|
|
50343
51526
|
*/
|
|
50344
51527
|
var DatabaseManager = class {
|
|
50345
51528
|
database = null;
|
|
50346
|
-
|
|
50347
|
-
|
|
50348
|
-
|
|
50349
|
-
|
|
50350
|
-
|
|
50351
|
-
|
|
50352
|
-
|
|
50353
|
-
|
|
50354
|
-
|
|
50355
|
-
|
|
50356
|
-
|
|
50357
|
-
log$5.info(`Recreating database due to version mismatch for: ${databaseHandle}`);
|
|
50358
|
-
const dbName = `InspectAI_${databaseHandle.replace(/[^a-zA-Z0-9_-]/g, "_")}`;
|
|
50359
|
-
await Dexie.delete(dbName);
|
|
50360
|
-
log$5.debug(`Deleted old database: ${dbName}`);
|
|
50361
|
-
}
|
|
50362
|
-
this.database = new AppDatabase(databaseHandle);
|
|
50363
|
-
this.databaseHandle = databaseHandle;
|
|
51529
|
+
/**
|
|
51530
|
+
* Open the database, returning the existing connection when already open.
|
|
51531
|
+
*/
|
|
51532
|
+
async openDatabase() {
|
|
51533
|
+
if (this.database) return this.database;
|
|
51534
|
+
if (await AppDatabase.checkVersionMismatch()) {
|
|
51535
|
+
log$6.info("Recreating database due to version mismatch");
|
|
51536
|
+
await Dexie.delete(DB_NAME);
|
|
51537
|
+
log$6.debug(`Deleted old database: ${DB_NAME}`);
|
|
51538
|
+
}
|
|
51539
|
+
this.database = new AppDatabase();
|
|
50364
51540
|
try {
|
|
50365
51541
|
await this.database.open();
|
|
50366
|
-
log$
|
|
51542
|
+
log$6.debug("Successfully opened database");
|
|
51543
|
+
deleteLegacyDatabases();
|
|
50367
51544
|
return this.database;
|
|
50368
51545
|
} catch (error) {
|
|
50369
|
-
log$
|
|
51546
|
+
log$6.error("Failed to open database:", error);
|
|
50370
51547
|
this.database = null;
|
|
50371
|
-
this.databaseHandle = null;
|
|
50372
51548
|
throw error;
|
|
50373
51549
|
}
|
|
50374
51550
|
}
|
|
@@ -50380,21 +51556,13 @@ var DatabaseManager = class {
|
|
|
50380
51556
|
return this.database;
|
|
50381
51557
|
}
|
|
50382
51558
|
/**
|
|
50383
|
-
* Get the current log directory.
|
|
50384
|
-
* Returns null if no database is open.
|
|
50385
|
-
*/
|
|
50386
|
-
getDatabaseHandle() {
|
|
50387
|
-
return this.databaseHandle;
|
|
50388
|
-
}
|
|
50389
|
-
/**
|
|
50390
51559
|
* Close the current database connection.
|
|
50391
51560
|
*/
|
|
50392
51561
|
close() {
|
|
50393
51562
|
if (this.database) {
|
|
50394
|
-
log$
|
|
51563
|
+
log$6.debug("Closing database");
|
|
50395
51564
|
this.database.close();
|
|
50396
51565
|
this.database = null;
|
|
50397
|
-
this.databaseHandle = null;
|
|
50398
51566
|
}
|
|
50399
51567
|
return Promise.resolve();
|
|
50400
51568
|
}
|
|
@@ -50402,21 +51570,12 @@ var DatabaseManager = class {
|
|
|
50402
51570
|
* Check if a database is currently open.
|
|
50403
51571
|
*/
|
|
50404
51572
|
isOpen() {
|
|
50405
|
-
return this.database !== null
|
|
50406
|
-
}
|
|
50407
|
-
/**
|
|
50408
|
-
* Get database info for debugging.
|
|
50409
|
-
*/
|
|
50410
|
-
getInfo() {
|
|
50411
|
-
return {
|
|
50412
|
-
databaseHandle: this.databaseHandle,
|
|
50413
|
-
isOpen: this.isOpen()
|
|
50414
|
-
};
|
|
51573
|
+
return this.database !== null;
|
|
50415
51574
|
}
|
|
50416
51575
|
};
|
|
50417
51576
|
//#endregion
|
|
50418
51577
|
//#region src/client/database/service.ts
|
|
50419
|
-
var log$
|
|
51578
|
+
var log$5 = createLogger("DatabaseService");
|
|
50420
51579
|
var newRow$1 = (handle) => ({
|
|
50421
51580
|
...handle,
|
|
50422
51581
|
depth: "listed",
|
|
@@ -50446,10 +51605,10 @@ var DatabaseService = class {
|
|
|
50446
51605
|
return this.manager.getDatabase() !== null;
|
|
50447
51606
|
}
|
|
50448
51607
|
/**
|
|
50449
|
-
* Open
|
|
51608
|
+
* Open the (unified) database.
|
|
50450
51609
|
*/
|
|
50451
|
-
async openDatabase(
|
|
50452
|
-
await this.manager.openDatabase(
|
|
51610
|
+
async openDatabase() {
|
|
51611
|
+
await this.manager.openDatabase();
|
|
50453
51612
|
}
|
|
50454
51613
|
/**
|
|
50455
51614
|
* Close the current database connection.
|
|
@@ -50458,12 +51617,6 @@ var DatabaseService = class {
|
|
|
50458
51617
|
await this.manager.close();
|
|
50459
51618
|
}
|
|
50460
51619
|
/**
|
|
50461
|
-
* Get the current log directory.
|
|
50462
|
-
*/
|
|
50463
|
-
getDatabaseHandle() {
|
|
50464
|
-
return this.manager.getDatabaseHandle();
|
|
50465
|
-
}
|
|
50466
|
-
/**
|
|
50467
51620
|
* Upsert the listing identity tier: new files get fresh listed-depth rows;
|
|
50468
51621
|
* known files update identity fields only (depth, content, and retrieval
|
|
50469
51622
|
* facts are preserved).
|
|
@@ -50471,7 +51624,7 @@ var DatabaseService = class {
|
|
|
50471
51624
|
async writeLogs(handles) {
|
|
50472
51625
|
const db = this.getDb();
|
|
50473
51626
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
50474
|
-
const existingRecords = await db.logs.toArray();
|
|
51627
|
+
const existingRecords = await db.logs.where("file_path").anyOf(handles.map((handle) => handle.name)).toArray();
|
|
50475
51628
|
const existingByPath = new Map(existingRecords.map((record) => [record.file_path, record]));
|
|
50476
51629
|
const records = handles.map((handle) => {
|
|
50477
51630
|
const existing = existingByPath.get(handle.name);
|
|
@@ -50483,25 +51636,25 @@ var DatabaseService = class {
|
|
|
50483
51636
|
cached_at: now
|
|
50484
51637
|
} : toLogRecord(newRow$1(handle), void 0, now);
|
|
50485
51638
|
});
|
|
50486
|
-
log$
|
|
51639
|
+
log$5.debug(`Upserting ${records.length} log rows (identity tier)`);
|
|
50487
51640
|
await db.logs.bulkPut(records);
|
|
50488
51641
|
}
|
|
50489
|
-
async readLogs() {
|
|
51642
|
+
async readLogs(scope) {
|
|
50490
51643
|
try {
|
|
50491
51644
|
if (!this.opened()) {
|
|
50492
|
-
log$
|
|
51645
|
+
log$5.debug("Database not open");
|
|
50493
51646
|
return null;
|
|
50494
51647
|
}
|
|
50495
|
-
const records = await this.getDb().logs.toArray();
|
|
51648
|
+
const records = await this.getDb().logs.where("file_path").startsWith(scopePrefix(scope.prefix)).toArray();
|
|
50496
51649
|
records.sort((a, b) => {
|
|
50497
51650
|
if (a.mtime != null && b.mtime != null) return b.mtime - a.mtime;
|
|
50498
51651
|
if (a.id != null && b.id != null) return a.id - b.id;
|
|
50499
51652
|
return 0;
|
|
50500
51653
|
});
|
|
50501
|
-
log$
|
|
51654
|
+
log$5.debug(`Retrieved ${records.length} log rows`);
|
|
50502
51655
|
return records.map(fromLogRecord);
|
|
50503
51656
|
} catch (error) {
|
|
50504
|
-
log$
|
|
51657
|
+
log$5.error("Error retrieving log rows:", error);
|
|
50505
51658
|
return null;
|
|
50506
51659
|
}
|
|
50507
51660
|
}
|
|
@@ -50510,7 +51663,7 @@ var DatabaseService = class {
|
|
|
50510
51663
|
const record = await this.getDb().logs.where("file_path").equals(filePath).first();
|
|
50511
51664
|
return record ? fromLogRecord(record) : null;
|
|
50512
51665
|
} catch (error) {
|
|
50513
|
-
log$
|
|
51666
|
+
log$5.error(`Error retrieving log row for ${filePath}:`, error);
|
|
50514
51667
|
return null;
|
|
50515
51668
|
}
|
|
50516
51669
|
}
|
|
@@ -50521,7 +51674,7 @@ var DatabaseService = class {
|
|
|
50521
51674
|
for (const record of records) result[record.file_path] = fromLogRecord(record);
|
|
50522
51675
|
return result;
|
|
50523
51676
|
} catch (error) {
|
|
50524
|
-
log$
|
|
51677
|
+
log$5.error("Error retrieving log rows:", error);
|
|
50525
51678
|
return {};
|
|
50526
51679
|
}
|
|
50527
51680
|
}
|
|
@@ -50549,39 +51702,41 @@ var DatabaseService = class {
|
|
|
50549
51702
|
await db.logs.bulkPut(records);
|
|
50550
51703
|
}
|
|
50551
51704
|
async writeLogPreviews(previews) {
|
|
50552
|
-
log$
|
|
51705
|
+
log$5.debug(`Upserting ${Object.keys(previews).length} log rows (previewed tier)`);
|
|
50553
51706
|
await this.mergeRows(Object.fromEntries(Object.entries(previews).map(([file, preview]) => [file, previewTier(preview)])));
|
|
50554
51707
|
}
|
|
50555
51708
|
/**
|
|
50556
|
-
* Ingest details payloads
|
|
50557
|
-
*
|
|
50558
|
-
*
|
|
50559
|
-
*
|
|
51709
|
+
* Ingest prepared details payloads (`prepareLogDetails` — the seam
|
|
51710
|
+
* normalizes once for both stores): merge the detailed tier into each log
|
|
51711
|
+
* row and replace the file's sample summary rows, in one transaction per
|
|
51712
|
+
* call so a reader never sees a header whose summary rows are from an
|
|
51713
|
+
* older ingestion.
|
|
50560
51714
|
*/
|
|
50561
51715
|
async writeLogDetails(details) {
|
|
50562
51716
|
const db = this.getDb();
|
|
50563
51717
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
50564
51718
|
const entries = Object.entries(details);
|
|
50565
|
-
log$
|
|
51719
|
+
log$5.debug(`Ingesting ${entries.length} log details (split)`);
|
|
50566
51720
|
await db.transaction("rw", db.logs, db.sample_summaries, async () => {
|
|
50567
|
-
await this.mergeRows(Object.fromEntries(entries.map(([file,
|
|
51721
|
+
await this.mergeRows(Object.fromEntries(entries.map(([file, { patch }]) => [file, patch])));
|
|
50568
51722
|
const files = entries.map(([filePath]) => filePath);
|
|
50569
51723
|
await db.sample_summaries.where("file_path").anyOf(files).delete();
|
|
50570
|
-
await db.sample_summaries.bulkPut(entries.flatMap(([filePath,
|
|
51724
|
+
await db.sample_summaries.bulkPut(entries.flatMap(([filePath, { summaries }]) => summaries.map(({ summary, derived }) => ({
|
|
50571
51725
|
file_path: filePath,
|
|
50572
51726
|
id: summary.id,
|
|
50573
51727
|
epoch: summary.epoch,
|
|
50574
51728
|
summary,
|
|
51729
|
+
derived,
|
|
50575
51730
|
cached_at: now
|
|
50576
51731
|
}))));
|
|
50577
51732
|
});
|
|
50578
51733
|
}
|
|
50579
51734
|
async readSampleSummaries(scope) {
|
|
50580
51735
|
const db = this.getDb();
|
|
50581
|
-
return ("file" in scope ? db.sample_summaries.where("file_path").equals(scope.file) : db.sample_summaries.where("file_path").startsWith(scope.prefix)).toArray();
|
|
51736
|
+
return ("file" in scope ? db.sample_summaries.where("file_path").equals(scope.file) : db.sample_summaries.where("file_path").startsWith(scopePrefix(scope.prefix))).toArray();
|
|
50582
51737
|
}
|
|
50583
51738
|
async writeFetchStates(states) {
|
|
50584
|
-
log$
|
|
51739
|
+
log$5.debug(`Merging retrieval facts into ${Object.keys(states).length} log rows`);
|
|
50585
51740
|
await this.mergeRows(states);
|
|
50586
51741
|
}
|
|
50587
51742
|
/**
|
|
@@ -50606,34 +51761,95 @@ var DatabaseService = class {
|
|
|
50606
51761
|
/** Remove a deleted file's row and its sample summaries. */
|
|
50607
51762
|
async clearCacheForFile(filePath) {
|
|
50608
51763
|
const db = this.getDb();
|
|
50609
|
-
log$
|
|
51764
|
+
log$5.debug(`Clearing cache for file: ${filePath}`);
|
|
50610
51765
|
await Promise.all([db.logs.where("file_path").equals(filePath).delete(), db.sample_summaries.where("file_path").equals(filePath).delete()]);
|
|
50611
51766
|
}
|
|
50612
51767
|
/**
|
|
50613
|
-
*
|
|
51768
|
+
* Wipe every table — the "Clear Local Database" escape hatch. Unlike
|
|
51769
|
+
* `clearScope`, this reaches rows persisted under names outside any synced
|
|
51770
|
+
* scope's namespace (see `namesInScope` in logsContent).
|
|
51771
|
+
*/
|
|
51772
|
+
async clearAllData() {
|
|
51773
|
+
const db = this.getDb();
|
|
51774
|
+
log$5.debug("Clearing all cached data");
|
|
51775
|
+
await db.transaction("rw", [
|
|
51776
|
+
db.logs,
|
|
51777
|
+
db.sample_summaries,
|
|
51778
|
+
db.sync_scopes
|
|
51779
|
+
], () => Promise.all([
|
|
51780
|
+
db.logs.clear(),
|
|
51781
|
+
db.sample_summaries.clear(),
|
|
51782
|
+
db.sync_scopes.clear()
|
|
51783
|
+
]));
|
|
51784
|
+
}
|
|
51785
|
+
/**
|
|
51786
|
+
* Clear all cached data under a scope: its log rows, their sample
|
|
51787
|
+
* summaries, and the scope's sync record. Other scopes' rows are untouched.
|
|
50614
51788
|
*/
|
|
50615
|
-
async
|
|
51789
|
+
async clearScope(scope) {
|
|
50616
51790
|
const db = this.getDb();
|
|
50617
|
-
|
|
50618
|
-
|
|
51791
|
+
const prefix = scopePrefix(scope.prefix);
|
|
51792
|
+
log$5.debug(`Clearing caches under: ${prefix}`);
|
|
51793
|
+
await db.transaction("rw", [
|
|
51794
|
+
db.logs,
|
|
51795
|
+
db.sample_summaries,
|
|
51796
|
+
db.sync_scopes
|
|
51797
|
+
], () => Promise.all([
|
|
51798
|
+
db.logs.where("file_path").startsWith(prefix).delete(),
|
|
51799
|
+
db.sample_summaries.where("file_path").startsWith(prefix).delete(),
|
|
51800
|
+
db.sync_scopes.where("prefix").startsWith(prefix).delete()
|
|
51801
|
+
]));
|
|
51802
|
+
}
|
|
51803
|
+
/** Record that a scope is active (creating its row on first contact). */
|
|
51804
|
+
async touchSyncScope(prefix) {
|
|
51805
|
+
const db = this.getDb();
|
|
51806
|
+
const key = scopePrefix(prefix);
|
|
51807
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
51808
|
+
await db.transaction("rw", db.sync_scopes, async () => {
|
|
51809
|
+
const existing = await db.sync_scopes.get(key);
|
|
51810
|
+
await db.sync_scopes.put({
|
|
51811
|
+
...existing,
|
|
51812
|
+
prefix: key,
|
|
51813
|
+
last_accessed: now
|
|
51814
|
+
});
|
|
51815
|
+
});
|
|
51816
|
+
}
|
|
51817
|
+
/** Read a scope's sync record (undefined when never activated). */
|
|
51818
|
+
async getSyncScope(prefix) {
|
|
51819
|
+
return this.getDb().sync_scopes.get(scopePrefix(prefix));
|
|
51820
|
+
}
|
|
51821
|
+
/** Record that a listing sync persisted under a scope. */
|
|
51822
|
+
async markScopeSynced(prefix) {
|
|
51823
|
+
const db = this.getDb();
|
|
51824
|
+
const key = scopePrefix(prefix);
|
|
51825
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
51826
|
+
await db.transaction("rw", db.sync_scopes, async () => {
|
|
51827
|
+
const existing = await db.sync_scopes.get(key);
|
|
51828
|
+
await db.sync_scopes.put({
|
|
51829
|
+
prefix: key,
|
|
51830
|
+
last_accessed: existing?.last_accessed ?? now,
|
|
51831
|
+
last_synced: now
|
|
51832
|
+
});
|
|
51833
|
+
});
|
|
50619
51834
|
}
|
|
50620
51835
|
/**
|
|
50621
|
-
* Get cache statistics.
|
|
51836
|
+
* Get cache statistics for a scope.
|
|
50622
51837
|
*/
|
|
50623
|
-
async getCacheStats() {
|
|
51838
|
+
async getCacheStats(scope) {
|
|
50624
51839
|
const db = this.getDb();
|
|
50625
|
-
const
|
|
50626
|
-
|
|
50627
|
-
|
|
50628
|
-
db.logs.where("
|
|
50629
|
-
|
|
51840
|
+
const prefix = scopePrefix(scope.prefix);
|
|
51841
|
+
const depthCount = (depth) => db.logs.where("[depth+file_path]").between([depth, prefix], [depth, prefix + ""]).count();
|
|
51842
|
+
const [logFiles, previewed, detailed, sampleSummaries] = await Promise.all([
|
|
51843
|
+
db.logs.where("file_path").startsWith(prefix).count(),
|
|
51844
|
+
depthCount("previewed"),
|
|
51845
|
+
depthCount("detailed"),
|
|
51846
|
+
db.sample_summaries.where("file_path").startsWith(prefix).count()
|
|
50630
51847
|
]);
|
|
50631
51848
|
return {
|
|
50632
51849
|
logFiles,
|
|
50633
|
-
logSummaries,
|
|
50634
|
-
logHeaders,
|
|
50635
|
-
sampleSummaries
|
|
50636
|
-
logHandle: this.manager.getDatabaseHandle()
|
|
51850
|
+
logSummaries: previewed + detailed,
|
|
51851
|
+
logHeaders: detailed,
|
|
51852
|
+
sampleSummaries
|
|
50637
51853
|
};
|
|
50638
51854
|
}
|
|
50639
51855
|
};
|
|
@@ -50744,11 +51960,12 @@ var rowContext = (row) => row === void 0 ? {} : {
|
|
|
50744
51960
|
model: row.model,
|
|
50745
51961
|
status: row.status
|
|
50746
51962
|
};
|
|
50747
|
-
/** Assemble listing rows from
|
|
51963
|
+
/** Assemble listing rows from a prepared payload's parts (the sink's push
|
|
50748
51964
|
* path — the db read below produces the same shape). */
|
|
50749
|
-
var toSamplesListingRows = (logFile, header, summaries) => summaries.map((summary) => ({
|
|
51965
|
+
var toSamplesListingRows = (logFile, header, summaries) => summaries.map(({ summary, derived }) => ({
|
|
50750
51966
|
logFile,
|
|
50751
51967
|
summary,
|
|
51968
|
+
derived,
|
|
50752
51969
|
log: logContext(header)
|
|
50753
51970
|
}));
|
|
50754
51971
|
var pageOf = (rows, params) => {
|
|
@@ -50765,6 +51982,7 @@ var readSamplesListing = async (params) => {
|
|
|
50765
51982
|
return pageOf(records.map((record) => ({
|
|
50766
51983
|
logFile: record.file_path,
|
|
50767
51984
|
summary: record.summary,
|
|
51985
|
+
derived: record.derived,
|
|
50768
51986
|
log: contexts.get(record.file_path) ?? {}
|
|
50769
51987
|
})), params);
|
|
50770
51988
|
};
|
|
@@ -50840,6 +52058,7 @@ var removeSamplesListings = (logDir) => {
|
|
|
50840
52058
|
* `set*`/`merge*`/`seed*` primitives) are allowed; the invariant is
|
|
50841
52059
|
* one-directional (db ⟹ cache).
|
|
50842
52060
|
*/
|
|
52061
|
+
var log$4 = createLogger("logsContent");
|
|
50843
52062
|
var EMPTY_LOGS = [];
|
|
50844
52063
|
var logsKey = (logDir) => [
|
|
50845
52064
|
"log_data",
|
|
@@ -50949,15 +52168,44 @@ var clearCache = (logDir) => {
|
|
|
50949
52168
|
removeSamplesListings(logDir);
|
|
50950
52169
|
};
|
|
50951
52170
|
/**
|
|
52171
|
+
* The store scopes every read by `file_path.startsWith(scopePrefix(logDir))`,
|
|
52172
|
+
* so persistence requires the listing's names to live in `logDir`'s
|
|
52173
|
+
* namespace. A server can violate that (e.g. an older view server hands out
|
|
52174
|
+
* an aliased local path as log_dir while names are `file://` URIs) —
|
|
52175
|
+
* persisting under such a scope would strand the rows where no scoped read,
|
|
52176
|
+
* clear, or seed can reach them, and the empty read-back would blank the
|
|
52177
|
+
* just-synced listing. Degrade to cache-only instead.
|
|
52178
|
+
*
|
|
52179
|
+
* Only listing persistence is gated: the keyed writes below (previews,
|
|
52180
|
+
* details, fetch states) still persist out-of-namespace rows, which serve
|
|
52181
|
+
* exact-path reads but which no listing sync governs and no scoped clear can
|
|
52182
|
+
* remove. "Clear Local Database" (`clearAll`) wipes them along with
|
|
52183
|
+
* everything else.
|
|
52184
|
+
*/
|
|
52185
|
+
var warnedScopes = /* @__PURE__ */ new Set();
|
|
52186
|
+
var namesInScope = (logDir, handles) => {
|
|
52187
|
+
const prefix = scopePrefix(logDir);
|
|
52188
|
+
const misnamed = handles.find((handle) => !handle.name.startsWith(prefix));
|
|
52189
|
+
if (misnamed !== void 0) {
|
|
52190
|
+
if (!warnedScopes.has(prefix)) {
|
|
52191
|
+
warnedScopes.add(prefix);
|
|
52192
|
+
log$4.warn(`Listing names (e.g. ${misnamed.name}) are outside the log dir's namespace (${prefix}); skipping persistence for this scope.`);
|
|
52193
|
+
}
|
|
52194
|
+
return false;
|
|
52195
|
+
}
|
|
52196
|
+
return true;
|
|
52197
|
+
};
|
|
52198
|
+
/**
|
|
50952
52199
|
* Persist the listing identity tier and cache the resulting full row list.
|
|
50953
52200
|
* The db write is a merge-upsert (rows keep depth/content) and the cache
|
|
50954
52201
|
* holds the full re-read, so the full list is read back and returned for the
|
|
50955
52202
|
* caller's continued sync logic.
|
|
50956
52203
|
*/
|
|
50957
52204
|
var writeListing = async (db, logDir, handles) => {
|
|
50958
|
-
if (db?.opened()) {
|
|
52205
|
+
if (db?.opened() && namesInScope(logDir, handles)) {
|
|
50959
52206
|
await db.writeLogs(handles);
|
|
50960
|
-
|
|
52207
|
+
await db.markScopeSynced(logDir);
|
|
52208
|
+
const all = await db.readLogs({ prefix: logDir });
|
|
50961
52209
|
if (all) {
|
|
50962
52210
|
setRows(logDir, all);
|
|
50963
52211
|
return all;
|
|
@@ -50982,14 +52230,11 @@ var writePreviews = async (db, logDir, previews) => {
|
|
|
50982
52230
|
* clobber them with an empty read — so the sweep is persistence-gated.
|
|
50983
52231
|
*/
|
|
50984
52232
|
var writeDetails = async (db, logDir, details) => {
|
|
50985
|
-
const
|
|
50986
|
-
await Promise.all(
|
|
50987
|
-
|
|
50988
|
-
return header === void 0 ? Promise.resolve() : pushFileSamples(logDir, name, toSamplesListingRows(name, header, payload.sampleSummaries));
|
|
50989
|
-
}));
|
|
50990
|
-
mergePatches(logDir, Object.fromEntries(Object.entries(headers).map(([name, header]) => [name, detailTier(header)])));
|
|
52233
|
+
const prepared = Object.entries(details).map(([name, payload]) => [name, prepareLogDetails(payload)]);
|
|
52234
|
+
await Promise.all(prepared.map(([name, file]) => pushFileSamples(logDir, name, toSamplesListingRows(name, file.header, file.summaries))));
|
|
52235
|
+
mergePatches(logDir, Object.fromEntries(prepared.map(([name, file]) => [name, file.patch])));
|
|
50991
52236
|
if (db?.opened()) {
|
|
50992
|
-
await db.writeLogDetails(
|
|
52237
|
+
await db.writeLogDetails(Object.fromEntries(prepared));
|
|
50993
52238
|
invalidateSamplesListings(logDir);
|
|
50994
52239
|
}
|
|
50995
52240
|
};
|
|
@@ -51023,7 +52268,7 @@ var clearFile = async (db, logDir, name) => {
|
|
|
51023
52268
|
};
|
|
51024
52269
|
var clearAll = async (db, logDir) => {
|
|
51025
52270
|
clearCache(logDir);
|
|
51026
|
-
if (db?.opened()) await db.
|
|
52271
|
+
if (db?.opened()) await db.clearAllData();
|
|
51027
52272
|
};
|
|
51028
52273
|
/**
|
|
51029
52274
|
* The seam as a fetch-engine sink: the write surface bound to a directory and
|
|
@@ -51073,7 +52318,8 @@ var resolveLogKey = (logDir, logFile) => {
|
|
|
51073
52318
|
var openLogDirDatabase = async (logDir) => {
|
|
51074
52319
|
const databaseService = getDatabaseService();
|
|
51075
52320
|
try {
|
|
51076
|
-
await databaseService.openDatabase(
|
|
52321
|
+
await databaseService.openDatabase();
|
|
52322
|
+
await databaseService.touchSyncScope(logDir);
|
|
51077
52323
|
return databaseService;
|
|
51078
52324
|
} catch (e) {
|
|
51079
52325
|
console.log(e);
|
|
@@ -51081,15 +52327,15 @@ var openLogDirDatabase = async (logDir) => {
|
|
|
51081
52327
|
}
|
|
51082
52328
|
};
|
|
51083
52329
|
var ensureActive = async (logDir) => {
|
|
51084
|
-
|
|
51085
|
-
if (!fetchEngine.isStarted() || engineDir !== logDir || getDatabaseService().getDatabaseHandle() !== databaseHandle) {
|
|
52330
|
+
if (!fetchEngine.isStarted() || engineDir !== logDir || !getDatabaseService().opened()) {
|
|
51086
52331
|
fetchEngine.stop();
|
|
51087
52332
|
const opened = await openLogDirDatabase(logDir);
|
|
51088
52333
|
if (!opened) throw new Error("Database service not available");
|
|
51089
52334
|
await fetchEngine.start({
|
|
51090
52335
|
api: getApi(),
|
|
51091
52336
|
database: opened,
|
|
51092
|
-
sink: createLogsContentSink(opened, logDir)
|
|
52337
|
+
sink: createLogsContentSink(opened, logDir),
|
|
52338
|
+
logDir
|
|
51093
52339
|
});
|
|
51094
52340
|
engineDir = logDir;
|
|
51095
52341
|
}
|
|
@@ -51114,7 +52360,8 @@ var ensureFetchEngine = (logDir) => {
|
|
|
51114
52360
|
await fetchEngine.start({
|
|
51115
52361
|
api: getApi(),
|
|
51116
52362
|
database,
|
|
51117
|
-
sink: createLogsContentSink(database, logDir)
|
|
52363
|
+
sink: createLogsContentSink(database, logDir),
|
|
52364
|
+
logDir
|
|
51118
52365
|
});
|
|
51119
52366
|
engineDir = logDir;
|
|
51120
52367
|
}
|
|
@@ -51537,90 +52784,6 @@ var sampleHandlesEqual = (sample1, sample2) => {
|
|
|
51537
52784
|
return sampleIdsEqual(sample1.id, sample2.id) && sample1.epoch === sample2.epoch && sample1.logFile === sample2.logFile;
|
|
51538
52785
|
};
|
|
51539
52786
|
//#endregion
|
|
51540
|
-
//#region ../../packages/inspect-common/src/utils/expandEvents.ts
|
|
51541
|
-
/**
|
|
51542
|
-
* Expand range-encoded refs against a pool.
|
|
51543
|
-
* Each ref is [start, endExclusive] → pool.slice(start, endExclusive).
|
|
51544
|
-
*/
|
|
51545
|
-
function expandRefs$1(refs, pool) {
|
|
51546
|
-
return refs.flatMap(([start, end]) => pool.slice(start, end));
|
|
51547
|
-
}
|
|
51548
|
-
function isModelEvent(event) {
|
|
51549
|
-
return event.event === "model";
|
|
51550
|
-
}
|
|
51551
|
-
/**
|
|
51552
|
-
* Expand condensed ModelEvent input/call refs back to inline data.
|
|
51553
|
-
*
|
|
51554
|
-
* Pure function — returns a new array; input is not mutated.
|
|
51555
|
-
* Non-ModelEvents and ModelEvents without refs pass through unchanged.
|
|
51556
|
-
*/
|
|
51557
|
-
function expandEvents(events, eventsData) {
|
|
51558
|
-
if (!eventsData) return events;
|
|
51559
|
-
const { messages, calls } = eventsData;
|
|
51560
|
-
const hasMessages = messages.length > 0;
|
|
51561
|
-
const hasCalls = calls.length > 0;
|
|
51562
|
-
if (!hasMessages && !hasCalls) return events;
|
|
51563
|
-
return events.map((event) => {
|
|
51564
|
-
if (!isModelEvent(event)) return event;
|
|
51565
|
-
let changed = false;
|
|
51566
|
-
let input = event.input;
|
|
51567
|
-
let call = event.call;
|
|
51568
|
-
if (event.input_refs != null && hasMessages) {
|
|
51569
|
-
input = expandRefs$1(event.input_refs, messages);
|
|
51570
|
-
changed = true;
|
|
51571
|
-
}
|
|
51572
|
-
if (call?.call_refs != null && hasCalls) {
|
|
51573
|
-
const key = call.call_key ?? "messages";
|
|
51574
|
-
const expandedMsgs = expandRefs$1(call.call_refs, calls);
|
|
51575
|
-
call = {
|
|
51576
|
-
...call,
|
|
51577
|
-
request: {
|
|
51578
|
-
...call.request,
|
|
51579
|
-
[key]: expandedMsgs
|
|
51580
|
-
},
|
|
51581
|
-
call_refs: null,
|
|
51582
|
-
call_key: null
|
|
51583
|
-
};
|
|
51584
|
-
changed = true;
|
|
51585
|
-
}
|
|
51586
|
-
return changed ? {
|
|
51587
|
-
...event,
|
|
51588
|
-
input,
|
|
51589
|
-
input_refs: null,
|
|
51590
|
-
call
|
|
51591
|
-
} : event;
|
|
51592
|
-
});
|
|
51593
|
-
}
|
|
51594
|
-
//#endregion
|
|
51595
|
-
//#region ../../packages/inspect-common/src/utils/inputString.ts
|
|
51596
|
-
/**
|
|
51597
|
-
* Gets a string for a sample input.
|
|
51598
|
-
*/
|
|
51599
|
-
var inputString = (input) => {
|
|
51600
|
-
if (typeof input === "string") return [input];
|
|
51601
|
-
else return input.map((inp) => {
|
|
51602
|
-
if (typeof inp === "string") return inp;
|
|
51603
|
-
else {
|
|
51604
|
-
const content = inp.content;
|
|
51605
|
-
if (typeof content === "string") return content;
|
|
51606
|
-
else return content.map((con) => {
|
|
51607
|
-
if (con.type === "text") return con.text;
|
|
51608
|
-
else return "";
|
|
51609
|
-
}).join("\n");
|
|
51610
|
-
}
|
|
51611
|
-
});
|
|
51612
|
-
};
|
|
51613
|
-
//#endregion
|
|
51614
|
-
//#region ../../packages/inspect-common/src/utils/modelFallbacks.ts
|
|
51615
|
-
/**
|
|
51616
|
-
* Total generate calls served via fallback across a sample's rollup.
|
|
51617
|
-
*/
|
|
51618
|
-
var totalModelFallbacks = (fallbacks) => (fallbacks ?? []).reduce((sum, f) => sum + (f.count ?? 1), 0);
|
|
51619
|
-
/**
|
|
51620
|
-
* One "requested → served (×N)" line per fallback rollup entry.
|
|
51621
|
-
*/
|
|
51622
|
-
var modelFallbackLines = (fallbacks) => (fallbacks ?? []).map((f) => `${f.model} → ${f.fallback_model}${(f.count ?? 1) > 1 ? ` (×${f.count})` : ""}`);
|
|
51623
|
-
//#endregion
|
|
51624
52787
|
//#region src/utils/attachments.ts
|
|
51625
52788
|
var resolveAttachments = (value, attachments, onFailedResolve) => {
|
|
51626
52789
|
const CONTENT_PROTOCOL = "tc://";
|
|
@@ -52269,13 +53432,14 @@ var scorerMetricKey = (scorerName, metricName) => `${scorerName}/${metricName}`;
|
|
|
52269
53432
|
* scorers emitting the same metric (e.g. two "accuracy"s) into one column.
|
|
52270
53433
|
*
|
|
52271
53434
|
* @param logs - The directory's Log rows
|
|
52272
|
-
* @param
|
|
52273
|
-
*
|
|
53435
|
+
* @param scopeDir - When set, only logs under this directory contribute
|
|
53436
|
+
* (folder view scoping)
|
|
52274
53437
|
*/
|
|
52275
|
-
function computeScorerMap(logs,
|
|
53438
|
+
function computeScorerMap(logs, scopeDir) {
|
|
52276
53439
|
const info = {};
|
|
53440
|
+
const prefix = scopeDir ? scopePrefix(scopeDir) : void 0;
|
|
52277
53441
|
for (const log of logs) {
|
|
52278
|
-
if (
|
|
53442
|
+
if (prefix && !log.name.startsWith(prefix)) continue;
|
|
52279
53443
|
if (log.header?.results?.scores) {
|
|
52280
53444
|
for (const evalScore of log.header.results.scores) if (evalScore.metrics) for (const [metricName, metric] of Object.entries(evalScore.metrics)) {
|
|
52281
53445
|
const key = scorerMetricKey(evalScore.name, metricName);
|
|
@@ -52309,8 +53473,8 @@ function scorerMapsEqual(a, b) {
|
|
|
52309
53473
|
* across flushes.
|
|
52310
53474
|
*/
|
|
52311
53475
|
var asyncScorerMapsEqual = (a, b) => a.loading === b.loading && a.error === b.error && (a.data !== void 0 && b.data !== void 0 ? scorerMapsEqual(a.data, b.data) : a.data === b.data);
|
|
52312
|
-
var useScoreSchema = (logDir,
|
|
52313
|
-
return useStableValue(useMapAsyncData(useLogs(logDir), useCallback((rows) => computeScorerMap(rows,
|
|
53476
|
+
var useScoreSchema = (logDir, scopeDir) => {
|
|
53477
|
+
return useStableValue(useMapAsyncData(useLogs(logDir), useCallback((rows) => computeScorerMap(rows, scopeDir), [scopeDir])), asyncScorerMapsEqual);
|
|
52314
53478
|
};
|
|
52315
53479
|
//#endregion
|
|
52316
53480
|
//#region src/utils/uri.ts
|
|
@@ -55227,7 +56391,7 @@ var initializeStore = (capabilities, storage) => {
|
|
|
55227
56391
|
getItem: (name) => {
|
|
55228
56392
|
return storage ? storage.getItem(name) : null;
|
|
55229
56393
|
},
|
|
55230
|
-
setItem: debounce$
|
|
56394
|
+
setItem: debounce$3((name, value) => {
|
|
55231
56395
|
if (storage) storage.setItem(name, value);
|
|
55232
56396
|
}, 1e3),
|
|
55233
56397
|
removeItem: (name) => {
|
|
@@ -57832,9 +58996,6 @@ var clientApi = (api, log_file, debug = false) => {
|
|
|
57832
58996
|
return api.client_events();
|
|
57833
58997
|
}),
|
|
57834
58998
|
get_log_dir: middleware("get_log_dir", get_log_dir),
|
|
57835
|
-
get_log_dir_handle: middleware("get_log_dir_handle", (log_dir) => {
|
|
57836
|
-
return api.get_log_dir_handle ? api.get_log_dir_handle(log_dir) : log_dir || "default_log_dir";
|
|
57837
|
-
}),
|
|
57838
58999
|
get_logs: middleware("get_log_files", get_logs),
|
|
57839
59000
|
get_log_root: middleware("get_log_root", get_log_root),
|
|
57840
59001
|
get_eval_set: middleware("get_eval_set", (dir) => {
|
|
@@ -58025,6 +59186,15 @@ function joinURI(...segments) {
|
|
|
58025
59186
|
}
|
|
58026
59187
|
//#endregion
|
|
58027
59188
|
//#region src/client/api/static-http/api-static-http.ts
|
|
59189
|
+
/** The canonical, origin-unique URL of a deployment's log dir. A relative
|
|
59190
|
+
* configured log_dir is page-relative for fetching, but page-relative
|
|
59191
|
+
* strings are not identities: two bundles at different paths on one origin
|
|
59192
|
+
* would collide in the shared per-origin IndexedDB. So everything the app
|
|
59193
|
+
* sees (log_dir, file names) is absolute. */
|
|
59194
|
+
var canonicalDirUrl = (log_dir) => {
|
|
59195
|
+
if (isUri(log_dir)) return log_dir;
|
|
59196
|
+
return joinURI(`${window.location.origin}${window.location.pathname.substring(0, window.location.pathname.lastIndexOf("/"))}`, log_dir);
|
|
59197
|
+
};
|
|
58028
59198
|
var kFallbackAppConfig = {
|
|
58029
59199
|
inspect_version: "unknown",
|
|
58030
59200
|
scout_version: null
|
|
@@ -58049,6 +59219,7 @@ function staticHttpApi(log_dir, log_file, abs_log_dir, app_config) {
|
|
|
58049
59219
|
*/
|
|
58050
59220
|
function staticHttpApiForLog(logInfo) {
|
|
58051
59221
|
const log_dir = logInfo.log_dir;
|
|
59222
|
+
const canonical_log_dir = log_dir === void 0 ? void 0 : canonicalDirUrl(log_dir);
|
|
58052
59223
|
const abs_log_dir = logInfo.abs_log_dir;
|
|
58053
59224
|
const app_config = logInfo.app_config ?? kFallbackAppConfig;
|
|
58054
59225
|
let manifest = void 0;
|
|
@@ -58069,27 +59240,24 @@ function staticHttpApiForLog(logInfo) {
|
|
|
58069
59240
|
return Promise.resolve([]);
|
|
58070
59241
|
},
|
|
58071
59242
|
get_log_root: async () => {
|
|
58072
|
-
if (log_dir) {
|
|
59243
|
+
if (log_dir && canonical_log_dir) {
|
|
58073
59244
|
const manifest = await getManifest();
|
|
58074
59245
|
if (manifest) {
|
|
58075
59246
|
const logs = Object.entries(manifest).map(([key, preview]) => {
|
|
58076
59247
|
return {
|
|
58077
|
-
name: joinURI(
|
|
59248
|
+
name: joinURI(canonical_log_dir, key),
|
|
58078
59249
|
task: preview.task,
|
|
58079
59250
|
task_id: preview.task_id
|
|
58080
59251
|
};
|
|
58081
59252
|
});
|
|
58082
59253
|
return Promise.resolve({
|
|
58083
59254
|
logs,
|
|
58084
|
-
log_dir,
|
|
59255
|
+
log_dir: canonical_log_dir,
|
|
58085
59256
|
abs_log_dir
|
|
58086
59257
|
});
|
|
58087
59258
|
}
|
|
58088
59259
|
}
|
|
58089
59260
|
},
|
|
58090
|
-
get_log_dir_handle: (log_dir) => {
|
|
58091
|
-
return joinURI(`${window.location.origin}${window.location.pathname.substring(0, window.location.pathname.lastIndexOf("/"))}`, log_dir || "default_log_dir");
|
|
58092
|
-
},
|
|
58093
59261
|
get_eval_set: async (dir) => {
|
|
58094
59262
|
const dirSegments = [];
|
|
58095
59263
|
if (log_dir) dirSegments.push(log_dir);
|
|
@@ -58128,7 +59296,7 @@ function staticHttpApiForLog(logInfo) {
|
|
|
58128
59296
|
if (manifest) {
|
|
58129
59297
|
const manifestAbs = {};
|
|
58130
59298
|
Object.entries(manifest).forEach(([key, preview]) => {
|
|
58131
|
-
manifestAbs[joinURI(
|
|
59299
|
+
manifestAbs[joinURI(canonical_log_dir || "", key)] = preview;
|
|
58132
59300
|
});
|
|
58133
59301
|
const header = manifestAbs[log_file];
|
|
58134
59302
|
if (header) return header;
|
|
@@ -58928,12 +60096,13 @@ var resolveLogRoot = async (bs) => {
|
|
|
58928
60096
|
*/
|
|
58929
60097
|
var loadResolvedAppConfig = async (bs) => {
|
|
58930
60098
|
const [versions, logRoot] = await Promise.all([bs.api.get_app_config(), resolveLogRoot(bs)]);
|
|
58931
|
-
|
|
60099
|
+
const logDir = logRoot.log_dir_uri ?? logRoot.log_dir;
|
|
60100
|
+
if (!logDir) throw new Error("Log dir not resolved");
|
|
58932
60101
|
return {
|
|
58933
60102
|
...bs,
|
|
58934
60103
|
inspect_version: versions.inspect_version,
|
|
58935
60104
|
scout_version: versions.scout_version ?? null,
|
|
58936
|
-
logDir
|
|
60105
|
+
logDir,
|
|
58937
60106
|
absLogDir: logRoot.abs_log_dir
|
|
58938
60107
|
};
|
|
58939
60108
|
};
|
|
@@ -62419,7 +63588,7 @@ var useVirtuosoState = (virtuosoRef, elementKey, delay = 1e3) => {
|
|
|
62419
63588
|
setListPosition(state);
|
|
62420
63589
|
}, [elementKey, setListPosition]);
|
|
62421
63590
|
useEffect(() => {
|
|
62422
|
-
debouncedFnRef.current = debounce$
|
|
63591
|
+
debouncedFnRef.current = debounce$3((isScrolling) => {
|
|
62423
63592
|
log$1.debug("List scroll", isScrolling);
|
|
62424
63593
|
const element = virtuosoRef.current;
|
|
62425
63594
|
if (!element) return;
|
|
@@ -65632,11 +66801,6 @@ var getNestedPropertyValue = (obj, path) => {
|
|
|
65632
66801
|
else return;
|
|
65633
66802
|
return current;
|
|
65634
66803
|
};
|
|
65635
|
-
var totalTokens = (sample) => {
|
|
65636
|
-
if (!sample.model_usage) return null;
|
|
65637
|
-
return Object.values(sample.model_usage).reduce((sum, u) => sum + (u.total_tokens ?? 0), 0);
|
|
65638
|
-
};
|
|
65639
|
-
var targetString = (target) => Array.isArray(target) ? target.join(", ") : target ?? "";
|
|
65640
66804
|
var sampleVariables = (sample, samplesDescriptor) => {
|
|
65641
66805
|
return {
|
|
65642
66806
|
epoch: sample.epoch,
|
|
@@ -65648,13 +66812,13 @@ var sampleVariables = (sample, samplesDescriptor) => {
|
|
|
65648
66812
|
id: sample.id,
|
|
65649
66813
|
uuid: sample.uuid ?? null,
|
|
65650
66814
|
input: inputString(sample.input).join(" "),
|
|
65651
|
-
target:
|
|
66815
|
+
target: arrayToString(sample.target ?? ""),
|
|
65652
66816
|
answer: samplesDescriptor?.selectedScorerDescriptor(sample)?.answer() ?? null,
|
|
65653
66817
|
error: sample.error ?? null,
|
|
65654
66818
|
limit: sample.limit ?? null,
|
|
65655
66819
|
retries: sample.retries ?? 0,
|
|
65656
66820
|
fallbacks: totalModelFallbacks(sample.model_fallbacks),
|
|
65657
|
-
tokens:
|
|
66821
|
+
tokens: totalSampleTokens(sample.model_usage) ?? null,
|
|
65658
66822
|
duration: sample.total_time ?? null,
|
|
65659
66823
|
metadata: sample.metadata
|
|
65660
66824
|
};
|
|
@@ -66332,11 +67496,11 @@ var baseUrl = (logPath, sampleId, sampleEpoch, prefix = "/logs") => {
|
|
|
66332
67496
|
};
|
|
66333
67497
|
var useSampleUrlBuilder = () => {
|
|
66334
67498
|
const location = useLocation();
|
|
66335
|
-
|
|
66336
|
-
|
|
67499
|
+
return useCallback((logPath, sampleId, sampleEpoch, sampleTabId) => {
|
|
67500
|
+
const prefix = location.pathname.startsWith("/tasks") ? "/tasks" : "/logs";
|
|
66337
67501
|
if (sampleId && sampleEpoch && location.pathname.startsWith("/samples/")) return samplesSampleUrl(logPath, sampleId, sampleEpoch, sampleTabId);
|
|
66338
67502
|
else return logSamplesUrl(logPath, sampleId, sampleEpoch, sampleTabId, prefix);
|
|
66339
|
-
};
|
|
67503
|
+
}, [location.pathname]);
|
|
66340
67504
|
};
|
|
66341
67505
|
var logSamplesUrl = (logPath, sampleId, sampleEpoch, sampleTabId, prefix = "/logs") => {
|
|
66342
67506
|
const decodedLogPath = decodeUrlParam(logPath) || logPath;
|
|
@@ -66361,6 +67525,27 @@ var sampleEventUrl = (builder, eventId, logPath, sampleId, sampleEpoch) => {
|
|
|
66361
67525
|
var sampleMessageUrl = (builder, messageId, logPath, sampleId, sampleEpoch, tab = kSampleMessagesTabId) => {
|
|
66362
67526
|
return `${builder(logPath, sampleId, sampleEpoch, tab)}?message=${messageId}`;
|
|
66363
67527
|
};
|
|
67528
|
+
/**
|
|
67529
|
+
* Returns a builder for *shareable* message links: the relative hash route
|
|
67530
|
+
* from `sampleMessageUrl` wrapped with the host page's origin/path via
|
|
67531
|
+
* `toFullUrl`. Copy-to-clipboard consumers (ChatMessage's copy button) must
|
|
67532
|
+
* use this rather than the bare route, which only works for in-app router
|
|
67533
|
+
* navigation.
|
|
67534
|
+
*/
|
|
67535
|
+
var useFullSampleMessageUrlBuilder = () => {
|
|
67536
|
+
const builder = useSampleUrlBuilder();
|
|
67537
|
+
const { logPath: urlLogPath, id: urlSampleId, epoch: urlEpoch } = useLogOrSampleRouteParams();
|
|
67538
|
+
const log_file = useStore((state) => state.logs.selectedLogFile);
|
|
67539
|
+
const log_dir = useLogDir();
|
|
67540
|
+
let targetLogPath = urlLogPath;
|
|
67541
|
+
if (!targetLogPath && log_file) targetLogPath = makeLogsPath(log_file, log_dir);
|
|
67542
|
+
return useCallback((messageId) => toFullUrlMaybe(targetLogPath ? sampleMessageUrl(builder, messageId, targetLogPath, urlSampleId, urlEpoch) : void 0), [
|
|
67543
|
+
builder,
|
|
67544
|
+
targetLogPath,
|
|
67545
|
+
urlSampleId,
|
|
67546
|
+
urlEpoch
|
|
67547
|
+
]);
|
|
67548
|
+
};
|
|
66364
67549
|
var tasksUrl = (log_file, log_dir) => {
|
|
66365
67550
|
const path = makeLogsPath(log_file, log_dir);
|
|
66366
67551
|
return encodePathParts(`/tasks/${decodeUrlParam(path) || path}`);
|
|
@@ -66406,6 +67591,14 @@ var logsUrlRaw = (log_segment, tabId, prefix = "/logs") => {
|
|
|
66406
67591
|
if (tabId) return encodePathParts(`${prefix}/${decodedLogSegment}/${tabId}`);
|
|
66407
67592
|
else return encodePathParts(`${prefix}/${decodedLogSegment}`);
|
|
66408
67593
|
};
|
|
67594
|
+
var toFullUrl = (path) => {
|
|
67595
|
+
return `${window.location.origin}${window.location.pathname}${window.location.search}#${path}`;
|
|
67596
|
+
};
|
|
67597
|
+
var toFullUrlMaybe = (route) => route ? toFullUrl(route) : void 0;
|
|
67598
|
+
var routeFromFullUrl = (url) => {
|
|
67599
|
+
const hashIndex = url.indexOf("#");
|
|
67600
|
+
return hashIndex >= 0 ? url.slice(hashIndex + 1) : url;
|
|
67601
|
+
};
|
|
66409
67602
|
var FlowButton_module_default = {
|
|
66410
67603
|
button: "_button_1bbut_1",
|
|
66411
67604
|
viewerOptions: "_viewerOptions_1bbut_7"
|
|
@@ -66746,7 +67939,7 @@ var ViewerOptionsPopover = ({ showing, positionEl, setShowing }) => {
|
|
|
66746
67939
|
}),
|
|
66747
67940
|
/* @__PURE__ */ jsx("div", {
|
|
66748
67941
|
className: clsx(),
|
|
66749
|
-
children:
|
|
67942
|
+
children: DB_VERSION
|
|
66750
67943
|
}),
|
|
66751
67944
|
/* @__PURE__ */ jsx("div", { className: clsx(ViewerOptionsPopover_module_default.spacer) }),
|
|
66752
67945
|
/* @__PURE__ */ jsx("div", {
|
|
@@ -67310,11 +68503,11 @@ var scorerMetricHeader = (scorerName, metricName) => `${scorerName} / ${metricNa
|
|
|
67310
68503
|
* the per-scorer `score_<scorer>/<metric>` field keys.
|
|
67311
68504
|
*/
|
|
67312
68505
|
var byMetricField = (metricName) => `metric_${metricName}`;
|
|
67313
|
-
var useLogListColumns = (mode = "logs",
|
|
68506
|
+
var useLogListColumns = (mode = "logs", scopeDir, viewMode = "by-metric") => {
|
|
67314
68507
|
const columnVisibility = useStore((state) => state.logs.listing.columnVisibility);
|
|
67315
68508
|
const setColumnVisibility = useStore((state) => state.logsActions.setLogsColumnVisibility);
|
|
67316
68509
|
const logDir = useLogDir();
|
|
67317
|
-
const scorerMap = useScoreSchema(logDir,
|
|
68510
|
+
const scorerMap = useScoreSchema(logDir, scopeDir).data ?? kNoScorerMap;
|
|
67318
68511
|
const allColumns = useMemo(() => {
|
|
67319
68512
|
const baseColumns = [
|
|
67320
68513
|
{
|
|
@@ -67829,7 +69022,10 @@ var useLogListColumns = (mode = "logs", scopePrefix, viewMode = "by-metric") =>
|
|
|
67829
69022
|
return allCols;
|
|
67830
69023
|
}, [scorerMap, mode]);
|
|
67831
69024
|
const listingRows = useLogListing(logDir).data ?? kNoListingRows$1;
|
|
67832
|
-
const hasSampleLimits = useMemo(() =>
|
|
69025
|
+
const hasSampleLimits = useMemo(() => {
|
|
69026
|
+
const prefix = scopeDir ? scopePrefix(scopeDir) : void 0;
|
|
69027
|
+
return listingRows.some((row) => (!prefix || row.name.startsWith(prefix)) && (row.header?.sampleLimits.length ?? 0) > 0);
|
|
69028
|
+
}, [listingRows, scopeDir]);
|
|
67833
69029
|
const defaultHiddenFields = useMemo(() => {
|
|
67834
69030
|
const hidden = /* @__PURE__ */ new Set();
|
|
67835
69031
|
if (mode === "tasks") {
|
|
@@ -67894,61 +69090,6 @@ var useLogListColumns = (mode = "logs", scopePrefix, viewMode = "by-metric") =>
|
|
|
67894
69090
|
};
|
|
67895
69091
|
};
|
|
67896
69092
|
//#endregion
|
|
67897
|
-
//#region src/components/FindBandUI.tsx
|
|
67898
|
-
var FindBandUI = ({ onClose, onNext, onPrevious, onKeyDown, onChange, onBeforeInput, value, matchCount, matchIndex, noResults = false, disableNav, inputRef: externalRef }) => {
|
|
67899
|
-
const internalRef = useRef(null);
|
|
67900
|
-
const inputRef = externalRef ?? internalRef;
|
|
67901
|
-
const inputProps = {
|
|
67902
|
-
type: "text",
|
|
67903
|
-
placeholder: "Find",
|
|
67904
|
-
onKeyDown,
|
|
67905
|
-
onBeforeInput,
|
|
67906
|
-
onChange
|
|
67907
|
-
};
|
|
67908
|
-
if (value !== void 0) inputProps.value = value;
|
|
67909
|
-
const hasCount = matchCount !== void 0 && matchIndex !== void 0;
|
|
67910
|
-
const showStatus = noResults || hasCount && matchCount > 0;
|
|
67911
|
-
const statusText = hasCount && matchCount > 0 ? `${matchIndex + 1} of ${matchCount}` : "No results";
|
|
67912
|
-
return /* @__PURE__ */ jsxs("div", {
|
|
67913
|
-
"data-unsearchable": "true",
|
|
67914
|
-
className: clsx("findBand"),
|
|
67915
|
-
children: [
|
|
67916
|
-
/* @__PURE__ */ jsx("input", {
|
|
67917
|
-
ref: inputRef,
|
|
67918
|
-
...inputProps
|
|
67919
|
-
}),
|
|
67920
|
-
/* @__PURE__ */ jsx("span", {
|
|
67921
|
-
className: clsx("findBand-match-count", noResults && "findBand-no-results"),
|
|
67922
|
-
style: { visibility: showStatus ? "visible" : "hidden" },
|
|
67923
|
-
children: statusText
|
|
67924
|
-
}),
|
|
67925
|
-
/* @__PURE__ */ jsx("button", {
|
|
67926
|
-
type: "button",
|
|
67927
|
-
title: "Previous match",
|
|
67928
|
-
className: "btn prev",
|
|
67929
|
-
onClick: onPrevious,
|
|
67930
|
-
disabled: disableNav,
|
|
67931
|
-
children: /* @__PURE__ */ jsx("i", { className: ApplicationIcons.arrows.up })
|
|
67932
|
-
}),
|
|
67933
|
-
/* @__PURE__ */ jsx("button", {
|
|
67934
|
-
type: "button",
|
|
67935
|
-
title: "Next match",
|
|
67936
|
-
className: "btn next",
|
|
67937
|
-
onClick: onNext,
|
|
67938
|
-
disabled: disableNav,
|
|
67939
|
-
children: /* @__PURE__ */ jsx("i", { className: ApplicationIcons.arrows.down })
|
|
67940
|
-
}),
|
|
67941
|
-
/* @__PURE__ */ jsx("button", {
|
|
67942
|
-
type: "button",
|
|
67943
|
-
title: "Close",
|
|
67944
|
-
className: "btn close",
|
|
67945
|
-
onClick: onClose,
|
|
67946
|
-
children: /* @__PURE__ */ jsx("i", { className: ApplicationIcons.close })
|
|
67947
|
-
})
|
|
67948
|
-
]
|
|
67949
|
-
});
|
|
67950
|
-
};
|
|
67951
|
-
//#endregion
|
|
67952
69093
|
//#region ../../node_modules/.pnpm/@tanstack+table-core@8.21.3/node_modules/@tanstack/table-core/build/lib/index.mjs
|
|
67953
69094
|
/**
|
|
67954
69095
|
* table-core
|
|
@@ -73194,9 +74335,9 @@ function findMatches(index, term) {
|
|
|
73194
74335
|
var LogListGrid = ({ rows, totalRowCount, sorting, columnFilters, currentPath, scopeKey, mode = "logs", busy }) => {
|
|
73195
74336
|
const { gridStateByScope, patchGridState } = useLogsListing();
|
|
73196
74337
|
const navigate = useNavigate();
|
|
73197
|
-
const
|
|
74338
|
+
const scopeDir = mode === "logs" ? currentPath : void 0;
|
|
73198
74339
|
const [scoresViewMode] = useProperty("log-list-scores-view", "mode", { defaultValue: "by-metric" });
|
|
73199
|
-
const { columns, visibility } = useLogListColumns(mode,
|
|
74340
|
+
const { columns, visibility } = useLogListColumns(mode, scopeDir, scoresViewMode);
|
|
73200
74341
|
const handleRowActivate = useCallback((row) => {
|
|
73201
74342
|
if (row.url) navigate(row.url);
|
|
73202
74343
|
}, [navigate]);
|
|
@@ -73282,19 +74423,13 @@ var LogListGrid = ({ rows, totalRowCount, sorting, columnFilters, currentPath, s
|
|
|
73282
74423
|
activeMatchIndex,
|
|
73283
74424
|
closeFind
|
|
73284
74425
|
]);
|
|
73285
|
-
|
|
73286
|
-
|
|
73287
|
-
|
|
73288
|
-
|
|
73289
|
-
|
|
73290
|
-
|
|
73291
|
-
|
|
73292
|
-
}
|
|
73293
|
-
if (e.key === "Escape" && showFind) closeFind();
|
|
73294
|
-
};
|
|
73295
|
-
document.addEventListener("keydown", handleFindKeyDown, true);
|
|
73296
|
-
return () => document.removeEventListener("keydown", handleFindKeyDown, true);
|
|
73297
|
-
}, [closeFind, showFind]);
|
|
74426
|
+
useFindBandShortcut(useCallback(() => {
|
|
74427
|
+
setShowFind(true);
|
|
74428
|
+
setTimeout(() => findInputRef.current?.focus(), 100);
|
|
74429
|
+
}, []), {
|
|
74430
|
+
onClose: closeFind,
|
|
74431
|
+
isOpen: showFind
|
|
74432
|
+
});
|
|
73298
74433
|
return /* @__PURE__ */ jsxs("div", {
|
|
73299
74434
|
className: clsx(gridCells_module_default.gridWrapper),
|
|
73300
74435
|
children: [showFind && /* @__PURE__ */ jsx(FindBandUI, {
|
|
@@ -73587,29 +74722,8 @@ var rowForItem = (item) => item.type === "file" ? item.log : void 0;
|
|
|
73587
74722
|
var buildLogListRow = (item) => {
|
|
73588
74723
|
const log = rowForItem(item);
|
|
73589
74724
|
const details = log?.header;
|
|
73590
|
-
|
|
73591
|
-
if (details?.stats?.model_usage) {
|
|
73592
|
-
totalTokens = 0;
|
|
73593
|
-
for (const usage of Object.values(details.stats.model_usage)) totalTokens += usage.total_tokens;
|
|
73594
|
-
}
|
|
73595
|
-
let duration;
|
|
73596
|
-
if (details?.stats?.started_at && details?.stats?.completed_at) {
|
|
73597
|
-
const start = new Date(details.stats.started_at).getTime();
|
|
73598
|
-
const end = new Date(details.stats.completed_at).getTime();
|
|
73599
|
-
if (start && end && end > start) duration = (end - start) / 1e3;
|
|
73600
|
-
}
|
|
74725
|
+
const derived = log?.derived;
|
|
73601
74726
|
const taskArgsSource = details?.eval?.task_args_passed ?? details?.eval?.task_args;
|
|
73602
|
-
let taskArgs;
|
|
73603
|
-
if (taskArgsSource) {
|
|
73604
|
-
const entries = Object.entries(taskArgsSource);
|
|
73605
|
-
if (entries.length > 0) taskArgs = entries.map(([k, v]) => `${k}=${JSON.stringify(v)}`).join(", ");
|
|
73606
|
-
}
|
|
73607
|
-
let percentCompleted;
|
|
73608
|
-
const total = details?.results?.total_samples;
|
|
73609
|
-
const completed = details?.results?.completed_samples;
|
|
73610
|
-
if (total && total > 0 && completed !== void 0) percentCompleted = completed / total * 100;
|
|
73611
|
-
const sampleErrors = details?.sampleErrorCount;
|
|
73612
|
-
const sampleLimits = details !== void 0 && details.sampleLimits.length > 0 ? details.sampleLimits.join(", ") : void 0;
|
|
73613
74727
|
const row = {
|
|
73614
74728
|
id: item.id,
|
|
73615
74729
|
name: item.name,
|
|
@@ -73628,20 +74742,18 @@ var buildLogListRow = (item) => {
|
|
|
73628
74742
|
totalSamples: details?.results?.total_samples,
|
|
73629
74743
|
completedSamples: details?.results?.completed_samples,
|
|
73630
74744
|
sandbox: details?.eval?.sandbox?.type,
|
|
73631
|
-
totalTokens,
|
|
73632
|
-
duration,
|
|
74745
|
+
totalTokens: derived?.total_tokens,
|
|
74746
|
+
duration: derived?.duration,
|
|
73633
74747
|
taskFile: details?.eval?.task_file ?? void 0,
|
|
73634
|
-
taskArgs,
|
|
74748
|
+
taskArgs: derived?.task_args,
|
|
73635
74749
|
taskArgsRaw: taskArgsSource ?? void 0,
|
|
73636
74750
|
tags: details?.tags,
|
|
73637
|
-
percentCompleted,
|
|
73638
|
-
sampleErrors,
|
|
73639
|
-
sampleLimits,
|
|
74751
|
+
percentCompleted: derived?.percent_completed,
|
|
74752
|
+
sampleErrors: details?.sampleErrorCount,
|
|
74753
|
+
sampleLimits: derived?.sample_limits,
|
|
73640
74754
|
errorMessage: details?.error?.message
|
|
73641
74755
|
};
|
|
73642
|
-
if (
|
|
73643
|
-
for (const evalScore of details.results.scores) if (evalScore.metrics) for (const [metricName, metric] of Object.entries(evalScore.metrics)) row[`score_${evalScore.name}/${metricName}`] = metric.value;
|
|
73644
|
-
}
|
|
74756
|
+
if (derived?.scores) for (const [scorerName, metrics] of Object.entries(derived.scores)) for (const [metricName, value] of Object.entries(metrics)) row[`score_${scorerName}/${metricName}`] = value;
|
|
73645
74757
|
return row;
|
|
73646
74758
|
};
|
|
73647
74759
|
/**
|
|
@@ -73850,9 +74962,9 @@ var LogsPanel = ({ maybeShowSingleLog, mode = "logs" }) => {
|
|
|
73850
74962
|
logDir,
|
|
73851
74963
|
showRetriedLogs
|
|
73852
74964
|
]);
|
|
73853
|
-
const
|
|
74965
|
+
const scopeDir = mode === "logs" ? currentDir : void 0;
|
|
73854
74966
|
const [scoresViewMode, setScoresViewMode] = useProperty("log-list-scores-view", "mode", { defaultValue: "by-metric" });
|
|
73855
|
-
const { pickerColumns, visibility, setColumnVisibility, getValue, getComparator, getFilterType } = useLogListColumns(mode,
|
|
74967
|
+
const { pickerColumns, visibility, setColumnVisibility, getValue, getComparator, getFilterType } = useLogListColumns(mode, scopeDir, scoresViewMode);
|
|
73856
74968
|
const listData = useLogListData({
|
|
73857
74969
|
items: logItems,
|
|
73858
74970
|
scopeKey,
|
|
@@ -74212,418 +75324,6 @@ var useLogSampleNavigationActions = () => {
|
|
|
74212
75324
|
hasNext
|
|
74213
75325
|
};
|
|
74214
75326
|
};
|
|
74215
|
-
//#endregion
|
|
74216
|
-
//#region src/utils/dom.ts
|
|
74217
|
-
/**
|
|
74218
|
-
* Finds the nearest scrollable ancestor of an element.
|
|
74219
|
-
* Useful for programmatic scrolling when you need to find the scroll container.
|
|
74220
|
-
*
|
|
74221
|
-
* @param element - The element to start searching from
|
|
74222
|
-
* @param options.minScrollBuffer - Minimum difference between scrollHeight and clientHeight
|
|
74223
|
-
* to consider an element scrollable (default: 100)
|
|
74224
|
-
* @returns The scrollable parent element, or null if none found
|
|
74225
|
-
*/
|
|
74226
|
-
function findScrollableParent(element, options) {
|
|
74227
|
-
const minBuffer = options?.minScrollBuffer ?? 100;
|
|
74228
|
-
let current = element instanceof HTMLElement ? element : element?.parentElement;
|
|
74229
|
-
while (current && current !== document.body) {
|
|
74230
|
-
const style = getComputedStyle(current);
|
|
74231
|
-
if ((style.overflowY === "auto" || style.overflowY === "scroll") && current.scrollHeight > current.clientHeight + minBuffer) return current;
|
|
74232
|
-
current = current.parentElement;
|
|
74233
|
-
}
|
|
74234
|
-
return null;
|
|
74235
|
-
}
|
|
74236
|
-
/**
|
|
74237
|
-
* Scrolls a Range (text selection) to the center of its scrollable container.
|
|
74238
|
-
* Unlike element.scrollIntoView({ block: "center" }), this works correctly
|
|
74239
|
-
* for selections within large elements (e.g., code blocks) by scrolling to
|
|
74240
|
-
* the actual selection position rather than the element's top.
|
|
74241
|
-
*
|
|
74242
|
-
* @param range - The Range to scroll into view
|
|
74243
|
-
* @param options.behavior - Scroll behavior ('auto' or 'smooth'), default: 'auto'
|
|
74244
|
-
* @param options.fallbackToScrollIntoView - Whether to fall back to scrollIntoView
|
|
74245
|
-
* if no scrollable parent is found (default: true)
|
|
74246
|
-
*/
|
|
74247
|
-
function scrollRangeToCenter(range, options) {
|
|
74248
|
-
const { behavior = "auto", fallbackToScrollIntoView = true } = options ?? {};
|
|
74249
|
-
const rects = range.getClientRects();
|
|
74250
|
-
if (rects.length === 0) return;
|
|
74251
|
-
const selectionRect = rects[0];
|
|
74252
|
-
if (selectionRect === void 0) return;
|
|
74253
|
-
const scrollableParent = findScrollableParent(range.startContainer.parentElement);
|
|
74254
|
-
if (scrollableParent) {
|
|
74255
|
-
const parentRect = scrollableParent.getBoundingClientRect();
|
|
74256
|
-
const targetScrollTop = selectionRect.top - parentRect.top + scrollableParent.scrollTop - scrollableParent.clientHeight / 2;
|
|
74257
|
-
scrollableParent.scrollTo({
|
|
74258
|
-
top: Math.max(0, targetScrollTop),
|
|
74259
|
-
behavior
|
|
74260
|
-
});
|
|
74261
|
-
} else if (fallbackToScrollIntoView) range.startContainer.parentElement?.scrollIntoView({
|
|
74262
|
-
behavior,
|
|
74263
|
-
block: "center"
|
|
74264
|
-
});
|
|
74265
|
-
}
|
|
74266
|
-
//#endregion
|
|
74267
|
-
//#region src/components/FindBand.tsx
|
|
74268
|
-
var findConfig = {
|
|
74269
|
-
caseSensitive: false,
|
|
74270
|
-
wrapAround: false,
|
|
74271
|
-
wholeWord: false,
|
|
74272
|
-
searchInFrames: false,
|
|
74273
|
-
showDialog: false
|
|
74274
|
-
};
|
|
74275
|
-
var FindBand = () => {
|
|
74276
|
-
const searchBoxRef = useRef(null);
|
|
74277
|
-
const storeHideFind = useStore((state) => state.appActions.hideFind);
|
|
74278
|
-
const { extendedFindTerm, countAllMatches } = useExtendedFind();
|
|
74279
|
-
const setFindTarget = useFindTargetSetter();
|
|
74280
|
-
const lastFoundItem = useRef(null);
|
|
74281
|
-
const currentSearchTerm = useRef("");
|
|
74282
|
-
const needsCursorRestoreRef = useRef(false);
|
|
74283
|
-
const scrollTimeoutRef = useRef(null);
|
|
74284
|
-
const focusTimeoutRef = useRef(null);
|
|
74285
|
-
const searchIdRef = useRef(0);
|
|
74286
|
-
const cachedCount = useRef({
|
|
74287
|
-
term: "",
|
|
74288
|
-
count: 0
|
|
74289
|
-
});
|
|
74290
|
-
const [matchCount, setMatchCount] = useState(null);
|
|
74291
|
-
const [currentMatchIndex, setCurrentMatchIndex] = useState(0);
|
|
74292
|
-
const [noResults, setNoResults] = useState(false);
|
|
74293
|
-
const handleSearch = useCallback(async (back = false) => {
|
|
74294
|
-
const thisSearchId = ++searchIdRef.current;
|
|
74295
|
-
const searchTerm = searchBoxRef.current?.value ?? "";
|
|
74296
|
-
if (!searchTerm) {
|
|
74297
|
-
setMatchCount(null);
|
|
74298
|
-
setCurrentMatchIndex(0);
|
|
74299
|
-
setNoResults(false);
|
|
74300
|
-
setFindTarget(null);
|
|
74301
|
-
return;
|
|
74302
|
-
}
|
|
74303
|
-
const termChanged = currentSearchTerm.current !== searchTerm;
|
|
74304
|
-
if (termChanged) {
|
|
74305
|
-
lastFoundItem.current = null;
|
|
74306
|
-
currentSearchTerm.current = searchTerm;
|
|
74307
|
-
setCurrentMatchIndex(0);
|
|
74308
|
-
}
|
|
74309
|
-
let total;
|
|
74310
|
-
if (cachedCount.current.term === searchTerm) total = cachedCount.current.count;
|
|
74311
|
-
else {
|
|
74312
|
-
total = countAllMatches(searchTerm);
|
|
74313
|
-
cachedCount.current = {
|
|
74314
|
-
term: searchTerm,
|
|
74315
|
-
count: total
|
|
74316
|
-
};
|
|
74317
|
-
}
|
|
74318
|
-
setMatchCount(total > 0 ? total : null);
|
|
74319
|
-
const focusedElement = document.activeElement;
|
|
74320
|
-
const selection = window.getSelection();
|
|
74321
|
-
let savedRange = null;
|
|
74322
|
-
if (selection && selection.rangeCount > 0) savedRange = selection.getRangeAt(0).cloneRange();
|
|
74323
|
-
const savedScrollParent = savedRange ? findScrollableParent(savedRange.startContainer.parentElement) : null;
|
|
74324
|
-
const savedScrollTop = savedScrollParent?.scrollTop ?? 0;
|
|
74325
|
-
const result = await findExtendedInDOM(searchTerm, back, lastFoundItem.current, extendedFindTerm);
|
|
74326
|
-
if (searchIdRef.current !== thisSearchId) return;
|
|
74327
|
-
setNoResults(!result);
|
|
74328
|
-
if (!result && savedRange) {
|
|
74329
|
-
const sel = window.getSelection();
|
|
74330
|
-
if (sel) {
|
|
74331
|
-
sel.removeAllRanges();
|
|
74332
|
-
sel.addRange(savedRange);
|
|
74333
|
-
}
|
|
74334
|
-
if (savedScrollParent) savedScrollParent.scrollTop = savedScrollTop;
|
|
74335
|
-
}
|
|
74336
|
-
if (result) {
|
|
74337
|
-
const selection = window.getSelection();
|
|
74338
|
-
if (selection && selection.rangeCount > 0) {
|
|
74339
|
-
const range = selection.getRangeAt(0);
|
|
74340
|
-
const parentElement = range.startContainer.parentElement || range.commonAncestorContainer;
|
|
74341
|
-
const isNewMatch = !isLastFoundItem(range, lastFoundItem.current);
|
|
74342
|
-
lastFoundItem.current = {
|
|
74343
|
-
text: range.toString(),
|
|
74344
|
-
offset: range.startOffset,
|
|
74345
|
-
parentElement
|
|
74346
|
-
};
|
|
74347
|
-
if (termChanged) setFindTarget({
|
|
74348
|
-
term: searchTerm,
|
|
74349
|
-
eventId: ""
|
|
74350
|
-
});
|
|
74351
|
-
if (isNewMatch) setCurrentMatchIndex((prev) => {
|
|
74352
|
-
if (back) return prev <= 1 ? total : prev - 1;
|
|
74353
|
-
else return prev >= total ? 1 : prev + 1;
|
|
74354
|
-
});
|
|
74355
|
-
if (scrollTimeoutRef.current !== null) window.clearTimeout(scrollTimeoutRef.current);
|
|
74356
|
-
scrollTimeoutRef.current = window.setTimeout(() => {
|
|
74357
|
-
scrollRangeToCenter(range);
|
|
74358
|
-
}, 100);
|
|
74359
|
-
}
|
|
74360
|
-
}
|
|
74361
|
-
focusedElement?.focus();
|
|
74362
|
-
}, [
|
|
74363
|
-
setFindTarget,
|
|
74364
|
-
extendedFindTerm,
|
|
74365
|
-
countAllMatches
|
|
74366
|
-
]);
|
|
74367
|
-
useEffect(() => {
|
|
74368
|
-
focusTimeoutRef.current = window.setTimeout(() => {
|
|
74369
|
-
searchBoxRef.current?.focus();
|
|
74370
|
-
searchBoxRef.current?.select();
|
|
74371
|
-
}, 10);
|
|
74372
|
-
const focusTimeout = focusTimeoutRef.current;
|
|
74373
|
-
return () => {
|
|
74374
|
-
if (scrollTimeoutRef.current !== null) window.clearTimeout(scrollTimeoutRef.current);
|
|
74375
|
-
if (focusTimeout !== null) window.clearTimeout(focusTimeout);
|
|
74376
|
-
setFindTarget(null);
|
|
74377
|
-
};
|
|
74378
|
-
}, [setFindTarget]);
|
|
74379
|
-
const handleKeyDown = useCallback((e) => {
|
|
74380
|
-
if (e.key === "Escape") storeHideFind();
|
|
74381
|
-
else if (e.key === "Enter") handleSearch(e.shiftKey);
|
|
74382
|
-
else if ((e.ctrlKey || e.metaKey) && e.key.toLowerCase() === "g") {
|
|
74383
|
-
e.preventDefault();
|
|
74384
|
-
handleSearch(e.shiftKey);
|
|
74385
|
-
} else if ((e.ctrlKey || e.metaKey) && e.key.toLowerCase() === "f") {
|
|
74386
|
-
searchBoxRef.current?.focus();
|
|
74387
|
-
searchBoxRef.current?.select();
|
|
74388
|
-
}
|
|
74389
|
-
}, [storeHideFind, handleSearch]);
|
|
74390
|
-
const findPrevious = useCallback(() => {
|
|
74391
|
-
handleSearch(true);
|
|
74392
|
-
}, [handleSearch]);
|
|
74393
|
-
const findNext = useCallback(() => {
|
|
74394
|
-
handleSearch(false);
|
|
74395
|
-
}, [handleSearch]);
|
|
74396
|
-
const restoreCursor = useCallback(() => {
|
|
74397
|
-
if (!needsCursorRestoreRef.current) return;
|
|
74398
|
-
needsCursorRestoreRef.current = false;
|
|
74399
|
-
const input = searchBoxRef.current;
|
|
74400
|
-
if (input) {
|
|
74401
|
-
const len = input.value.length;
|
|
74402
|
-
input.setSelectionRange(len, len);
|
|
74403
|
-
}
|
|
74404
|
-
}, []);
|
|
74405
|
-
const runDebouncedSearch = useCallback(async () => {
|
|
74406
|
-
if (!searchBoxRef.current) return;
|
|
74407
|
-
await handleSearch(false);
|
|
74408
|
-
needsCursorRestoreRef.current = true;
|
|
74409
|
-
}, [handleSearch]);
|
|
74410
|
-
const latestRunSearchRef = useRef(runDebouncedSearch);
|
|
74411
|
-
useEffect(() => {
|
|
74412
|
-
latestRunSearchRef.current = runDebouncedSearch;
|
|
74413
|
-
return () => {
|
|
74414
|
-
latestRunSearchRef.current = null;
|
|
74415
|
-
};
|
|
74416
|
-
}, [runDebouncedSearch]);
|
|
74417
|
-
const debouncedSearchRef = useRef(null);
|
|
74418
|
-
const handleInputChange = useCallback(() => {
|
|
74419
|
-
debouncedSearchRef.current ??= debounce$2(() => void latestRunSearchRef.current?.(), 100);
|
|
74420
|
-
debouncedSearchRef.current();
|
|
74421
|
-
}, []);
|
|
74422
|
-
const handleBeforeInput = useCallback(() => {
|
|
74423
|
-
const input = searchBoxRef.current;
|
|
74424
|
-
if (input) {
|
|
74425
|
-
if (!(input.selectionStart !== input.selectionEnd)) restoreCursor();
|
|
74426
|
-
}
|
|
74427
|
-
}, [restoreCursor]);
|
|
74428
|
-
useEffect(() => {
|
|
74429
|
-
const handleGlobalKeyDown = (e) => {
|
|
74430
|
-
if (e.key === "F3") {
|
|
74431
|
-
e.preventDefault();
|
|
74432
|
-
handleSearch(e.shiftKey);
|
|
74433
|
-
return;
|
|
74434
|
-
}
|
|
74435
|
-
if ((e.ctrlKey || e.metaKey) && e.key === "f") {
|
|
74436
|
-
e.preventDefault();
|
|
74437
|
-
e.stopPropagation();
|
|
74438
|
-
searchBoxRef.current?.focus();
|
|
74439
|
-
searchBoxRef.current?.select();
|
|
74440
|
-
return;
|
|
74441
|
-
}
|
|
74442
|
-
if ((e.ctrlKey || e.metaKey) && e.key === "g") {
|
|
74443
|
-
e.preventDefault();
|
|
74444
|
-
e.stopPropagation();
|
|
74445
|
-
handleSearch(e.shiftKey);
|
|
74446
|
-
return;
|
|
74447
|
-
}
|
|
74448
|
-
if (e.ctrlKey || e.metaKey || e.altKey) return;
|
|
74449
|
-
if (e.key.length !== 1 && e.key !== "Backspace" && e.key !== "Delete") return;
|
|
74450
|
-
const input = searchBoxRef.current;
|
|
74451
|
-
if (!input) return;
|
|
74452
|
-
if (document.activeElement !== input) {
|
|
74453
|
-
let active = document.activeElement;
|
|
74454
|
-
while (active?.shadowRoot?.activeElement) active = active.shadowRoot.activeElement;
|
|
74455
|
-
if (active instanceof HTMLInputElement || active instanceof HTMLTextAreaElement || active instanceof HTMLElement && active.isContentEditable) return;
|
|
74456
|
-
}
|
|
74457
|
-
if (!(input.selectionStart !== input.selectionEnd)) restoreCursor();
|
|
74458
|
-
if (document.activeElement !== input) input.focus();
|
|
74459
|
-
};
|
|
74460
|
-
document.addEventListener("keydown", handleGlobalKeyDown, true);
|
|
74461
|
-
return () => {
|
|
74462
|
-
document.removeEventListener("keydown", handleGlobalKeyDown, true);
|
|
74463
|
-
};
|
|
74464
|
-
}, [handleSearch, restoreCursor]);
|
|
74465
|
-
return /* @__PURE__ */ jsx(FindBandUI, {
|
|
74466
|
-
inputRef: searchBoxRef,
|
|
74467
|
-
onClose: storeHideFind,
|
|
74468
|
-
onNext: findNext,
|
|
74469
|
-
onPrevious: findPrevious,
|
|
74470
|
-
onKeyDown: handleKeyDown,
|
|
74471
|
-
onBeforeInput: handleBeforeInput,
|
|
74472
|
-
onChange: handleInputChange,
|
|
74473
|
-
noResults,
|
|
74474
|
-
matchCount: matchCount ?? void 0,
|
|
74475
|
-
matchIndex: matchCount !== null && matchCount > 0 ? currentMatchIndex - 1 : void 0
|
|
74476
|
-
});
|
|
74477
|
-
};
|
|
74478
|
-
function windowFind(searchTerm, back) {
|
|
74479
|
-
return window.find(searchTerm, findConfig.caseSensitive, back, findConfig.wrapAround, findConfig.wholeWord, findConfig.searchInFrames, findConfig.showDialog);
|
|
74480
|
-
}
|
|
74481
|
-
function positionSelectionForWrap(back) {
|
|
74482
|
-
if (!back) return;
|
|
74483
|
-
const sel = window.getSelection();
|
|
74484
|
-
if (sel) {
|
|
74485
|
-
const range = document.createRange();
|
|
74486
|
-
range.selectNodeContents(document.body);
|
|
74487
|
-
range.collapse(false);
|
|
74488
|
-
sel.removeAllRanges();
|
|
74489
|
-
sel.addRange(range);
|
|
74490
|
-
}
|
|
74491
|
-
}
|
|
74492
|
-
async function findExtendedInDOM(searchTerm, back, lastFoundItem, extendedFindTerm) {
|
|
74493
|
-
let result = false;
|
|
74494
|
-
let hasTriedExtendedSearch = false;
|
|
74495
|
-
let extendedSearchSucceeded = false;
|
|
74496
|
-
const maxAttempts = 25;
|
|
74497
|
-
for (let attempts = 0; attempts < maxAttempts; attempts++) {
|
|
74498
|
-
result = windowFind(searchTerm, back);
|
|
74499
|
-
if (result) {
|
|
74500
|
-
const selection = window.getSelection();
|
|
74501
|
-
if (selection && selection.rangeCount > 0) {
|
|
74502
|
-
const range = selection.getRangeAt(0);
|
|
74503
|
-
const isUnsearchable = inUnsearchableElement(range);
|
|
74504
|
-
const isSameAsLast = isLastFoundItem(range, lastFoundItem);
|
|
74505
|
-
if (!isUnsearchable && !isSameAsLast) break;
|
|
74506
|
-
if (isSameAsLast) {
|
|
74507
|
-
if (!hasTriedExtendedSearch) {
|
|
74508
|
-
hasTriedExtendedSearch = true;
|
|
74509
|
-
window.getSelection()?.removeAllRanges();
|
|
74510
|
-
if (await extendedFindTerm(searchTerm, back ? "backward" : "forward")) {
|
|
74511
|
-
extendedSearchSucceeded = true;
|
|
74512
|
-
await waitForTextInDOM(searchTerm);
|
|
74513
|
-
continue;
|
|
74514
|
-
}
|
|
74515
|
-
}
|
|
74516
|
-
if (extendedSearchSucceeded) {
|
|
74517
|
-
const sel = window.getSelection();
|
|
74518
|
-
if (sel?.rangeCount) sel.getRangeAt(0).collapse(!back);
|
|
74519
|
-
} else {
|
|
74520
|
-
window.getSelection()?.removeAllRanges();
|
|
74521
|
-
positionSelectionForWrap(back);
|
|
74522
|
-
}
|
|
74523
|
-
result = windowFind(searchTerm, back);
|
|
74524
|
-
if (result) {
|
|
74525
|
-
const sel = window.getSelection();
|
|
74526
|
-
if (sel && sel.rangeCount > 0) {
|
|
74527
|
-
if (inUnsearchableElement(sel.getRangeAt(0))) continue;
|
|
74528
|
-
}
|
|
74529
|
-
}
|
|
74530
|
-
break;
|
|
74531
|
-
}
|
|
74532
|
-
}
|
|
74533
|
-
} else if (!hasTriedExtendedSearch) {
|
|
74534
|
-
hasTriedExtendedSearch = true;
|
|
74535
|
-
window.getSelection()?.removeAllRanges();
|
|
74536
|
-
if (await extendedFindTerm(searchTerm, back ? "backward" : "forward")) {
|
|
74537
|
-
extendedSearchSucceeded = true;
|
|
74538
|
-
await waitForTextInDOM(searchTerm);
|
|
74539
|
-
continue;
|
|
74540
|
-
}
|
|
74541
|
-
positionSelectionForWrap(back);
|
|
74542
|
-
result = windowFind(searchTerm, back);
|
|
74543
|
-
if (result) {
|
|
74544
|
-
const sel = window.getSelection();
|
|
74545
|
-
if (sel && sel.rangeCount > 0) {
|
|
74546
|
-
if (inUnsearchableElement(sel.getRangeAt(0))) continue;
|
|
74547
|
-
}
|
|
74548
|
-
}
|
|
74549
|
-
break;
|
|
74550
|
-
} else break;
|
|
74551
|
-
}
|
|
74552
|
-
if (result) {
|
|
74553
|
-
const sel = window.getSelection();
|
|
74554
|
-
if (sel?.rangeCount && inUnsearchableElement(sel.getRangeAt(0))) {
|
|
74555
|
-
sel.removeAllRanges();
|
|
74556
|
-
result = false;
|
|
74557
|
-
}
|
|
74558
|
-
}
|
|
74559
|
-
return result;
|
|
74560
|
-
}
|
|
74561
|
-
function isLastFoundItem(range, lastFoundItem) {
|
|
74562
|
-
if (!lastFoundItem) return false;
|
|
74563
|
-
const currentText = range.toString();
|
|
74564
|
-
const currentOffset = range.startOffset;
|
|
74565
|
-
const currentParentElement = range.startContainer.parentElement || range.commonAncestorContainer;
|
|
74566
|
-
return currentText === lastFoundItem.text && currentOffset === lastFoundItem.offset && currentParentElement === lastFoundItem.parentElement;
|
|
74567
|
-
}
|
|
74568
|
-
function inUnsearchableElement(range) {
|
|
74569
|
-
let element = selectionParentElement(range);
|
|
74570
|
-
let isUnsearchable = false;
|
|
74571
|
-
while (element) {
|
|
74572
|
-
if (element.hasAttribute("data-unsearchable") || getComputedStyle(element).userSelect === "none") {
|
|
74573
|
-
isUnsearchable = true;
|
|
74574
|
-
break;
|
|
74575
|
-
}
|
|
74576
|
-
element = element.parentElement;
|
|
74577
|
-
}
|
|
74578
|
-
return isUnsearchable;
|
|
74579
|
-
}
|
|
74580
|
-
function selectionParentElement(range) {
|
|
74581
|
-
let element = null;
|
|
74582
|
-
if (range.startContainer.nodeType === Node.ELEMENT_NODE) element = range.startContainer;
|
|
74583
|
-
else element = range.startContainer.parentElement;
|
|
74584
|
-
if (!element && range.commonAncestorContainer.nodeType === Node.ELEMENT_NODE) element = range.commonAncestorContainer;
|
|
74585
|
-
else if (!element && range.commonAncestorContainer.parentElement) element = range.commonAncestorContainer.parentElement;
|
|
74586
|
-
return element;
|
|
74587
|
-
}
|
|
74588
|
-
/**
|
|
74589
|
-
* Polls until the search term appears in a searchable (non-unsearchable) DOM
|
|
74590
|
-
* text node. After Virtuoso scrolls a virtual list item into view, the
|
|
74591
|
-
* onContentReady callback may fire before the content is actually rendered,
|
|
74592
|
-
* especially for large scroll distances. This ensures we wait for the text
|
|
74593
|
-
* to be present before calling window.find().
|
|
74594
|
-
*/
|
|
74595
|
-
function waitForTextInDOM(searchTerm, timeoutMs = 2e3) {
|
|
74596
|
-
const lowerTerm = searchTerm.toLowerCase();
|
|
74597
|
-
const isTextInSearchableDOM = () => {
|
|
74598
|
-
const walker = document.createTreeWalker(document.body, NodeFilter.SHOW_TEXT, { acceptNode: (node) => {
|
|
74599
|
-
let el = node.parentElement;
|
|
74600
|
-
while (el) {
|
|
74601
|
-
if (el.hasAttribute("data-unsearchable")) return NodeFilter.FILTER_REJECT;
|
|
74602
|
-
el = el.parentElement;
|
|
74603
|
-
}
|
|
74604
|
-
return NodeFilter.FILTER_ACCEPT;
|
|
74605
|
-
} });
|
|
74606
|
-
while (walker.nextNode()) if (walker.currentNode.textContent?.toLowerCase().includes(lowerTerm)) return true;
|
|
74607
|
-
return false;
|
|
74608
|
-
};
|
|
74609
|
-
return new Promise((resolve) => {
|
|
74610
|
-
const interval = 50;
|
|
74611
|
-
let elapsed = 0;
|
|
74612
|
-
const check = () => {
|
|
74613
|
-
if (isTextInSearchableDOM()) {
|
|
74614
|
-
resolve(true);
|
|
74615
|
-
return;
|
|
74616
|
-
}
|
|
74617
|
-
elapsed += interval;
|
|
74618
|
-
if (elapsed >= timeoutMs) {
|
|
74619
|
-
resolve(false);
|
|
74620
|
-
return;
|
|
74621
|
-
}
|
|
74622
|
-
setTimeout(check, interval);
|
|
74623
|
-
};
|
|
74624
|
-
check();
|
|
74625
|
-
});
|
|
74626
|
-
}
|
|
74627
75327
|
var InlineSampleDisplay_module_default = {
|
|
74628
75328
|
container: "_container_ly812_1",
|
|
74629
75329
|
scroller: "_scroller_ly812_7"
|
|
@@ -76134,6 +76834,184 @@ var MessageContents = ({ message, references }) => {
|
|
|
76134
76834
|
references
|
|
76135
76835
|
}) });
|
|
76136
76836
|
};
|
|
76837
|
+
var AnnotatedScreenshot_module_default = {
|
|
76838
|
+
container: "_container_nfqzf_1",
|
|
76839
|
+
screenshot: "_screenshot_nfqzf_10",
|
|
76840
|
+
overlay: "_overlay_nfqzf_16",
|
|
76841
|
+
badge: "_badge_nfqzf_24",
|
|
76842
|
+
type: "_type_nfqzf_39",
|
|
76843
|
+
key: "_key_nfqzf_45"
|
|
76844
|
+
};
|
|
76845
|
+
//#endregion
|
|
76846
|
+
//#region ../../packages/inspect-components/src/chat/tools/browserActionUtils.ts
|
|
76847
|
+
/**
|
|
76848
|
+
* Tools whose actions can be annotated onto a screenshot. Membership requires
|
|
76849
|
+
* the tool's coordinate arguments to be in screenshot-pixel space and its
|
|
76850
|
+
* results to carry post-action screenshots (element-based browser tools like
|
|
76851
|
+
* web_browser_* don't qualify). The set plays two roles: it gates which calls
|
|
76852
|
+
* get a selfAnnotation, and the before-state scan in computeVisualActionContext
|
|
76853
|
+
* stops at the first tool call outside it — so adding a tool here also changes
|
|
76854
|
+
* which screenshots earlier actions may pair with.
|
|
76855
|
+
*/
|
|
76856
|
+
var BROWSER_TOOL_FUNCTIONS = /* @__PURE__ */ new Set(["browser", "computer"]);
|
|
76857
|
+
var CLICK_ACTIONS = /* @__PURE__ */ new Set([
|
|
76858
|
+
"left_click",
|
|
76859
|
+
"right_click",
|
|
76860
|
+
"middle_click",
|
|
76861
|
+
"double_click",
|
|
76862
|
+
"triple_click"
|
|
76863
|
+
]);
|
|
76864
|
+
var VISUAL_BROWSER_ACTIONS = /* @__PURE__ */ new Set([
|
|
76865
|
+
...CLICK_ACTIONS,
|
|
76866
|
+
"scroll",
|
|
76867
|
+
"type",
|
|
76868
|
+
"key"
|
|
76869
|
+
]);
|
|
76870
|
+
function asString(value) {
|
|
76871
|
+
return typeof value === "string" ? value : void 0;
|
|
76872
|
+
}
|
|
76873
|
+
function asCoordinate(value) {
|
|
76874
|
+
if (Array.isArray(value) && value.length === 2 && typeof value[0] === "number" && Number.isFinite(value[0]) && typeof value[1] === "number" && Number.isFinite(value[1])) return [value[0], value[1]];
|
|
76875
|
+
}
|
|
76876
|
+
/**
|
|
76877
|
+
* Narrows a tool call's arguments into a renderable annotation, or undefined
|
|
76878
|
+
* when the call is not a visual browser action (or its args are malformed).
|
|
76879
|
+
*/
|
|
76880
|
+
function buildSelfAnnotation(functionName, args) {
|
|
76881
|
+
if (!BROWSER_TOOL_FUNCTIONS.has(functionName)) return void 0;
|
|
76882
|
+
const action = asString(args.action);
|
|
76883
|
+
if (action === void 0 || !VISUAL_BROWSER_ACTIONS.has(action)) return void 0;
|
|
76884
|
+
return {
|
|
76885
|
+
action,
|
|
76886
|
+
coordinate: asCoordinate(args.coordinate),
|
|
76887
|
+
text: asString(args.text),
|
|
76888
|
+
scrollDirection: asString(args.scroll_direction)
|
|
76889
|
+
};
|
|
76890
|
+
}
|
|
76891
|
+
//#endregion
|
|
76892
|
+
//#region ../../packages/inspect-components/src/chat/tools/AnnotatedScreenshot.tsx
|
|
76893
|
+
/**
|
|
76894
|
+
* Renders a tool result's content with the action annotation drawn over its
|
|
76895
|
+
* screenshot. Only the last renderable image is annotated: results may carry
|
|
76896
|
+
* text alongside the screenshot, and the last image reflects the page state
|
|
76897
|
+
* the action targeted.
|
|
76898
|
+
*/
|
|
76899
|
+
var AnnotatedScreenshotOutput = ({ contents, annotation, context }) => {
|
|
76900
|
+
const annotatedIndex = contents.findLastIndex((c) => c.type === "image" && isRenderableImageSource(c.image));
|
|
76901
|
+
return /* @__PURE__ */ jsx(Fragment$1, { children: contents.map((c, i) => i === annotatedIndex && c.type === "image" ? /* @__PURE__ */ jsx(AnnotatedScreenshot, {
|
|
76902
|
+
src: c.image,
|
|
76903
|
+
annotation
|
|
76904
|
+
}, i) : /* @__PURE__ */ jsx(MessageContent, {
|
|
76905
|
+
contents: [c],
|
|
76906
|
+
context
|
|
76907
|
+
}, i)) });
|
|
76908
|
+
};
|
|
76909
|
+
/**
|
|
76910
|
+
* A screenshot with the action annotation drawn on top. The SVG overlay's
|
|
76911
|
+
* viewBox is the image's natural size, so annotation coordinates (which are
|
|
76912
|
+
* in screenshot pixels) map to display position without any JS measurement,
|
|
76913
|
+
* and the overlay rescales with the image automatically.
|
|
76914
|
+
*/
|
|
76915
|
+
var AnnotatedScreenshot = ({ src, annotation }) => {
|
|
76916
|
+
const [naturalSize, setNaturalSize] = useState();
|
|
76917
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
76918
|
+
className: AnnotatedScreenshot_module_default.container,
|
|
76919
|
+
children: [
|
|
76920
|
+
/* @__PURE__ */ jsx("img", {
|
|
76921
|
+
src,
|
|
76922
|
+
className: AnnotatedScreenshot_module_default.screenshot,
|
|
76923
|
+
onLoad: (e) => setNaturalSize({
|
|
76924
|
+
width: e.currentTarget.naturalWidth,
|
|
76925
|
+
height: e.currentTarget.naturalHeight
|
|
76926
|
+
})
|
|
76927
|
+
}),
|
|
76928
|
+
naturalSize && naturalSize.width > 0 && naturalSize.height > 0 && /* @__PURE__ */ jsx("svg", {
|
|
76929
|
+
viewBox: `0 0 ${naturalSize.width} ${naturalSize.height}`,
|
|
76930
|
+
preserveAspectRatio: "none",
|
|
76931
|
+
className: AnnotatedScreenshot_module_default.overlay,
|
|
76932
|
+
children: renderSvgAnnotation(annotation)
|
|
76933
|
+
}),
|
|
76934
|
+
renderHtmlAnnotation(annotation)
|
|
76935
|
+
]
|
|
76936
|
+
});
|
|
76937
|
+
};
|
|
76938
|
+
function renderSvgAnnotation(annotation) {
|
|
76939
|
+
const { action, coordinate } = annotation;
|
|
76940
|
+
if (CLICK_ACTIONS.has(action) && coordinate) {
|
|
76941
|
+
const [x, y] = coordinate;
|
|
76942
|
+
return /* @__PURE__ */ jsxs("g", {
|
|
76943
|
+
transform: `translate(${x}, ${y})`,
|
|
76944
|
+
children: [/* @__PURE__ */ jsx("circle", {
|
|
76945
|
+
cx: "0",
|
|
76946
|
+
cy: "0",
|
|
76947
|
+
r: "16",
|
|
76948
|
+
stroke: "rgba(239,68,68,0.8)",
|
|
76949
|
+
strokeWidth: "3",
|
|
76950
|
+
fill: "none",
|
|
76951
|
+
filter: "drop-shadow(0 0 6px rgba(239,68,68,0.4))"
|
|
76952
|
+
}), /* @__PURE__ */ jsx("svg", {
|
|
76953
|
+
viewBox: "0 0 32 32",
|
|
76954
|
+
width: "30",
|
|
76955
|
+
height: "30",
|
|
76956
|
+
x: "-10",
|
|
76957
|
+
y: "-7",
|
|
76958
|
+
children: /* @__PURE__ */ jsxs("g", {
|
|
76959
|
+
fill: "none",
|
|
76960
|
+
fillRule: "evenodd",
|
|
76961
|
+
transform: "translate(10 7)",
|
|
76962
|
+
children: [/* @__PURE__ */ jsx("path", {
|
|
76963
|
+
d: "m6.148 18.473 1.863-1.003 1.615-.839-2.568-4.816h4.332l-11.379-11.408v16.015l3.316-3.221z",
|
|
76964
|
+
fill: "#fff"
|
|
76965
|
+
}), /* @__PURE__ */ jsx("path", {
|
|
76966
|
+
d: "m6.431 17 1.765-.941-2.775-5.202h3.604l-8.025-8.043v11.188l2.53-2.442z",
|
|
76967
|
+
fill: "#000"
|
|
76968
|
+
})]
|
|
76969
|
+
})
|
|
76970
|
+
})]
|
|
76971
|
+
});
|
|
76972
|
+
}
|
|
76973
|
+
if (action === "scroll" && coordinate) {
|
|
76974
|
+
const [x, y] = coordinate;
|
|
76975
|
+
let arrow = "↕";
|
|
76976
|
+
if (annotation.scrollDirection) {
|
|
76977
|
+
const dir = annotation.scrollDirection.toLowerCase();
|
|
76978
|
+
if (dir.includes("up")) arrow = "↑";
|
|
76979
|
+
else if (dir.includes("down")) arrow = "↓";
|
|
76980
|
+
else if (dir.includes("left")) arrow = "←";
|
|
76981
|
+
else if (dir.includes("right")) arrow = "→";
|
|
76982
|
+
}
|
|
76983
|
+
return /* @__PURE__ */ jsxs("g", {
|
|
76984
|
+
transform: `translate(${x}, ${y})`,
|
|
76985
|
+
children: [/* @__PURE__ */ jsx("circle", {
|
|
76986
|
+
cx: "0",
|
|
76987
|
+
cy: "0",
|
|
76988
|
+
r: "18",
|
|
76989
|
+
fill: "rgba(59,130,246,0.8)"
|
|
76990
|
+
}), /* @__PURE__ */ jsx("text", {
|
|
76991
|
+
x: "0",
|
|
76992
|
+
y: "0",
|
|
76993
|
+
fill: "white",
|
|
76994
|
+
fontSize: "20",
|
|
76995
|
+
textAnchor: "middle",
|
|
76996
|
+
dominantBaseline: "central",
|
|
76997
|
+
fontWeight: "bold",
|
|
76998
|
+
children: arrow
|
|
76999
|
+
})]
|
|
77000
|
+
});
|
|
77001
|
+
}
|
|
77002
|
+
return null;
|
|
77003
|
+
}
|
|
77004
|
+
function renderHtmlAnnotation(annotation) {
|
|
77005
|
+
const { action, text } = annotation;
|
|
77006
|
+
if (action === "type" || action === "key") {
|
|
77007
|
+
const isKey = action === "key";
|
|
77008
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
77009
|
+
className: clsx(AnnotatedScreenshot_module_default.badge, isKey ? AnnotatedScreenshot_module_default.key : AnnotatedScreenshot_module_default.type),
|
|
77010
|
+
children: ["⌨ ", text || ""]
|
|
77011
|
+
});
|
|
77012
|
+
}
|
|
77013
|
+
return null;
|
|
77014
|
+
}
|
|
76137
77015
|
var customToolRendering_module_default = { submitView: "_submitView_1ru17_1" };
|
|
76138
77016
|
var ToolSearchView_module_default = {
|
|
76139
77017
|
catalog: "_catalog_gx8eg_1",
|
|
@@ -76246,7 +77124,7 @@ var ToolCallView_module_default = { toolCallView: "_toolCallView_x6cus_1" };
|
|
|
76246
77124
|
/**
|
|
76247
77125
|
* Renders the ToolCallView component.
|
|
76248
77126
|
*/
|
|
76249
|
-
var ToolCallView = ({ id, tool, functionCall, input, description, contentType, view, output, mode, collapsible = true, section = "all", getCustomToolView }) => {
|
|
77127
|
+
var ToolCallView = ({ id, tool, functionCall, input, selfAnnotation, inputScreenshot, description, contentType, view, output, mode, collapsible = true, section = "all", getCustomToolView }) => {
|
|
76250
77128
|
const displayMode = useDisplayMode();
|
|
76251
77129
|
function isContentImage(value) {
|
|
76252
77130
|
if (value && typeof value === "object") {
|
|
@@ -76282,6 +77160,8 @@ var ToolCallView = ({ id, tool, functionCall, input, description, contentType, v
|
|
|
76282
77160
|
description,
|
|
76283
77161
|
contentType,
|
|
76284
77162
|
output,
|
|
77163
|
+
selfAnnotation,
|
|
77164
|
+
inputScreenshot,
|
|
76285
77165
|
mode
|
|
76286
77166
|
};
|
|
76287
77167
|
const customView = displayMode === "rendered" ? getCustomToolView?.(props) ?? getDefaultCustomToolView(props) : void 0;
|
|
@@ -76327,9 +77207,25 @@ var ToolCallView = ({ id, tool, functionCall, input, description, contentType, v
|
|
|
76327
77207
|
contents: normalizedContent,
|
|
76328
77208
|
context
|
|
76329
77209
|
}) : null;
|
|
77210
|
+
const actionElement = selfAnnotation && inputScreenshot ? /* @__PURE__ */ jsx(AnnotatedScreenshotOutput, {
|
|
77211
|
+
contents: inputScreenshot,
|
|
77212
|
+
annotation: selfAnnotation,
|
|
77213
|
+
context
|
|
77214
|
+
}) : null;
|
|
77215
|
+
let outputContent = outputSection;
|
|
77216
|
+
if (actionElement) outputContent = hasContent ? /* @__PURE__ */ jsxs(NavPills, {
|
|
77217
|
+
id: `${id}-browser-action`,
|
|
77218
|
+
children: [/* @__PURE__ */ jsx("div", {
|
|
77219
|
+
title: "Result",
|
|
77220
|
+
children: outputSection
|
|
77221
|
+
}), /* @__PURE__ */ jsx("div", {
|
|
77222
|
+
title: "Action",
|
|
77223
|
+
children: actionElement
|
|
77224
|
+
})]
|
|
77225
|
+
}) : actionElement;
|
|
76330
77226
|
return /* @__PURE__ */ jsxs("div", {
|
|
76331
77227
|
className: clsx(ToolCallView_module_default.toolCallView),
|
|
76332
|
-
children: [section !== "output" ? callSection : null, section !== "call" ?
|
|
77228
|
+
children: [section !== "output" ? callSection : null, section !== "call" ? outputContent : null]
|
|
76333
77229
|
});
|
|
76334
77230
|
};
|
|
76335
77231
|
/**
|
|
@@ -76366,7 +77262,7 @@ var ClientToolCall_module_default = { custom: "_custom_v2cay_4" };
|
|
|
76366
77262
|
* header (terminal icon · mono tool name · args summary), the input zone
|
|
76367
77263
|
* (e.g. code) and the output well stacked beneath.
|
|
76368
77264
|
*/
|
|
76369
|
-
var ClientToolCall = ({ id, tool, title, functionCall, input, description, contentType, view, output, error, className, getCustomToolView }) => {
|
|
77265
|
+
var ClientToolCall = ({ id, tool, title, functionCall, input, description, contentType, view, output, selfAnnotation, inputScreenshot, error, className, getCustomToolView }) => {
|
|
76370
77266
|
const displayMode = useDisplayMode();
|
|
76371
77267
|
const viewProps = {
|
|
76372
77268
|
id,
|
|
@@ -76376,7 +77272,9 @@ var ClientToolCall = ({ id, tool, title, functionCall, input, description, conte
|
|
|
76376
77272
|
description,
|
|
76377
77273
|
contentType,
|
|
76378
77274
|
view,
|
|
76379
|
-
output
|
|
77275
|
+
output,
|
|
77276
|
+
selfAnnotation,
|
|
77277
|
+
inputScreenshot
|
|
76380
77278
|
};
|
|
76381
77279
|
const customView = displayMode === "rendered" ? getCustomToolView?.(viewProps) ?? getDefaultCustomToolView(viewProps) : void 0;
|
|
76382
77280
|
if (customView) return /* @__PURE__ */ jsx("div", {
|
|
@@ -76385,7 +77283,8 @@ var ClientToolCall = ({ id, tool, title, functionCall, input, description, conte
|
|
|
76385
77283
|
});
|
|
76386
77284
|
const hasInput = input !== void 0 && input !== null && input !== "" || !!view?.content;
|
|
76387
77285
|
const showError = !!error;
|
|
76388
|
-
const
|
|
77286
|
+
const showAnnotation = !!selfAnnotation && !!inputScreenshot;
|
|
77287
|
+
const showOutput = !showError && (hasOutputContent(output) || showAnnotation);
|
|
76389
77288
|
return /* @__PURE__ */ jsxs(ToolBlock, {
|
|
76390
77289
|
id,
|
|
76391
77290
|
icon: iconForTool(tool),
|
|
@@ -76403,7 +77302,11 @@ var ClientToolCall = ({ id, tool, title, functionCall, input, description, conte
|
|
|
76403
77302
|
contents: input,
|
|
76404
77303
|
toolCallView: view
|
|
76405
77304
|
})
|
|
76406
|
-
}) }) : null, showError ? /* @__PURE__ */
|
|
77305
|
+
}) }) : null, showError ? /* @__PURE__ */ jsxs(ToolBlockOutput, { children: [/* @__PURE__ */ jsx(ToolCallErrorView, { error }), selfAnnotation && inputScreenshot ? /* @__PURE__ */ jsx(AnnotatedScreenshotOutput, {
|
|
77306
|
+
contents: inputScreenshot,
|
|
77307
|
+
annotation: selfAnnotation,
|
|
77308
|
+
context: defaultContext()
|
|
77309
|
+
}) : null] }) : showOutput ? /* @__PURE__ */ jsx(ToolBlockOutput, { children: /* @__PURE__ */ jsx(ToolCallView, {
|
|
76407
77310
|
...viewProps,
|
|
76408
77311
|
section: "output"
|
|
76409
77312
|
}) }) : null]
|
|
@@ -88412,7 +89315,9 @@ var ToolEventView = ({ eventNode, childNodes, className, context, eventCallbacks
|
|
|
88412
89315
|
description,
|
|
88413
89316
|
contentType,
|
|
88414
89317
|
output: event.result ?? "",
|
|
88415
|
-
|
|
89318
|
+
selfAnnotation: context?.selfAnnotation,
|
|
89319
|
+
inputScreenshot: context?.inputScreenshot,
|
|
89320
|
+
error: showError && event.error ? event.error : void 0,
|
|
88416
89321
|
view: resolvedView
|
|
88417
89322
|
});
|
|
88418
89323
|
const toolLabel = toolLabels.messageLabels?.[event.id];
|
|
@@ -88517,6 +89422,40 @@ var TranscriptVirtualListComponent_module_default = {
|
|
|
88517
89422
|
runningTool: "_runningTool_t3xlr_31"
|
|
88518
89423
|
};
|
|
88519
89424
|
//#endregion
|
|
89425
|
+
//#region ../../packages/inspect-components/src/transcript/transcriptVisualActions.ts
|
|
89426
|
+
function computeVisualActionContext(eventNodes, index) {
|
|
89427
|
+
const node = eventNodes[index];
|
|
89428
|
+
if (!node || node.event.event !== "tool") return {};
|
|
89429
|
+
const toolEvent = node.event;
|
|
89430
|
+
const selfAnnotation = buildSelfAnnotation(toolEvent.function, toolEvent.arguments);
|
|
89431
|
+
if (!selfAnnotation) return {};
|
|
89432
|
+
for (let i = index - 1; i >= 0; i--) {
|
|
89433
|
+
const candidate = eventNodes[i];
|
|
89434
|
+
if (!candidate) continue;
|
|
89435
|
+
if (candidate.depth > node.depth) continue;
|
|
89436
|
+
if (candidate.depth < node.depth) break;
|
|
89437
|
+
if (candidate.event.event !== "tool") continue;
|
|
89438
|
+
const candEvent = candidate.event;
|
|
89439
|
+
if (!BROWSER_TOOL_FUNCTIONS.has(candEvent.function)) break;
|
|
89440
|
+
const inputScreenshot = normalizeScreenshotResult(candEvent.result);
|
|
89441
|
+
if (inputScreenshot && inputScreenshot.some((c) => c.type === "image")) return {
|
|
89442
|
+
inputScreenshot,
|
|
89443
|
+
selfAnnotation
|
|
89444
|
+
};
|
|
89445
|
+
}
|
|
89446
|
+
return {};
|
|
89447
|
+
}
|
|
89448
|
+
function normalizeScreenshotResult(result) {
|
|
89449
|
+
if (Array.isArray(result)) {
|
|
89450
|
+
const filtered = result.filter((item) => item.type !== "document");
|
|
89451
|
+
return filtered.length > 0 ? filtered : void 0;
|
|
89452
|
+
}
|
|
89453
|
+
if (result && typeof result === "object" && "type" in result) {
|
|
89454
|
+
if (result.type === "document") return void 0;
|
|
89455
|
+
return [result];
|
|
89456
|
+
}
|
|
89457
|
+
}
|
|
89458
|
+
//#endregion
|
|
88520
89459
|
//#region ../../packages/inspect-components/src/transcript/TranscriptVirtualListComponent.tsx
|
|
88521
89460
|
/**
|
|
88522
89461
|
* Renders the Transcript component.
|
|
@@ -88541,10 +89480,13 @@ var TranscriptVirtualListComponent = ({ id, listHandle, eventNodes, scrollRef, r
|
|
|
88541
89480
|
for (const [i, node] of eventNodes.entries()) {
|
|
88542
89481
|
const hasToolEvents = hasToolEventsLookup[i] ?? false;
|
|
88543
89482
|
const turnInfo = turnMap?.get(node.id);
|
|
89483
|
+
const { inputScreenshot, selfAnnotation } = computeVisualActionContext(eventNodes, i);
|
|
88544
89484
|
map.set(node.id, {
|
|
88545
89485
|
hasToolEvents,
|
|
88546
89486
|
turnInfo,
|
|
88547
|
-
...eventNodeContext
|
|
89487
|
+
...eventNodeContext,
|
|
89488
|
+
inputScreenshot,
|
|
89489
|
+
selfAnnotation
|
|
88548
89490
|
});
|
|
88549
89491
|
}
|
|
88550
89492
|
return map;
|
|
@@ -94712,8 +95654,9 @@ var TranscriptPanel = memo((props) => {
|
|
|
94712
95654
|
logFile,
|
|
94713
95655
|
logDir
|
|
94714
95656
|
]);
|
|
95657
|
+
const getFullEventUrl = useCallback((eventId) => toFullUrlMaybe(getEventUrl(eventId)), [getEventUrl]);
|
|
94715
95658
|
const renderLink = useCallback((url, children) => /* @__PURE__ */ jsx(Link, {
|
|
94716
|
-
to: url,
|
|
95659
|
+
to: routeFromFullUrl(url),
|
|
94717
95660
|
replace: true,
|
|
94718
95661
|
children
|
|
94719
95662
|
}), []);
|
|
@@ -94751,8 +95694,8 @@ var TranscriptPanel = memo((props) => {
|
|
|
94751
95694
|
listId: id,
|
|
94752
95695
|
initialEventId,
|
|
94753
95696
|
initialMessageId,
|
|
94754
|
-
getEventUrl,
|
|
94755
|
-
linkingEnabled:
|
|
95697
|
+
getEventUrl: getFullEventUrl,
|
|
95698
|
+
linkingEnabled: isHostedEnvironment(),
|
|
94756
95699
|
bulkCollapse,
|
|
94757
95700
|
collapseState,
|
|
94758
95701
|
eventsListRef,
|
|
@@ -94857,14 +95800,7 @@ var SampleDisplay = ({ id, scrollRef, showActivity, focusOnLoad }) => {
|
|
|
94857
95800
|
navigate
|
|
94858
95801
|
]);
|
|
94859
95802
|
const setNativeFind = useStore((state) => state.appActions.setNativeFind);
|
|
94860
|
-
const getMessageUrl =
|
|
94861
|
-
return urlLogPath ? sampleMessageUrl(sampleUrlBuilder, messageId, urlLogPath, urlSampleId, urlEpoch) : void 0;
|
|
94862
|
-
}, [
|
|
94863
|
-
sampleUrlBuilder,
|
|
94864
|
-
urlLogPath,
|
|
94865
|
-
urlSampleId,
|
|
94866
|
-
urlEpoch
|
|
94867
|
-
]);
|
|
95803
|
+
const getMessageUrl = useFullSampleMessageUrlBuilder();
|
|
94868
95804
|
const chatDisplay = useMemo(() => ({
|
|
94869
95805
|
indented: true,
|
|
94870
95806
|
formatDateTime
|
|
@@ -95528,37 +96464,27 @@ var SampleDetailComponent = ({ sampleId, epoch, tabId, navigation, navbarConfig
|
|
|
95528
96464
|
useEffect(() => {
|
|
95529
96465
|
if (tabId) setSampleTab(tabId);
|
|
95530
96466
|
}, [tabId, setSampleTab]);
|
|
96467
|
+
useFindBandShortcut(useCallback(() => setShowFind(true), [setShowFind]), {
|
|
96468
|
+
onClose: hideFind,
|
|
96469
|
+
isOpen: showFind,
|
|
96470
|
+
enabled: !nativeFind
|
|
96471
|
+
});
|
|
95531
96472
|
const handleKeyDown = useCallback((e) => {
|
|
95532
|
-
|
|
95533
|
-
|
|
95534
|
-
|
|
95535
|
-
if ((e.ctrlKey || e.metaKey) && e.key === "f") {
|
|
95536
|
-
if (!nativeFind) {
|
|
96473
|
+
if (isEditableTarget(deepActiveElement())) return;
|
|
96474
|
+
if (e.key === "ArrowLeft") {
|
|
96475
|
+
if (hasPrevious) {
|
|
95537
96476
|
e.preventDefault();
|
|
95538
|
-
|
|
95539
|
-
setShowFind(true);
|
|
96477
|
+
onPrevious();
|
|
95540
96478
|
}
|
|
95541
|
-
} else if (e.key === "
|
|
95542
|
-
if (
|
|
95543
|
-
|
|
95544
|
-
|
|
95545
|
-
if (hasPrevious) {
|
|
95546
|
-
e.preventDefault();
|
|
95547
|
-
onPrevious();
|
|
95548
|
-
}
|
|
95549
|
-
} else if (e.key === "ArrowRight") {
|
|
95550
|
-
if (hasNext) {
|
|
95551
|
-
e.preventDefault();
|
|
95552
|
-
onNext();
|
|
95553
|
-
}
|
|
96479
|
+
} else if (e.key === "ArrowRight") {
|
|
96480
|
+
if (hasNext) {
|
|
96481
|
+
e.preventDefault();
|
|
96482
|
+
onNext();
|
|
95554
96483
|
}
|
|
95555
96484
|
}
|
|
95556
96485
|
}, [
|
|
95557
|
-
setShowFind,
|
|
95558
|
-
hideFind,
|
|
95559
96486
|
hasPrevious,
|
|
95560
96487
|
hasNext,
|
|
95561
|
-
nativeFind,
|
|
95562
96488
|
onPrevious,
|
|
95563
96489
|
onNext
|
|
95564
96490
|
]);
|
|
@@ -95574,7 +96500,7 @@ var SampleDetailComponent = ({ sampleId, epoch, tabId, navigation, navbarConfig
|
|
|
95574
96500
|
action();
|
|
95575
96501
|
}
|
|
95576
96502
|
}, []);
|
|
95577
|
-
return /* @__PURE__ */ jsx(ExtendedFindProvider, { children: /* @__PURE__ */ jsxs(FindTargetProvider, { children: [showFind ? /* @__PURE__ */ jsx(FindBand, {}) : "", /* @__PURE__ */ jsxs("div", {
|
|
96503
|
+
return /* @__PURE__ */ jsx(ExtendedFindProvider, { children: /* @__PURE__ */ jsxs(FindTargetProvider, { children: [showFind ? /* @__PURE__ */ jsx(FindBand, { onClose: hideFind }) : "", /* @__PURE__ */ jsxs("div", {
|
|
95578
96504
|
className: SampleDetailComponent_module_default.detail,
|
|
95579
96505
|
children: [/* @__PURE__ */ jsx(ApplicationNavbar, {
|
|
95580
96506
|
currentPath,
|
|
@@ -120440,7 +121366,7 @@ var SampleFilter = () => {
|
|
|
120440
121366
|
activateOnCompletion: (c) => c.label.endsWith(" ")
|
|
120441
121367
|
}), [filterItems, samples]);
|
|
120442
121368
|
const makeLinter = useCallback(() => linter((view) => getLints(view, filterError)), [filterError]);
|
|
120443
|
-
const debounceSetFilter = useMemo(() => debounce$
|
|
121369
|
+
const debounceSetFilter = useMemo(() => debounce$3((value) => {
|
|
120444
121370
|
setFilter(value);
|
|
120445
121371
|
}, 200), [setFilter]);
|
|
120446
121372
|
const makeUpdateListener = useCallback(() => EditorView.updateListener.of((update) => {
|
|
@@ -120885,7 +121811,7 @@ var SamplesTab = ({ running, scrollRef, showColumnSelector, setShowColumnSelecto
|
|
|
120885
121811
|
const items = useMemo(() => {
|
|
120886
121812
|
if (!samplesDescriptor || !selectedLogFile) return [];
|
|
120887
121813
|
return sampleSummaries.map((sample) => {
|
|
120888
|
-
const tokens =
|
|
121814
|
+
const tokens = totalSampleTokens(sample.model_usage);
|
|
120889
121815
|
return {
|
|
120890
121816
|
logFile: selectedLogFile,
|
|
120891
121817
|
sampleId: sample.id,
|
|
@@ -122592,30 +123518,17 @@ var LogViewLayout = () => {
|
|
|
122592
123518
|
const prefix = useRoutePrefix();
|
|
122593
123519
|
const navigationUrl = (file, log_dir) => logsUrl(file, log_dir, void 0, prefix);
|
|
122594
123520
|
const mainAppRef = useRef(null);
|
|
122595
|
-
|
|
122596
|
-
|
|
122597
|
-
|
|
122598
|
-
|
|
122599
|
-
|
|
122600
|
-
e.stopPropagation();
|
|
122601
|
-
if (setShowFind) setShowFind(true);
|
|
122602
|
-
} else if (e.key === "Escape") hideFind();
|
|
122603
|
-
};
|
|
122604
|
-
document.addEventListener("keydown", handleGlobalKeyDown, true);
|
|
122605
|
-
return () => {
|
|
122606
|
-
document.removeEventListener("keydown", handleGlobalKeyDown, true);
|
|
122607
|
-
};
|
|
122608
|
-
}, [
|
|
122609
|
-
setShowFind,
|
|
122610
|
-
hideFind,
|
|
122611
|
-
nativeFind
|
|
122612
|
-
]);
|
|
123521
|
+
useFindBandShortcut(useCallback(() => setShowFind(true), [setShowFind]), {
|
|
123522
|
+
onClose: hideFind,
|
|
123523
|
+
isOpen: showFind,
|
|
123524
|
+
enabled: !nativeFind
|
|
123525
|
+
});
|
|
122613
123526
|
return /* @__PURE__ */ jsx(ExtendedFindProvider, { children: /* @__PURE__ */ jsx(FindTargetProvider, { children: /* @__PURE__ */ jsxs("div", {
|
|
122614
123527
|
ref: mainAppRef,
|
|
122615
123528
|
className: clsx("app-main-grid", singleFileMode ? "single-file-mode" : void 0, "log-view"),
|
|
122616
123529
|
tabIndex: 0,
|
|
122617
123530
|
children: [
|
|
122618
|
-
showFind ? /* @__PURE__ */ jsx(FindBand, {}) : "",
|
|
123531
|
+
showFind ? /* @__PURE__ */ jsx(FindBand, { onClose: hideFind }) : "",
|
|
122619
123532
|
!singleFileMode ? /* @__PURE__ */ jsx(ApplicationNavbar, {
|
|
122620
123533
|
fnNavigationUrl: navigationUrl,
|
|
122621
123534
|
currentPath: logPath
|
|
@@ -123213,7 +124126,7 @@ var SamplesPanel = () => {
|
|
|
123213
124126
|
const currentDirLogFiles = useMemo(() => {
|
|
123214
124127
|
const files = [];
|
|
123215
124128
|
for (const logFile of logFiles) {
|
|
123216
|
-
const inCurrentDir = logFile.name.startsWith(currentDir);
|
|
124129
|
+
const inCurrentDir = logFile.name.startsWith(scopePrefix(currentDir));
|
|
123217
124130
|
const skipped = !showRetriedLogs && logFile.retried;
|
|
123218
124131
|
if (inCurrentDir && !skipped) files.push(logFile);
|
|
123219
124132
|
}
|
|
@@ -123324,8 +124237,7 @@ var SamplesPanel = () => {
|
|
|
123324
124237
|
acc[log.name] = log;
|
|
123325
124238
|
return acc;
|
|
123326
124239
|
}, {});
|
|
123327
|
-
const allRows = scopedSamples.map(({ logFile, summary: sample, log }) => {
|
|
123328
|
-
const tokens = sample.model_usage ? Object.values(sample.model_usage).reduce((sum, u) => sum + (u.total_tokens ?? 0), 0) : void 0;
|
|
124240
|
+
const allRows = scopedSamples.map(({ logFile, summary: sample, derived, log }) => {
|
|
123329
124241
|
const row = {
|
|
123330
124242
|
logFile,
|
|
123331
124243
|
sampleId: sample.id,
|
|
@@ -123335,17 +124247,17 @@ var SamplesPanel = () => {
|
|
|
123335
124247
|
task: log.task || "",
|
|
123336
124248
|
model: log.model || "",
|
|
123337
124249
|
status: log.status,
|
|
123338
|
-
input:
|
|
123339
|
-
target:
|
|
124250
|
+
input: derived.input,
|
|
124251
|
+
target: derived.target,
|
|
123340
124252
|
error: sample.error,
|
|
123341
124253
|
limit: sample.limit,
|
|
123342
124254
|
retries: sample.retries,
|
|
123343
|
-
fallbacks:
|
|
124255
|
+
fallbacks: derived.fallbacks,
|
|
123344
124256
|
completed: sample.completed,
|
|
123345
|
-
tokens,
|
|
124257
|
+
tokens: derived.tokens,
|
|
123346
124258
|
duration: sample.total_time ?? void 0
|
|
123347
124259
|
};
|
|
123348
|
-
if (
|
|
124260
|
+
if (derived.scores) for (const [scoreName, value] of Object.entries(derived.scores)) row[`${SCORE_FIELD_RAW_PREFIX}${scoreName}`] = value;
|
|
123349
124261
|
return row;
|
|
123350
124262
|
});
|
|
123351
124263
|
const _sampleRows = allRows.filter((row) => row.logFile in logInCurrentDirByName);
|
|
@@ -123570,6 +124482,8 @@ var AppRouter = createHashRouter([{
|
|
|
123570
124482
|
//#endregion
|
|
123571
124483
|
//#region src/app/App.tsx
|
|
123572
124484
|
var componentIcons = {
|
|
124485
|
+
arrowDown: ApplicationIcons.arrows.down,
|
|
124486
|
+
arrowUp: ApplicationIcons.arrows.up,
|
|
123573
124487
|
chevronDown: ApplicationIcons.chevron.down,
|
|
123574
124488
|
chevronUp: ApplicationIcons.collapse.up,
|
|
123575
124489
|
clearText: ApplicationIcons["clear-text"],
|