@flanksource/clicky-ui 0.3.5 → 0.3.7
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/README.md +42 -0
- package/dist/ai.cjs +15 -0
- package/dist/ai.cjs.map +1 -1
- package/dist/ai.js +15 -0
- package/dist/ai.js.map +1 -1
- package/dist/components/DateField.d.ts +1 -1
- package/dist/components/DatePicker.d.ts +1 -1
- package/dist/components/DateTimePicker.d.ts +1 -1
- package/dist/components/FormLookupProvider.cjs +12 -0
- package/dist/components/FormLookupProvider.cjs.map +1 -0
- package/dist/components/FormLookupProvider.d.ts +7 -0
- package/dist/components/FormLookupProvider.d.ts.map +1 -0
- package/dist/components/FormLookupProvider.js +12 -0
- package/dist/components/FormLookupProvider.js.map +1 -0
- package/dist/components/JsonSchemaForm.cjs +2 -2
- package/dist/components/JsonSchemaForm.cjs.map +1 -1
- package/dist/components/JsonSchemaForm.js +1 -1
- package/dist/components/JsonSchemaForm.js.map +1 -1
- package/dist/components/ListMenu.cjs +145 -0
- package/dist/components/ListMenu.cjs.map +1 -0
- package/dist/components/ListMenu.d.ts +54 -0
- package/dist/components/ListMenu.d.ts.map +1 -0
- package/dist/components/ListMenu.js +145 -0
- package/dist/components/ListMenu.js.map +1 -0
- package/dist/components/MdxEditorField.cjs +128 -0
- package/dist/components/MdxEditorField.cjs.map +1 -0
- package/dist/components/MdxEditorField.d.ts +4 -0
- package/dist/components/MdxEditorField.d.ts.map +1 -0
- package/dist/components/MdxEditorField.js +106 -0
- package/dist/components/MdxEditorField.js.map +1 -0
- package/dist/components/MdxEditorToolbar.cjs +76 -0
- package/dist/components/MdxEditorToolbar.cjs.map +1 -0
- package/dist/components/MdxEditorToolbar.d.ts +8 -0
- package/dist/components/MdxEditorToolbar.d.ts.map +1 -0
- package/dist/components/MdxEditorToolbar.js +76 -0
- package/dist/components/MdxEditorToolbar.js.map +1 -0
- package/dist/components/button-variants.d.ts +1 -1
- package/dist/components/button.d.ts +1 -1
- package/dist/components/form-lookup-context.cjs +1 -8
- package/dist/components/form-lookup-context.cjs.map +1 -1
- package/dist/components/form-lookup-context.d.ts +1 -5
- package/dist/components/form-lookup-context.d.ts.map +1 -1
- package/dist/components/form-lookup-context.js +1 -8
- package/dist/components/form-lookup-context.js.map +1 -1
- package/dist/components/jotai-bindings-core.cjs +197 -0
- package/dist/components/jotai-bindings-core.cjs.map +1 -0
- package/dist/components/jotai-bindings-core.d.ts +45 -0
- package/dist/components/jotai-bindings-core.d.ts.map +1 -0
- package/dist/components/jotai-bindings-core.js +197 -0
- package/dist/components/jotai-bindings-core.js.map +1 -0
- package/dist/components/jotai-bindings.cjs +17 -0
- package/dist/components/jotai-bindings.cjs.map +1 -0
- package/dist/components/jotai-bindings.d.ts +4 -0
- package/dist/components/jotai-bindings.d.ts.map +1 -0
- package/dist/components/jotai-bindings.js +17 -0
- package/dist/components/jotai-bindings.js.map +1 -0
- package/dist/components/json-schema-form-fields.cjs +37 -0
- package/dist/components/json-schema-form-fields.cjs.map +1 -1
- package/dist/components/json-schema-form-fields.d.ts +6 -0
- package/dist/components/json-schema-form-fields.d.ts.map +1 -1
- package/dist/components/json-schema-form-fields.js +38 -1
- package/dist/components/json-schema-form-fields.js.map +1 -1
- package/dist/components/json-schema-form-render.cjs +3 -1
- package/dist/components/json-schema-form-render.cjs.map +1 -1
- package/dist/components/json-schema-form-render.d.ts.map +1 -1
- package/dist/components/json-schema-form-render.js +4 -2
- package/dist/components/json-schema-form-render.js.map +1 -1
- package/dist/components/json-schema-form-resolve.cjs +9 -0
- package/dist/components/json-schema-form-resolve.cjs.map +1 -1
- package/dist/components/json-schema-form-resolve.d.ts.map +1 -1
- package/dist/components/json-schema-form-resolve.js +9 -0
- package/dist/components/json-schema-form-resolve.js.map +1 -1
- package/dist/components/json-schema-form-types.d.ts +4 -1
- package/dist/components/json-schema-form-types.d.ts.map +1 -1
- package/dist/components/mdx-editor-field-plugins.cjs +124 -0
- package/dist/components/mdx-editor-field-plugins.cjs.map +1 -0
- package/dist/components/mdx-editor-field-plugins.d.ts +6 -0
- package/dist/components/mdx-editor-field-plugins.d.ts.map +1 -0
- package/dist/components/mdx-editor-field-plugins.js +124 -0
- package/dist/components/mdx-editor-field-plugins.js.map +1 -0
- package/dist/components/mdx-editor-options.d.ts +77 -0
- package/dist/components/mdx-editor-options.d.ts.map +1 -0
- package/dist/components/use-list-menu-selection.cjs +77 -0
- package/dist/components/use-list-menu-selection.cjs.map +1 -0
- package/dist/components/use-list-menu-selection.d.ts +40 -0
- package/dist/components/use-list-menu-selection.d.ts.map +1 -0
- package/dist/components/use-list-menu-selection.js +77 -0
- package/dist/components/use-list-menu-selection.js.map +1 -0
- package/dist/components.cjs +10 -1
- package/dist/components.cjs.map +1 -1
- package/dist/components.d.ts +4 -1
- package/dist/components.d.ts.map +1 -1
- package/dist/components.js +10 -1
- package/dist/components.js.map +1 -1
- package/dist/data/MarkdownEditor.model.d.ts +1 -1
- package/dist/data/ProgressBars.cjs +194 -0
- package/dist/data/ProgressBars.cjs.map +1 -0
- package/dist/data/ProgressBars.d.ts +85 -0
- package/dist/data/ProgressBars.d.ts.map +1 -0
- package/dist/data/ProgressBars.js +194 -0
- package/dist/data/ProgressBars.js.map +1 -0
- package/dist/data/ProgressBars.model.cjs +27 -0
- package/dist/data/ProgressBars.model.cjs.map +1 -0
- package/dist/data/ProgressBars.model.d.ts +20 -0
- package/dist/data/ProgressBars.model.d.ts.map +1 -0
- package/dist/data/ProgressBars.model.js +27 -0
- package/dist/data/ProgressBars.model.js.map +1 -0
- package/dist/data/PromptBanner.cjs +199 -0
- package/dist/data/PromptBanner.cjs.map +1 -0
- package/dist/data/PromptBanner.d.ts +17 -0
- package/dist/data/PromptBanner.d.ts.map +1 -0
- package/dist/data/PromptBanner.js +199 -0
- package/dist/data/PromptBanner.js.map +1 -0
- package/dist/data/PromptBanner.model.cjs +132 -0
- package/dist/data/PromptBanner.model.cjs.map +1 -0
- package/dist/data/PromptBanner.model.d.ts +23 -0
- package/dist/data/PromptBanner.model.d.ts.map +1 -0
- package/dist/data/PromptBanner.model.js +132 -0
- package/dist/data/PromptBanner.model.js.map +1 -0
- package/dist/data/PromptDialog.cjs +43 -0
- package/dist/data/PromptDialog.cjs.map +1 -0
- package/dist/data/PromptDialog.d.ts +14 -0
- package/dist/data/PromptDialog.d.ts.map +1 -0
- package/dist/data/PromptDialog.js +43 -0
- package/dist/data/PromptDialog.js.map +1 -0
- package/dist/data/TaskManager.cjs +8 -1
- package/dist/data/TaskManager.cjs.map +1 -1
- package/dist/data/TaskManager.d.ts.map +1 -1
- package/dist/data/TaskManager.js +8 -1
- package/dist/data/TaskManager.js.map +1 -1
- package/dist/data/TaskProgress.cjs +15 -2
- package/dist/data/TaskProgress.cjs.map +1 -1
- package/dist/data/TaskProgress.d.ts +0 -10
- package/dist/data/TaskProgress.d.ts.map +1 -1
- package/dist/data/TaskProgress.js +15 -2
- package/dist/data/TaskProgress.js.map +1 -1
- package/dist/data/TimeseriesCoreBars.cjs +19 -173
- package/dist/data/TimeseriesCoreBars.cjs.map +1 -1
- package/dist/data/TimeseriesCoreBars.d.ts +9 -26
- package/dist/data/TimeseriesCoreBars.d.ts.map +1 -1
- package/dist/data/TimeseriesCoreBars.js +20 -174
- package/dist/data/TimeseriesCoreBars.js.map +1 -1
- package/dist/data/WorkloadCard.model.cjs.map +1 -1
- package/dist/data/WorkloadCard.model.d.ts +2 -2
- package/dist/data/WorkloadCard.model.d.ts.map +1 -1
- package/dist/data/WorkloadCard.model.js.map +1 -1
- package/dist/data/ai/ChatWindow.cjs +53 -9
- package/dist/data/ai/ChatWindow.cjs.map +1 -1
- package/dist/data/ai/ChatWindow.d.ts.map +1 -1
- package/dist/data/ai/ChatWindow.js +53 -9
- package/dist/data/ai/ChatWindow.js.map +1 -1
- package/dist/data/ai/SessionViewer.cjs +275 -0
- package/dist/data/ai/SessionViewer.cjs.map +1 -0
- package/dist/data/ai/SessionViewer.d.ts +33 -0
- package/dist/data/ai/SessionViewer.d.ts.map +1 -0
- package/dist/data/ai/SessionViewer.fixtures.d.ts +4 -0
- package/dist/data/ai/SessionViewer.fixtures.d.ts.map +1 -0
- package/dist/data/ai/SessionViewer.js +275 -0
- package/dist/data/ai/SessionViewer.js.map +1 -0
- package/dist/data/ai/SessionViewer.model.cjs +275 -0
- package/dist/data/ai/SessionViewer.model.cjs.map +1 -0
- package/dist/data/ai/SessionViewer.model.d.ts +87 -0
- package/dist/data/ai/SessionViewer.model.d.ts.map +1 -0
- package/dist/data/ai/SessionViewer.model.js +275 -0
- package/dist/data/ai/SessionViewer.model.js.map +1 -0
- package/dist/data/ai/SessionViewerMenu.cjs +190 -0
- package/dist/data/ai/SessionViewerMenu.cjs.map +1 -0
- package/dist/data/ai/SessionViewerMenu.d.ts +24 -0
- package/dist/data/ai/SessionViewerMenu.d.ts.map +1 -0
- package/dist/data/ai/SessionViewerMenu.js +190 -0
- package/dist/data/ai/SessionViewerMenu.js.map +1 -0
- package/dist/data/ai/ToolPreferences.cjs +232 -39
- package/dist/data/ai/ToolPreferences.cjs.map +1 -1
- package/dist/data/ai/ToolPreferences.d.ts +4 -7
- package/dist/data/ai/ToolPreferences.d.ts.map +1 -1
- package/dist/data/ai/ToolPreferences.js +234 -41
- package/dist/data/ai/ToolPreferences.js.map +1 -1
- package/dist/data/ai/index.d.ts +3 -0
- package/dist/data/ai/index.d.ts.map +1 -1
- package/dist/data/ai/session-categories.cjs +219 -0
- package/dist/data/ai/session-categories.cjs.map +1 -0
- package/dist/data/ai/session-categories.d.ts +36 -0
- package/dist/data/ai/session-categories.d.ts.map +1 -0
- package/dist/data/ai/session-categories.js +219 -0
- package/dist/data/ai/session-categories.js.map +1 -0
- package/dist/data/chat/clickyOperationsToTools.cjs +89 -3
- package/dist/data/chat/clickyOperationsToTools.cjs.map +1 -1
- package/dist/data/chat/clickyOperationsToTools.d.ts +1 -1
- package/dist/data/chat/clickyOperationsToTools.d.ts.map +1 -1
- package/dist/data/chat/clickyOperationsToTools.js +89 -3
- package/dist/data/chat/clickyOperationsToTools.js.map +1 -1
- package/dist/data/chat/types.cjs.map +1 -1
- package/dist/data/chat/types.d.ts +7 -1
- package/dist/data/chat/types.d.ts.map +1 -1
- package/dist/data/chat/types.js.map +1 -1
- package/dist/data/task-status.cjs +19 -12
- package/dist/data/task-status.cjs.map +1 -1
- package/dist/data/task-status.d.ts +2 -1
- package/dist/data/task-status.d.ts.map +1 -1
- package/dist/data/task-status.js +19 -12
- package/dist/data/task-status.js.map +1 -1
- package/dist/data/test-runner/TestRunner.fixtures.d.ts +11 -4
- package/dist/data/test-runner/TestRunner.fixtures.d.ts.map +1 -1
- package/dist/data/version-info.cjs +3 -3
- package/dist/data/version-info.cjs.map +1 -1
- package/dist/data/version-info.js +3 -3
- package/dist/data/version-info.js.map +1 -1
- package/dist/data.cjs +11 -2
- package/dist/data.cjs.map +1 -1
- package/dist/data.d.ts +6 -2
- package/dist/data.d.ts.map +1 -1
- package/dist/data.js +11 -2
- package/dist/data.js.map +1 -1
- package/dist/hooks/use-prompts.cjs +83 -0
- package/dist/hooks/use-prompts.cjs.map +1 -0
- package/dist/hooks/use-prompts.d.ts +43 -0
- package/dist/hooks/use-prompts.d.ts.map +1 -0
- package/dist/hooks/use-prompts.js +83 -0
- package/dist/hooks/use-prompts.js.map +1 -0
- package/dist/hooks.cjs +3 -0
- package/dist/hooks.cjs.map +1 -1
- package/dist/hooks.d.ts +1 -0
- package/dist/hooks.d.ts.map +1 -1
- package/dist/hooks.js +3 -0
- package/dist/hooks.js.map +1 -1
- package/dist/index.cjs +21 -3
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +21 -3
- package/dist/index.js.map +1 -1
- package/dist/jotai.cjs +9 -0
- package/dist/jotai.cjs.map +1 -0
- package/dist/jotai.d.ts +4 -0
- package/dist/jotai.d.ts.map +1 -0
- package/dist/jotai.js +9 -0
- package/dist/jotai.js.map +1 -0
- package/dist/lib/utils.cjs +18 -1
- package/dist/lib/utils.cjs.map +1 -1
- package/dist/lib/utils.d.ts.map +1 -1
- package/dist/lib/utils.js +18 -1
- package/dist/lib/utils.js.map +1 -1
- package/dist/mdx-editor.cjs +5 -0
- package/dist/mdx-editor.cjs.map +1 -0
- package/dist/mdx-editor.css +2 -0
- package/dist/mdx-editor.d.ts +2 -0
- package/dist/mdx-editor.d.ts.map +1 -0
- package/dist/mdx-editor.js +5 -0
- package/dist/mdx-editor.js.map +1 -0
- package/dist/rpc/apiClient.cjs +1 -1
- package/dist/rpc/apiClient.cjs.map +1 -1
- package/dist/rpc/apiClient.js +1 -1
- package/dist/rpc/apiClient.js.map +1 -1
- package/dist/rpc/surfaceIconMap.cjs +12 -1
- package/dist/rpc/surfaceIconMap.cjs.map +1 -1
- package/dist/rpc/surfaceIconMap.d.ts.map +1 -1
- package/dist/rpc/surfaceIconMap.js +12 -1
- package/dist/rpc/surfaceIconMap.js.map +1 -1
- package/dist/rpc/types.cjs.map +1 -1
- package/dist/rpc/types.d.ts +1 -0
- package/dist/rpc/types.d.ts.map +1 -1
- package/dist/rpc/types.js.map +1 -1
- package/dist/styles.css +1 -1
- package/oxlint-plugins/README.md +148 -0
- package/oxlint-plugins/clicky-ui-no-adhoc-overlay.js +88 -0
- package/oxlint-plugins/clicky-ui-prefer-components.js +46 -0
- package/oxlint-plugins/clicky-ui-prefer-icons.js +121 -0
- package/oxlint-plugins/clicky-ui-prefer-tailwind.js +98 -0
- package/oxlint-plugins/clicky-ui-prefer-theme.js +134 -0
- package/oxlint-plugins/clicky-ui-shared.js +132 -0
- package/oxlint-plugins/clicky-ui.js +34 -0
- package/oxlint-plugins/no-iconify-names.js +37 -0
- package/package.json +21 -1
- package/dist/data/TimeseriesCoreBars.model.cjs +0 -27
- package/dist/data/TimeseriesCoreBars.model.cjs.map +0 -1
- package/dist/data/TimeseriesCoreBars.model.d.ts +0 -20
- package/dist/data/TimeseriesCoreBars.model.d.ts.map +0 -1
- package/dist/data/TimeseriesCoreBars.model.js +0 -27
- package/dist/data/TimeseriesCoreBars.model.js.map +0 -1
|
@@ -0,0 +1,275 @@
|
|
|
1
|
+
import { jsx, jsxs, Fragment } from "react/jsx-runtime";
|
|
2
|
+
import { useMemo, useState } from "react";
|
|
3
|
+
import { cn } from "../../lib/utils.js";
|
|
4
|
+
import { Icon } from "../Icon.js";
|
|
5
|
+
import { CodeBlock } from "../CodeBlock.js";
|
|
6
|
+
import { useDensityValue } from "../../hooks/use-density.js";
|
|
7
|
+
import { DensityValueProvider } from "../../hooks/density-provider.js";
|
|
8
|
+
import { normalizeSession, summarizeSession, getSessionAction, summarizeToolInput } from "./SessionViewer.model.js";
|
|
9
|
+
import { collectSessionFilters, isEventVisible } from "./session-categories.js";
|
|
10
|
+
import { SessionViewerMenu } from "./SessionViewerMenu.js";
|
|
11
|
+
import { UiRobotAi } from "../../icons/components/UiRobotAi.js";
|
|
12
|
+
import { UiUserCircle } from "../../icons/components/UiUserCircle.js";
|
|
13
|
+
import { UiWarningTriangle } from "../../icons/components/UiWarningTriangle.js";
|
|
14
|
+
import { UiBrain } from "../../icons/components/UiBrain.js";
|
|
15
|
+
import { UiSparkles } from "../../icons/components/UiSparkles.js";
|
|
16
|
+
import { UiChevronDown } from "../../icons/components/UiChevronDown.js";
|
|
17
|
+
const DISC_TONE = {
|
|
18
|
+
sky: "bg-sky-100 text-sky-700 [[data-theme=dark]_&]:bg-sky-500/15 [[data-theme=dark]_&]:text-sky-300",
|
|
19
|
+
amber: "bg-amber-100 text-amber-700 [[data-theme=dark]_&]:bg-amber-500/15 [[data-theme=dark]_&]:text-amber-300",
|
|
20
|
+
violet: "bg-violet-100 text-violet-700 [[data-theme=dark]_&]:bg-violet-500/15 [[data-theme=dark]_&]:text-violet-300",
|
|
21
|
+
emerald: "bg-emerald-100 text-emerald-700 [[data-theme=dark]_&]:bg-emerald-500/15 [[data-theme=dark]_&]:text-emerald-300",
|
|
22
|
+
rose: "bg-rose-100 text-rose-700 [[data-theme=dark]_&]:bg-rose-500/15 [[data-theme=dark]_&]:text-rose-300",
|
|
23
|
+
indigo: "bg-indigo-100 text-indigo-700 [[data-theme=dark]_&]:bg-indigo-500/15 [[data-theme=dark]_&]:text-indigo-300",
|
|
24
|
+
fuchsia: "bg-fuchsia-100 text-fuchsia-700 [[data-theme=dark]_&]:bg-fuchsia-500/15 [[data-theme=dark]_&]:text-fuchsia-300",
|
|
25
|
+
pink: "bg-pink-100 text-pink-700 [[data-theme=dark]_&]:bg-pink-500/15 [[data-theme=dark]_&]:text-pink-300",
|
|
26
|
+
slate: "bg-muted text-muted-foreground"
|
|
27
|
+
};
|
|
28
|
+
function toggleInSet(set, value) {
|
|
29
|
+
const next = new Set(set);
|
|
30
|
+
if (next.has(value)) next.delete(value);
|
|
31
|
+
else next.add(value);
|
|
32
|
+
return next;
|
|
33
|
+
}
|
|
34
|
+
function SessionViewer({
|
|
35
|
+
session,
|
|
36
|
+
className,
|
|
37
|
+
defaultExpanded = false,
|
|
38
|
+
showThinking = true,
|
|
39
|
+
showHeader = true,
|
|
40
|
+
showMenu = true,
|
|
41
|
+
defaultDensity,
|
|
42
|
+
defaultTheme
|
|
43
|
+
}) {
|
|
44
|
+
const allEvents = useMemo(() => normalizeSession(session), [session]);
|
|
45
|
+
const pageDensity = useDensityValue();
|
|
46
|
+
const [densityOverride, setDensityOverride] = useState(defaultDensity);
|
|
47
|
+
const [themeOverride, setThemeOverride] = useState(defaultTheme);
|
|
48
|
+
const [hiddenCategories, setHiddenCategories] = useState(
|
|
49
|
+
() => /* @__PURE__ */ new Set()
|
|
50
|
+
);
|
|
51
|
+
const [hiddenTools, setHiddenTools] = useState(() => /* @__PURE__ */ new Set());
|
|
52
|
+
const [hiddenSources, setHiddenSources] = useState(() => /* @__PURE__ */ new Set());
|
|
53
|
+
const [showThinkingOverride, setShowThinkingOverride] = useState(void 0);
|
|
54
|
+
const effectiveShowThinking = showThinkingOverride ?? showThinking;
|
|
55
|
+
const filters = useMemo(() => collectSessionFilters(allEvents), [allEvents]);
|
|
56
|
+
const hasThinking = useMemo(() => allEvents.some((e) => e.kind === "thinking"), [allEvents]);
|
|
57
|
+
const visibility = { hiddenCategories, hiddenTools, hiddenSources, showThinking: effectiveShowThinking };
|
|
58
|
+
const events = allEvents.filter((event) => isEventVisible(event, visibility));
|
|
59
|
+
if (allEvents.length === 0) {
|
|
60
|
+
return /* @__PURE__ */ jsx(
|
|
61
|
+
"div",
|
|
62
|
+
{
|
|
63
|
+
className: cn(
|
|
64
|
+
"rounded-md border border-dashed border-border p-density-4 text-center text-sm text-muted-foreground",
|
|
65
|
+
className
|
|
66
|
+
),
|
|
67
|
+
children: "No session activity."
|
|
68
|
+
}
|
|
69
|
+
);
|
|
70
|
+
}
|
|
71
|
+
const summary = summarizeSession(allEvents);
|
|
72
|
+
const effectiveDensity = densityOverride ?? pageDensity;
|
|
73
|
+
const dataAttrs = {
|
|
74
|
+
...densityOverride ? { "data-density": densityOverride } : {},
|
|
75
|
+
...themeOverride ? { "data-theme": themeOverride } : {}
|
|
76
|
+
};
|
|
77
|
+
return /* @__PURE__ */ jsx("div", { className: cn("text-sm", className), ...dataAttrs, children: /* @__PURE__ */ jsxs(DensityValueProvider, { density: effectiveDensity, children: [
|
|
78
|
+
(showHeader || showMenu) && /* @__PURE__ */ jsxs("div", { className: "mb-density-3 flex items-center justify-between gap-density-3", children: [
|
|
79
|
+
/* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center gap-x-density-3 gap-y-1 text-xs text-muted-foreground", children: [
|
|
80
|
+
showHeader && summary.model && /* @__PURE__ */ jsxs("span", { className: "inline-flex items-center gap-1 font-medium text-foreground", children: [
|
|
81
|
+
/* @__PURE__ */ jsx(Icon, { icon: UiRobotAi, className: "size-3.5" }),
|
|
82
|
+
summary.model
|
|
83
|
+
] }),
|
|
84
|
+
showHeader && /* @__PURE__ */ jsxs("span", { children: [
|
|
85
|
+
summary.toolCount,
|
|
86
|
+
" actions"
|
|
87
|
+
] }),
|
|
88
|
+
showHeader && /* @__PURE__ */ jsxs("span", { children: [
|
|
89
|
+
summary.messageCount,
|
|
90
|
+
" messages"
|
|
91
|
+
] })
|
|
92
|
+
] }),
|
|
93
|
+
showMenu && /* @__PURE__ */ jsx(
|
|
94
|
+
SessionViewerMenu,
|
|
95
|
+
{
|
|
96
|
+
density: densityOverride,
|
|
97
|
+
onDensityChange: setDensityOverride,
|
|
98
|
+
theme: themeOverride,
|
|
99
|
+
onThemeChange: setThemeOverride,
|
|
100
|
+
filters,
|
|
101
|
+
hiddenCategories,
|
|
102
|
+
hiddenTools,
|
|
103
|
+
hiddenSources,
|
|
104
|
+
onToggleCategory: (category) => setHiddenCategories((set) => toggleInSet(set, category)),
|
|
105
|
+
onToggleTool: (tool) => setHiddenTools((set) => toggleInSet(set, tool)),
|
|
106
|
+
onToggleSource: (source) => setHiddenSources((set) => toggleInSet(set, source)),
|
|
107
|
+
showThinking: effectiveShowThinking,
|
|
108
|
+
onToggleThinking: () => setShowThinkingOverride(!effectiveShowThinking),
|
|
109
|
+
hasThinking
|
|
110
|
+
}
|
|
111
|
+
)
|
|
112
|
+
] }),
|
|
113
|
+
events.length === 0 ? /* @__PURE__ */ jsx("div", { className: "rounded-md border border-dashed border-border p-density-4 text-center text-sm text-muted-foreground", children: "All actions are hidden by the active filters." }) : /* @__PURE__ */ jsx("ol", { className: "relative", children: events.map((event, index) => /* @__PURE__ */ jsx(
|
|
114
|
+
SessionRow,
|
|
115
|
+
{
|
|
116
|
+
event,
|
|
117
|
+
last: index === events.length - 1,
|
|
118
|
+
defaultExpanded
|
|
119
|
+
},
|
|
120
|
+
event.id
|
|
121
|
+
)) })
|
|
122
|
+
] }) });
|
|
123
|
+
}
|
|
124
|
+
function SessionRow({
|
|
125
|
+
event,
|
|
126
|
+
last,
|
|
127
|
+
defaultExpanded
|
|
128
|
+
}) {
|
|
129
|
+
if (event.kind === "user") return /* @__PURE__ */ jsx(UserRow, { event });
|
|
130
|
+
const visual = eventVisual(event);
|
|
131
|
+
return /* @__PURE__ */ jsxs("li", { "data-event-kind": event.kind, className: "relative flex gap-density-3 pb-density-4 last:pb-0", children: [
|
|
132
|
+
!last && /* @__PURE__ */ jsx("span", { "aria-hidden": true, className: "absolute bottom-0 left-[10px] top-[22px] w-px bg-border" }),
|
|
133
|
+
/* @__PURE__ */ jsx(
|
|
134
|
+
"span",
|
|
135
|
+
{
|
|
136
|
+
className: cn(
|
|
137
|
+
"relative z-[1] flex h-[21px] w-[21px] shrink-0 items-center justify-center rounded-full",
|
|
138
|
+
DISC_TONE[visual.tone]
|
|
139
|
+
),
|
|
140
|
+
children: /* @__PURE__ */ jsx(Icon, { icon: visual.icon, className: "h-3 w-3" })
|
|
141
|
+
}
|
|
142
|
+
),
|
|
143
|
+
/* @__PURE__ */ jsx("div", { className: "min-w-0 flex-1 pt-px", children: /* @__PURE__ */ jsx(EventBody, { event, visual, defaultExpanded }) })
|
|
144
|
+
] });
|
|
145
|
+
}
|
|
146
|
+
function UserRow({ event }) {
|
|
147
|
+
return /* @__PURE__ */ jsx("li", { "data-event-kind": "user", className: "relative flex justify-end pb-density-4 last:pb-0", children: /* @__PURE__ */ jsxs("div", { className: "flex max-w-[85%] items-start gap-density-3", children: [
|
|
148
|
+
/* @__PURE__ */ jsxs("div", { className: "min-w-0", children: [
|
|
149
|
+
/* @__PURE__ */ jsx("div", { className: "mb-0.5 text-right text-xs font-medium text-muted-foreground", children: "You" }),
|
|
150
|
+
/* @__PURE__ */ jsx("div", { className: "whitespace-pre-wrap break-words rounded-lg bg-accent px-density-3 py-density-2 text-right leading-relaxed text-accent-foreground", children: event.text })
|
|
151
|
+
] }),
|
|
152
|
+
/* @__PURE__ */ jsx(
|
|
153
|
+
"span",
|
|
154
|
+
{
|
|
155
|
+
className: cn(
|
|
156
|
+
"relative z-[1] flex h-[21px] w-[21px] shrink-0 items-center justify-center rounded-full",
|
|
157
|
+
DISC_TONE.slate
|
|
158
|
+
),
|
|
159
|
+
children: /* @__PURE__ */ jsx(Icon, { icon: UiUserCircle, className: "h-3 w-3" })
|
|
160
|
+
}
|
|
161
|
+
)
|
|
162
|
+
] }) });
|
|
163
|
+
}
|
|
164
|
+
function eventVisual(event) {
|
|
165
|
+
switch (event.kind) {
|
|
166
|
+
case "tool": {
|
|
167
|
+
const action = getSessionAction(event.tool ?? "");
|
|
168
|
+
return { icon: action.icon, tone: action.tone, label: action.label };
|
|
169
|
+
}
|
|
170
|
+
case "user":
|
|
171
|
+
return { icon: UiUserCircle, tone: "slate", label: "User" };
|
|
172
|
+
case "assistant":
|
|
173
|
+
return { icon: UiSparkles, tone: "indigo", label: "Assistant" };
|
|
174
|
+
case "thinking":
|
|
175
|
+
return { icon: UiBrain, tone: "slate", label: "Thinking" };
|
|
176
|
+
case "error":
|
|
177
|
+
return { icon: UiWarningTriangle, tone: "rose", label: "Error" };
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
function EventBody({
|
|
181
|
+
event,
|
|
182
|
+
visual,
|
|
183
|
+
defaultExpanded
|
|
184
|
+
}) {
|
|
185
|
+
if (event.kind === "tool") return /* @__PURE__ */ jsx(ToolBody, { event, label: visual.label, defaultExpanded });
|
|
186
|
+
if (event.kind === "thinking") return /* @__PURE__ */ jsx(ThinkingBody, { event });
|
|
187
|
+
if (event.kind === "error") return /* @__PURE__ */ jsx(ErrorBody, { event });
|
|
188
|
+
return /* @__PURE__ */ jsx(MessageBody, { event, label: visual.label });
|
|
189
|
+
}
|
|
190
|
+
function ToolBody({
|
|
191
|
+
event,
|
|
192
|
+
label,
|
|
193
|
+
defaultExpanded
|
|
194
|
+
}) {
|
|
195
|
+
const summary = summarizeToolInput(event.tool ?? "", event.toolInput);
|
|
196
|
+
const hasDetail = event.toolInput !== void 0 || event.toolResponse !== void 0;
|
|
197
|
+
const [open, setOpen] = useState(defaultExpanded);
|
|
198
|
+
const header = /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
199
|
+
/* @__PURE__ */ jsx("span", { className: "font-medium text-foreground", children: label }),
|
|
200
|
+
summary && /* @__PURE__ */ jsx("span", { className: "truncate font-mono text-xs text-muted-foreground", children: summary })
|
|
201
|
+
] });
|
|
202
|
+
return /* @__PURE__ */ jsxs("div", { className: "not-prose", children: [
|
|
203
|
+
hasDetail ? /* @__PURE__ */ jsxs(
|
|
204
|
+
"button",
|
|
205
|
+
{
|
|
206
|
+
type: "button",
|
|
207
|
+
"aria-expanded": open,
|
|
208
|
+
onClick: () => setOpen((value) => !value),
|
|
209
|
+
className: "flex w-full items-center gap-1.5 text-left hover:text-foreground",
|
|
210
|
+
children: [
|
|
211
|
+
header,
|
|
212
|
+
/* @__PURE__ */ jsx(
|
|
213
|
+
Icon,
|
|
214
|
+
{
|
|
215
|
+
icon: UiChevronDown,
|
|
216
|
+
className: cn("ml-auto size-3 shrink-0 text-muted-foreground transition-transform", open && "rotate-180")
|
|
217
|
+
}
|
|
218
|
+
)
|
|
219
|
+
]
|
|
220
|
+
}
|
|
221
|
+
) : /* @__PURE__ */ jsx("div", { className: "flex items-center gap-1.5", children: header }),
|
|
222
|
+
(event.model || event.source) && /* @__PURE__ */ jsxs("div", { className: "mt-0.5 flex gap-density-2 text-[11px] text-muted-foreground", children: [
|
|
223
|
+
event.source && /* @__PURE__ */ jsx("span", { children: event.source }),
|
|
224
|
+
event.model && /* @__PURE__ */ jsx("span", { children: event.model }),
|
|
225
|
+
event.reasoningEffort && /* @__PURE__ */ jsxs("span", { children: [
|
|
226
|
+
"effort: ",
|
|
227
|
+
event.reasoningEffort
|
|
228
|
+
] })
|
|
229
|
+
] }),
|
|
230
|
+
open && hasDetail && /* @__PURE__ */ jsxs("div", { className: "mt-1.5 space-y-1.5", children: [
|
|
231
|
+
event.toolInput !== void 0 && /* @__PURE__ */ jsx(DetailBlock, { language: "json", source: JSON.stringify(event.toolInput, null, 2) }),
|
|
232
|
+
event.toolResponse !== void 0 && /* @__PURE__ */ jsx(ResponseBlock, { response: event.toolResponse })
|
|
233
|
+
] })
|
|
234
|
+
] });
|
|
235
|
+
}
|
|
236
|
+
function ResponseBlock({ response }) {
|
|
237
|
+
const trimmed = response.trim();
|
|
238
|
+
const isJson = trimmed.startsWith("{") || trimmed.startsWith("[");
|
|
239
|
+
return /* @__PURE__ */ jsx(DetailBlock, { language: isJson ? "json" : "text", source: response });
|
|
240
|
+
}
|
|
241
|
+
function DetailBlock({ language, source }) {
|
|
242
|
+
return /* @__PURE__ */ jsx("div", { className: "overflow-x-auto text-xs", children: /* @__PURE__ */ jsx(CodeBlock, { language, source }) });
|
|
243
|
+
}
|
|
244
|
+
function MessageBody({ event, label }) {
|
|
245
|
+
return /* @__PURE__ */ jsxs("div", { children: [
|
|
246
|
+
/* @__PURE__ */ jsx("div", { className: "mb-0.5 text-xs font-medium text-muted-foreground", children: label }),
|
|
247
|
+
/* @__PURE__ */ jsx("div", { className: "whitespace-pre-wrap break-words leading-relaxed text-foreground", children: event.text })
|
|
248
|
+
] });
|
|
249
|
+
}
|
|
250
|
+
function ThinkingBody({ event }) {
|
|
251
|
+
const [open, setOpen] = useState(false);
|
|
252
|
+
return /* @__PURE__ */ jsxs("div", { className: "not-prose", children: [
|
|
253
|
+
/* @__PURE__ */ jsxs(
|
|
254
|
+
"button",
|
|
255
|
+
{
|
|
256
|
+
type: "button",
|
|
257
|
+
"aria-expanded": open,
|
|
258
|
+
onClick: () => setOpen((value) => !value),
|
|
259
|
+
className: "flex items-center gap-1.5 text-xs text-muted-foreground hover:text-foreground",
|
|
260
|
+
children: [
|
|
261
|
+
/* @__PURE__ */ jsx("span", { className: "italic", children: "Reasoning" }),
|
|
262
|
+
/* @__PURE__ */ jsx(Icon, { icon: UiChevronDown, className: cn("size-3 transition-transform", open && "rotate-180") })
|
|
263
|
+
]
|
|
264
|
+
}
|
|
265
|
+
),
|
|
266
|
+
open && /* @__PURE__ */ jsx("div", { className: "mt-1 whitespace-pre-wrap break-words border-l-2 border-border pl-density-3 text-xs italic leading-relaxed text-muted-foreground", children: event.text })
|
|
267
|
+
] });
|
|
268
|
+
}
|
|
269
|
+
function ErrorBody({ event }) {
|
|
270
|
+
return /* @__PURE__ */ jsx("div", { className: "rounded-md border border-rose-200 bg-rose-50 px-density-3 py-1.5 text-xs text-rose-700 [[data-theme=dark]_&]:border-rose-500/30 [[data-theme=dark]_&]:bg-rose-500/10 [[data-theme=dark]_&]:text-rose-300", children: event.text });
|
|
271
|
+
}
|
|
272
|
+
export {
|
|
273
|
+
SessionViewer
|
|
274
|
+
};
|
|
275
|
+
//# sourceMappingURL=SessionViewer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SessionViewer.js","sources":["../../../src/data/ai/SessionViewer.tsx"],"sourcesContent":["import { useMemo, useState, type ReactNode } from \"react\";\nimport { cn } from \"../../lib/utils\";\nimport { Icon, type StaticIconComponent } from \"../Icon\";\nimport { CodeBlock } from \"../CodeBlock\";\nimport { useDensityValue, type Density } from \"../../hooks/use-density\";\nimport { DensityValueProvider } from \"../../hooks/density-provider\";\nimport {\n UiBrain,\n UiChevronDown,\n UiRobotAi,\n UiSparkles,\n UiUserCircle,\n UiWarningTriangle,\n} from \"../../icons\";\nimport {\n getSessionAction,\n normalizeSession,\n summarizeSession,\n summarizeToolInput,\n type SessionEvent,\n type SessionInput,\n type SessionTone,\n} from \"./SessionViewer.model\";\nimport {\n collectSessionFilters,\n isEventVisible,\n type SessionCategory,\n} from \"./session-categories\";\nimport { SessionViewerMenu, type SessionThemeOverride } from \"./SessionViewerMenu\";\n\nexport type {\n SessionEntry,\n SessionEvent,\n SessionInput,\n SessionActionMeta,\n} from \"./SessionViewer.model\";\nexport type { SessionThemeOverride } from \"./SessionViewerMenu\";\n\nexport interface SessionViewerProps {\n /** A captain session: parsed `SessionEntry[]` or raw log text (JSON / JSONL). */\n session: SessionInput;\n className?: string;\n /** Expand each tool call's input/output by default. Defaults to false. */\n defaultExpanded?: boolean;\n /** Render assistant reasoning (\"thinking\") blocks. Defaults to true. */\n showThinking?: boolean;\n /** Show the summary header (model + action counts). Defaults to true. */\n showHeader?: boolean;\n /** Show the 3-dot menu (density + category/tool/source filters). Defaults to true. */\n showMenu?: boolean;\n /** Initial density override; undefined inherits the page/document density. */\n defaultDensity?: Density;\n /** Initial theme override; undefined inherits the page/document `data-theme`. */\n defaultTheme?: SessionThemeOverride;\n}\n\n// Disc colors per tone. The dark variants key off a `[data-theme=\"dark\"]`\n// ancestor (the document attribute set by ThemeProvider, or the component-level\n// override painted on this viewer's root) rather than Tailwind's `dark:` —\n// which this library compiles to `prefers-color-scheme` and so would ignore the\n// `data-theme` attribute. Written as literal class strings so Tailwind scans them.\nconst DISC_TONE: Record<SessionTone, string> = {\n sky: \"bg-sky-100 text-sky-700 [[data-theme=dark]_&]:bg-sky-500/15 [[data-theme=dark]_&]:text-sky-300\",\n amber: \"bg-amber-100 text-amber-700 [[data-theme=dark]_&]:bg-amber-500/15 [[data-theme=dark]_&]:text-amber-300\",\n violet: \"bg-violet-100 text-violet-700 [[data-theme=dark]_&]:bg-violet-500/15 [[data-theme=dark]_&]:text-violet-300\",\n emerald: \"bg-emerald-100 text-emerald-700 [[data-theme=dark]_&]:bg-emerald-500/15 [[data-theme=dark]_&]:text-emerald-300\",\n rose: \"bg-rose-100 text-rose-700 [[data-theme=dark]_&]:bg-rose-500/15 [[data-theme=dark]_&]:text-rose-300\",\n indigo: \"bg-indigo-100 text-indigo-700 [[data-theme=dark]_&]:bg-indigo-500/15 [[data-theme=dark]_&]:text-indigo-300\",\n fuchsia: \"bg-fuchsia-100 text-fuchsia-700 [[data-theme=dark]_&]:bg-fuchsia-500/15 [[data-theme=dark]_&]:text-fuchsia-300\",\n pink: \"bg-pink-100 text-pink-700 [[data-theme=dark]_&]:bg-pink-500/15 [[data-theme=dark]_&]:text-pink-300\",\n slate: \"bg-muted text-muted-foreground\",\n};\n\nfunction toggleInSet<T>(set: ReadonlySet<T>, value: T): Set<T> {\n const next = new Set(set);\n if (next.has(value)) next.delete(value);\n else next.add(value);\n return next;\n}\n\n/**\n * SessionViewer renders a recorded AI coding-agent session (the captain\n * `pkg/ai/history` JSON schema — Claude Code / Codex transcripts) as a vertical\n * action log. Each entry sits on a tone-colored icon disc from the Flanksource\n * \"Agent Action Icons\" set; user prompts/selections are right-aligned like a\n * chat. Tool calls expand to their input and response. The \"3-dot\" menu mirrors\n * `captain history` filtering — toggle density and hide categories, tools or\n * sources.\n */\nexport function SessionViewer({\n session,\n className,\n defaultExpanded = false,\n showThinking = true,\n showHeader = true,\n showMenu = true,\n defaultDensity,\n defaultTheme,\n}: SessionViewerProps) {\n const allEvents = useMemo(() => normalizeSession(session), [session]);\n\n const pageDensity = useDensityValue();\n const [densityOverride, setDensityOverride] = useState<Density | undefined>(defaultDensity);\n const [themeOverride, setThemeOverride] = useState<SessionThemeOverride | undefined>(defaultTheme);\n const [hiddenCategories, setHiddenCategories] = useState<ReadonlySet<SessionCategory>>(\n () => new Set(),\n );\n const [hiddenTools, setHiddenTools] = useState<ReadonlySet<string>>(() => new Set());\n const [hiddenSources, setHiddenSources] = useState<ReadonlySet<string>>(() => new Set());\n // Undefined = follow the `showThinking` prop; the menu toggle sets an override.\n const [showThinkingOverride, setShowThinkingOverride] = useState<boolean | undefined>(undefined);\n const effectiveShowThinking = showThinkingOverride ?? showThinking;\n\n const filters = useMemo(() => collectSessionFilters(allEvents), [allEvents]);\n const hasThinking = useMemo(() => allEvents.some((e) => e.kind === \"thinking\"), [allEvents]);\n\n const visibility = { hiddenCategories, hiddenTools, hiddenSources, showThinking: effectiveShowThinking };\n const events = allEvents.filter((event) => isEventVisible(event, visibility));\n\n if (allEvents.length === 0) {\n return (\n <div\n className={cn(\n \"rounded-md border border-dashed border-border p-density-4 text-center text-sm text-muted-foreground\",\n className,\n )}\n >\n No session activity.\n </div>\n );\n }\n\n const summary = summarizeSession(allEvents);\n const effectiveDensity = densityOverride ?? pageDensity;\n const dataAttrs: Record<string, string> = {\n ...(densityOverride ? { \"data-density\": densityOverride } : {}),\n ...(themeOverride ? { \"data-theme\": themeOverride } : {}),\n };\n\n return (\n <div className={cn(\"text-sm\", className)} {...dataAttrs}>\n <DensityValueProvider density={effectiveDensity}>\n {(showHeader || showMenu) && (\n <div className=\"mb-density-3 flex items-center justify-between gap-density-3\">\n <div className=\"flex flex-wrap items-center gap-x-density-3 gap-y-1 text-xs text-muted-foreground\">\n {showHeader && summary.model && (\n <span className=\"inline-flex items-center gap-1 font-medium text-foreground\">\n <Icon icon={UiRobotAi} className=\"size-3.5\" />\n {summary.model}\n </span>\n )}\n {showHeader && <span>{summary.toolCount} actions</span>}\n {showHeader && <span>{summary.messageCount} messages</span>}\n </div>\n {showMenu && (\n <SessionViewerMenu\n density={densityOverride}\n onDensityChange={setDensityOverride}\n theme={themeOverride}\n onThemeChange={setThemeOverride}\n filters={filters}\n hiddenCategories={hiddenCategories}\n hiddenTools={hiddenTools}\n hiddenSources={hiddenSources}\n onToggleCategory={(category) =>\n setHiddenCategories((set) => toggleInSet(set, category))\n }\n onToggleTool={(tool) => setHiddenTools((set) => toggleInSet(set, tool))}\n onToggleSource={(source) => setHiddenSources((set) => toggleInSet(set, source))}\n showThinking={effectiveShowThinking}\n onToggleThinking={() => setShowThinkingOverride(!effectiveShowThinking)}\n hasThinking={hasThinking}\n />\n )}\n </div>\n )}\n\n {events.length === 0 ? (\n <div className=\"rounded-md border border-dashed border-border p-density-4 text-center text-sm text-muted-foreground\">\n All actions are hidden by the active filters.\n </div>\n ) : (\n <ol className=\"relative\">\n {events.map((event, index) => (\n <SessionRow\n key={event.id}\n event={event}\n last={index === events.length - 1}\n defaultExpanded={defaultExpanded}\n />\n ))}\n </ol>\n )}\n </DensityValueProvider>\n </div>\n );\n}\n\nfunction SessionRow({\n event,\n last,\n defaultExpanded,\n}: {\n event: SessionEvent;\n last: boolean;\n defaultExpanded: boolean;\n}) {\n if (event.kind === \"user\") return <UserRow event={event} />;\n\n const visual = eventVisual(event);\n return (\n <li data-event-kind={event.kind} className=\"relative flex gap-density-3 pb-density-4 last:pb-0\">\n {!last && <span aria-hidden className=\"absolute bottom-0 left-[10px] top-[22px] w-px bg-border\" />}\n <span\n className={cn(\n \"relative z-[1] flex h-[21px] w-[21px] shrink-0 items-center justify-center rounded-full\",\n DISC_TONE[visual.tone],\n )}\n >\n <Icon icon={visual.icon} className=\"h-3 w-3\" />\n </span>\n <div className=\"min-w-0 flex-1 pt-px\">\n <EventBody event={event} visual={visual} defaultExpanded={defaultExpanded} />\n </div>\n </li>\n );\n}\n\n// User prompts and selections sit on the right, like a chat composer turn.\nfunction UserRow({ event }: { event: SessionEvent }) {\n return (\n <li data-event-kind=\"user\" className=\"relative flex justify-end pb-density-4 last:pb-0\">\n <div className=\"flex max-w-[85%] items-start gap-density-3\">\n <div className=\"min-w-0\">\n <div className=\"mb-0.5 text-right text-xs font-medium text-muted-foreground\">You</div>\n <div className=\"whitespace-pre-wrap break-words rounded-lg bg-accent px-density-3 py-density-2 text-right leading-relaxed text-accent-foreground\">\n {event.text}\n </div>\n </div>\n <span\n className={cn(\n \"relative z-[1] flex h-[21px] w-[21px] shrink-0 items-center justify-center rounded-full\",\n DISC_TONE.slate,\n )}\n >\n <Icon icon={UiUserCircle} className=\"h-3 w-3\" />\n </span>\n </div>\n </li>\n );\n}\n\ninterface EventVisual {\n icon: StaticIconComponent;\n tone: SessionTone;\n label: string;\n}\n\nfunction eventVisual(event: SessionEvent): EventVisual {\n switch (event.kind) {\n case \"tool\": {\n const action = getSessionAction(event.tool ?? \"\");\n return { icon: action.icon, tone: action.tone, label: action.label };\n }\n case \"user\":\n return { icon: UiUserCircle, tone: \"slate\", label: \"User\" };\n case \"assistant\":\n return { icon: UiSparkles, tone: \"indigo\", label: \"Assistant\" };\n case \"thinking\":\n return { icon: UiBrain, tone: \"slate\", label: \"Thinking\" };\n case \"error\":\n return { icon: UiWarningTriangle, tone: \"rose\", label: \"Error\" };\n }\n}\n\nfunction EventBody({\n event,\n visual,\n defaultExpanded,\n}: {\n event: SessionEvent;\n visual: EventVisual;\n defaultExpanded: boolean;\n}) {\n if (event.kind === \"tool\") return <ToolBody event={event} label={visual.label} defaultExpanded={defaultExpanded} />;\n if (event.kind === \"thinking\") return <ThinkingBody event={event} />;\n if (event.kind === \"error\") return <ErrorBody event={event} />;\n return <MessageBody event={event} label={visual.label} />;\n}\n\nfunction ToolBody({\n event,\n label,\n defaultExpanded,\n}: {\n event: SessionEvent;\n label: string;\n defaultExpanded: boolean;\n}) {\n const summary = summarizeToolInput(event.tool ?? \"\", event.toolInput);\n const hasDetail = event.toolInput !== undefined || event.toolResponse !== undefined;\n const [open, setOpen] = useState(defaultExpanded);\n\n const header = (\n <>\n <span className=\"font-medium text-foreground\">{label}</span>\n {summary && <span className=\"truncate font-mono text-xs text-muted-foreground\">{summary}</span>}\n </>\n );\n\n return (\n <div className=\"not-prose\">\n {hasDetail ? (\n <button\n type=\"button\"\n aria-expanded={open}\n onClick={() => setOpen((value) => !value)}\n className=\"flex w-full items-center gap-1.5 text-left hover:text-foreground\"\n >\n {header}\n <Icon\n icon={UiChevronDown}\n className={cn(\"ml-auto size-3 shrink-0 text-muted-foreground transition-transform\", open && \"rotate-180\")}\n />\n </button>\n ) : (\n <div className=\"flex items-center gap-1.5\">{header}</div>\n )}\n\n {(event.model || event.source) && (\n <div className=\"mt-0.5 flex gap-density-2 text-[11px] text-muted-foreground\">\n {event.source && <span>{event.source}</span>}\n {event.model && <span>{event.model}</span>}\n {event.reasoningEffort && <span>effort: {event.reasoningEffort}</span>}\n </div>\n )}\n\n {open && hasDetail && (\n <div className=\"mt-1.5 space-y-1.5\">\n {event.toolInput !== undefined && (\n <DetailBlock language=\"json\" source={JSON.stringify(event.toolInput, null, 2)} />\n )}\n {event.toolResponse !== undefined && <ResponseBlock response={event.toolResponse} />}\n </div>\n )}\n </div>\n );\n}\n\nfunction ResponseBlock({ response }: { response: string }) {\n const trimmed = response.trim();\n const isJson = trimmed.startsWith(\"{\") || trimmed.startsWith(\"[\");\n return <DetailBlock language={isJson ? \"json\" : \"text\"} source={response} />;\n}\n\nfunction DetailBlock({ language, source }: { language: string; source: string }): ReactNode {\n return (\n <div className=\"overflow-x-auto text-xs\">\n <CodeBlock language={language} source={source} />\n </div>\n );\n}\n\nfunction MessageBody({ event, label }: { event: SessionEvent; label: string }) {\n return (\n <div>\n <div className=\"mb-0.5 text-xs font-medium text-muted-foreground\">{label}</div>\n <div className=\"whitespace-pre-wrap break-words leading-relaxed text-foreground\">{event.text}</div>\n </div>\n );\n}\n\nfunction ThinkingBody({ event }: { event: SessionEvent }) {\n const [open, setOpen] = useState(false);\n return (\n <div className=\"not-prose\">\n <button\n type=\"button\"\n aria-expanded={open}\n onClick={() => setOpen((value) => !value)}\n className=\"flex items-center gap-1.5 text-xs text-muted-foreground hover:text-foreground\"\n >\n <span className=\"italic\">Reasoning</span>\n <Icon icon={UiChevronDown} className={cn(\"size-3 transition-transform\", open && \"rotate-180\")} />\n </button>\n {open && (\n <div className=\"mt-1 whitespace-pre-wrap break-words border-l-2 border-border pl-density-3 text-xs italic leading-relaxed text-muted-foreground\">\n {event.text}\n </div>\n )}\n </div>\n );\n}\n\nfunction ErrorBody({ event }: { event: SessionEvent }) {\n return (\n <div className=\"rounded-md border border-rose-200 bg-rose-50 px-density-3 py-1.5 text-xs text-rose-700 [[data-theme=dark]_&]:border-rose-500/30 [[data-theme=dark]_&]:bg-rose-500/10 [[data-theme=dark]_&]:text-rose-300\">\n {event.text}\n </div>\n );\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,275 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
|
+
const UiClose = require("../../icons/components/UiClose.cjs");
|
|
4
|
+
const UiHourglass = require("../../icons/components/UiHourglass.cjs");
|
|
5
|
+
const UiNetwork = require("../../icons/components/UiNetwork.cjs");
|
|
6
|
+
const UiCode2 = require("../../icons/components/UiCode2.cjs");
|
|
7
|
+
const UiCamera = require("../../icons/components/UiCamera.cjs");
|
|
8
|
+
const UiEye = require("../../icons/components/UiEye.cjs");
|
|
9
|
+
const UiCommand = require("../../icons/components/UiCommand.cjs");
|
|
10
|
+
const UiTerminal = require("../../icons/components/UiTerminal.cjs");
|
|
11
|
+
const UiSelect = require("../../icons/components/UiSelect.cjs");
|
|
12
|
+
const UiGlobe = require("../../icons/components/UiGlobe.cjs");
|
|
13
|
+
const UiCloudDownload = require("../../icons/components/UiCloudDownload.cjs");
|
|
14
|
+
const UiKanban = require("../../icons/components/UiKanban.cjs");
|
|
15
|
+
const UiQuestion = require("../../icons/components/UiQuestion.cjs");
|
|
16
|
+
const UiSearch = require("../../icons/components/UiSearch.cjs");
|
|
17
|
+
const UiStop = require("../../icons/components/UiStop.cjs");
|
|
18
|
+
const UiMagicWand = require("../../icons/components/UiMagicWand.cjs");
|
|
19
|
+
const UiRobotAi = require("../../icons/components/UiRobotAi.cjs");
|
|
20
|
+
const UiFileSearch = require("../../icons/components/UiFileSearch.cjs");
|
|
21
|
+
const UiEdit = require("../../icons/components/UiEdit.cjs");
|
|
22
|
+
const UiLayers = require("../../icons/components/UiLayers.cjs");
|
|
23
|
+
const UiSave = require("../../icons/components/UiSave.cjs");
|
|
24
|
+
const UiFileText = require("../../icons/components/UiFileText.cjs");
|
|
25
|
+
const UiImage = require("../../icons/components/UiImage.cjs");
|
|
26
|
+
const UiSparkles = require("../../icons/components/UiSparkles.cjs");
|
|
27
|
+
const UiPuzzle = require("../../icons/components/UiPuzzle.cjs");
|
|
28
|
+
const UiWrench = require("../../icons/components/UiWrench.cjs");
|
|
29
|
+
function truncate(text, max) {
|
|
30
|
+
return text.length <= max ? text : `${text.slice(0, max)}…`;
|
|
31
|
+
}
|
|
32
|
+
function parseEntries(input) {
|
|
33
|
+
if (Array.isArray(input)) return input;
|
|
34
|
+
const text = input.trim();
|
|
35
|
+
if (!text) return [];
|
|
36
|
+
try {
|
|
37
|
+
const parsed = JSON.parse(text);
|
|
38
|
+
return Array.isArray(parsed) ? parsed : [parsed];
|
|
39
|
+
} catch {
|
|
40
|
+
}
|
|
41
|
+
return text.split("\n").map((line) => line.trim()).filter(Boolean).map((line) => {
|
|
42
|
+
try {
|
|
43
|
+
return JSON.parse(line);
|
|
44
|
+
} catch {
|
|
45
|
+
throw new Error(`SessionViewer: invalid session JSON line: ${truncate(line, 80)}`);
|
|
46
|
+
}
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
function roleFromType(type) {
|
|
50
|
+
return type === "user" || type === "assistant" ? type : "assistant";
|
|
51
|
+
}
|
|
52
|
+
function toolEvent(id, tool, input, response, timestamp, meta = {}) {
|
|
53
|
+
return {
|
|
54
|
+
id,
|
|
55
|
+
kind: "tool",
|
|
56
|
+
tool,
|
|
57
|
+
...input ? { toolInput: input } : {},
|
|
58
|
+
...response ? { toolResponse: response } : {},
|
|
59
|
+
...timestamp ? { timestamp } : {},
|
|
60
|
+
...meta.model ? { model: meta.model } : {},
|
|
61
|
+
...meta.reasoningEffort ? { reasoningEffort: meta.reasoningEffort } : {},
|
|
62
|
+
...meta.source ? { source: meta.source } : {}
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
function blockEvent(block, role, id, timestamp) {
|
|
66
|
+
if (block.type === "tool_use" || block.name && block.input) {
|
|
67
|
+
if (!block.name) return null;
|
|
68
|
+
return toolEvent(id, block.name, block.input, void 0, timestamp);
|
|
69
|
+
}
|
|
70
|
+
if (block.type === "thinking" || block.thinking) {
|
|
71
|
+
const text = block.thinking ?? block.text;
|
|
72
|
+
return text ? { id, kind: "thinking", text, ...timestamp ? { timestamp } : {} } : null;
|
|
73
|
+
}
|
|
74
|
+
if (block.text) {
|
|
75
|
+
return {
|
|
76
|
+
id,
|
|
77
|
+
kind: role === "user" ? "user" : "assistant",
|
|
78
|
+
text: block.text,
|
|
79
|
+
...timestamp ? { timestamp } : {}
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
return null;
|
|
83
|
+
}
|
|
84
|
+
function normalizeSession(input) {
|
|
85
|
+
const entries = parseEntries(input);
|
|
86
|
+
const events = [];
|
|
87
|
+
entries.forEach((entry, seq) => {
|
|
88
|
+
var _a, _b;
|
|
89
|
+
const baseId = entry.uuid ?? `e${seq}`;
|
|
90
|
+
if (entry.isApiErrorMessage) {
|
|
91
|
+
events.push({
|
|
92
|
+
id: `${baseId}-err`,
|
|
93
|
+
kind: "error",
|
|
94
|
+
text: errorMessage(entry),
|
|
95
|
+
...entry.error ? { errorType: entry.error } : {},
|
|
96
|
+
...entry.apiErrorStatus ? { errorStatus: entry.apiErrorStatus } : {},
|
|
97
|
+
...entry.timestamp ? { timestamp: entry.timestamp } : {}
|
|
98
|
+
});
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
const tu = entry.tool_use;
|
|
102
|
+
if (tu == null ? void 0 : tu.tool) {
|
|
103
|
+
events.push(
|
|
104
|
+
toolEvent(`${baseId}-tool`, tu.tool, tu.input, tu.response, tu.timestamp ?? entry.timestamp, {
|
|
105
|
+
...tu.model ? { model: tu.model } : {},
|
|
106
|
+
...tu.reasoning_effort ? { reasoningEffort: tu.reasoning_effort } : {},
|
|
107
|
+
...tu.source ? { source: tu.source } : {}
|
|
108
|
+
})
|
|
109
|
+
);
|
|
110
|
+
return;
|
|
111
|
+
}
|
|
112
|
+
const role = roleFromType(((_a = entry.message) == null ? void 0 : _a.role) ?? entry.type);
|
|
113
|
+
for (const [i, block] of (((_b = entry.message) == null ? void 0 : _b.content) ?? []).entries()) {
|
|
114
|
+
const ev = blockEvent(block, role, `${baseId}-${i}`, entry.timestamp);
|
|
115
|
+
if (ev) events.push(ev);
|
|
116
|
+
}
|
|
117
|
+
});
|
|
118
|
+
return events;
|
|
119
|
+
}
|
|
120
|
+
function errorMessage(entry) {
|
|
121
|
+
const status = entry.apiErrorStatus ? ` (HTTP ${entry.apiErrorStatus})` : "";
|
|
122
|
+
return `${entry.error ?? "API error"}${status}`;
|
|
123
|
+
}
|
|
124
|
+
const ACTIONS = {
|
|
125
|
+
// File operations
|
|
126
|
+
Read: { icon: UiFileText.UiFileText, tone: "sky", label: "Read file" },
|
|
127
|
+
Write: { icon: UiSave.UiSave, tone: "amber", label: "Write file" },
|
|
128
|
+
Edit: { icon: UiEdit.UiEdit, tone: "violet", label: "Edit file" },
|
|
129
|
+
MultiEdit: { icon: UiLayers.UiLayers, tone: "violet", label: "Multi-edit" },
|
|
130
|
+
NotebookEdit: { icon: UiEdit.UiEdit, tone: "violet", label: "Edit notebook" },
|
|
131
|
+
// Search & navigation
|
|
132
|
+
Grep: { icon: UiSearch.UiSearch, tone: "amber", label: "Grep" },
|
|
133
|
+
Glob: { icon: UiFileSearch.UiFileSearch, tone: "sky", label: "Glob" },
|
|
134
|
+
// Execution & shell
|
|
135
|
+
Bash: { icon: UiTerminal.UiTerminal, tone: "emerald", label: "Run command" },
|
|
136
|
+
BashOutput: { icon: UiCode2.UiCode2, tone: "emerald", label: "Shell output" },
|
|
137
|
+
KillShell: { icon: UiStop.UiStop, tone: "rose", label: "Kill shell" },
|
|
138
|
+
KillBash: { icon: UiStop.UiStop, tone: "rose", label: "Kill shell" },
|
|
139
|
+
// Agents & planning
|
|
140
|
+
Task: { icon: UiRobotAi.UiRobotAi, tone: "indigo", label: "Sub-agent task" },
|
|
141
|
+
Agent: { icon: UiRobotAi.UiRobotAi, tone: "indigo", label: "Sub-agent task" },
|
|
142
|
+
Skill: { icon: UiMagicWand.UiMagicWand, tone: "fuchsia", label: "Invoke skill" },
|
|
143
|
+
TodoWrite: { icon: UiKanban.UiKanban, tone: "sky", label: "Update todos" },
|
|
144
|
+
TaskCreate: { icon: UiKanban.UiKanban, tone: "sky", label: "Create task" },
|
|
145
|
+
TaskUpdate: { icon: UiKanban.UiKanban, tone: "sky", label: "Update task" },
|
|
146
|
+
TaskList: { icon: UiKanban.UiKanban, tone: "sky", label: "List tasks" },
|
|
147
|
+
TaskGet: { icon: UiKanban.UiKanban, tone: "sky", label: "Get task" },
|
|
148
|
+
TaskOutput: { icon: UiKanban.UiKanban, tone: "sky", label: "Task output" },
|
|
149
|
+
TaskStop: { icon: UiStop.UiStop, tone: "rose", label: "Stop task" },
|
|
150
|
+
ToolSearch: { icon: UiSearch.UiSearch, tone: "amber", label: "Search tools" },
|
|
151
|
+
AskUserQuestion: { icon: UiQuestion.UiQuestion, tone: "sky", label: "Ask user" },
|
|
152
|
+
EnterPlanMode: { icon: UiKanban.UiKanban, tone: "sky", label: "Enter plan mode" },
|
|
153
|
+
ExitPlanMode: { icon: UiKanban.UiKanban, tone: "sky", label: "Exit plan mode" },
|
|
154
|
+
// Web & browser automation
|
|
155
|
+
WebFetch: { icon: UiCloudDownload.UiCloudDownload, tone: "sky", label: "Fetch URL" },
|
|
156
|
+
WebSearch: { icon: UiGlobe.UiGlobe, tone: "sky", label: "Web search" },
|
|
157
|
+
browser_navigate: { icon: UiGlobe.UiGlobe, tone: "sky", label: "Navigate" },
|
|
158
|
+
browser_navigate_back: { icon: UiGlobe.UiGlobe, tone: "sky", label: "Navigate back" },
|
|
159
|
+
browser_click: { icon: UiSelect.UiSelect, tone: "sky", label: "Click" },
|
|
160
|
+
browser_triple_click: { icon: UiSelect.UiSelect, tone: "sky", label: "Triple click" },
|
|
161
|
+
browser_type: { icon: UiTerminal.UiTerminal, tone: "emerald", label: "Type text" },
|
|
162
|
+
browser_press_key: { icon: UiCommand.UiCommand, tone: "amber", label: "Press key" },
|
|
163
|
+
browser_snapshot: { icon: UiEye.UiEye, tone: "violet", label: "Snapshot" },
|
|
164
|
+
browser_take_screenshot: { icon: UiCamera.UiCamera, tone: "violet", label: "Screenshot" },
|
|
165
|
+
browser_evaluate: { icon: UiCode2.UiCode2, tone: "violet", label: "Evaluate JS" },
|
|
166
|
+
browser_network_requests: { icon: UiNetwork.UiNetwork, tone: "emerald", label: "Network" },
|
|
167
|
+
browser_wait_for: { icon: UiHourglass.UiHourglass, tone: "amber", label: "Wait" },
|
|
168
|
+
browser_close: { icon: UiClose.UiClose, tone: "rose", label: "Close browser" }
|
|
169
|
+
};
|
|
170
|
+
const MCP_ICON_SERVERS = /* @__PURE__ */ new Set(["iconify", "icons8", "lucide", "react-icons"]);
|
|
171
|
+
const MCP_GEN_SERVERS = /* @__PURE__ */ new Set(["gemini", "openai", "anthropic"]);
|
|
172
|
+
function splitMcpTool(tool) {
|
|
173
|
+
const rest = tool.startsWith("mcp__") ? tool.slice("mcp__".length) : tool;
|
|
174
|
+
const idx = rest.indexOf("__");
|
|
175
|
+
if (idx < 0) return null;
|
|
176
|
+
return { server: rest.slice(0, idx), name: rest.slice(idx + 2) };
|
|
177
|
+
}
|
|
178
|
+
function getSessionAction(tool) {
|
|
179
|
+
const exact = ACTIONS[tool];
|
|
180
|
+
if (exact) return exact;
|
|
181
|
+
const mcp = splitMcpTool(tool);
|
|
182
|
+
if (mcp) {
|
|
183
|
+
const label = `${mcp.server}: ${mcp.name.replace(/_/g, " ")}`;
|
|
184
|
+
if (MCP_ICON_SERVERS.has(mcp.server)) return { icon: UiImage.UiImage, tone: "pink", label };
|
|
185
|
+
if (MCP_GEN_SERVERS.has(mcp.server)) return { icon: UiSparkles.UiSparkles, tone: "violet", label };
|
|
186
|
+
return { icon: UiPuzzle.UiPuzzle, tone: "violet", label };
|
|
187
|
+
}
|
|
188
|
+
return { icon: UiWrench.UiWrench, tone: "slate", label: tool };
|
|
189
|
+
}
|
|
190
|
+
function summarizeToolInput(tool, input) {
|
|
191
|
+
if (!input) return "";
|
|
192
|
+
const str = (key) => typeof input[key] === "string" ? input[key] : "";
|
|
193
|
+
const first = (...keys) => {
|
|
194
|
+
for (const key of keys) {
|
|
195
|
+
const value = str(key);
|
|
196
|
+
if (value) return value;
|
|
197
|
+
}
|
|
198
|
+
return "";
|
|
199
|
+
};
|
|
200
|
+
const mcp = splitMcpTool(tool);
|
|
201
|
+
if (mcp) {
|
|
202
|
+
const arg = first("url", "sql", "query", "element", "method");
|
|
203
|
+
return arg ? truncate(arg, 80) : "";
|
|
204
|
+
}
|
|
205
|
+
switch (tool) {
|
|
206
|
+
case "Bash":
|
|
207
|
+
case "browser_type":
|
|
208
|
+
return truncate(str("command") || str("text"), 80);
|
|
209
|
+
case "Read":
|
|
210
|
+
case "Write":
|
|
211
|
+
case "Edit":
|
|
212
|
+
case "MultiEdit":
|
|
213
|
+
case "NotebookEdit":
|
|
214
|
+
return first("file_path", "notebook_path", "path");
|
|
215
|
+
case "Grep":
|
|
216
|
+
return [str("pattern"), str("path")].filter(Boolean).join(" ");
|
|
217
|
+
case "Glob":
|
|
218
|
+
return str("pattern");
|
|
219
|
+
case "Task":
|
|
220
|
+
case "Agent":
|
|
221
|
+
return truncate(first("description", "prompt"), 80);
|
|
222
|
+
case "Skill":
|
|
223
|
+
return first("skill", "command", "name");
|
|
224
|
+
case "TaskCreate":
|
|
225
|
+
return truncate(first("subject", "description"), 80);
|
|
226
|
+
case "TaskUpdate": {
|
|
227
|
+
const id = first("taskId", "task_id", "id");
|
|
228
|
+
const status = str("status");
|
|
229
|
+
return status ? `${id} ${status}`.trim() : id;
|
|
230
|
+
}
|
|
231
|
+
case "TaskGet":
|
|
232
|
+
case "TaskOutput":
|
|
233
|
+
case "TaskStop":
|
|
234
|
+
return first("task_id", "taskId", "id");
|
|
235
|
+
case "ToolSearch":
|
|
236
|
+
case "WebSearch":
|
|
237
|
+
return truncate(str("query"), 80);
|
|
238
|
+
case "WebFetch":
|
|
239
|
+
case "browser_navigate":
|
|
240
|
+
return str("url");
|
|
241
|
+
case "AskUserQuestion": {
|
|
242
|
+
const questions = input["questions"];
|
|
243
|
+
return Array.isArray(questions) ? `${questions.length} questions` : "";
|
|
244
|
+
}
|
|
245
|
+
case "ExitPlanMode":
|
|
246
|
+
return str("planFilePath");
|
|
247
|
+
default:
|
|
248
|
+
return "";
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
function summarizeSession(events) {
|
|
252
|
+
let toolCount = 0;
|
|
253
|
+
let messageCount = 0;
|
|
254
|
+
const modelCounts = /* @__PURE__ */ new Map();
|
|
255
|
+
for (const event of events) {
|
|
256
|
+
if (event.kind === "tool") toolCount += 1;
|
|
257
|
+
if (event.kind === "user" || event.kind === "assistant") messageCount += 1;
|
|
258
|
+
if (event.model) modelCounts.set(event.model, (modelCounts.get(event.model) ?? 0) + 1);
|
|
259
|
+
}
|
|
260
|
+
let model;
|
|
261
|
+
let best = 0;
|
|
262
|
+
for (const [name, count] of modelCounts) {
|
|
263
|
+
if (count > best) {
|
|
264
|
+
best = count;
|
|
265
|
+
model = name;
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
return { toolCount, messageCount, ...model ? { model } : {} };
|
|
269
|
+
}
|
|
270
|
+
exports.getSessionAction = getSessionAction;
|
|
271
|
+
exports.normalizeSession = normalizeSession;
|
|
272
|
+
exports.splitMcpTool = splitMcpTool;
|
|
273
|
+
exports.summarizeSession = summarizeSession;
|
|
274
|
+
exports.summarizeToolInput = summarizeToolInput;
|
|
275
|
+
//# sourceMappingURL=SessionViewer.model.cjs.map
|