mirror of
https://github.com/getpaseo/paseo.git
synced 2026-07-29 12:01:31 +00:00
Support per-arch desktop builds and prune runtime artifacts
This commit is contained in:
13
.github/workflows/desktop-release.yml
vendored
13
.github/workflows/desktop-release.yml
vendored
@@ -21,10 +21,17 @@ env:
|
|||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
publish-macos:
|
publish-macos:
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
include:
|
||||||
|
- runner: macos-14
|
||||||
|
rust_target: aarch64-apple-darwin
|
||||||
|
- runner: macos-13
|
||||||
|
rust_target: x86_64-apple-darwin
|
||||||
permissions:
|
permissions:
|
||||||
contents: write
|
contents: write
|
||||||
packages: read
|
packages: read
|
||||||
runs-on: macos-latest
|
runs-on: ${{ matrix.runner }}
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
@@ -43,7 +50,7 @@ jobs:
|
|||||||
- name: Install Rust stable
|
- name: Install Rust stable
|
||||||
uses: dtolnay/rust-toolchain@stable
|
uses: dtolnay/rust-toolchain@stable
|
||||||
with:
|
with:
|
||||||
targets: aarch64-apple-darwin,x86_64-apple-darwin
|
targets: ${{ matrix.rust_target }}
|
||||||
|
|
||||||
- name: Install JS dependencies
|
- name: Install JS dependencies
|
||||||
run: npm ci
|
run: npm ci
|
||||||
@@ -111,7 +118,7 @@ jobs:
|
|||||||
releaseBody: See the assets to download and install this version.
|
releaseBody: See the assets to download and install this version.
|
||||||
releaseDraft: false
|
releaseDraft: false
|
||||||
prerelease: false
|
prerelease: false
|
||||||
args: --target universal-apple-darwin
|
args: --target ${{ matrix.rust_target }}
|
||||||
|
|
||||||
publish-linux:
|
publish-linux:
|
||||||
permissions:
|
permissions:
|
||||||
|
|||||||
@@ -1,12 +1,14 @@
|
|||||||
import { useCallback, useEffect, useState } from "react";
|
import { useCallback, useEffect, useState } from "react";
|
||||||
import { ActivityIndicator, Alert, Image, Text, View } from "react-native";
|
import { ActivityIndicator, Alert, Image, Pressable, Text, View } from "react-native";
|
||||||
import * as Clipboard from "expo-clipboard";
|
import * as Clipboard from "expo-clipboard";
|
||||||
import * as QRCode from "qrcode";
|
import * as QRCode from "qrcode";
|
||||||
import { useFocusEffect } from "@react-navigation/native";
|
import { useFocusEffect } from "@react-navigation/native";
|
||||||
import { StyleSheet } from "react-native-unistyles";
|
import { StyleSheet } from "react-native-unistyles";
|
||||||
import { AdaptiveModalSheet, AdaptiveTextInput } from "@/components/adaptive-modal-sheet";
|
import { ArrowUpRight } from "lucide-react-native";
|
||||||
|
import { AdaptiveModalSheet } from "@/components/adaptive-modal-sheet";
|
||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/ui/button";
|
||||||
import { confirmDialog } from "@/utils/confirm-dialog";
|
import { confirmDialog } from "@/utils/confirm-dialog";
|
||||||
|
import { openExternalUrl } from "@/utils/open-external-url";
|
||||||
import {
|
import {
|
||||||
formatVersionWithPrefix,
|
formatVersionWithPrefix,
|
||||||
isVersionMismatch,
|
isVersionMismatch,
|
||||||
@@ -19,7 +21,6 @@ import {
|
|||||||
restartManagedDaemon,
|
restartManagedDaemon,
|
||||||
shouldUseManagedDesktopDaemon,
|
shouldUseManagedDesktopDaemon,
|
||||||
uninstallManagedCliShim,
|
uninstallManagedCliShim,
|
||||||
updateManagedDaemonTcpSettings,
|
|
||||||
type ManagedDaemonLogs,
|
type ManagedDaemonLogs,
|
||||||
type ManagedPairingOffer,
|
type ManagedPairingOffer,
|
||||||
type ManagedDaemonStatus,
|
type ManagedDaemonStatus,
|
||||||
@@ -36,11 +37,9 @@ export function LocalDaemonSection({ appVersion }: LocalDaemonSectionProps) {
|
|||||||
const [statusError, setStatusError] = useState<string | null>(null);
|
const [statusError, setStatusError] = useState<string | null>(null);
|
||||||
const [isRestartingDaemon, setIsRestartingDaemon] = useState(false);
|
const [isRestartingDaemon, setIsRestartingDaemon] = useState(false);
|
||||||
const [isInstallingCli, setIsInstallingCli] = useState(false);
|
const [isInstallingCli, setIsInstallingCli] = useState(false);
|
||||||
const [isSavingTcpSettings, setIsSavingTcpSettings] = useState(false);
|
|
||||||
const [statusMessage, setStatusMessage] = useState<string | null>(null);
|
const [statusMessage, setStatusMessage] = useState<string | null>(null);
|
||||||
const [cliStatusMessage, setCliStatusMessage] = useState<string | null>(null);
|
const [cliStatusMessage, setCliStatusMessage] = useState<string | null>(null);
|
||||||
const [managedLogs, setManagedLogs] = useState<ManagedDaemonLogs | null>(null);
|
const [managedLogs, setManagedLogs] = useState<ManagedDaemonLogs | null>(null);
|
||||||
const [isTcpModalOpen, setIsTcpModalOpen] = useState(false);
|
|
||||||
const [isLogsModalOpen, setIsLogsModalOpen] = useState(false);
|
const [isLogsModalOpen, setIsLogsModalOpen] = useState(false);
|
||||||
const [isPairingModalOpen, setIsPairingModalOpen] = useState(false);
|
const [isPairingModalOpen, setIsPairingModalOpen] = useState(false);
|
||||||
const [isCliInstallModalOpen, setIsCliInstallModalOpen] = useState(false);
|
const [isCliInstallModalOpen, setIsCliInstallModalOpen] = useState(false);
|
||||||
@@ -50,8 +49,6 @@ export function LocalDaemonSection({ appVersion }: LocalDaemonSectionProps) {
|
|||||||
null
|
null
|
||||||
);
|
);
|
||||||
const [pairingStatusMessage, setPairingStatusMessage] = useState<string | null>(null);
|
const [pairingStatusMessage, setPairingStatusMessage] = useState<string | null>(null);
|
||||||
const [tcpHostInput, setTcpHostInput] = useState(DEFAULT_TCP_HOST);
|
|
||||||
const [tcpPortInput, setTcpPortInput] = useState(String(DEFAULT_TCP_PORT));
|
|
||||||
|
|
||||||
const loadManagedStatus = useCallback(() => {
|
const loadManagedStatus = useCallback(() => {
|
||||||
if (!showSection) {
|
if (!showSection) {
|
||||||
@@ -62,9 +59,6 @@ export function LocalDaemonSection({ appVersion }: LocalDaemonSectionProps) {
|
|||||||
setManagedStatus(status);
|
setManagedStatus(status);
|
||||||
setManagedLogs(logs);
|
setManagedLogs(logs);
|
||||||
setStatusError(null);
|
setStatusError(null);
|
||||||
const [tcpHost, tcpPort] = splitTcpListen(status.tcpListen);
|
|
||||||
setTcpHostInput(tcpHost);
|
|
||||||
setTcpPortInput(tcpPort);
|
|
||||||
})
|
})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
const message = error instanceof Error ? error.message : String(error);
|
const message = error instanceof Error ? error.message : String(error);
|
||||||
@@ -85,12 +79,7 @@ export function LocalDaemonSection({ appVersion }: LocalDaemonSectionProps) {
|
|||||||
const localDaemonVersionText = formatVersionWithPrefix(managedStatus?.runtimeVersion ?? null);
|
const localDaemonVersionText = formatVersionWithPrefix(managedStatus?.runtimeVersion ?? null);
|
||||||
const daemonVersionMismatch = isVersionMismatch(appVersion, managedStatus?.runtimeVersion ?? null);
|
const daemonVersionMismatch = isVersionMismatch(appVersion, managedStatus?.runtimeVersion ?? null);
|
||||||
const daemonVersionHint =
|
const daemonVersionHint =
|
||||||
statusError ??
|
statusError ?? (managedStatus?.daemonRunning ? "Running." : "Not running.");
|
||||||
(managedStatus?.daemonRunning
|
|
||||||
? managedStatus.transportType === "tcp"
|
|
||||||
? `Running on ${managedStatus.transportPath}.`
|
|
||||||
: "Running."
|
|
||||||
: "Not running.");
|
|
||||||
|
|
||||||
const handleUpdateLocalDaemon = useCallback(() => {
|
const handleUpdateLocalDaemon = useCallback(() => {
|
||||||
if (!showSection) {
|
if (!showSection) {
|
||||||
@@ -246,101 +235,23 @@ export function LocalDaemonSection({ appVersion }: LocalDaemonSectionProps) {
|
|||||||
});
|
});
|
||||||
}, [pairingOffer?.url]);
|
}, [pairingOffer?.url]);
|
||||||
|
|
||||||
const handleOpenTcpModal = useCallback(() => {
|
|
||||||
if (!managedStatus) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const [tcpHost, tcpPort] = splitTcpListen(managedStatus.tcpListen);
|
|
||||||
setTcpHostInput(tcpHost);
|
|
||||||
setTcpPortInput(tcpPort);
|
|
||||||
setIsTcpModalOpen(true);
|
|
||||||
}, [managedStatus]);
|
|
||||||
|
|
||||||
const handleDisableTcp = useCallback(() => {
|
|
||||||
if (isSavingTcpSettings) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
setIsSavingTcpSettings(true);
|
|
||||||
setStatusMessage(null);
|
|
||||||
void updateManagedDaemonTcpSettings({
|
|
||||||
enabled: false,
|
|
||||||
host: tcpHostInput.trim() || DEFAULT_TCP_HOST,
|
|
||||||
port: parseTcpPort(tcpPortInput) ?? DEFAULT_TCP_PORT,
|
|
||||||
})
|
|
||||||
.then((status) => {
|
|
||||||
setManagedStatus(status);
|
|
||||||
setStatusMessage("Network access disabled.");
|
|
||||||
return loadManagedStatus();
|
|
||||||
})
|
|
||||||
.catch((error) => {
|
|
||||||
const message = error instanceof Error ? error.message : String(error);
|
|
||||||
setStatusMessage(`Failed to update: ${message}`);
|
|
||||||
})
|
|
||||||
.finally(() => {
|
|
||||||
setIsSavingTcpSettings(false);
|
|
||||||
});
|
|
||||||
}, [isSavingTcpSettings, loadManagedStatus, tcpHostInput, tcpPortInput]);
|
|
||||||
|
|
||||||
const handleSaveTcp = useCallback(() => {
|
|
||||||
if (isSavingTcpSettings) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const host = tcpHostInput.trim();
|
|
||||||
const port = parseTcpPort(tcpPortInput);
|
|
||||||
if (!host) {
|
|
||||||
Alert.alert("Host required", "Enter a TCP bind host.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (port == null || port <= 0) {
|
|
||||||
Alert.alert("Port required", "Enter a valid TCP port.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (port === 6767) {
|
|
||||||
Alert.alert("Port unavailable", "Port 6767 is reserved. Choose a different port.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
void confirmDialog({
|
|
||||||
title: "Enable network access",
|
|
||||||
message:
|
|
||||||
"This makes the daemon reachable on your local network. Relay connections will continue to work.",
|
|
||||||
confirmLabel: "Enable",
|
|
||||||
cancelLabel: "Cancel",
|
|
||||||
})
|
|
||||||
.then((confirmed) => {
|
|
||||||
if (!confirmed) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
setIsSavingTcpSettings(true);
|
|
||||||
setStatusMessage(null);
|
|
||||||
void updateManagedDaemonTcpSettings({ enabled: true, host, port })
|
|
||||||
.then((status) => {
|
|
||||||
setManagedStatus(status);
|
|
||||||
setIsTcpModalOpen(false);
|
|
||||||
setStatusMessage(`Network access enabled on ${host}:${port}.`);
|
|
||||||
return loadManagedStatus();
|
|
||||||
})
|
|
||||||
.catch((error) => {
|
|
||||||
const message = error instanceof Error ? error.message : String(error);
|
|
||||||
setStatusMessage(`Failed to update: ${message}`);
|
|
||||||
})
|
|
||||||
.finally(() => {
|
|
||||||
setIsSavingTcpSettings(false);
|
|
||||||
});
|
|
||||||
})
|
|
||||||
.catch((error) => {
|
|
||||||
console.error("[Settings] Failed to open TCP confirmation", error);
|
|
||||||
Alert.alert("Error", "Unable to open the confirmation dialog.");
|
|
||||||
});
|
|
||||||
}, [isSavingTcpSettings, loadManagedStatus, tcpHostInput, tcpPortInput]);
|
|
||||||
|
|
||||||
if (!showSection) {
|
if (!showSection) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View style={styles.section}>
|
<View style={styles.section}>
|
||||||
<Text style={styles.sectionTitle}>Built-in daemon</Text>
|
<View style={styles.sectionHeader}>
|
||||||
|
<Text style={styles.sectionTitle}>Built-in daemon</Text>
|
||||||
|
<Pressable
|
||||||
|
accessibilityRole="link"
|
||||||
|
onPress={() => void openExternalUrl(ADVANCED_DAEMON_SETTINGS_URL)}
|
||||||
|
style={styles.sectionLink}
|
||||||
|
>
|
||||||
|
<Text style={styles.sectionLinkText}>Advanced settings</Text>
|
||||||
|
<ArrowUpRight size={14} color={styles.sectionLinkText.color} />
|
||||||
|
</Pressable>
|
||||||
|
</View>
|
||||||
<View style={styles.card}>
|
<View style={styles.card}>
|
||||||
<View style={styles.row}>
|
<View style={styles.row}>
|
||||||
<View style={styles.rowContent}>
|
<View style={styles.rowContent}>
|
||||||
@@ -352,9 +263,7 @@ export function LocalDaemonSection({ appVersion }: LocalDaemonSectionProps) {
|
|||||||
<View style={[styles.row, styles.rowBorder]}>
|
<View style={[styles.row, styles.rowBorder]}>
|
||||||
<View style={styles.rowContent}>
|
<View style={styles.rowContent}>
|
||||||
<Text style={styles.rowTitle}>Restart daemon</Text>
|
<Text style={styles.rowTitle}>Restart daemon</Text>
|
||||||
<Text style={styles.hintText}>
|
<Text style={styles.hintText}>Restarts the built-in daemon.</Text>
|
||||||
Restarts the built-in daemon. Your data and external connections are not affected.
|
|
||||||
</Text>
|
|
||||||
{statusMessage ? (
|
{statusMessage ? (
|
||||||
<Text style={styles.statusText}>{statusMessage}</Text>
|
<Text style={styles.statusText}>{statusMessage}</Text>
|
||||||
) : null}
|
) : null}
|
||||||
@@ -425,39 +334,6 @@ export function LocalDaemonSection({ appVersion }: LocalDaemonSectionProps) {
|
|||||||
Pair device
|
Pair device
|
||||||
</Button>
|
</Button>
|
||||||
</View>
|
</View>
|
||||||
<View style={[styles.row, styles.rowBorder]}>
|
|
||||||
<View style={styles.rowContent}>
|
|
||||||
<Text style={styles.rowTitle}>Network access</Text>
|
|
||||||
<Text style={styles.hintText}>
|
|
||||||
Allow other apps or devices on your network to connect directly.
|
|
||||||
</Text>
|
|
||||||
<Text style={styles.statusText}>
|
|
||||||
{managedStatus?.tcpEnabled
|
|
||||||
? `Enabled on ${managedStatus.tcpListen ?? managedStatus.transportPath}`
|
|
||||||
: "Disabled"}
|
|
||||||
</Text>
|
|
||||||
</View>
|
|
||||||
<View style={styles.actionGroup}>
|
|
||||||
{managedStatus?.tcpEnabled ? (
|
|
||||||
<Button
|
|
||||||
variant="secondary"
|
|
||||||
size="sm"
|
|
||||||
onPress={handleDisableTcp}
|
|
||||||
disabled={isSavingTcpSettings}
|
|
||||||
>
|
|
||||||
{isSavingTcpSettings ? "Working..." : "Disable TCP"}
|
|
||||||
</Button>
|
|
||||||
) : null}
|
|
||||||
<Button
|
|
||||||
variant="secondary"
|
|
||||||
size="sm"
|
|
||||||
onPress={handleOpenTcpModal}
|
|
||||||
disabled={isSavingTcpSettings}
|
|
||||||
>
|
|
||||||
{managedStatus?.tcpEnabled ? "Edit TCP" : "Enable TCP"}
|
|
||||||
</Button>
|
|
||||||
</View>
|
|
||||||
</View>
|
|
||||||
</View>
|
</View>
|
||||||
|
|
||||||
{daemonVersionMismatch ? (
|
{daemonVersionMismatch ? (
|
||||||
@@ -469,44 +345,6 @@ export function LocalDaemonSection({ appVersion }: LocalDaemonSectionProps) {
|
|||||||
</View>
|
</View>
|
||||||
) : null}
|
) : null}
|
||||||
|
|
||||||
<AdaptiveModalSheet
|
|
||||||
visible={isTcpModalOpen}
|
|
||||||
onClose={() => setIsTcpModalOpen(false)}
|
|
||||||
title="Network access"
|
|
||||||
>
|
|
||||||
<View style={styles.modalBody}>
|
|
||||||
<Text style={styles.hintText}>
|
|
||||||
Expose the daemon on a specific address and port so other apps can connect directly.
|
|
||||||
Port 6767 is reserved and cannot be used here.
|
|
||||||
</Text>
|
|
||||||
<AdaptiveTextInput
|
|
||||||
value={tcpHostInput}
|
|
||||||
onChangeText={setTcpHostInput}
|
|
||||||
autoCapitalize="none"
|
|
||||||
autoCorrect={false}
|
|
||||||
placeholder="127.0.0.1"
|
|
||||||
style={styles.input}
|
|
||||||
/>
|
|
||||||
<AdaptiveTextInput
|
|
||||||
value={tcpPortInput}
|
|
||||||
onChangeText={setTcpPortInput}
|
|
||||||
autoCapitalize="none"
|
|
||||||
autoCorrect={false}
|
|
||||||
keyboardType="number-pad"
|
|
||||||
placeholder={String(DEFAULT_TCP_PORT)}
|
|
||||||
style={styles.input}
|
|
||||||
/>
|
|
||||||
<View style={styles.modalActions}>
|
|
||||||
<Button variant="secondary" size="sm" onPress={() => setIsTcpModalOpen(false)}>
|
|
||||||
Cancel
|
|
||||||
</Button>
|
|
||||||
<Button size="sm" onPress={handleSaveTcp} disabled={isSavingTcpSettings}>
|
|
||||||
{isSavingTcpSettings ? "Saving..." : "Save"}
|
|
||||||
</Button>
|
|
||||||
</View>
|
|
||||||
</View>
|
|
||||||
</AdaptiveModalSheet>
|
|
||||||
|
|
||||||
<AdaptiveModalSheet
|
<AdaptiveModalSheet
|
||||||
visible={isCliInstallModalOpen}
|
visible={isCliInstallModalOpen}
|
||||||
onClose={() => setIsCliInstallModalOpen(false)}
|
onClose={() => setIsCliInstallModalOpen(false)}
|
||||||
@@ -571,21 +409,7 @@ export function LocalDaemonSection({ appVersion }: LocalDaemonSectionProps) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const DEFAULT_TCP_HOST = "127.0.0.1";
|
const ADVANCED_DAEMON_SETTINGS_URL = "https://paseo.sh/docs/configuration";
|
||||||
const DEFAULT_TCP_PORT = 7771;
|
|
||||||
|
|
||||||
function splitTcpListen(value: string | null): [string, string] {
|
|
||||||
if (!value) {
|
|
||||||
return [DEFAULT_TCP_HOST, String(DEFAULT_TCP_PORT)];
|
|
||||||
}
|
|
||||||
const [host, port] = value.split(":");
|
|
||||||
return [host || DEFAULT_TCP_HOST, port || String(DEFAULT_TCP_PORT)];
|
|
||||||
}
|
|
||||||
|
|
||||||
function parseTcpPort(value: string): number | null {
|
|
||||||
const parsed = Number.parseInt(value.trim(), 10);
|
|
||||||
return Number.isFinite(parsed) ? parsed : null;
|
|
||||||
}
|
|
||||||
|
|
||||||
function PairingOfferDialogContent(input: {
|
function PairingOfferDialogContent(input: {
|
||||||
isLoading: boolean;
|
isLoading: boolean;
|
||||||
@@ -690,12 +514,26 @@ const styles = StyleSheet.create((theme) => ({
|
|||||||
section: {
|
section: {
|
||||||
marginBottom: theme.spacing[6],
|
marginBottom: theme.spacing[6],
|
||||||
},
|
},
|
||||||
|
sectionHeader: {
|
||||||
|
alignItems: "center",
|
||||||
|
flexDirection: "row",
|
||||||
|
justifyContent: "space-between",
|
||||||
|
marginBottom: theme.spacing[3],
|
||||||
|
marginLeft: theme.spacing[1],
|
||||||
|
},
|
||||||
sectionTitle: {
|
sectionTitle: {
|
||||||
color: theme.colors.foregroundMuted,
|
color: theme.colors.foregroundMuted,
|
||||||
fontSize: theme.fontSize.xs,
|
fontSize: theme.fontSize.xs,
|
||||||
fontWeight: theme.fontWeight.normal,
|
fontWeight: theme.fontWeight.normal,
|
||||||
marginBottom: theme.spacing[3],
|
},
|
||||||
marginLeft: theme.spacing[1],
|
sectionLink: {
|
||||||
|
alignItems: "center",
|
||||||
|
flexDirection: "row",
|
||||||
|
gap: theme.spacing[1],
|
||||||
|
},
|
||||||
|
sectionLinkText: {
|
||||||
|
color: theme.colors.foregroundMuted,
|
||||||
|
fontSize: theme.fontSize.xs,
|
||||||
},
|
},
|
||||||
card: {
|
card: {
|
||||||
backgroundColor: theme.colors.surface2,
|
backgroundColor: theme.colors.surface2,
|
||||||
@@ -807,15 +645,6 @@ const styles = StyleSheet.create((theme) => ({
|
|||||||
backgroundColor: theme.colors.surface0,
|
backgroundColor: theme.colors.surface0,
|
||||||
padding: theme.spacing[3],
|
padding: theme.spacing[3],
|
||||||
},
|
},
|
||||||
input: {
|
|
||||||
borderWidth: 1,
|
|
||||||
borderColor: theme.colors.border,
|
|
||||||
borderRadius: theme.borderRadius.md,
|
|
||||||
color: theme.colors.foreground,
|
|
||||||
backgroundColor: theme.colors.surface1,
|
|
||||||
paddingHorizontal: theme.spacing[3],
|
|
||||||
paddingVertical: theme.spacing[3],
|
|
||||||
},
|
|
||||||
modalActions: {
|
modalActions: {
|
||||||
flexDirection: "row",
|
flexDirection: "row",
|
||||||
justifyContent: "flex-end",
|
justifyContent: "flex-end",
|
||||||
|
|||||||
@@ -20,6 +20,21 @@ const workspaces = [
|
|||||||
{ name: "@getpaseo/cli", root: path.join(repoRoot, "packages", "cli") },
|
{ name: "@getpaseo/cli", root: path.join(repoRoot, "packages", "cli") },
|
||||||
];
|
];
|
||||||
|
|
||||||
|
const ripgrepPlatformDirMap = {
|
||||||
|
darwin: {
|
||||||
|
arm64: "arm64-darwin",
|
||||||
|
x64: "x64-darwin",
|
||||||
|
},
|
||||||
|
linux: {
|
||||||
|
arm64: "arm64-linux",
|
||||||
|
x64: "x64-linux",
|
||||||
|
},
|
||||||
|
win32: {
|
||||||
|
arm64: "arm64-win32",
|
||||||
|
x64: "x64-win32",
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
async function rmSafe(target) {
|
async function rmSafe(target) {
|
||||||
await fs.rm(target, { recursive: true, force: true });
|
await fs.rm(target, { recursive: true, force: true });
|
||||||
}
|
}
|
||||||
@@ -50,6 +65,12 @@ async function pathExists(target) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function removeIfExists(target) {
|
||||||
|
if (await pathExists(target)) {
|
||||||
|
await rmSafe(target);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async function readToolVersions() {
|
async function readToolVersions() {
|
||||||
const raw = await fs.readFile(path.join(repoRoot, ".tool-versions"), "utf8");
|
const raw = await fs.readFile(path.join(repoRoot, ".tool-versions"), "utf8");
|
||||||
const entries = new Map();
|
const entries = new Map();
|
||||||
@@ -284,6 +305,92 @@ async function writeRuntimePackageJson(runtimeRoot) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function pruneChildrenExcept(parent, keepNames) {
|
||||||
|
if (!(await pathExists(parent))) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const entries = await fs.readdir(parent);
|
||||||
|
await Promise.all(
|
||||||
|
entries
|
||||||
|
.filter((entry) => !keepNames.has(entry))
|
||||||
|
.map((entry) => rmSafe(path.join(parent, entry)))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function pruneNodeDistribution(runtimeRoot) {
|
||||||
|
const nodeRoot = path.join(runtimeRoot, "node");
|
||||||
|
await Promise.all([
|
||||||
|
removeIfExists(path.join(nodeRoot, "include")),
|
||||||
|
removeIfExists(path.join(nodeRoot, "share")),
|
||||||
|
removeIfExists(path.join(nodeRoot, "CHANGELOG.md")),
|
||||||
|
]);
|
||||||
|
|
||||||
|
const nodeGlobalModulesRoot = path.join(nodeRoot, "lib", "node_modules");
|
||||||
|
if (await pathExists(nodeGlobalModulesRoot)) {
|
||||||
|
const keepNames = new Set(["npm"]);
|
||||||
|
await pruneChildrenExcept(nodeGlobalModulesRoot, keepNames);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function pruneOnnxRuntime(runtimeRoot) {
|
||||||
|
const onnxRoot = path.join(runtimeRoot, "node_modules", "onnxruntime-node", "bin", "napi-v6");
|
||||||
|
if (!(await pathExists(onnxRoot))) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (process.platform === "darwin") {
|
||||||
|
await removeIfExists(path.join(onnxRoot, "linux"));
|
||||||
|
await removeIfExists(path.join(onnxRoot, "win32"));
|
||||||
|
await pruneChildrenExcept(path.join(onnxRoot, "darwin"), new Set([process.arch]));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (process.platform === "linux") {
|
||||||
|
await removeIfExists(path.join(onnxRoot, "darwin"));
|
||||||
|
await removeIfExists(path.join(onnxRoot, "win32"));
|
||||||
|
await pruneChildrenExcept(path.join(onnxRoot, "linux"), new Set([process.arch]));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (process.platform === "win32") {
|
||||||
|
await removeIfExists(path.join(onnxRoot, "darwin"));
|
||||||
|
await removeIfExists(path.join(onnxRoot, "linux"));
|
||||||
|
await pruneChildrenExcept(path.join(onnxRoot, "win32"), new Set([process.arch]));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function pruneNodePty(runtimeRoot) {
|
||||||
|
const prebuildsRoot = path.join(runtimeRoot, "node_modules", "node-pty", "prebuilds");
|
||||||
|
const keepName = `${process.platform}-${process.arch}`;
|
||||||
|
await pruneChildrenExcept(prebuildsRoot, new Set([keepName]));
|
||||||
|
|
||||||
|
if (process.platform !== "win32") {
|
||||||
|
await removeIfExists(path.join(runtimeRoot, "node_modules", "node-pty", "third_party"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function pruneClaudeAgentSdk(runtimeRoot) {
|
||||||
|
const ripgrepRoot = path.join(
|
||||||
|
runtimeRoot,
|
||||||
|
"node_modules",
|
||||||
|
"@anthropic-ai",
|
||||||
|
"claude-agent-sdk",
|
||||||
|
"vendor",
|
||||||
|
"ripgrep"
|
||||||
|
);
|
||||||
|
const keepName = ripgrepPlatformDirMap[process.platform]?.[process.arch];
|
||||||
|
if (keepName) {
|
||||||
|
await pruneChildrenExcept(ripgrepRoot, new Set(["COPYING", keepName]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function pruneManagedRuntime(runtimeRoot) {
|
||||||
|
await Promise.all([
|
||||||
|
pruneNodeDistribution(runtimeRoot),
|
||||||
|
pruneOnnxRuntime(runtimeRoot),
|
||||||
|
pruneNodePty(runtimeRoot),
|
||||||
|
pruneClaudeAgentSdk(runtimeRoot),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
async function main() {
|
async function main() {
|
||||||
await ensureWorkspaceBuilds();
|
await ensureWorkspaceBuilds();
|
||||||
|
|
||||||
@@ -322,6 +429,7 @@ async function main() {
|
|||||||
path.join(runtimeRoot, "node"),
|
path.join(runtimeRoot, "node"),
|
||||||
tarballs.map((entry) => entry.path)
|
tarballs.map((entry) => entry.path)
|
||||||
);
|
);
|
||||||
|
await pruneManagedRuntime(runtimeRoot);
|
||||||
|
|
||||||
const nodeRelativePath = process.platform === "win32"
|
const nodeRelativePath = process.platform === "win32"
|
||||||
? path.join("node", "node.exe")
|
? path.join("node", "node.exe")
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import websitePackage from '../../package.json'
|
|||||||
import '~/styles.css'
|
import '~/styles.css'
|
||||||
|
|
||||||
const desktopVersion = websitePackage.version
|
const desktopVersion = websitePackage.version
|
||||||
const macDownloadHref = `https://github.com/getpaseo/paseo/releases/download/v${desktopVersion}/Paseo_${desktopVersion}_universal.dmg`
|
const macDownloadHref = `https://github.com/getpaseo/paseo/releases/download/v${desktopVersion}/Paseo_${desktopVersion}_aarch64.dmg`
|
||||||
|
|
||||||
export const Route = createFileRoute('/')({
|
export const Route = createFileRoute('/')({
|
||||||
head: () => ({
|
head: () => ({
|
||||||
|
|||||||
Reference in New Issue
Block a user