From 0f8c533566ff80ba8acc8a93aa71fff541fbf3c3 Mon Sep 17 00:00:00 2001 From: William Guss Date: Sun, 11 Aug 2024 17:50:51 -0700 Subject: [PATCH 1/9] unified layout --- .../src/components/LMPDetailsSidePanel.js | 191 +++++----- ell-studio/src/components/MetricChart.js | 17 +- .../src/components/common/MetricCard.js | 18 + .../src/components/common/ScrollArea.js | 16 +- ell-studio/src/components/common/SidePanel.js | 13 + ell-studio/src/components/common/StatItem.js | 17 + .../InvocationsAnalyticsSidePanel.js | 75 ++++ .../invocations/InvocationsLayout.js | 2 +- .../{ => details}/InvocationDataPane.js | 4 +- .../InvocationDetailsPopover.js} | 10 +- .../{ => details}/TraceDetailsPane.js | 0 .../components/layouts/GenericPageLayout.js | 41 +++ ell-studio/src/pages/Invocations.js | 342 +++++++----------- ell-studio/src/pages/LMP.js | 319 ++++++++-------- 14 files changed, 538 insertions(+), 527 deletions(-) create mode 100644 ell-studio/src/components/common/MetricCard.js create mode 100644 ell-studio/src/components/common/SidePanel.js create mode 100644 ell-studio/src/components/common/StatItem.js create mode 100644 ell-studio/src/components/invocations/InvocationsAnalyticsSidePanel.js rename ell-studio/src/components/invocations/{ => details}/InvocationDataPane.js (94%) rename ell-studio/src/components/invocations/{InvocationDetailsSidebar.js => details/InvocationDetailsPopover.js} (94%) rename ell-studio/src/components/invocations/{ => details}/TraceDetailsPane.js (100%) create mode 100644 ell-studio/src/components/layouts/GenericPageLayout.js diff --git a/ell-studio/src/components/LMPDetailsSidePanel.js b/ell-studio/src/components/LMPDetailsSidePanel.js index 9c4f2660..8d06f64c 100644 --- a/ell-studio/src/components/LMPDetailsSidePanel.js +++ b/ell-studio/src/components/LMPDetailsSidePanel.js @@ -1,30 +1,20 @@ -import React, { useState, useMemo } from 'react'; +import React, { useMemo } from 'react'; import { Link } from 'react-router-dom'; import { FiClock, FiTag, FiGitCommit, FiZap, FiHash, FiCalendar } from 'react-icons/fi'; import { getTimeAgo } from '../utils/lmpUtils'; import VersionBadge from './VersionBadge'; -import MetricChart from './MetricChart'; import { useInvocationsFromLMP } from '../hooks/useBackend'; import { LMPCardTitle } from './depgraph/LMPCardTitle'; -import { subDays, format, addDays, endOfMonth } from 'date-fns'; -import { ScrollArea } from './common/ScrollArea'; - -function StatItem({ icon: Icon, label, value }) { - return ( -
- {label} - {value} -
- ); -} +import { format } from 'date-fns'; +import SidePanel from './common/SidePanel'; +import StatItem from './common/StatItem'; +import MetricCard from './common/MetricCard'; function LMPDetailsSidePanel({ lmp, uses, versionHistory }) { - // TODO: update this for all versions aswell.. const { data: invocations } = useInvocationsFromLMP(lmp.name, lmp.lmp_id, 0, 100); const chartData = useMemo(() => { if (!invocations || invocations.length === 0) return []; - return invocations .map(inv => ({ date: new Date(inv.created_at), @@ -42,101 +32,96 @@ function LMPDetailsSidePanel({ lmp, uses, versionHistory }) { }, [invocations]); return ( - // -
-

Details

-
-
-
-

Version

- -
- - - - -
+ +
+
+

Version

+ +
+ + + + +
- {lmp.lm_kwargs && ( -
-

LM Keywords

-
-                {JSON.stringify(lmp.lm_kwargs, null, 2)}
-              
-
- )} + {lmp.lm_kwargs && ( +
+

LM Keywords

+
+            {JSON.stringify(lmp.lm_kwargs, null, 2)}
+          
+
+ )} -
-

Uses

- {uses && uses.length > 0 ? ( -
    - {uses.filter(use => !!use).map((use) => ( -
  • - - - -
  • - ))} -
- ) : ( -

No dependencies

- )} -
+
+

Uses

+ {uses && uses.length > 0 ? ( +
    + {uses.filter(use => !!use).map((use) => ( +
  • + + + +
  • + ))} +
+ ) : ( +

No dependencies

+ )} +
- + - + -
-

Version History

-
- {versionHistory.map((version, index) => ( - -
- - v{versionHistory.length - index} - - - - {format(new Date(version.created_at), 'MMM d, yyyy')} - -
- {version.commit_message && ( -

- - {version.commit_message} -

- )} - - ))} -
-
+
+

Version History

+
+ {versionHistory.map((version, index) => ( + +
+ + v{versionHistory.length - index} + + + + {format(new Date(version.created_at), 'MMM d, yyyy')} + +
+ {version.commit_message && ( +

+ + {version.commit_message} +

+ )} + + ))}
- // +
); } diff --git a/ell-studio/src/components/MetricChart.js b/ell-studio/src/components/MetricChart.js index 977baeb2..f7daadc1 100644 --- a/ell-studio/src/components/MetricChart.js +++ b/ell-studio/src/components/MetricChart.js @@ -8,7 +8,7 @@ import { ResponsiveContainer, CartesianGrid, Brush, - Legend, + Legend } from "recharts"; import { format, @@ -31,7 +31,7 @@ import { subHours, } from "date-fns"; -function MetricChart({ rawData, dataKey, color, title, yAxisLabel, aggregation="sum" }) { +function MetricChart({ rawData, dataKey, color, yAxisLabel, aggregation="sum", title }) { const [dateRange, setDateRange] = useState(null); const [selectedTimeRange, setSelectedTimeRange] = useState("all"); @@ -170,8 +170,8 @@ function MetricChart({ rawData, dataKey, color, title, yAxisLabel, aggregation=" ); const formatTooltip = useCallback( - (value, name, props) => { - return [`${value} ${yAxisLabel || title.toLowerCase()}`, title]; + (value) => { + return [`${value} ${yAxisLabel || ''}`, title]; }, [yAxisLabel, title] ); @@ -181,8 +181,7 @@ function MetricChart({ rawData, dataKey, color, title, yAxisLabel, aggregation=" return (
-
-

{title}

+
setSearchTerm(e.target.value)} - /> - -
- - -
- - {advancedFilters.isOpen && ( -
- setAdvancedFilters(prev => ({ ...prev, lmpName: e.target.value }))} - /> - setAdvancedFilters(prev => ({ ...prev, inputContains: e.target.value }))} - /> - setAdvancedFilters(prev => ({ ...prev, outputContains: e.target.value }))} - /> -
- setAdvancedFilters(prev => ({ ...prev, latencyMin: e.target.value }))} - /> - setAdvancedFilters(prev => ({ ...prev, latencyMax: e.target.value }))} - /> -
-
- setAdvancedFilters(prev => ({ ...prev, tokensMin: e.target.value }))} - /> - setAdvancedFilters(prev => ({ ...prev, tokensMax: e.target.value }))} - /> -
-
- )} - + {/* Search bar, advanced filters, and controls */} +
+
+
+ setSearchTerm(e.target.value)} + /> +
- -
- + + +
+ + {advancedFilters.isOpen && ( +
+ setAdvancedFilters(prev => ({ ...prev, lmpName: e.target.value }))} + /> + setAdvancedFilters(prev => ({ ...prev, inputContains: e.target.value }))} + /> + setAdvancedFilters(prev => ({ ...prev, outputContains: e.target.value }))} + /> +
+ setAdvancedFilters(prev => ({ ...prev, latencyMin: e.target.value }))} + /> + setAdvancedFilters(prev => ({ ...prev, latencyMax: e.target.value }))} + /> +
+
+ setAdvancedFilters(prev => ({ ...prev, tokensMin: e.target.value }))} + /> + setAdvancedFilters(prev => ({ ...prev, tokensMax: e.target.value }))} + /> +
- - - - {!selectedTrace && ( - <> - - - - {!isAggregateLoading && aggregateData && ( - <> -
-
-

Total Invocations

-

{aggregateData.total_invocations}

-
-
-

Avg Latency

-

{aggregateData.avg_latency.toFixed(2)}ms

-
-
-

Total Tokens

-

{aggregateData.total_tokens}

-
-
-

Unique LMPs

-

{aggregateData.unique_lmps}

-
-
- -
-
-

Invocations Over Time

- -
- -
-

Latency Over Time

- -
- -
-

Tokens Over Time

- -
- - -
-

Top 5 LMPs

-
    - {sidebarMetrics.topLMPs.map(([lmp, count], index) => ( -
  • - {index + 1}. {lmp} - {count} invocations -
  • - ))} -
-
+ )} + +
-
-

Additional Metrics

-
-
- Success Rate: - {aggregateData.success_rate?.toFixed(2)}% -
-
- Avg Tokens per Invocation: - {(aggregateData.total_tokens / aggregateData.total_invocations).toFixed(2)} -
-
-
-
- - )} - - - - )} - +
+ +
+ + ); }; -export default Traces; \ No newline at end of file +export default Invocations; \ No newline at end of file diff --git a/ell-studio/src/pages/LMP.js b/ell-studio/src/pages/LMP.js index f16227dc..e3d853fd 100644 --- a/ell-studio/src/pages/LMP.js +++ b/ell-studio/src/pages/LMP.js @@ -21,13 +21,9 @@ import { LMPCardTitle } from "../components/depgraph/LMPCardTitle"; import InvocationsLayout from "../components/invocations/InvocationsLayout"; import ToggleSwitch from "../components/common/ToggleSwitch"; import LMPDetailsSidePanel from "../components/LMPDetailsSidePanel"; -import { - ResizablePanelGroup, - ResizablePanel, - ResizableHandle, -} from "../components/common/Resizable"; -import { ScrollArea } from "../components/common/ScrollArea"; +import {Card} from "../components/common/Card"; +import GenericPageLayout from "../components/layouts/GenericPageLayout"; function LMP() { const { name, id } = useParams(); let [searchParams, setSearchParams] = useSearchParams(); @@ -56,7 +52,6 @@ function LMP() { ); const uses = lmp?.uses; - const [activeTab, setActiveTab] = useState("runs"); const [selectedTrace, setSelectedTrace] = useState(null); const navigate = useNavigate(); @@ -119,181 +114,153 @@ function LMP() { const omitColumns = ["name"]; return ( - + } > - - {/* */} - -
-

- - - -

-
- - -
-
+
+

+ + + + + +

+
-
-
-
-
-

- Language Model Program -

- {(id || requestedInvocationId) && ( - <> - - - - )} -
-
- {previousVersion && ( - <> - {viewMode === "Diff" && ( -
- - Comparing to - -
- )} - - - )} - -
-
-
- +
+
+
+

Language Model Program

+ {(id || requestedInvocationId) && ( + <> + + -
-
- -
-
- {["Runs", "Version History"].map( - (tab) => ( - - ) - )} -
- -
- {activeTab === "runs" && ( - <> -
-
- - - - - -
- -
- { - setSelectedTrace(trace); - setSearchParams({ i: trace.id }); - }} - currentlySelectedTrace={selectedTrace} - omitColumns={omitColumns} + + )} +
+
+ {previousVersion && ( + <> + {viewMode === "Diff" && ( +
+ + Comparing to + - +
)} - {activeTab === "version_history" && ( - - )} - -
-
-
-
- {/*
*/} -
- {!selectedTrace && ( - <> - - -
- + + + )} +
-
- - )} -
+
+
+ +
+
+ +
+
+ {["Runs", "Version History"].map((tab) => ( + + ))} +
+ +
+ {activeTab === "runs" && ( + <> +
+
+ + + + + +
+ +
+ { + setSelectedTrace(trace); + setSearchParams({ i: trace.id }); + }} + currentlySelectedTrace={selectedTrace} + omitColumns={omitColumns} + /> + + )} + {activeTab === "version_history" && ( + + )} +
+
+ + ); } From 05ea5c0270abae2bb9f6f4b44a75f1efd7f9bcb8 Mon Sep 17 00:00:00 2001 From: William Guss Date: Sun, 11 Aug 2024 18:08:35 -0700 Subject: [PATCH 2/9] clean up thigns --- .../src/components/HierarchicalTable.js | 40 ++++++++++++------- ell-studio/src/components/common/StatItem.js | 7 ++-- .../components/layouts/GenericPageLayout.js | 26 ++++++------ ell-studio/src/pages/LMP.js | 26 +++++++----- 4 files changed, 58 insertions(+), 41 deletions(-) diff --git a/ell-studio/src/components/HierarchicalTable.js b/ell-studio/src/components/HierarchicalTable.js index cb0b2902..48fee663 100644 --- a/ell-studio/src/components/HierarchicalTable.js +++ b/ell-studio/src/components/HierarchicalTable.js @@ -2,6 +2,8 @@ import React, { useMemo, useRef, useEffect, useState, useCallback } from 'react' import { FiChevronDown, FiArrowUp, FiArrowDown, FiChevronLeft, FiChevronRight, FiChevronsLeft, FiChevronsRight } from 'react-icons/fi'; import { HierarchicalTableProvider, useHierarchicalTable } from './HierarchicalTableContext'; import { Checkbox } from "components/common/Checkbox" +import { debounce } from 'lodash'; + // Update the SmoothLine component const SmoothLine = ({ index, startX, startY, endX: endXPreprocess, special, endY, color, animated, opacity, offset }) => { const endX = endXPreprocess; @@ -83,34 +85,44 @@ const TableRow = ({ item, schema, level = 0, onRowClick, columnWidths, updateWid }, [isNew]); const primaryColumnRef = useRef(null); - + useEffect(() => { if (!primaryColumnRef.current) return; + const table = primaryColumnRef.current.closest('table'); + let tableRect = table.getBoundingClientRect(); + const updatePosition = () => { - const tableRect = primaryColumnRef.current.closest('table').getBoundingClientRect(); - const rowRect = primaryColumnRef.current.getBoundingClientRect(); - const relativeX = rowRect.left - tableRect.left; - const relativeY = rowRect.top - tableRect.top + rowRect.height / 2; - setRowRef(item.id, { id: item.id, x: relativeX, y: relativeY, visible: true }); + requestAnimationFrame(() => { + if (!primaryColumnRef.current) return; + const rowRect = primaryColumnRef.current.getBoundingClientRect(); + const relativeX = rowRect.left - tableRect.left; + const relativeY = rowRect.top - tableRect.top + rowRect.height / 2; + setRowRef(item.id, { id: item.id, x: relativeX, y: relativeY, visible: true }); + }); }; - // Initial position update - updatePosition(); + const debouncedUpdatePosition = debounce(updatePosition, 100); + + // Shared ResizeObserver + const resizeObserver = new ResizeObserver(() => { + tableRect = table.getBoundingClientRect(); // Update tableRect + debouncedUpdatePosition(); + }); - // Create a ResizeObserver - const resizeObserver = new ResizeObserver(updatePosition); + // Observe only the table + resizeObserver.observe(table); - // Observe both the row and the table - resizeObserver.observe(primaryColumnRef.current); - resizeObserver.observe(primaryColumnRef.current.closest('table')); + // Initial position update + updatePosition(); // Clean up return () => { setRowRef(item.id, {visible: false}); resizeObserver.disconnect(); + debouncedUpdatePosition.cancel(); }; - }, [item.id, setRowRef, sortedData.length, expandedRows, linkColumn]); + }, [item.id, setRowRef]); return ( diff --git a/ell-studio/src/components/common/StatItem.js b/ell-studio/src/components/common/StatItem.js index a7c4a72d..829df0a2 100644 --- a/ell-studio/src/components/common/StatItem.js +++ b/ell-studio/src/components/common/StatItem.js @@ -1,9 +1,8 @@ import React from 'react'; -import { motion } from 'framer-motion'; const StatItem = ({ icon: Icon, label, value }) => ( - @@ -11,7 +10,7 @@ const StatItem = ({ icon: Icon, label, value }) => ( {label} {value} - +
); export default StatItem; \ No newline at end of file diff --git a/ell-studio/src/components/layouts/GenericPageLayout.js b/ell-studio/src/components/layouts/GenericPageLayout.js index e8796669..f5789f1d 100644 --- a/ell-studio/src/components/layouts/GenericPageLayout.js +++ b/ell-studio/src/components/layouts/GenericPageLayout.js @@ -1,4 +1,4 @@ -import React from 'react'; +import React, { useState, useEffect } from 'react'; import { ResizablePanelGroup, ResizablePanel, ResizableHandle } from "../common/Resizable"; import { ScrollArea } from '../common/ScrollArea'; import InvocationsLayout from '../invocations/InvocationsLayout'; @@ -10,9 +10,15 @@ const GenericPageLayout = ({ sidebarContent, showSidebar = true, }) => { + const [sidebarVisible, setSidebarVisible] = useState(!selectedTrace && showSidebar); + + useEffect(() => { + setSidebarVisible(!selectedTrace && showSidebar); + }, [selectedTrace, showSidebar]); + return ( - + - {!selectedTrace && showSidebar && ( - <> - - - - {sidebarContent} - - - - )} + + + + {sidebarContent} + + ); }; diff --git a/ell-studio/src/pages/LMP.js b/ell-studio/src/pages/LMP.js index e3d853fd..4bbbf65c 100644 --- a/ell-studio/src/pages/LMP.js +++ b/ell-studio/src/pages/LMP.js @@ -21,7 +21,7 @@ import { LMPCardTitle } from "../components/depgraph/LMPCardTitle"; import InvocationsLayout from "../components/invocations/InvocationsLayout"; import ToggleSwitch from "../components/common/ToggleSwitch"; import LMPDetailsSidePanel from "../components/LMPDetailsSidePanel"; -import {Card} from "../components/common/Card"; +import { Card } from "../components/common/Card"; import GenericPageLayout from "../components/layouts/GenericPageLayout"; function LMP() { @@ -100,6 +100,16 @@ function LMP() { }); }; + const sidebar = useMemo( + () => ( + + ), + [lmp, uses, versionHistory] + ); const handleViewModeToggle = () => { setViewMode((prevMode) => (prevMode === "Source" ? "Diff" : "Source")); }; @@ -117,20 +127,14 @@ function LMP() { - } + sidebarContent={sidebar} >

- - - + + +

From aae6349f52a5251f0c90cc6eac89f74ebe7eb3b2 Mon Sep 17 00:00:00 2001 From: William Guss Date: Sun, 11 Aug 2024 18:17:34 -0700 Subject: [PATCH 3/9] theme changes --- ell-studio/src/App.css | 38 ---------------- .../src/components/LMPDetailsSidePanel.js | 32 +++++++------- ell-studio/src/components/Sidebar.js | 10 ++--- .../src/components/common/MetricCard.js | 4 +- ell-studio/src/components/common/SidePanel.js | 4 +- .../components/layouts/GenericPageLayout.js | 12 +++--- ell-studio/src/contexts/ThemeContext.js | 10 ++++- ell-studio/src/pages/Home.js | 7 ++- ell-studio/src/pages/LMP.js | 36 ++++++++-------- ell-studio/src/styles/globals.css | 7 +-- tailwind.config.js | 43 ++++++++++++++++--- 11 files changed, 99 insertions(+), 104 deletions(-) delete mode 100644 ell-studio/src/App.css diff --git a/ell-studio/src/App.css b/ell-studio/src/App.css deleted file mode 100644 index 74b5e053..00000000 --- a/ell-studio/src/App.css +++ /dev/null @@ -1,38 +0,0 @@ -.App { - text-align: center; -} - -.App-logo { - height: 40vmin; - pointer-events: none; -} - -@media (prefers-reduced-motion: no-preference) { - .App-logo { - animation: App-logo-spin infinite 20s linear; - } -} - -.App-header { - background-color: #282c34; - min-height: 100vh; - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; - font-size: calc(10px + 2vmin); - color: white; -} - -.App-link { - color: #61dafb; -} - -@keyframes App-logo-spin { - from { - transform: rotate(0deg); - } - to { - transform: rotate(360deg); - } -} diff --git a/ell-studio/src/components/LMPDetailsSidePanel.js b/ell-studio/src/components/LMPDetailsSidePanel.js index 8d06f64c..0efe8a2d 100644 --- a/ell-studio/src/components/LMPDetailsSidePanel.js +++ b/ell-studio/src/components/LMPDetailsSidePanel.js @@ -33,9 +33,9 @@ function LMPDetailsSidePanel({ lmp, uses, versionHistory }) { return ( -
+
-

Version

+

Version

@@ -45,28 +45,28 @@ function LMPDetailsSidePanel({ lmp, uses, versionHistory }) {
{lmp.lm_kwargs && ( -
-

LM Keywords

-
+        
+

LM Keywords

+
             {JSON.stringify(lmp.lm_kwargs, null, 2)}
           
)} -
-

Uses

+
+

Uses

{uses && uses.length > 0 ? (
    {uses.filter(use => !!use).map((use) => (
  • - +
  • ))}
) : ( -

No dependencies

+

No dependencies

)}
@@ -87,8 +87,8 @@ function LMPDetailsSidePanel({ lmp, uses, versionHistory }) { yAxisLabel="ms" /> -
-

Version History

+
+

Version History

{versionHistory.map((version, index) => (
v{versionHistory.length - index} - + {format(new Date(version.created_at), 'MMM d, yyyy')}
{version.commit_message && ( -

+

{version.commit_message}

diff --git a/ell-studio/src/components/Sidebar.js b/ell-studio/src/components/Sidebar.js index d3e1578f..d6bc1cbf 100644 --- a/ell-studio/src/components/Sidebar.js +++ b/ell-studio/src/components/Sidebar.js @@ -12,7 +12,7 @@ const Sidebar = () => { to={to} className={({ isActive }) => ` group flex items-center py-3 px-4 rounded-lg transition-all duration-200 - ${isActive ? 'bg-blue-500/10 text-blue-500' : 'text-gray-400 hover:text-white'} + ${isActive ? 'bg-primary/10 text-primary' : 'text-muted-foreground hover:text-foreground'} `} > @@ -20,7 +20,7 @@ const Sidebar = () => { {label} )} {!isExpanded && ( -
+
{label}
)} @@ -31,7 +31,7 @@ const Sidebar = () => {
ell-studio Logo @@ -50,9 +50,9 @@ const Sidebar = () => { diff --git a/ell-studio/src/components/common/MetricCard.js b/ell-studio/src/components/common/MetricCard.js index b4aaa1ba..7b339e4b 100644 --- a/ell-studio/src/components/common/MetricCard.js +++ b/ell-studio/src/components/common/MetricCard.js @@ -2,8 +2,8 @@ import React from 'react'; import MetricChart from '../MetricChart'; const MetricCard = ({ title, rawData, dataKey, color, yAxisLabel, aggregation }) => ( -
-

{title}

+
+

{title}

( - -

{title}

+ +

{title}

{children}
diff --git a/ell-studio/src/components/layouts/GenericPageLayout.js b/ell-studio/src/components/layouts/GenericPageLayout.js index f5789f1d..948df84d 100644 --- a/ell-studio/src/components/layouts/GenericPageLayout.js +++ b/ell-studio/src/components/layouts/GenericPageLayout.js @@ -17,21 +17,21 @@ const GenericPageLayout = ({ }, [selectedTrace, showSidebar]); return ( - + -
- {children} -
+
+ {children} +
- + {sidebarContent} diff --git a/ell-studio/src/contexts/ThemeContext.js b/ell-studio/src/contexts/ThemeContext.js index 847202f6..a2b2a58b 100644 --- a/ell-studio/src/contexts/ThemeContext.js +++ b/ell-studio/src/contexts/ThemeContext.js @@ -1,4 +1,4 @@ -import React, { createContext, useState, useContext } from 'react'; +import React, { createContext, useState, useContext, useEffect } from 'react'; const ThemeContext = createContext(); @@ -7,6 +7,14 @@ export const useTheme = () => useContext(ThemeContext); export const ThemeProvider = ({ children }) => { const [darkMode, setDarkMode] = useState(true); + useEffect(() => { + if (darkMode) { + document.documentElement.classList.add('dark'); + } else { + document.documentElement.classList.remove('dark'); + } + }, [darkMode]); + const toggleDarkMode = () => { setDarkMode(!darkMode); }; diff --git a/ell-studio/src/pages/Home.js b/ell-studio/src/pages/Home.js index e6a3485f..98cb2a17 100644 --- a/ell-studio/src/pages/Home.js +++ b/ell-studio/src/pages/Home.js @@ -17,7 +17,6 @@ function Home() { const { darkMode } = useTheme(); const { data: lmps, isLoading: isLoadingLMPs } = useLatestLMPs(); const { data: traces, isLoading: isLoadingTraces } = useTraces(lmps); - const toggleExpand = (lmpName, event) => { if (event.target.tagName.toLowerCase() !== 'a') { @@ -56,14 +55,14 @@ function Home() {
- + Language Model Programs
- + Total LMPs: {lmps.length} - + Last Updated: {lmps[0] && lmps[0].versions && lmps[0].versions[0] ? getTimeAgo(lmps[0].versions[0].created_at) : 'N/A'}
diff --git a/ell-studio/src/pages/LMP.js b/ell-studio/src/pages/LMP.js index 4bbbf65c..a9004c9e 100644 --- a/ell-studio/src/pages/LMP.js +++ b/ell-studio/src/pages/LMP.js @@ -116,7 +116,7 @@ function LMP() { if (isLoadingLMP) return ( -
+
Loading...
); @@ -139,14 +139,14 @@ function LMP() {
-
-
+
+
-

Language Model Program

+

Language Model Program

{(id || requestedInvocationId) && ( <> - + {viewMode === "Diff" && ( -
+
Comparing to
)} @@ -181,7 +181,7 @@ function LMP() { )}
-
+
{["Runs", "Version History"].map((tab) => ( - - - -
-
@@ -268,4 +268,4 @@ function LMP() { ); } -export default LMP; +export default LMP; \ No newline at end of file diff --git a/ell-studio/src/styles/globals.css b/ell-studio/src/styles/globals.css index 4c6132f7..9418614b 100644 --- a/ell-studio/src/styles/globals.css +++ b/ell-studio/src/styles/globals.css @@ -23,11 +23,6 @@ --border: 217.2 32.6% 17.5%; --input: 217.2 32.6% 17.5%; --ring: 224.3 76.3% 48%; - --chart-1: 220 70% 50%; - --chart-2: 160 60% 45%; - --chart-3: 30 80% 55%; - --chart-4: 280 65% 60%; - --chart-5: 340 75% 55%; --radius: 0.5rem; } } @@ -87,4 +82,4 @@ to { stroke-dashoffset: -10; } -} +} \ No newline at end of file diff --git a/tailwind.config.js b/tailwind.config.js index d3ec7ae0..dc8495df 100644 --- a/tailwind.config.js +++ b/tailwind.config.js @@ -1,11 +1,43 @@ module.exports = { - // ... other config + darkMode: ["class"], + content: [ + "./src/**/*.{js,jsx,ts,tsx}", + ], theme: { extend: { colors: { - gray: { - 750: '#2d333b', - 850: '#22272e', + border: "hsl(var(--border))", + input: "hsl(var(--input))", + ring: "hsl(var(--ring))", + background: "hsl(var(--background))", + foreground: "hsl(var(--foreground))", + primary: { + DEFAULT: "hsl(var(--primary))", + foreground: "hsl(var(--primary-foreground))", + }, + secondary: { + DEFAULT: "hsl(var(--secondary))", + foreground: "hsl(var(--secondary-foreground))", + }, + destructive: { + DEFAULT: "hsl(var(--destructive))", + foreground: "hsl(var(--destructive-foreground))", + }, + muted: { + DEFAULT: "hsl(var(--muted))", + foreground: "hsl(var(--muted-foreground))", + }, + accent: { + DEFAULT: "hsl(var(--accent))", + foreground: "hsl(var(--accent-foreground))", + }, + popover: { + DEFAULT: "hsl(var(--popover))", + foreground: "hsl(var(--popover-foreground))", + }, + card: { + DEFAULT: "hsl(var(--card))", + foreground: "hsl(var(--card-foreground))", }, }, keyframes: { @@ -29,5 +61,4 @@ module.exports = { addUtilities(newUtilities, ['responsive', 'hover']); }, ], - // ... other config -}; \ No newline at end of file +} \ No newline at end of file From 54979a91a2db7a2ed859676193e265ff724519b4 Mon Sep 17 00:00:00 2001 From: William Guss Date: Sun, 11 Aug 2024 18:20:01 -0700 Subject: [PATCH 4/9] cool theme improvmeent --- ell-studio/src/components/Sidebar.js | 6 ++-- ell-studio/src/pages/Home.js | 34 +++++++++--------- ell-studio/src/styles/globals.css | 54 +++++++++++++++++++--------- 3 files changed, 58 insertions(+), 36 deletions(-) diff --git a/ell-studio/src/components/Sidebar.js b/ell-studio/src/components/Sidebar.js index d6bc1cbf..80ad504d 100644 --- a/ell-studio/src/components/Sidebar.js +++ b/ell-studio/src/components/Sidebar.js @@ -12,7 +12,7 @@ const Sidebar = () => { to={to} className={({ isActive }) => ` group flex items-center py-3 px-4 rounded-lg transition-all duration-200 - ${isActive ? 'bg-primary/10 text-primary' : 'text-muted-foreground hover:text-foreground'} + ${isActive ? 'bg-accent text-accent-foreground' : 'text-muted-foreground hover:text-foreground hover:bg-accent/50'} `} > @@ -20,7 +20,7 @@ const Sidebar = () => { {label} )} {!isExpanded && ( -
+
{label}
)} @@ -31,7 +31,7 @@ const Sidebar = () => {
ell-studio Logo diff --git a/ell-studio/src/pages/Home.js b/ell-studio/src/pages/Home.js index 98cb2a17..6436530f 100644 --- a/ell-studio/src/pages/Home.js +++ b/ell-studio/src/pages/Home.js @@ -44,58 +44,58 @@ function Home() { const memoizedLMPs = useMemo(() => firstLMPs, [firstLMPs]); if (!memoizedLMPs || !memoizedTraces) { - return
-

Loading...

+ return
+

Loading...

; } return ( -
+
-
- +
+ Language Model Programs
- + Total LMPs: {lmps.length} - + Last Updated: {lmps[0] && lmps[0].versions && lmps[0].versions[0] ? getTimeAgo(lmps[0].versions[0].created_at) : 'N/A'}
- +
-
+
{lmps.map((lmp) => ( toggleExpand(lmp.name, e)} >
e.stopPropagation()} > - {lmp.name} + {lmp.name}
- + ID: {truncateId(lmp.lmp_id)} - + Latest @@ -103,9 +103,9 @@ function Home() {
-
- - {lmp.source.length > 100 ? `${lmp.source.substring(0, 100)}...` : lmp.source} +
+ + {lmp.source.length > 100 ? `${lmp.source.substring(0, 100)}...` : lmp.source}
diff --git a/ell-studio/src/styles/globals.css b/ell-studio/src/styles/globals.css index 9418614b..a1cebeff 100644 --- a/ell-studio/src/styles/globals.css +++ b/ell-studio/src/styles/globals.css @@ -4,27 +4,49 @@ @layer base { :root { - --background: 222.2 84% 4.9%; - --foreground: 210 40% 98%; - --card: 222.2 84% 4.9%; - --card-foreground: 210 40% 98%; - --popover: 222.2 84% 4.9%; - --popover-foreground: 210 40% 98%; - --primary: 217.2 91.2% 59.8%; - --primary-foreground: 222.2 47.4% 11.2%; - --secondary: 217.2 32.6% 17.5%; + --background: 224 71% 4%; + --foreground: 213 31% 91%; + --card: 224 71% 4%; + --card-foreground: 213 31% 91%; + --popover: 224 71% 4%; + --popover-foreground: 213 31% 91%; + --primary: 210 40% 98%; + --primary-foreground: 222.2 47.4% 1.2%; + --secondary: 222.2 47.4% 11.2%; --secondary-foreground: 210 40% 98%; - --muted: 217.2 32.6% 17.5%; - --muted-foreground: 215 20.2% 65.1%; - --accent: 217.2 32.6% 17.5%; + --muted: 223 47% 11%; + --muted-foreground: 215.4 16.3% 56.9%; + --accent: 216 34% 17%; --accent-foreground: 210 40% 98%; - --destructive: 0 62.8% 30.6%; + --destructive: 0 63% 31%; --destructive-foreground: 210 40% 98%; - --border: 217.2 32.6% 17.5%; - --input: 217.2 32.6% 17.5%; - --ring: 224.3 76.3% 48%; + --border: 216 34% 17%; + --input: 216 34% 17%; + --ring: 216 34% 17%; --radius: 0.5rem; } + + .dark { + --background: 224 71% 4%; + --foreground: 213 31% 91%; + --card: 224 71% 4%; + --card-foreground: 213 31% 91%; + --popover: 224 71% 4%; + --popover-foreground: 213 31% 91%; + --primary: 210 40% 98%; + --primary-foreground: 222.2 47.4% 1.2%; + --secondary: 222.2 47.4% 11.2%; + --secondary-foreground: 210 40% 98%; + --muted: 223 47% 11%; + --muted-foreground: 215.4 16.3% 56.9%; + --accent: 216 34% 17%; + --accent-foreground: 210 40% 98%; + --destructive: 0 63% 31%; + --destructive-foreground: 210 40% 98%; + --border: 216 34% 17%; + --input: 216 34% 17%; + --ring: 216 34% 17%; + } } @layer base { From 25b5838ae90e75149d37e5fde1c58952ab4a753a Mon Sep 17 00:00:00 2001 From: William Guss Date: Sun, 11 Aug 2024 18:21:12 -0700 Subject: [PATCH 5/9] sexy --- .../components/layouts/GenericPageLayout.js | 8 +- ell-studio/src/pages/Invocations.js | 66 +++-- ell-studio/src/pages/LMP.js | 253 +++++++++--------- 3 files changed, 163 insertions(+), 164 deletions(-) diff --git a/ell-studio/src/components/layouts/GenericPageLayout.js b/ell-studio/src/components/layouts/GenericPageLayout.js index 948df84d..06a4aec2 100644 --- a/ell-studio/src/components/layouts/GenericPageLayout.js +++ b/ell-studio/src/components/layouts/GenericPageLayout.js @@ -23,16 +23,16 @@ const GenericPageLayout = ({ selectedTrace={selectedTrace} setSelectedTrace={setSelectedTrace} showSidebar={showSidebar} - containerClass="flex flex-col h-full" + containerClass="flex flex-col h-full bg-background" > -
+
{children}
- + - + {sidebarContent} diff --git a/ell-studio/src/pages/Invocations.js b/ell-studio/src/pages/Invocations.js index ad1e2a61..073d3b81 100644 --- a/ell-studio/src/pages/Invocations.js +++ b/ell-studio/src/pages/Invocations.js @@ -145,24 +145,30 @@ const Invocations = () => { setSelectedTrace={setSelectedTrace} sidebarContent={sidebarContent} > -
-

- Invocations -

-
+
+
+

Invocations

+
+ +
+
- {/* Search bar, advanced filters, and controls */} -
-
-
+
+
setSearchTerm(e.target.value)} /> - +
-
{advancedFilters.isOpen && ( @@ -238,23 +237,22 @@ const Invocations = () => {
)} +
+ +
+
- -
- -
- ); }; diff --git a/ell-studio/src/pages/LMP.js b/ell-studio/src/pages/LMP.js index a9004c9e..9cc2f66a 100644 --- a/ell-studio/src/pages/LMP.js +++ b/ell-studio/src/pages/LMP.js @@ -129,141 +129,142 @@ function LMP() { setSelectedTrace={setSelectedTrace} sidebarContent={sidebar} > -
-

- - - - - -

-
+
+
+

+ + + + + +

+
-
-
-
-
-

Language Model Program

- {(id || requestedInvocationId) && ( - <> - - - - )} +
+
+
+
+

Language Model Program

+ {(id || requestedInvocationId) && ( + <> + + + + )} +
+
+ {previousVersion && ( + <> + {viewMode === "Diff" && ( +
+ + Comparing to + +
+ )} + + + )} + +
-
- {previousVersion && ( - <> - {viewMode === "Diff" && ( -
- - Comparing to - -
- )} - - - )} - +
+
-
- -
-
-
-
- {["Runs", "Version History"].map((tab) => ( - - ))} -
+
+
+ {["Runs", "Version History"].map((tab) => ( + + ))} +
-
- {activeTab === "runs" && ( - <> -
-
- - - - - + + + + +
+
- -
- { - setSelectedTrace(trace); - setSearchParams({ i: trace.id }); - }} - currentlySelectedTrace={selectedTrace} - omitColumns={omitColumns} - /> - - )} - {activeTab === "version_history" && ( - - )} + { + setSelectedTrace(trace); + setSearchParams({ i: trace.id }); + }} + currentlySelectedTrace={selectedTrace} + omitColumns={omitColumns} + /> + + )} + {activeTab === "version_history" && ( + + )} +
-
-
+
+
); } From 5532465f5867d488d9823429d9cacd6fee695001 Mon Sep 17 00:00:00 2001 From: William Guss Date: Sun, 11 Aug 2024 18:22:38 -0700 Subject: [PATCH 6/9] a much more goregous view --- .../InvocationsAnalyticsSidePanel.js | 38 +++++++------------ 1 file changed, 14 insertions(+), 24 deletions(-) diff --git a/ell-studio/src/components/invocations/InvocationsAnalyticsSidePanel.js b/ell-studio/src/components/invocations/InvocationsAnalyticsSidePanel.js index 377871e4..076db775 100644 --- a/ell-studio/src/components/invocations/InvocationsAnalyticsSidePanel.js +++ b/ell-studio/src/components/invocations/InvocationsAnalyticsSidePanel.js @@ -1,25 +1,21 @@ import React from 'react'; +import { FiZap, FiClock, FiHash, FiUsers, FiPercent, FiBox } from 'react-icons/fi'; import SidePanel from '../common/SidePanel'; import StatItem from '../common/StatItem'; import MetricCard from '../common/MetricCard'; -import { FiZap, FiClock, FiHash, FiUsers, FiPercent, FiBox } from 'react-icons/fi'; const InvocationsAnalyticsSidePanel = ({ aggregateData, sidebarMetrics }) => { - if (!aggregateData) return null; - - const statsData = [ - { icon: FiZap, label: "Total Invocations", value: aggregateData.total_invocations }, - { icon: FiClock, label: "Avg Latency", value: `${aggregateData.avg_latency.toFixed(2)}ms` }, - { icon: FiHash, label: "Total Tokens", value: aggregateData.total_tokens }, - { icon: FiUsers, label: "Unique LMPs", value: aggregateData.unique_lmps }, - ]; + if (!aggregateData || !sidebarMetrics) return null; return ( -
- {statsData.map((stat, index) => ( - - ))} +
+ + + + + +
{ yAxisLabel="Tokens" /> -
-

Top 5 LMPs

+
+

Top 5 LMPs

    {sidebarMetrics.topLMPs.map(([lmp, count], index) => (
  • - - {index + 1}. + + {index + 1}. {lmp} - {count} invocations + {count} invocations
  • ))}
- -
-

Additional Metrics

- - -
); }; From 45a6d59bc7814f42d6e6db207c9347e07c8b5c31 Mon Sep 17 00:00:00 2001 From: William Guss Date: Sun, 11 Aug 2024 19:00:57 -0700 Subject: [PATCH 7/9] better sidebar --- .../src/components/LMPDetailsSidePanel.js | 180 ++++++++++-------- ell-studio/src/components/MetricChart.js | 106 ++++------- .../src/components/common/MetricCard.js | 3 +- .../InvocationsAnalyticsSidePanel.js | 105 +++++----- 4 files changed, 195 insertions(+), 199 deletions(-) diff --git a/ell-studio/src/components/LMPDetailsSidePanel.js b/ell-studio/src/components/LMPDetailsSidePanel.js index 0efe8a2d..195611dc 100644 --- a/ell-studio/src/components/LMPDetailsSidePanel.js +++ b/ell-studio/src/components/LMPDetailsSidePanel.js @@ -1,6 +1,6 @@ import React, { useMemo } from 'react'; import { Link } from 'react-router-dom'; -import { FiClock, FiTag, FiGitCommit, FiZap, FiHash, FiCalendar } from 'react-icons/fi'; +import { FiClock, FiTag, FiGitCommit, FiZap, FiHash, FiCalendar, FiChevronRight } from 'react-icons/fi'; import { getTimeAgo } from '../utils/lmpUtils'; import VersionBadge from './VersionBadge'; import { useInvocationsFromLMP } from '../hooks/useBackend'; @@ -9,6 +9,7 @@ import { format } from 'date-fns'; import SidePanel from './common/SidePanel'; import StatItem from './common/StatItem'; import MetricCard from './common/MetricCard'; +import { motion } from 'framer-motion'; function LMPDetailsSidePanel({ lmp, uses, versionHistory }) { const { data: invocations } = useInvocationsFromLMP(lmp.name, lmp.lmp_id, 0, 100); @@ -33,94 +34,109 @@ function LMPDetailsSidePanel({ lmp, uses, versionHistory }) { return ( -
-
-

Version

- + +
+
+

Version Info

+ +
+
+ + + + +
- - - - -
- {lmp.lm_kwargs && ( -
-

LM Keywords

-
-            {JSON.stringify(lmp.lm_kwargs, null, 2)}
-          
-
- )} - -
-

Uses

- {uses && uses.length > 0 ? ( -
    - {uses.filter(use => !!use).map((use) => ( -
  • - - - -
  • - ))} -
- ) : ( -

No dependencies

+ {lmp.lm_kwargs && ( +
+

LM Keywords

+
+              {JSON.stringify(lmp.lm_kwargs, null, 2)}
+            
+
)} -
- +
+

Uses

+ {uses && uses.length > 0 ? ( +
    + {uses.filter(use => !!use).map((use) => ( + + + + + + ))} +
+ ) : ( +

No dependencies

+ )} +
+ + - + -
-

Version History

-
- {versionHistory.map((version, index) => ( - -
- - v{versionHistory.length - index} - - - - {format(new Date(version.created_at), 'MMM d, yyyy')} - -
- {version.commit_message && ( -

- - {version.commit_message} -

- )} - - ))} +
+

Version History

+
+ {versionHistory.map((version, index) => ( + + +
+ + v{versionHistory.length - index} + + + + {format(new Date(version.created_at), 'MMM d, yyyy')} + +
+ {version.commit_message && ( +

+ + {version.commit_message} +

+ )} + +
+ ))} +
-
+ ); } diff --git a/ell-studio/src/components/MetricChart.js b/ell-studio/src/components/MetricChart.js index f7daadc1..7bf9e2f4 100644 --- a/ell-studio/src/components/MetricChart.js +++ b/ell-studio/src/components/MetricChart.js @@ -8,22 +8,17 @@ import { ResponsiveContainer, CartesianGrid, Brush, - Legend } from "recharts"; import { format, differenceInDays, differenceInHours, - differenceInMinutes, startOfMinute, - endOfMinute, eachMinuteOfInterval, eachHourOfInterval, eachDayOfInterval, startOfHour, - endOfHour, startOfDay, - endOfDay, addMinutes, getMinutes, subMonths, @@ -43,23 +38,16 @@ function MetricChart({ rawData, dataKey, color, yAxisLabel, aggregation="sum", t { value: "12h", label: "Last 12 Hours" }, { value: "1h", label: "Last Hour" }, ].filter((range) => { - if(!rawData) - return true; - else { - // if the range extends beyond the available data, don't show it - const earliestDate = new Date(rawData[0]?.date); - if(range.value === "all") - return true; - else { - const start = range.value === "1m" ? subMonths(new Date(), 1) : - range.value === "7d" ? subDays(new Date(), 7) : - range.value === "24h" ? subHours(new Date(), 24) : - range.value === "12h" ? subHours(new Date(), 12) : - range.value === "1h" ? subHours(new Date(), 1) : - new Date(); // Default case, shouldn't occur - return start >= earliestDate; - } - } + if(!rawData) return true; + const earliestDate = new Date(rawData[0]?.date); + if(range.value === "all") return true; + const start = range.value === "1m" ? subMonths(new Date(), 1) : + range.value === "7d" ? subDays(new Date(), 7) : + range.value === "24h" ? subHours(new Date(), 24) : + range.value === "12h" ? subHours(new Date(), 12) : + range.value === "1h" ? subHours(new Date(), 1) : + new Date(); + return start >= earliestDate; }), [rawData]); useEffect(() => { @@ -68,24 +56,12 @@ function MetricChart({ rawData, dataKey, color, yAxisLabel, aggregation="sum", t let start = rawData[0]?.date; switch (selectedTimeRange) { - case "1m": - start = subMonths(latestNow, 1); - break; - case "7d": - start = subDays(latestNow, 7); - break; - case "24h": - start = subHours(latestNow, 24); - break; - case "12h": - start = subHours(latestNow, 12); - break; - case "1h": - start = subHours(latestNow, 1); - break; - default: - // "all" - use the earliest date in rawData - break; + case "1m": start = subMonths(latestNow, 1); break; + case "7d": start = subDays(latestNow, 7); break; + case "24h": start = subHours(latestNow, 24); break; + case "12h": start = subHours(latestNow, 12); break; + case "1h": start = subHours(latestNow, 1); break; + default: break; } setDateRange({ @@ -95,19 +71,16 @@ function MetricChart({ rawData, dataKey, color, yAxisLabel, aggregation="sum", t } }, [rawData, selectedTimeRange]); - // Determine aggregation based on zoom const aggregatedData = useMemo(() => { if (!rawData?.length || !dateRange) return []; - const zoomStart = dateRange.start; + const zoomStart = dateRange.start; const zoomEnd = dateRange.end; const daysDiff = differenceInDays(zoomEnd, zoomStart); const hoursDiff = differenceInHours(zoomEnd, zoomStart); - const minutesDiff = differenceInMinutes(zoomEnd, zoomStart); - let aggregationInterval; - let aggregationFunction; + let aggregationInterval, aggregationFunction; if (daysDiff > 30) { aggregationInterval = eachDayOfInterval; @@ -157,7 +130,6 @@ function MetricChart({ rawData, dataKey, color, yAxisLabel, aggregation="sum", t ); }, [rawData, dateRange, dataKey, aggregation]); - // Memoize formatting functions const formatXAxis = useCallback( (tickItem) => { const date = new Date(tickItem); @@ -171,19 +143,17 @@ function MetricChart({ rawData, dataKey, color, yAxisLabel, aggregation="sum", t const formatTooltip = useCallback( (value) => { - return [`${value} ${yAxisLabel || ''}`, title]; + return [`${value} ${yAxisLabel || ''}`, '']; }, - [yAxisLabel, title] + [yAxisLabel] ); - const handleZoom = (domain) => { - }; - return ( -
-
+
+
+

{title}

setSelectedTimeRange(e.target.value)} > @@ -164,11 +164,11 @@ function MetricChart({ rawData, dataKey, color, yAxisLabel, aggregation="sum", t ))}
-
+
@@ -179,18 +179,18 @@ function MetricChart({ rawData, dataKey, color, yAxisLabel, aggregation="sum", t @@ -199,7 +199,7 @@ function MetricChart({ rawData, dataKey, color, yAxisLabel, aggregation="sum", t backgroundColor: "#2D3748", border: "1px solid #4A5568", color: "#E2E8F0", - fontSize: 12, + fontSize: 10, }} labelFormatter={(label) => format(new Date(label), "PPpp")} formatter={formatTooltip} @@ -213,7 +213,7 @@ function MetricChart({ rawData, dataKey, color, yAxisLabel, aggregation="sum", t /> { if (!aggregateData || !sidebarMetrics) return null; @@ -14,21 +16,45 @@ const InvocationsAnalyticsSidePanel = ({ aggregateData, sidebarMetrics }) => { initial={{ opacity: 0, y: 20 }} animate={{ opacity: 1, y: 0 }} transition={{ duration: 0.3 }} - className="space-y-6" + className="space-y-2 text-sm" > -
-

Overview

-
- - - - - - +
+

Overview

+
+
+ + Total Invocations: +
+
{sidebarMetrics.totalInvocations}
+
+ + Avg. Latency: +
+
{sidebarMetrics.avgLatency?.toFixed(2)}ms
+
+ + Total Tokens: +
+
{sidebarMetrics.totalTokens}
+
+ + Unique LMPs: +
+
{sidebarMetrics.uniqueLMPs}
+
+ + Success Rate: +
+
{sidebarMetrics.successRate.toFixed(2)}%
+
+ + Avg Tokens/Invocation: +
+
{(sidebarMetrics.totalTokens / sidebarMetrics.totalInvocations)?.toFixed(2)}
- { yAxisLabel="Count" /> - { yAxisLabel="ms" /> - { yAxisLabel="Tokens" /> -
-

Top 5 LMPs

-
    - {sidebarMetrics.topLMPs.map(([lmp, count], index) => ( + {/*
    +

    Top 5 LMPs

    +
      + {sidebarMetrics.topLMPs.map(([lmpName, count], index) => ( - - {index + 1}. - {lmp} - - {count} invocations + + + +
      + {count} invocations +
      +
      +
      +
      +
      +
      ))}
    -
    +
*/} ); diff --git a/ell-studio/src/styles/globals.css b/ell-studio/src/styles/globals.css index a1cebeff..3a4fdaca 100644 --- a/ell-studio/src/styles/globals.css +++ b/ell-studio/src/styles/globals.css @@ -104,4 +104,5 @@ to { stroke-dashoffset: -10; } -} \ No newline at end of file +} + From 0832cdc40b0bdd9cec4d4b0663a9c659a139f9c4 Mon Sep 17 00:00:00 2001 From: William Guss Date: Wed, 14 Aug 2024 11:47:38 -0700 Subject: [PATCH 9/9] Update README.md --- README.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index c165a6b0..62fd657d 100644 --- a/README.md +++ b/README.md @@ -1,13 +1,13 @@ # `ell` [WIP, unreleased, experimental] -[![](https://dcbadge.limes.pink/api/server/Yqyga6Qr?style=flat)](https://discord.gg/Yqyga6Qr) -[![](https://dcbadge.limes.pink/api/server/Yqyga6Qr?style=flat)](https://discord.gg/Yqyga6Qr) -[![](https://dcbadge.limes.pink/api/server/Yqyga6Qr?style=flat)](https://discord.gg/Yqyga6Qr) -[![](https://dcbadge.limes.pink/api/server/Yqyga6Qr?style=flat)](https://discord.gg/Yqyga6Qr) +[![](https://dcbadge.limes.pink/api/server/vWntgU52Xb?style=flat)](https://discord.gg/vWntgU52Xb) +[![](https://dcbadge.limes.pink/api/server/vWntgU52Xb?style=flat)](https://discord.gg/vWntgU52Xb) +[![](https://dcbadge.limes.pink/api/server/vWntgU52Xb?style=flat)](https://discord.gg/vWntgU52Xb) +[![](https://dcbadge.limes.pink/api/server/vWntgU52Xb?style=flat)](https://discord.gg/vWntgU52Xb) > **IMPORTANT**: This repository is currently pre-v1.0, highly experimental, and not yet packaged for general use. It contains numerous bugs, and the schemas are subject to frequent changes. While we welcome contributions, please be aware that submitting pull requests at this stage is at your own discretion, as the codebase is rapidly evolving. -> **[JOIN THE DISCORD](https://discord.gg/Yqyga6Qr)** We are developing this in public and I want all hands on deck regarding design decisions! Join us at [https://discord.gg/Yqyga6Qr](https://discord.gg/Yqyga6Qr) +> **[JOIN THE DISCORD](https://discord.gg/vWntgU52Xb)** We are developing this in public and I want all hands on deck regarding design decisions! Join us at [https://discord.gg/vWntgU52Xb](https://discord.gg/vWntgU52Xb) # What is `ell`?