mirror of
https://github.com/MadcowD/ell.git
synced 2024-09-22 16:14:36 +03:00
Working invocaiton panels
This commit is contained in:
@@ -107,7 +107,6 @@ You can then visualize your promtps by visiting the frontend on `http://localhos
|
||||
|
||||
## Todos
|
||||
|
||||
|
||||
### Bugs
|
||||
|
||||
- [ ] Fix weird rehashing issue of the main prompt whenever subprompt changes? Or just make commits more of a background deal.
|
||||
|
||||
@@ -16,7 +16,7 @@ function App() {
|
||||
<div className="flex min-h-screen max-h-screen bg-gray-900 text-gray-100">
|
||||
<Sidebar />
|
||||
<div className="flex-1 flex flex-col max-h-screen overflow-hidden">
|
||||
<main className="flex-1 max-h-screen overflow-auto">
|
||||
<main className="flex-1 max-h-screen overflow-auto hide-scrollbar">
|
||||
<Routes>
|
||||
<Route path="/" element={<Home />} />
|
||||
<Route path="/lmp/:name/:id?" element={<LMP />} />
|
||||
|
||||
78
ell-studio/src/components/CodeSection.js
Normal file
78
ell-studio/src/components/CodeSection.js
Normal file
@@ -0,0 +1,78 @@
|
||||
import React, { useState, useEffect, useRef } from 'react';
|
||||
import { Prism as SyntaxHighlighter } from 'react-syntax-highlighter';
|
||||
import { atomDark } from 'react-syntax-highlighter/dist/esm/styles/prism';
|
||||
import { FiChevronDown, FiChevronRight, FiMaximize2, FiMinimize2 } from 'react-icons/fi';
|
||||
import '../styles/SourceCodeView.css';
|
||||
|
||||
export function CodeSection({
|
||||
title,
|
||||
code,
|
||||
showCode,
|
||||
setShowCode,
|
||||
lines,
|
||||
startingLineNumber = 1,
|
||||
isDependent = false,
|
||||
collapsedHeight = '150px' // New prop with default value
|
||||
}) {
|
||||
const [isHovering, setIsHovering] = useState(false);
|
||||
const codeRef = useRef(null);
|
||||
|
||||
useEffect(() => {
|
||||
if (codeRef.current) {
|
||||
codeRef.current.style.maxHeight = showCode ? 'none' : collapsedHeight;
|
||||
}
|
||||
}, [showCode, collapsedHeight]);
|
||||
|
||||
return (
|
||||
<div className="code-section mb-4">
|
||||
<button
|
||||
onClick={() => setShowCode(!showCode)}
|
||||
className="section-header flex items-center justify-between w-full text-sm text-gray-300 hover:text-white py-2 px-4 rounded-t-md bg-gray-800 hover:bg-gray-700 transition-colors duration-200"
|
||||
>
|
||||
<span className="flex items-center">
|
||||
{showCode ? <FiChevronDown className="mr-2" /> : <FiChevronRight className="mr-2" />}
|
||||
{title}
|
||||
</span>
|
||||
<span className="text-xs text-gray-400">
|
||||
{lines} lines
|
||||
</span>
|
||||
</button>
|
||||
<div
|
||||
className={`code-container ${showCode ? 'expanded' : ''}`}
|
||||
onMouseEnter={() => setIsHovering(true)}
|
||||
onMouseLeave={() => setIsHovering(false)}
|
||||
ref={codeRef}
|
||||
onClick={() => !showCode && setShowCode(true)}
|
||||
>
|
||||
<SyntaxHighlighter
|
||||
language="python"
|
||||
style={atomDark}
|
||||
showLineNumbers={true}
|
||||
startingLineNumber={startingLineNumber}
|
||||
customStyle={{
|
||||
margin: 0,
|
||||
padding: '1em',
|
||||
borderRadius: '0 0 6px 6px',
|
||||
}}
|
||||
>
|
||||
{code}
|
||||
</SyntaxHighlighter>
|
||||
{!showCode && (
|
||||
<div className="gradient-overlay">
|
||||
{isHovering && (
|
||||
<button
|
||||
className="show-more-button"
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
setShowCode(true);
|
||||
} }
|
||||
>
|
||||
Show more ({lines} lines)
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -4,6 +4,8 @@ import { atomDark } from 'react-syntax-highlighter/dist/esm/styles/prism';
|
||||
import { FiChevronDown, FiChevronRight, FiMaximize2, FiMinimize2 } from 'react-icons/fi';
|
||||
import '../styles/SourceCodeView.css';
|
||||
|
||||
import { CodeSection } from './CodeSection';
|
||||
|
||||
const SourceCodeView = ({ dependencies, source, uses, showDependenciesInitial = false }) => {
|
||||
const [showDependencies, setShowDependencies] = useState(showDependenciesInitial);
|
||||
const [showSource, setShowSource] = useState(true);
|
||||
@@ -23,70 +25,6 @@ const SourceCodeView = ({ dependencies, source, uses, showDependenciesInitial =
|
||||
if(showDependenciesInitial) setShowDependencies(showDependenciesInitial);
|
||||
}, [showDependenciesInitial]);
|
||||
|
||||
const CodeSection = ({ title, code, showCode, setShowCode, lines, startingLineNumber = 1, isDependent = false }) => {
|
||||
const [isHovering, setIsHovering] = useState(false);
|
||||
const codeRef = useRef(null);
|
||||
|
||||
useEffect(() => {
|
||||
if (codeRef.current) {
|
||||
codeRef.current.style.maxHeight = showCode ? 'none' : '150px';
|
||||
}
|
||||
}, [showCode]);
|
||||
|
||||
return (
|
||||
<div className="code-section mb-4">
|
||||
<button
|
||||
onClick={() => setShowCode(!showCode)}
|
||||
className="section-header flex items-center justify-between w-full text-sm text-gray-300 hover:text-white py-2 px-4 rounded-t-md bg-gray-800 hover:bg-gray-700 transition-colors duration-200"
|
||||
>
|
||||
<span className="flex items-center">
|
||||
{showCode ? <FiChevronDown className="mr-2" /> : <FiChevronRight className="mr-2" />}
|
||||
{title}
|
||||
</span>
|
||||
<span className="text-xs text-gray-400">
|
||||
{lines} lines
|
||||
{isDependent && `, ${dependentLMPs} LMPs`}
|
||||
</span>
|
||||
</button>
|
||||
<div
|
||||
className={`code-container ${showCode ? 'expanded' : ''}`}
|
||||
onMouseEnter={() => setIsHovering(true)}
|
||||
onMouseLeave={() => setIsHovering(false)}
|
||||
ref={codeRef}
|
||||
onClick={() => !showCode && setShowCode(true)}
|
||||
>
|
||||
<SyntaxHighlighter
|
||||
language="python"
|
||||
style={atomDark}
|
||||
showLineNumbers={true}
|
||||
startingLineNumber={startingLineNumber}
|
||||
customStyle={{
|
||||
margin: 0,
|
||||
padding: '1em',
|
||||
borderRadius: '0 0 6px 6px',
|
||||
}}
|
||||
>
|
||||
{code}
|
||||
</SyntaxHighlighter>
|
||||
{!showCode && (
|
||||
<div className="gradient-overlay">
|
||||
{isHovering && (
|
||||
<button
|
||||
className="show-more-button"
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
setShowCode(true);
|
||||
}}
|
||||
>
|
||||
Show more ({lines} lines)
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="source-code-container">
|
||||
|
||||
@@ -1,153 +1,176 @@
|
||||
import React, { useState, useRef, useEffect } from 'react';
|
||||
import { FiLink, FiCopy, FiChevronDown, FiChevronRight } from 'react-icons/fi';
|
||||
import React, { useState, useRef, useEffect, useMemo } from "react";
|
||||
import { FiLink, FiCopy, FiChevronDown, FiChevronRight } from "react-icons/fi";
|
||||
import { lstrCleanStringify } from './lstrCleanStringify';
|
||||
|
||||
const TraceDetailsSidebar = ({ trace, onClose }) => {
|
||||
const [activeTab, setActiveTab] = useState('Run');
|
||||
import { CodeSection } from './CodeSection';
|
||||
|
||||
const InvocationDetailsSidebar = ({ invocation, onClose }) => {
|
||||
const [activeTab, setActiveTab] = useState("Details");
|
||||
const [inputExpanded, setInputExpanded] = useState(true);
|
||||
const [outputExpanded, setOutputExpanded] = useState(true);
|
||||
const [sidebarWidth, setSidebarWidth] = useState(600);
|
||||
const [sidebarWidth, setSidebarWidth] = useState(document.body.clientWidth * 0.75);
|
||||
const resizeRef = useRef(null);
|
||||
|
||||
const argsLines = useMemo(() => {
|
||||
return lstrCleanStringify(invocation.args, 1);
|
||||
}, [invocation.args]);
|
||||
|
||||
const kwargsLines = useMemo(() => {
|
||||
return lstrCleanStringify(invocation.kwargs, 1);
|
||||
}, [invocation.kwargs]);
|
||||
|
||||
const hasKwargs = useMemo(() => {
|
||||
return Object.keys(invocation.kwargs).length > 0;
|
||||
}, [invocation.kwargs]);
|
||||
|
||||
useEffect(() => {
|
||||
if (argsLines.split('\n').length > 10 || (hasKwargs && kwargsLines.split('\n').length > 10)) {
|
||||
setInputExpanded(false);
|
||||
}
|
||||
}, [argsLines, kwargsLines, hasKwargs]);
|
||||
|
||||
useEffect(() => {
|
||||
const handleMouseMove = (e) => {
|
||||
if (resizeRef.current) {
|
||||
const newWidth = document.body.clientWidth - e.clientX;
|
||||
setSidebarWidth(Math.max(400, newWidth));
|
||||
setSidebarWidth(Math.max(800, newWidth));
|
||||
}
|
||||
};
|
||||
|
||||
const handleMouseUp = () => {
|
||||
resizeRef.current = null;
|
||||
document.removeEventListener('mousemove', handleMouseMove);
|
||||
document.removeEventListener('mouseup', handleMouseUp);
|
||||
document.removeEventListener("mousemove", handleMouseMove);
|
||||
document.removeEventListener("mouseup", handleMouseUp);
|
||||
};
|
||||
|
||||
const handleMouseDown = (e) => {
|
||||
resizeRef.current = e.target;
|
||||
document.addEventListener('mousemove', handleMouseMove);
|
||||
document.addEventListener('mouseup', handleMouseUp);
|
||||
document.addEventListener("mousemove", handleMouseMove);
|
||||
document.addEventListener("mouseup", handleMouseUp);
|
||||
};
|
||||
|
||||
const resizer = document.getElementById('sidebar-resizer');
|
||||
resizer.addEventListener('mousedown', handleMouseDown);
|
||||
const resizer = document.getElementById("sidebar-resizer");
|
||||
resizer.addEventListener("mousedown", handleMouseDown);
|
||||
|
||||
return () => {
|
||||
resizer.removeEventListener('mousedown', handleMouseDown);
|
||||
resizer.removeEventListener("mousedown", handleMouseDown);
|
||||
};
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<>
|
||||
<div id="sidebar-resizer" className="w-1 bg-gray-600 cursor-col-resize" />
|
||||
<div className="bg-[#0d1117] border-l border-gray-800 overflow-y-auto flex flex-col" style={{ width: sidebarWidth }}>
|
||||
<div
|
||||
className="bg-[#0d1117] border-l border-gray-800 overflow-y-auto flex flex-col hide-scrollbar"
|
||||
style={{ width: sidebarWidth }}
|
||||
>
|
||||
<div className="flex items-center justify-between p-4 border-b border-gray-800">
|
||||
<div className="flex items-center space-x-2">
|
||||
<FiLink className="text-blue-400" />
|
||||
<h2 className="text-xl font-semibold text-blue-400">{trace.name}</h2>
|
||||
<h2 className="text-xl font-semibold text-blue-400">
|
||||
{invocation.lmp.name}
|
||||
</h2>
|
||||
</div>
|
||||
<div className="flex items-center space-x-4">
|
||||
<button className="text-gray-400 hover:text-white">
|
||||
<FiCopy /> Run ID
|
||||
<FiCopy /> Invocation ID
|
||||
</button>
|
||||
<button className="text-gray-400 hover:text-white">
|
||||
<FiCopy /> Trace ID
|
||||
</button>
|
||||
<button onClick={onClose} className="text-gray-400 hover:text-white">
|
||||
✕
|
||||
</button>
|
||||
</div>
|
||||
</div>{" "}
|
||||
<button onClick={onClose} className="text-gray-400 hover:text-white">
|
||||
✕
|
||||
</button>
|
||||
</div>
|
||||
<div className="flex border-b border-gray-800">
|
||||
<button
|
||||
className={`px-4 py-2 ${activeTab === 'Run' ? 'text-blue-400 border-b-2 border-blue-400' : 'text-gray-400'}`}
|
||||
onClick={() => setActiveTab('Run')}
|
||||
className={`px-4 py-2 ${
|
||||
activeTab === "Details"
|
||||
? "text-blue-400 border-b-2 border-blue-400"
|
||||
: "text-gray-400"
|
||||
}`}
|
||||
onClick={() => setActiveTab("Details")}
|
||||
>
|
||||
Run
|
||||
Details
|
||||
</button>
|
||||
<button
|
||||
className={`px-4 py-2 ${activeTab === 'Feedback' ? 'text-blue-400 border-b-2 border-blue-400' : 'text-gray-400'}`}
|
||||
onClick={() => setActiveTab('Feedback')}
|
||||
className={`px-4 py-2 ${
|
||||
activeTab === "Results"
|
||||
? "text-blue-400 border-b-2 border-blue-400"
|
||||
: "text-gray-400"
|
||||
}`}
|
||||
onClick={() => setActiveTab("Results")}
|
||||
>
|
||||
Feedback
|
||||
</button>
|
||||
<button
|
||||
className={`px-4 py-2 ${activeTab === 'Metadata' ? 'text-blue-400 border-b-2 border-blue-400' : 'text-gray-400'}`}
|
||||
onClick={() => setActiveTab('Metadata')}
|
||||
>
|
||||
Metadata
|
||||
Results
|
||||
</button>
|
||||
</div>
|
||||
<div className="flex flex-grow">
|
||||
<div className="flex-grow p-4 overflow-y-auto">
|
||||
<div className="flex justify-between items-center mb-4">
|
||||
<button
|
||||
className="flex items-center text-gray-300"
|
||||
onClick={() => setInputExpanded(!inputExpanded)}
|
||||
>
|
||||
<span className="mr-2">Input</span>
|
||||
{inputExpanded ? <FiChevronDown /> : <FiChevronRight />}
|
||||
</button>
|
||||
<span className="text-gray-500">YAML</span>
|
||||
</div>
|
||||
{inputExpanded && (
|
||||
<pre className="bg-[#161b22] p-4 rounded text-sm text-gray-300 mb-4">
|
||||
<code>
|
||||
{`input: What is a document loader?
|
||||
chat_history: []`}
|
||||
</code>
|
||||
</pre>
|
||||
)}
|
||||
<div className="flex justify-between items-center mb-4">
|
||||
<button
|
||||
className="flex items-center text-gray-300"
|
||||
onClick={() => setOutputExpanded(!outputExpanded)}
|
||||
>
|
||||
<span className="mr-2">Output</span>
|
||||
{outputExpanded ? <FiChevronDown /> : <FiChevronRight />}
|
||||
</button>
|
||||
</div>
|
||||
{outputExpanded && (
|
||||
<pre className="bg-[#161b22] p-4 rounded text-sm text-gray-300">
|
||||
<code>
|
||||
{trace.output}
|
||||
</code>
|
||||
</pre>
|
||||
<div className="flex flex-grow source-code-container">
|
||||
<div className="flex-grow p-4 overflow-y-auto w-[400px] hide-scrollbar">
|
||||
<CodeSection
|
||||
title="Args"
|
||||
code={argsLines}
|
||||
showCode={inputExpanded}
|
||||
setShowCode={setInputExpanded}
|
||||
collapsedHeight={'300px'}
|
||||
lines={argsLines.split('\n').length}
|
||||
language="json"
|
||||
/>
|
||||
|
||||
{hasKwargs && (
|
||||
<CodeSection
|
||||
title="Kwargs"
|
||||
code={kwargsLines}
|
||||
showCode={inputExpanded}
|
||||
setShowCode={setInputExpanded}
|
||||
collapsedHeight={'300px'}
|
||||
lines={kwargsLines.split('\n').length}
|
||||
language="json"
|
||||
/>
|
||||
)}
|
||||
|
||||
{
|
||||
invocation.results.map((result, index) => (
|
||||
<CodeSection
|
||||
key={index}
|
||||
title={`Output ${index + 1}`}
|
||||
code={result.content}
|
||||
showCode={outputExpanded}
|
||||
setShowCode={setOutputExpanded}
|
||||
lines={result.content.split('\n').length}
|
||||
language="plaintext"
|
||||
/>
|
||||
))
|
||||
}
|
||||
</div>
|
||||
<div className="w-64 bg-[#0d1117] p-4 border-l border-gray-800 text-sm">
|
||||
|
||||
<div className="w-64 bg-[#0d1117] p-4 border-l border-gray-800 text-sm hide-scrollbar">
|
||||
<div className="mb-2">
|
||||
<p className="text-gray-500">START TIME</p>
|
||||
<p className="text-gray-300">{trace.startTime}</p>
|
||||
</div>
|
||||
<div className="mb-2">
|
||||
<p className="text-gray-500">END TIME</p>
|
||||
<p className="text-gray-300">{trace.endTime}</p>
|
||||
</div>
|
||||
<div className="mb-2">
|
||||
<p className="text-gray-500">TIME TO FIRST TOKEN</p>
|
||||
<p className="text-gray-300">{trace.timeToFirstToken}</p>
|
||||
</div>
|
||||
<div className="mb-2">
|
||||
<p className="text-gray-500">STATUS</p>
|
||||
<p className="text-green-400 flex items-center">
|
||||
<span className="mr-1">●</span> Success
|
||||
</p>
|
||||
</div>
|
||||
<div className="mb-2">
|
||||
<p className="text-gray-500">TOTAL TOKENS</p>
|
||||
<p className="text-gray-300">{trace.tokens} tokens</p>
|
||||
<p className="text-gray-500">CREATED AT</p>
|
||||
<p className="text-gray-300">{new Date(invocation.created_at).toTimeString()}</p>
|
||||
</div>
|
||||
<div className="mb-2">
|
||||
<p className="text-gray-500">LATENCY</p>
|
||||
<p className="text-red-400">{trace.latency}</p>
|
||||
{/* <p className="text-gray-300">{formatDuration(invocation.latency_ms)}</p> */}
|
||||
</div>
|
||||
<div className="mb-2">
|
||||
<p className="text-gray-500">TYPE</p>
|
||||
<p className="text-gray-300 bg-blue-900 inline-block px-2 py-0.5 rounded">Chain</p>
|
||||
<p className="text-gray-500">PROMPT TOKENS</p>
|
||||
<p className="text-gray-300">
|
||||
{invocation.prompt_tokens || "N/A"}
|
||||
</p>
|
||||
</div>
|
||||
<div className="mb-2">
|
||||
<p className="text-gray-500">COMPLETION TOKENS</p>
|
||||
<p className="text-gray-300">
|
||||
{invocation.completion_tokens || "N/A"}
|
||||
</p>
|
||||
</div>
|
||||
<div className="mb-2">
|
||||
<p className="text-gray-500">LMP TYPE</p>
|
||||
<p className="text-gray-300 bg-blue-900 inline-block px-2 py-0.5 rounded">
|
||||
{invocation.lmp.is_lm ? "LM" : "LMP"}
|
||||
</p>
|
||||
</div>
|
||||
<div>
|
||||
<p className="text-gray-500">TAGS</p>
|
||||
<p className="text-gray-300 bg-gray-700 inline-block px-2 py-0.5 rounded">{trace.tags[0]}</p>
|
||||
<p className="text-gray-500">DEPENDENCIES</p>
|
||||
<p className="text-gray-300">{invocation.lmp.dependencies}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -156,4 +179,4 @@ chat_history: []`}
|
||||
);
|
||||
};
|
||||
|
||||
export default TraceDetailsSidebar;
|
||||
export default InvocationDetailsSidebar;
|
||||
@@ -4,17 +4,7 @@ import React, { useMemo } from 'react';
|
||||
import { Card } from './Card';
|
||||
import { getTimeAgo } from '../utils/lmpUtils';
|
||||
import VersionBadge from './VersionBadge';
|
||||
|
||||
const lstrCleanStringify = (obj_containing_lstrs) => {
|
||||
return JSON.stringify(obj_containing_lstrs, (key, value) => {
|
||||
if (value && value.__lstr === true) {
|
||||
return value.content;
|
||||
}
|
||||
return value;
|
||||
}, 2);
|
||||
};
|
||||
|
||||
|
||||
import { lstrCleanStringify } from './lstrCleanStringify';
|
||||
|
||||
const TracesRunsPane = ({ invocations, onSelectTrace }) => {
|
||||
const traces = useMemo(() => {
|
||||
@@ -30,6 +20,7 @@ const TracesRunsPane = ({ invocations, onSelectTrace }) => {
|
||||
}));
|
||||
}, [invocations]);
|
||||
|
||||
|
||||
const schema = {
|
||||
columns: [
|
||||
{
|
||||
|
||||
8
ell-studio/src/components/lstrCleanStringify.js
Normal file
8
ell-studio/src/components/lstrCleanStringify.js
Normal file
@@ -0,0 +1,8 @@
|
||||
export const lstrCleanStringify = (obj_containing_lstrs, indentLevel = 2) => {
|
||||
return JSON.stringify(obj_containing_lstrs, (key, value) => {
|
||||
if (value && value.__lstr === true) {
|
||||
return value.content;
|
||||
}
|
||||
return value;
|
||||
}, indentLevel);
|
||||
};
|
||||
@@ -10,6 +10,7 @@ import VersionHistoryPane from '../components/VersionHistoryPane';
|
||||
import LMPDetailsSidePanel from '../components/LMPDetailsSidePanel';
|
||||
import toast, { Toaster } from 'react-hot-toast';
|
||||
import { Link } from 'react-router-dom';
|
||||
import TraceDetailsSidebar from '../components/TraceDetailsSidebar';
|
||||
|
||||
function LMP() {
|
||||
const { name, id } = useParams();
|
||||
@@ -19,6 +20,7 @@ function LMP() {
|
||||
const [uses, setUses] = useState([]);
|
||||
const { darkMode } = useTheme();
|
||||
const [activeTab, setActiveTab] = useState('runs');
|
||||
const [selectedTrace, setSelectedTrace] = useState(null);
|
||||
|
||||
const API_BASE_URL = "http://localhost:8080";
|
||||
|
||||
@@ -117,7 +119,7 @@ function LMP() {
|
||||
</header>
|
||||
|
||||
<div className="flex-grow flex overflow-hidden">
|
||||
<main className="flex-grow p-6 overflow-y-auto">
|
||||
<main className="flex-grow p-6 overflow-y-auto hide-scrollbar">
|
||||
<div className="mb-6 bg-[#1c1f26] rounded-lg p-4">
|
||||
<div className="flex justify-between items-center mb-4">
|
||||
<h2 className="text-lg font-semibold">Language Model Program</h2>
|
||||
@@ -185,7 +187,7 @@ function LMP() {
|
||||
<TracesRunsPane
|
||||
invocations={invocations}
|
||||
producingLmp={lmp}
|
||||
onSelectTrace={(trace) => console.log('Selected trace:', trace)}
|
||||
onSelectTrace={(trace) => setSelectedTrace(trace)}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
@@ -200,6 +202,12 @@ function LMP() {
|
||||
versionHistory={versionHistory}
|
||||
onSeeAllClick={handleSeeAllClick}
|
||||
/>
|
||||
{selectedTrace && (
|
||||
<TraceDetailsSidebar
|
||||
invocation={selectedTrace}
|
||||
onClose={() => setSelectedTrace(null)}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -40,7 +40,7 @@ const Traces = () => {
|
||||
|
||||
return (
|
||||
<div className="flex bg-[#0d1117] text-gray-300 h-screen overflow-hidden">
|
||||
<div className="flex-grow p-6 overflow-y-auto">
|
||||
<div className="flex-grow p-6 overflow-y-auto hide-scrollbar">
|
||||
<div className="flex items-center mb-6">
|
||||
<div className="flex items-center space-x-2 text-sm text-gray-400">
|
||||
<span>Personal</span>
|
||||
@@ -112,7 +112,7 @@ const Traces = () => {
|
||||
</div>
|
||||
{selectedTrace && (
|
||||
<TraceDetailsSidebar
|
||||
trace={selectedTrace}
|
||||
invocation={selectedTrace}
|
||||
onClose={() => setSelectedTrace(null)}
|
||||
/>
|
||||
)}
|
||||
|
||||
@@ -1,5 +1,10 @@
|
||||
.source-code-wrapper {
|
||||
height: 70vh;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.source-code-container {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
max-width: 100%;
|
||||
overflow-x: auto;
|
||||
}
|
||||
|
||||
@@ -8,4 +8,13 @@ body,
|
||||
|
||||
body {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.hide-scrollbar {
|
||||
scrollbar-width: none; /* Firefox */
|
||||
-ms-overflow-style: none; /* Internet Explorer and Edge */
|
||||
}
|
||||
|
||||
.hide-scrollbar::-webkit-scrollbar {
|
||||
display: none; /* Chrome, Safari, and Opera */
|
||||
}
|
||||
@@ -75,9 +75,7 @@ export const fetchTraces = async (lmps) => {
|
||||
|
||||
export function getTimeAgo(date) {
|
||||
const now = new Date();
|
||||
console.log(date)
|
||||
const secondsPast = (now.getTime() - date.getTime()) / 1000;
|
||||
console.log(now, date);
|
||||
if (secondsPast < 60) {
|
||||
return `${Math.round(secondsPast)} seconds ago`;
|
||||
}
|
||||
|
||||
4
setup.py
4
setup.py
@@ -6,10 +6,6 @@ from setuptools import setup, find_packages
|
||||
from setuptools.command.develop import develop
|
||||
from setuptools.command.install import install
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
class NPMInstall(object):
|
||||
def run_npm_install(self):
|
||||
print("Running npm install")
|
||||
|
||||
@@ -26,16 +26,8 @@ def main():
|
||||
async def serve_react_app(full_path: str):
|
||||
return FileResponse(os.path.join(static_dir, "index.html"))
|
||||
|
||||
if args.dev:
|
||||
# In development mode, use watchfiles for auto-reloading
|
||||
run_process(
|
||||
os.path.dirname(__file__),
|
||||
target=lambda: uvicorn.run(app, host=args.host, port=args.port, reload=True),
|
||||
watch_filter=lambda change, path: path.endswith(".py")
|
||||
)
|
||||
else:
|
||||
# In production mode, run without auto-reloading
|
||||
uvicorn.run(app, host=args.host, port=args.port)
|
||||
# In production mode, run without auto-reloading
|
||||
uvicorn.run(app, host=args.host, port=args.port)
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user