Integrate version tracking for DenchClaw and OpenClaw into the telemetry system. The versions are now read from the package.json and environment variables, and are included in the PostHog client initialization and telemetry events. This enhancement allows for better monitoring and analytics of the versions in use.
122 lines
3.3 KiB
TypeScript
122 lines
3.3 KiB
TypeScript
import { createRequire } from "node:module";
|
|
|
|
declare const __OPENCLAW_VERSION__: string | undefined;
|
|
const CORE_PACKAGE_NAME = "denchclaw";
|
|
|
|
const PACKAGE_JSON_CANDIDATES = [
|
|
"../package.json",
|
|
"../../package.json",
|
|
"../../../package.json",
|
|
"./package.json",
|
|
] as const;
|
|
|
|
const BUILD_INFO_CANDIDATES = [
|
|
"../build-info.json",
|
|
"../../build-info.json",
|
|
"./build-info.json",
|
|
] as const;
|
|
|
|
function readVersionFromJsonCandidates(
|
|
moduleUrl: string,
|
|
candidates: readonly string[],
|
|
opts: { requirePackageName?: boolean } = {},
|
|
): string | null {
|
|
try {
|
|
const require = createRequire(moduleUrl);
|
|
for (const candidate of candidates) {
|
|
try {
|
|
const parsed = require(candidate) as { name?: string; version?: string };
|
|
const version = parsed.version?.trim();
|
|
if (!version) {
|
|
continue;
|
|
}
|
|
if (opts.requirePackageName && parsed.name !== CORE_PACKAGE_NAME) {
|
|
continue;
|
|
}
|
|
return version;
|
|
} catch {
|
|
// ignore missing or unreadable candidate
|
|
}
|
|
}
|
|
return null;
|
|
} catch {
|
|
return null;
|
|
}
|
|
}
|
|
|
|
function firstNonEmpty(...values: Array<string | undefined>): string | undefined {
|
|
for (const value of values) {
|
|
const trimmed = value?.trim();
|
|
if (trimmed) {
|
|
return trimmed;
|
|
}
|
|
}
|
|
return undefined;
|
|
}
|
|
|
|
export function readVersionFromPackageJsonForModuleUrl(moduleUrl: string): string | null {
|
|
return readVersionFromJsonCandidates(moduleUrl, PACKAGE_JSON_CANDIDATES, {
|
|
requirePackageName: true,
|
|
});
|
|
}
|
|
|
|
export function readVersionFromBuildInfoForModuleUrl(moduleUrl: string): string | null {
|
|
return readVersionFromJsonCandidates(moduleUrl, BUILD_INFO_CANDIDATES);
|
|
}
|
|
|
|
export function resolveVersionFromModuleUrl(moduleUrl: string): string | null {
|
|
return (
|
|
readVersionFromPackageJsonForModuleUrl(moduleUrl) ||
|
|
readVersionFromBuildInfoForModuleUrl(moduleUrl)
|
|
);
|
|
}
|
|
|
|
export type RuntimeVersionEnv = {
|
|
[key: string]: string | undefined;
|
|
};
|
|
|
|
export function resolveRuntimeServiceVersion(
|
|
env: RuntimeVersionEnv = process.env as RuntimeVersionEnv,
|
|
fallback = "dev",
|
|
): string {
|
|
return (
|
|
firstNonEmpty(
|
|
env["OPENCLAW_VERSION"],
|
|
env["OPENCLAW_SERVICE_VERSION"],
|
|
env["npm_package_version"],
|
|
) ?? fallback
|
|
);
|
|
}
|
|
|
|
// Single source of truth for the current DenchClaw version.
|
|
// - Embedded/bundled builds: injected define or env var.
|
|
// - Dev/npm builds: package.json.
|
|
export const VERSION =
|
|
(typeof __OPENCLAW_VERSION__ === "string" && __OPENCLAW_VERSION__) ||
|
|
process.env.OPENCLAW_BUNDLED_VERSION ||
|
|
resolveVersionFromModuleUrl(import.meta.url) ||
|
|
"0.0.0";
|
|
|
|
let _cachedOpenClawVersion: string | undefined;
|
|
|
|
export function resolveOpenClawVersion(): string | undefined {
|
|
if (_cachedOpenClawVersion !== undefined) return _cachedOpenClawVersion || undefined;
|
|
|
|
const envVersion = (process.env.OPENCLAW_VERSION || process.env.OPENCLAW_SERVICE_VERSION)?.trim();
|
|
if (envVersion) {
|
|
_cachedOpenClawVersion = envVersion;
|
|
return envVersion;
|
|
}
|
|
|
|
try {
|
|
const req = createRequire(import.meta.url);
|
|
const pkg = req("openclaw/package.json") as { version?: string };
|
|
const v = pkg.version?.trim();
|
|
_cachedOpenClawVersion = v || "";
|
|
return v || undefined;
|
|
} catch {
|
|
_cachedOpenClawVersion = "";
|
|
return undefined;
|
|
}
|
|
}
|