feat(plugins): manage saved hosts through client handles

This commit is contained in:
Mohamed Boudra
2026-11-02 05:01:46 +01:00
parent 4992b8d3da
commit 8029f8d5ea
17 changed files with 577 additions and 53 deletions
+43 -14
View File
@@ -3,6 +3,7 @@ import {
useHosts,
usePaseo,
type PluginSurfaceProps,
type PluginHost,
} from "@getpaseo/plugin/client";
import { useCallback, useMemo, useState } from "react";
import { Pressable, Text, View } from "react-native";
@@ -33,27 +34,55 @@ export function Hosts({ theme }: PluginSurfaceProps) {
const listSelected = useCallback(() => {
void list();
}, [list]);
const rows = hosts.map((host) => ({
serverId: host.serverId,
label: host.label,
status: host.status,
onPress() {
void list(host.serverId);
},
}));
return (
<View style={styles.root}>
<Pressable accessibilityRole="button" onPress={listSelected}>
<Text style={styles.text}>List selected host agents</Text>
</Pressable>
{rows.map((host) => (
<Pressable key={host.serverId} accessibilityRole="button" onPress={host.onPress}>
<Text style={styles.text}>
{host.label}: {host.status}
</Text>
</Pressable>
{hosts.map((host) => (
<HostRow key={host.serverId} host={host} color={theme.colors.foreground} list={list} />
))}
<Text style={styles.text}>{result}</Text>
</View>
);
}
function HostRow({
host,
color,
list,
}: {
host: PluginHost;
color: string;
list: (serverId: string) => Promise<void>;
}) {
const style = useMemo(() => ({ color }), [color]);
const rowStyle = useMemo(() => ({ gap: 4 }), []);
const listAgents = useCallback(() => void list(host.serverId), [host, list]);
const update = useCallback(
() => void host.update({ label: `${host.label} (build)`, appearance: { color: "sky" } }),
[host],
);
const open = useCallback(() => host.openSettings(), [host]);
const remove = useCallback(() => void host.remove(), [host]);
return (
<View style={rowStyle}>
<Text style={style}>
{host.label}: {host.status} ·{" "}
{host.connections.map((connection) => connection.uri ?? "via another host").join(", ")}
</Text>
<Pressable accessibilityRole="button" onPress={listAgents}>
<Text style={style}>List agents</Text>
</Pressable>
<Pressable accessibilityRole="button" onPress={update}>
<Text style={style}>Rename and color</Text>
</Pressable>
<Pressable accessibilityRole="button" onPress={open}>
<Text style={style}>Host settings</Text>
</Pressable>
<Pressable accessibilityRole="button" onPress={remove}>
<Text style={style}>Remove host</Text>
</Pressable>
</View>
);
}
+5 -1
View File
@@ -1,5 +1,6 @@
import { useCallback } from "react";
import type { PluginClientContext, PluginSidebarItemProps } from "@getpaseo/plugin/client";
import { observeHosts } from "@getpaseo/plugin/client";
import { SidebarRow } from "@getpaseo/plugin/client/ui";
import { Hosts } from "./client/hosts";
@@ -11,5 +12,8 @@ function HostsItem({ currentScreen, openScreen }: PluginSidebarItemProps) {
export default function contribute(client: PluginClientContext) {
client.addScreen({ id: "main", title: "Host agents", Component: Hosts });
client.addSidebarHeaderItem({ id: "hosts", title: "Host agents", Component: HostsItem });
return () => {};
return observeHosts((hosts) => {
for (const host of hosts)
if (host.authFailureReason) console.log(`${host.label} requires attention`);
});
}
+1 -1
View File
@@ -1 +1 @@
{ "id": "host-agents", "requirements": { "paseo": ">=0.8.0" } }
{ "id": "host-agents", "requirements": { "paseo": ">=0.15.0" } }