executable-stories-react 0.12.0 → 0.13.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/interactive.cjs +469 -172
- package/dist/interactive.cjs.map +1 -1
- package/dist/interactive.js +426 -123
- package/dist/interactive.js.map +1 -1
- package/dist/report-island.global.js +64 -54
- package/dist/ssr.cjs +1 -1
- package/dist/ssr.cjs.map +1 -1
- package/dist/ssr.js +1 -1
- package/dist/ssr.js.map +1 -1
- package/dist/tailwind.css +2 -2
- package/package.json +24 -23
package/dist/interactive.js
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
// src/interactive/ReportInteractive.tsx
|
|
4
4
|
import { Monitor, Moon, Sun } from "lucide-react";
|
|
5
|
+
import { useTools } from "webmcpable/react";
|
|
5
6
|
import {
|
|
6
7
|
useCallback as useCallback5,
|
|
7
8
|
useDeferredValue,
|
|
@@ -2068,9 +2069,69 @@ function listFailures(report) {
|
|
|
2068
2069
|
return out;
|
|
2069
2070
|
}
|
|
2070
2071
|
|
|
2072
|
+
// src/interactive/ReportAgentFilterNotice.tsx
|
|
2073
|
+
import { Bot, X } from "lucide-react";
|
|
2074
|
+
import { Fragment as Fragment11, jsx as jsx39, jsxs as jsxs25 } from "react/jsx-runtime";
|
|
2075
|
+
function ReportAgentFilterNotice({
|
|
2076
|
+
applied,
|
|
2077
|
+
onReset,
|
|
2078
|
+
onDismiss
|
|
2079
|
+
}) {
|
|
2080
|
+
const terms = [];
|
|
2081
|
+
if (applied.search) terms.push(`matching \u201C${applied.search}\u201D`);
|
|
2082
|
+
if (applied.status !== "all") terms.push(applied.status);
|
|
2083
|
+
if (applied.tags.length > 0) terms.push(applied.tags.join(", "));
|
|
2084
|
+
return /* @__PURE__ */ jsxs25(
|
|
2085
|
+
"div",
|
|
2086
|
+
{
|
|
2087
|
+
role: "status",
|
|
2088
|
+
"aria-live": "polite",
|
|
2089
|
+
className: "flex flex-wrap items-center gap-x-3 gap-y-1 rounded-md border border-primary/40 bg-primary/5 px-3 py-2 text-sm",
|
|
2090
|
+
children: [
|
|
2091
|
+
/* @__PURE__ */ jsx39(Bot, { "aria-hidden": true, className: "size-4 shrink-0 text-primary" }),
|
|
2092
|
+
/* @__PURE__ */ jsxs25("span", { className: "min-w-0 flex-1", children: [
|
|
2093
|
+
"An agent filtered this report",
|
|
2094
|
+
terms.length > 0 ? /* @__PURE__ */ jsxs25(Fragment11, { children: [
|
|
2095
|
+
" to ",
|
|
2096
|
+
terms.join(" \xB7 ")
|
|
2097
|
+
] }) : null,
|
|
2098
|
+
" \u2014",
|
|
2099
|
+
" ",
|
|
2100
|
+
/* @__PURE__ */ jsxs25("span", { className: "tabular-nums", children: [
|
|
2101
|
+
applied.matched,
|
|
2102
|
+
" of ",
|
|
2103
|
+
applied.total,
|
|
2104
|
+
" scenarios"
|
|
2105
|
+
] }),
|
|
2106
|
+
"."
|
|
2107
|
+
] }),
|
|
2108
|
+
/* @__PURE__ */ jsx39(
|
|
2109
|
+
"button",
|
|
2110
|
+
{
|
|
2111
|
+
type: "button",
|
|
2112
|
+
onClick: onReset,
|
|
2113
|
+
className: "cursor-pointer rounded-md border border-border px-2 py-1 text-xs hover:bg-muted",
|
|
2114
|
+
children: "Show all"
|
|
2115
|
+
}
|
|
2116
|
+
),
|
|
2117
|
+
/* @__PURE__ */ jsx39(
|
|
2118
|
+
"button",
|
|
2119
|
+
{
|
|
2120
|
+
type: "button",
|
|
2121
|
+
onClick: onDismiss,
|
|
2122
|
+
"aria-label": "Dismiss",
|
|
2123
|
+
className: "cursor-pointer rounded-md p-1 text-muted-foreground hover:text-foreground",
|
|
2124
|
+
children: /* @__PURE__ */ jsx39(X, { "aria-hidden": true, className: "size-4" })
|
|
2125
|
+
}
|
|
2126
|
+
)
|
|
2127
|
+
]
|
|
2128
|
+
}
|
|
2129
|
+
);
|
|
2130
|
+
}
|
|
2131
|
+
|
|
2071
2132
|
// src/interactive/ReportFailureBanner.tsx
|
|
2072
2133
|
import { useCallback as useCallback2 } from "react";
|
|
2073
|
-
import { jsx as
|
|
2134
|
+
import { jsx as jsx40, jsxs as jsxs26 } from "react/jsx-runtime";
|
|
2074
2135
|
function ReportFailureBanner({ failures }) {
|
|
2075
2136
|
const first = failures[0];
|
|
2076
2137
|
const jumpToFirst = useCallback2(() => {
|
|
@@ -2078,7 +2139,7 @@ function ReportFailureBanner({ failures }) {
|
|
|
2078
2139
|
scrollToScenarioId(first.scenarioId);
|
|
2079
2140
|
}, [first]);
|
|
2080
2141
|
if (failures.length === 0) return null;
|
|
2081
|
-
return /* @__PURE__ */
|
|
2142
|
+
return /* @__PURE__ */ jsxs26(
|
|
2082
2143
|
"div",
|
|
2083
2144
|
{
|
|
2084
2145
|
className: "es-failure-banner",
|
|
@@ -2086,13 +2147,13 @@ function ReportFailureBanner({ failures }) {
|
|
|
2086
2147
|
"aria-live": "polite",
|
|
2087
2148
|
"aria-label": "Failure summary",
|
|
2088
2149
|
children: [
|
|
2089
|
-
/* @__PURE__ */
|
|
2090
|
-
/* @__PURE__ */
|
|
2150
|
+
/* @__PURE__ */ jsxs26("span", { className: "es-failure-banner-text", children: [
|
|
2151
|
+
/* @__PURE__ */ jsx40("strong", { children: failures.length }),
|
|
2091
2152
|
" ",
|
|
2092
2153
|
"failure",
|
|
2093
2154
|
failures.length === 1 ? "" : "s"
|
|
2094
2155
|
] }),
|
|
2095
|
-
/* @__PURE__ */
|
|
2156
|
+
/* @__PURE__ */ jsx40(
|
|
2096
2157
|
"button",
|
|
2097
2158
|
{
|
|
2098
2159
|
type: "button",
|
|
@@ -2109,7 +2170,7 @@ function ReportFailureBanner({ failures }) {
|
|
|
2109
2170
|
|
|
2110
2171
|
// src/interactive/ReportFilters.tsx
|
|
2111
2172
|
import { useState as useState3 } from "react";
|
|
2112
|
-
import { jsx as
|
|
2173
|
+
import { jsx as jsx41, jsxs as jsxs27 } from "react/jsx-runtime";
|
|
2113
2174
|
var TAG_LIMIT = 12;
|
|
2114
2175
|
function ReportFilters({
|
|
2115
2176
|
statuses,
|
|
@@ -2123,10 +2184,10 @@ function ReportFilters({
|
|
|
2123
2184
|
if (statuses.length === 0 && tags.length === 0) return null;
|
|
2124
2185
|
const tagsCollapsed = tags.length > TAG_LIMIT && !showAllTags;
|
|
2125
2186
|
const visibleTags = tagsCollapsed ? tags.slice(0, TAG_LIMIT) : tags;
|
|
2126
|
-
return /* @__PURE__ */
|
|
2127
|
-
statuses.length > 0 ? /* @__PURE__ */
|
|
2187
|
+
return /* @__PURE__ */ jsxs27("div", { className: "flex flex-col gap-2", children: [
|
|
2188
|
+
statuses.length > 0 ? /* @__PURE__ */ jsx41("div", { role: "group", "aria-label": "Filter by status", className: "flex flex-wrap gap-1", children: statuses.map((opt) => {
|
|
2128
2189
|
const active = status === opt.key;
|
|
2129
|
-
return /* @__PURE__ */
|
|
2190
|
+
return /* @__PURE__ */ jsxs27(
|
|
2130
2191
|
"button",
|
|
2131
2192
|
{
|
|
2132
2193
|
type: "button",
|
|
@@ -2138,23 +2199,23 @@ function ReportFilters({
|
|
|
2138
2199
|
),
|
|
2139
2200
|
children: [
|
|
2140
2201
|
opt.label,
|
|
2141
|
-
/* @__PURE__ */
|
|
2202
|
+
/* @__PURE__ */ jsx41("span", { className: "ml-1 font-mono opacity-70", children: opt.count })
|
|
2142
2203
|
]
|
|
2143
2204
|
},
|
|
2144
2205
|
opt.key
|
|
2145
2206
|
);
|
|
2146
2207
|
}) }) : null,
|
|
2147
|
-
tags.length > 0 ? /* @__PURE__ */
|
|
2208
|
+
tags.length > 0 ? /* @__PURE__ */ jsxs27("ul", { "aria-label": "Filter by tag", className: "flex flex-wrap items-center gap-1.5", children: [
|
|
2148
2209
|
visibleTags.map((tag) => {
|
|
2149
2210
|
const active = activeTags.includes(tag);
|
|
2150
|
-
return /* @__PURE__ */
|
|
2211
|
+
return /* @__PURE__ */ jsx41("li", { children: /* @__PURE__ */ jsx41(
|
|
2151
2212
|
"button",
|
|
2152
2213
|
{
|
|
2153
2214
|
type: "button",
|
|
2154
2215
|
"aria-pressed": active,
|
|
2155
2216
|
onClick: () => onToggleTag(tag),
|
|
2156
2217
|
className: "cursor-pointer",
|
|
2157
|
-
children: /* @__PURE__ */
|
|
2218
|
+
children: /* @__PURE__ */ jsx41(
|
|
2158
2219
|
Badge,
|
|
2159
2220
|
{
|
|
2160
2221
|
variant: "tag",
|
|
@@ -2167,7 +2228,7 @@ function ReportFilters({
|
|
|
2167
2228
|
}
|
|
2168
2229
|
) }, tag);
|
|
2169
2230
|
}),
|
|
2170
|
-
tags.length > TAG_LIMIT ? /* @__PURE__ */
|
|
2231
|
+
tags.length > TAG_LIMIT ? /* @__PURE__ */ jsx41("li", { children: /* @__PURE__ */ jsx41(
|
|
2171
2232
|
"button",
|
|
2172
2233
|
{
|
|
2173
2234
|
type: "button",
|
|
@@ -2183,7 +2244,7 @@ function ReportFilters({
|
|
|
2183
2244
|
|
|
2184
2245
|
// src/interactive/ReportFreshness.tsx
|
|
2185
2246
|
import { useEffect as useEffect2, useState as useState4 } from "react";
|
|
2186
|
-
import { Fragment as
|
|
2247
|
+
import { Fragment as Fragment12, jsx as jsx42, jsxs as jsxs28 } from "react/jsx-runtime";
|
|
2187
2248
|
function ReportFreshness({ lastRunMs, ciUrl, staleAfterDays, nowMs }) {
|
|
2188
2249
|
const [now, setNow] = useState4(nowMs);
|
|
2189
2250
|
useEffect2(() => {
|
|
@@ -2191,7 +2252,7 @@ function ReportFreshness({ lastRunMs, ciUrl, staleAfterDays, nowMs }) {
|
|
|
2191
2252
|
}, [nowMs]);
|
|
2192
2253
|
if (lastRunMs === void 0 || now === void 0) return null;
|
|
2193
2254
|
const age = formatRelativeAge(lastRunMs, now);
|
|
2194
|
-
const runLink = ciUrl ? /* @__PURE__ */
|
|
2255
|
+
const runLink = ciUrl ? /* @__PURE__ */ jsx42(
|
|
2195
2256
|
"a",
|
|
2196
2257
|
{
|
|
2197
2258
|
href: ciUrl,
|
|
@@ -2202,9 +2263,9 @@ function ReportFreshness({ lastRunMs, ciUrl, staleAfterDays, nowMs }) {
|
|
|
2202
2263
|
}
|
|
2203
2264
|
) : null;
|
|
2204
2265
|
if (isReportStale(lastRunMs, staleAfterDays, now)) {
|
|
2205
|
-
return /* @__PURE__ */
|
|
2206
|
-
/* @__PURE__ */
|
|
2207
|
-
/* @__PURE__ */
|
|
2266
|
+
return /* @__PURE__ */ jsxs28("div", { className: "es-stale-banner", role: "status", "aria-label": "Report freshness", children: [
|
|
2267
|
+
/* @__PURE__ */ jsxs28("span", { children: [
|
|
2268
|
+
/* @__PURE__ */ jsxs28("strong", { children: [
|
|
2208
2269
|
"Last verified ",
|
|
2209
2270
|
age,
|
|
2210
2271
|
"."
|
|
@@ -2214,10 +2275,10 @@ function ReportFreshness({ lastRunMs, ciUrl, staleAfterDays, nowMs }) {
|
|
|
2214
2275
|
runLink
|
|
2215
2276
|
] });
|
|
2216
2277
|
}
|
|
2217
|
-
return /* @__PURE__ */
|
|
2278
|
+
return /* @__PURE__ */ jsxs28("p", { className: "es-freshness", "aria-label": "Report freshness", children: [
|
|
2218
2279
|
"Verified ",
|
|
2219
2280
|
age,
|
|
2220
|
-
runLink ? /* @__PURE__ */
|
|
2281
|
+
runLink ? /* @__PURE__ */ jsxs28(Fragment12, { children: [
|
|
2221
2282
|
" \xB7 ",
|
|
2222
2283
|
runLink
|
|
2223
2284
|
] }) : null
|
|
@@ -2225,15 +2286,15 @@ function ReportFreshness({ lastRunMs, ciUrl, staleAfterDays, nowMs }) {
|
|
|
2225
2286
|
}
|
|
2226
2287
|
|
|
2227
2288
|
// src/interactive/ReportLastRunDelta.tsx
|
|
2228
|
-
import { Fragment as
|
|
2289
|
+
import { Fragment as Fragment13, jsx as jsx43, jsxs as jsxs29 } from "react/jsx-runtime";
|
|
2229
2290
|
var MAX_LINKS = 5;
|
|
2230
2291
|
function ScenarioLinks({ scenarios, tone }) {
|
|
2231
|
-
return /* @__PURE__ */
|
|
2232
|
-
scenarios.slice(0, MAX_LINKS).map((s, i) => /* @__PURE__ */
|
|
2292
|
+
return /* @__PURE__ */ jsxs29(Fragment13, { children: [
|
|
2293
|
+
scenarios.slice(0, MAX_LINKS).map((s, i) => /* @__PURE__ */ jsxs29("span", { children: [
|
|
2233
2294
|
i > 0 ? ", " : "",
|
|
2234
|
-
/* @__PURE__ */
|
|
2295
|
+
/* @__PURE__ */ jsx43("a", { href: `#${s.id}`, className: cn("underline underline-offset-2 hover:no-underline", tone), children: s.title })
|
|
2235
2296
|
] }, s.id)),
|
|
2236
|
-
scenarios.length > MAX_LINKS ? /* @__PURE__ */
|
|
2297
|
+
scenarios.length > MAX_LINKS ? /* @__PURE__ */ jsxs29("span", { children: [
|
|
2237
2298
|
" and ",
|
|
2238
2299
|
scenarios.length - MAX_LINKS,
|
|
2239
2300
|
" more"
|
|
@@ -2250,23 +2311,23 @@ function ReportLastRunDelta({
|
|
|
2250
2311
|
if (!delta) return null;
|
|
2251
2312
|
const { newlyFailing, newlyPassing, added } = delta;
|
|
2252
2313
|
if (newlyFailing.length === 0 && newlyPassing.length === 0 && added.length === 0) {
|
|
2253
|
-
return /* @__PURE__ */
|
|
2314
|
+
return /* @__PURE__ */ jsx43("p", { className: "text-xs text-muted-foreground", "data-testid": "es-last-run-delta", children: "Since last run: no behavior changes." });
|
|
2254
2315
|
}
|
|
2255
|
-
return /* @__PURE__ */
|
|
2256
|
-
/* @__PURE__ */
|
|
2257
|
-
newlyFailing.length > 0 ? /* @__PURE__ */
|
|
2316
|
+
return /* @__PURE__ */ jsxs29("p", { className: "text-xs text-muted-foreground", "data-testid": "es-last-run-delta", children: [
|
|
2317
|
+
/* @__PURE__ */ jsx43("span", { className: "font-medium text-foreground", children: "Since last run:" }),
|
|
2318
|
+
newlyFailing.length > 0 ? /* @__PURE__ */ jsxs29("span", { className: "ml-2 text-fail", children: [
|
|
2258
2319
|
newlyFailing.length,
|
|
2259
2320
|
" newly failing (",
|
|
2260
|
-
/* @__PURE__ */
|
|
2321
|
+
/* @__PURE__ */ jsx43(ScenarioLinks, { scenarios: newlyFailing, tone: "text-fail" }),
|
|
2261
2322
|
")"
|
|
2262
2323
|
] }) : null,
|
|
2263
|
-
newlyPassing.length > 0 ? /* @__PURE__ */
|
|
2324
|
+
newlyPassing.length > 0 ? /* @__PURE__ */ jsxs29("span", { className: "ml-2 text-pass", children: [
|
|
2264
2325
|
newlyPassing.length,
|
|
2265
2326
|
" fixed (",
|
|
2266
|
-
/* @__PURE__ */
|
|
2327
|
+
/* @__PURE__ */ jsx43(ScenarioLinks, { scenarios: newlyPassing, tone: "text-pass" }),
|
|
2267
2328
|
")"
|
|
2268
2329
|
] }) : null,
|
|
2269
|
-
added.length > 0 ? /* @__PURE__ */
|
|
2330
|
+
added.length > 0 ? /* @__PURE__ */ jsxs29("span", { className: "ml-2", children: [
|
|
2270
2331
|
added.length,
|
|
2271
2332
|
" new"
|
|
2272
2333
|
] }) : null
|
|
@@ -2282,9 +2343,9 @@ import { Search } from "lucide-react";
|
|
|
2282
2343
|
|
|
2283
2344
|
// src/components/ui/input.tsx
|
|
2284
2345
|
import "react";
|
|
2285
|
-
import { jsx as
|
|
2346
|
+
import { jsx as jsx44 } from "react/jsx-runtime";
|
|
2286
2347
|
function Input({ className, type, ...props }) {
|
|
2287
|
-
return /* @__PURE__ */
|
|
2348
|
+
return /* @__PURE__ */ jsx44(
|
|
2288
2349
|
"input",
|
|
2289
2350
|
{
|
|
2290
2351
|
type,
|
|
@@ -2301,7 +2362,7 @@ function Input({ className, type, ...props }) {
|
|
|
2301
2362
|
}
|
|
2302
2363
|
|
|
2303
2364
|
// src/interactive/ReportSearch.tsx
|
|
2304
|
-
import { jsx as
|
|
2365
|
+
import { jsx as jsx45, jsxs as jsxs30 } from "react/jsx-runtime";
|
|
2305
2366
|
var ReportSearch = forwardRef(
|
|
2306
2367
|
function ReportSearch2(props, ref) {
|
|
2307
2368
|
const {
|
|
@@ -2323,17 +2384,17 @@ var ReportSearch = forwardRef(
|
|
|
2323
2384
|
e.preventDefault();
|
|
2324
2385
|
}
|
|
2325
2386
|
}
|
|
2326
|
-
return /* @__PURE__ */
|
|
2327
|
-
/* @__PURE__ */
|
|
2328
|
-
/* @__PURE__ */
|
|
2329
|
-
/* @__PURE__ */
|
|
2387
|
+
return /* @__PURE__ */ jsxs30("div", { className: cn("es-search flex flex-col gap-1", className), children: [
|
|
2388
|
+
/* @__PURE__ */ jsx45("label", { htmlFor: inputId, className: "sr-only", children: "Search" }),
|
|
2389
|
+
/* @__PURE__ */ jsxs30("div", { className: "relative w-full sm:w-72", children: [
|
|
2390
|
+
/* @__PURE__ */ jsx45(
|
|
2330
2391
|
Search,
|
|
2331
2392
|
{
|
|
2332
2393
|
"aria-hidden": true,
|
|
2333
2394
|
className: "pointer-events-none absolute top-1/2 left-2.5 size-4 -translate-y-1/2 text-muted-foreground"
|
|
2334
2395
|
}
|
|
2335
2396
|
),
|
|
2336
|
-
/* @__PURE__ */
|
|
2397
|
+
/* @__PURE__ */ jsx45(
|
|
2337
2398
|
Input,
|
|
2338
2399
|
{
|
|
2339
2400
|
ref,
|
|
@@ -2350,7 +2411,7 @@ var ReportSearch = forwardRef(
|
|
|
2350
2411
|
}
|
|
2351
2412
|
)
|
|
2352
2413
|
] }),
|
|
2353
|
-
showCounts ? /* @__PURE__ */
|
|
2414
|
+
showCounts ? /* @__PURE__ */ jsxs30(
|
|
2354
2415
|
"span",
|
|
2355
2416
|
{
|
|
2356
2417
|
className: "text-xs tabular-nums text-muted-foreground",
|
|
@@ -2424,7 +2485,7 @@ function Button({
|
|
|
2424
2485
|
}
|
|
2425
2486
|
|
|
2426
2487
|
// src/interactive/ReportShortcutsHelp.tsx
|
|
2427
|
-
import { jsx as
|
|
2488
|
+
import { jsx as jsx46, jsxs as jsxs31 } from "react/jsx-runtime";
|
|
2428
2489
|
var SHORTCUTS = [
|
|
2429
2490
|
{ keys: "/", description: "Focus search" },
|
|
2430
2491
|
{ keys: "f", description: "Jump to next failure" },
|
|
@@ -2436,9 +2497,9 @@ var SHORTCUTS = [
|
|
|
2436
2497
|
];
|
|
2437
2498
|
function Keys({ keys }) {
|
|
2438
2499
|
const parts = keys.split(" ");
|
|
2439
|
-
return /* @__PURE__ */
|
|
2440
|
-
i > 0 ? /* @__PURE__ */
|
|
2441
|
-
/* @__PURE__ */
|
|
2500
|
+
return /* @__PURE__ */ jsx46("span", { className: "inline-flex items-center gap-1", children: parts.map((k, i) => /* @__PURE__ */ jsxs31("span", { className: "inline-flex items-center gap-1", children: [
|
|
2501
|
+
i > 0 ? /* @__PURE__ */ jsx46("span", { className: "text-xs text-muted-foreground", children: "+" }) : null,
|
|
2502
|
+
/* @__PURE__ */ jsx46("kbd", { className: "inline-flex h-6 min-w-6 items-center justify-center rounded border border-border bg-muted px-1.5 font-mono text-xs font-medium text-muted-foreground", children: k })
|
|
2442
2503
|
] }, k)) });
|
|
2443
2504
|
}
|
|
2444
2505
|
function ReportShortcutsHelp({ open, onClose }) {
|
|
@@ -2449,7 +2510,7 @@ function ReportShortcutsHelp({ open, onClose }) {
|
|
|
2449
2510
|
if (open && !dialog.open) dialog.showModal();
|
|
2450
2511
|
else if (!open && dialog.open) dialog.close();
|
|
2451
2512
|
}, [open]);
|
|
2452
|
-
return /* @__PURE__ */
|
|
2513
|
+
return /* @__PURE__ */ jsxs31(
|
|
2453
2514
|
"dialog",
|
|
2454
2515
|
{
|
|
2455
2516
|
ref: dialogRef,
|
|
@@ -2457,12 +2518,12 @@ function ReportShortcutsHelp({ open, onClose }) {
|
|
|
2457
2518
|
"aria-label": "Keyboard shortcuts",
|
|
2458
2519
|
onClose,
|
|
2459
2520
|
children: [
|
|
2460
|
-
/* @__PURE__ */
|
|
2461
|
-
/* @__PURE__ */
|
|
2462
|
-
/* @__PURE__ */
|
|
2463
|
-
/* @__PURE__ */
|
|
2521
|
+
/* @__PURE__ */ jsx46("h2", { className: "text-base font-semibold", children: "Keyboard shortcuts" }),
|
|
2522
|
+
/* @__PURE__ */ jsx46("dl", { className: "mt-4 grid grid-cols-[auto_1fr] items-center gap-x-4 gap-y-2.5", children: SHORTCUTS.map((s) => /* @__PURE__ */ jsxs31("div", { className: "col-span-2 grid grid-cols-subgrid items-center", children: [
|
|
2523
|
+
/* @__PURE__ */ jsx46("dt", { className: "justify-self-start", children: /* @__PURE__ */ jsx46(Keys, { keys: s.keys }) }),
|
|
2524
|
+
/* @__PURE__ */ jsx46("dd", { className: "text-sm text-muted-foreground", children: s.description })
|
|
2464
2525
|
] }, s.keys)) }),
|
|
2465
|
-
/* @__PURE__ */
|
|
2526
|
+
/* @__PURE__ */ jsx46("form", { method: "dialog", className: "mt-6", children: /* @__PURE__ */ jsx46(Button, { type: "submit", variant: "outline", size: "sm", children: "Close" }) })
|
|
2466
2527
|
]
|
|
2467
2528
|
}
|
|
2468
2529
|
);
|
|
@@ -2470,7 +2531,7 @@ function ReportShortcutsHelp({ open, onClose }) {
|
|
|
2470
2531
|
|
|
2471
2532
|
// src/interactive/ReportToc.tsx
|
|
2472
2533
|
import { useEffect as useEffect4, useMemo as useMemo2, useState as useState5 } from "react";
|
|
2473
|
-
import { jsx as
|
|
2534
|
+
import { jsx as jsx47, jsxs as jsxs32 } from "react/jsx-runtime";
|
|
2474
2535
|
var DOT = {
|
|
2475
2536
|
passed: "bg-pass",
|
|
2476
2537
|
failed: "bg-fail",
|
|
@@ -2499,11 +2560,11 @@ function TocContent({ onNavigate }) {
|
|
|
2499
2560
|
return () => observer.disconnect();
|
|
2500
2561
|
}, [scenarioIds]);
|
|
2501
2562
|
if (report.features.length === 0) return null;
|
|
2502
|
-
return /* @__PURE__ */
|
|
2503
|
-
/* @__PURE__ */
|
|
2504
|
-
/* @__PURE__ */
|
|
2563
|
+
return /* @__PURE__ */ jsx47("ul", { className: "flex list-none flex-col gap-4 pl-0", children: report.features.map((feature) => /* @__PURE__ */ jsxs32("li", { children: [
|
|
2564
|
+
/* @__PURE__ */ jsx47("p", { className: "mb-1.5 font-semibold leading-snug text-foreground", children: feature.title }),
|
|
2565
|
+
/* @__PURE__ */ jsx47("ul", { className: "flex list-none flex-col gap-0.5 pl-0", children: feature.scenarios.map((scenario) => {
|
|
2505
2566
|
const active = activeId === scenario.id;
|
|
2506
|
-
return /* @__PURE__ */
|
|
2567
|
+
return /* @__PURE__ */ jsx47("li", { children: /* @__PURE__ */ jsxs32(
|
|
2507
2568
|
"a",
|
|
2508
2569
|
{
|
|
2509
2570
|
href: `#${scenario.id}`,
|
|
@@ -2518,14 +2579,14 @@ function TocContent({ onNavigate }) {
|
|
|
2518
2579
|
active ? "border-primary font-medium text-foreground" : "border-border text-muted-foreground"
|
|
2519
2580
|
),
|
|
2520
2581
|
children: [
|
|
2521
|
-
/* @__PURE__ */
|
|
2582
|
+
/* @__PURE__ */ jsx47(
|
|
2522
2583
|
"span",
|
|
2523
2584
|
{
|
|
2524
2585
|
"aria-hidden": true,
|
|
2525
2586
|
className: cn("mt-1 size-1.5 shrink-0 rounded-full", DOT[scenario.status])
|
|
2526
2587
|
}
|
|
2527
2588
|
),
|
|
2528
|
-
/* @__PURE__ */
|
|
2589
|
+
/* @__PURE__ */ jsx47("span", { className: "break-words", children: scenario.title })
|
|
2529
2590
|
]
|
|
2530
2591
|
}
|
|
2531
2592
|
) }, scenario.id);
|
|
@@ -2535,14 +2596,14 @@ function TocContent({ onNavigate }) {
|
|
|
2535
2596
|
function ReportToc() {
|
|
2536
2597
|
const report = useReport();
|
|
2537
2598
|
if (report.features.length === 0) return null;
|
|
2538
|
-
return /* @__PURE__ */
|
|
2599
|
+
return /* @__PURE__ */ jsxs32(
|
|
2539
2600
|
"nav",
|
|
2540
2601
|
{
|
|
2541
2602
|
"aria-label": "Table of contents",
|
|
2542
2603
|
className: "sticky top-4 hidden h-fit w-64 shrink-0 self-start text-xs lg:block",
|
|
2543
2604
|
children: [
|
|
2544
|
-
/* @__PURE__ */
|
|
2545
|
-
/* @__PURE__ */
|
|
2605
|
+
/* @__PURE__ */ jsx47("p", { className: "mb-3 text-xs font-semibold uppercase tracking-wide text-muted-foreground", children: "Contents" }),
|
|
2606
|
+
/* @__PURE__ */ jsx47(TocContent, {})
|
|
2546
2607
|
]
|
|
2547
2608
|
}
|
|
2548
2609
|
);
|
|
@@ -2552,31 +2613,31 @@ function ReportToc() {
|
|
|
2552
2613
|
import { useState as useState6 } from "react";
|
|
2553
2614
|
import { Dialog as DialogPrimitive } from "@base-ui/react/dialog";
|
|
2554
2615
|
import { ListIcon, XIcon } from "lucide-react";
|
|
2555
|
-
import { jsx as
|
|
2616
|
+
import { jsx as jsx48, jsxs as jsxs33 } from "react/jsx-runtime";
|
|
2556
2617
|
function ReportTocDrawer() {
|
|
2557
2618
|
const report = useReport();
|
|
2558
2619
|
const [open, setOpen] = useState6(false);
|
|
2559
2620
|
if (report.features.length === 0) return null;
|
|
2560
|
-
return /* @__PURE__ */
|
|
2561
|
-
/* @__PURE__ */
|
|
2562
|
-
/* @__PURE__ */
|
|
2621
|
+
return /* @__PURE__ */ jsxs33(DialogPrimitive.Root, { open, onOpenChange: setOpen, children: [
|
|
2622
|
+
/* @__PURE__ */ jsxs33(DialogPrimitive.Trigger, { className: "flex cursor-pointer items-center gap-1 rounded-md border border-border px-2 py-1 text-xs text-muted-foreground hover:bg-muted hover:text-foreground lg:hidden [&_svg]:size-3.5", children: [
|
|
2623
|
+
/* @__PURE__ */ jsx48(ListIcon, { "aria-hidden": true }),
|
|
2563
2624
|
" Contents"
|
|
2564
2625
|
] }),
|
|
2565
|
-
/* @__PURE__ */
|
|
2566
|
-
/* @__PURE__ */
|
|
2567
|
-
/* @__PURE__ */
|
|
2568
|
-
/* @__PURE__ */
|
|
2569
|
-
/* @__PURE__ */
|
|
2570
|
-
/* @__PURE__ */
|
|
2626
|
+
/* @__PURE__ */ jsxs33(DialogPrimitive.Portal, { children: [
|
|
2627
|
+
/* @__PURE__ */ jsx48(DialogPrimitive.Backdrop, { className: "fixed inset-0 z-50 bg-black/50 transition-opacity duration-200 data-[ending-style]:opacity-0 data-[starting-style]:opacity-0" }),
|
|
2628
|
+
/* @__PURE__ */ jsxs33(DialogPrimitive.Popup, { className: "fixed inset-y-0 left-0 z-50 flex w-72 max-w-[80vw] flex-col gap-3 overflow-y-auto border-r border-border bg-background p-4 font-sans text-xs shadow-lg outline-none transition-transform duration-200 data-[ending-style]:-translate-x-full data-[starting-style]:-translate-x-full", children: [
|
|
2629
|
+
/* @__PURE__ */ jsxs33("div", { className: "flex items-center justify-between", children: [
|
|
2630
|
+
/* @__PURE__ */ jsx48(DialogPrimitive.Title, { className: "text-xs font-semibold tracking-wide text-muted-foreground uppercase", children: "Contents" }),
|
|
2631
|
+
/* @__PURE__ */ jsx48(
|
|
2571
2632
|
DialogPrimitive.Close,
|
|
2572
2633
|
{
|
|
2573
2634
|
"aria-label": "Close contents",
|
|
2574
2635
|
className: "cursor-pointer rounded p-1 text-muted-foreground hover:bg-muted hover:text-foreground [&_svg]:size-4",
|
|
2575
|
-
children: /* @__PURE__ */
|
|
2636
|
+
children: /* @__PURE__ */ jsx48(XIcon, { "aria-hidden": true })
|
|
2576
2637
|
}
|
|
2577
2638
|
)
|
|
2578
2639
|
] }),
|
|
2579
|
-
/* @__PURE__ */
|
|
2640
|
+
/* @__PURE__ */ jsx48(TocContent, { onNavigate: () => setOpen(false) })
|
|
2580
2641
|
] })
|
|
2581
2642
|
] })
|
|
2582
2643
|
] });
|
|
@@ -2759,13 +2820,233 @@ function useUrlState() {
|
|
|
2759
2820
|
return [state, update];
|
|
2760
2821
|
}
|
|
2761
2822
|
|
|
2823
|
+
// src/interactive/webmcp-tools.ts
|
|
2824
|
+
import {
|
|
2825
|
+
getFeatureSummary,
|
|
2826
|
+
getScenario,
|
|
2827
|
+
listScenarioSummaries,
|
|
2828
|
+
runProvenance,
|
|
2829
|
+
toScenarioSummary
|
|
2830
|
+
} from "executable-stories-core/report-queries";
|
|
2831
|
+
var STATUSES2 = [
|
|
2832
|
+
"passed",
|
|
2833
|
+
"failed",
|
|
2834
|
+
"skipped",
|
|
2835
|
+
"pending"
|
|
2836
|
+
];
|
|
2837
|
+
var VIEW_STATUSES = ["all", ...STATUSES2];
|
|
2838
|
+
var ToolArgumentError = class extends Error {
|
|
2839
|
+
};
|
|
2840
|
+
function asRecord(input) {
|
|
2841
|
+
return typeof input === "object" && input !== null ? input : {};
|
|
2842
|
+
}
|
|
2843
|
+
function readString(input, key) {
|
|
2844
|
+
const value = input[key];
|
|
2845
|
+
if (value === void 0 || value === null) return void 0;
|
|
2846
|
+
if (typeof value !== "string") {
|
|
2847
|
+
throw new ToolArgumentError(`"${key}" must be a string, received ${typeof value}.`);
|
|
2848
|
+
}
|
|
2849
|
+
return value;
|
|
2850
|
+
}
|
|
2851
|
+
function readStringArray(input, key) {
|
|
2852
|
+
const value = input[key];
|
|
2853
|
+
if (value === void 0 || value === null) return void 0;
|
|
2854
|
+
if (typeof value === "string") return [value];
|
|
2855
|
+
if (!Array.isArray(value) || value.some((item) => typeof item !== "string")) {
|
|
2856
|
+
throw new ToolArgumentError(`"${key}" must be an array of strings.`);
|
|
2857
|
+
}
|
|
2858
|
+
return value;
|
|
2859
|
+
}
|
|
2860
|
+
function readEnum(input, key, allowed) {
|
|
2861
|
+
const value = readString(input, key);
|
|
2862
|
+
if (value === void 0) return void 0;
|
|
2863
|
+
if (!allowed.includes(value)) {
|
|
2864
|
+
throw new ToolArgumentError(
|
|
2865
|
+
`"${key}" must be one of: ${allowed.join(", ")}. Received "${value}".`
|
|
2866
|
+
);
|
|
2867
|
+
}
|
|
2868
|
+
return value;
|
|
2869
|
+
}
|
|
2870
|
+
function readStatuses(input) {
|
|
2871
|
+
const values = readStringArray(input, "statuses");
|
|
2872
|
+
if (values === void 0) return void 0;
|
|
2873
|
+
const invalid = values.filter((v) => !STATUSES2.includes(v));
|
|
2874
|
+
if (invalid.length > 0) {
|
|
2875
|
+
throw new ToolArgumentError(
|
|
2876
|
+
`"statuses" must contain only: ${STATUSES2.join(", ")}. Received "${invalid.join('", "')}".`
|
|
2877
|
+
);
|
|
2878
|
+
}
|
|
2879
|
+
return values;
|
|
2880
|
+
}
|
|
2881
|
+
function guarded(run) {
|
|
2882
|
+
try {
|
|
2883
|
+
return run();
|
|
2884
|
+
} catch (error) {
|
|
2885
|
+
if (error instanceof ToolArgumentError) return `Invalid input \u2014 ${error.message}`;
|
|
2886
|
+
throw error;
|
|
2887
|
+
}
|
|
2888
|
+
}
|
|
2889
|
+
var scenarioListSchema = {
|
|
2890
|
+
type: "object",
|
|
2891
|
+
properties: {
|
|
2892
|
+
statuses: {
|
|
2893
|
+
type: "array",
|
|
2894
|
+
items: { type: "string", enum: [...STATUSES2] },
|
|
2895
|
+
description: "Keep only scenarios with any of these statuses."
|
|
2896
|
+
},
|
|
2897
|
+
tags: {
|
|
2898
|
+
type: "array",
|
|
2899
|
+
items: { type: "string" },
|
|
2900
|
+
description: "Keep only scenarios carrying any of these tags."
|
|
2901
|
+
},
|
|
2902
|
+
sourceFiles: {
|
|
2903
|
+
type: "array",
|
|
2904
|
+
items: { type: "string" },
|
|
2905
|
+
description: "Keep only scenarios whose source file path contains any of these."
|
|
2906
|
+
}
|
|
2907
|
+
}
|
|
2908
|
+
};
|
|
2909
|
+
var READ_ONLY = { readOnlyHint: true, untrustedContentHint: true };
|
|
2910
|
+
function reportTools(deps) {
|
|
2911
|
+
const { report, setView, onAgentFilter } = deps;
|
|
2912
|
+
const now = deps.now ?? Date.now;
|
|
2913
|
+
const provenance = () => ({ run: runProvenance(report, now()) });
|
|
2914
|
+
const list = (filters) => {
|
|
2915
|
+
const scenarios = listScenarioSummaries(report, filters);
|
|
2916
|
+
return { ...provenance(), total: scenarios.length, scenarios };
|
|
2917
|
+
};
|
|
2918
|
+
return {
|
|
2919
|
+
list_scenarios: {
|
|
2920
|
+
title: "List scenarios",
|
|
2921
|
+
description: "List the behaviour scenarios in this report, optionally filtered by status, tag, or source file. Returns each scenario with its steps, tags, timing and failure message.",
|
|
2922
|
+
annotations: READ_ONLY,
|
|
2923
|
+
input: scenarioListSchema,
|
|
2924
|
+
execute: (input) => guarded(() => {
|
|
2925
|
+
const args = asRecord(input);
|
|
2926
|
+
const filters = {};
|
|
2927
|
+
const statuses = readStatuses(args);
|
|
2928
|
+
const tags = readStringArray(args, "tags");
|
|
2929
|
+
const sourceFiles = readStringArray(args, "sourceFiles");
|
|
2930
|
+
if (statuses) filters.statuses = statuses;
|
|
2931
|
+
if (tags) filters.tags = tags;
|
|
2932
|
+
if (sourceFiles) filters.sourceFiles = sourceFiles;
|
|
2933
|
+
return list(filters);
|
|
2934
|
+
})
|
|
2935
|
+
},
|
|
2936
|
+
get_failing_scenarios: {
|
|
2937
|
+
title: "Get failing scenarios",
|
|
2938
|
+
description: "List only the scenarios that failed in this run, each with the step that failed and its error message. Use this first when asked what is broken.",
|
|
2939
|
+
annotations: READ_ONLY,
|
|
2940
|
+
execute: () => list({ statuses: ["failed"] })
|
|
2941
|
+
},
|
|
2942
|
+
get_feature_summary: {
|
|
2943
|
+
title: "Get feature summary",
|
|
2944
|
+
description: 'Summarise each feature in the report with its scenario counts by status. Use this for "how are we doing" questions rather than listing every scenario.',
|
|
2945
|
+
annotations: READ_ONLY,
|
|
2946
|
+
execute: () => ({
|
|
2947
|
+
...provenance(),
|
|
2948
|
+
summary: report.summary,
|
|
2949
|
+
features: getFeatureSummary(report)
|
|
2950
|
+
})
|
|
2951
|
+
},
|
|
2952
|
+
get_scenario: {
|
|
2953
|
+
title: "Get scenario",
|
|
2954
|
+
description: "Get one scenario by its id or its exact title, with every step and any failure detail. Attachment and document bodies are omitted \u2014 `docKinds` names what the page shows.",
|
|
2955
|
+
annotations: READ_ONLY,
|
|
2956
|
+
input: {
|
|
2957
|
+
type: "object",
|
|
2958
|
+
properties: {
|
|
2959
|
+
idOrTitle: {
|
|
2960
|
+
type: "string",
|
|
2961
|
+
description: "The scenario id, or its exact title as shown in the report."
|
|
2962
|
+
}
|
|
2963
|
+
},
|
|
2964
|
+
required: ["idOrTitle"]
|
|
2965
|
+
},
|
|
2966
|
+
execute: (input) => guarded(() => {
|
|
2967
|
+
const idOrTitle = readString(asRecord(input), "idOrTitle") ?? "";
|
|
2968
|
+
const found = getScenario(report, idOrTitle);
|
|
2969
|
+
if (!found) {
|
|
2970
|
+
return {
|
|
2971
|
+
...provenance(),
|
|
2972
|
+
error: `No scenario found with id or title "${idOrTitle}". Call list_scenarios to see what this report contains.`
|
|
2973
|
+
};
|
|
2974
|
+
}
|
|
2975
|
+
return {
|
|
2976
|
+
...provenance(),
|
|
2977
|
+
feature: {
|
|
2978
|
+
id: found.feature.id,
|
|
2979
|
+
title: found.feature.title,
|
|
2980
|
+
sourceFile: found.feature.sourceFile
|
|
2981
|
+
},
|
|
2982
|
+
// The summary projection, not the raw scenario: doc entry bodies and
|
|
2983
|
+
// base64 attachments are unbounded, and this payload goes straight
|
|
2984
|
+
// into a model's context window.
|
|
2985
|
+
scenario: toScenarioSummary(found.feature, found.scenario)
|
|
2986
|
+
};
|
|
2987
|
+
})
|
|
2988
|
+
},
|
|
2989
|
+
filter_scenarios: {
|
|
2990
|
+
title: "Filter the report",
|
|
2991
|
+
description: `Change what the reader is looking at: set the report's search text, status filter and tag filter. Omitted fields are left as they are; pass an empty string, "all", or an empty array to clear one.`,
|
|
2992
|
+
input: {
|
|
2993
|
+
type: "object",
|
|
2994
|
+
properties: {
|
|
2995
|
+
search: {
|
|
2996
|
+
type: "string",
|
|
2997
|
+
description: "Free text matched against scenario titles, tags and step text. Empty string clears it."
|
|
2998
|
+
},
|
|
2999
|
+
status: {
|
|
3000
|
+
type: "string",
|
|
3001
|
+
enum: [...VIEW_STATUSES],
|
|
3002
|
+
description: 'Show only scenarios with this status. "all" clears the filter.'
|
|
3003
|
+
},
|
|
3004
|
+
tags: {
|
|
3005
|
+
type: "array",
|
|
3006
|
+
items: { type: "string" },
|
|
3007
|
+
description: "Show only scenarios carrying any of these tags. Empty array clears the filter."
|
|
3008
|
+
}
|
|
3009
|
+
}
|
|
3010
|
+
},
|
|
3011
|
+
execute: (input) => guarded(() => {
|
|
3012
|
+
const args = asRecord(input);
|
|
3013
|
+
const search = readString(args, "search");
|
|
3014
|
+
const status = readEnum(args, "status", VIEW_STATUSES);
|
|
3015
|
+
const tags = readStringArray(args, "tags");
|
|
3016
|
+
const applied = {
|
|
3017
|
+
search: search ?? deps.view.query,
|
|
3018
|
+
status: status ?? deps.view.status,
|
|
3019
|
+
tags: tags ?? deps.view.tags
|
|
3020
|
+
};
|
|
3021
|
+
const patch = {};
|
|
3022
|
+
if (search !== void 0) patch.query = search;
|
|
3023
|
+
if (status !== void 0) patch.status = status;
|
|
3024
|
+
if (tags !== void 0) patch.tags = tags;
|
|
3025
|
+
setView(patch);
|
|
3026
|
+
const matched = filterReport(report, {
|
|
3027
|
+
query: applied.search,
|
|
3028
|
+
status: applied.status,
|
|
3029
|
+
tags: applied.tags
|
|
3030
|
+
}).summary.total;
|
|
3031
|
+
const result = {
|
|
3032
|
+
...applied,
|
|
3033
|
+
matched,
|
|
3034
|
+
total: report.summary.total
|
|
3035
|
+
};
|
|
3036
|
+
onAgentFilter?.(result);
|
|
3037
|
+
return { ...provenance(), applied: result };
|
|
3038
|
+
})
|
|
3039
|
+
}
|
|
3040
|
+
};
|
|
3041
|
+
}
|
|
3042
|
+
|
|
2762
3043
|
// src/interactive/ReportInteractive.tsx
|
|
2763
|
-
import { Fragment as
|
|
3044
|
+
import { Fragment as Fragment14, jsx as jsx49, jsxs as jsxs34 } from "react/jsx-runtime";
|
|
2764
3045
|
function ReportInteractive(props) {
|
|
2765
3046
|
const { report, className, title, dataTheme } = props;
|
|
2766
3047
|
const result = unwrapReport(report);
|
|
2767
3048
|
if (!result.ok) {
|
|
2768
|
-
return /* @__PURE__ */
|
|
3049
|
+
return /* @__PURE__ */ jsx49(
|
|
2769
3050
|
ReportErrorShell,
|
|
2770
3051
|
{
|
|
2771
3052
|
error: result.error,
|
|
@@ -2775,7 +3056,7 @@ function ReportInteractive(props) {
|
|
|
2775
3056
|
}
|
|
2776
3057
|
);
|
|
2777
3058
|
}
|
|
2778
|
-
return /* @__PURE__ */
|
|
3059
|
+
return /* @__PURE__ */ jsx49(ReportInteractiveView, { ...props, report: result.data });
|
|
2779
3060
|
}
|
|
2780
3061
|
var THEME_OPTIONS = [
|
|
2781
3062
|
{ value: "light", label: "Light", Icon: Sun },
|
|
@@ -2786,7 +3067,7 @@ function ThemeSegment({
|
|
|
2786
3067
|
pref,
|
|
2787
3068
|
onPref
|
|
2788
3069
|
}) {
|
|
2789
|
-
return /* @__PURE__ */
|
|
3070
|
+
return /* @__PURE__ */ jsx49(
|
|
2790
3071
|
ToggleGroup,
|
|
2791
3072
|
{
|
|
2792
3073
|
size: "sm",
|
|
@@ -2796,14 +3077,14 @@ function ThemeSegment({
|
|
|
2796
3077
|
if (next) onPref(next);
|
|
2797
3078
|
},
|
|
2798
3079
|
"aria-label": "Color theme",
|
|
2799
|
-
children: THEME_OPTIONS.map(({ value, label, Icon }) => /* @__PURE__ */
|
|
3080
|
+
children: THEME_OPTIONS.map(({ value, label, Icon }) => /* @__PURE__ */ jsx49(
|
|
2800
3081
|
ToggleGroupItem,
|
|
2801
3082
|
{
|
|
2802
3083
|
value,
|
|
2803
3084
|
"aria-label": label,
|
|
2804
3085
|
title: label,
|
|
2805
3086
|
className: "px-2",
|
|
2806
|
-
children: /* @__PURE__ */
|
|
3087
|
+
children: /* @__PURE__ */ jsx49(Icon, {})
|
|
2807
3088
|
},
|
|
2808
3089
|
value
|
|
2809
3090
|
))
|
|
@@ -2932,6 +3213,20 @@ function ReportInteractiveView({
|
|
|
2932
3213
|
},
|
|
2933
3214
|
[collapse, collapseAll]
|
|
2934
3215
|
);
|
|
3216
|
+
const [agentFilter, setAgentFilter] = useState9(null);
|
|
3217
|
+
useTools(
|
|
3218
|
+
reportTools({
|
|
3219
|
+
report,
|
|
3220
|
+
view: urlState,
|
|
3221
|
+
setView: setUrlState,
|
|
3222
|
+
onAgentFilter: setAgentFilter
|
|
3223
|
+
})
|
|
3224
|
+
);
|
|
3225
|
+
const showAgentFilter = agentFilter !== null && agentFilter.search === query && agentFilter.status === statusFilter && agentFilter.tags.length === activeTags.length && agentFilter.tags.every((tag) => activeTags.includes(tag));
|
|
3226
|
+
const clearFilters = useCallback5(
|
|
3227
|
+
() => setUrlState({ query: "", status: "all", tags: [] }),
|
|
3228
|
+
[setUrlState]
|
|
3229
|
+
);
|
|
2935
3230
|
const focusSearch = useCallback5(() => {
|
|
2936
3231
|
searchRef.current?.focus();
|
|
2937
3232
|
}, []);
|
|
@@ -2965,13 +3260,13 @@ function ReportInteractiveView({
|
|
|
2965
3260
|
const totalScenarios = report.summary.total;
|
|
2966
3261
|
const matchedScenarios = filtered.summary.total;
|
|
2967
3262
|
const showToc = !hideToc && totalScenarios > 3;
|
|
2968
|
-
return /* @__PURE__ */
|
|
3263
|
+
return /* @__PURE__ */ jsx49(CollapseProvider, { value: visibleCollapse, children: /* @__PURE__ */ jsx49(ScenarioActionsProvider, { value: scenarioActions, children: /* @__PURE__ */ jsx49(ScenarioHistoryProvider, { value: scenarioHistory ?? null, children: /* @__PURE__ */ jsx49(ScenarioFreshnessProvider, { value: { staleAfterDays, report }, children: /* @__PURE__ */ jsx49(
|
|
2969
3264
|
ReportRoot,
|
|
2970
3265
|
{
|
|
2971
3266
|
report: filtered,
|
|
2972
3267
|
customRenderers,
|
|
2973
3268
|
renderers,
|
|
2974
|
-
children: /* @__PURE__ */
|
|
3269
|
+
children: /* @__PURE__ */ jsxs34(
|
|
2975
3270
|
"main",
|
|
2976
3271
|
{
|
|
2977
3272
|
className: cn("es-report", "es-report-interactive", className),
|
|
@@ -2980,8 +3275,8 @@ function ReportInteractiveView({
|
|
|
2980
3275
|
"data-theme": dataTheme,
|
|
2981
3276
|
"data-detail-level": detail,
|
|
2982
3277
|
children: [
|
|
2983
|
-
/* @__PURE__ */
|
|
2984
|
-
/* @__PURE__ */
|
|
3278
|
+
/* @__PURE__ */ jsxs34("header", { className: "es-report-header", children: [
|
|
3279
|
+
/* @__PURE__ */ jsxs34(
|
|
2985
3280
|
"div",
|
|
2986
3281
|
{
|
|
2987
3282
|
"data-es-navbar": true,
|
|
@@ -2990,9 +3285,9 @@ function ReportInteractiveView({
|
|
|
2990
3285
|
hideHeader ? "justify-end" : "justify-between"
|
|
2991
3286
|
),
|
|
2992
3287
|
children: [
|
|
2993
|
-
hideHeader ? null : /* @__PURE__ */
|
|
2994
|
-
/* @__PURE__ */
|
|
2995
|
-
/* @__PURE__ */
|
|
3288
|
+
hideHeader ? null : /* @__PURE__ */ jsx49("h1", { className: "min-w-0", children: title ?? "Story Report" }),
|
|
3289
|
+
/* @__PURE__ */ jsxs34("div", { className: "flex items-center gap-2", children: [
|
|
3290
|
+
/* @__PURE__ */ jsx49(
|
|
2996
3291
|
ReportSearch,
|
|
2997
3292
|
{
|
|
2998
3293
|
ref: searchRef,
|
|
@@ -3002,16 +3297,16 @@ function ReportInteractiveView({
|
|
|
3002
3297
|
totalCount: totalScenarios
|
|
3003
3298
|
}
|
|
3004
3299
|
),
|
|
3005
|
-
/* @__PURE__ */
|
|
3300
|
+
/* @__PURE__ */ jsx49(ThemeSegment, { pref: themePref, onPref: setThemePref })
|
|
3006
3301
|
] })
|
|
3007
3302
|
]
|
|
3008
3303
|
}
|
|
3009
3304
|
),
|
|
3010
|
-
hideHeader ? null : /* @__PURE__ */
|
|
3011
|
-
/* @__PURE__ */
|
|
3012
|
-
/* @__PURE__ */
|
|
3305
|
+
hideHeader ? null : /* @__PURE__ */ jsxs34(Fragment14, { children: [
|
|
3306
|
+
/* @__PURE__ */ jsx49(ReportSummary, {}),
|
|
3307
|
+
/* @__PURE__ */ jsx49(ReportMeta, {})
|
|
3013
3308
|
] }),
|
|
3014
|
-
/* @__PURE__ */
|
|
3309
|
+
/* @__PURE__ */ jsx49(
|
|
3015
3310
|
ReportFreshness,
|
|
3016
3311
|
{
|
|
3017
3312
|
lastRunMs: reportLastRunMs(report),
|
|
@@ -3019,14 +3314,14 @@ function ReportInteractiveView({
|
|
|
3019
3314
|
staleAfterDays
|
|
3020
3315
|
}
|
|
3021
3316
|
),
|
|
3022
|
-
/* @__PURE__ */
|
|
3317
|
+
/* @__PURE__ */ jsx49(
|
|
3023
3318
|
ReportLastRunDelta,
|
|
3024
3319
|
{
|
|
3025
3320
|
history: scenarioHistory,
|
|
3026
3321
|
report
|
|
3027
3322
|
}
|
|
3028
3323
|
),
|
|
3029
|
-
/* @__PURE__ */
|
|
3324
|
+
/* @__PURE__ */ jsx49(
|
|
3030
3325
|
ReportFilters,
|
|
3031
3326
|
{
|
|
3032
3327
|
statuses: statusOptions,
|
|
@@ -3037,10 +3332,10 @@ function ReportInteractiveView({
|
|
|
3037
3332
|
onToggleTag: toggleTag
|
|
3038
3333
|
}
|
|
3039
3334
|
),
|
|
3040
|
-
/* @__PURE__ */
|
|
3041
|
-
showToc ? /* @__PURE__ */
|
|
3042
|
-
/* @__PURE__ */
|
|
3043
|
-
/* @__PURE__ */
|
|
3335
|
+
/* @__PURE__ */ jsxs34("div", { className: "flex flex-wrap items-center gap-x-6 gap-y-2 border-t border-border/60 pt-3", children: [
|
|
3336
|
+
showToc ? /* @__PURE__ */ jsx49(ReportTocDrawer, {}) : null,
|
|
3337
|
+
/* @__PURE__ */ jsxs34("div", { className: "flex items-center gap-2", children: [
|
|
3338
|
+
/* @__PURE__ */ jsx49(
|
|
3044
3339
|
Switch,
|
|
3045
3340
|
{
|
|
3046
3341
|
id: expandId,
|
|
@@ -3048,7 +3343,7 @@ function ReportInteractiveView({
|
|
|
3048
3343
|
onCheckedChange: setExpanded
|
|
3049
3344
|
}
|
|
3050
3345
|
),
|
|
3051
|
-
/* @__PURE__ */
|
|
3346
|
+
/* @__PURE__ */ jsx49(
|
|
3052
3347
|
"label",
|
|
3053
3348
|
{
|
|
3054
3349
|
htmlFor: expandId,
|
|
@@ -3057,8 +3352,8 @@ function ReportInteractiveView({
|
|
|
3057
3352
|
}
|
|
3058
3353
|
)
|
|
3059
3354
|
] }),
|
|
3060
|
-
/* @__PURE__ */
|
|
3061
|
-
/* @__PURE__ */
|
|
3355
|
+
/* @__PURE__ */ jsxs34("div", { className: "flex items-center gap-2", children: [
|
|
3356
|
+
/* @__PURE__ */ jsx49(
|
|
3062
3357
|
Switch,
|
|
3063
3358
|
{
|
|
3064
3359
|
id: docsId,
|
|
@@ -3066,7 +3361,7 @@ function ReportInteractiveView({
|
|
|
3066
3361
|
onCheckedChange: (checked) => setDetail(checked ? "full" : "minimal")
|
|
3067
3362
|
}
|
|
3068
3363
|
),
|
|
3069
|
-
/* @__PURE__ */
|
|
3364
|
+
/* @__PURE__ */ jsx49(
|
|
3070
3365
|
"label",
|
|
3071
3366
|
{
|
|
3072
3367
|
htmlFor: docsId,
|
|
@@ -3077,17 +3372,25 @@ function ReportInteractiveView({
|
|
|
3077
3372
|
] })
|
|
3078
3373
|
] })
|
|
3079
3374
|
] }),
|
|
3080
|
-
/* @__PURE__ */
|
|
3081
|
-
|
|
3082
|
-
|
|
3083
|
-
|
|
3084
|
-
|
|
3375
|
+
showAgentFilter ? /* @__PURE__ */ jsx49(
|
|
3376
|
+
ReportAgentFilterNotice,
|
|
3377
|
+
{
|
|
3378
|
+
applied: agentFilter,
|
|
3379
|
+
onReset: clearFilters,
|
|
3380
|
+
onDismiss: () => setAgentFilter(null)
|
|
3381
|
+
}
|
|
3382
|
+
) : null,
|
|
3383
|
+
/* @__PURE__ */ jsx49(ReportFailureBanner, { failures }),
|
|
3384
|
+
hasContent ? showToc ? /* @__PURE__ */ jsxs34("div", { className: "flex gap-6", children: [
|
|
3385
|
+
/* @__PURE__ */ jsx49(ReportToc, {}),
|
|
3386
|
+
/* @__PURE__ */ jsx49("div", { className: "flex min-w-0 flex-1 flex-col gap-4", children: /* @__PURE__ */ jsx49(ReportFeatureList, {}) })
|
|
3387
|
+
] }) : /* @__PURE__ */ jsx49("div", { className: "flex flex-col gap-4", children: /* @__PURE__ */ jsx49(ReportFeatureList, {}) }) : /* @__PURE__ */ jsx49(
|
|
3085
3388
|
ReportEmpty,
|
|
3086
3389
|
{
|
|
3087
3390
|
message: query ? "No scenarios match the search." : void 0
|
|
3088
3391
|
}
|
|
3089
3392
|
),
|
|
3090
|
-
/* @__PURE__ */
|
|
3393
|
+
/* @__PURE__ */ jsx49(
|
|
3091
3394
|
"button",
|
|
3092
3395
|
{
|
|
3093
3396
|
type: "button",
|
|
@@ -3098,14 +3401,14 @@ function ReportInteractiveView({
|
|
|
3098
3401
|
children: "?"
|
|
3099
3402
|
}
|
|
3100
3403
|
),
|
|
3101
|
-
/* @__PURE__ */
|
|
3404
|
+
/* @__PURE__ */ jsx49(
|
|
3102
3405
|
ReportShortcutsHelp,
|
|
3103
3406
|
{
|
|
3104
3407
|
open: helpOpen,
|
|
3105
3408
|
onClose: () => setHelpOpen(false)
|
|
3106
3409
|
}
|
|
3107
3410
|
),
|
|
3108
|
-
toast ? /* @__PURE__ */
|
|
3411
|
+
toast ? /* @__PURE__ */ jsx49(
|
|
3109
3412
|
"div",
|
|
3110
3413
|
{
|
|
3111
3414
|
role: "status",
|
|
@@ -3129,7 +3432,7 @@ import { createElement, useEffect as useEffect10, useState as useState11 } from
|
|
|
3129
3432
|
|
|
3130
3433
|
// src/components/doc/MermaidView.tsx
|
|
3131
3434
|
import { useEffect as useEffect9, useRef as useRef6, useState as useState10 } from "react";
|
|
3132
|
-
import { Fragment as
|
|
3435
|
+
import { Fragment as Fragment15, jsx as jsx50, jsxs as jsxs35 } from "react/jsx-runtime";
|
|
3133
3436
|
function prefersDark(el) {
|
|
3134
3437
|
const themed = el?.closest("[data-theme]");
|
|
3135
3438
|
if (themed?.dataset.theme === "dark") return true;
|
|
@@ -3183,9 +3486,9 @@ function MermaidView({ entry, load }) {
|
|
|
3183
3486
|
};
|
|
3184
3487
|
}, [entry.code, load]);
|
|
3185
3488
|
if (svg) {
|
|
3186
|
-
return /* @__PURE__ */
|
|
3187
|
-
entry.title ? /* @__PURE__ */
|
|
3188
|
-
/* @__PURE__ */
|
|
3489
|
+
return /* @__PURE__ */ jsxs35("figure", { ref, className: "my-3", children: [
|
|
3490
|
+
entry.title ? /* @__PURE__ */ jsx50("figcaption", { className: "mb-1.5 text-xs font-medium text-muted-foreground", children: entry.title }) : null,
|
|
3491
|
+
/* @__PURE__ */ jsx50(
|
|
3189
3492
|
"div",
|
|
3190
3493
|
{
|
|
3191
3494
|
role: "img",
|
|
@@ -3196,8 +3499,8 @@ function MermaidView({ entry, load }) {
|
|
|
3196
3499
|
)
|
|
3197
3500
|
] });
|
|
3198
3501
|
}
|
|
3199
|
-
return /* @__PURE__ */
|
|
3200
|
-
error ? /* @__PURE__ */
|
|
3502
|
+
return /* @__PURE__ */ jsxs35(Fragment15, { children: [
|
|
3503
|
+
error ? /* @__PURE__ */ jsxs35(
|
|
3201
3504
|
"p",
|
|
3202
3505
|
{
|
|
3203
3506
|
role: "alert",
|
|
@@ -3209,12 +3512,12 @@ function MermaidView({ entry, load }) {
|
|
|
3209
3512
|
]
|
|
3210
3513
|
}
|
|
3211
3514
|
) : null,
|
|
3212
|
-
/* @__PURE__ */
|
|
3515
|
+
/* @__PURE__ */ jsx50(MermaidSource, { entry, ref })
|
|
3213
3516
|
] });
|
|
3214
3517
|
}
|
|
3215
3518
|
|
|
3216
3519
|
// src/interactive/island-renderers.tsx
|
|
3217
|
-
import { jsx as
|
|
3520
|
+
import { jsx as jsx51 } from "react/jsx-runtime";
|
|
3218
3521
|
var HLJS_ESM = "https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/es/highlight.min.js";
|
|
3219
3522
|
var MERMAID_ESM = "https://cdn.jsdelivr.net/npm/mermaid@10/dist/mermaid.esm.min.mjs";
|
|
3220
3523
|
function cachedCdnModule(url) {
|
|
@@ -3248,13 +3551,13 @@ function CdnHighlightedCode({ entry }) {
|
|
|
3248
3551
|
cancelled = true;
|
|
3249
3552
|
};
|
|
3250
3553
|
}, [entry.content, entry.lang]);
|
|
3251
|
-
return /* @__PURE__ */
|
|
3554
|
+
return /* @__PURE__ */ jsx51(CodeFigure, { label: entry.label, children: html !== null ? /* @__PURE__ */ jsx51(
|
|
3252
3555
|
"code",
|
|
3253
3556
|
{
|
|
3254
3557
|
className: cn("hljs font-mono text-xs", entry.lang && `language-${entry.lang}`),
|
|
3255
3558
|
dangerouslySetInnerHTML: { __html: html }
|
|
3256
3559
|
}
|
|
3257
|
-
) : /* @__PURE__ */
|
|
3560
|
+
) : /* @__PURE__ */ jsx51("code", { className: cn("font-mono text-xs", entry.lang && `language-${entry.lang}`), children: entry.content }) });
|
|
3258
3561
|
}
|
|
3259
3562
|
function buildIslandRenderers(opts) {
|
|
3260
3563
|
const renderers = {};
|
|
@@ -3268,7 +3571,7 @@ function buildIslandRenderers(opts) {
|
|
|
3268
3571
|
}
|
|
3269
3572
|
|
|
3270
3573
|
// src/interactive/ReportInteractiveIsland.tsx
|
|
3271
|
-
import { jsx as
|
|
3574
|
+
import { jsx as jsx52 } from "react/jsx-runtime";
|
|
3272
3575
|
function ReportInteractiveIsland({
|
|
3273
3576
|
report,
|
|
3274
3577
|
title,
|
|
@@ -3282,7 +3585,7 @@ function ReportInteractiveIsland({
|
|
|
3282
3585
|
() => buildIslandRenderers({ syntaxHighlighting, mermaid }),
|
|
3283
3586
|
[syntaxHighlighting, mermaid]
|
|
3284
3587
|
);
|
|
3285
|
-
return /* @__PURE__ */
|
|
3588
|
+
return /* @__PURE__ */ jsx52(
|
|
3286
3589
|
ReportInteractive,
|
|
3287
3590
|
{
|
|
3288
3591
|
report,
|