@sentry/junior-dashboard 0.60.0 → 0.61.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/client/format.d.ts +16 -2
- package/dist/client/types.d.ts +1 -0
- package/dist/client.js +147 -53
- package/dist/tailwind.css +1 -1
- package/package.json +2 -2
- package/src/client/code.tsx +19 -5
- package/src/client/components/ConversationRowStats.tsx +24 -4
- package/src/client/components/TranscriptText.tsx +1 -1
- package/src/client/components/TranscriptTurn.tsx +34 -14
- package/src/client/format.ts +106 -25
- package/src/client/pages/ConversationPage.tsx +7 -0
- package/src/client/types.ts +1 -1
package/dist/client/format.d.ts
CHANGED
|
@@ -10,6 +10,8 @@ export declare function formatTime(value: string | undefined): string;
|
|
|
10
10
|
export declare function formatRelativeTime(value: string | undefined): string;
|
|
11
11
|
/** Format millisecond durations for compact transcript metadata. */
|
|
12
12
|
export declare function formatMs(value: number | undefined): string;
|
|
13
|
+
/** Format aggregate runtime across turn summaries when duration data exists. */
|
|
14
|
+
export declare function formatDurationTotal(durations: Array<number | undefined>): string;
|
|
13
15
|
/** Format transcript event timestamps independently from turn start offsets. */
|
|
14
16
|
export declare function formatMessageTimestamp(value: number | undefined): string;
|
|
15
17
|
/** Format a transcript event as an offset from the current turn start. */
|
|
@@ -22,6 +24,8 @@ export declare function turnMessageCount(turn: ConversationTurn): number;
|
|
|
22
24
|
export declare function turnToolCallCount(turn: ConversationTurn): number;
|
|
23
25
|
/** Format known token counters without estimating per-message usage. */
|
|
24
26
|
export declare function formatTokenTotal(usage: TurnUsage | undefined): string;
|
|
27
|
+
/** Format the aggregate token count across conversation turns. */
|
|
28
|
+
export declare function formatUsageTotal(usages: Array<TurnUsage | undefined>): string;
|
|
25
29
|
/** Format known token counters with available input/output detail. */
|
|
26
30
|
export declare function formatUsage(usage: TurnUsage | undefined): string;
|
|
27
31
|
/** Format a conversation span from first turn start to latest activity. */
|
|
@@ -48,8 +52,18 @@ export declare function unavailableTranscriptLabel(turn: ConversationTurn): stri
|
|
|
48
52
|
export declare function conversationPath(conversationId: string): string;
|
|
49
53
|
/** Detect the syntax highlighter language for raw transcript blocks. */
|
|
50
54
|
export declare function detectLanguage(text: string): BundledLanguage;
|
|
51
|
-
/**
|
|
52
|
-
|
|
55
|
+
/**
|
|
56
|
+
* Detect the language for LLM text output prose: json if the text is valid
|
|
57
|
+
* JSON or JSONL, markdown otherwise. Never auto-detects XML, HTML, TypeScript,
|
|
58
|
+
* or shell — those heuristics are unreliable for rendered assistant output.
|
|
59
|
+
*/
|
|
60
|
+
export declare function detectOutputLanguage(text: string): BundledLanguage;
|
|
61
|
+
/**
|
|
62
|
+
* Decide whether a fenced block can use the interactive markup renderer.
|
|
63
|
+
* Structured XML/HTML rendering is only enabled for explicitly-fenced blocks;
|
|
64
|
+
* auto-detected prose is never eligible regardless of inferred language.
|
|
65
|
+
*/
|
|
66
|
+
export declare function canRenderStructuredMarkup(block: CodeBlock): boolean;
|
|
53
67
|
/** Parse markdown into renderable code blocks while preserving plain text blocks. */
|
|
54
68
|
export declare function parseMarkdownBlocks(text: string): CodeBlock[];
|
|
55
69
|
/** Parse XML/HTML-ish fragments for the collapsible transcript renderer. */
|
package/dist/client/types.d.ts
CHANGED
|
@@ -140,6 +140,7 @@ export type SessionFilter = "active" | "recent" | "hung" | "failed" | "all";
|
|
|
140
140
|
export type VisualStatus = "active" | "failed" | "hung" | "idle";
|
|
141
141
|
export type CodeBlock = {
|
|
142
142
|
code: string;
|
|
143
|
+
fenced?: boolean;
|
|
143
144
|
language: BundledLanguage;
|
|
144
145
|
};
|
|
145
146
|
export type MarkupNode = {
|
package/dist/client.js
CHANGED
|
@@ -15891,12 +15891,12 @@ var require_use_sync_external_store_shim_production = __commonJS({
|
|
|
15891
15891
|
return x2 === y2 && (0 !== x2 || 1 / x2 === 1 / y2) || x2 !== x2 && y2 !== y2;
|
|
15892
15892
|
}
|
|
15893
15893
|
var objectIs = "function" === typeof Object.is ? Object.is : is4;
|
|
15894
|
-
var
|
|
15894
|
+
var useState23 = React53.useState;
|
|
15895
15895
|
var useEffect27 = React53.useEffect;
|
|
15896
15896
|
var useLayoutEffect12 = React53.useLayoutEffect;
|
|
15897
15897
|
var useDebugValue2 = React53.useDebugValue;
|
|
15898
15898
|
function useSyncExternalStore$2(subscribe, getSnapshot) {
|
|
15899
|
-
var value = getSnapshot(), _useState =
|
|
15899
|
+
var value = getSnapshot(), _useState = useState23({ inst: { value, getSnapshot } }), inst = _useState[0].inst, forceUpdate = _useState[1];
|
|
15900
15900
|
useLayoutEffect12(
|
|
15901
15901
|
function() {
|
|
15902
15902
|
inst.value = value;
|
|
@@ -19462,7 +19462,7 @@ function useQuery(options, queryClient) {
|
|
|
19462
19462
|
}
|
|
19463
19463
|
|
|
19464
19464
|
// src/client.tsx
|
|
19465
|
-
var
|
|
19465
|
+
var import_react53 = __toESM(require_react(), 1);
|
|
19466
19466
|
var import_client = __toESM(require_client(), 1);
|
|
19467
19467
|
|
|
19468
19468
|
// ../../node_modules/.pnpm/react-router@7.16.0_react-dom@19.2.6_react@19.2.6__react@19.2.6/node_modules/react-router/dist/development/chunk-QUQL4437.mjs
|
|
@@ -30771,6 +30771,13 @@ function formatMs(value) {
|
|
|
30771
30771
|
const remainingSeconds = Math.round(seconds2 % 60);
|
|
30772
30772
|
return `${minutes}m ${remainingSeconds}s`;
|
|
30773
30773
|
}
|
|
30774
|
+
function formatDurationTotal(durations) {
|
|
30775
|
+
const total = durations.reduce((sum, value) => {
|
|
30776
|
+
if (typeof value !== "number" || !Number.isFinite(value)) return sum;
|
|
30777
|
+
return (sum ?? 0) + Math.max(0, Math.floor(value));
|
|
30778
|
+
}, void 0);
|
|
30779
|
+
return total === void 0 ? "" : formatMs(total);
|
|
30780
|
+
}
|
|
30774
30781
|
function formatMessageTimestamp(value) {
|
|
30775
30782
|
if (typeof value !== "number" || !Number.isFinite(value))
|
|
30776
30783
|
return "no timestamp";
|
|
@@ -30798,6 +30805,21 @@ function formatNumber(value) {
|
|
|
30798
30805
|
const formatted = scaled >= 100 || Number.isInteger(scaled) ? Math.round(scaled).toString() : scaled >= 10 ? Math.round(scaled).toString() : (Math.floor(scaled * 10) / 10).toFixed(1).replace(/\.0$/, "");
|
|
30799
30806
|
return `${formatted}${suffix2}`;
|
|
30800
30807
|
}
|
|
30808
|
+
function getFiniteTokenCount(value) {
|
|
30809
|
+
return typeof value === "number" && Number.isFinite(value) ? Math.max(0, Math.floor(value)) : void 0;
|
|
30810
|
+
}
|
|
30811
|
+
function getUsageComponentTotal(usage) {
|
|
30812
|
+
return [
|
|
30813
|
+
usage.inputTokens,
|
|
30814
|
+
usage.outputTokens,
|
|
30815
|
+
usage.cachedInputTokens,
|
|
30816
|
+
usage.cacheCreationTokens
|
|
30817
|
+
].reduce((sum, value) => {
|
|
30818
|
+
const count = getFiniteTokenCount(value);
|
|
30819
|
+
if (count === void 0) return sum;
|
|
30820
|
+
return (sum ?? 0) + count;
|
|
30821
|
+
}, void 0);
|
|
30822
|
+
}
|
|
30801
30823
|
function formatBytes(value) {
|
|
30802
30824
|
if (typeof value !== "number" || !Number.isFinite(value)) return "0b";
|
|
30803
30825
|
const bytes = Math.max(0, Math.floor(value));
|
|
@@ -30814,8 +30836,28 @@ function formatBytes(value) {
|
|
|
30814
30836
|
function transcriptSource(turn) {
|
|
30815
30837
|
return turn.transcriptAvailable ? turn.transcript : turn.transcriptMetadata ?? [];
|
|
30816
30838
|
}
|
|
30839
|
+
function isConversationMessageRole(role) {
|
|
30840
|
+
const normalized = role.toLowerCase();
|
|
30841
|
+
return normalized === "user" || normalized === "assistant";
|
|
30842
|
+
}
|
|
30843
|
+
function hasTextPart(message) {
|
|
30844
|
+
return message.parts.some((part) => {
|
|
30845
|
+
if (part.type !== "text") return false;
|
|
30846
|
+
if (part.redacted) return true;
|
|
30847
|
+
return typeof part.text === "string" && part.text.trim().length > 0;
|
|
30848
|
+
});
|
|
30849
|
+
}
|
|
30850
|
+
function isConversationMessage(message) {
|
|
30851
|
+
if (!isConversationMessageRole(message.role)) return false;
|
|
30852
|
+
if (message.role.toLowerCase() === "assistant") return hasTextPart(message);
|
|
30853
|
+
return message.parts.length > 0;
|
|
30854
|
+
}
|
|
30817
30855
|
function turnMessageCount(turn) {
|
|
30818
|
-
|
|
30856
|
+
const source = transcriptSource(turn);
|
|
30857
|
+
if (source.length > 0) {
|
|
30858
|
+
return source.filter(isConversationMessage).length;
|
|
30859
|
+
}
|
|
30860
|
+
return turn.transcriptMessageCount ?? 0;
|
|
30819
30861
|
}
|
|
30820
30862
|
function turnToolCallCount(turn) {
|
|
30821
30863
|
return transcriptSource(turn).reduce((count, message) => {
|
|
@@ -30824,23 +30866,20 @@ function turnToolCallCount(turn) {
|
|
|
30824
30866
|
}
|
|
30825
30867
|
function totalUsageTokens(usage) {
|
|
30826
30868
|
if (!usage) return void 0;
|
|
30827
|
-
|
|
30828
|
-
return usage.totalTokens;
|
|
30829
|
-
}
|
|
30830
|
-
return [
|
|
30831
|
-
usage.inputTokens,
|
|
30832
|
-
usage.outputTokens,
|
|
30833
|
-
usage.cachedInputTokens,
|
|
30834
|
-
usage.cacheCreationTokens
|
|
30835
|
-
].reduce((sum, value) => {
|
|
30836
|
-
if (typeof value !== "number" || !Number.isFinite(value)) return sum;
|
|
30837
|
-
return (sum ?? 0) + Math.max(0, Math.floor(value));
|
|
30838
|
-
}, void 0);
|
|
30869
|
+
return getUsageComponentTotal(usage) ?? getFiniteTokenCount(usage.totalTokens);
|
|
30839
30870
|
}
|
|
30840
30871
|
function formatTokenTotal(usage) {
|
|
30841
30872
|
const total = totalUsageTokens(usage);
|
|
30842
30873
|
return total === void 0 ? "" : `${formatNumber(total)} tokens`;
|
|
30843
30874
|
}
|
|
30875
|
+
function formatUsageTotal(usages) {
|
|
30876
|
+
const total = usages.reduce((sum, usage) => {
|
|
30877
|
+
const tokens = totalUsageTokens(usage);
|
|
30878
|
+
if (tokens === void 0) return sum;
|
|
30879
|
+
return (sum ?? 0) + tokens;
|
|
30880
|
+
}, void 0);
|
|
30881
|
+
return total === void 0 ? "" : `${formatNumber(total)} tokens`;
|
|
30882
|
+
}
|
|
30844
30883
|
function formatUsage(usage) {
|
|
30845
30884
|
const total = totalUsageTokens(usage);
|
|
30846
30885
|
if (total === void 0) return "";
|
|
@@ -31006,8 +31045,19 @@ function prettyJsonData(text2) {
|
|
|
31006
31045
|
function formatCodeBlock(code, language) {
|
|
31007
31046
|
return language === "json" ? prettyJsonData(code) ?? code : code;
|
|
31008
31047
|
}
|
|
31009
|
-
function
|
|
31010
|
-
|
|
31048
|
+
function detectOutputLanguage(text2) {
|
|
31049
|
+
const trimmed = text2.trim();
|
|
31050
|
+
if (!trimmed) return "markdown";
|
|
31051
|
+
try {
|
|
31052
|
+
JSON.parse(trimmed);
|
|
31053
|
+
return "json";
|
|
31054
|
+
} catch {
|
|
31055
|
+
}
|
|
31056
|
+
if (prettyJsonl(trimmed)) return "json";
|
|
31057
|
+
return "markdown";
|
|
31058
|
+
}
|
|
31059
|
+
function canRenderStructuredMarkup(block) {
|
|
31060
|
+
return block.fenced === true && (block.language === "xml" || block.language === "html");
|
|
31011
31061
|
}
|
|
31012
31062
|
function parseMarkdownBlocks(text2) {
|
|
31013
31063
|
const blocks = [];
|
|
@@ -31017,24 +31067,25 @@ function parseMarkdownBlocks(text2) {
|
|
|
31017
31067
|
while (match = fence.exec(text2)) {
|
|
31018
31068
|
const prose = text2.slice(cursor, match.index).trim();
|
|
31019
31069
|
if (prose) {
|
|
31020
|
-
const language3 =
|
|
31021
|
-
blocks.push({ code: formatCodeBlock(prose, language3), language: language3 });
|
|
31070
|
+
const language3 = detectOutputLanguage(prose);
|
|
31071
|
+
blocks.push({ code: formatCodeBlock(prose, language3), fenced: false, language: language3 });
|
|
31022
31072
|
}
|
|
31023
31073
|
const language2 = normalizeLanguage(match[1]);
|
|
31024
31074
|
blocks.push({
|
|
31025
31075
|
code: formatCodeBlock(match[2] ?? "", language2),
|
|
31076
|
+
fenced: true,
|
|
31026
31077
|
language: language2
|
|
31027
31078
|
});
|
|
31028
31079
|
cursor = match.index + match[0].length;
|
|
31029
31080
|
}
|
|
31030
31081
|
const rest = text2.slice(cursor).trim();
|
|
31031
31082
|
if (rest) {
|
|
31032
|
-
const language2 =
|
|
31033
|
-
blocks.push({ code: formatCodeBlock(rest, language2), language: language2 });
|
|
31083
|
+
const language2 = detectOutputLanguage(rest);
|
|
31084
|
+
blocks.push({ code: formatCodeBlock(rest, language2), fenced: false, language: language2 });
|
|
31034
31085
|
}
|
|
31035
31086
|
if (blocks.length > 0) return blocks;
|
|
31036
|
-
const language =
|
|
31037
|
-
return [{ code: formatCodeBlock(text2, language), language }];
|
|
31087
|
+
const language = detectOutputLanguage(text2);
|
|
31088
|
+
return [{ code: formatCodeBlock(text2, language), fenced: false, language }];
|
|
31038
31089
|
}
|
|
31039
31090
|
function parseMarkupNodes(code, language) {
|
|
31040
31091
|
const parser = new DOMParser();
|
|
@@ -31250,13 +31301,24 @@ function Stat(props) {
|
|
|
31250
31301
|
// src/client/components/ConversationRowStats.tsx
|
|
31251
31302
|
var import_jsx_runtime10 = __toESM(require_jsx_runtime(), 1);
|
|
31252
31303
|
function ConversationRowStats(props) {
|
|
31304
|
+
const tokens = formatUsageTotal(
|
|
31305
|
+
props.conversation.turns.map((turn) => turn.cumulativeUsage)
|
|
31306
|
+
);
|
|
31307
|
+
const runtime = formatDurationTotal(
|
|
31308
|
+
props.conversation.turns.map((turn) => turn.cumulativeDurationMs)
|
|
31309
|
+
);
|
|
31310
|
+
const primaryStats = [
|
|
31311
|
+
`${props.conversation.turns.length} turns`,
|
|
31312
|
+
tokens,
|
|
31313
|
+
runtime ? `${runtime} runtime` : void 0
|
|
31314
|
+
].filter(Boolean);
|
|
31315
|
+
const secondaryStats = [
|
|
31316
|
+
props.timeLabel,
|
|
31317
|
+
slackLocationLabel(props.conversation, { includeId: false })
|
|
31318
|
+
].filter(Boolean);
|
|
31253
31319
|
return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "grid min-w-0 justify-items-end gap-1 text-right max-md:justify-items-start max-md:text-left", children: [
|
|
31254
|
-
/* @__PURE__ */ (0, import_jsx_runtime10.
|
|
31255
|
-
|
|
31256
|
-
" turns \xB7 ",
|
|
31257
|
-
props.timeLabel
|
|
31258
|
-
] }),
|
|
31259
|
-
props.conversation.channel ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "max-w-full break-words text-[0.84rem] leading-relaxed text-[#888] md:truncate", children: slackLocationLabel(props.conversation, { includeId: false }) }) : null
|
|
31320
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "text-[0.84rem] leading-relaxed text-[#b8b8b8]", children: primaryStats.join(" \xB7 ") }),
|
|
31321
|
+
secondaryStats.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "max-w-full break-words text-[0.84rem] leading-relaxed text-[#888] md:truncate", children: secondaryStats.join(" \xB7 ") }) : null
|
|
31260
31322
|
] });
|
|
31261
31323
|
}
|
|
31262
31324
|
|
|
@@ -54640,7 +54702,7 @@ function CommandCenter(props) {
|
|
|
54640
54702
|
}
|
|
54641
54703
|
|
|
54642
54704
|
// src/client/components/Transcript.tsx
|
|
54643
|
-
var
|
|
54705
|
+
var import_react52 = __toESM(require_react(), 1);
|
|
54644
54706
|
|
|
54645
54707
|
// src/client/components/TranscriptHeader.tsx
|
|
54646
54708
|
var import_jsx_runtime16 = __toESM(require_jsx_runtime(), 1);
|
|
@@ -54674,10 +54736,14 @@ function TranscriptViewToggle(props) {
|
|
|
54674
54736
|
);
|
|
54675
54737
|
}
|
|
54676
54738
|
|
|
54739
|
+
// src/client/components/TranscriptTurn.tsx
|
|
54740
|
+
var import_react51 = __toESM(require_react(), 1);
|
|
54741
|
+
|
|
54677
54742
|
// src/client/code.tsx
|
|
54743
|
+
var import_react50 = __toESM(require_react(), 1);
|
|
54678
54744
|
var import_jsx_runtime17 = __toESM(require_jsx_runtime(), 1);
|
|
54679
54745
|
function countStructuredBlockChildren(block) {
|
|
54680
|
-
if (!canRenderStructuredMarkup(block
|
|
54746
|
+
if (!canRenderStructuredMarkup(block)) return 1;
|
|
54681
54747
|
const rootCount = parseMarkupNodes(block.code, block.language).length;
|
|
54682
54748
|
return rootCount > 0 ? rootCount : 1;
|
|
54683
54749
|
}
|
|
@@ -54711,8 +54777,12 @@ function MarkupNodeView(props) {
|
|
|
54711
54777
|
if (props.node.type === "text") {
|
|
54712
54778
|
return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("div", { className: "min-w-0 whitespace-pre-wrap break-words text-white", children: props.node.text.trim() });
|
|
54713
54779
|
}
|
|
54780
|
+
return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(MarkupElementView, { defaultOpen: props.defaultOpen, node: props.node });
|
|
54781
|
+
}
|
|
54782
|
+
function MarkupElementView(props) {
|
|
54714
54783
|
const children = props.node.children;
|
|
54715
54784
|
const hasChildren = children.length > 0;
|
|
54785
|
+
const [open, setOpen] = (0, import_react50.useState)(props.defaultOpen ?? true);
|
|
54716
54786
|
const attributes = props.node.attributes.map(([name, value]) => /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("span", { className: "ml-1.5 text-[#b8b8b8]", children: [
|
|
54717
54787
|
name,
|
|
54718
54788
|
"=",
|
|
@@ -54733,12 +54803,15 @@ function MarkupNodeView(props) {
|
|
|
54733
54803
|
return /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(
|
|
54734
54804
|
"details",
|
|
54735
54805
|
{
|
|
54736
|
-
className: "
|
|
54737
|
-
|
|
54806
|
+
className: "min-w-0 break-words",
|
|
54807
|
+
onToggle: (event) => {
|
|
54808
|
+
if (event.currentTarget !== event.target) return;
|
|
54809
|
+
setOpen(event.currentTarget.open);
|
|
54810
|
+
},
|
|
54811
|
+
open,
|
|
54738
54812
|
children: [
|
|
54739
54813
|
/* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("summary", { className: "-ml-1 flex w-full max-w-full cursor-pointer list-none flex-wrap items-baseline px-1 py-0.5 transition-colors hover:bg-white/[0.05] hover:text-white [&::-webkit-details-marker]:hidden", children: [
|
|
54740
|
-
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { className: "mr-1 w-2 text-white
|
|
54741
|
-
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { className: "mr-1 hidden w-2 text-white group-open:inline", children: "-" }),
|
|
54814
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { className: "mr-1 w-2 text-white", children: open ? "-" : "+" }),
|
|
54742
54815
|
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { className: "text-[#888]", children: "<" }),
|
|
54743
54816
|
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { className: "font-bold text-white", children: props.node.tagName }),
|
|
54744
54817
|
attributes,
|
|
@@ -54827,7 +54900,7 @@ function TranscriptText(props) {
|
|
|
54827
54900
|
const firstChildIndex = seenChildren;
|
|
54828
54901
|
const childCount = countStructuredBlockChildren(block);
|
|
54829
54902
|
seenChildren += childCount;
|
|
54830
|
-
if (!canRenderStructuredMarkup(block
|
|
54903
|
+
if (!canRenderStructuredMarkup(block)) {
|
|
54831
54904
|
return /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
54832
54905
|
HighlightedCode,
|
|
54833
54906
|
{
|
|
@@ -55437,20 +55510,7 @@ function TranscriptPartView(props) {
|
|
|
55437
55510
|
}
|
|
55438
55511
|
const value = part.output;
|
|
55439
55512
|
if (part.type === "thinking") {
|
|
55440
|
-
|
|
55441
|
-
return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("details", { className: "border border-[#beaaff]/20 bg-white/[0.03] transition-colors hover:border-[#beaaff]/45 hover:bg-[rgba(190,170,255,0.06)]", children: [
|
|
55442
|
-
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("summary", { className: "grid cursor-pointer grid-cols-[auto_minmax(0,1fr)] items-center gap-3 px-3 py-2 font-mono text-[0.8rem] leading-tight text-[#888] hover:bg-[rgba(190,170,255,0.07)] max-md:grid-cols-1 max-md:gap-1", children: [
|
|
55443
|
-
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "uppercase text-[#b8b8b8]", children: "thinking" }),
|
|
55444
|
-
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "min-w-0 truncate", children: previewToolValue(value) })
|
|
55445
|
-
] }),
|
|
55446
|
-
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
55447
|
-
HighlightedCode,
|
|
55448
|
-
{
|
|
55449
|
-
code: rendered2 || "{}",
|
|
55450
|
-
language: detectLanguage(rendered2)
|
|
55451
|
-
}
|
|
55452
|
-
)
|
|
55453
|
-
] });
|
|
55513
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(ThinkingPartView, { value });
|
|
55454
55514
|
}
|
|
55455
55515
|
const rendered = stringifyPartValue(value);
|
|
55456
55516
|
return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("details", { className: toolFrameClass(), children: [
|
|
@@ -55462,6 +55522,34 @@ function TranscriptPartView(props) {
|
|
|
55462
55522
|
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(HighlightedCode, { code: rendered || "{}", language: "json" })
|
|
55463
55523
|
] });
|
|
55464
55524
|
}
|
|
55525
|
+
function ThinkingPartView(props) {
|
|
55526
|
+
const [open, setOpen] = (0, import_react51.useState)(false);
|
|
55527
|
+
const rendered = stringifyPartValue(props.value);
|
|
55528
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
|
|
55529
|
+
"details",
|
|
55530
|
+
{
|
|
55531
|
+
className: "border border-[#beaaff]/20 bg-white/[0.03] transition-colors hover:border-[#beaaff]/45 hover:bg-[rgba(190,170,255,0.06)]",
|
|
55532
|
+
onToggle: (event) => {
|
|
55533
|
+
if (event.currentTarget !== event.target) return;
|
|
55534
|
+
setOpen(event.currentTarget.open);
|
|
55535
|
+
},
|
|
55536
|
+
open,
|
|
55537
|
+
children: [
|
|
55538
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("summary", { className: "grid cursor-pointer grid-cols-[auto_minmax(0,1fr)] items-center gap-3 px-3 py-2 font-mono text-[0.8rem] leading-tight text-[#888] hover:bg-[rgba(190,170,255,0.07)] max-md:grid-cols-1 max-md:gap-1", children: [
|
|
55539
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "uppercase text-[#b8b8b8]", children: "thinking" }),
|
|
55540
|
+
open ? null : /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "min-w-0 truncate", children: previewToolValue(props.value) })
|
|
55541
|
+
] }),
|
|
55542
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "border-t border-[#beaaff]/15 px-3 py-3", children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
55543
|
+
HighlightedCode,
|
|
55544
|
+
{
|
|
55545
|
+
code: rendered || "{}",
|
|
55546
|
+
language: detectOutputLanguage(rendered)
|
|
55547
|
+
}
|
|
55548
|
+
) })
|
|
55549
|
+
]
|
|
55550
|
+
}
|
|
55551
|
+
);
|
|
55552
|
+
}
|
|
55465
55553
|
function isString3(value) {
|
|
55466
55554
|
return typeof value === "string" && value.length > 0;
|
|
55467
55555
|
}
|
|
@@ -55469,7 +55557,7 @@ function isString3(value) {
|
|
|
55469
55557
|
// src/client/components/Transcript.tsx
|
|
55470
55558
|
var import_jsx_runtime22 = __toESM(require_jsx_runtime(), 1);
|
|
55471
55559
|
function Transcript(props) {
|
|
55472
|
-
const [view, setView] = (0,
|
|
55560
|
+
const [view, setView] = (0, import_react52.useState)("rich");
|
|
55473
55561
|
const hasRedactedTurns = props.turns.some((turn) => turn.transcriptRedacted);
|
|
55474
55562
|
if (props.turns.length === 0) {
|
|
55475
55563
|
return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("div", { className: transcriptEmptyClass(), children: "No transcript is available for this conversation." });
|
|
@@ -55573,11 +55661,17 @@ function ConversationStats(props) {
|
|
|
55573
55661
|
(count, turn) => count + turnToolCallCount(turn),
|
|
55574
55662
|
0
|
|
55575
55663
|
) : void 0;
|
|
55664
|
+
const tokens = formatUsageTotal(
|
|
55665
|
+
(props.detail?.turns ?? props.conversation.turns).map(
|
|
55666
|
+
(turn) => turn.cumulativeUsage
|
|
55667
|
+
)
|
|
55668
|
+
);
|
|
55576
55669
|
const stats = [
|
|
55577
55670
|
slackLocationLabel(props.conversation, { includeId: false }),
|
|
55578
55671
|
`${props.conversation.turns.length} turns`,
|
|
55579
55672
|
messages === void 0 ? "messages loading" : `${messages} messages`,
|
|
55580
55673
|
toolCalls === void 0 ? "tool calls loading" : `${toolCalls} tool calls`,
|
|
55674
|
+
tokens,
|
|
55581
55675
|
formatConversationDuration(props.conversation),
|
|
55582
55676
|
`started ${formatTime(props.conversation.startedAt)}`
|
|
55583
55677
|
].filter(Boolean);
|
|
@@ -55865,7 +55959,7 @@ function LegacyConversationRedirect() {
|
|
|
55865
55959
|
|
|
55866
55960
|
// src/client.tsx
|
|
55867
55961
|
var import_jsx_runtime29 = __toESM(require_jsx_runtime(), 1);
|
|
55868
|
-
var DashboardErrorBoundary = class extends
|
|
55962
|
+
var DashboardErrorBoundary = class extends import_react53.Component {
|
|
55869
55963
|
state = { error: null };
|
|
55870
55964
|
static getDerivedStateFromError(error) {
|
|
55871
55965
|
return { error };
|
package/dist/tailwind.css
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
/*! tailwindcss v4.3.0 | MIT License | https://tailwindcss.com */
|
|
2
|
-
@layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-border-style:solid;--tw-leading:initial;--tw-font-weight:initial;--tw-tracking:initial;--tw-blur:initial;--tw-brightness:initial;--tw-contrast:initial;--tw-grayscale:initial;--tw-hue-rotate:initial;--tw-invert:initial;--tw-opacity:initial;--tw-saturate:initial;--tw-sepia:initial;--tw-drop-shadow:initial;--tw-drop-shadow-color:initial;--tw-drop-shadow-alpha:100%;--tw-drop-shadow-size:initial;--tw-backdrop-blur:initial;--tw-backdrop-brightness:initial;--tw-backdrop-contrast:initial;--tw-backdrop-grayscale:initial;--tw-backdrop-hue-rotate:initial;--tw-backdrop-invert:initial;--tw-backdrop-opacity:initial;--tw-backdrop-saturate:initial;--tw-backdrop-sepia:initial}}}@layer theme{:root,:host{--font-sans:-apple-system, "system-ui", "Segoe UI", Roboto, Oxygen, Ubuntu, sans-serif;--font-mono:"Geist Mono", ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", monospace;--color-amber-200:oklch(92.4% .12 95.746);--color-amber-300:oklch(87.9% .169 91.605);--color-amber-400:oklch(82.8% .189 84.429);--color-emerald-300:oklch(84.5% .143 164.978);--color-emerald-400:oklch(76.5% .177 163.223);--color-violet-200:oklch(89.4% .057 293.283);--color-violet-300:oklch(81.1% .111 293.571);--color-rose-300:oklch(81% .117 11.638);--color-rose-400:oklch(71.2% .194 13.428);--color-black:#000;--color-white:#fff;--spacing:.25rem;--container-sm:24rem;--container-lg:32rem;--container-3xl:48rem;--container-5xl:64rem;--text-xs:.75rem;--text-xs--line-height:calc(1 / .75);--text-sm:.875rem;--text-sm--line-height:calc(1.25 / .875);--text-2xl:1.5rem;--text-2xl--line-height:calc(2 / 1.5);--text-3xl:1.875rem;--text-3xl--line-height:calc(2.25 / 1.875);--text-5xl:3rem;--text-5xl--line-height:1;--text-6xl:3.75rem;--text-6xl--line-height:1;--font-weight-semibold:600;--font-weight-bold:700;--font-weight-extrabold:800;--font-weight-black:900;--tracking-normal:0em;--leading-tight:1.25;--leading-snug:1.375;--leading-relaxed:1.625;--animate-pulse:pulse 2s cubic-bezier(.4, 0, .6, 1) infinite;--default-transition-duration:.15s;--default-transition-timing-function:cubic-bezier(.4, 0, .2, 1);--default-font-family:var(--font-sans);--default-mono-font-family:var(--font-mono)}}@layer base{*,:after,:before,::backdrop{box-sizing:border-box;border:0 solid;margin:0;padding:0}::file-selector-button{box-sizing:border-box;border:0 solid;margin:0;padding:0}html,:host{-webkit-text-size-adjust:100%;tab-size:4;line-height:1.5;font-family:var(--default-font-family,ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji");font-feature-settings:var(--default-font-feature-settings,normal);font-variation-settings:var(--default-font-variation-settings,normal);-webkit-tap-highlight-color:transparent}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:var(--default-mono-font-family,ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace);font-feature-settings:var(--default-mono-font-feature-settings,normal);font-variation-settings:var(--default-mono-font-variation-settings,normal);font-size:1em}small{font-size:80%}sub,sup{vertical-align:baseline;font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}:-moz-focusring{outline:auto}progress{vertical-align:baseline}summary{display:list-item}ol,ul,menu{list-style:none}img,svg,video,canvas,audio,iframe,embed,object{vertical-align:middle;display:block}img,video{max-width:100%;height:auto}button,input,select,optgroup,textarea{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}::file-selector-button{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}:where(select:is([multiple],[size])) optgroup{font-weight:bolder}:where(select:is([multiple],[size])) optgroup option{padding-inline-start:20px}::file-selector-button{margin-inline-end:4px}::placeholder{opacity:1}@supports (not ((-webkit-appearance:-apple-pay-button))) or (contain-intrinsic-size:1px){::placeholder{color:currentColor}@supports (color:color-mix(in lab, red, red)){::placeholder{color:color-mix(in oklab, currentcolor 50%, transparent)}}}textarea{resize:vertical}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-date-and-time-value{min-height:1lh;text-align:inherit}::-webkit-datetime-edit{display:inline-flex}::-webkit-datetime-edit-fields-wrapper{padding:0}::-webkit-datetime-edit{padding-block:0}::-webkit-datetime-edit-year-field{padding-block:0}::-webkit-datetime-edit-month-field{padding-block:0}::-webkit-datetime-edit-day-field{padding-block:0}::-webkit-datetime-edit-hour-field{padding-block:0}::-webkit-datetime-edit-minute-field{padding-block:0}::-webkit-datetime-edit-second-field{padding-block:0}::-webkit-datetime-edit-millisecond-field{padding-block:0}::-webkit-datetime-edit-meridiem-field{padding-block:0}::-webkit-calendar-picker-indicator{line-height:1}:-moz-ui-invalid{box-shadow:none}button,input:where([type=button],[type=reset],[type=submit]){appearance:button}::file-selector-button{appearance:button}::-webkit-inner-spin-button{height:auto}::-webkit-outer-spin-button{height:auto}[hidden]:where(:not([hidden=until-found])){display:none!important}}@layer components;@layer utilities{.visible{visibility:visible}.absolute{position:absolute}.relative{position:relative}.static{position:static}.sticky{position:sticky}.top-0{top:calc(var(--spacing) * 0)}.bottom-0{bottom:calc(var(--spacing) * 0)}.left-0{left:calc(var(--spacing) * 0)}.z-10{z-index:10}.z-\[1\]{z-index:1}.col-span-full{grid-column:1/-1}.m-0{margin:calc(var(--spacing) * 0)}.my-4{margin-block:calc(var(--spacing) * 4)}.mt-0\.5{margin-top:calc(var(--spacing) * .5)}.mt-1{margin-top:calc(var(--spacing) * 1)}.mt-2{margin-top:calc(var(--spacing) * 2)}.mt-3{margin-top:calc(var(--spacing) * 3)}.mr-1{margin-right:calc(var(--spacing) * 1)}.mr-3{margin-right:calc(var(--spacing) * 3)}.mb-1{margin-bottom:calc(var(--spacing) * 1)}.mb-3{margin-bottom:calc(var(--spacing) * 3)}.mb-4{margin-bottom:calc(var(--spacing) * 4)}.mb-6{margin-bottom:calc(var(--spacing) * 6)}.-ml-1{margin-left:calc(var(--spacing) * -1)}.ml-1{margin-left:calc(var(--spacing) * 1)}.ml-1\.5{margin-left:calc(var(--spacing) * 1.5)}.block{display:block}.contents{display:contents}.flex{display:flex}.grid{display:grid}.hidden{display:none}.inline{display:inline}.inline-block{display:inline-block}.inline-flex{display:inline-flex}.table{display:table}.size-1\.5{width:calc(var(--spacing) * 1.5);height:calc(var(--spacing) * 1.5)}.size-2{width:calc(var(--spacing) * 2);height:calc(var(--spacing) * 2)}.size-2\.5{width:calc(var(--spacing) * 2.5);height:calc(var(--spacing) * 2.5)}.size-9{width:calc(var(--spacing) * 9);height:calc(var(--spacing) * 9)}.h-1\.5{height:calc(var(--spacing) * 1.5)}.max-h-\[60vh\]{max-height:60vh}.min-h-16{min-height:calc(var(--spacing) * 16)}.min-h-28{min-height:calc(var(--spacing) * 28)}.min-h-48{min-height:calc(var(--spacing) * 48)}.min-h-\[4\.5rem\]{min-height:4.5rem}.min-h-\[calc\(100vh-5rem\)\]{min-height:calc(100vh - 5rem)}.min-h-screen{min-height:100vh}.w-1{width:calc(var(--spacing) * 1)}.w-2{width:calc(var(--spacing) * 2)}.w-fit{width:fit-content}.w-full{width:100%}.w-px{width:1px}.max-w-3xl{max-width:var(--container-3xl)}.max-w-5xl{max-width:var(--container-5xl)}.max-w-full{max-width:100%}.max-w-lg{max-width:var(--container-lg)}.max-w-sm{max-width:var(--container-sm)}.min-w-0{min-width:calc(var(--spacing) * 0)}.min-w-64{min-width:calc(var(--spacing) * 64)}.flex-1{flex:1}.shrink-0{flex-shrink:0}.basis-1\/2{flex-basis:50%}.animate-pulse{animation:var(--animate-pulse)}.cursor-default{cursor:default}.cursor-pointer{cursor:pointer}.list-none{list-style-type:none}.grid-cols-\[0\.875rem_minmax\(0\,1fr\)\]{grid-template-columns:.875rem minmax(0,1fr)}.grid-cols-\[auto_minmax\(0\,1fr\)\]{grid-template-columns:auto minmax(0,1fr)}.grid-cols-\[auto_minmax\(0\,1fr\)_auto\]{grid-template-columns:auto minmax(0,1fr) auto}.grid-cols-\[minmax\(0\,1fr\)_auto\]{grid-template-columns:minmax(0,1fr) auto}.grid-cols-\[minmax\(0\,1fr\)_minmax\(12rem\,max-content\)\]{grid-template-columns:minmax(0,1fr) minmax(12rem,max-content)}.grid-cols-\[minmax\(13rem\,1\.7fr\)_minmax\(13rem\,1fr\)\]{grid-template-columns:minmax(13rem,1.7fr) minmax(13rem,1fr)}.grid-rows-\[auto_1fr\]{grid-template-rows:auto 1fr}.flex-col{flex-direction:column}.flex-wrap{flex-wrap:wrap}.place-items-center{place-items:center}.items-baseline{align-items:baseline}.items-center{align-items:center}.items-start{align-items:flex-start}.justify-between{justify-content:space-between}.justify-end{justify-content:flex-end}.justify-items-end{justify-items:end}.gap-0{gap:calc(var(--spacing) * 0)}.gap-1{gap:calc(var(--spacing) * 1)}.gap-1\.5{gap:calc(var(--spacing) * 1.5)}.gap-2{gap:calc(var(--spacing) * 2)}.gap-3{gap:calc(var(--spacing) * 3)}.gap-4{gap:calc(var(--spacing) * 4)}.gap-5{gap:calc(var(--spacing) * 5)}.gap-x-1{column-gap:calc(var(--spacing) * 1)}.gap-x-3{column-gap:calc(var(--spacing) * 3)}.gap-y-0\.5{row-gap:calc(var(--spacing) * .5)}.gap-y-1{row-gap:calc(var(--spacing) * 1)}.self-start{align-self:flex-start}.justify-self-end{justify-self:flex-end}.justify-self-start{justify-self:flex-start}.truncate{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.overflow-auto{overflow:auto}.overflow-hidden{overflow:hidden}.overflow-visible{overflow:visible}.rounded-full{border-radius:3.40282e38px}.border{border-style:var(--tw-border-style);border-width:1px}.border-0{border-style:var(--tw-border-style);border-width:0}.border-t{border-top-style:var(--tw-border-style);border-top-width:1px}.border-r{border-right-style:var(--tw-border-style);border-right-width:1px}.border-b{border-bottom-style:var(--tw-border-style);border-bottom-width:1px}.border-b-4{border-bottom-style:var(--tw-border-style);border-bottom-width:4px}.border-l{border-left-style:var(--tw-border-style);border-left-width:1px}.border-l-4{border-left-style:var(--tw-border-style);border-left-width:4px}.border-\[\#beaaff\]\/20{border-color:oklab(78.6663% .0494663 -.109708/.2)}.border-\[\#beaaff\]\/70{border-color:oklab(78.6663% .0494663 -.109708/.7)}.border-amber-300{border-color:var(--color-amber-300)}.border-amber-400\/25{border-color:#fcbb0040}@supports (color:color-mix(in lab, red, red)){.border-amber-400\/25{border-color:color-mix(in oklab, var(--color-amber-400) 25%, transparent)}}.border-emerald-300{border-color:var(--color-emerald-300)}.border-emerald-400\/25{border-color:#00d29440}@supports (color:color-mix(in lab, red, red)){.border-emerald-400\/25{border-color:color-mix(in oklab, var(--color-emerald-400) 25%, transparent)}}.border-rose-300{border-color:var(--color-rose-300)}.border-rose-400{border-color:var(--color-rose-400)}.border-rose-400\/25{border-color:#ff667f40}@supports (color:color-mix(in lab, red, red)){.border-rose-400\/25{border-color:color-mix(in oklab, var(--color-rose-400) 25%, transparent)}}.border-rose-400\/50{border-color:#ff667f80}@supports (color:color-mix(in lab, red, red)){.border-rose-400\/50{border-color:color-mix(in oklab, var(--color-rose-400) 50%, transparent)}}.border-white\/10{border-color:#ffffff1a}@supports (color:color-mix(in lab, red, red)){.border-white\/10{border-color:color-mix(in oklab, var(--color-white) 10%, transparent)}}.border-white\/15{border-color:#ffffff26}@supports (color:color-mix(in lab, red, red)){.border-white\/15{border-color:color-mix(in oklab, var(--color-white) 15%, transparent)}}.border-white\/30{border-color:#ffffff4d}@supports (color:color-mix(in lab, red, red)){.border-white\/30{border-color:color-mix(in oklab, var(--color-white) 30%, transparent)}}.border-b-\[\#beaaff\]{border-bottom-color:#beaaff}.border-b-transparent{border-bottom-color:#0000}.border-b-white\/10{border-bottom-color:#ffffff1a}@supports (color:color-mix(in lab, red, red)){.border-b-white\/10{border-bottom-color:color-mix(in oklab, var(--color-white) 10%, transparent)}}.border-l-\[\#888\]{border-left-color:#888}.border-l-\[\#beaaff\]\/60{border-left-color:oklab(78.6663% .0494663 -.109708/.6)}.border-l-amber-300{border-left-color:var(--color-amber-300)}.border-l-amber-400{border-left-color:var(--color-amber-400)}.border-l-emerald-400{border-left-color:var(--color-emerald-400)}.border-l-rose-400{border-left-color:var(--color-rose-400)}.border-l-violet-300{border-left-color:var(--color-violet-300)}.border-l-white{border-left-color:var(--color-white)}.border-l-white\/25{border-left-color:#ffffff40}@supports (color:color-mix(in lab, red, red)){.border-l-white\/25{border-left-color:color-mix(in oklab, var(--color-white) 25%, transparent)}}.border-l-white\/35{border-left-color:#ffffff59}@supports (color:color-mix(in lab, red, red)){.border-l-white\/35{border-left-color:color-mix(in oklab, var(--color-white) 35%, transparent)}}.border-l-white\/70{border-left-color:#ffffffb3}@supports (color:color-mix(in lab, red, red)){.border-l-white\/70{border-left-color:color-mix(in oklab, var(--color-white) 70%, transparent)}}.bg-\[\#0b0b0b\]{background-color:#0b0b0b}.bg-\[\#111\]{background-color:#111}.bg-\[\#050505\]{background-color:#050505}.bg-\[\#050505\]\/95{background-color:oklab(11.4918% 7.45058e-9 7.45058e-9/.95)}.bg-\[\#b8b8b8\]{background-color:#b8b8b8}.bg-\[\#beaaff\]\/20{background-color:oklab(78.6663% .0494663 -.109708/.2)}.bg-\[\#beaaff\]\/50{background-color:oklab(78.6663% .0494663 -.109708/.5)}.bg-\[rgba\(190\,170\,255\,0\.08\)\]{background-color:#beaaff14}.bg-amber-300{background-color:var(--color-amber-300)}.bg-amber-300\/\[0\.06\]{background-color:#ffd2360f}@supports (color:color-mix(in lab, red, red)){.bg-amber-300\/\[0\.06\]{background-color:color-mix(in oklab, var(--color-amber-300) 6%, transparent)}}.bg-amber-400{background-color:var(--color-amber-400)}.bg-amber-400\/10{background-color:#fcbb001a}@supports (color:color-mix(in lab, red, red)){.bg-amber-400\/10{background-color:color-mix(in oklab, var(--color-amber-400) 10%, transparent)}}.bg-black{background-color:var(--color-black)}.bg-emerald-300{background-color:var(--color-emerald-300)}.bg-emerald-400\/10{background-color:#00d2941a}@supports (color:color-mix(in lab, red, red)){.bg-emerald-400\/10{background-color:color-mix(in oklab, var(--color-emerald-400) 10%, transparent)}}.bg-rose-300{background-color:var(--color-rose-300)}.bg-rose-400{background-color:var(--color-rose-400)}.bg-rose-400\/10{background-color:#ff667f1a}@supports (color:color-mix(in lab, red, red)){.bg-rose-400\/10{background-color:color-mix(in oklab, var(--color-rose-400) 10%, transparent)}}.bg-transparent{background-color:#0000}.bg-white{background-color:var(--color-white)}.bg-white\/20{background-color:#fff3}@supports (color:color-mix(in lab, red, red)){.bg-white\/20{background-color:color-mix(in oklab, var(--color-white) 20%, transparent)}}.bg-white\/35{background-color:#ffffff59}@supports (color:color-mix(in lab, red, red)){.bg-white\/35{background-color:color-mix(in oklab, var(--color-white) 35%, transparent)}}.bg-white\/\[0\.03\]{background-color:#ffffff08}@supports (color:color-mix(in lab, red, red)){.bg-white\/\[0\.03\]{background-color:color-mix(in oklab, var(--color-white) 3%, transparent)}}.bg-white\/\[0\.04\]{background-color:#ffffff0a}@supports (color:color-mix(in lab, red, red)){.bg-white\/\[0\.04\]{background-color:color-mix(in oklab, var(--color-white) 4%, transparent)}}.p-0{padding:calc(var(--spacing) * 0)}.p-3{padding:calc(var(--spacing) * 3)}.p-4{padding:calc(var(--spacing) * 4)}.p-5{padding:calc(var(--spacing) * 5)}.p-8{padding:calc(var(--spacing) * 8)}.px-0\.5{padding-inline:calc(var(--spacing) * .5)}.px-1{padding-inline:calc(var(--spacing) * 1)}.px-1\.5{padding-inline:calc(var(--spacing) * 1.5)}.px-2{padding-inline:calc(var(--spacing) * 2)}.px-3{padding-inline:calc(var(--spacing) * 3)}.px-4{padding-inline:calc(var(--spacing) * 4)}.py-0\.5{padding-block:calc(var(--spacing) * .5)}.py-1{padding-block:calc(var(--spacing) * 1)}.py-2{padding-block:calc(var(--spacing) * 2)}.py-2\.5{padding-block:calc(var(--spacing) * 2.5)}.py-3{padding-block:calc(var(--spacing) * 3)}.py-4{padding-block:calc(var(--spacing) * 4)}.py-5{padding-block:calc(var(--spacing) * 5)}.py-8{padding-block:calc(var(--spacing) * 8)}.pt-2{padding-top:calc(var(--spacing) * 2)}.pt-3{padding-top:calc(var(--spacing) * 3)}.pt-4{padding-top:calc(var(--spacing) * 4)}.pr-3{padding-right:calc(var(--spacing) * 3)}.pb-1\.5{padding-bottom:calc(var(--spacing) * 1.5)}.pb-2{padding-bottom:calc(var(--spacing) * 2)}.pb-3{padding-bottom:calc(var(--spacing) * 3)}.pl-3{padding-left:calc(var(--spacing) * 3)}.pl-4{padding-left:calc(var(--spacing) * 4)}.pl-5{padding-left:calc(var(--spacing) * 5)}.text-left{text-align:left}.text-right{text-align:right}.font-\[inherit\]{font-family:inherit}.font-mono{font-family:var(--font-mono)}.font-sans{font-family:var(--font-sans)}.text-2xl{font-size:var(--text-2xl);line-height:var(--tw-leading,var(--text-2xl--line-height))}.text-3xl{font-size:var(--text-3xl);line-height:var(--tw-leading,var(--text-3xl--line-height))}.text-5xl{font-size:var(--text-5xl);line-height:var(--tw-leading,var(--text-5xl--line-height))}.text-sm{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}.text-xs{font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height))}.text-\[0\.8rem\]{font-size:.8rem}.text-\[0\.9rem\]{font-size:.9rem}.text-\[0\.68rem\]{font-size:.68rem}.text-\[0\.72rem\]{font-size:.72rem}.text-\[0\.76rem\]{font-size:.76rem}.text-\[0\.78rem\]{font-size:.78rem}.text-\[0\.82rem\]{font-size:.82rem}.text-\[0\.84rem\]{font-size:.84rem}.text-\[0\.86rem\]{font-size:.86rem}.text-\[0\.88rem\]{font-size:.88rem}.text-\[0\.92rem\]{font-size:.92rem}.text-\[0\.98rem\]{font-size:.98rem}.text-\[1\.04rem\]{font-size:1.04rem}.text-\[1\.05rem\]{font-size:1.05rem}.text-\[1\.75rem\]{font-size:1.75rem}.leading-\[1\.45\]{--tw-leading:1.45;line-height:1.45}.leading-none{--tw-leading:1;line-height:1}.leading-relaxed{--tw-leading:var(--leading-relaxed);line-height:var(--leading-relaxed)}.leading-snug{--tw-leading:var(--leading-snug);line-height:var(--leading-snug)}.leading-tight{--tw-leading:var(--leading-tight);line-height:var(--leading-tight)}.font-black{--tw-font-weight:var(--font-weight-black);font-weight:var(--font-weight-black)}.font-bold{--tw-font-weight:var(--font-weight-bold);font-weight:var(--font-weight-bold)}.font-extrabold{--tw-font-weight:var(--font-weight-extrabold);font-weight:var(--font-weight-extrabold)}.font-semibold{--tw-font-weight:var(--font-weight-semibold);font-weight:var(--font-weight-semibold)}.tracking-normal{--tw-tracking:var(--tracking-normal);letter-spacing:var(--tracking-normal)}.break-words{overflow-wrap:break-word}.break-all{word-break:break-all}.whitespace-nowrap{white-space:nowrap}.whitespace-pre-wrap{white-space:pre-wrap}.text-\[\#666\]{color:#666}.text-\[\#777\]{color:#777}.text-\[\#888\]{color:#888}.text-\[\#b8b8b8\]{color:#b8b8b8}.text-\[\#d6d6d6\]{color:#d6d6d6}.text-\[\#d8ccff\]{color:#d8ccff}.text-\[\#f4f4f4\]{color:#f4f4f4}.text-amber-200{color:var(--color-amber-200)}.text-amber-300{color:var(--color-amber-300)}.text-black{color:var(--color-black)}.text-emerald-300{color:var(--color-emerald-300)}.text-inherit{color:inherit}.text-rose-300{color:var(--color-rose-300)}.text-violet-200{color:var(--color-violet-200)}.text-white{color:var(--color-white)}.lowercase{text-transform:lowercase}.uppercase{text-transform:uppercase}.no-underline{text-decoration-line:none}.underline{text-decoration-line:underline}.decoration-white{-webkit-text-decoration-color:var(--color-white);-webkit-text-decoration-color:var(--color-white);text-decoration-color:var(--color-white)}.underline-offset-4{text-underline-offset:4px}.\[color-scheme\:dark\]{color-scheme:dark}.saturate-50{--tw-saturate:saturate(50%);filter:var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,)}.filter{filter:var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,)}.backdrop-blur{--tw-backdrop-blur:blur(8px);-webkit-backdrop-filter:var(--tw-backdrop-blur,) var(--tw-backdrop-brightness,) var(--tw-backdrop-contrast,) var(--tw-backdrop-grayscale,) var(--tw-backdrop-hue-rotate,) var(--tw-backdrop-invert,) var(--tw-backdrop-opacity,) var(--tw-backdrop-saturate,) var(--tw-backdrop-sepia,);backdrop-filter:var(--tw-backdrop-blur,) var(--tw-backdrop-brightness,) var(--tw-backdrop-contrast,) var(--tw-backdrop-grayscale,) var(--tw-backdrop-hue-rotate,) var(--tw-backdrop-invert,) var(--tw-backdrop-opacity,) var(--tw-backdrop-saturate,) var(--tw-backdrop-sepia,)}.transition-\[filter\,stroke\,stroke-width\]{transition-property:filter,stroke,stroke-width;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-colors{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.outline-none{--tw-outline-style:none;outline-style:none}.select-none{-webkit-user-select:none;user-select:none}.group-open\:hidden:is(:where(.group):is([open],:popover-open,:open) *){display:none}.group-open\:inline:is(:where(.group):is([open],:popover-open,:open) *){display:inline}.first\:border-t-0:first-child{border-top-style:var(--tw-border-style);border-top-width:0}.last\:border-b-0:last-child{border-bottom-style:var(--tw-border-style);border-bottom-width:0}@media (hover:hover){.hover\:border-\[\#beaaff\]\/45:hover{border-color:oklab(78.6663% .0494663 -.109708/.45)}.hover\:border-white:hover{border-color:var(--color-white)}.hover\:border-white\/25:hover{border-color:#ffffff40}@supports (color:color-mix(in lab, red, red)){.hover\:border-white\/25:hover{border-color:color-mix(in oklab, var(--color-white) 25%, transparent)}}.hover\:border-white\/30:hover{border-color:#ffffff4d}@supports (color:color-mix(in lab, red, red)){.hover\:border-white\/30:hover{border-color:color-mix(in oklab, var(--color-white) 30%, transparent)}}.hover\:border-b-white\/45:hover{border-bottom-color:#ffffff73}@supports (color:color-mix(in lab, red, red)){.hover\:border-b-white\/45:hover{border-bottom-color:color-mix(in oklab, var(--color-white) 45%, transparent)}}.hover\:bg-\[\#151515\]:hover{background-color:#151515}.hover\:bg-\[rgba\(190\,170\,255\,0\.06\)\]:hover{background-color:#beaaff0f}.hover\:bg-\[rgba\(190\,170\,255\,0\.07\)\]:hover{background-color:#beaaff12}.hover\:bg-white\/\[0\.04\]:hover{background-color:#ffffff0a}@supports (color:color-mix(in lab, red, red)){.hover\:bg-white\/\[0\.04\]:hover{background-color:color-mix(in oklab, var(--color-white) 4%, transparent)}}.hover\:bg-white\/\[0\.05\]:hover{background-color:#ffffff0d}@supports (color:color-mix(in lab, red, red)){.hover\:bg-white\/\[0\.05\]:hover{background-color:color-mix(in oklab, var(--color-white) 5%, transparent)}}.hover\:text-white:hover{color:var(--color-white)}.hover\:underline:hover{text-decoration-line:underline}.hover\:brightness-125:hover{--tw-brightness:brightness(125%);filter:var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,)}}.focus-visible\:stroke-emerald-400:focus-visible{stroke:var(--color-emerald-400)}.focus-visible\:stroke-2:focus-visible{stroke-width:2px}@media not all and (min-width:48rem){.max-md\:hidden{display:none}.max-md\:w-full{width:100%}.max-md\:grid-cols-1{grid-template-columns:repeat(1,minmax(0,1fr))}.max-md\:flex-col{flex-direction:column}.max-md\:flex-wrap{flex-wrap:wrap}.max-md\:items-stretch{align-items:stretch}.max-md\:justify-between{justify-content:space-between}.max-md\:justify-items-start{justify-items:start}.max-md\:gap-1{gap:calc(var(--spacing) * 1)}.max-md\:px-4{padding-inline:calc(var(--spacing) * 4)}.max-md\:py-4{padding-block:calc(var(--spacing) * 4)}.max-md\:text-left{text-align:left}}@media (min-width:40rem){.sm\:basis-1\/3{flex-basis:33.3333%}}@media (min-width:48rem){.md\:grid-cols-\[minmax\(0\,1fr\)_auto\]{grid-template-columns:minmax(0,1fr) auto}.md\:truncate{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.md\:px-8{padding-inline:calc(var(--spacing) * 8)}.md\:text-right{text-align:right}.md\:text-6xl{font-size:var(--text-6xl);line-height:var(--tw-leading,var(--text-6xl--line-height))}}@media (min-width:64rem){.lg\:grid-cols-\[minmax\(21rem\,0\.32fr\)_minmax\(0\,1fr\)\]{grid-template-columns:minmax(21rem,.32fr) minmax(0,1fr)}}.\[\&_code\]\:break-words code{overflow-wrap:break-word}.\[\&_code\]\:whitespace-pre-wrap code{white-space:pre-wrap}.\[\&_pre\]\:\!m-0 pre{margin:calc(var(--spacing) * 0)!important}.\[\&_pre\]\:\!overflow-visible pre{overflow:visible!important}.\[\&_pre\]\:\!bg-transparent pre{background-color:#0000!important}.\[\&_pre\]\:\!p-0 pre{padding:calc(var(--spacing) * 0)!important}.\[\&_pre\]\:font-mono pre{font-family:var(--font-mono)}.\[\&_pre\]\:text-\[0\.86rem\] pre{font-size:.86rem}.\[\&_pre\]\:leading-relaxed pre{--tw-leading:var(--leading-relaxed);line-height:var(--leading-relaxed)}.\[\&_pre\]\:break-words pre{overflow-wrap:break-word}.\[\&_pre\]\:whitespace-pre-wrap pre{white-space:pre-wrap}.\[\&\:\:-webkit-details-marker\]\:hidden::-webkit-details-marker{display:none}}@property --tw-border-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-leading{syntax:"*";inherits:false}@property --tw-font-weight{syntax:"*";inherits:false}@property --tw-tracking{syntax:"*";inherits:false}@property --tw-blur{syntax:"*";inherits:false}@property --tw-brightness{syntax:"*";inherits:false}@property --tw-contrast{syntax:"*";inherits:false}@property --tw-grayscale{syntax:"*";inherits:false}@property --tw-hue-rotate{syntax:"*";inherits:false}@property --tw-invert{syntax:"*";inherits:false}@property --tw-opacity{syntax:"*";inherits:false}@property --tw-saturate{syntax:"*";inherits:false}@property --tw-sepia{syntax:"*";inherits:false}@property --tw-drop-shadow{syntax:"*";inherits:false}@property --tw-drop-shadow-color{syntax:"*";inherits:false}@property --tw-drop-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-drop-shadow-size{syntax:"*";inherits:false}@property --tw-backdrop-blur{syntax:"*";inherits:false}@property --tw-backdrop-brightness{syntax:"*";inherits:false}@property --tw-backdrop-contrast{syntax:"*";inherits:false}@property --tw-backdrop-grayscale{syntax:"*";inherits:false}@property --tw-backdrop-hue-rotate{syntax:"*";inherits:false}@property --tw-backdrop-invert{syntax:"*";inherits:false}@property --tw-backdrop-opacity{syntax:"*";inherits:false}@property --tw-backdrop-saturate{syntax:"*";inherits:false}@property --tw-backdrop-sepia{syntax:"*";inherits:false}@keyframes pulse{50%{opacity:.5}}
|
|
2
|
+
@layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-border-style:solid;--tw-leading:initial;--tw-font-weight:initial;--tw-tracking:initial;--tw-blur:initial;--tw-brightness:initial;--tw-contrast:initial;--tw-grayscale:initial;--tw-hue-rotate:initial;--tw-invert:initial;--tw-opacity:initial;--tw-saturate:initial;--tw-sepia:initial;--tw-drop-shadow:initial;--tw-drop-shadow-color:initial;--tw-drop-shadow-alpha:100%;--tw-drop-shadow-size:initial;--tw-backdrop-blur:initial;--tw-backdrop-brightness:initial;--tw-backdrop-contrast:initial;--tw-backdrop-grayscale:initial;--tw-backdrop-hue-rotate:initial;--tw-backdrop-invert:initial;--tw-backdrop-opacity:initial;--tw-backdrop-saturate:initial;--tw-backdrop-sepia:initial}}}@layer theme{:root,:host{--font-sans:-apple-system, "system-ui", "Segoe UI", Roboto, Oxygen, Ubuntu, sans-serif;--font-mono:"Geist Mono", ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", monospace;--color-amber-200:oklch(92.4% .12 95.746);--color-amber-300:oklch(87.9% .169 91.605);--color-amber-400:oklch(82.8% .189 84.429);--color-emerald-300:oklch(84.5% .143 164.978);--color-emerald-400:oklch(76.5% .177 163.223);--color-violet-200:oklch(89.4% .057 293.283);--color-violet-300:oklch(81.1% .111 293.571);--color-rose-300:oklch(81% .117 11.638);--color-rose-400:oklch(71.2% .194 13.428);--color-black:#000;--color-white:#fff;--spacing:.25rem;--container-sm:24rem;--container-lg:32rem;--container-3xl:48rem;--container-5xl:64rem;--text-xs:.75rem;--text-xs--line-height:calc(1 / .75);--text-sm:.875rem;--text-sm--line-height:calc(1.25 / .875);--text-2xl:1.5rem;--text-2xl--line-height:calc(2 / 1.5);--text-3xl:1.875rem;--text-3xl--line-height:calc(2.25 / 1.875);--text-5xl:3rem;--text-5xl--line-height:1;--text-6xl:3.75rem;--text-6xl--line-height:1;--font-weight-semibold:600;--font-weight-bold:700;--font-weight-extrabold:800;--font-weight-black:900;--tracking-normal:0em;--leading-tight:1.25;--leading-snug:1.375;--leading-relaxed:1.625;--animate-pulse:pulse 2s cubic-bezier(.4, 0, .6, 1) infinite;--default-transition-duration:.15s;--default-transition-timing-function:cubic-bezier(.4, 0, .2, 1);--default-font-family:var(--font-sans);--default-mono-font-family:var(--font-mono)}}@layer base{*,:after,:before,::backdrop{box-sizing:border-box;border:0 solid;margin:0;padding:0}::file-selector-button{box-sizing:border-box;border:0 solid;margin:0;padding:0}html,:host{-webkit-text-size-adjust:100%;tab-size:4;line-height:1.5;font-family:var(--default-font-family,ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji");font-feature-settings:var(--default-font-feature-settings,normal);font-variation-settings:var(--default-font-variation-settings,normal);-webkit-tap-highlight-color:transparent}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:var(--default-mono-font-family,ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace);font-feature-settings:var(--default-mono-font-feature-settings,normal);font-variation-settings:var(--default-mono-font-variation-settings,normal);font-size:1em}small{font-size:80%}sub,sup{vertical-align:baseline;font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}:-moz-focusring{outline:auto}progress{vertical-align:baseline}summary{display:list-item}ol,ul,menu{list-style:none}img,svg,video,canvas,audio,iframe,embed,object{vertical-align:middle;display:block}img,video{max-width:100%;height:auto}button,input,select,optgroup,textarea{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}::file-selector-button{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}:where(select:is([multiple],[size])) optgroup{font-weight:bolder}:where(select:is([multiple],[size])) optgroup option{padding-inline-start:20px}::file-selector-button{margin-inline-end:4px}::placeholder{opacity:1}@supports (not ((-webkit-appearance:-apple-pay-button))) or (contain-intrinsic-size:1px){::placeholder{color:currentColor}@supports (color:color-mix(in lab, red, red)){::placeholder{color:color-mix(in oklab, currentcolor 50%, transparent)}}}textarea{resize:vertical}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-date-and-time-value{min-height:1lh;text-align:inherit}::-webkit-datetime-edit{display:inline-flex}::-webkit-datetime-edit-fields-wrapper{padding:0}::-webkit-datetime-edit{padding-block:0}::-webkit-datetime-edit-year-field{padding-block:0}::-webkit-datetime-edit-month-field{padding-block:0}::-webkit-datetime-edit-day-field{padding-block:0}::-webkit-datetime-edit-hour-field{padding-block:0}::-webkit-datetime-edit-minute-field{padding-block:0}::-webkit-datetime-edit-second-field{padding-block:0}::-webkit-datetime-edit-millisecond-field{padding-block:0}::-webkit-datetime-edit-meridiem-field{padding-block:0}::-webkit-calendar-picker-indicator{line-height:1}:-moz-ui-invalid{box-shadow:none}button,input:where([type=button],[type=reset],[type=submit]){appearance:button}::file-selector-button{appearance:button}::-webkit-inner-spin-button{height:auto}::-webkit-outer-spin-button{height:auto}[hidden]:where(:not([hidden=until-found])){display:none!important}}@layer components;@layer utilities{.visible{visibility:visible}.absolute{position:absolute}.relative{position:relative}.static{position:static}.sticky{position:sticky}.top-0{top:calc(var(--spacing) * 0)}.bottom-0{bottom:calc(var(--spacing) * 0)}.left-0{left:calc(var(--spacing) * 0)}.z-10{z-index:10}.z-\[1\]{z-index:1}.col-span-full{grid-column:1/-1}.m-0{margin:calc(var(--spacing) * 0)}.my-4{margin-block:calc(var(--spacing) * 4)}.mt-0\.5{margin-top:calc(var(--spacing) * .5)}.mt-1{margin-top:calc(var(--spacing) * 1)}.mt-2{margin-top:calc(var(--spacing) * 2)}.mt-3{margin-top:calc(var(--spacing) * 3)}.mr-1{margin-right:calc(var(--spacing) * 1)}.mr-3{margin-right:calc(var(--spacing) * 3)}.mb-1{margin-bottom:calc(var(--spacing) * 1)}.mb-3{margin-bottom:calc(var(--spacing) * 3)}.mb-4{margin-bottom:calc(var(--spacing) * 4)}.mb-6{margin-bottom:calc(var(--spacing) * 6)}.-ml-1{margin-left:calc(var(--spacing) * -1)}.ml-1{margin-left:calc(var(--spacing) * 1)}.ml-1\.5{margin-left:calc(var(--spacing) * 1.5)}.block{display:block}.contents{display:contents}.flex{display:flex}.grid{display:grid}.hidden{display:none}.inline{display:inline}.inline-block{display:inline-block}.inline-flex{display:inline-flex}.table{display:table}.size-1\.5{width:calc(var(--spacing) * 1.5);height:calc(var(--spacing) * 1.5)}.size-2{width:calc(var(--spacing) * 2);height:calc(var(--spacing) * 2)}.size-2\.5{width:calc(var(--spacing) * 2.5);height:calc(var(--spacing) * 2.5)}.size-9{width:calc(var(--spacing) * 9);height:calc(var(--spacing) * 9)}.h-1\.5{height:calc(var(--spacing) * 1.5)}.max-h-\[60vh\]{max-height:60vh}.min-h-16{min-height:calc(var(--spacing) * 16)}.min-h-28{min-height:calc(var(--spacing) * 28)}.min-h-48{min-height:calc(var(--spacing) * 48)}.min-h-\[4\.5rem\]{min-height:4.5rem}.min-h-\[calc\(100vh-5rem\)\]{min-height:calc(100vh - 5rem)}.min-h-screen{min-height:100vh}.w-1{width:calc(var(--spacing) * 1)}.w-2{width:calc(var(--spacing) * 2)}.w-fit{width:fit-content}.w-full{width:100%}.w-px{width:1px}.max-w-3xl{max-width:var(--container-3xl)}.max-w-5xl{max-width:var(--container-5xl)}.max-w-full{max-width:100%}.max-w-lg{max-width:var(--container-lg)}.max-w-sm{max-width:var(--container-sm)}.min-w-0{min-width:calc(var(--spacing) * 0)}.min-w-64{min-width:calc(var(--spacing) * 64)}.flex-1{flex:1}.shrink-0{flex-shrink:0}.basis-1\/2{flex-basis:50%}.animate-pulse{animation:var(--animate-pulse)}.cursor-default{cursor:default}.cursor-pointer{cursor:pointer}.list-none{list-style-type:none}.grid-cols-\[0\.875rem_minmax\(0\,1fr\)\]{grid-template-columns:.875rem minmax(0,1fr)}.grid-cols-\[auto_minmax\(0\,1fr\)\]{grid-template-columns:auto minmax(0,1fr)}.grid-cols-\[auto_minmax\(0\,1fr\)_auto\]{grid-template-columns:auto minmax(0,1fr) auto}.grid-cols-\[minmax\(0\,1fr\)_auto\]{grid-template-columns:minmax(0,1fr) auto}.grid-cols-\[minmax\(0\,1fr\)_minmax\(12rem\,max-content\)\]{grid-template-columns:minmax(0,1fr) minmax(12rem,max-content)}.grid-cols-\[minmax\(13rem\,1\.7fr\)_minmax\(13rem\,1fr\)\]{grid-template-columns:minmax(13rem,1.7fr) minmax(13rem,1fr)}.grid-rows-\[auto_1fr\]{grid-template-rows:auto 1fr}.flex-col{flex-direction:column}.flex-wrap{flex-wrap:wrap}.place-items-center{place-items:center}.items-baseline{align-items:baseline}.items-center{align-items:center}.items-start{align-items:flex-start}.justify-between{justify-content:space-between}.justify-end{justify-content:flex-end}.justify-items-end{justify-items:end}.gap-0{gap:calc(var(--spacing) * 0)}.gap-1{gap:calc(var(--spacing) * 1)}.gap-1\.5{gap:calc(var(--spacing) * 1.5)}.gap-2{gap:calc(var(--spacing) * 2)}.gap-3{gap:calc(var(--spacing) * 3)}.gap-4{gap:calc(var(--spacing) * 4)}.gap-5{gap:calc(var(--spacing) * 5)}.gap-x-1{column-gap:calc(var(--spacing) * 1)}.gap-x-3{column-gap:calc(var(--spacing) * 3)}.gap-y-0\.5{row-gap:calc(var(--spacing) * .5)}.gap-y-1{row-gap:calc(var(--spacing) * 1)}.self-start{align-self:flex-start}.justify-self-end{justify-self:flex-end}.justify-self-start{justify-self:flex-start}.truncate{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.overflow-auto{overflow:auto}.overflow-hidden{overflow:hidden}.overflow-visible{overflow:visible}.rounded-full{border-radius:3.40282e38px}.border{border-style:var(--tw-border-style);border-width:1px}.border-0{border-style:var(--tw-border-style);border-width:0}.border-t{border-top-style:var(--tw-border-style);border-top-width:1px}.border-r{border-right-style:var(--tw-border-style);border-right-width:1px}.border-b{border-bottom-style:var(--tw-border-style);border-bottom-width:1px}.border-b-4{border-bottom-style:var(--tw-border-style);border-bottom-width:4px}.border-l{border-left-style:var(--tw-border-style);border-left-width:1px}.border-l-4{border-left-style:var(--tw-border-style);border-left-width:4px}.border-\[\#beaaff\]\/15{border-color:oklab(78.6663% .0494663 -.109708/.15)}.border-\[\#beaaff\]\/20{border-color:oklab(78.6663% .0494663 -.109708/.2)}.border-\[\#beaaff\]\/70{border-color:oklab(78.6663% .0494663 -.109708/.7)}.border-amber-300{border-color:var(--color-amber-300)}.border-amber-400\/25{border-color:#fcbb0040}@supports (color:color-mix(in lab, red, red)){.border-amber-400\/25{border-color:color-mix(in oklab, var(--color-amber-400) 25%, transparent)}}.border-emerald-300{border-color:var(--color-emerald-300)}.border-emerald-400\/25{border-color:#00d29440}@supports (color:color-mix(in lab, red, red)){.border-emerald-400\/25{border-color:color-mix(in oklab, var(--color-emerald-400) 25%, transparent)}}.border-rose-300{border-color:var(--color-rose-300)}.border-rose-400{border-color:var(--color-rose-400)}.border-rose-400\/25{border-color:#ff667f40}@supports (color:color-mix(in lab, red, red)){.border-rose-400\/25{border-color:color-mix(in oklab, var(--color-rose-400) 25%, transparent)}}.border-rose-400\/50{border-color:#ff667f80}@supports (color:color-mix(in lab, red, red)){.border-rose-400\/50{border-color:color-mix(in oklab, var(--color-rose-400) 50%, transparent)}}.border-white\/10{border-color:#ffffff1a}@supports (color:color-mix(in lab, red, red)){.border-white\/10{border-color:color-mix(in oklab, var(--color-white) 10%, transparent)}}.border-white\/15{border-color:#ffffff26}@supports (color:color-mix(in lab, red, red)){.border-white\/15{border-color:color-mix(in oklab, var(--color-white) 15%, transparent)}}.border-white\/30{border-color:#ffffff4d}@supports (color:color-mix(in lab, red, red)){.border-white\/30{border-color:color-mix(in oklab, var(--color-white) 30%, transparent)}}.border-b-\[\#beaaff\]{border-bottom-color:#beaaff}.border-b-transparent{border-bottom-color:#0000}.border-b-white\/10{border-bottom-color:#ffffff1a}@supports (color:color-mix(in lab, red, red)){.border-b-white\/10{border-bottom-color:color-mix(in oklab, var(--color-white) 10%, transparent)}}.border-l-\[\#888\]{border-left-color:#888}.border-l-\[\#beaaff\]\/60{border-left-color:oklab(78.6663% .0494663 -.109708/.6)}.border-l-amber-300{border-left-color:var(--color-amber-300)}.border-l-amber-400{border-left-color:var(--color-amber-400)}.border-l-emerald-400{border-left-color:var(--color-emerald-400)}.border-l-rose-400{border-left-color:var(--color-rose-400)}.border-l-violet-300{border-left-color:var(--color-violet-300)}.border-l-white{border-left-color:var(--color-white)}.border-l-white\/25{border-left-color:#ffffff40}@supports (color:color-mix(in lab, red, red)){.border-l-white\/25{border-left-color:color-mix(in oklab, var(--color-white) 25%, transparent)}}.border-l-white\/35{border-left-color:#ffffff59}@supports (color:color-mix(in lab, red, red)){.border-l-white\/35{border-left-color:color-mix(in oklab, var(--color-white) 35%, transparent)}}.border-l-white\/70{border-left-color:#ffffffb3}@supports (color:color-mix(in lab, red, red)){.border-l-white\/70{border-left-color:color-mix(in oklab, var(--color-white) 70%, transparent)}}.bg-\[\#0b0b0b\]{background-color:#0b0b0b}.bg-\[\#111\]{background-color:#111}.bg-\[\#050505\]{background-color:#050505}.bg-\[\#050505\]\/95{background-color:oklab(11.4918% 7.45058e-9 7.45058e-9/.95)}.bg-\[\#b8b8b8\]{background-color:#b8b8b8}.bg-\[\#beaaff\]\/20{background-color:oklab(78.6663% .0494663 -.109708/.2)}.bg-\[\#beaaff\]\/50{background-color:oklab(78.6663% .0494663 -.109708/.5)}.bg-\[rgba\(190\,170\,255\,0\.08\)\]{background-color:#beaaff14}.bg-amber-300{background-color:var(--color-amber-300)}.bg-amber-300\/\[0\.06\]{background-color:#ffd2360f}@supports (color:color-mix(in lab, red, red)){.bg-amber-300\/\[0\.06\]{background-color:color-mix(in oklab, var(--color-amber-300) 6%, transparent)}}.bg-amber-400{background-color:var(--color-amber-400)}.bg-amber-400\/10{background-color:#fcbb001a}@supports (color:color-mix(in lab, red, red)){.bg-amber-400\/10{background-color:color-mix(in oklab, var(--color-amber-400) 10%, transparent)}}.bg-black{background-color:var(--color-black)}.bg-emerald-300{background-color:var(--color-emerald-300)}.bg-emerald-400\/10{background-color:#00d2941a}@supports (color:color-mix(in lab, red, red)){.bg-emerald-400\/10{background-color:color-mix(in oklab, var(--color-emerald-400) 10%, transparent)}}.bg-rose-300{background-color:var(--color-rose-300)}.bg-rose-400{background-color:var(--color-rose-400)}.bg-rose-400\/10{background-color:#ff667f1a}@supports (color:color-mix(in lab, red, red)){.bg-rose-400\/10{background-color:color-mix(in oklab, var(--color-rose-400) 10%, transparent)}}.bg-transparent{background-color:#0000}.bg-white{background-color:var(--color-white)}.bg-white\/20{background-color:#fff3}@supports (color:color-mix(in lab, red, red)){.bg-white\/20{background-color:color-mix(in oklab, var(--color-white) 20%, transparent)}}.bg-white\/35{background-color:#ffffff59}@supports (color:color-mix(in lab, red, red)){.bg-white\/35{background-color:color-mix(in oklab, var(--color-white) 35%, transparent)}}.bg-white\/\[0\.03\]{background-color:#ffffff08}@supports (color:color-mix(in lab, red, red)){.bg-white\/\[0\.03\]{background-color:color-mix(in oklab, var(--color-white) 3%, transparent)}}.bg-white\/\[0\.04\]{background-color:#ffffff0a}@supports (color:color-mix(in lab, red, red)){.bg-white\/\[0\.04\]{background-color:color-mix(in oklab, var(--color-white) 4%, transparent)}}.p-0{padding:calc(var(--spacing) * 0)}.p-3{padding:calc(var(--spacing) * 3)}.p-4{padding:calc(var(--spacing) * 4)}.p-5{padding:calc(var(--spacing) * 5)}.p-8{padding:calc(var(--spacing) * 8)}.px-0\.5{padding-inline:calc(var(--spacing) * .5)}.px-1{padding-inline:calc(var(--spacing) * 1)}.px-1\.5{padding-inline:calc(var(--spacing) * 1.5)}.px-2{padding-inline:calc(var(--spacing) * 2)}.px-3{padding-inline:calc(var(--spacing) * 3)}.px-4{padding-inline:calc(var(--spacing) * 4)}.py-0\.5{padding-block:calc(var(--spacing) * .5)}.py-1{padding-block:calc(var(--spacing) * 1)}.py-2{padding-block:calc(var(--spacing) * 2)}.py-2\.5{padding-block:calc(var(--spacing) * 2.5)}.py-3{padding-block:calc(var(--spacing) * 3)}.py-4{padding-block:calc(var(--spacing) * 4)}.py-5{padding-block:calc(var(--spacing) * 5)}.py-8{padding-block:calc(var(--spacing) * 8)}.pt-2{padding-top:calc(var(--spacing) * 2)}.pt-3{padding-top:calc(var(--spacing) * 3)}.pt-4{padding-top:calc(var(--spacing) * 4)}.pr-3{padding-right:calc(var(--spacing) * 3)}.pb-1\.5{padding-bottom:calc(var(--spacing) * 1.5)}.pb-2{padding-bottom:calc(var(--spacing) * 2)}.pb-3{padding-bottom:calc(var(--spacing) * 3)}.pl-3{padding-left:calc(var(--spacing) * 3)}.pl-4{padding-left:calc(var(--spacing) * 4)}.pl-5{padding-left:calc(var(--spacing) * 5)}.text-left{text-align:left}.text-right{text-align:right}.font-\[inherit\]{font-family:inherit}.font-mono{font-family:var(--font-mono)}.font-sans{font-family:var(--font-sans)}.text-2xl{font-size:var(--text-2xl);line-height:var(--tw-leading,var(--text-2xl--line-height))}.text-3xl{font-size:var(--text-3xl);line-height:var(--tw-leading,var(--text-3xl--line-height))}.text-5xl{font-size:var(--text-5xl);line-height:var(--tw-leading,var(--text-5xl--line-height))}.text-sm{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}.text-xs{font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height))}.text-\[0\.8rem\]{font-size:.8rem}.text-\[0\.9rem\]{font-size:.9rem}.text-\[0\.68rem\]{font-size:.68rem}.text-\[0\.72rem\]{font-size:.72rem}.text-\[0\.76rem\]{font-size:.76rem}.text-\[0\.78rem\]{font-size:.78rem}.text-\[0\.82rem\]{font-size:.82rem}.text-\[0\.84rem\]{font-size:.84rem}.text-\[0\.86rem\]{font-size:.86rem}.text-\[0\.88rem\]{font-size:.88rem}.text-\[0\.92rem\]{font-size:.92rem}.text-\[0\.98rem\]{font-size:.98rem}.text-\[1\.04rem\]{font-size:1.04rem}.text-\[1\.05rem\]{font-size:1.05rem}.text-\[1\.75rem\]{font-size:1.75rem}.leading-\[1\.45\]{--tw-leading:1.45;line-height:1.45}.leading-none{--tw-leading:1;line-height:1}.leading-relaxed{--tw-leading:var(--leading-relaxed);line-height:var(--leading-relaxed)}.leading-snug{--tw-leading:var(--leading-snug);line-height:var(--leading-snug)}.leading-tight{--tw-leading:var(--leading-tight);line-height:var(--leading-tight)}.font-black{--tw-font-weight:var(--font-weight-black);font-weight:var(--font-weight-black)}.font-bold{--tw-font-weight:var(--font-weight-bold);font-weight:var(--font-weight-bold)}.font-extrabold{--tw-font-weight:var(--font-weight-extrabold);font-weight:var(--font-weight-extrabold)}.font-semibold{--tw-font-weight:var(--font-weight-semibold);font-weight:var(--font-weight-semibold)}.tracking-normal{--tw-tracking:var(--tracking-normal);letter-spacing:var(--tracking-normal)}.break-words{overflow-wrap:break-word}.break-all{word-break:break-all}.whitespace-nowrap{white-space:nowrap}.whitespace-pre-wrap{white-space:pre-wrap}.text-\[\#666\]{color:#666}.text-\[\#777\]{color:#777}.text-\[\#888\]{color:#888}.text-\[\#b8b8b8\]{color:#b8b8b8}.text-\[\#d6d6d6\]{color:#d6d6d6}.text-\[\#d8ccff\]{color:#d8ccff}.text-\[\#f4f4f4\]{color:#f4f4f4}.text-amber-200{color:var(--color-amber-200)}.text-amber-300{color:var(--color-amber-300)}.text-black{color:var(--color-black)}.text-emerald-300{color:var(--color-emerald-300)}.text-inherit{color:inherit}.text-rose-300{color:var(--color-rose-300)}.text-violet-200{color:var(--color-violet-200)}.text-white{color:var(--color-white)}.lowercase{text-transform:lowercase}.uppercase{text-transform:uppercase}.no-underline{text-decoration-line:none}.underline{text-decoration-line:underline}.decoration-white{-webkit-text-decoration-color:var(--color-white);-webkit-text-decoration-color:var(--color-white);text-decoration-color:var(--color-white)}.underline-offset-4{text-underline-offset:4px}.\[color-scheme\:dark\]{color-scheme:dark}.saturate-50{--tw-saturate:saturate(50%);filter:var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,)}.filter{filter:var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,)}.backdrop-blur{--tw-backdrop-blur:blur(8px);-webkit-backdrop-filter:var(--tw-backdrop-blur,) var(--tw-backdrop-brightness,) var(--tw-backdrop-contrast,) var(--tw-backdrop-grayscale,) var(--tw-backdrop-hue-rotate,) var(--tw-backdrop-invert,) var(--tw-backdrop-opacity,) var(--tw-backdrop-saturate,) var(--tw-backdrop-sepia,);backdrop-filter:var(--tw-backdrop-blur,) var(--tw-backdrop-brightness,) var(--tw-backdrop-contrast,) var(--tw-backdrop-grayscale,) var(--tw-backdrop-hue-rotate,) var(--tw-backdrop-invert,) var(--tw-backdrop-opacity,) var(--tw-backdrop-saturate,) var(--tw-backdrop-sepia,)}.transition-\[filter\,stroke\,stroke-width\]{transition-property:filter,stroke,stroke-width;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-colors{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.outline-none{--tw-outline-style:none;outline-style:none}.select-none{-webkit-user-select:none;user-select:none}.first\:border-t-0:first-child{border-top-style:var(--tw-border-style);border-top-width:0}.last\:border-b-0:last-child{border-bottom-style:var(--tw-border-style);border-bottom-width:0}@media (hover:hover){.hover\:border-\[\#beaaff\]\/45:hover{border-color:oklab(78.6663% .0494663 -.109708/.45)}.hover\:border-white:hover{border-color:var(--color-white)}.hover\:border-white\/25:hover{border-color:#ffffff40}@supports (color:color-mix(in lab, red, red)){.hover\:border-white\/25:hover{border-color:color-mix(in oklab, var(--color-white) 25%, transparent)}}.hover\:border-white\/30:hover{border-color:#ffffff4d}@supports (color:color-mix(in lab, red, red)){.hover\:border-white\/30:hover{border-color:color-mix(in oklab, var(--color-white) 30%, transparent)}}.hover\:border-b-white\/45:hover{border-bottom-color:#ffffff73}@supports (color:color-mix(in lab, red, red)){.hover\:border-b-white\/45:hover{border-bottom-color:color-mix(in oklab, var(--color-white) 45%, transparent)}}.hover\:bg-\[\#151515\]:hover{background-color:#151515}.hover\:bg-\[rgba\(190\,170\,255\,0\.06\)\]:hover{background-color:#beaaff0f}.hover\:bg-\[rgba\(190\,170\,255\,0\.07\)\]:hover{background-color:#beaaff12}.hover\:bg-white\/\[0\.04\]:hover{background-color:#ffffff0a}@supports (color:color-mix(in lab, red, red)){.hover\:bg-white\/\[0\.04\]:hover{background-color:color-mix(in oklab, var(--color-white) 4%, transparent)}}.hover\:bg-white\/\[0\.05\]:hover{background-color:#ffffff0d}@supports (color:color-mix(in lab, red, red)){.hover\:bg-white\/\[0\.05\]:hover{background-color:color-mix(in oklab, var(--color-white) 5%, transparent)}}.hover\:text-white:hover{color:var(--color-white)}.hover\:underline:hover{text-decoration-line:underline}.hover\:brightness-125:hover{--tw-brightness:brightness(125%);filter:var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,)}}.focus-visible\:stroke-emerald-400:focus-visible{stroke:var(--color-emerald-400)}.focus-visible\:stroke-2:focus-visible{stroke-width:2px}@media not all and (min-width:48rem){.max-md\:hidden{display:none}.max-md\:w-full{width:100%}.max-md\:grid-cols-1{grid-template-columns:repeat(1,minmax(0,1fr))}.max-md\:flex-col{flex-direction:column}.max-md\:flex-wrap{flex-wrap:wrap}.max-md\:items-stretch{align-items:stretch}.max-md\:justify-between{justify-content:space-between}.max-md\:justify-items-start{justify-items:start}.max-md\:gap-1{gap:calc(var(--spacing) * 1)}.max-md\:px-4{padding-inline:calc(var(--spacing) * 4)}.max-md\:py-4{padding-block:calc(var(--spacing) * 4)}.max-md\:text-left{text-align:left}}@media (min-width:40rem){.sm\:basis-1\/3{flex-basis:33.3333%}}@media (min-width:48rem){.md\:grid-cols-\[minmax\(0\,1fr\)_auto\]{grid-template-columns:minmax(0,1fr) auto}.md\:truncate{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.md\:px-8{padding-inline:calc(var(--spacing) * 8)}.md\:text-right{text-align:right}.md\:text-6xl{font-size:var(--text-6xl);line-height:var(--tw-leading,var(--text-6xl--line-height))}}@media (min-width:64rem){.lg\:grid-cols-\[minmax\(21rem\,0\.32fr\)_minmax\(0\,1fr\)\]{grid-template-columns:minmax(21rem,.32fr) minmax(0,1fr)}}.\[\&_code\]\:break-words code{overflow-wrap:break-word}.\[\&_code\]\:whitespace-pre-wrap code{white-space:pre-wrap}.\[\&_pre\]\:\!m-0 pre{margin:calc(var(--spacing) * 0)!important}.\[\&_pre\]\:\!overflow-visible pre{overflow:visible!important}.\[\&_pre\]\:\!bg-transparent pre{background-color:#0000!important}.\[\&_pre\]\:\!p-0 pre{padding:calc(var(--spacing) * 0)!important}.\[\&_pre\]\:font-mono pre{font-family:var(--font-mono)}.\[\&_pre\]\:text-\[0\.86rem\] pre{font-size:.86rem}.\[\&_pre\]\:leading-relaxed pre{--tw-leading:var(--leading-relaxed);line-height:var(--leading-relaxed)}.\[\&_pre\]\:break-words pre{overflow-wrap:break-word}.\[\&_pre\]\:whitespace-pre-wrap pre{white-space:pre-wrap}.\[\&\:\:-webkit-details-marker\]\:hidden::-webkit-details-marker{display:none}}@property --tw-border-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-leading{syntax:"*";inherits:false}@property --tw-font-weight{syntax:"*";inherits:false}@property --tw-tracking{syntax:"*";inherits:false}@property --tw-blur{syntax:"*";inherits:false}@property --tw-brightness{syntax:"*";inherits:false}@property --tw-contrast{syntax:"*";inherits:false}@property --tw-grayscale{syntax:"*";inherits:false}@property --tw-hue-rotate{syntax:"*";inherits:false}@property --tw-invert{syntax:"*";inherits:false}@property --tw-opacity{syntax:"*";inherits:false}@property --tw-saturate{syntax:"*";inherits:false}@property --tw-sepia{syntax:"*";inherits:false}@property --tw-drop-shadow{syntax:"*";inherits:false}@property --tw-drop-shadow-color{syntax:"*";inherits:false}@property --tw-drop-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-drop-shadow-size{syntax:"*";inherits:false}@property --tw-backdrop-blur{syntax:"*";inherits:false}@property --tw-backdrop-brightness{syntax:"*";inherits:false}@property --tw-backdrop-contrast{syntax:"*";inherits:false}@property --tw-backdrop-grayscale{syntax:"*";inherits:false}@property --tw-backdrop-hue-rotate{syntax:"*";inherits:false}@property --tw-backdrop-invert{syntax:"*";inherits:false}@property --tw-backdrop-opacity{syntax:"*";inherits:false}@property --tw-backdrop-saturate{syntax:"*";inherits:false}@property --tw-backdrop-sepia{syntax:"*";inherits:false}@keyframes pulse{50%{opacity:.5}}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sentry/junior-dashboard",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.61.0",
|
|
4
4
|
"private": false,
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
@@ -39,7 +39,7 @@
|
|
|
39
39
|
"react-router": "^7.16.0",
|
|
40
40
|
"recharts": "^3.8.1",
|
|
41
41
|
"shiki": "4.1.0",
|
|
42
|
-
"@sentry/junior": "0.
|
|
42
|
+
"@sentry/junior": "0.61.0"
|
|
43
43
|
},
|
|
44
44
|
"devDependencies": {
|
|
45
45
|
"@tailwindcss/cli": "^4.3.0",
|
package/src/client/code.tsx
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { useState } from "react";
|
|
1
2
|
import { useQuery } from "@tanstack/react-query";
|
|
2
3
|
import { codeToHtml, type BundledLanguage } from "shiki/bundle/web";
|
|
3
4
|
|
|
@@ -6,7 +7,7 @@ import type { CodeBlock, MarkupNode } from "./types";
|
|
|
6
7
|
|
|
7
8
|
/** Count rendered children so transcripts can decide which markup node expands. */
|
|
8
9
|
export function countStructuredBlockChildren(block: CodeBlock): number {
|
|
9
|
-
if (!canRenderStructuredMarkup(block
|
|
10
|
+
if (!canRenderStructuredMarkup(block)) return 1;
|
|
10
11
|
const rootCount = parseMarkupNodes(block.code, block.language).length;
|
|
11
12
|
return rootCount > 0 ? rootCount : 1;
|
|
12
13
|
}
|
|
@@ -53,8 +54,18 @@ function MarkupNodeView(props: { defaultOpen?: boolean; node: MarkupNode }) {
|
|
|
53
54
|
);
|
|
54
55
|
}
|
|
55
56
|
|
|
57
|
+
return (
|
|
58
|
+
<MarkupElementView defaultOpen={props.defaultOpen} node={props.node} />
|
|
59
|
+
);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
function MarkupElementView(props: {
|
|
63
|
+
defaultOpen?: boolean;
|
|
64
|
+
node: Extract<MarkupNode, { type: "element" }>;
|
|
65
|
+
}) {
|
|
56
66
|
const children = props.node.children;
|
|
57
67
|
const hasChildren = children.length > 0;
|
|
68
|
+
const [open, setOpen] = useState(props.defaultOpen ?? true);
|
|
58
69
|
const attributes = props.node.attributes.map(([name, value]) => (
|
|
59
70
|
<span className="ml-1.5 text-[#b8b8b8]" key={name}>
|
|
60
71
|
{name}=<span className="text-white">"{value}"</span>
|
|
@@ -74,12 +85,15 @@ function MarkupNodeView(props: { defaultOpen?: boolean; node: MarkupNode }) {
|
|
|
74
85
|
|
|
75
86
|
return (
|
|
76
87
|
<details
|
|
77
|
-
className="
|
|
78
|
-
|
|
88
|
+
className="min-w-0 break-words"
|
|
89
|
+
onToggle={(event) => {
|
|
90
|
+
if (event.currentTarget !== event.target) return;
|
|
91
|
+
setOpen(event.currentTarget.open);
|
|
92
|
+
}}
|
|
93
|
+
open={open}
|
|
79
94
|
>
|
|
80
95
|
<summary className="-ml-1 flex w-full max-w-full cursor-pointer list-none flex-wrap items-baseline px-1 py-0.5 transition-colors hover:bg-white/[0.05] hover:text-white [&::-webkit-details-marker]:hidden">
|
|
81
|
-
<span className="mr-1 w-2 text-white
|
|
82
|
-
<span className="mr-1 hidden w-2 text-white group-open:inline">-</span>
|
|
96
|
+
<span className="mr-1 w-2 text-white">{open ? "-" : "+"}</span>
|
|
83
97
|
<span className="text-[#888]"><</span>
|
|
84
98
|
<span className="font-bold text-white">{props.node.tagName}</span>
|
|
85
99
|
{attributes}
|
|
@@ -1,4 +1,8 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
formatDurationTotal,
|
|
3
|
+
formatUsageTotal,
|
|
4
|
+
slackLocationLabel,
|
|
5
|
+
} from "../format";
|
|
2
6
|
import type { Conversation } from "../types";
|
|
3
7
|
|
|
4
8
|
/** Render compact conversation metadata aligned to row context. */
|
|
@@ -6,14 +10,30 @@ export function ConversationRowStats(props: {
|
|
|
6
10
|
conversation: Conversation;
|
|
7
11
|
timeLabel: string;
|
|
8
12
|
}) {
|
|
13
|
+
const tokens = formatUsageTotal(
|
|
14
|
+
props.conversation.turns.map((turn) => turn.cumulativeUsage),
|
|
15
|
+
);
|
|
16
|
+
const runtime = formatDurationTotal(
|
|
17
|
+
props.conversation.turns.map((turn) => turn.cumulativeDurationMs),
|
|
18
|
+
);
|
|
19
|
+
const primaryStats = [
|
|
20
|
+
`${props.conversation.turns.length} turns`,
|
|
21
|
+
tokens,
|
|
22
|
+
runtime ? `${runtime} runtime` : undefined,
|
|
23
|
+
].filter(Boolean);
|
|
24
|
+
const secondaryStats = [
|
|
25
|
+
props.timeLabel,
|
|
26
|
+
slackLocationLabel(props.conversation, { includeId: false }),
|
|
27
|
+
].filter(Boolean);
|
|
28
|
+
|
|
9
29
|
return (
|
|
10
30
|
<div className="grid min-w-0 justify-items-end gap-1 text-right max-md:justify-items-start max-md:text-left">
|
|
11
31
|
<div className="text-[0.84rem] leading-relaxed text-[#b8b8b8]">
|
|
12
|
-
{
|
|
32
|
+
{primaryStats.join(" · ")}
|
|
13
33
|
</div>
|
|
14
|
-
{
|
|
34
|
+
{secondaryStats.length > 0 ? (
|
|
15
35
|
<div className="max-w-full break-words text-[0.84rem] leading-relaxed text-[#888] md:truncate">
|
|
16
|
-
{
|
|
36
|
+
{secondaryStats.join(" · ")}
|
|
17
37
|
</div>
|
|
18
38
|
) : null}
|
|
19
39
|
</div>
|
|
@@ -21,7 +21,7 @@ export function TranscriptText(props: {
|
|
|
21
21
|
const childCount = countStructuredBlockChildren(block);
|
|
22
22
|
seenChildren += childCount;
|
|
23
23
|
|
|
24
|
-
if (!canRenderStructuredMarkup(block
|
|
24
|
+
if (!canRenderStructuredMarkup(block)) {
|
|
25
25
|
return (
|
|
26
26
|
<HighlightedCode
|
|
27
27
|
code={block.code}
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import { useState, type ClipboardEventHandler, type ReactNode } from "react";
|
|
2
2
|
|
|
3
3
|
import { HighlightedCode } from "../code";
|
|
4
4
|
import {
|
|
5
5
|
detectLanguage,
|
|
6
|
+
detectOutputLanguage,
|
|
6
7
|
formatBytes,
|
|
7
8
|
formatMessageOffset,
|
|
8
9
|
formatMessageTimestamp,
|
|
@@ -450,19 +451,7 @@ function TranscriptPartView(props: {
|
|
|
450
451
|
|
|
451
452
|
const value = part.output;
|
|
452
453
|
if (part.type === "thinking") {
|
|
453
|
-
|
|
454
|
-
return (
|
|
455
|
-
<details className="border border-[#beaaff]/20 bg-white/[0.03] transition-colors hover:border-[#beaaff]/45 hover:bg-[rgba(190,170,255,0.06)]">
|
|
456
|
-
<summary className="grid cursor-pointer grid-cols-[auto_minmax(0,1fr)] items-center gap-3 px-3 py-2 font-mono text-[0.8rem] leading-tight text-[#888] hover:bg-[rgba(190,170,255,0.07)] max-md:grid-cols-1 max-md:gap-1">
|
|
457
|
-
<span className="uppercase text-[#b8b8b8]">thinking</span>
|
|
458
|
-
<span className="min-w-0 truncate">{previewToolValue(value)}</span>
|
|
459
|
-
</summary>
|
|
460
|
-
<HighlightedCode
|
|
461
|
-
code={rendered || "{}"}
|
|
462
|
-
language={detectLanguage(rendered)}
|
|
463
|
-
/>
|
|
464
|
-
</details>
|
|
465
|
-
);
|
|
454
|
+
return <ThinkingPartView value={value} />;
|
|
466
455
|
}
|
|
467
456
|
|
|
468
457
|
const rendered = stringifyPartValue(value);
|
|
@@ -482,6 +471,37 @@ function TranscriptPartView(props: {
|
|
|
482
471
|
);
|
|
483
472
|
}
|
|
484
473
|
|
|
474
|
+
function ThinkingPartView(props: { value: unknown }) {
|
|
475
|
+
const [open, setOpen] = useState(false);
|
|
476
|
+
const rendered = stringifyPartValue(props.value);
|
|
477
|
+
|
|
478
|
+
return (
|
|
479
|
+
<details
|
|
480
|
+
className="border border-[#beaaff]/20 bg-white/[0.03] transition-colors hover:border-[#beaaff]/45 hover:bg-[rgba(190,170,255,0.06)]"
|
|
481
|
+
onToggle={(event) => {
|
|
482
|
+
if (event.currentTarget !== event.target) return;
|
|
483
|
+
setOpen(event.currentTarget.open);
|
|
484
|
+
}}
|
|
485
|
+
open={open}
|
|
486
|
+
>
|
|
487
|
+
<summary className="grid cursor-pointer grid-cols-[auto_minmax(0,1fr)] items-center gap-3 px-3 py-2 font-mono text-[0.8rem] leading-tight text-[#888] hover:bg-[rgba(190,170,255,0.07)] max-md:grid-cols-1 max-md:gap-1">
|
|
488
|
+
<span className="uppercase text-[#b8b8b8]">thinking</span>
|
|
489
|
+
{open ? null : (
|
|
490
|
+
<span className="min-w-0 truncate">
|
|
491
|
+
{previewToolValue(props.value)}
|
|
492
|
+
</span>
|
|
493
|
+
)}
|
|
494
|
+
</summary>
|
|
495
|
+
<div className="border-t border-[#beaaff]/15 px-3 py-3">
|
|
496
|
+
<HighlightedCode
|
|
497
|
+
code={rendered || "{}"}
|
|
498
|
+
language={detectOutputLanguage(rendered)}
|
|
499
|
+
/>
|
|
500
|
+
</div>
|
|
501
|
+
</details>
|
|
502
|
+
);
|
|
503
|
+
}
|
|
504
|
+
|
|
485
505
|
function isString(value: string | undefined): value is string {
|
|
486
506
|
return typeof value === "string" && value.length > 0;
|
|
487
507
|
}
|
package/src/client/format.ts
CHANGED
|
@@ -104,6 +104,17 @@ export function formatMs(value: number | undefined): string {
|
|
|
104
104
|
return `${minutes}m ${remainingSeconds}s`;
|
|
105
105
|
}
|
|
106
106
|
|
|
107
|
+
/** Format aggregate runtime across turn summaries when duration data exists. */
|
|
108
|
+
export function formatDurationTotal(
|
|
109
|
+
durations: Array<number | undefined>,
|
|
110
|
+
): string {
|
|
111
|
+
const total = durations.reduce<number | undefined>((sum, value) => {
|
|
112
|
+
if (typeof value !== "number" || !Number.isFinite(value)) return sum;
|
|
113
|
+
return (sum ?? 0) + Math.max(0, Math.floor(value));
|
|
114
|
+
}, undefined);
|
|
115
|
+
return total === undefined ? "" : formatMs(total);
|
|
116
|
+
}
|
|
117
|
+
|
|
107
118
|
/** Format transcript event timestamps independently from turn start offsets. */
|
|
108
119
|
export function formatMessageTimestamp(value: number | undefined): string {
|
|
109
120
|
if (typeof value !== "number" || !Number.isFinite(value))
|
|
@@ -151,6 +162,25 @@ function formatNumber(value: number | undefined): string {
|
|
|
151
162
|
return `${formatted}${suffix}`;
|
|
152
163
|
}
|
|
153
164
|
|
|
165
|
+
function getFiniteTokenCount(value: unknown): number | undefined {
|
|
166
|
+
return typeof value === "number" && Number.isFinite(value)
|
|
167
|
+
? Math.max(0, Math.floor(value))
|
|
168
|
+
: undefined;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
function getUsageComponentTotal(usage: TurnUsage): number | undefined {
|
|
172
|
+
return [
|
|
173
|
+
usage.inputTokens,
|
|
174
|
+
usage.outputTokens,
|
|
175
|
+
usage.cachedInputTokens,
|
|
176
|
+
usage.cacheCreationTokens,
|
|
177
|
+
].reduce<number | undefined>((sum, value) => {
|
|
178
|
+
const count = getFiniteTokenCount(value);
|
|
179
|
+
if (count === undefined) return sum;
|
|
180
|
+
return (sum ?? 0) + count;
|
|
181
|
+
}, undefined);
|
|
182
|
+
}
|
|
183
|
+
|
|
154
184
|
/** Format byte counts in lowercase compact units for transcript metadata. */
|
|
155
185
|
export function formatBytes(value: number | undefined): string {
|
|
156
186
|
if (typeof value !== "number" || !Number.isFinite(value)) return "0b";
|
|
@@ -174,9 +204,36 @@ function transcriptSource(turn: ConversationTurn) {
|
|
|
174
204
|
: (turn.transcriptMetadata ?? []);
|
|
175
205
|
}
|
|
176
206
|
|
|
207
|
+
function isConversationMessageRole(role: string): boolean {
|
|
208
|
+
const normalized = role.toLowerCase();
|
|
209
|
+
return normalized === "user" || normalized === "assistant";
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
function hasTextPart(
|
|
213
|
+
message: Pick<ConversationTurn["transcript"][number], "parts" | "role">,
|
|
214
|
+
): boolean {
|
|
215
|
+
return message.parts.some((part) => {
|
|
216
|
+
if (part.type !== "text") return false;
|
|
217
|
+
if (part.redacted) return true;
|
|
218
|
+
return typeof part.text === "string" && part.text.trim().length > 0;
|
|
219
|
+
});
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
function isConversationMessage(
|
|
223
|
+
message: Pick<ConversationTurn["transcript"][number], "parts" | "role">,
|
|
224
|
+
): boolean {
|
|
225
|
+
if (!isConversationMessageRole(message.role)) return false;
|
|
226
|
+
if (message.role.toLowerCase() === "assistant") return hasTextPart(message);
|
|
227
|
+
return message.parts.length > 0;
|
|
228
|
+
}
|
|
229
|
+
|
|
177
230
|
/** Count visible or redacted message records for a turn. */
|
|
178
231
|
export function turnMessageCount(turn: ConversationTurn): number {
|
|
179
|
-
|
|
232
|
+
const source = transcriptSource(turn);
|
|
233
|
+
if (source.length > 0) {
|
|
234
|
+
return source.filter(isConversationMessage).length;
|
|
235
|
+
}
|
|
236
|
+
return turn.transcriptMessageCount ?? 0;
|
|
180
237
|
}
|
|
181
238
|
|
|
182
239
|
/** Count tool calls from visible transcripts or safe redacted metadata. */
|
|
@@ -190,21 +247,9 @@ export function turnToolCallCount(turn: ConversationTurn): number {
|
|
|
190
247
|
|
|
191
248
|
function totalUsageTokens(usage: TurnUsage | undefined): number | undefined {
|
|
192
249
|
if (!usage) return undefined;
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
) {
|
|
197
|
-
return usage.totalTokens;
|
|
198
|
-
}
|
|
199
|
-
return [
|
|
200
|
-
usage.inputTokens,
|
|
201
|
-
usage.outputTokens,
|
|
202
|
-
usage.cachedInputTokens,
|
|
203
|
-
usage.cacheCreationTokens,
|
|
204
|
-
].reduce<number | undefined>((sum, value) => {
|
|
205
|
-
if (typeof value !== "number" || !Number.isFinite(value)) return sum;
|
|
206
|
-
return (sum ?? 0) + Math.max(0, Math.floor(value));
|
|
207
|
-
}, undefined);
|
|
250
|
+
return (
|
|
251
|
+
getUsageComponentTotal(usage) ?? getFiniteTokenCount(usage.totalTokens)
|
|
252
|
+
);
|
|
208
253
|
}
|
|
209
254
|
|
|
210
255
|
/** Format known token counters without estimating per-message usage. */
|
|
@@ -213,6 +258,16 @@ export function formatTokenTotal(usage: TurnUsage | undefined): string {
|
|
|
213
258
|
return total === undefined ? "" : `${formatNumber(total)} tokens`;
|
|
214
259
|
}
|
|
215
260
|
|
|
261
|
+
/** Format the aggregate token count across conversation turns. */
|
|
262
|
+
export function formatUsageTotal(usages: Array<TurnUsage | undefined>): string {
|
|
263
|
+
const total = usages.reduce<number | undefined>((sum, usage) => {
|
|
264
|
+
const tokens = totalUsageTokens(usage);
|
|
265
|
+
if (tokens === undefined) return sum;
|
|
266
|
+
return (sum ?? 0) + tokens;
|
|
267
|
+
}, undefined);
|
|
268
|
+
return total === undefined ? "" : `${formatNumber(total)} tokens`;
|
|
269
|
+
}
|
|
270
|
+
|
|
216
271
|
/** Format known token counters with available input/output detail. */
|
|
217
272
|
export function formatUsage(usage: TurnUsage | undefined): string {
|
|
218
273
|
const total = totalUsageTokens(usage);
|
|
@@ -456,9 +511,34 @@ function formatCodeBlock(code: string, language: BundledLanguage): string {
|
|
|
456
511
|
return language === "json" ? (prettyJsonData(code) ?? code) : code;
|
|
457
512
|
}
|
|
458
513
|
|
|
459
|
-
/**
|
|
460
|
-
|
|
461
|
-
|
|
514
|
+
/**
|
|
515
|
+
* Detect the language for LLM text output prose: json if the text is valid
|
|
516
|
+
* JSON or JSONL, markdown otherwise. Never auto-detects XML, HTML, TypeScript,
|
|
517
|
+
* or shell — those heuristics are unreliable for rendered assistant output.
|
|
518
|
+
*/
|
|
519
|
+
export function detectOutputLanguage(text: string): BundledLanguage {
|
|
520
|
+
const trimmed = text.trim();
|
|
521
|
+
if (!trimmed) return "markdown";
|
|
522
|
+
try {
|
|
523
|
+
JSON.parse(trimmed);
|
|
524
|
+
return "json";
|
|
525
|
+
} catch {
|
|
526
|
+
// continue
|
|
527
|
+
}
|
|
528
|
+
if (prettyJsonl(trimmed)) return "json";
|
|
529
|
+
return "markdown";
|
|
530
|
+
}
|
|
531
|
+
|
|
532
|
+
/**
|
|
533
|
+
* Decide whether a fenced block can use the interactive markup renderer.
|
|
534
|
+
* Structured XML/HTML rendering is only enabled for explicitly-fenced blocks;
|
|
535
|
+
* auto-detected prose is never eligible regardless of inferred language.
|
|
536
|
+
*/
|
|
537
|
+
export function canRenderStructuredMarkup(block: CodeBlock): boolean {
|
|
538
|
+
return (
|
|
539
|
+
block.fenced === true &&
|
|
540
|
+
(block.language === "xml" || block.language === "html")
|
|
541
|
+
);
|
|
462
542
|
}
|
|
463
543
|
|
|
464
544
|
/** Parse markdown into renderable code blocks while preserving plain text blocks. */
|
|
@@ -470,24 +550,25 @@ export function parseMarkdownBlocks(text: string): CodeBlock[] {
|
|
|
470
550
|
while ((match = fence.exec(text))) {
|
|
471
551
|
const prose = text.slice(cursor, match.index).trim();
|
|
472
552
|
if (prose) {
|
|
473
|
-
const language =
|
|
474
|
-
blocks.push({ code: formatCodeBlock(prose, language), language });
|
|
553
|
+
const language = detectOutputLanguage(prose);
|
|
554
|
+
blocks.push({ code: formatCodeBlock(prose, language), fenced: false, language });
|
|
475
555
|
}
|
|
476
556
|
const language = normalizeLanguage(match[1]);
|
|
477
557
|
blocks.push({
|
|
478
558
|
code: formatCodeBlock(match[2] ?? "", language),
|
|
559
|
+
fenced: true,
|
|
479
560
|
language,
|
|
480
561
|
});
|
|
481
562
|
cursor = match.index + match[0].length;
|
|
482
563
|
}
|
|
483
564
|
const rest = text.slice(cursor).trim();
|
|
484
565
|
if (rest) {
|
|
485
|
-
const language =
|
|
486
|
-
blocks.push({ code: formatCodeBlock(rest, language), language });
|
|
566
|
+
const language = detectOutputLanguage(rest);
|
|
567
|
+
blocks.push({ code: formatCodeBlock(rest, language), fenced: false, language });
|
|
487
568
|
}
|
|
488
569
|
if (blocks.length > 0) return blocks;
|
|
489
|
-
const language =
|
|
490
|
-
return [{ code: formatCodeBlock(text, language), language }];
|
|
570
|
+
const language = detectOutputLanguage(text);
|
|
571
|
+
return [{ code: formatCodeBlock(text, language), fenced: false, language }];
|
|
491
572
|
}
|
|
492
573
|
|
|
493
574
|
/** Parse XML/HTML-ish fragments for the collapsible transcript renderer. */
|
|
@@ -8,6 +8,7 @@ import {
|
|
|
8
8
|
formatConversationDuration,
|
|
9
9
|
formatRelativeTime,
|
|
10
10
|
formatTime,
|
|
11
|
+
formatUsageTotal,
|
|
11
12
|
slackLocationLabel,
|
|
12
13
|
turnMessageCount,
|
|
13
14
|
turnToolCallCount,
|
|
@@ -123,11 +124,17 @@ function ConversationStats(props: {
|
|
|
123
124
|
0,
|
|
124
125
|
)
|
|
125
126
|
: undefined;
|
|
127
|
+
const tokens = formatUsageTotal(
|
|
128
|
+
(props.detail?.turns ?? props.conversation.turns).map(
|
|
129
|
+
(turn) => turn.cumulativeUsage,
|
|
130
|
+
),
|
|
131
|
+
);
|
|
126
132
|
const stats = [
|
|
127
133
|
slackLocationLabel(props.conversation, { includeId: false }),
|
|
128
134
|
`${props.conversation.turns.length} turns`,
|
|
129
135
|
messages === undefined ? "messages loading" : `${messages} messages`,
|
|
130
136
|
toolCalls === undefined ? "tool calls loading" : `${toolCalls} tool calls`,
|
|
137
|
+
tokens,
|
|
131
138
|
formatConversationDuration(props.conversation),
|
|
132
139
|
`started ${formatTime(props.conversation.startedAt)}`,
|
|
133
140
|
].filter(Boolean);
|
package/src/client/types.ts
CHANGED
|
@@ -141,7 +141,7 @@ export type SessionFilter = "active" | "recent" | "hung" | "failed" | "all";
|
|
|
141
141
|
|
|
142
142
|
export type VisualStatus = "active" | "failed" | "hung" | "idle";
|
|
143
143
|
|
|
144
|
-
export type CodeBlock = { code: string; language: BundledLanguage };
|
|
144
|
+
export type CodeBlock = { code: string; fenced?: boolean; language: BundledLanguage };
|
|
145
145
|
|
|
146
146
|
export type MarkupNode =
|
|
147
147
|
| {
|