From 982aeaaf85cdee432a1a4f1925edfea6a92fc5ca Mon Sep 17 00:00:00 2001 From: Adam Gough Date: Tue, 10 Jun 2025 23:00:21 -0700 Subject: [PATCH 01/11] fix: added pages for chunks --- .../knowledge/[id]/[documentId]/document.tsx | 134 ++++++++++++++++-- apps/sim/hooks/use-knowledge.ts | 102 +++++++++++-- apps/sim/stores/knowledge/store.ts | 17 ++- 3 files changed, 227 insertions(+), 26 deletions(-) diff --git a/apps/sim/app/w/knowledge/[id]/[documentId]/document.tsx b/apps/sim/app/w/knowledge/[id]/[documentId]/document.tsx index 84888da21a0..78fad89108b 100644 --- a/apps/sim/app/w/knowledge/[id]/[documentId]/document.tsx +++ b/apps/sim/app/w/knowledge/[id]/[documentId]/document.tsx @@ -1,7 +1,7 @@ 'use client' -import { useEffect, useState } from 'react' -import { Circle, CircleOff, FileText, Plus, Search, Trash2, X } from 'lucide-react' +import { useCallback, useEffect, useRef, useState } from 'react' +import { ChevronLeft, ChevronRight, Circle, CircleOff, FileText, Plus, Search, Trash2, X } from 'lucide-react' import { Button } from '@/components/ui/button' import { Checkbox } from '@/components/ui/checkbox' import { Tooltip, TooltipContent, TooltipTrigger } from '@/components/ui/tooltip' @@ -59,18 +59,55 @@ export function Document({ const [isLoadingDocument, setIsLoadingDocument] = useState(true) const [error, setError] = useState(null) - // Use the new chunks hook + // Search debouncing + const [debouncedSearchQuery, setDebouncedSearchQuery] = useState('') + + // Use the updated chunks hook with pagination const { chunks, isLoading: isLoadingChunks, error: chunksError, + pagination, + currentPage, + totalPages, + hasNextPage, + hasPrevPage, + goToPage, + nextPage, + prevPage, refreshChunks, + searchChunks, updateChunk, } = useDocumentChunks(knowledgeBaseId, documentId) // Combine errors const combinedError = error || chunksError + // Handle pagination navigation + const handlePrevPage = useCallback(() => { + if (hasPrevPage && !isLoadingChunks) { + prevPage()?.catch((err) => { + logger.error('Previous page failed:', err) + }) + } + }, [hasPrevPage, isLoadingChunks, prevPage]) + + const handleNextPage = useCallback(() => { + if (hasNextPage && !isLoadingChunks) { + nextPage()?.catch((err) => { + logger.error('Next page failed:', err) + }) + } + }, [hasNextPage, isLoadingChunks, nextPage]) + + const handleGoToPage = useCallback((page: number) => { + if (page !== currentPage && !isLoadingChunks) { + goToPage(page)?.catch((err) => { + logger.error('Go to page failed:', err) + }) + } + }, [currentPage, isLoadingChunks, goToPage]) + // Try to get document from store cache first, then fetch if needed useEffect(() => { const fetchDocument = async () => { @@ -182,7 +219,7 @@ export function Document({ } const handleChunkDeleted = async () => { - await refreshChunks() + await refreshChunks({ search: debouncedSearchQuery || undefined }) if (chunkToDelete) { setSelectedChunks((prev) => { const newSet = new Set(prev) @@ -219,7 +256,7 @@ export function Document({ const handleChunkCreated = async (newChunk: ChunkData) => { // Refresh the chunks list to include the new chunk - await refreshChunks() + await refreshChunks({ search: debouncedSearchQuery || undefined }) } const isAllSelected = chunks.length > 0 && selectedChunks.size === chunks.length @@ -315,6 +352,27 @@ export function Document({ + {/* Pagination Info */} + {document?.processingStatus === 'completed' && chunks.length > 0 && ( +
+
+ + Showing {((currentPage - 1) * pagination.limit) + 1}-{Math.min(currentPage * pagination.limit, pagination.total)} of {pagination.total} chunks + + {searchQuery && ( + + • Filtered by "{searchQuery}" + + )} +
+ {totalPages > 1 && ( + + Page {currentPage} of {totalPages} + + )} +
+ )} + {/* Error State for chunks */} {combinedError && !isLoadingChunks && (
@@ -426,9 +484,9 @@ export function Document({
- {document?.processingStatus === 'completed' - ? 'No chunks found' - : 'Document is still processing...'} + {searchQuery + ? `No chunks found matching "${searchQuery}"` + : 'No chunks found'}
@@ -566,6 +624,66 @@ export function Document({
+ + {/* Pagination Controls */} + {document?.processingStatus === 'completed' && totalPages > 1 && ( +
+
+ + + {/* Page numbers - show a few around current page */} +
+ {Array.from({ length: Math.min(totalPages, 7) }, (_, i) => { + let page: number + if (totalPages <= 7) { + page = i + 1 + } else if (currentPage <= 4) { + page = i + 1 + } else if (currentPage >= totalPages - 3) { + page = totalPages - 6 + i + } else { + page = currentPage - 3 + i + } + + if (page < 1 || page > totalPages) return null + + return ( + + ) + })} +
+ + +
+
+ )} diff --git a/apps/sim/hooks/use-knowledge.ts b/apps/sim/hooks/use-knowledge.ts index 53dbe56926d..9aad98a6dc7 100644 --- a/apps/sim/hooks/use-knowledge.ts +++ b/apps/sim/hooks/use-knowledge.ts @@ -228,11 +228,18 @@ export function useDocumentChunks(knowledgeBaseId: string, documentId: string) { offset: 0, hasMore: false, }) + const [currentPage, setCurrentPage] = useState(1) + const [searchQuery, setSearchQuery] = useState('') const [initialLoadDone, setInitialLoadDone] = useState(false) const isStoreLoading = isChunksLoading(documentId) const combinedIsLoading = isLoading || isStoreLoading + // Computed pagination properties + const totalPages = Math.ceil(pagination.total / pagination.limit) + const hasNextPage = currentPage < totalPages + const hasPrevPage = currentPage > 1 + // Single effect to handle all data loading and syncing useEffect(() => { if (!knowledgeBaseId || !documentId) return @@ -243,7 +250,9 @@ export function useDocumentChunks(knowledgeBaseId: string, documentId: string) { try { // Check cache first const cached = getCachedChunks(documentId) - if (cached) { + if (cached && + cached.searchQuery === searchQuery && + cached.pagination.offset === (currentPage - 1) * pagination.limit) { if (isMounted) { setChunks(cached.chunks) setPagination(cached.pagination) @@ -258,9 +267,12 @@ export function useDocumentChunks(knowledgeBaseId: string, documentId: string) { setIsLoading(true) setError(null) + const offset = (currentPage - 1) * pagination.limit + const fetchedChunks = await getChunks(knowledgeBaseId, documentId, { - limit: 50, // Use fixed initial values to avoid dependency issues - offset: 0, + limit: pagination.limit, + offset, + search: searchQuery || undefined, }) if (isMounted) { @@ -291,14 +303,16 @@ export function useDocumentChunks(knowledgeBaseId: string, documentId: string) { return () => { isMounted = false } - }, [knowledgeBaseId, documentId, isStoreLoading, initialLoadDone]) // Removed getCachedChunks and getChunks from dependencies + }, [knowledgeBaseId, documentId, currentPage, searchQuery, isStoreLoading, initialLoadDone, pagination.limit]) // Separate effect to sync with store state changes (no API calls) useEffect(() => { if (!documentId || !initialLoadDone) return const cached = getCachedChunks(documentId) - if (cached) { + if (cached && + cached.searchQuery === searchQuery && + cached.pagination.offset === (currentPage - 1) * pagination.limit) { setChunks(cached.chunks) setPagination(cached.pagination) } @@ -307,7 +321,53 @@ export function useDocumentChunks(knowledgeBaseId: string, documentId: string) { if (!isStoreLoading && isLoading) { setIsLoading(false) } - }, [documentId, isStoreLoading, isLoading, initialLoadDone]) // Removed getCachedChunks from dependencies + }, [documentId, isStoreLoading, isLoading, initialLoadDone, searchQuery, currentPage, pagination.limit]) + + const goToPage = async (page: number) => { + if (page < 1 || page > totalPages || page === currentPage) return + + try { + setIsLoading(true) + setError(null) + setCurrentPage(page) + + const offset = (page - 1) * pagination.limit + + const fetchedChunks = await getChunks(knowledgeBaseId, documentId, { + limit: pagination.limit, + offset, + search: searchQuery || undefined, + }) + + // Update local state from cache + const cached = getCachedChunks(documentId) + if (cached) { + setChunks(cached.chunks) + setPagination(cached.pagination) + } + + return fetchedChunks + } catch (err) { + setError(err instanceof Error ? err.message : 'Failed to load page') + // Reset page on error + setCurrentPage((prev) => prev) + throw err + } finally { + setIsLoading(false) + } + } + + const nextPage = () => { + if (hasNextPage) { + return goToPage(currentPage + 1) + } + } + + const prevPage = () => { + if (hasPrevPage) { + return goToPage(currentPage - 1) + } + } const refreshChunksData = async (options?: { search?: string @@ -318,10 +378,21 @@ export function useDocumentChunks(knowledgeBaseId: string, documentId: string) { setIsLoading(true) setError(null) - const fetchedChunks = await refreshChunks(knowledgeBaseId, documentId, options) + // Update search query if provided and reset to page 1 + if (options?.search !== undefined) { + setSearchQuery(options.search) + setCurrentPage(1) + } + + const offset = options?.offset ?? (currentPage - 1) * pagination.limit + + const fetchedChunks = await refreshChunks(knowledgeBaseId, documentId, { + ...options, + offset, + }) // Update local state from cache - const cached = getCachedChunks(documentId, { search: options?.search }) + const cached = getCachedChunks(documentId) if (cached) { setChunks(cached.chunks) setPagination(cached.pagination) @@ -336,19 +407,21 @@ export function useDocumentChunks(knowledgeBaseId: string, documentId: string) { } } - const searchChunks = async (searchQuery: string) => { + const searchChunks = async (newSearchQuery: string) => { try { setIsLoading(true) setError(null) + setSearchQuery(newSearchQuery) + setCurrentPage(1) // Reset to first page for new search const searchResults = await getChunks(knowledgeBaseId, documentId, { - search: searchQuery, + search: newSearchQuery, limit: pagination.limit, offset: 0, // Reset to first page for new search }) // Update local state from cache - const cached = getCachedChunks(documentId, { search: searchQuery }) + const cached = getCachedChunks(documentId) if (cached) { setChunks(cached.chunks) setPagination(cached.pagination) @@ -368,6 +441,13 @@ export function useDocumentChunks(knowledgeBaseId: string, documentId: string) { isLoading: combinedIsLoading, error, pagination, + currentPage, + totalPages, + hasNextPage, + hasPrevPage, + goToPage, + nextPage, + prevPage, refreshChunks: refreshChunksData, searchChunks, updateChunk: (chunkId: string, updates: Partial) => { diff --git a/apps/sim/stores/knowledge/store.ts b/apps/sim/stores/knowledge/store.ts index e3db4e62b83..7f729df8dad 100644 --- a/apps/sim/stores/knowledge/store.ts +++ b/apps/sim/stores/knowledge/store.ts @@ -288,9 +288,12 @@ export const useKnowledgeStore = create((set, get) => ({ ) => { const state = get() - // Return cached chunks if they exist and match the search criteria + // Return cached chunks if they exist and match the exact search criteria AND offset const cached = state.chunks[documentId] - if (cached && cached.searchQuery === options?.search) { + if (cached && + cached.searchQuery === options?.search && + cached.pagination.offset === (options?.offset || 0) && + cached.pagination.limit === (options?.limit || 50)) { return cached.chunks } @@ -331,7 +334,7 @@ export const useKnowledgeStore = create((set, get) => ({ chunks: { ...state.chunks, [documentId]: { - chunks, + chunks, // Always replace chunks for traditional pagination pagination: { total: pagination?.total || chunks.length, limit: pagination?.limit || options?.limit || 50, @@ -571,11 +574,11 @@ export const useKnowledgeStore = create((set, get) => ({ loadingChunks: new Set([...state.loadingChunks, documentId]), })) - // Build query parameters + // Build query parameters - for refresh, always start from offset 0 const params = new URLSearchParams() if (options?.search) params.set('search', options.search) if (options?.limit) params.set('limit', options.limit.toString()) - if (options?.offset) params.set('offset', options.offset.toString()) + params.set('offset', '0') // Always start fresh on refresh const response = await fetch( `/api/knowledge/${knowledgeBaseId}/documents/${documentId}/chunks?${params.toString()}` @@ -598,11 +601,11 @@ export const useKnowledgeStore = create((set, get) => ({ chunks: { ...state.chunks, [documentId]: { - chunks, // Use server data as source of truth + chunks, // Replace all chunks with fresh data pagination: { total: pagination?.total || chunks.length, limit: pagination?.limit || options?.limit || 50, - offset: pagination?.offset || options?.offset || 0, + offset: 0, // Reset to start hasMore: pagination?.hasMore || false, }, searchQuery: options?.search, From 1ccfd54fbec5e539dc3b209c51bafbca12ae812d Mon Sep 17 00:00:00 2001 From: Adam Gough Date: Tue, 10 Jun 2025 23:14:27 -0700 Subject: [PATCH 02/11] fix: colors and collpase for function block --- apps/sim/app/w/[id]/components/loop-node/loop-node.tsx | 2 +- .../w/[id]/components/parallel-node/parallel-config.ts | 2 +- .../w/[id]/components/parallel-node/parallel-node.tsx | 2 +- .../components/sub-block/components/code.tsx | 9 ++++++++- 4 files changed, 11 insertions(+), 4 deletions(-) diff --git a/apps/sim/app/w/[id]/components/loop-node/loop-node.tsx b/apps/sim/app/w/[id]/components/loop-node/loop-node.tsx index ae0bb86741b..d657fac658b 100644 --- a/apps/sim/app/w/[id]/components/loop-node/loop-node.tsx +++ b/apps/sim/app/w/[id]/components/loop-node/loop-node.tsx @@ -94,7 +94,7 @@ export const LoopNodeComponent = memo(({ data, selected, id }: NodeProps) => { const getNestedStyles = () => { // Base styles const styles: Record = { - backgroundColor: 'transparent', + backgroundColor: 'rgba(0, 0, 0, 0.02)', } // Apply nested styles diff --git a/apps/sim/app/w/[id]/components/parallel-node/parallel-config.ts b/apps/sim/app/w/[id]/components/parallel-node/parallel-config.ts index a1a79eb29bd..fe00c935bec 100644 --- a/apps/sim/app/w/[id]/components/parallel-node/parallel-config.ts +++ b/apps/sim/app/w/[id]/components/parallel-node/parallel-config.ts @@ -6,7 +6,7 @@ export const ParallelTool = { name: 'Parallel', description: 'Parallel Execution', icon: SplitIcon, - bgColor: '#8BC34A', + bgColor: '#FEE12B', data: { label: 'Parallel', parallelType: 'collection' as 'collection' | 'count', diff --git a/apps/sim/app/w/[id]/components/parallel-node/parallel-node.tsx b/apps/sim/app/w/[id]/components/parallel-node/parallel-node.tsx index d5b1cbd4e90..299a75acaed 100644 --- a/apps/sim/app/w/[id]/components/parallel-node/parallel-node.tsx +++ b/apps/sim/app/w/[id]/components/parallel-node/parallel-node.tsx @@ -111,7 +111,7 @@ export const ParallelNodeComponent = memo(({ data, selected, id }: NodeProps) => const getNestedStyles = () => { // Base styles const styles: Record = { - backgroundColor: 'transparent', + backgroundColor: 'rgba(0, 0, 0, 0.02)', } // Apply nested styles diff --git a/apps/sim/app/w/[id]/components/workflow-block/components/sub-block/components/code.tsx b/apps/sim/app/w/[id]/components/workflow-block/components/sub-block/components/code.tsx index b04b805bcb3..5f7ef0860e1 100644 --- a/apps/sim/app/w/[id]/components/workflow-block/components/sub-block/components/code.tsx +++ b/apps/sim/app/w/[id]/components/workflow-block/components/sub-block/components/code.tsx @@ -15,6 +15,7 @@ import { useCodeGeneration } from '@/app/w/[id]/hooks/use-code-generation' import { useSubBlockStore } from '@/stores/workflows/subblock/store' import { CodePromptBar } from '../../../../code-prompt-bar/code-prompt-bar' import { useSubBlockValue } from '../hooks/use-sub-block-value' +import { useWorkflowStore } from '@/stores/workflows/workflow/store' const logger = createLogger('Code') @@ -81,7 +82,13 @@ export function Code({ (useSubBlockStore((state) => state.getValue(blockId, collapsedStateKey)) as boolean) ?? false const setCollapsedValue = useSubBlockStore((state) => state.setValue) - const showCollapseButton = subBlockId === 'responseFormat' && code.split('\n').length > 5 + // Get block type to determine if we should show collapse button + const blockType = useWorkflowStore((state) => state.blocks[blockId]?.type) + + const showCollapseButton = + ((subBlockId === 'responseFormat') || + (blockType === 'function' && subBlockId === 'code')) && + code.split('\n').length > 5 const editorRef = useRef(null) From 2cde915a0f01284f9dd270680fe068baa75090a7 Mon Sep 17 00:00:00 2001 From: Adam Gough Date: Tue, 10 Jun 2025 23:26:40 -0700 Subject: [PATCH 03/11] quick update --- apps/sim/app/w/knowledge/[id]/[documentId]/document.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/apps/sim/app/w/knowledge/[id]/[documentId]/document.tsx b/apps/sim/app/w/knowledge/[id]/[documentId]/document.tsx index 78fad89108b..bb3b6496b14 100644 --- a/apps/sim/app/w/knowledge/[id]/[documentId]/document.tsx +++ b/apps/sim/app/w/knowledge/[id]/[documentId]/document.tsx @@ -76,7 +76,6 @@ export function Document({ nextPage, prevPage, refreshChunks, - searchChunks, updateChunk, } = useDocumentChunks(knowledgeBaseId, documentId) From 2bb1078498e75dbebdd07fe87b39554e025d7af9 Mon Sep 17 00:00:00 2001 From: Adam Gough Date: Tue, 10 Jun 2025 23:56:11 -0700 Subject: [PATCH 04/11] removed debounce --- apps/sim/app/w/knowledge/[id]/[documentId]/document.tsx | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/apps/sim/app/w/knowledge/[id]/[documentId]/document.tsx b/apps/sim/app/w/knowledge/[id]/[documentId]/document.tsx index bb3b6496b14..19b713c8de0 100644 --- a/apps/sim/app/w/knowledge/[id]/[documentId]/document.tsx +++ b/apps/sim/app/w/knowledge/[id]/[documentId]/document.tsx @@ -59,9 +59,6 @@ export function Document({ const [isLoadingDocument, setIsLoadingDocument] = useState(true) const [error, setError] = useState(null) - // Search debouncing - const [debouncedSearchQuery, setDebouncedSearchQuery] = useState('') - // Use the updated chunks hook with pagination const { chunks, @@ -218,7 +215,7 @@ export function Document({ } const handleChunkDeleted = async () => { - await refreshChunks({ search: debouncedSearchQuery || undefined }) + await refreshChunks() if (chunkToDelete) { setSelectedChunks((prev) => { const newSet = new Set(prev) @@ -255,7 +252,7 @@ export function Document({ const handleChunkCreated = async (newChunk: ChunkData) => { // Refresh the chunks list to include the new chunk - await refreshChunks({ search: debouncedSearchQuery || undefined }) + await refreshChunks() } const isAllSelected = chunks.length > 0 && selectedChunks.size === chunks.length From aa856584645713d36d7e4c2871a0f17a01426e23 Mon Sep 17 00:00:00 2001 From: Adam Gough Date: Wed, 11 Jun 2025 00:11:15 -0700 Subject: [PATCH 05/11] fix: changed styling of page display --- .../knowledge/[id]/[documentId]/document.tsx | 25 ++----------------- 1 file changed, 2 insertions(+), 23 deletions(-) diff --git a/apps/sim/app/w/knowledge/[id]/[documentId]/document.tsx b/apps/sim/app/w/knowledge/[id]/[documentId]/document.tsx index 19b713c8de0..ddac4203a2b 100644 --- a/apps/sim/app/w/knowledge/[id]/[documentId]/document.tsx +++ b/apps/sim/app/w/knowledge/[id]/[documentId]/document.tsx @@ -341,34 +341,13 @@ export function Document({ onClick={() => setIsCreateChunkModalOpen(true)} disabled={document?.processingStatus === 'failed'} size='sm' - className='flex items-center gap-1 bg-[#701FFC] font-[480] text-primary-foreground shadow-[0_0_0_0_#701FFC] transition-all duration-200 hover:bg-[#6518E6] hover:shadow-[0_0_0_4px_rgba(127,47,255,0.15)] disabled:cursor-not-allowed disabled:opacity-50' + className='flex items-center gap-1 bg-[#701FFC] font-[480] text-white shadow-[0_0_0_0_#701FFC] transition-all duration-200 hover:bg-[#6518E6] hover:shadow-[0_0_0_4px_rgba(127,47,255,0.15)] disabled:cursor-not-allowed disabled:opacity-50' > Create Chunk - {/* Pagination Info */} - {document?.processingStatus === 'completed' && chunks.length > 0 && ( -
-
- - Showing {((currentPage - 1) * pagination.limit) + 1}-{Math.min(currentPage * pagination.limit, pagination.total)} of {pagination.total} chunks - - {searchQuery && ( - - • Filtered by "{searchQuery}" - - )} -
- {totalPages > 1 && ( - - Page {currentPage} of {totalPages} - - )} -
- )} - {/* Error State for chunks */} {combinedError && !isLoadingChunks && (
@@ -636,7 +615,7 @@ export function Document({ {/* Page numbers - show a few around current page */} -
+
{Array.from({ length: Math.min(totalPages, 7) }, (_, i) => { let page: number if (totalPages <= 7) { From d7e5b21cd29331ce539ad57956dc8b0c6ca3be34 Mon Sep 17 00:00:00 2001 From: Adam Gough Date: Wed, 11 Jun 2025 00:18:07 -0700 Subject: [PATCH 06/11] fix: more styling --- .../knowledge/[id]/[documentId]/document.tsx | 21 +++++++++---------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/apps/sim/app/w/knowledge/[id]/[documentId]/document.tsx b/apps/sim/app/w/knowledge/[id]/[documentId]/document.tsx index ddac4203a2b..1222befaf15 100644 --- a/apps/sim/app/w/knowledge/[id]/[documentId]/document.tsx +++ b/apps/sim/app/w/knowledge/[id]/[documentId]/document.tsx @@ -1,6 +1,6 @@ 'use client' -import { useCallback, useEffect, useRef, useState } from 'react' +import { useCallback, useEffect, useState } from 'react' import { ChevronLeft, ChevronRight, Circle, CircleOff, FileText, Plus, Search, Trash2, X } from 'lucide-react' import { Button } from '@/components/ui/button' import { Checkbox } from '@/components/ui/checkbox' @@ -64,7 +64,6 @@ export function Document({ chunks, isLoading: isLoadingChunks, error: chunksError, - pagination, currentPage, totalPages, hasNextPage, @@ -459,9 +458,9 @@ export function Document({
- {searchQuery - ? `No chunks found matching "${searchQuery}"` - : 'No chunks found'} + {document?.processingStatus === 'completed' + ? 'No chunks found' + : 'Document is still processing...'}
@@ -616,16 +615,16 @@ export function Document({ {/* Page numbers - show a few around current page */}
- {Array.from({ length: Math.min(totalPages, 7) }, (_, i) => { + {Array.from({ length: Math.min(totalPages, 5) }, (_, i) => { let page: number - if (totalPages <= 7) { + if (totalPages <= 5) { page = i + 1 - } else if (currentPage <= 4) { + } else if (currentPage <= 3) { page = i + 1 - } else if (currentPage >= totalPages - 3) { - page = totalPages - 6 + i + } else if (currentPage >= totalPages - 2) { + page = totalPages - 4 + i } else { - page = currentPage - 3 + i + page = currentPage - 2 + i } if (page < 1 || page > totalPages) return null From 06aa10ad190460975e8dde06327264ccab71bdda Mon Sep 17 00:00:00 2001 From: Adam Gough Date: Wed, 11 Jun 2025 00:30:22 -0700 Subject: [PATCH 07/11] bun run lint (#478) --- .../components/sub-block/components/code.tsx | 9 ++--- .../knowledge/[id]/[documentId]/document.tsx | 37 ++++++++++++------- apps/sim/hooks/use-knowledge.ts | 36 ++++++++++++++---- apps/sim/stores/knowledge/store.ts | 10 +++-- 4 files changed, 62 insertions(+), 30 deletions(-) diff --git a/apps/sim/app/w/[id]/components/workflow-block/components/sub-block/components/code.tsx b/apps/sim/app/w/[id]/components/workflow-block/components/sub-block/components/code.tsx index 5f7ef0860e1..ab24bfef1ae 100644 --- a/apps/sim/app/w/[id]/components/workflow-block/components/sub-block/components/code.tsx +++ b/apps/sim/app/w/[id]/components/workflow-block/components/sub-block/components/code.tsx @@ -13,9 +13,9 @@ import { createLogger } from '@/lib/logs/console-logger' import { cn } from '@/lib/utils' import { useCodeGeneration } from '@/app/w/[id]/hooks/use-code-generation' import { useSubBlockStore } from '@/stores/workflows/subblock/store' +import { useWorkflowStore } from '@/stores/workflows/workflow/store' import { CodePromptBar } from '../../../../code-prompt-bar/code-prompt-bar' import { useSubBlockValue } from '../hooks/use-sub-block-value' -import { useWorkflowStore } from '@/stores/workflows/workflow/store' const logger = createLogger('Code') @@ -84,10 +84,9 @@ export function Code({ // Get block type to determine if we should show collapse button const blockType = useWorkflowStore((state) => state.blocks[blockId]?.type) - - const showCollapseButton = - ((subBlockId === 'responseFormat') || - (blockType === 'function' && subBlockId === 'code')) && + + const showCollapseButton = + (subBlockId === 'responseFormat' || (blockType === 'function' && subBlockId === 'code')) && code.split('\n').length > 5 const editorRef = useRef(null) diff --git a/apps/sim/app/w/knowledge/[id]/[documentId]/document.tsx b/apps/sim/app/w/knowledge/[id]/[documentId]/document.tsx index 1222befaf15..6d663f464d9 100644 --- a/apps/sim/app/w/knowledge/[id]/[documentId]/document.tsx +++ b/apps/sim/app/w/knowledge/[id]/[documentId]/document.tsx @@ -1,7 +1,17 @@ 'use client' import { useCallback, useEffect, useState } from 'react' -import { ChevronLeft, ChevronRight, Circle, CircleOff, FileText, Plus, Search, Trash2, X } from 'lucide-react' +import { + ChevronLeft, + ChevronRight, + Circle, + CircleOff, + FileText, + Plus, + Search, + Trash2, + X, +} from 'lucide-react' import { Button } from '@/components/ui/button' import { Checkbox } from '@/components/ui/checkbox' import { Tooltip, TooltipContent, TooltipTrigger } from '@/components/ui/tooltip' @@ -95,13 +105,16 @@ export function Document({ } }, [hasNextPage, isLoadingChunks, nextPage]) - const handleGoToPage = useCallback((page: number) => { - if (page !== currentPage && !isLoadingChunks) { - goToPage(page)?.catch((err) => { - logger.error('Go to page failed:', err) - }) - } - }, [currentPage, isLoadingChunks, goToPage]) + const handleGoToPage = useCallback( + (page: number) => { + if (page !== currentPage && !isLoadingChunks) { + goToPage(page)?.catch((err) => { + logger.error('Go to page failed:', err) + }) + } + }, + [currentPage, isLoadingChunks, goToPage] + ) // Try to get document from store cache first, then fetch if needed useEffect(() => { @@ -614,7 +627,7 @@ export function Document({ {/* Page numbers - show a few around current page */} -
+
{Array.from({ length: Math.min(totalPages, 5) }, (_, i) => { let page: number if (totalPages <= 5) { @@ -634,10 +647,8 @@ export function Document({ key={page} onClick={() => handleGoToPage(page)} disabled={isLoadingChunks} - className={`text-sm font-medium transition-colors hover:text-foreground disabled:opacity-50 disabled:cursor-not-allowed ${ - page === currentPage - ? 'text-foreground' - : 'text-muted-foreground' + className={`font-medium text-sm transition-colors hover:text-foreground disabled:cursor-not-allowed disabled:opacity-50 ${ + page === currentPage ? 'text-foreground' : 'text-muted-foreground' }`} > {page} diff --git a/apps/sim/hooks/use-knowledge.ts b/apps/sim/hooks/use-knowledge.ts index 9aad98a6dc7..fc70942eecc 100644 --- a/apps/sim/hooks/use-knowledge.ts +++ b/apps/sim/hooks/use-knowledge.ts @@ -250,9 +250,11 @@ export function useDocumentChunks(knowledgeBaseId: string, documentId: string) { try { // Check cache first const cached = getCachedChunks(documentId) - if (cached && - cached.searchQuery === searchQuery && - cached.pagination.offset === (currentPage - 1) * pagination.limit) { + if ( + cached && + cached.searchQuery === searchQuery && + cached.pagination.offset === (currentPage - 1) * pagination.limit + ) { if (isMounted) { setChunks(cached.chunks) setPagination(cached.pagination) @@ -303,16 +305,26 @@ export function useDocumentChunks(knowledgeBaseId: string, documentId: string) { return () => { isMounted = false } - }, [knowledgeBaseId, documentId, currentPage, searchQuery, isStoreLoading, initialLoadDone, pagination.limit]) + }, [ + knowledgeBaseId, + documentId, + currentPage, + searchQuery, + isStoreLoading, + initialLoadDone, + pagination.limit, + ]) // Separate effect to sync with store state changes (no API calls) useEffect(() => { if (!documentId || !initialLoadDone) return const cached = getCachedChunks(documentId) - if (cached && - cached.searchQuery === searchQuery && - cached.pagination.offset === (currentPage - 1) * pagination.limit) { + if ( + cached && + cached.searchQuery === searchQuery && + cached.pagination.offset === (currentPage - 1) * pagination.limit + ) { setChunks(cached.chunks) setPagination(cached.pagination) } @@ -321,7 +333,15 @@ export function useDocumentChunks(knowledgeBaseId: string, documentId: string) { if (!isStoreLoading && isLoading) { setIsLoading(false) } - }, [documentId, isStoreLoading, isLoading, initialLoadDone, searchQuery, currentPage, pagination.limit]) + }, [ + documentId, + isStoreLoading, + isLoading, + initialLoadDone, + searchQuery, + currentPage, + pagination.limit, + ]) const goToPage = async (page: number) => { if (page < 1 || page > totalPages || page === currentPage) return diff --git a/apps/sim/stores/knowledge/store.ts b/apps/sim/stores/knowledge/store.ts index 7f729df8dad..0f6b0fb7542 100644 --- a/apps/sim/stores/knowledge/store.ts +++ b/apps/sim/stores/knowledge/store.ts @@ -290,10 +290,12 @@ export const useKnowledgeStore = create((set, get) => ({ // Return cached chunks if they exist and match the exact search criteria AND offset const cached = state.chunks[documentId] - if (cached && - cached.searchQuery === options?.search && - cached.pagination.offset === (options?.offset || 0) && - cached.pagination.limit === (options?.limit || 50)) { + if ( + cached && + cached.searchQuery === options?.search && + cached.pagination.offset === (options?.offset || 0) && + cached.pagination.limit === (options?.limit || 50) + ) { return cached.chunks } From db4e7be800c38072024bc0552e7c2a665bffc3c4 Mon Sep 17 00:00:00 2001 From: Adam Gough Date: Wed, 11 Jun 2025 01:05:17 -0700 Subject: [PATCH 08/11] fix: greptile comments (#478) --- apps/sim/hooks/use-knowledge.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/apps/sim/hooks/use-knowledge.ts b/apps/sim/hooks/use-knowledge.ts index fc70942eecc..f7c2f0a1d05 100644 --- a/apps/sim/hooks/use-knowledge.ts +++ b/apps/sim/hooks/use-knowledge.ts @@ -369,8 +369,6 @@ export function useDocumentChunks(knowledgeBaseId: string, documentId: string) { return fetchedChunks } catch (err) { setError(err instanceof Error ? err.message : 'Failed to load page') - // Reset page on error - setCurrentPage((prev) => prev) throw err } finally { setIsLoading(false) From 00cf73833a83389f36aa06e676e342c8c544598d Mon Sep 17 00:00:00 2001 From: Adam Gough Date: Wed, 11 Jun 2025 22:55:52 -0700 Subject: [PATCH 09/11] fix: changed button color (#478) --- apps/sim/app/w/knowledge/[id]/base.tsx | 2 +- apps/sim/app/w/knowledge/knowledge.tsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/sim/app/w/knowledge/[id]/base.tsx b/apps/sim/app/w/knowledge/[id]/base.tsx index 5c0acac5c72..4eba4ca7fc8 100644 --- a/apps/sim/app/w/knowledge/[id]/base.tsx +++ b/apps/sim/app/w/knowledge/[id]/base.tsx @@ -569,7 +569,7 @@ export function KnowledgeBase({ onClick={handleAddDocuments} disabled={isUploading} size='sm' - className='flex items-center gap-1 bg-[#701FFC] font-[480] text-primary-foreground shadow-[0_0_0_0_#701FFC] transition-all duration-200 hover:bg-[#6518E6] hover:shadow-[0_0_0_4px_rgba(127,47,255,0.15)]' + className='flex items-center gap-1 bg-[#701FFC] font-[480] text-white shadow-[0_0_0_0_#701FFC] transition-all duration-200 hover:bg-[#6518E6] hover:shadow-[0_0_0_4px_rgba(127,47,255,0.15)]' > {isUploading ? 'Uploading...' : 'Add Documents'} diff --git a/apps/sim/app/w/knowledge/knowledge.tsx b/apps/sim/app/w/knowledge/knowledge.tsx index b9721ef749a..cc0cfc70cb2 100644 --- a/apps/sim/app/w/knowledge/knowledge.tsx +++ b/apps/sim/app/w/knowledge/knowledge.tsx @@ -92,7 +92,7 @@ export function Knowledge() {