mirror of
https://github.com/getpaseo/paseo.git
synced 2026-07-29 12:01:31 +00:00
Add daemon MCP injection toggle to settings
This commit is contained in:
71
packages/app/src/hooks/use-daemon-config.ts
Normal file
71
packages/app/src/hooks/use-daemon-config.ts
Normal file
@@ -0,0 +1,71 @@
|
||||
import { useCallback, useEffect, useMemo } from "react";
|
||||
import { useQuery, useQueryClient } from "@tanstack/react-query";
|
||||
import type {
|
||||
MutableDaemonConfig,
|
||||
MutableDaemonConfigPatch,
|
||||
} from "@server/shared/messages";
|
||||
import { useHostRuntimeClient, useHostRuntimeIsConnected } from "@/runtime/host-runtime";
|
||||
|
||||
export function daemonConfigQueryKey(serverId: string | null) {
|
||||
return ["daemon-config", serverId] as const;
|
||||
}
|
||||
|
||||
interface UseDaemonConfigResult {
|
||||
config: MutableDaemonConfig | null;
|
||||
isLoading: boolean;
|
||||
patchConfig: (patch: MutableDaemonConfigPatch) => Promise<MutableDaemonConfig | undefined>;
|
||||
}
|
||||
|
||||
export function useDaemonConfig(serverId: string | null): UseDaemonConfigResult {
|
||||
const queryClient = useQueryClient();
|
||||
const client = useHostRuntimeClient(serverId ?? "");
|
||||
const isConnected = useHostRuntimeIsConnected(serverId ?? "");
|
||||
const queryKey = useMemo(() => daemonConfigQueryKey(serverId), [serverId]);
|
||||
|
||||
const configQuery = useQuery({
|
||||
queryKey,
|
||||
enabled: Boolean(serverId && client && isConnected),
|
||||
staleTime: Infinity,
|
||||
queryFn: async () => {
|
||||
if (!client) {
|
||||
throw new Error("Host is not connected");
|
||||
}
|
||||
const result = await client.getDaemonConfig();
|
||||
return result.config;
|
||||
},
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
if (!client || !isConnected || !serverId) {
|
||||
return;
|
||||
}
|
||||
|
||||
return client.on("status", (message) => {
|
||||
if (message.type !== "status") {
|
||||
return;
|
||||
}
|
||||
if (message.payload.status !== "daemon_config_changed") {
|
||||
return;
|
||||
}
|
||||
queryClient.setQueryData(queryKey, message.payload.config as MutableDaemonConfig);
|
||||
});
|
||||
}, [client, isConnected, queryClient, queryKey, serverId]);
|
||||
|
||||
const patchConfig = useCallback(
|
||||
async (patch: MutableDaemonConfigPatch) => {
|
||||
if (!client) {
|
||||
return undefined;
|
||||
}
|
||||
const result = await client.patchDaemonConfig(patch);
|
||||
queryClient.setQueryData(queryKey, result.config);
|
||||
return result.config;
|
||||
},
|
||||
[client, queryClient, queryKey],
|
||||
);
|
||||
|
||||
return {
|
||||
config: configQuery.data ?? null,
|
||||
isLoading: configQuery.isLoading,
|
||||
patchConfig,
|
||||
};
|
||||
}
|
||||
@@ -65,6 +65,7 @@ import { settingsStyles } from "@/styles/settings";
|
||||
import { THINKING_TONE_NATIVE_PCM_BASE64 } from "@/utils/thinking-tone.native-pcm";
|
||||
import { useVoiceAudioEngineOptional } from "@/contexts/voice-context";
|
||||
import { useIsLocalDaemon } from "@/hooks/use-is-local-daemon";
|
||||
import { useDaemonConfig } from "@/hooks/use-daemon-config";
|
||||
import { useProvidersSnapshot } from "@/hooks/use-providers-snapshot";
|
||||
import { useIsCompactFormFactor } from "@/constants/layout";
|
||||
import { AGENT_PROVIDER_DEFINITIONS } from "@server/server/agent/provider-manifest";
|
||||
@@ -360,6 +361,7 @@ function HostsSection(props: HostsSectionProps) {
|
||||
}
|
||||
|
||||
interface GeneralSectionProps {
|
||||
routeServerId: string;
|
||||
settings: AppSettings;
|
||||
handleThemeChange: (theme: AppSettings["theme"]) => void;
|
||||
handleSendBehaviorChange: (behavior: SendBehavior) => void;
|
||||
@@ -404,11 +406,14 @@ const THEME_LABELS: Record<AppSettings["theme"], string> = {
|
||||
};
|
||||
|
||||
function GeneralSection({
|
||||
routeServerId,
|
||||
settings,
|
||||
handleThemeChange,
|
||||
handleSendBehaviorChange,
|
||||
}: GeneralSectionProps) {
|
||||
const { theme } = useUnistyles();
|
||||
const isConnected = useHostRuntimeIsConnected(routeServerId);
|
||||
const { config, patchConfig } = useDaemonConfig(routeServerId);
|
||||
const iconSize = theme.iconSize.md;
|
||||
const iconColor = theme.colors.foregroundMuted;
|
||||
|
||||
@@ -475,6 +480,31 @@ function GeneralSection({
|
||||
]}
|
||||
/>
|
||||
</View>
|
||||
{routeServerId.length > 0 && isConnected ? (
|
||||
<View style={[styles.audioRow, styles.audioRowBorder]}>
|
||||
<View style={styles.audioRowContent}>
|
||||
<Text style={styles.audioRowTitle}>Inject Paseo tools</Text>
|
||||
<Text style={styles.audioRowSubtitle}>
|
||||
Automatically inject Paseo MCP tools into new agents
|
||||
</Text>
|
||||
</View>
|
||||
<SegmentedControl
|
||||
size="sm"
|
||||
value={config?.mcp.injectIntoAgents === false ? "off" : "on"}
|
||||
onValueChange={(value) => {
|
||||
void patchConfig({
|
||||
mcp: {
|
||||
injectIntoAgents: value === "on",
|
||||
},
|
||||
});
|
||||
}}
|
||||
options={[
|
||||
{ value: "on", label: "On" },
|
||||
{ value: "off", label: "Off" },
|
||||
]}
|
||||
/>
|
||||
</View>
|
||||
) : null}
|
||||
</View>
|
||||
</View>
|
||||
);
|
||||
@@ -1107,6 +1137,7 @@ export default function SettingsScreen() {
|
||||
};
|
||||
|
||||
const generalProps: GeneralSectionProps = {
|
||||
routeServerId,
|
||||
settings,
|
||||
handleThemeChange,
|
||||
handleSendBehaviorChange,
|
||||
|
||||
Reference in New Issue
Block a user