From 28dea3ded2fb58d864b502a15757275ce802d19e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s?= Date: Tue, 19 Nov 2024 09:09:14 +0100 Subject: [PATCH] Moooore QA fixes in new document parameters (#630) - [ ] Link from a log to document paramaters history tag. - [ ] Fix run batch eval modal to show mapped input - [ ] Fix run batch doc modal to show linked dataset to doc and mapped fields. - [ ] Fix tooltip colors in evaluation stats - [ ] Fix tabs when fullWidth prop is present --- .../HistoryLogParams/useLogHistoryParams.ts | 41 ++------- .../_components/MetadataInfoTabs/index.tsx | 9 +- .../RunPromptInBatchModal/index.tsx | 89 +++++++++++++------ .../useMappedParametersFromLocalStorage.ts | 44 +++++++++ .../DatasetForm/index.tsx | 47 +++++++--- .../CreateBatchEvaluationModal/index.tsx | 1 + .../useRunBatchForm.ts | 39 +++++--- .../BigNumberPanels/Panel/index.tsx | 3 +- .../_components/BatchEvaluationsTable.tsx | 2 +- .../DocumentLogs/DocumentLogInfo/index.tsx | 66 +++++++++++++- .../src/hooks/useDocumentParameters/index.ts | 53 +++++++++++ .../recalculateInputs/index.test.ts | 18 ++++ .../recalculateInputs/index.ts | 9 +- packages/web-ui/src/ds/atoms/Button/index.tsx | 3 + packages/web-ui/src/ds/atoms/Icons/index.tsx | 2 + .../src/ds/molecules/TabSelector/index.tsx | 8 +- 16 files changed, 339 insertions(+), 95 deletions(-) create mode 100644 apps/web/src/app/(private)/projects/[projectId]/versions/[commitUuid]/documents/[documentUuid]/batch/_components/RunPromptInBatchModal/useMappedParametersFromLocalStorage.ts diff --git a/apps/web/src/app/(private)/projects/[projectId]/versions/[commitUuid]/documents/[documentUuid]/_components/DocumentEditor/Editor/Playground/DocumentParams/HistoryLogParams/useLogHistoryParams.ts b/apps/web/src/app/(private)/projects/[projectId]/versions/[commitUuid]/documents/[documentUuid]/_components/DocumentEditor/Editor/Playground/DocumentParams/HistoryLogParams/useLogHistoryParams.ts index 7e4ad780d..89d351ac5 100644 --- a/apps/web/src/app/(private)/projects/[projectId]/versions/[commitUuid]/documents/[documentUuid]/_components/DocumentEditor/Editor/Playground/DocumentParams/HistoryLogParams/useLogHistoryParams.ts +++ b/apps/web/src/app/(private)/projects/[projectId]/versions/[commitUuid]/documents/[documentUuid]/_components/DocumentEditor/Editor/Playground/DocumentParams/HistoryLogParams/useLogHistoryParams.ts @@ -1,40 +1,14 @@ import { useCallback, useState } from 'react' -import { DocumentLog, DocumentVersion } from '@latitude-data/core/browser' +import { DocumentVersion } from '@latitude-data/core/browser' import { useCurrentCommit, useCurrentProject } from '@latitude-data/web-ui' -import { Inputs, useDocumentParameters } from '$/hooks/useDocumentParameters' +import { useDocumentParameters } from '$/hooks/useDocumentParameters' import useDocumentLogs from '$/stores/documentLogs' import useDocumentLogWithPaginationPosition, { LogWithPosition, } from '$/stores/documentLogWithPaginationPosition' import useDocumentLogsPagination from '$/stores/useDocumentLogsPagination' -function getValue({ paramValue }: { paramValue: unknown | undefined }) { - try { - const value = JSON.stringify(paramValue) - return { value, metadata: { includeInPrompt: paramValue !== undefined } } - } catch { - return { value: '', metadata: { includeInPrompt: false } } - } -} - -function mapLogParametersToInputs({ - inputs, - parameters, -}: { - inputs: Inputs<'history'> - parameters: DocumentLog['parameters'] | undefined -}): Inputs<'history'> | undefined { - const params = parameters ?? {} - // No parameters - if (!Object.keys(params).length) return undefined - - return Object.entries(inputs).reduce((acc, [key]) => { - acc[key] = getValue({ paramValue: params[key] }) - return acc - }, {} as Inputs<'history'>) -} - const ONLY_ONE_PAGE = '1' export function useLogHistoryParams({ document, @@ -44,7 +18,8 @@ export function useLogHistoryParams({ commitVersionUuid: string }) { const { - history: { inputs, setInputs, setHistoryLog, logUuid }, + mapDocParametersToInputs, + history: { setHistoryLog, logUuid }, } = useDocumentParameters({ documentVersionUuid: document.documentUuid, commitVersionUuid, @@ -92,14 +67,10 @@ export function useLogHistoryParams({ const log = logs[0] if (!log) return - const newInputs = mapLogParametersToInputs({ - inputs, + mapDocParametersToInputs({ + source: 'history', parameters: log.parameters, }) - - if (!newInputs) return - - setInputs(newInputs) setHistoryLog(log.uuid) }, }) diff --git a/apps/web/src/app/(private)/projects/[projectId]/versions/[commitUuid]/documents/[documentUuid]/_components/MetadataInfoTabs/index.tsx b/apps/web/src/app/(private)/projects/[projectId]/versions/[commitUuid]/documents/[documentUuid]/_components/MetadataInfoTabs/index.tsx index af370ba71..7ee83a168 100644 --- a/apps/web/src/app/(private)/projects/[projectId]/versions/[commitUuid]/documents/[documentUuid]/_components/MetadataInfoTabs/index.tsx +++ b/apps/web/src/app/(private)/projects/[projectId]/versions/[commitUuid]/documents/[documentUuid]/_components/MetadataInfoTabs/index.tsx @@ -7,6 +7,7 @@ type Props = { children: (args: RenderProps) => ReactNode tabs?: TabSelectorOption[] className?: string + tabsActions?: ReactNode } export const MetadataInfoTabs = forwardRef( function MetadataInfoTabs( @@ -16,6 +17,7 @@ export const MetadataInfoTabs = forwardRef( { label: 'Metadata', value: 'metadata' }, { label: 'Messages', value: 'messages' }, ], + tabsActions, children, }, ref, @@ -30,12 +32,17 @@ export const MetadataInfoTabs = forwardRef( className, )} > -
+
+ {tabsActions ? ( +
+ {tabsActions} +
+ ) : null}
diff --git a/apps/web/src/app/(private)/projects/[projectId]/versions/[commitUuid]/documents/[documentUuid]/batch/_components/RunPromptInBatchModal/index.tsx b/apps/web/src/app/(private)/projects/[projectId]/versions/[commitUuid]/documents/[documentUuid]/batch/_components/RunPromptInBatchModal/index.tsx index dfb45589c..c0c5d07ae 100644 --- a/apps/web/src/app/(private)/projects/[projectId]/versions/[commitUuid]/documents/[documentUuid]/batch/_components/RunPromptInBatchModal/index.tsx +++ b/apps/web/src/app/(private)/projects/[projectId]/versions/[commitUuid]/documents/[documentUuid]/batch/_components/RunPromptInBatchModal/index.tsx @@ -23,28 +23,20 @@ import useDatasets from '$/stores/datasets' import DatasetForm from '../../../evaluations/[evaluationId]/_components/Actions/CreateBatchEvaluationModal/DatasetForm' import { RunBatchParameters } from '../../../evaluations/[evaluationId]/_components/Actions/CreateBatchEvaluationModal/useRunBatch' import { buildEmptyParameters } from '../../../evaluations/[evaluationId]/_components/Actions/CreateBatchEvaluationModal/useRunBatchForm' +import { useMappedParametersFromLocalStorage } from './useMappedParametersFromLocalStorage' -function useRunDocumentInBatchForm(document: DocumentVersion) { +function useRunDocumentInBatchForm({ + document, + commitVersionUuid, +}: { + document: DocumentVersion + commitVersionUuid: string +}) { const [metadata, setMetadata] = useState() - useEffect(() => { - const fn = async () => { - if (!document || !document.content) return - - const metadata = await readMetadata({ - prompt: document.content, - }) - - setMetadata(metadata) - } - - fn() - }, [document]) - const parametersList = useMemo( () => Array.from(metadata?.parameters ?? []), [metadata?.parameters], ) - const { data: datasets, isLoading: isLoadingDatasets } = useDatasets() const [selectedDataset, setSelectedDataset] = useState(null) const [headers, setHeaders] = useState([]) const [wantAllLines, setAllRows] = useState(true) @@ -53,7 +45,6 @@ function useRunDocumentInBatchForm(document: DocumentVersion) { const [parameters, setParameters] = useState(() => buildEmptyParameters(parametersList), ) - const onParameterChange = useCallback( (param: string) => (header: string) => { setParameters((prev: RunBatchParameters) => ({ @@ -64,6 +55,20 @@ function useRunDocumentInBatchForm(document: DocumentVersion) { [selectedDataset], ) + const buildHeaders = useCallback( + (dataset: Dataset) => { + setHeaders([ + { value: '-1', label: '-- Leave this parameter empty' }, + ...dataset.fileMetadata.headers.map((header) => ({ + value: header, + label: header, + })), + ]) + }, + [setHeaders, selectedDataset], + ) + + const { data: datasets, isLoading: isLoadingDatasets } = useDatasets() const onSelectDataset = useCallback( async (value: string) => { const ds = datasets.find((ds) => ds.id === Number(value)) @@ -73,16 +78,44 @@ function useRunDocumentInBatchForm(document: DocumentVersion) { setParameters(buildEmptyParameters(parametersList)) setFromLine(1) setToLine(ds.fileMetadata.rowCount) - setHeaders([ - { value: '-1', label: '-- Leave this parameter empty' }, - ...ds.fileMetadata.headers.map((header) => ({ - value: header, - label: header, - })), - ]) + buildHeaders(ds) }, - [parametersList, datasets], + [parametersList, datasets, buildHeaders], ) + + useEffect(() => { + const fn = async () => { + if (!document || !document.content) return + + const metadata = await readMetadata({ + prompt: document.content, + }) + + setMetadata(metadata) + + // Only choose the dataset if it's not already selected + const ds = selectedDataset + ? undefined + : datasets.find((ds) => ds.id === document.datasetId) + + if (!ds) return + + setSelectedDataset(ds) + buildHeaders(ds) + } + + fn() + }, [document, selectedDataset, setSelectedDataset, buildHeaders, datasets]) + + useMappedParametersFromLocalStorage({ + document, + commitVersionUuid, + parametersList, + selectedDataset, + onDatasetReady: ({ mapped }) => { + setParameters(mapped) + }, + }) return { datasets, isLoadingDatasets, @@ -159,7 +192,10 @@ export default function RunPromptInBatchModal() { const { commit } = useCurrentCommit() const { toast } = useToast() - const form = useRunDocumentInBatchForm(document) + const form = useRunDocumentInBatchForm({ + document, + commitVersionUuid: commit.uuid, + }) const { runBatch, errors, isRunningBatch } = useRunDocumentInBatch({ document, projectId: project.id, @@ -224,6 +260,7 @@ export default function RunPromptInBatchModal() { headers={form.headers} parametersList={form.parametersList} onParametersChange={form.onParameterChange} + parameters={form.parameters} /> ) diff --git a/apps/web/src/app/(private)/projects/[projectId]/versions/[commitUuid]/documents/[documentUuid]/batch/_components/RunPromptInBatchModal/useMappedParametersFromLocalStorage.ts b/apps/web/src/app/(private)/projects/[projectId]/versions/[commitUuid]/documents/[documentUuid]/batch/_components/RunPromptInBatchModal/useMappedParametersFromLocalStorage.ts new file mode 100644 index 000000000..f721214ae --- /dev/null +++ b/apps/web/src/app/(private)/projects/[projectId]/versions/[commitUuid]/documents/[documentUuid]/batch/_components/RunPromptInBatchModal/useMappedParametersFromLocalStorage.ts @@ -0,0 +1,44 @@ +import { useEffect } from 'react' + +import { Dataset, DocumentVersion } from '@latitude-data/core/browser' +import { RunBatchParameters } from '$/app/(private)/projects/[projectId]/versions/[commitUuid]/documents/[documentUuid]/evaluations/[evaluationId]/_components/Actions/CreateBatchEvaluationModal/useRunBatch' +import { useDocumentParameters } from '$/hooks/useDocumentParameters' + +/** + * This hook map parameters + * from document.datasetId that are mapped in the + * document paramters UI if any + * + * IMPORTANT: Other wise it will ignore if it's a different dataset + */ +export function useMappedParametersFromLocalStorage({ + document, + commitVersionUuid, + parametersList, + onDatasetReady, + selectedDataset, +}: { + document: DocumentVersion + commitVersionUuid: string + parametersList: string[] + selectedDataset: Dataset | null | undefined + onDatasetReady: (_args: { mapped: RunBatchParameters }) => void +}) { + const { + dataset: { mappedInputs }, + } = useDocumentParameters({ + documentVersionUuid: document.documentUuid, + commitVersionUuid, + }) + useEffect(() => { + if (!selectedDataset) return + if (selectedDataset.id !== document.datasetId) return + + const mappedParameters = parametersList.reduce((acc, key) => { + acc[key] = mappedInputs[key] + return acc + }, {} as RunBatchParameters) + + onDatasetReady({ mapped: mappedParameters }) + }, [parametersList, document, selectedDataset, mappedInputs]) +} diff --git a/apps/web/src/app/(private)/projects/[projectId]/versions/[commitUuid]/documents/[documentUuid]/evaluations/[evaluationId]/_components/Actions/CreateBatchEvaluationModal/DatasetForm/index.tsx b/apps/web/src/app/(private)/projects/[projectId]/versions/[commitUuid]/documents/[documentUuid]/evaluations/[evaluationId]/_components/Actions/CreateBatchEvaluationModal/DatasetForm/index.tsx index 3bf10461f..384c9d5af 100644 --- a/apps/web/src/app/(private)/projects/[projectId]/versions/[commitUuid]/documents/[documentUuid]/evaluations/[evaluationId]/_components/Actions/CreateBatchEvaluationModal/DatasetForm/index.tsx +++ b/apps/web/src/app/(private)/projects/[projectId]/versions/[commitUuid]/documents/[documentUuid]/evaluations/[evaluationId]/_components/Actions/CreateBatchEvaluationModal/DatasetForm/index.tsx @@ -1,4 +1,5 @@ import { useMemo } from 'react' +import { isNumber } from 'lodash-es' import { Dataset, DocumentVersion } from '@latitude-data/core/browser' import { @@ -12,9 +13,24 @@ import { SelectOption, SwitchInput, } from '@latitude-data/web-ui' +import { RunBatchParameters } from '$/app/(private)/projects/[projectId]/versions/[commitUuid]/documents/[documentUuid]/evaluations/[evaluationId]/_components/Actions/CreateBatchEvaluationModal/useRunBatch' import { ROUTES } from '$/services/routes' import Link from 'next/link' +function findValue({ + headers, + parameters, + param, +}: { + headers: SelectOption[] + parameters: RunBatchParameters + param: string +}) { + const index = parameters?.[param] + const header = isNumber(index) ? headers[index + 1] : undefined + return header ? String(header.value) : '' +} + function LineRangeInputs({ disabled, fromDefaultValue, @@ -60,6 +76,7 @@ function LineRangeInputs({ export default function DatasetForm({ document, onParametersChange, + parameters, selectedDataset, headers, wantAllLines, @@ -75,6 +92,7 @@ export default function DatasetForm({ }: { document: DocumentVersion onParametersChange: (param: string) => (header: string) => void + parameters: RunBatchParameters parametersList: string[] wantAllLines: boolean fromLine: number | undefined @@ -171,19 +189,22 @@ export default function DatasetForm({ > {selectedDataset ? (
- {parametersList.map((param) => ( - + ) + })}
) : null} diff --git a/apps/web/src/app/(private)/projects/[projectId]/versions/[commitUuid]/documents/[documentUuid]/evaluations/[evaluationId]/_components/Actions/CreateBatchEvaluationModal/index.tsx b/apps/web/src/app/(private)/projects/[projectId]/versions/[commitUuid]/documents/[documentUuid]/evaluations/[evaluationId]/_components/Actions/CreateBatchEvaluationModal/index.tsx index e128db25f..b4bfe01fd 100644 --- a/apps/web/src/app/(private)/projects/[projectId]/versions/[commitUuid]/documents/[documentUuid]/evaluations/[evaluationId]/_components/Actions/CreateBatchEvaluationModal/index.tsx +++ b/apps/web/src/app/(private)/projects/[projectId]/versions/[commitUuid]/documents/[documentUuid]/evaluations/[evaluationId]/_components/Actions/CreateBatchEvaluationModal/index.tsx @@ -94,6 +94,7 @@ export default function CreateBatchEvaluationModal({ headers={form.headers} parametersList={form.parametersList} onParametersChange={form.onParameterChange} + parameters={form.parameters} /> ) diff --git a/apps/web/src/app/(private)/projects/[projectId]/versions/[commitUuid]/documents/[documentUuid]/evaluations/[evaluationId]/_components/Actions/CreateBatchEvaluationModal/useRunBatchForm.ts b/apps/web/src/app/(private)/projects/[projectId]/versions/[commitUuid]/documents/[documentUuid]/evaluations/[evaluationId]/_components/Actions/CreateBatchEvaluationModal/useRunBatchForm.ts index 02f6e7f9f..2ef2af55d 100644 --- a/apps/web/src/app/(private)/projects/[projectId]/versions/[commitUuid]/documents/[documentUuid]/evaluations/[evaluationId]/_components/Actions/CreateBatchEvaluationModal/useRunBatchForm.ts +++ b/apps/web/src/app/(private)/projects/[projectId]/versions/[commitUuid]/documents/[documentUuid]/evaluations/[evaluationId]/_components/Actions/CreateBatchEvaluationModal/useRunBatchForm.ts @@ -2,7 +2,8 @@ import { useCallback, useMemo, useState } from 'react' import { ConversationMetadata } from '@latitude-data/compiler' import { Dataset, DocumentVersion } from '@latitude-data/core/browser' -import { SelectOption } from '@latitude-data/web-ui' +import { SelectOption, useCurrentCommit } from '@latitude-data/web-ui' +import { useMappedParametersFromLocalStorage } from '$/app/(private)/projects/[projectId]/versions/[commitUuid]/documents/[documentUuid]/batch/_components/RunPromptInBatchModal/useMappedParametersFromLocalStorage' import useDatasets from '$/stores/datasets' import { RunBatchParameters } from './useRunBatch' @@ -26,15 +27,28 @@ export function useRunBatchForm({ [documentMetadata?.parameters], ) const [selectedDataset, setSelectedDataset] = useState(null) + const [headers, setHeaders] = useState([]) + const buildHeaders = useCallback( + (dataset: Dataset) => { + setHeaders([ + { value: '-1', label: '-- Leave this parameter empty' }, + ...dataset.fileMetadata.headers.map((header) => ({ + value: header, + label: header, + })), + ]) + }, + [setHeaders, selectedDataset], + ) const { data: datasets, isLoading: isLoadingDatasets } = useDatasets({ onFetched: (ds) => { const selected = ds.find((d) => d.id === document.datasetId) if (!selected) return setSelectedDataset(selected) + buildHeaders(selected) }, }) - const [headers, setHeaders] = useState([]) const [wantAllLines, setAllRows] = useState(true) const [fromLine, setFromLine] = useState(undefined) const [toLine, setToLine] = useState(undefined) @@ -61,16 +75,21 @@ export function useRunBatchForm({ setParameters(buildEmptyParameters(parametersList)) setFromLine(1) setToLine(ds.fileMetadata.rowCount) - setHeaders([ - { value: '-1', label: '-- Leave this parameter empty' }, - ...ds.fileMetadata.headers.map((header) => ({ - value: header, - label: header, - })), - ]) + buildHeaders(ds) }, - [parametersList, datasets], + [parametersList, datasets, buildHeaders], ) + + const { commit } = useCurrentCommit() + useMappedParametersFromLocalStorage({ + document, + commitVersionUuid: commit.uuid, + parametersList, + selectedDataset, + onDatasetReady: ({ mapped }) => { + setParameters(mapped) + }, + }) return { datasets, isLoadingDatasets, diff --git a/apps/web/src/app/(private)/projects/[projectId]/versions/[commitUuid]/documents/[documentUuid]/evaluations/[evaluationId]/_components/MetricsSummary/BigNumberPanels/Panel/index.tsx b/apps/web/src/app/(private)/projects/[projectId]/versions/[commitUuid]/documents/[documentUuid]/evaluations/[evaluationId]/_components/MetricsSummary/BigNumberPanels/Panel/index.tsx index 1a7170ab3..5180779f8 100644 --- a/apps/web/src/app/(private)/projects/[projectId]/versions/[commitUuid]/documents/[documentUuid]/evaluations/[evaluationId]/_components/MetricsSummary/BigNumberPanels/Panel/index.tsx +++ b/apps/web/src/app/(private)/projects/[projectId]/versions/[commitUuid]/documents/[documentUuid]/evaluations/[evaluationId]/_components/MetricsSummary/BigNumberPanels/Panel/index.tsx @@ -27,6 +27,7 @@ export default function Panel({ const onMouseLeave = useCallback(() => { setOpen(false) }, []) + return ( } > - {additionalInfo} + {additionalInfo} ) } diff --git a/apps/web/src/app/(private)/projects/[projectId]/versions/[commitUuid]/documents/[documentUuid]/evaluations/dashboard/_components/BatchEvaluationsTable.tsx b/apps/web/src/app/(private)/projects/[projectId]/versions/[commitUuid]/documents/[documentUuid]/evaluations/dashboard/_components/BatchEvaluationsTable.tsx index babca4ed7..0fe259e63 100644 --- a/apps/web/src/app/(private)/projects/[projectId]/versions/[commitUuid]/documents/[documentUuid]/evaluations/dashboard/_components/BatchEvaluationsTable.tsx +++ b/apps/web/src/app/(private)/projects/[projectId]/versions/[commitUuid]/documents/[documentUuid]/evaluations/dashboard/_components/BatchEvaluationsTable.tsx @@ -54,7 +54,7 @@ export default function ConnectedEvaluationsTable({
- {evaluation.description} + {evaluation.description} ))} diff --git a/apps/web/src/app/(private)/projects/[projectId]/versions/[commitUuid]/documents/[documentUuid]/logs/_components/DocumentLogs/DocumentLogInfo/index.tsx b/apps/web/src/app/(private)/projects/[projectId]/versions/[commitUuid]/documents/[documentUuid]/logs/_components/DocumentLogs/DocumentLogInfo/index.tsx index e03079a00..e0404e2ed 100644 --- a/apps/web/src/app/(private)/projects/[projectId]/versions/[commitUuid]/documents/[documentUuid]/logs/_components/DocumentLogs/DocumentLogInfo/index.tsx +++ b/apps/web/src/app/(private)/projects/[projectId]/versions/[commitUuid]/documents/[documentUuid]/logs/_components/DocumentLogs/DocumentLogInfo/index.tsx @@ -1,11 +1,20 @@ 'use client' -import { RefObject, useEffect, useRef, useState } from 'react' +import { RefObject, useCallback, useEffect, useRef, useState } from 'react' import { ProviderLogDto } from '@latitude-data/core/browser' import { DocumentLogWithMetadataAndError } from '@latitude-data/core/repositories' -import { Alert } from '@latitude-data/web-ui' +import { + Alert, + Button, + Tooltip, + useCurrentCommit, + useCurrentProject, +} from '@latitude-data/web-ui' +import { useDocumentParameters } from '$/hooks/useDocumentParameters' import { useStickyNested } from '$/hooks/useStickyNested' +import { ROUTES } from '$/services/routes' +import { useRouter } from 'next/navigation' import { usePanelDomRef } from 'node_modules/@latitude-data/web-ui/src/ds/atoms/SplitPane' import { MetadataInfoTabs } from '../../../../_components/MetadataInfoTabs' @@ -52,6 +61,15 @@ export function DocumentLogInfo({ }, [ref.current]) const scrollableArea = usePanelDomRef({ selfRef: target }) const beacon = tableRef?.current + const { commit } = useCurrentCommit() + const { project } = useCurrentProject() + const { + setSource, + history: { setHistoryLog }, + } = useDocumentParameters({ + documentVersionUuid: documentLog.documentUuid, + commitVersionUuid: commit.uuid, + }) useStickyNested({ scrollableArea, beacon, @@ -60,8 +78,50 @@ export function DocumentLogInfo({ offset: 24, }) const { lastResponse, messages } = useGetProviderLogMessages({ providerLogs }) + const navigate = useRouter() + const employLogAsDocumentParameters = useCallback(() => { + setSource('history') + setHistoryLog(documentLog.uuid) + navigate.push( + ROUTES.projects + .detail({ id: project.id }) + .commits.detail({ + uuid: commit.uuid, + }) + .documents.detail({ uuid: documentLog.documentUuid }).root, + ) + }, [ + setHistoryLog, + setSource, + navigate, + project.id, + commit.uuid, + documentLog.documentUuid, + documentLog.uuid, + ]) return ( - + + } + > + Use this log in the playground + + } + > {({ selectedTab }) => isLoading ? ( diff --git a/apps/web/src/hooks/useDocumentParameters/index.ts b/apps/web/src/hooks/useDocumentParameters/index.ts index b883448ca..87f909ff7 100644 --- a/apps/web/src/hooks/useDocumentParameters/index.ts +++ b/apps/web/src/hooks/useDocumentParameters/index.ts @@ -1,5 +1,6 @@ import { useCallback, useMemo } from 'react' +import { DocumentLog } from '@latitude-data/core/browser' import { AppLocalStorage, useLocalStorage } from '@latitude-data/web-ui' import { recalculateInputs } from '$/hooks/useDocumentParameters/recalculateInputs' @@ -74,6 +75,33 @@ function getDocState(oldState: InputsByDocument | null, key: string) { return { state, doc } } +function getValue({ paramValue }: { paramValue: unknown | undefined }) { + try { + const value = + typeof paramValue === 'string' ? paramValue : JSON.stringify(paramValue) + return { value, metadata: { includeInPrompt: paramValue !== undefined } } + } catch { + return { value: '', metadata: { includeInPrompt: false } } + } +} + +function mapLogParametersToInputs({ + inputs, + parameters, +}: { + inputs: Inputs<'history'> + parameters: DocumentLog['parameters'] | undefined +}): Inputs<'history'> | undefined { + const params = parameters ?? {} + // No parameters + if (!Object.keys(params).length) return undefined + + return Object.entries(inputs).reduce((acc, [key]) => { + acc[key] = getValue({ paramValue: params[key] }) + return acc + }, {} as Inputs<'history'>) +} + type InputsByDocument = Record> export function useDocumentParameters({ documentVersionUuid, @@ -231,6 +259,30 @@ export function useDocumentParameters({ [allInputs, key, setValue], ) + const mapDocParametersToInputs = useCallback( + ({ + parameters, + source, + }: { + parameters: DocumentLog['parameters'] + source: InputSource + }) => { + const state = allInputs[key] + if (!state) return + + const docState = state[source] + const sourceInputs = docState.inputs + const newInputs = mapLogParametersToInputs({ + inputs: sourceInputs, + parameters, + }) + if (!newInputs) return + + setInputs(source, newInputs) + }, + [inputs, key, setInputs], + ) + const onMetadataProcessed = useCallback( (metadataParameters: Set) => { setInputs( @@ -266,6 +318,7 @@ export function useDocumentParameters({ source, setSource, setInput, + mapDocParametersToInputs, manual: { inputs: inputs['manual'].inputs, setInput: setManualInput, diff --git a/apps/web/src/hooks/useDocumentParameters/recalculateInputs/index.test.ts b/apps/web/src/hooks/useDocumentParameters/recalculateInputs/index.test.ts index 6c1feb4b6..f4f654052 100644 --- a/apps/web/src/hooks/useDocumentParameters/recalculateInputs/index.test.ts +++ b/apps/web/src/hooks/useDocumentParameters/recalculateInputs/index.test.ts @@ -41,6 +41,24 @@ describe('recalculateInputs', () => { }) }) + it('respect metadata', () => { + const newInputs = recalculateInputs({ + inputs: { + param1: { value: 'value1', metadata: { includeInPrompt: false } }, + }, + metadataParameters: new Set(['param1']), + }) + + expect(newInputs).toEqual({ + param1: { + value: 'value1', + metadata: { + includeInPrompt: false, + }, + }, + }) + }) + it('replace existing parameter if only one changed and keep value', () => { const newInputs = recalculateInputs({ inputs: { diff --git a/apps/web/src/hooks/useDocumentParameters/recalculateInputs/index.ts b/apps/web/src/hooks/useDocumentParameters/recalculateInputs/index.ts index b6fbc00e5..92d052a5b 100644 --- a/apps/web/src/hooks/useDocumentParameters/recalculateInputs/index.ts +++ b/apps/web/src/hooks/useDocumentParameters/recalculateInputs/index.ts @@ -11,7 +11,8 @@ export function recalculateInputs({ Array.from(metadataParameters).map((param) => { if (param in inputs) { const value = inputs[param]?.value ?? '' - return [param, { value, metadata: { includeInPrompt: true } }] + const includeInPrompt = inputs[param]?.metadata.includeInPrompt ?? true + return [param, { value, metadata: { includeInPrompt } }] } const availableInputKey = Object.keys(inputs).find( @@ -19,8 +20,10 @@ export function recalculateInputs({ ) if (availableInputKey) { - const value = inputs[availableInputKey]?.value ?? '' - return [param, { value, metadata: { includeInPrompt: true } }] + const input = inputs[availableInputKey] + const value = input?.value ?? '' + const includeInPrompt = input?.metadata.includeInPrompt ?? true + return [param, { value, metadata: { includeInPrompt } }] } return [param, { value: '', metadata: { includeInPrompt: true } }] diff --git a/packages/web-ui/src/ds/atoms/Button/index.tsx b/packages/web-ui/src/ds/atoms/Button/index.tsx index 9314dc7c1..d2806ecfc 100644 --- a/packages/web-ui/src/ds/atoms/Button/index.tsx +++ b/packages/web-ui/src/ds/atoms/Button/index.tsx @@ -129,11 +129,13 @@ export type ButtonProps = ButtonHTMLAttributes & fancy?: boolean lookDisabled?: boolean ellipsis?: boolean + containerClassName?: string } const Button = forwardRef(function Button( { className, + containerClassName, variant, size, fancy, @@ -163,6 +165,7 @@ const Button = forwardRef(function Button( className={cn( 'group relative', buttonContainerVariants({ fanciness, variant }), + containerClassName, { 'w-full': fullWidth, 'opacity-50': lookDisabled, diff --git a/packages/web-ui/src/ds/atoms/Icons/index.tsx b/packages/web-ui/src/ds/atoms/Icons/index.tsx index 7c8deef24..e22ae62f4 100644 --- a/packages/web-ui/src/ds/atoms/Icons/index.tsx +++ b/packages/web-ui/src/ds/atoms/Icons/index.tsx @@ -34,6 +34,7 @@ import { Pin, PinOff, RefreshCcw, + ScrollTextIcon, Sparkles, SquareDot, SquareMinus, @@ -100,6 +101,7 @@ const Icons = { trash: Trash, twitter: Twitter, undo: Undo, + rollText: ScrollTextIcon, } export type IconName = keyof typeof Icons diff --git a/packages/web-ui/src/ds/molecules/TabSelector/index.tsx b/packages/web-ui/src/ds/molecules/TabSelector/index.tsx index 207895bc3..0c74e4fce 100644 --- a/packages/web-ui/src/ds/molecules/TabSelector/index.tsx +++ b/packages/web-ui/src/ds/molecules/TabSelector/index.tsx @@ -80,8 +80,12 @@ export function TabSelector({ >