diff --git a/packages/browseros-agent/apps/agent/entrypoints/app/login/LogoutPage.tsx b/packages/browseros-agent/apps/agent/entrypoints/app/login/LogoutPage.tsx index 4e3e50ae4..1be344474 100644 --- a/packages/browseros-agent/apps/agent/entrypoints/app/login/LogoutPage.tsx +++ b/packages/browseros-agent/apps/agent/entrypoints/app/login/LogoutPage.tsx @@ -1,5 +1,5 @@ import { useQueryClient } from '@tanstack/react-query' -import localforage from 'localforage' +import { clear } from 'idb-keyval' import { Loader2 } from 'lucide-react' import type { FC } from 'react' import { useEffect } from 'react' @@ -25,7 +25,7 @@ export const LogoutPage: FC = () => { await providersStorage.removeValue() await scheduledJobStorage.removeValue() queryClient.clear() - await localforage.clear() + await clear() resetIdentity() await signOut() diff --git a/packages/browseros-agent/apps/agent/entrypoints/sidepanel/history/ChatHistory.tsx b/packages/browseros-agent/apps/agent/entrypoints/sidepanel/history/ChatHistory.tsx index 2e0577dbe..4058b2169 100644 --- a/packages/browseros-agent/apps/agent/entrypoints/sidepanel/history/ChatHistory.tsx +++ b/packages/browseros-agent/apps/agent/entrypoints/sidepanel/history/ChatHistory.tsx @@ -32,6 +32,7 @@ const RemoteChatHistory: FC<{ userId: string }> = ({ userId }) => { const { data: graphqlData, isLoading: isLoadingConversations, + isFetching, hasNextPage, isFetchingNextPage, fetchNextPage, @@ -112,6 +113,7 @@ const RemoteChatHistory: FC<{ userId: string }> = ({ userId }) => { hasNextPage={hasNextPage} isFetchingNextPage={isFetchingNextPage} onLoadMore={fetchNextPage} + isRefreshing={isFetching && !isLoadingConversations} /> ) } diff --git a/packages/browseros-agent/apps/agent/entrypoints/sidepanel/history/components/ConversationList.tsx b/packages/browseros-agent/apps/agent/entrypoints/sidepanel/history/components/ConversationList.tsx index 9e7414dff..e4962a293 100644 --- a/packages/browseros-agent/apps/agent/entrypoints/sidepanel/history/components/ConversationList.tsx +++ b/packages/browseros-agent/apps/agent/entrypoints/sidepanel/history/components/ConversationList.tsx @@ -12,6 +12,7 @@ interface ConversationListProps { hasNextPage?: boolean isFetchingNextPage?: boolean onLoadMore?: () => void + isRefreshing?: boolean } export const ConversationList: FC = ({ @@ -21,6 +22,7 @@ export const ConversationList: FC = ({ hasNextPage, isFetchingNextPage, onLoadMore, + isRefreshing, }) => { const loadMoreRef = useRef(null) @@ -57,6 +59,12 @@ export const ConversationList: FC = ({ return (
+ {isRefreshing && ( +
+ + Fetching latest conversations +
+ )} {!hasConversations ? (
diff --git a/packages/browseros-agent/apps/agent/entrypoints/sidepanel/history/graphql/chatHistoryDocument.ts b/packages/browseros-agent/apps/agent/entrypoints/sidepanel/history/graphql/chatHistoryDocument.ts index ffe2601c8..1f534a034 100644 --- a/packages/browseros-agent/apps/agent/entrypoints/sidepanel/history/graphql/chatHistoryDocument.ts +++ b/packages/browseros-agent/apps/agent/entrypoints/sidepanel/history/graphql/chatHistoryDocument.ts @@ -11,7 +11,7 @@ export const GetConversationsForHistoryDocument = graphql(` nodes { rowId lastMessagedAt - conversationMessages(last: 5, orderBy: ORDER_INDEX_ASC) { + conversationMessages(first: 2, orderBy: ORDER_INDEX_DESC) { nodes { message } diff --git a/packages/browseros-agent/apps/agent/lib/graphql/QueryProvider.tsx b/packages/browseros-agent/apps/agent/lib/graphql/QueryProvider.tsx index be1fdff80..81f71231e 100644 --- a/packages/browseros-agent/apps/agent/lib/graphql/QueryProvider.tsx +++ b/packages/browseros-agent/apps/agent/lib/graphql/QueryProvider.tsx @@ -1,7 +1,10 @@ import { createAsyncStoragePersister } from '@tanstack/query-async-storage-persister' import { QueryClient } from '@tanstack/react-query' -import { PersistQueryClientProvider } from '@tanstack/react-query-persist-client' -import localforage from 'localforage' +import { + type AsyncStorage, + PersistQueryClientProvider, +} from '@tanstack/react-query-persist-client' +import { del, get, set } from 'idb-keyval' import type { FC, ReactNode } from 'react' const queryClient = new QueryClient({ @@ -12,8 +15,14 @@ const queryClient = new QueryClient({ }, }) +const idbStorage: AsyncStorage = { + getItem: (key: string) => get(key).then((v) => v ?? null), + setItem: (key: string, value: string) => set(key, value), + removeItem: (key: string) => del(key), +} + const asyncStoragePersister = createAsyncStoragePersister({ - storage: localforage, + storage: idbStorage, }) export const QueryProvider: FC<{ children: ReactNode }> = ({ children }) => { diff --git a/packages/browseros-agent/apps/agent/package.json b/packages/browseros-agent/apps/agent/package.json index bd20b609a..dcc3aa9d6 100644 --- a/packages/browseros-agent/apps/agent/package.json +++ b/packages/browseros-agent/apps/agent/package.json @@ -44,9 +44,9 @@ "@radix-ui/react-use-controllable-state": "^1.2.2", "@sentry/react": "^10.31.0", "@sentry/vite-plugin": "^4.6.1", - "@tanstack/query-async-storage-persister": "^5.90.21", - "@tanstack/react-query": "^5.90.19", - "@tanstack/react-query-persist-client": "^5.90.21", + "@tanstack/query-async-storage-persister": "^5.95.2", + "@tanstack/react-query": "^5.95.2", + "@tanstack/react-query-persist-client": "^5.95.2", "@types/cytoscape": "^3.31.0", "@types/dompurify": "^3.2.0", "@webext-core/messaging": "^2.3.0", @@ -69,8 +69,8 @@ "eventsource-parser": "^3.0.6", "graphql": "^16.12.0", "hono": "^4.12.3", + "idb-keyval": "^6.2.2", "klavis": "^2.15.0", - "localforage": "^1.10.0", "lucide-react": "^0.562.0", "motion": "^12.23.24", "nanoid": "^5.1.6", diff --git a/packages/browseros-agent/bun.lock b/packages/browseros-agent/bun.lock index 6535adc01..e33408e99 100644 --- a/packages/browseros-agent/bun.lock +++ b/packages/browseros-agent/bun.lock @@ -51,9 +51,9 @@ "@radix-ui/react-use-controllable-state": "^1.2.2", "@sentry/react": "^10.31.0", "@sentry/vite-plugin": "^4.6.1", - "@tanstack/query-async-storage-persister": "^5.90.21", - "@tanstack/react-query": "^5.90.19", - "@tanstack/react-query-persist-client": "^5.90.21", + "@tanstack/query-async-storage-persister": "^5.95.2", + "@tanstack/react-query": "^5.95.2", + "@tanstack/react-query-persist-client": "^5.95.2", "@types/cytoscape": "^3.31.0", "@types/dompurify": "^3.2.0", "@webext-core/messaging": "^2.3.0", @@ -76,8 +76,8 @@ "eventsource-parser": "^3.0.6", "graphql": "^16.12.0", "hono": "^4.12.3", + "idb-keyval": "^6.2.2", "klavis": "^2.15.0", - "localforage": "^1.10.0", "lucide-react": "^0.562.0", "motion": "^12.23.24", "nanoid": "^5.1.6", @@ -1780,15 +1780,15 @@ "@tailwindcss/vite": ["@tailwindcss/vite@4.1.18", "", { "dependencies": { "@tailwindcss/node": "4.1.18", "@tailwindcss/oxide": "4.1.18", "tailwindcss": "4.1.18" }, "peerDependencies": { "vite": "^5.2.0 || ^6 || ^7" } }, "sha512-jVA+/UpKL1vRLg6Hkao5jldawNmRo7mQYrZtNHMIVpLfLhDml5nMRUo/8MwoX2vNXvnaXNNMedrMfMugAVX1nA=="], - "@tanstack/query-async-storage-persister": ["@tanstack/query-async-storage-persister@5.90.21", "", { "dependencies": { "@tanstack/query-core": "5.90.19", "@tanstack/query-persist-client-core": "5.91.18" } }, "sha512-edpZzybucsMxGiWOMy24io+5l4Lciw4bgv/N2EXQnSp0exS1siTOQbCAQET8jwStCEnaoEiS8ljChnfmnd2pkw=="], + "@tanstack/query-async-storage-persister": ["@tanstack/query-async-storage-persister@5.95.2", "", { "dependencies": { "@tanstack/query-core": "5.95.2", "@tanstack/query-persist-client-core": "5.95.2" } }, "sha512-ZhPIHH8J833OVZhEWwwdOk0uhY94d9Wgdnq97JoQx4Ui4xx4Dh6e7WPUrjlUWo88Yqi4Ij+T1o/VR7Vlbnkbjw=="], - "@tanstack/query-core": ["@tanstack/query-core@5.90.19", "", {}, "sha512-GLW5sjPVIvH491VV1ufddnfldyVB+teCnpPIvweEfkpRx7CfUmUGhoh9cdcUKBh/KwVxk22aNEDxeTsvmyB/WA=="], + "@tanstack/query-core": ["@tanstack/query-core@5.95.2", "", {}, "sha512-o4T8vZHZET4Bib3jZ/tCW9/7080urD4c+0/AUaYVpIqOsr7y0reBc1oX3ttNaSW5mYyvZHctiQ/UOP2PfdmFEQ=="], - "@tanstack/query-persist-client-core": ["@tanstack/query-persist-client-core@5.91.18", "", { "dependencies": { "@tanstack/query-core": "5.90.19" } }, "sha512-1FNvccVTFZph07dtA/4p5PRAVKfqVLPPxA8BXUoYjPOZP6T4qY1asItVkUFtUr6kBu48i0DBnEEZQLmK82BIFw=="], + "@tanstack/query-persist-client-core": ["@tanstack/query-persist-client-core@5.95.2", "", { "dependencies": { "@tanstack/query-core": "5.95.2" } }, "sha512-Opfj34WZ594YXpEcZEs8WBiyPGrjrKlGILfk/Ss283uwWQ36C5nX3tRY/bBiXmM82KWauUuNvahwGwiyco/8cQ=="], - "@tanstack/react-query": ["@tanstack/react-query@5.90.19", "", { "dependencies": { "@tanstack/query-core": "5.90.19" }, "peerDependencies": { "react": "^18 || ^19" } }, "sha512-qTZRZ4QyTzQc+M0IzrbKHxSeISUmRB3RPGmao5bT+sI6ayxSRhn0FXEnT5Hg3as8SBFcRosrXXRFB+yAcxVxJQ=="], + "@tanstack/react-query": ["@tanstack/react-query@5.95.2", "", { "dependencies": { "@tanstack/query-core": "5.95.2" }, "peerDependencies": { "react": "^18 || ^19" } }, "sha512-/wGkvLj/st5Ud1Q76KF1uFxScV7WeqN1slQx5280ycwAyYkIPGaRZAEgHxe3bjirSd5Zpwkj6zNcR4cqYni/ZA=="], - "@tanstack/react-query-persist-client": ["@tanstack/react-query-persist-client@5.90.21", "", { "dependencies": { "@tanstack/query-persist-client-core": "5.91.18" }, "peerDependencies": { "@tanstack/react-query": "^5.90.19", "react": "^18 || ^19" } }, "sha512-ix9fVeS96QZxaMPRUwf+k6RlNLJxvu0WSjQp9nPiosxRqquxz0tJ5ErMsclZO9Q/jmVhoFm4FKEZ8mfTLBMoiQ=="], + "@tanstack/react-query-persist-client": ["@tanstack/react-query-persist-client@5.95.2", "", { "dependencies": { "@tanstack/query-persist-client-core": "5.95.2" }, "peerDependencies": { "@tanstack/react-query": "^5.95.2", "react": "^18 || ^19" } }, "sha512-i3fvzD8gaLgQyFvRc/+iSUr60aL31tMN+5QM11zdPRg0K9CirIQjHD7WgXFBnD29KJDvcjcv7OrIBaPwZ+H9xw=="], "@theguild/federation-composition": ["@theguild/federation-composition@0.21.3", "", { "dependencies": { "constant-case": "^3.0.4", "debug": "4.4.3", "json5": "^2.2.3", "lodash.sortby": "^4.7.0" }, "peerDependencies": { "graphql": "^16.0.0" } }, "sha512-+LlHTa4UbRpZBog3ggAxjYIFvdfH3UMvvBUptur19TMWkqU4+n3GmN+mDjejU+dyBXIG27c25RsiQP1HyvM99g=="], @@ -2960,6 +2960,8 @@ "iconv-lite": ["iconv-lite@0.7.2", "", { "dependencies": { "safer-buffer": ">= 2.1.2 < 3.0.0" } }, "sha512-im9DjEDQ55s9fL4EYzOAv0yMqmMBSZp6G0VvFyTMPKWxiSBHUj9NW/qqLmXUwXrrM7AvqSlTCfvqRb0cM8yYqw=="], + "idb-keyval": ["idb-keyval@6.2.2", "", {}, "sha512-yjD9nARJ/jb1g+CvD0tlhUHOrJ9Sy0P8T9MF3YaLlHnSRpwPfpTX0XIvpmw3gAJUmEu3FiICLBDPXVwyEvrleg=="], + "ieee754": ["ieee754@1.2.1", "", {}, "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA=="], "ignore": ["ignore@7.0.5", "", {}, "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg=="], @@ -3186,7 +3188,7 @@ "lib0": ["lib0@0.2.117", "", { "dependencies": { "isomorphic.js": "^0.2.4" }, "bin": { "0serve": "bin/0serve.js", "0gentesthtml": "bin/gentesthtml.js", "0ecdsa-generate-keypair": "bin/0ecdsa-generate-keypair.js" } }, "sha512-DeXj9X5xDCjgKLU/7RR+/HQEVzuuEUiwldwOGsHK/sfAfELGWEyTcf0x+uOvCvK3O2zPmZePXWL85vtia6GyZw=="], - "lie": ["lie@3.1.1", "", { "dependencies": { "immediate": "~3.0.5" } }, "sha512-RiNhHysUjhrDQntfYSfY4MU24coXXdEOgw9WGcKHNeEwffDYbF//u87M1EWaMGzuFoSbqW0C9C6lEEhDOAswfw=="], + "lie": ["lie@3.3.0", "", { "dependencies": { "immediate": "~3.0.5" } }, "sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ=="], "lighthouse-logger": ["lighthouse-logger@2.0.2", "", { "dependencies": { "debug": "^4.4.1", "marky": "^1.2.2" } }, "sha512-vWl2+u5jgOQuZR55Z1WM0XDdrJT6mzMP8zHUct7xTlWhuQs+eV0g+QL0RQdFjT54zVmbhLCP8vIVpy1wGn/gCg=="], @@ -3232,8 +3234,6 @@ "local-pkg": ["local-pkg@1.1.2", "", { "dependencies": { "mlly": "^1.7.4", "pkg-types": "^2.3.0", "quansync": "^0.2.11" } }, "sha512-arhlxbFRmoQHl33a0Zkle/YWlmNwoyt6QNZEIJcqNbdrsix5Lvc4HyyI3EnwxTYlZYc32EbYrQ8SzEZ7dqgg9A=="], - "localforage": ["localforage@1.10.0", "", { "dependencies": { "lie": "3.1.1" } }, "sha512-14/H1aX7hzBBmmh7sGPd+AOMkkIrHM3Z1PAyGgZigA1H1p5O5ANnMyWzvpAETtG68/dC4pC0ncy3+PPGzXZHPg=="], - "locate-path": ["locate-path@6.0.0", "", { "dependencies": { "p-locate": "^5.0.0" } }, "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw=="], "lodash": ["lodash@4.17.23", "", {}, "sha512-LgVTMpQtIopCi79SJeDiP0TfWi5CNEc/L/aRdTh3yIvmZXTnheWpKjSZhnvMl8iXbC1tFg9gdHHDMLoV7CnG+w=="], @@ -4552,7 +4552,7 @@ "@better-auth/core/zod": ["zod@4.3.5", "", {}, "sha512-k7Nwx6vuWx1IJ9Bjuf4Zt1PEllcwe7cls3VNzm4CQ1/hgtFUK2bRNG3rvnpPUhFjmqJKAKtjV576KnUkHocg/g=="], - "@browseros/agent/@types/bun": ["@types/bun@1.3.10", "", { "dependencies": { "bun-types": "1.3.10" } }, "sha512-0+rlrUrOrTSskibryHbvQkDOWRJwJZqZlxrUs1u4oOoTln8+WIXBPmAuCF35SWB2z4Zl3E84Nl/D0P7803nigQ=="], + "@browseros/agent/@types/bun": ["@types/bun@1.3.11", "", { "dependencies": { "bun-types": "1.3.11" } }, "sha512-5vPne5QvtpjGpsGYXiFyycfpDF2ECyPcTSsFBMa0fraoxiQyMJ3SmuQIGhzPg2WJuWxVBoxWJ2kClYTcw/4fAg=="], "@browseros/agent/zod": ["zod@4.3.5", "", {}, "sha512-k7Nwx6vuWx1IJ9Bjuf4Zt1PEllcwe7cls3VNzm4CQ1/hgtFUK2bRNG3rvnpPUhFjmqJKAKtjV576KnUkHocg/g=="], @@ -5104,8 +5104,6 @@ "jest-worker/supports-color": ["supports-color@8.1.1", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q=="], - "jszip/lie": ["lie@3.3.0", "", { "dependencies": { "immediate": "~3.0.5" } }, "sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ=="], - "jszip/readable-stream": ["readable-stream@2.3.8", "", { "dependencies": { "core-util-is": "~1.0.0", "inherits": "~2.0.3", "isarray": "~1.0.0", "process-nextick-args": "~2.0.0", "safe-buffer": "~5.1.1", "string_decoder": "~1.1.1", "util-deprecate": "~1.0.1" } }, "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA=="], "jwa/safe-buffer": ["safe-buffer@5.2.1", "", {}, "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ=="], @@ -5306,7 +5304,7 @@ "@aws-crypto/util/@smithy/util-utf8/@smithy/util-buffer-from": ["@smithy/util-buffer-from@2.2.0", "", { "dependencies": { "@smithy/is-array-buffer": "^2.2.0", "tslib": "^2.6.2" } }, "sha512-IJdWBbTcMQ6DA0gdNhh/BwrLkDR+ADW5Kr1aZmd4k3DIF6ezMV4R2NIAmT08wQJ3yUK82thHWmC/TnK/wpMMIA=="], - "@browseros/agent/@types/bun/bun-types": ["bun-types@1.3.10", "", { "dependencies": { "@types/node": "*" } }, "sha512-tcpfCCl6XWo6nCVnpcVrxQ+9AYN1iqMIzgrSKYMB/fjLtV2eyAVEg7AxQJuCq/26R6HpKWykQXuSOq/21RYcbg=="], + "@browseros/agent/@types/bun/bun-types": ["bun-types@1.3.11", "", { "dependencies": { "@types/node": "*" } }, "sha512-1KGPpoxQWl9f6wcZh57LvrPIInQMn2TQ7jsgxqpRzg+l0QPOFvJVH7HmvHo/AiPgwXy+/Thf6Ov3EdVn1vOabg=="], "@browseros/eval/@aws-sdk/client-s3/@aws-sdk/core": ["@aws-sdk/core@3.973.23", "", { "dependencies": { "@aws-sdk/types": "^3.973.6", "@aws-sdk/xml-builder": "^3.972.15", "@smithy/core": "^3.23.12", "@smithy/node-config-provider": "^4.3.12", "@smithy/property-provider": "^4.2.12", "@smithy/protocol-http": "^5.3.12", "@smithy/signature-v4": "^5.3.12", "@smithy/smithy-client": "^4.12.7", "@smithy/types": "^4.13.1", "@smithy/util-base64": "^4.3.2", "@smithy/util-middleware": "^4.2.12", "@smithy/util-utf8": "^4.2.2", "tslib": "^2.6.2" } }, "sha512-aoJncvD1XvloZ9JLnKqTRL9dBy+Szkryoag9VT+V1TqsuUgIxV9cnBVM/hrDi2vE8bDqLiDR8nirdRcCdtJu0w=="],