fix(landing): derive platform support from release assets
This commit is contained in:
1 parent
1453a8fa95
commit
f8ed2aa666
6 files changed
+227
-6
No files matched your search
@@ -1,6 +1,7 @@
|
||||
import type { Metadata } from "next";
|
||||
import "./globals.css";
|
||||
import { ThemeProvider } from "../components/theme-provider";
|
||||
import { platformSupportSummary } from "../lib/platform-support";
|
||||
|
||||
const description =
|
||||
"Local-first desktop control plane for autonomous AI companies. Set a goal, let an AI CEO assemble specialists, delegate work, and deliver code, research, content, and operations from your desktop.";
|
||||
@@ -143,7 +144,7 @@ const faqJsonLd = {
|
||||
name: "How do I download AgentCompany?",
|
||||
acceptedAnswer: {
|
||||
"@type": "Answer",
|
||||
text: "Use the download section on the website to choose the installer for your platform. macOS ships as a signed and notarized DMG. Windows and Linux builds are distributed directly from our Cloudflare release host.",
|
||||
text: platformSupportSummary.downloadAnswer,
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -151,7 +152,7 @@ const faqJsonLd = {
|
||||
name: "What platforms does AgentCompany support?",
|
||||
acceptedAnswer: {
|
||||
"@type": "Answer",
|
||||
text: "AgentCompany is available on macOS, Windows, and Linux. It is built with Electron and runs natively on all three platforms with full feature parity.",
|
||||
text: platformSupportSummary.platformAnswer,
|
||||
},
|
||||
},
|
||||
{
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
import { motion } from "framer-motion";
|
||||
import { useState } from "react";
|
||||
import { platformSupportSummary } from "../lib/platform-support";
|
||||
|
||||
const faqs = [
|
||||
{
|
||||
@@ -11,13 +12,11 @@ const faqs = [
|
||||
},
|
||||
{
|
||||
question: "How do I download AgentCompany?",
|
||||
answer:
|
||||
"Use the download section on this page to choose the build that matches your architecture and package format. macOS ships as signed and notarized DMGs, Windows ships as a universal installer covering ARM64, x64, and x86, and Linux ships as AppImage, DEB, and RPM builds from our Cloudflare release host.",
|
||||
answer: platformSupportSummary.downloadAnswer,
|
||||
},
|
||||
{
|
||||
question: "What platforms does AgentCompany support?",
|
||||
answer:
|
||||
"AgentCompany is available on macOS arm64 and x64, Windows ARM64/x64/x86, and Linux x64 and ARM64. It is built with Electron and the desktop feature set stays aligned across all supported targets.",
|
||||
answer: platformSupportSummary.platformAnswer,
|
||||
},
|
||||
{
|
||||
question: "What AI models can AgentCompany use?",
|
||||
|
||||
@@ -1,12 +1,16 @@
|
||||
export type PlatformDownloadAsset = {
|
||||
architectures: ReleaseArchitecture[];
|
||||
id: string;
|
||||
label: string;
|
||||
href: string;
|
||||
note: string;
|
||||
};
|
||||
|
||||
export type ReleaseArchitecture = "arm64" | "x64" | "x86";
|
||||
|
||||
export type PlatformDownload = {
|
||||
id: "macos" | "windows" | "linux";
|
||||
packageDescription: string;
|
||||
title: string;
|
||||
note: string;
|
||||
assets: PlatformDownloadAsset[];
|
||||
@@ -17,16 +21,19 @@ export const releaseVersion = "0.4.174";
|
||||
export const platformDownloads: PlatformDownload[] = [
|
||||
{
|
||||
id: "macos",
|
||||
packageDescription: "signed and notarized DMG builds",
|
||||
title: "macOS",
|
||||
note: "Signed + notarized DMG builds",
|
||||
assets: [
|
||||
{
|
||||
architectures: ["arm64"],
|
||||
id: "macos-arm64-dmg",
|
||||
label: "Apple Silicon DMG",
|
||||
href: "https://pub-a19a3a2c1d2e4fa3a9c120b184024448.r2.dev/AC/AgentCompany-0.4.174-arm64.dmg",
|
||||
note: "arm64",
|
||||
},
|
||||
{
|
||||
architectures: ["x64"],
|
||||
id: "macos-x64-dmg",
|
||||
label: "Intel Mac DMG",
|
||||
href: "https://pub-a19a3a2c1d2e4fa3a9c120b184024448.r2.dev/AC/AgentCompany-0.4.174.dmg",
|
||||
@@ -36,10 +43,12 @@ export const platformDownloads: PlatformDownload[] = [
|
||||
},
|
||||
{
|
||||
id: "windows",
|
||||
packageDescription: "an NSIS installer build",
|
||||
title: "Windows",
|
||||
note: "NSIS installer builds",
|
||||
assets: [
|
||||
{
|
||||
architectures: ["arm64", "x64"],
|
||||
id: "windows-universal-installer",
|
||||
label: "Windows Universal Installer",
|
||||
href: "https://pub-a19a3a2c1d2e4fa3a9c120b184024448.r2.dev/AC/AgentCompany.Setup.0.4.174.exe",
|
||||
@@ -49,40 +58,47 @@ export const platformDownloads: PlatformDownload[] = [
|
||||
},
|
||||
{
|
||||
id: "linux",
|
||||
packageDescription: "AppImage, DEB, and RPM builds",
|
||||
title: "Linux",
|
||||
note: "AppImage, DEB, and RPM builds",
|
||||
assets: [
|
||||
{
|
||||
architectures: ["x64"],
|
||||
id: "linux-x64-appimage",
|
||||
label: "Linux x64 AppImage",
|
||||
href: "https://pub-a19a3a2c1d2e4fa3a9c120b184024448.r2.dev/AC/AgentCompany-0.4.174.AppImage",
|
||||
note: "x64",
|
||||
},
|
||||
{
|
||||
architectures: ["x64"],
|
||||
id: "linux-x64-deb",
|
||||
label: "Linux x64 DEB",
|
||||
href: "https://pub-a19a3a2c1d2e4fa3a9c120b184024448.r2.dev/AC/agent-company_0.4.174_amd64.deb",
|
||||
note: "x64",
|
||||
},
|
||||
{
|
||||
architectures: ["x64"],
|
||||
id: "linux-x64-rpm",
|
||||
label: "Linux x64 RPM",
|
||||
href: "https://pub-a19a3a2c1d2e4fa3a9c120b184024448.r2.dev/AC/agent-company-0.4.174.x86_64.rpm",
|
||||
note: "x64",
|
||||
},
|
||||
{
|
||||
architectures: ["arm64"],
|
||||
id: "linux-arm64-appimage",
|
||||
label: "Linux ARM64 AppImage",
|
||||
href: "https://pub-a19a3a2c1d2e4fa3a9c120b184024448.r2.dev/AC/AgentCompany-0.4.174-arm64.AppImage",
|
||||
note: "arm64",
|
||||
},
|
||||
{
|
||||
architectures: ["arm64"],
|
||||
id: "linux-arm64-deb",
|
||||
label: "Linux ARM64 DEB",
|
||||
href: "https://pub-a19a3a2c1d2e4fa3a9c120b184024448.r2.dev/AC/agent-company_0.4.174_arm64.deb",
|
||||
note: "arm64",
|
||||
},
|
||||
{
|
||||
architectures: ["arm64"],
|
||||
id: "linux-arm64-rpm",
|
||||
label: "Linux ARM64 RPM",
|
||||
href: "https://pub-a19a3a2c1d2e4fa3a9c120b184024448.r2.dev/AC/agent-company-0.4.174.aarch64.rpm",
|
||||
|
||||
@@ -0,0 +1,106 @@
|
||||
import {
|
||||
platformDownloads,
|
||||
type PlatformDownload,
|
||||
type PlatformDownloadAsset,
|
||||
type ReleaseArchitecture,
|
||||
} from "../components/release-links.generated";
|
||||
|
||||
const ARCHITECTURE_ORDER: ReleaseArchitecture[] = ["arm64", "x64", "x86"];
|
||||
|
||||
export type PlatformSupportSummary = {
|
||||
downloadAnswer: string;
|
||||
platformAnswer: string;
|
||||
};
|
||||
|
||||
export const platformSupportSummary = buildPlatformSupportSummary(platformDownloads);
|
||||
|
||||
export function buildPlatformSupportSummary(downloads: PlatformDownload[]): PlatformSupportSummary {
|
||||
const macos = requirePlatform(downloads, "macos");
|
||||
const windows = requirePlatform(downloads, "windows");
|
||||
const linux = requirePlatform(downloads, "linux");
|
||||
|
||||
return {
|
||||
downloadAnswer:
|
||||
`Use the download section on this page to choose the build that matches your architecture and package format. ` +
|
||||
`${formatDownloadSentence(macos)} ${formatDownloadSentence(windows)} ${formatDownloadSentence(linux)}`,
|
||||
platformAnswer:
|
||||
`AgentCompany is available on ${formatAvailability(macos)}, ${formatAvailability(windows)}, ` +
|
||||
`and ${formatAvailability(linux)}. It is built with Electron and the desktop feature set stays aligned across all supported targets.`,
|
||||
};
|
||||
}
|
||||
|
||||
function requirePlatform(downloads: PlatformDownload[], id: PlatformDownload["id"]): PlatformDownload {
|
||||
const platform = downloads.find((download) => download.id === id);
|
||||
if (!platform) {
|
||||
throw new Error(`Missing ${id} release download metadata.`);
|
||||
}
|
||||
return platform;
|
||||
}
|
||||
|
||||
function formatDownloadSentence(download: PlatformDownload): string {
|
||||
const architectures = formatArchitectureList(collectArchitectures(download));
|
||||
|
||||
if (!download.packageDescription.trim()) {
|
||||
throw new Error(`Release platform ${download.id} must include package format copy.`);
|
||||
}
|
||||
|
||||
return `${download.title} ships as ${download.packageDescription} for ${architectures}.`;
|
||||
}
|
||||
|
||||
function formatAvailability(download: PlatformDownload): string {
|
||||
return `${download.title} (${formatArchitectureList(collectArchitectures(download), "comma")})`;
|
||||
}
|
||||
|
||||
function collectArchitectures(download: PlatformDownload): ReleaseArchitecture[] {
|
||||
const architectures = new Set<ReleaseArchitecture>();
|
||||
|
||||
for (const asset of download.assets) {
|
||||
collectAssetArchitectures(download.id, asset).forEach((architecture) => architectures.add(architecture));
|
||||
}
|
||||
|
||||
return [...architectures].sort((left, right) => architectureRank(left) - architectureRank(right));
|
||||
}
|
||||
|
||||
function collectAssetArchitectures(
|
||||
platformId: PlatformDownload["id"],
|
||||
asset: PlatformDownloadAsset,
|
||||
): ReleaseArchitecture[] {
|
||||
if (asset.architectures.length === 0) {
|
||||
throw new Error(`Release asset ${platformId}/${asset.id} must declare at least one architecture.`);
|
||||
}
|
||||
|
||||
for (const architecture of asset.architectures) {
|
||||
if (!isReleaseArchitecture(architecture)) {
|
||||
throw new Error(`Release asset ${platformId}/${asset.id} declares unsupported architecture: ${architecture}`);
|
||||
}
|
||||
}
|
||||
|
||||
return asset.architectures;
|
||||
}
|
||||
|
||||
function isReleaseArchitecture(value: string): value is ReleaseArchitecture {
|
||||
return ARCHITECTURE_ORDER.includes(value as ReleaseArchitecture);
|
||||
}
|
||||
|
||||
function architectureRank(architecture: ReleaseArchitecture): number {
|
||||
return ARCHITECTURE_ORDER.indexOf(architecture);
|
||||
}
|
||||
|
||||
function formatArchitectureList(
|
||||
architectures: ReleaseArchitecture[],
|
||||
style: "and" | "comma" = "and",
|
||||
): string {
|
||||
if (architectures.length === 0) {
|
||||
throw new Error("Release download metadata must include at least one architecture.");
|
||||
}
|
||||
if (style === "comma") {
|
||||
return architectures.join(", ");
|
||||
}
|
||||
if (architectures.length === 1) {
|
||||
return architectures[0];
|
||||
}
|
||||
if (architectures.length === 2) {
|
||||
return `${architectures[0]} and ${architectures[1]}`;
|
||||
}
|
||||
return `${architectures.slice(0, -1).join(", ")}, and ${architectures.at(-1)}`;
|
||||
}
|
||||
@@ -123,14 +123,18 @@ async function main() {
|
||||
]);
|
||||
|
||||
const content = `export type PlatformDownloadAsset = {
|
||||
architectures: ReleaseArchitecture[];
|
||||
id: string;
|
||||
label: string;
|
||||
href: string;
|
||||
note: string;
|
||||
};
|
||||
|
||||
export type ReleaseArchitecture = "arm64" | "x64" | "x86";
|
||||
|
||||
export type PlatformDownload = {
|
||||
id: "macos" | "windows" | "linux";
|
||||
packageDescription: string;
|
||||
title: string;
|
||||
note: string;
|
||||
assets: PlatformDownloadAsset[];
|
||||
@@ -141,16 +145,19 @@ export const releaseVersion = "${version}";
|
||||
export const platformDownloads: PlatformDownload[] = [
|
||||
{
|
||||
id: "macos",
|
||||
packageDescription: "signed and notarized DMG builds",
|
||||
title: "macOS",
|
||||
note: "Signed + notarized DMG builds",
|
||||
assets: [
|
||||
{
|
||||
architectures: ["arm64"],
|
||||
id: "macos-arm64-dmg",
|
||||
label: "Apple Silicon DMG",
|
||||
href: "${urlFor(baseUrl, macArm64Dmg)}",
|
||||
note: "arm64",
|
||||
},
|
||||
{
|
||||
architectures: ["x64"],
|
||||
id: "macos-x64-dmg",
|
||||
label: "Intel Mac DMG",
|
||||
href: "${urlFor(baseUrl, macIntelDmg)}",
|
||||
@@ -160,10 +167,12 @@ export const platformDownloads: PlatformDownload[] = [
|
||||
},
|
||||
{
|
||||
id: "windows",
|
||||
packageDescription: "an NSIS installer build",
|
||||
title: "Windows",
|
||||
note: "NSIS installer builds",
|
||||
assets: [
|
||||
{
|
||||
architectures: ["arm64", "x64"],
|
||||
id: "windows-universal-installer",
|
||||
label: "Windows Universal Installer",
|
||||
href: "${urlFor(baseUrl, windowsUniversalInstaller)}",
|
||||
@@ -173,40 +182,47 @@ export const platformDownloads: PlatformDownload[] = [
|
||||
},
|
||||
{
|
||||
id: "linux",
|
||||
packageDescription: "AppImage, DEB, and RPM builds",
|
||||
title: "Linux",
|
||||
note: "AppImage, DEB, and RPM builds",
|
||||
assets: [
|
||||
{
|
||||
architectures: ["x64"],
|
||||
id: "linux-x64-appimage",
|
||||
label: "Linux x64 AppImage",
|
||||
href: "${urlFor(baseUrl, linuxX64AppImage)}",
|
||||
note: "x64",
|
||||
},
|
||||
{
|
||||
architectures: ["x64"],
|
||||
id: "linux-x64-deb",
|
||||
label: "Linux x64 DEB",
|
||||
href: "${urlFor(baseUrl, linuxX64Deb)}",
|
||||
note: "x64",
|
||||
},
|
||||
{
|
||||
architectures: ["x64"],
|
||||
id: "linux-x64-rpm",
|
||||
label: "Linux x64 RPM",
|
||||
href: "${urlFor(baseUrl, linuxX64Rpm)}",
|
||||
note: "x64",
|
||||
},
|
||||
{
|
||||
architectures: ["arm64"],
|
||||
id: "linux-arm64-appimage",
|
||||
label: "Linux ARM64 AppImage",
|
||||
href: "${urlFor(baseUrl, linuxArm64AppImage)}",
|
||||
note: "arm64",
|
||||
},
|
||||
{
|
||||
architectures: ["arm64"],
|
||||
id: "linux-arm64-deb",
|
||||
label: "Linux ARM64 DEB",
|
||||
href: "${urlFor(baseUrl, linuxArm64Deb)}",
|
||||
note: "arm64",
|
||||
},
|
||||
{
|
||||
architectures: ["arm64"],
|
||||
id: "linux-arm64-rpm",
|
||||
label: "Linux ARM64 RPM",
|
||||
href: "${urlFor(baseUrl, linuxArm64Rpm)}",
|
||||
|
||||
@@ -0,0 +1,83 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { platformDownloads, type PlatformDownload } from "../../landing/components/release-links.generated";
|
||||
import { buildPlatformSupportSummary } from "../../landing/lib/platform-support";
|
||||
|
||||
describe("landing platform support copy", () => {
|
||||
it("derives FAQ support copy from current generated release assets", () => {
|
||||
const summary = buildPlatformSupportSummary(platformDownloads);
|
||||
|
||||
expect(summary.downloadAnswer).toBe(
|
||||
"Use the download section on this page to choose the build that matches your architecture and package format. " +
|
||||
"macOS ships as signed and notarized DMG builds for arm64 and x64. " +
|
||||
"Windows ships as an NSIS installer build for arm64 and x64. " +
|
||||
"Linux ships as AppImage, DEB, and RPM builds for arm64 and x64.",
|
||||
);
|
||||
expect(summary.platformAnswer).toBe(
|
||||
"AgentCompany is available on macOS (arm64, x64), Windows (arm64, x64), " +
|
||||
"and Linux (arm64, x64). It is built with Electron and the desktop feature set stays aligned across all supported targets.",
|
||||
);
|
||||
});
|
||||
|
||||
it("uses structured architectures and platform package notes", () => {
|
||||
const downloads = [
|
||||
platform("macos", "macOS", "PKG builds", "PKG Builds", [["Apple Silicon", ["arm64"], "display-only note"]]),
|
||||
platform("windows", "Windows", "an MSIX build", "MSIX Builds", [["Universal", ["arm64", "x64"], "ARM64 + x64"]]),
|
||||
platform("linux", "Linux", "tarball builds", "Tarball Builds", [["Linux bundle", ["x64"], "x64 (glibc)"]]),
|
||||
];
|
||||
|
||||
const summary = buildPlatformSupportSummary(downloads);
|
||||
|
||||
expect(summary.downloadAnswer).toBe(
|
||||
"Use the download section on this page to choose the build that matches your architecture and package format. " +
|
||||
"macOS ships as PKG builds for arm64. " +
|
||||
"Windows ships as an MSIX build for arm64 and x64. " +
|
||||
"Linux ships as tarball builds for x64.",
|
||||
);
|
||||
expect(summary.platformAnswer).toBe(
|
||||
"AgentCompany is available on macOS (arm64), Windows (arm64, x64), and Linux (x64). " +
|
||||
"It is built with Electron and the desktop feature set stays aligned across all supported targets.",
|
||||
);
|
||||
});
|
||||
|
||||
it("keeps generated asset notes synchronized with structured architectures", () => {
|
||||
for (const platformDownload of platformDownloads) {
|
||||
for (const asset of platformDownload.assets) {
|
||||
expect(asset.note).toBe(asset.architectures.join(" + "));
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
it("fails when generated release assets omit architecture metadata", () => {
|
||||
const downloads = [
|
||||
platform("macos", "macOS", "DMG builds", "DMG Builds", [["Apple Silicon", [], "arm64"]]),
|
||||
platform("windows", "Windows", "an NSIS installer build", "NSIS Builds", [["Universal", ["arm64", "x64"], "arm64 + x64"]]),
|
||||
platform("linux", "Linux", "AppImage builds", "AppImage Builds", [["Linux", ["x64"], "x64"]]),
|
||||
];
|
||||
|
||||
expect(() => buildPlatformSupportSummary(downloads)).toThrow(
|
||||
"Release asset macos/macos-apple-silicon must declare at least one architecture.",
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
function platform(
|
||||
id: PlatformDownload["id"],
|
||||
title: string,
|
||||
packageDescription: string,
|
||||
note: string,
|
||||
assets: Array<[label: string, architectures: PlatformDownload["assets"][number]["architectures"], note: string]>,
|
||||
): PlatformDownload {
|
||||
return {
|
||||
id,
|
||||
packageDescription,
|
||||
title,
|
||||
note,
|
||||
assets: assets.map(([label, architectures, assetNote]) => ({
|
||||
architectures,
|
||||
id: `${id}-${label.toLowerCase().replaceAll(/\s+/g, "-")}`,
|
||||
label,
|
||||
href: `https://download.example/${id}`,
|
||||
note: assetNote,
|
||||
})),
|
||||
};
|
||||
}
|
||||
Reference in new issue
Block a user