feat: show token usage

This commit is contained in:
Stephen Zhou 2025-08-27 11:44:04 +08:00
parent 6dea9e8cfe
commit 7cb684d411
No known key found for this signature in database
8 changed files with 240 additions and 95 deletions

View File

@ -11,7 +11,6 @@ import { PanelStyleSection } from "./ai/PanelStyleSection"
import { PersonalizePromptSection } from "./ai/PersonalizePromptSection"
import { AIShortcutsSection } from "./ai/shortcuts/AIShortcutsSection"
import { TaskSchedulingSection } from "./ai/tasks"
import { TokenUsageSection } from "./ai/TokenUsageSection"
const SettingBuilder = createSettingBuilder(useAISettingValue)
const defineSettingItem = createDefineSettingItem(useAISettingValue, setAISetting)
@ -23,11 +22,6 @@ export const SettingAI = () => {
<div className="mt-4">
<SettingBuilder
settings={[
{
type: "title",
value: t("token_usage.title"),
},
TokenUsageSection,
{
type: "title",
value: t("features.title"),

View File

@ -1,73 +0,0 @@
import { Progress } from "@follow/components/ui/progress/index.jsx"
import { useQuery } from "@tanstack/react-query"
import { useTranslation } from "react-i18next"
import { followClient } from "~/lib/api-client"
import { SettingDescription } from "../../control"
const useTokenUsage = () => {
return useQuery({
queryKey: ["aiTokenUsage"],
queryFn: async () => {
return (await followClient.api.ai.config()).usage
},
})
}
export const TokenUsageSection = () => {
const { t } = useTranslation("ai")
const tokenUsage = useTokenUsage().data || {
total: 0,
used: 0,
remaining: 0,
resetAt: new Date(),
}
const usagePercentage = tokenUsage.total === 0 ? 0 : (tokenUsage.used / tokenUsage.total) * 100
const resetDate = new Date(tokenUsage.resetAt)
return (
<div className="space-y-4">
<SettingDescription>{t("token_usage.description")}</SettingDescription>
<div className="bg-material-medium border-border space-y-4 rounded-lg border p-4">
<div className="flex items-center justify-between">
<div className="space-y-1">
<p className="text-text text-sm font-medium">
{t("token_usage.tokens_used", {
used: tokenUsage.used.toLocaleString(),
total: tokenUsage.total.toLocaleString(),
})}
</p>
<p className="text-text-secondary text-xs">
{tokenUsage.remaining.toLocaleString()} {t("token_usage.tokens_remaining")}
</p>
</div>
<div className="text-right">
<div className="text-text text-sm font-medium">{Math.round(usagePercentage)}%</div>
</div>
</div>
<div className="space-y-2">
<Progress value={usagePercentage} className="h-2" />
<div className="text-text-tertiary flex items-center justify-between text-xs">
<span>0</span>
<span>
{t("token_usage.resets_at")}: {resetDate.toLocaleString()}
</span>
<span>{tokenUsage.total.toLocaleString()}</span>
</div>
</div>
<div className="flex items-center gap-2 pt-2">
<div className="bg-accent size-3 rounded-full" />
<span className="text-text-secondary text-xs">Current usage</span>
</div>
</div>
</div>
)
}

View File

@ -1,4 +1,3 @@
export { PanelStyleSection } from "./PanelStyleSection"
export { PersonalizePromptSection } from "./PersonalizePromptSection"
export { AIShortcutsSection } from "./shortcuts"
export { TokenUsageSection } from "./TokenUsageSection"

View File

@ -0,0 +1,200 @@
import { Progress } from "@follow/components/ui/progress/index.jsx"
import {
Table,
TableBody,
TableCell,
TableHead,
TableHeader,
TableRow,
} from "@follow/components/ui/table/index.jsx"
import { cn } from "@follow/utils/utils"
import { useQuery } from "@tanstack/react-query"
import { pick } from "es-toolkit"
import { useMemo } from "react"
import { useTranslation } from "react-i18next"
import { followClient } from "~/lib/api-client"
import { SettingDescription } from "../control"
const useTokenUsage = () => {
return useQuery({
queryKey: ["aiTokenUsage"],
queryFn: async () => {
const res = await followClient.api.ai.config()
return pick(res, ["usage", "usageHistory"])
},
})
}
// Format large numbers with appropriate units
const formatTokenCount = (count: number): { value: string; unit: string } => {
if (count >= 1_000_000) {
return { value: (count / 1_000_000).toFixed(1), unit: "M" }
}
if (count >= 1_000) {
return { value: (count / 1_000).toFixed(1), unit: "K" }
}
return { value: count.toString(), unit: "" }
}
// Format percentage for display
const formatPercentage = (percentage: number): string => {
return percentage < 1 && percentage > 0 ? "<1" : Math.round(percentage).toString()
}
const TokenUsageSection = () => {
const { t } = useTranslation("ai")
const { usage: tokenUsage, usageHistory } = useTokenUsage().data || {
usage: {
total: 0,
used: 0,
remaining: 0,
resetAt: new Date(),
},
usageHistory: [],
}
const usagePercentage = tokenUsage.total === 0 ? 0 : (tokenUsage.used / tokenUsage.total) * 100
const resetDate = useMemo(() => new Date(tokenUsage.resetAt), [tokenUsage.resetAt])
const usedFormatted = useMemo(() => formatTokenCount(tokenUsage.used), [tokenUsage.used])
const totalFormatted = useMemo(() => formatTokenCount(tokenUsage.total), [tokenUsage.total])
const remainingFormatted = useMemo(
() => formatTokenCount(tokenUsage.remaining),
[tokenUsage.remaining],
)
return (
<div className="space-y-6">
<SettingDescription>{t("token_usage.description")}</SettingDescription>
{/* Usage Overview */}
<div className="space-y-6">
{/* Main Usage Display */}
<div className="rounded-lg border border-gray-200 bg-white p-6">
<div className="mb-4 flex items-center justify-between">
<h3 className="text-lg font-medium text-gray-900">Token Usage</h3>
<span className="font-mono text-2xl text-gray-900">
{formatPercentage(usagePercentage)}%
</span>
</div>
<div className="space-y-3">
<Progress value={usagePercentage} className="h-2" />
<div className="flex items-center justify-between text-sm text-gray-600">
<span>
{usedFormatted.value}
{usedFormatted.unit} of {totalFormatted.value}
{totalFormatted.unit} tokens used
</span>
<span>
{remainingFormatted.value}
{remainingFormatted.unit} remaining
</span>
</div>
</div>
</div>
{/* Stats Grid */}
<div className="grid gap-4 md:grid-cols-3">
<div className="rounded-lg border border-gray-200 bg-white p-4">
<div className="text-sm text-gray-600">Used</div>
<div className="mt-1 font-mono text-xl text-gray-900">
{usedFormatted.value}
<span className="text-sm text-gray-500">{usedFormatted.unit}</span>
</div>
</div>
<div className="rounded-lg border border-gray-200 bg-white p-4">
<div className="text-sm text-gray-600">Total</div>
<div className="mt-1 font-mono text-xl text-gray-900">
{totalFormatted.value}
<span className="text-sm text-gray-500">{totalFormatted.unit}</span>
</div>
</div>
<div className="rounded-lg border border-gray-200 bg-white p-4">
<div className="text-sm text-gray-600">Resets</div>
<div className="mt-1 font-mono text-sm text-gray-900">
{resetDate.toLocaleDateString([], {
month: "short",
day: "numeric",
year: resetDate.getFullYear() !== new Date().getFullYear() ? "numeric" : undefined,
})}
</div>
</div>
</div>
</div>
{/* Usage History */}
{usageHistory && usageHistory.length > 0 && (
<div className="rounded-lg border border-gray-200 bg-white">
<div className="border-b border-gray-200 px-6 py-4">
<h3 className="text-lg font-medium text-gray-900">Usage History</h3>
<p className="mt-1 text-sm text-gray-600">Recent token usage activity</p>
</div>
<div className="overflow-hidden">
<Table>
<TableHeader>
<TableRow className="border-gray-200 hover:bg-transparent">
<TableHead className="text-gray-900">Change</TableHead>
<TableHead className="text-gray-900">Description</TableHead>
<TableHead className="text-right text-gray-900">Date</TableHead>
</TableRow>
</TableHeader>
<TableBody>
{usageHistory.map((entry, index) => (
<TableRow key={entry.id || index} className="border-gray-200 hover:bg-gray-50">
<TableCell className="py-3">
<div className="flex items-center gap-3">
<div
className={cn(
"flex size-6 items-center justify-center rounded text-xs font-medium",
entry.changes > 0
? "bg-green-100 text-green-700"
: entry.changes < 0
? "bg-red-100 text-red-700"
: "bg-gray-100 text-gray-700",
)}
>
{entry.changes > 0 ? "+" : entry.changes < 0 ? "" : "="}
</div>
<span className="font-mono text-sm text-gray-900">
{entry.changes > 0
? `+${entry.changes.toLocaleString()}`
: entry.changes.toLocaleString()}
</span>
</div>
</TableCell>
<TableCell className="py-3">
<span className="text-sm text-gray-900">{entry.comment || ""}</span>
</TableCell>
<TableCell className="py-3 text-right">
<span className="font-mono text-sm text-gray-600">
{new Date(entry.createdAt).toLocaleDateString([], {
month: "short",
day: "numeric",
})}
</span>
</TableCell>
</TableRow>
))}
</TableBody>
</Table>
</div>
</div>
)}
</div>
)
}
export const SettingTokenUsage = () => {
return (
<div className="mt-4">
<TokenUsageSection />
</div>
)
}

View File

@ -0,0 +1,24 @@
import { getFeature } from "~/hooks/biz/useFeature"
import { SettingTokenUsage } from "~/modules/settings/tabs/token-usage"
import { SettingsTitle } from "~/modules/settings/title"
import { defineSettingPageData } from "~/modules/settings/utils"
const iconName = "i-mgc-rada-cute-re"
const priority = (1000 << 1) + 16
// eslint-disable-next-line react-refresh/only-export-components
export const loader = defineSettingPageData({
icon: iconName,
name: "titles.token_usage",
priority,
hideIf: () => !getFeature("ai"),
})
export function Component() {
return (
<>
<SettingsTitle />
<SettingTokenUsage />
</>
)
}

View File

@ -669,6 +669,7 @@
"titles.referral.short": "Invite & Earn",
"titles.shortcuts": "Shortcuts",
"titles.sign_out": "Sign Out",
"titles.token_usage": "Token Usage",
"wallet.balance.activePoints": "Active Points",
"wallet.balance.dailyReward": "Your Daily Reward",
"wallet.balance.title": "Your Balance",

View File

@ -7,8 +7,8 @@ settings:
catalogs:
default:
'@follow-app/client-sdk':
specifier: 0.3.46
version: 0.3.46
specifier: 0.3.47
version: 0.3.47
tailwindcss-uikit-colors:
specifier: 1.0.0
version: 1.0.0
@ -465,7 +465,7 @@ importers:
version: 3.0.2(electron@37.2.0)
'@follow-app/client-sdk':
specifier: 'catalog:'
version: 0.3.46(@opentelemetry/api@1.9.0)(@types/pg@8.6.1)(expo-sqlite@15.2.12(expo@53.0.12(@babel/core@7.28.0)(@expo/metro-runtime@5.0.4(react-native@0.79.1(@babel/core@7.28.0)(@types/react@19.1.8)(bufferutil@4.0.9)(react@19.0.0)))(bufferutil@4.0.9)(graphql@16.8.1)(react-native-webview@13.15.0(react-native@0.79.1(@babel/core@7.28.0)(@types/react@19.1.8)(bufferutil@4.0.9)(react@19.0.0))(react@19.0.0))(react-native@0.79.1(@babel/core@7.28.0)(@types/react@19.1.8)(bufferutil@4.0.9)(react@19.0.0))(react@19.0.0))(react-native@0.79.1(@babel/core@7.28.0)(@types/react@19.1.8)(bufferutil@4.0.9)(react@19.0.0))(react@19.0.0))(kysely@0.28.2)(pg@8.16.3)
version: 0.3.47(@opentelemetry/api@1.9.0)(@types/pg@8.6.1)(expo-sqlite@15.2.12(expo@53.0.12(@babel/core@7.28.0)(@expo/metro-runtime@5.0.4(react-native@0.79.1(@babel/core@7.28.0)(@types/react@19.1.8)(bufferutil@4.0.9)(react@19.0.0)))(bufferutil@4.0.9)(graphql@16.8.1)(react-native-webview@13.15.0(react-native@0.79.1(@babel/core@7.28.0)(@types/react@19.1.8)(bufferutil@4.0.9)(react@19.0.0))(react@19.0.0))(react-native@0.79.1(@babel/core@7.28.0)(@types/react@19.1.8)(bufferutil@4.0.9)(react@19.0.0))(react@19.0.0))(react-native@0.79.1(@babel/core@7.28.0)(@types/react@19.1.8)(bufferutil@4.0.9)(react@19.0.0))(react@19.0.0))(kysely@0.28.2)(pg@8.16.3)
'@follow/database':
specifier: workspace:*
version: link:../../../../packages/internal/database
@ -1673,7 +1673,7 @@ importers:
dependencies:
'@follow-app/client-sdk':
specifier: 'catalog:'
version: 0.3.46(@opentelemetry/api@1.9.0)(@types/pg@8.6.1)(expo-sqlite@15.2.12(expo@53.0.12(@babel/core@7.28.0)(@expo/metro-runtime@5.0.4(react-native@0.79.1(@babel/core@7.28.0)(@types/react@19.1.8)(bufferutil@4.0.9)(react@19.0.0)))(bufferutil@4.0.9)(graphql@16.8.1)(react-native-webview@13.15.0(react-native@0.79.1(@babel/core@7.28.0)(@types/react@19.1.8)(bufferutil@4.0.9)(react@19.0.0))(react@19.0.0))(react-native@0.79.1(@babel/core@7.28.0)(@types/react@19.1.8)(bufferutil@4.0.9)(react@19.0.0))(react@19.0.0))(react-native@0.79.1(@babel/core@7.28.0)(@types/react@19.1.8)(bufferutil@4.0.9)(react@19.0.0))(react@19.0.0))(kysely@0.28.2)(pg@8.16.3)
version: 0.3.47(@opentelemetry/api@1.9.0)(@types/pg@8.6.1)(expo-sqlite@15.2.12(expo@53.0.12(@babel/core@7.28.0)(@expo/metro-runtime@5.0.4(react-native@0.79.1(@babel/core@7.28.0)(@types/react@19.1.8)(bufferutil@4.0.9)(react@19.0.0)))(bufferutil@4.0.9)(graphql@16.8.1)(react-native-webview@13.15.0(react-native@0.79.1(@babel/core@7.28.0)(@types/react@19.1.8)(bufferutil@4.0.9)(react@19.0.0))(react@19.0.0))(react-native@0.79.1(@babel/core@7.28.0)(@types/react@19.1.8)(bufferutil@4.0.9)(react@19.0.0))(react@19.0.0))(react-native@0.79.1(@babel/core@7.28.0)(@types/react@19.1.8)(bufferutil@4.0.9)(react@19.0.0))(react@19.0.0))(kysely@0.28.2)(pg@8.16.3)
'@follow/configs':
specifier: workspace:*
version: link:../../configs
@ -1685,7 +1685,7 @@ importers:
dependencies:
'@follow-app/client-sdk':
specifier: 'catalog:'
version: 0.3.46(@opentelemetry/api@1.9.0)(@types/pg@8.6.1)(expo-sqlite@15.2.12(expo@53.0.12(@babel/core@7.28.0)(@expo/metro-runtime@5.0.4(react-native@0.79.1(@babel/core@7.28.0)(@types/react@19.1.8)(bufferutil@4.0.9)(react@19.0.0)))(bufferutil@4.0.9)(graphql@16.8.1)(react-native-webview@13.15.0(react-native@0.79.1(@babel/core@7.28.0)(@types/react@19.1.8)(bufferutil@4.0.9)(react@19.0.0))(react@19.0.0))(react-native@0.79.1(@babel/core@7.28.0)(@types/react@19.1.8)(bufferutil@4.0.9)(react@19.0.0))(react@19.0.0))(react-native@0.79.1(@babel/core@7.28.0)(@types/react@19.1.8)(bufferutil@4.0.9)(react@19.0.0))(react@19.0.0))(kysely@0.28.2)(pg@8.16.3)
version: 0.3.47(@opentelemetry/api@1.9.0)(@types/pg@8.6.1)(expo-sqlite@15.2.12(expo@53.0.12(@babel/core@7.28.0)(@expo/metro-runtime@5.0.4(react-native@0.79.1(@babel/core@7.28.0)(@types/react@19.1.8)(bufferutil@4.0.9)(react@19.0.0)))(bufferutil@4.0.9)(graphql@16.8.1)(react-native-webview@13.15.0(react-native@0.79.1(@babel/core@7.28.0)(@types/react@19.1.8)(bufferutil@4.0.9)(react@19.0.0))(react@19.0.0))(react-native@0.79.1(@babel/core@7.28.0)(@types/react@19.1.8)(bufferutil@4.0.9)(react@19.0.0))(react@19.0.0))(react-native@0.79.1(@babel/core@7.28.0)(@types/react@19.1.8)(bufferutil@4.0.9)(react@19.0.0))(react@19.0.0))(kysely@0.28.2)(pg@8.16.3)
'@follow/constants':
specifier: workspace:*
version: link:../constants
@ -1757,7 +1757,7 @@ importers:
dependencies:
'@follow-app/client-sdk':
specifier: 'catalog:'
version: 0.3.46(@opentelemetry/api@1.9.0)(@types/pg@8.6.1)(expo-sqlite@15.2.12(expo@53.0.12(@babel/core@7.28.0)(@expo/metro-runtime@5.0.4(react-native@0.79.1(@babel/core@7.28.0)(@types/react@19.1.8)(bufferutil@4.0.9)(react@19.0.0)))(bufferutil@4.0.9)(graphql@16.8.1)(react-native-webview@13.15.0(react-native@0.79.1(@babel/core@7.28.0)(@types/react@19.1.8)(bufferutil@4.0.9)(react@19.0.0))(react@19.0.0))(react-native@0.79.1(@babel/core@7.28.0)(@types/react@19.1.8)(bufferutil@4.0.9)(react@19.0.0))(react@19.0.0))(react-native@0.79.1(@babel/core@7.28.0)(@types/react@19.1.8)(bufferutil@4.0.9)(react@19.0.0))(react@19.0.0))(kysely@0.28.2)(pg@8.16.3)
version: 0.3.47(@opentelemetry/api@1.9.0)(@types/pg@8.6.1)(expo-sqlite@15.2.12(expo@53.0.12(@babel/core@7.28.0)(@expo/metro-runtime@5.0.4(react-native@0.79.1(@babel/core@7.28.0)(@types/react@19.1.8)(bufferutil@4.0.9)(react@19.0.0)))(bufferutil@4.0.9)(graphql@16.8.1)(react-native-webview@13.15.0(react-native@0.79.1(@babel/core@7.28.0)(@types/react@19.1.8)(bufferutil@4.0.9)(react@19.0.0))(react@19.0.0))(react-native@0.79.1(@babel/core@7.28.0)(@types/react@19.1.8)(bufferutil@4.0.9)(react@19.0.0))(react@19.0.0))(react-native@0.79.1(@babel/core@7.28.0)(@types/react@19.1.8)(bufferutil@4.0.9)(react@19.0.0))(react@19.0.0))(kysely@0.28.2)(pg@8.16.3)
'@follow/constants':
specifier: workspace:*
version: link:../constants
@ -1821,7 +1821,7 @@ importers:
dependencies:
'@follow-app/client-sdk':
specifier: 'catalog:'
version: 0.3.46(@opentelemetry/api@1.9.0)(@types/pg@8.6.1)(expo-sqlite@15.2.12(expo@53.0.12(@babel/core@7.28.0)(@expo/metro-runtime@5.0.4(react-native@0.79.1(@babel/core@7.28.0)(@types/react@19.1.8)(bufferutil@4.0.9)(react@19.0.0)))(bufferutil@4.0.9)(graphql@16.8.1)(react-native-webview@13.15.0(react-native@0.79.1(@babel/core@7.28.0)(@types/react@19.1.8)(bufferutil@4.0.9)(react@19.0.0))(react@19.0.0))(react-native@0.79.1(@babel/core@7.28.0)(@types/react@19.1.8)(bufferutil@4.0.9)(react@19.0.0))(react@19.0.0))(react-native@0.79.1(@babel/core@7.28.0)(@types/react@19.1.8)(bufferutil@4.0.9)(react@19.0.0))(react@19.0.0))(kysely@0.28.2)(pg@8.16.3)
version: 0.3.47(@opentelemetry/api@1.9.0)(@types/pg@8.6.1)(expo-sqlite@15.2.12(expo@53.0.12(@babel/core@7.28.0)(@expo/metro-runtime@5.0.4(react-native@0.79.1(@babel/core@7.28.0)(@types/react@19.1.8)(bufferutil@4.0.9)(react@19.0.0)))(bufferutil@4.0.9)(graphql@16.8.1)(react-native-webview@13.15.0(react-native@0.79.1(@babel/core@7.28.0)(@types/react@19.1.8)(bufferutil@4.0.9)(react@19.0.0))(react@19.0.0))(react-native@0.79.1(@babel/core@7.28.0)(@types/react@19.1.8)(bufferutil@4.0.9)(react@19.0.0))(react@19.0.0))(react-native@0.79.1(@babel/core@7.28.0)(@types/react@19.1.8)(bufferutil@4.0.9)(react@19.0.0))(react@19.0.0))(kysely@0.28.2)(pg@8.16.3)
'@follow/configs':
specifier: workspace:*
version: link:../../configs
@ -4045,14 +4045,14 @@ packages:
'@floating-ui/utils@0.2.10':
resolution: {integrity: sha512-aGTxbpbg8/b5JfU1HXSrbH3wXZuLPJcNEcZQFMxLs3oSzgtVu6nFPkbbGGUvBcUjKV2YyB9Wxxabo+HEH9tcRQ==}
'@follow-app/client-sdk@0.3.46':
resolution: {integrity: sha512-mk1S3EuWt700E26o0S8OQBLvPqd4adIhQfpr8UKeFRbbaUH/qZGwrPboJ8solq62DKqK7p++H0BoMMnuAc3ctw==}
'@follow-app/client-sdk@0.3.47':
resolution: {integrity: sha512-RyQivFAJOnY5KEkpX5cJ2Z01Spq6sGOD8Btg2lIg4UWvE0gr8dBN8AcfFI7qyLXDg9FlSGZLUuDzEBkdGntVhg==}
'@folo-services/ai-tools@0.2.20':
resolution: {integrity: sha512-1AJI48H2g64JhuTruSqQKUrn4Tc353hMFdKAbohh65AxTAMN/1pIw9w17Dtjm+g5BVlZUXYKaiIvaN9tHsXLNA==}
'@folo-services/constants@0.1.25':
resolution: {integrity: sha512-qRAasMUOsNCIgKpQjtAoBWSm4EuibHJDRK7eWQAGgSb2KaMtMQ/VKiOraLHCNauML25/mkyqL2PIzKhflMCutA==}
'@folo-services/constants@0.1.26':
resolution: {integrity: sha512-Twk3LGC1G3KWMIr1usLnvq2CnojNtRFNs/xzZwtsHhgdXCG0waqm4dlZnnUEqwBsEyoTgxrZLq7mqUB//32VzA==}
'@folo-services/drizzle@0.1.13':
resolution: {integrity: sha512-h6tndGnTLrAmfvxK5XsXGdZaMi2GBmFZBFiBqtabC7Y05A1ZSOaWg/d9f60Ydh586LmVonz5VGrhvzTdn5ukhg==}
@ -18934,9 +18934,9 @@ snapshots:
'@floating-ui/utils@0.2.10': {}
'@follow-app/client-sdk@0.3.46(@opentelemetry/api@1.9.0)(@types/pg@8.6.1)(expo-sqlite@15.2.12(expo@53.0.12(@babel/core@7.28.0)(@expo/metro-runtime@5.0.4(react-native@0.79.1(@babel/core@7.28.0)(@types/react@19.1.8)(bufferutil@4.0.9)(react@19.0.0)))(bufferutil@4.0.9)(graphql@16.8.1)(react-native-webview@13.15.0(react-native@0.79.1(@babel/core@7.28.0)(@types/react@19.1.8)(bufferutil@4.0.9)(react@19.0.0))(react@19.0.0))(react-native@0.79.1(@babel/core@7.28.0)(@types/react@19.1.8)(bufferutil@4.0.9)(react@19.0.0))(react@19.0.0))(react-native@0.79.1(@babel/core@7.28.0)(@types/react@19.1.8)(bufferutil@4.0.9)(react@19.0.0))(react@19.0.0))(kysely@0.28.2)(pg@8.16.3)':
'@follow-app/client-sdk@0.3.47(@opentelemetry/api@1.9.0)(@types/pg@8.6.1)(expo-sqlite@15.2.12(expo@53.0.12(@babel/core@7.28.0)(@expo/metro-runtime@5.0.4(react-native@0.79.1(@babel/core@7.28.0)(@types/react@19.1.8)(bufferutil@4.0.9)(react@19.0.0)))(bufferutil@4.0.9)(graphql@16.8.1)(react-native-webview@13.15.0(react-native@0.79.1(@babel/core@7.28.0)(@types/react@19.1.8)(bufferutil@4.0.9)(react@19.0.0))(react@19.0.0))(react-native@0.79.1(@babel/core@7.28.0)(@types/react@19.1.8)(bufferutil@4.0.9)(react@19.0.0))(react@19.0.0))(react-native@0.79.1(@babel/core@7.28.0)(@types/react@19.1.8)(bufferutil@4.0.9)(react@19.0.0))(react@19.0.0))(kysely@0.28.2)(pg@8.16.3)':
dependencies:
'@folo-services/constants': 0.1.25
'@folo-services/constants': 0.1.26
'@folo-services/drizzle': 0.1.20(@opentelemetry/api@1.9.0)(@types/pg@8.6.1)(expo-sqlite@15.2.12(expo@53.0.12(@babel/core@7.28.0)(@expo/metro-runtime@5.0.4(react-native@0.79.1(@babel/core@7.28.0)(@types/react@19.1.8)(bufferutil@4.0.9)(react@19.0.0)))(bufferutil@4.0.9)(graphql@16.8.1)(react-native-webview@13.15.0(react-native@0.79.1(@babel/core@7.28.0)(@types/react@19.1.8)(bufferutil@4.0.9)(react@19.0.0))(react@19.0.0))(react-native@0.79.1(@babel/core@7.28.0)(@types/react@19.1.8)(bufferutil@4.0.9)(react@19.0.0))(react@19.0.0))(react-native@0.79.1(@babel/core@7.28.0)(@types/react@19.1.8)(bufferutil@4.0.9)(react@19.0.0))(react@19.0.0))(kysely@0.28.2)
'@folo-services/exceptions': 0.1.15
'@folo-services/shared': 0.0.15(@opentelemetry/api@1.9.0)(@types/pg@8.6.1)(expo-sqlite@15.2.12(expo@53.0.12(@babel/core@7.28.0)(@expo/metro-runtime@5.0.4(react-native@0.79.1(@babel/core@7.28.0)(@types/react@19.1.8)(bufferutil@4.0.9)(react@19.0.0)))(bufferutil@4.0.9)(graphql@16.8.1)(react-native-webview@13.15.0(react-native@0.79.1(@babel/core@7.28.0)(@types/react@19.1.8)(bufferutil@4.0.9)(react@19.0.0))(react@19.0.0))(react-native@0.79.1(@babel/core@7.28.0)(@types/react@19.1.8)(bufferutil@4.0.9)(react@19.0.0))(react@19.0.0))(react-native@0.79.1(@babel/core@7.28.0)(@types/react@19.1.8)(bufferutil@4.0.9)(react@19.0.0))(react@19.0.0))(kysely@0.28.2)(pg@8.16.3)
@ -19012,7 +19012,7 @@ snapshots:
- sql.js
- sqlite3
'@folo-services/constants@0.1.25':
'@folo-services/constants@0.1.26':
dependencies:
zod: 3.25.76

View File

@ -9,7 +9,7 @@ packages:
catalog:
typescript: 5.8.3
"@follow-app/client-sdk": 0.3.46
"@follow-app/client-sdk": 0.3.47
tailwindcss-uikit-colors: 1.0.0
onlyBuiltDependencies: