Show app version in system settings sidebar (#4044)

* Add version tagging
resolves #4038
closes #4034
closes #4028

* add hook

* add build

* patch
This commit is contained in:
Timothy Carambat 2025-06-24 13:56:12 -07:00 committed by GitHub
parent 1e1694fcd0
commit 64d9fbc8f0
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 89 additions and 4 deletions

View File

@ -6,7 +6,7 @@ concurrency:
on:
push:
branches: ['3982-disable-login-simple-sso'] # put your current branch to create a build. Core team only.
branches: ['4034-version-control'] # put your current branch to create a build. Core team only.
paths-ignore:
- '**.md'
- 'cloud-deployments/*'

View File

@ -1,6 +1,6 @@
{
"name": "anything-llm-document-collector",
"version": "0.2.0",
"version": "1.8.2",
"description": "Document collector server endpoints",
"main": "index.js",
"author": "Timothy Carambat (Mintplex Labs)",

View File

@ -169,6 +169,7 @@ USER anythingllm
# Setup the environment
ENV NODE_ENV=production
ENV ANYTHING_LLM_RUNTIME=docker
ENV DEPLOYMENT_VERSION=1.8.2
# Setup the healthcheck
HEALTHCHECK --interval=1m --timeout=10s --start-period=1m \

View File

@ -22,6 +22,7 @@ import showToast from "@/utils/toast";
import System from "@/models/system";
import Option from "./MenuOption";
import { CanViewChatHistoryProvider } from "../CanViewChatHistory";
import useAppVersion from "@/hooks/useAppVersion";
export default function SettingsSidebar() {
const { t } = useTranslation();
@ -119,6 +120,7 @@ export default function SettingsSidebar() {
>
{t("settings.privacy")}
</Link>
<AppVersion />
</div>
</div>
</div>
@ -169,6 +171,7 @@ export default function SettingsSidebar() {
>
{t("settings.privacy")}
</Link>
<AppVersion />
</div>
</div>
</div>
@ -451,3 +454,18 @@ function HoldToReveal({ children, holdForMs = 3_000 }) {
if (!showing) return null;
return children;
}
function AppVersion() {
const { version, isLoading } = useAppVersion();
if (isLoading) return null;
return (
<Link
to={`https://github.com/Mintplex-Labs/anything-llm/releases/tag/v${version}`}
target="_blank"
rel="noreferrer"
className="text-theme-text-secondary light:opacity-80 opacity-50 text-xs mx-3"
>
v{version}
</Link>
);
}

View File

@ -0,0 +1,20 @@
import { useEffect, useState } from "react";
import System from "../models/system";
/**
* Hook to fetch the app version.
* @returns {Object} The app version.
* @returns {string | null} version - The app version.
* @returns {boolean} isLoading - Whether the app version is loading.
*/
export default function useAppVersion() {
const [version, setVersion] = useState(null);
const [isLoading, setIsLoading] = useState(true);
useEffect(() => {
System.fetchAppVersion()
.then(setVersion)
.finally(() => setIsLoading(false));
}, []);
return { version, isLoading };
}

View File

@ -11,6 +11,7 @@ const System = {
supportEmail: "anythingllm_support_email",
customAppName: "anythingllm_custom_app_name",
canViewChatHistory: "anythingllm_can_view_chat_history",
deploymentVersion: "anythingllm_deployment_version",
},
ping: async function () {
return await fetch(`${API_BASE}/ping`)
@ -742,6 +743,36 @@ const System = {
});
},
/**
* Fetches the app version from the server.
* @returns {Promise<string | null>} The app version.
*/
fetchAppVersion: async function () {
const cache = window.localStorage.getItem(this.cacheKeys.deploymentVersion);
const { version, lastFetched } = cache
? safeJsonParse(cache, { version: null, lastFetched: 0 })
: { version: null, lastFetched: 0 };
if (!!version && Date.now() - lastFetched < 3_600_000) return version;
const newVersion = await fetch(`${API_BASE}/utils/metrics`, {
method: "GET",
cache: "no-cache",
})
.then((res) => {
if (!res.ok) throw new Error("Could not fetch app version.");
return res.json();
})
.then((res) => res?.version)
.catch(() => null);
if (!newVersion) return null;
window.localStorage.setItem(
this.cacheKeys.deploymentVersion,
JSON.stringify({ version: newVersion, lastFetched: Date.now() })
);
return newVersion;
},
experimentalFeatures: {
liveSync: LiveDocumentSync,
agentPlugins: AgentPlugins,

View File

@ -1,6 +1,6 @@
{
"name": "anything-llm",
"version": "0.2.0",
"version": "1.8.2",
"description": "The best solution for turning private documents into a chat bot using off-the-shelf tools and commercially viable AI technologies.",
"main": "index.js",
"type": "module",

View File

@ -13,6 +13,7 @@ function utilEndpoints(app) {
: "single-user",
vectorDB: process.env.VECTOR_DB || "lancedb",
storage: await getDiskStorage(),
version: getDeploymentVersion(),
};
response.status(200).json(metrics);
} catch (e) {
@ -148,6 +149,20 @@ function getModelTag() {
return model;
}
/**
* Returns the deployment version.
* - Dev: reads from package.json
* - Prod: reads from ENV
* expected format: major.minor.patch
* @returns {string|null} The deployment version.
*/
function getDeploymentVersion() {
if (process.env.NODE_ENV === "development")
return require("../../package.json").version;
if (process.env.DEPLOYMENT_VERSION) return process.env.DEPLOYMENT_VERSION;
return null;
}
module.exports = {
utilEndpoints,
getGitVersion,

View File

@ -1,6 +1,6 @@
{
"name": "anything-llm-server",
"version": "0.2.0",
"version": "1.8.2",
"description": "Server endpoints to process or create content for chatting",
"main": "index.js",
"author": "Timothy Carambat (Mintplex Labs)",