Add observability for LLM topic context inclusion (#1038)

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: thomasnordquist <7721625+thomasnordquist@users.noreply.github.com>
Co-authored-by: Thomas Nordquist <thomasnordquist@users.noreply.github.com>
This commit is contained in:
Copilot
2026-01-30 20:53:29 +01:00
committed by GitHub
parent 080a773dbd
commit ed8a7f559e
194 changed files with 35234 additions and 4085 deletions

View File

@@ -1,9 +1,9 @@
import React, { memo } from 'react'
import { bindActionCreators } from 'redux'
import { chartActions } from '../../../actions'
import { ChartParameters } from '../../../reducers/Charts'
import { connect } from 'react-redux'
import { Menu, MenuItem } from '@mui/material'
import { chartActions } from '../../../actions'
import { ChartParameters } from '../../../reducers/Charts'
import { colors as createColors } from './colors'
function chartParametersForColor(chart: ChartParameters, color?: string) {
@@ -30,17 +30,24 @@ function ColorSettings(props: {
[props.chart]
)
const menuItems = React.useMemo(() => {
return colors.map(color => (
<MenuItem
style={{ minWidth: '8em', minHeight: '36px', backgroundColor: color, textAlign: 'center' }}
key={color}
onClick={() => setColor(color)}
>
{props.chart.color === color ? 'X' : ''}
</MenuItem>
))
}, [colors, props.chart])
const menuItems = React.useMemo(
() =>
colors.map(color => (
<MenuItem
style={{
minWidth: '8em',
minHeight: '36px',
backgroundColor: color,
textAlign: 'center',
}}
key={color}
onClick={() => setColor(color)}
>
{props.chart.color === color ? 'X' : ''}
</MenuItem>
)),
[colors, props.chart]
)
return (
<Menu anchorEl={props.anchorEl} open={props.open} onClose={props.close}>
@@ -57,12 +64,10 @@ function ColorSettings(props: {
)
}
const mapDispatchToProps = (dispatch: any) => {
return {
actions: {
chart: bindActionCreators(chartActions, dispatch),
},
}
}
const mapDispatchToProps = (dispatch: any) => ({
actions: {
chart: bindActionCreators(chartActions, dispatch),
},
})
export default connect(undefined, mapDispatchToProps)(memo(ColorSettings))

View File

@@ -1,10 +1,10 @@
import * as React from 'react'
import { AppState } from '../../../reducers'
import { bindActionCreators } from 'redux'
import { chartActions } from '../../../actions'
import { ChartParameters, PlotCurveTypes } from '../../../reducers/Charts'
import { connect } from 'react-redux'
import { Menu, MenuItem, Typography } from '@mui/material'
import { AppState } from '../../../reducers'
import { chartActions } from '../../../actions'
import { ChartParameters, PlotCurveTypes } from '../../../reducers/Charts'
function chartParametersForAction(chart: ChartParameters, action: string) {
return {
@@ -37,18 +37,20 @@ function InterpolationSettings(props: {
return callbacks
}, [curves])
const menuItems = React.useMemo(() => {
return curves.map(curve => (
<MenuItem
key={curve}
onClick={callbacks[curve]}
selected={props.chart.interpolation === curve}
data-menu-item={curve.replace(/_/g, ' ')}
>
<Typography variant="inherit">{curve.replace(/_/g, ' ')}</Typography>
</MenuItem>
))
}, [curves, props.chart])
const menuItems = React.useMemo(
() =>
curves.map(curve => (
<MenuItem
key={curve}
onClick={callbacks[curve]}
selected={props.chart.interpolation === curve}
data-menu-item={curve.replace(/_/g, ' ')}
>
<Typography variant="inherit">{curve.replace(/_/g, ' ')}</Typography>
</MenuItem>
)),
[curves, props.chart]
)
return (
<Menu anchorEl={props.anchorEl} open={props.open} onClose={props.close}>
@@ -57,12 +59,10 @@ function InterpolationSettings(props: {
)
}
const mapDispatchToProps = (dispatch: any) => {
return {
actions: {
chart: bindActionCreators(chartActions, dispatch),
},
}
}
const mapDispatchToProps = (dispatch: any) => ({
actions: {
chart: bindActionCreators(chartActions, dispatch),
},
})
export default connect(undefined, mapDispatchToProps)(InterpolationSettings)

View File

@@ -1,10 +1,10 @@
import * as React from 'react'
import ArrowUpward from '@mui/icons-material/ArrowUpward'
import { bindActionCreators } from 'redux'
import { chartActions } from '../../../actions'
import { ChartParameters } from '../../../reducers/Charts'
import { connect } from 'react-redux'
import { MenuItem, Typography, ListItemIcon } from '@mui/material'
import { chartActions } from '../../../actions'
import { ChartParameters } from '../../../reducers/Charts'
function MoveUp(props: { actions: { chart: typeof chartActions }; chart: ChartParameters; close: () => void }) {
const moveUp = React.useCallback(() => {
@@ -25,12 +25,10 @@ function MoveUp(props: { actions: { chart: typeof chartActions }; chart: ChartPa
)
}
const mapDispatchToProps = (dispatch: any) => {
return {
actions: {
chart: bindActionCreators(chartActions, dispatch),
},
}
}
const mapDispatchToProps = (dispatch: any) => ({
actions: {
chart: bindActionCreators(chartActions, dispatch),
},
})
export default connect(undefined, mapDispatchToProps)(MoveUp)

View File

@@ -1,8 +1,8 @@
import React, { useCallback, useState, ChangeEvent, MouseEvent, useRef, useEffect, useMemo } from 'react'
import { ChartParameters } from '../../../reducers/Charts'
import { Menu, TextField, Typography } from '@mui/material'
import { connect } from 'react-redux'
import { bindActionCreators } from 'redux'
import { ChartParameters } from '../../../reducers/Charts'
import { chartActions } from '../../../actions'
import { KeyCodes } from '../../../utils/KeyCodes'
@@ -50,7 +50,7 @@ function RangeSettings(props: Props) {
() => (
<Menu
style={{ textAlign: 'center' }}
keepMounted={true}
keepMounted
anchorEl={props.anchorEl}
open={props.open}
onClose={props.onClose}
@@ -62,7 +62,7 @@ function RangeSettings(props: Props) {
inputProps={{
ref: rangeFromRef,
}}
autoFocus={true}
autoFocus
style={{ marginTop: '0' }}
label="from"
value={rangeFrom}
@@ -87,13 +87,11 @@ function RangeSettings(props: Props) {
)
}
const mapDispatchToProps = (dispatch: any) => {
return {
actions: {
chart: bindActionCreators(chartActions, dispatch),
},
}
}
const mapDispatchToProps = (dispatch: any) => ({
actions: {
chart: bindActionCreators(chartActions, dispatch),
},
})
export default connect(undefined, mapDispatchToProps)(RangeSettings)

View File

@@ -1,7 +1,7 @@
import * as React from 'react'
import MoreVertIcon from '@mui/icons-material/Settings'
import ChartSettings from '.'
import CustomIconButton from '../../helper/CustomIconButton'
import MoreVertIcon from '@mui/icons-material/Settings'
import { ChartParameters } from '../../../reducers/Charts'
export function SettingsButton(props: {

View File

@@ -1,8 +1,8 @@
import React, { memo } from 'react'
import { ChartParameters } from '../../../reducers/Charts'
import { Menu, MenuItem, TextField, Typography } from '@mui/material'
import { connect } from 'react-redux'
import { bindActionCreators } from 'redux'
import { ChartParameters } from '../../../reducers/Charts'
import { chartActions } from '../../../actions'
function Size(props: {
@@ -39,12 +39,10 @@ function Size(props: {
)
}
const mapDispatchToProps = (dispatch: any) => {
return {
actions: {
chart: bindActionCreators(chartActions, dispatch),
},
}
}
const mapDispatchToProps = (dispatch: any) => ({
actions: {
chart: bindActionCreators(chartActions, dispatch),
},
})
export default connect(undefined, mapDispatchToProps)(memo(Size))

View File

@@ -1,9 +1,10 @@
import React, { ChangeEvent, MouseEvent, useCallback, useEffect, useMemo, useRef, useState } from 'react'
import { bindActionCreators } from 'redux'
import { Button, Menu, TextField, Typography } from '@mui/material'
import { connect } from 'react-redux'
import { chartActions } from '../../../actions'
import { ChartParameters } from '../../../reducers/Charts'
import { connect } from 'react-redux'
const parseDuration = require('parse-duration')
interface Props {
@@ -51,25 +52,23 @@ function TimeRangeSettings(props: Props) {
return (
<Menu
style={{ textAlign: 'center' }}
keepMounted={true}
keepMounted
anchorEl={props.anchorEl}
open={props.open}
onClose={props.onClose}
>
<Typography>Chart data within a time interval</Typography>
<div style={{ padding: '0 16px', width: '275px', textAlign: 'center' }}>
{ranges.map(r => {
return (
<Button
style={{ margin: '4px', textTransform: 'none' }}
variant="contained"
key={r}
onClick={createRangeHandler(r)}
>
{r}
</Button>
)
})}
{ranges.map(r => (
<Button
style={{ margin: '4px', textTransform: 'none' }}
variant="contained"
key={r}
onClick={createRangeHandler(r)}
>
{r}
</Button>
))}
</div>
<Typography style={{ fontSize: '0.75em' }}>
<i>Limited to 500 data points</i>
@@ -88,12 +87,10 @@ function TimeRangeSettings(props: Props) {
}, [value, props.open])
}
const mapDispatchToProps = (dispatch: any) => {
return {
actions: {
chart: bindActionCreators(chartActions, dispatch),
},
}
}
const mapDispatchToProps = (dispatch: any) => ({
actions: {
chart: bindActionCreators(chartActions, dispatch),
},
})
export default connect(undefined, mapDispatchToProps)(TimeRangeSettings)

View File

@@ -22,7 +22,7 @@ export function colors() {
function colorCompare(colorA: string, colorB: string) {
const a = colorToInt(colorA)
const b = colorToInt(colorB)
return Math.sqrt(Math.pow(a[0] - b[0], 2) + Math.pow(a[1] - b[1], 2) + Math.pow(a[2] - b[2], 2))
return Math.sqrt((a[0] - b[0]) ** 2 + (a[1] - b[1]) ** 2 + (a[2] - b[2]) ** 2)
}
const colors: Array<string> = [
brown,

View File

@@ -1,17 +1,17 @@
import BarChart from '@mui/icons-material/BarChart'
import Clear from '@mui/icons-material/Refresh'
import ColorLens from '@mui/icons-material/ColorLens'
import MultilineChart from '@mui/icons-material/MultilineChart'
import React, { memo } from 'react'
import Sort from '@mui/icons-material/Sort'
import { Menu, MenuItem, ListItemIcon, Typography } from '@mui/material'
import ColorSettings from './ColorSettings'
import InterpolationSettings from './InterpolationSettings'
import MoveUp from './MoveUp'
import MultilineChart from '@mui/icons-material/MultilineChart'
import RangeSettings from './RangeSettings'
import React, { memo } from 'react'
import Size from './Size'
import Sort from '@mui/icons-material/Sort'
import TimeRangeSettings from './TimeRangeSettings'
import { ChartParameters } from '../../../reducers/Charts'
import { Menu, MenuItem, ListItemIcon, Typography } from '@mui/material'
function ChartSettings(props: {
open: boolean
@@ -25,7 +25,7 @@ function ChartSettings(props: {
const [interpolationVisible, setInterpolationVisible] = React.useState(false)
const [sizeVisible, setSizeVisible] = React.useState(false)
const [colorVisible, setColorVisible] = React.useState(false)
const open = props.open
const { open } = props
const toggleRange = React.useCallback(() => {
if (open) {

View File

@@ -1,8 +1,8 @@
import * as React from 'react'
import { ChartParameters } from '../../reducers/Charts'
import { Typography } from '@mui/material'
import { withStyles } from '@mui/styles'
import { Theme } from '@mui/material/styles'
import { ChartParameters } from '../../reducers/Charts'
function ChartTitle(props: { parameters: ChartParameters; classes: any }) {
const { classes, parameters } = props
@@ -13,7 +13,7 @@ function ChartTitle(props: { parameters: ChartParameters; classes: any }) {
</Typography>
<br />
<Typography variant="caption" className={classes.topic}>
{parameters.dotPath ? parameters.topic : <span dangerouslySetInnerHTML={{ __html: '&nbsp;' }}></span>}
{parameters.dotPath ? parameters.topic : <span dangerouslySetInnerHTML={{ __html: '&nbsp;' }} />}
</Typography>
</div>
)
@@ -21,10 +21,10 @@ function ChartTitle(props: { parameters: ChartParameters; classes: any }) {
const styles = (theme: Theme) => ({
topic: {
wordBreak: 'break-all' as 'break-all',
whiteSpace: 'nowrap' as 'nowrap',
overflow: 'hidden' as 'hidden',
textOverflow: 'ellipsis' as 'ellipsis',
wordBreak: 'break-all' as const,
whiteSpace: 'nowrap' as const,
overflow: 'hidden' as const,
textOverflow: 'ellipsis' as const,
},
})

View File

@@ -1,5 +1,5 @@
import * as q from '../../../../backend/src/Model'
import React from 'react'
import * as q from '../../../../backend/src/Model'
import TopicChart from './TopicChart'
import { ChartParameters } from '../../reducers/Charts'
import { usePollingToFetchTreeNode } from '../helper/usePollingToFetchTreeNode'

View File

@@ -1,13 +1,14 @@
import React, { useState, useCallback, memo, useRef } from 'react'
import { bindActionCreators } from 'redux'
import { connect } from 'react-redux'
import { Paper } from '@mui/material'
import * as q from '../../../../backend/src/Model'
import ChartTitle from './ChartTitle'
import React, { useState, useCallback, memo, useRef } from 'react'
import TopicPlot from '../TopicPlot'
import { bindActionCreators } from 'redux'
import { ChartActions } from './ChartActions'
import { chartActions } from '../../actions'
import { ChartParameters } from '../../reducers/Charts'
import { connect } from 'react-redux'
import { Paper } from '@mui/material'
const throttle = require('lodash.throttle')
class ClearableMessageBuffer extends q.RingBuffer<q.Message> {
@@ -126,12 +127,10 @@ function TopicChart(props: Props) {
)
}
const mapDispatchToProps = (dispatch: any) => {
return {
actions: {
chart: bindActionCreators(chartActions, dispatch),
},
}
}
const mapDispatchToProps = (dispatch: any) => ({
actions: {
chart: bindActionCreators(chartActions, dispatch),
},
})
export default connect(undefined, mapDispatchToProps)(memo(TopicChart))

View File

@@ -1,16 +1,17 @@
import * as q from '../../../../backend/src/Model'
import * as React from 'react'
import ShowChart from '@mui/icons-material/ShowChart'
import { AppState } from '../../reducers'
import { bindActionCreators } from 'redux'
import { chartActions } from '../../actions'
import { ChartParameters } from '../../reducers/Charts'
import { ChartWithTreeNode } from './ChartWithTreeNode'
import { connect } from 'react-redux'
import { Grid, Typography } from '@mui/material'
import { withStyles } from '@mui/styles'
import { Theme } from '@mui/material/styles'
import { List } from 'immutable'
import * as q from '../../../../backend/src/Model'
import { AppState } from '../../reducers'
import { ChartWithTreeNode } from './ChartWithTreeNode'
import { ChartParameters } from '../../reducers/Charts'
import { chartActions } from '../../actions'
const { TransitionGroup, CSSTransition } = require('react-transition-group/esm')
interface Props {
@@ -26,11 +27,11 @@ interface Props {
function spacingForChartCount(count: number): 4 | 6 | 12 {
if (count >= 5) {
return 4
} else if (count >= 2) {
return 6
} else {
return 12
}
if (count >= 2) {
return 6
}
return 12
}
function mapWidth(width: 'big' | 'medium' | 'small' | undefined, calculatedSpacing: 4 | 6 | 12): 4 | 6 | 12 {
@@ -46,7 +47,6 @@ function mapWidth(width: 'big' | 'medium' | 'small' | undefined, calculatedSpaci
}
}
// Helper function to generate unique keys for charts
const getChartKey = (chart: ChartParameters) => `${chart.topic}-${chart.dotPath || ''}`
@@ -74,32 +74,27 @@ function ChartPanel(props: Props) {
React.useEffect(() => {
const currentKeys = new Set(props.charts.map(getChartKey).toArray())
const refsToDelete: string[] = []
nodeRefsMap.current.forEach((_, key) => {
if (!currentKeys.has(key)) {
refsToDelete.push(key)
}
})
refsToDelete.forEach(key => nodeRefsMap.current.delete(key))
}, [props.charts])
const charts = props.charts.map(chartParameters => {
const key = getChartKey(chartParameters)
// Get or create a ref for this specific chart
if (!nodeRefsMap.current.has(key)) {
nodeRefsMap.current.set(key, React.createRef<HTMLDivElement>())
}
const nodeRef = nodeRefsMap.current.get(key)!
return (
<CSSTransition
key={key}
timeout={{ enter: 500, exit: 500 }}
classNames="example"
nodeRef={nodeRef}
>
<CSSTransition key={key} timeout={{ enter: 500, exit: 500 }} classNames="example" nodeRef={nodeRef}>
<Grid item xs={mapWidth(chartParameters.width, spacing)} ref={nodeRef}>
<ChartWithTreeNode tree={props.tree} parameters={chartParameters} />
</Grid>
@@ -131,21 +126,17 @@ function NoCharts() {
)
}
const mapStateToProps = (state: AppState) => {
return {
charts: state.charts.get('charts'),
connectionId: state.connection.connectionId,
tree: state.connection.tree,
}
}
const mapStateToProps = (state: AppState) => ({
charts: state.charts.get('charts'),
connectionId: state.connection.connectionId,
tree: state.connection.tree,
})
const mapDispatchToProps = (dispatch: any) => {
return {
actions: {
chart: bindActionCreators(chartActions, dispatch),
},
}
}
const mapDispatchToProps = (dispatch: any) => ({
actions: {
chart: bindActionCreators(chartActions, dispatch),
},
})
const styles = (theme: Theme) => ({
container: {