feat: serve plugin http and websockets from one mount instead of ports

This commit is contained in:
LukeGus committed 2026-09-22 16:39:41 -05:00
1 parent c496a093ca
commit 8431570ff7
102 files changed
+2894 -2308

No files matched your search

+29 -20
View File
@@ -52,7 +52,7 @@ export interface AiStatus {
export async function getAiStatus(): Promise<AiStatus> {
try {
return (await authApi.get("/ai/status")).data;
return (await authApi.get("/plugin-api/ai/status")).data;
} catch (error) {
throw handleApiError(error, "get AI status");
}
@@ -60,7 +60,7 @@ export async function getAiStatus(): Promise<AiStatus> {
export async function getAiProviders(): Promise<AiProvider[]> {
try {
return (await authApi.get("/ai/providers")).data.providers;
return (await authApi.get("/plugin-api/ai/providers")).data.providers;
} catch (error) {
throw handleApiError(error, "list AI providers");
}
@@ -74,7 +74,8 @@ export async function createAiProvider(input: {
defaultModel?: string | null;
}): Promise<AiProvider> {
try {
return (await authApi.post("/ai/providers", input)).data.provider;
return (await authApi.post("/plugin-api/ai/providers", input)).data
.provider;
} catch (error) {
throw handleApiError(error, "create AI provider");
}
@@ -91,7 +92,8 @@ export async function updateAiProvider(
}>,
): Promise<AiProvider> {
try {
return (await authApi.patch(`/ai/providers/${id}`, input)).data.provider;
return (await authApi.patch(`/plugin-api/ai/providers/${id}`, input)).data
.provider;
} catch (error) {
throw handleApiError(error, "update AI provider");
}
@@ -99,7 +101,7 @@ export async function updateAiProvider(
export async function deleteAiProvider(id: number): Promise<void> {
try {
await authApi.delete(`/ai/providers/${id}`);
await authApi.delete(`/plugin-api/ai/providers/${id}`);
} catch (error) {
throw handleApiError(error, "delete AI provider");
}
@@ -120,7 +122,7 @@ export async function probeAiModels(input: {
warning?: string;
}> {
try {
return (await authApi.post("/ai/probe-models", input)).data;
return (await authApi.post("/plugin-api/ai/probe-models", input)).data;
} catch (error) {
throw handleApiError(error, "detect models");
}
@@ -128,7 +130,8 @@ export async function probeAiModels(input: {
export async function getAiProviderModels(id: number): Promise<string[]> {
try {
return (await authApi.get(`/ai/providers/${id}/models`)).data.models;
return (await authApi.get(`/plugin-api/ai/providers/${id}/models`)).data
.models;
} catch (error) {
throw handleApiError(error, "list provider models");
}
@@ -136,7 +139,8 @@ export async function getAiProviderModels(id: number): Promise<string[]> {
export async function getAiConversations(): Promise<AiConversation[]> {
try {
return (await authApi.get("/ai/conversations")).data.conversations;
return (await authApi.get("/plugin-api/ai/conversations")).data
.conversations;
} catch (error) {
throw handleApiError(error, "list AI conversations");
}
@@ -148,7 +152,7 @@ export async function getAiConversation(id: number): Promise<{
proposals: AiProposal[];
}> {
try {
return (await authApi.get(`/ai/conversations/${id}`)).data;
return (await authApi.get(`/plugin-api/ai/conversations/${id}`)).data;
} catch (error) {
throw handleApiError(error, "load AI conversation");
}
@@ -156,7 +160,7 @@ export async function getAiConversation(id: number): Promise<{
export async function deleteAiConversation(id: number): Promise<void> {
try {
await authApi.delete(`/ai/conversations/${id}`);
await authApi.delete(`/plugin-api/ai/conversations/${id}`);
} catch (error) {
throw handleApiError(error, "delete AI conversation");
}
@@ -166,7 +170,7 @@ export async function applyAiProposal(
id: number,
): Promise<{ success: boolean; summary: string }> {
try {
return (await authApi.post(`/ai/proposals/${id}/apply`)).data;
return (await authApi.post(`/plugin-api/ai/proposals/${id}/apply`)).data;
} catch (error) {
throw handleApiError(error, "apply AI proposal");
}
@@ -174,7 +178,7 @@ export async function applyAiProposal(
export async function rejectAiProposal(id: number): Promise<void> {
try {
await authApi.post(`/ai/proposals/${id}/reject`);
await authApi.post(`/plugin-api/ai/proposals/${id}/reject`);
} catch (error) {
throw handleApiError(error, "reject AI proposal");
}
@@ -191,10 +195,13 @@ export async function markAiProposalRunInTerminal(
): Promise<{ success: boolean; summary: string }> {
try {
return (
await authApi.post(`/ai/proposals/${id}/mark-run-in-terminal`, {
hostId,
summary,
})
await authApi.post(
`/plugin-api/ai/proposals/${id}/mark-run-in-terminal`,
{
hostId,
summary,
},
)
).data;
} catch (error) {
throw handleApiError(error, "mark AI proposal run in terminal");
@@ -205,7 +212,7 @@ export async function markAiProposalRunInTerminal(
export async function getAiGloballyEnabled(): Promise<boolean> {
try {
return (await authApi.get("/ai/enabled")).data.enabled;
return (await authApi.get("/plugin-api/ai/enabled")).data.enabled;
} catch (error) {
throw handleApiError(error, "get AI enabled setting");
}
@@ -213,7 +220,8 @@ export async function getAiGloballyEnabled(): Promise<boolean> {
export async function setAiGloballyEnabled(enabled: boolean): Promise<boolean> {
try {
return (await authApi.patch("/ai/enabled", { enabled })).data.enabled;
return (await authApi.patch("/plugin-api/ai/enabled", { enabled })).data
.enabled;
} catch (error) {
throw handleApiError(error, "update AI enabled setting");
}
@@ -221,7 +229,7 @@ export async function setAiGloballyEnabled(enabled: boolean): Promise<boolean> {
export async function getAiPrivateEndpoints(): Promise<string[]> {
try {
return (await authApi.get("/ai/private-endpoints")).data.hosts;
return (await authApi.get("/plugin-api/ai/private-endpoints")).data.hosts;
} catch (error) {
throw handleApiError(error, "get AI endpoint allowlist");
}
@@ -231,7 +239,8 @@ export async function setAiPrivateEndpoints(
hosts: string[],
): Promise<string[]> {
try {
return (await authApi.patch("/ai/private-endpoints", { hosts })).data.hosts;
return (await authApi.patch("/plugin-api/ai/private-endpoints", { hosts }))
.data.hosts;
} catch (error) {
throw handleApiError(error, "update AI endpoint allowlist");
}
+41 -22
View File
@@ -60,7 +60,7 @@ export type FleetPackageAction = "install" | "remove" | "upgrade-all";
export async function listFleets(): Promise<FleetRow[]> {
try {
const response = await authApi.get("/fleets");
const response = await authApi.get("/plugin-api/fleets");
return response.data;
} catch (error) {
throw handleApiError(error, "fetch fleets");
@@ -75,7 +75,7 @@ export async function createFleet(fleetData: {
tagRules?: string[];
}): Promise<FleetRow> {
try {
const response = await authApi.post("/fleets", fleetData);
const response = await authApi.post("/plugin-api/fleets", fleetData);
return response.data;
} catch (error) {
throw handleApiError(error, "create fleet");
@@ -93,7 +93,10 @@ export async function updateFleet(
},
): Promise<FleetRow> {
try {
const response = await authApi.patch(`/fleets/${fleetId}`, fleetData);
const response = await authApi.patch(
`/plugin-api/fleets/${fleetId}`,
fleetData,
);
return response.data;
} catch (error) {
throw handleApiError(error, "update fleet");
@@ -104,7 +107,7 @@ export async function deleteFleet(
fleetId: number,
): Promise<{ success: boolean }> {
try {
const response = await authApi.delete(`/fleets/${fleetId}`);
const response = await authApi.delete(`/plugin-api/fleets/${fleetId}`);
return response.data;
} catch (error) {
throw handleApiError(error, "delete fleet");
@@ -115,7 +118,7 @@ export async function getFleetMembers(
fleetId: number,
): Promise<FleetMemberRow[]> {
try {
const response = await authApi.get(`/fleets/${fleetId}/members`);
const response = await authApi.get(`/plugin-api/fleets/${fleetId}/members`);
return response.data;
} catch (error) {
throw handleApiError(error, "fetch fleet members");
@@ -127,9 +130,12 @@ export async function addFleetMember(
hostId: number,
): Promise<{ success: boolean }> {
try {
const response = await authApi.post(`/fleets/${fleetId}/members`, {
hostId,
});
const response = await authApi.post(
`/plugin-api/fleets/${fleetId}/members`,
{
hostId,
},
);
return response.data;
} catch (error) {
throw handleApiError(error, "add fleet member");
@@ -142,7 +148,7 @@ export async function removeFleetMember(
): Promise<{ success: boolean }> {
try {
const response = await authApi.delete(
`/fleets/${fleetId}/members/${hostId}`,
`/plugin-api/fleets/${fleetId}/members/${hostId}`,
);
return response.data;
} catch (error) {
@@ -156,10 +162,13 @@ export async function runFleetCommand(
inputValues?: Record<string, string>,
): Promise<{ results: FleetHostResult[] }> {
try {
const response = await authApi.post(`/fleets/${fleetId}/execute`, {
command,
...(inputValues ? { inputValues } : {}),
});
const response = await authApi.post(
`/plugin-api/fleets/${fleetId}/execute`,
{
command,
...(inputValues ? { inputValues } : {}),
},
);
return response.data;
} catch (error) {
throw handleApiError(error, "run fleet command");
@@ -176,7 +185,7 @@ export async function pushFleetFile(
form.append("file", file);
form.append("remotePath", remotePath);
const response = await authApi.post(
`/fleets/${fleetId}/transfer/push`,
`/plugin-api/fleets/${fleetId}/transfer/push`,
form,
{ headers: { "Content-Type": "multipart/form-data" } },
);
@@ -192,7 +201,7 @@ export async function pullFleetFile(
): Promise<{ results: FleetHostResult[]; blob: Blob; fileName: string }> {
try {
const response = await authApi.post(
`/fleets/${fleetId}/transfer/pull`,
`/plugin-api/fleets/${fleetId}/transfer/pull`,
{ remotePath },
{ responseType: "blob" },
);
@@ -217,7 +226,9 @@ export async function getFleetInventory(
fleetId: number,
): Promise<FleetInventoryEntry[]> {
try {
const response = await authApi.get(`/fleets/${fleetId}/inventory`);
const response = await authApi.get(
`/plugin-api/fleets/${fleetId}/inventory`,
);
return response.data;
} catch (error) {
throw handleApiError(error, "fetch fleet inventory");
@@ -228,7 +239,9 @@ export async function refreshFleetInventory(
fleetId: number,
): Promise<{ results: FleetHostResult[] }> {
try {
const response = await authApi.post(`/fleets/${fleetId}/inventory`);
const response = await authApi.post(
`/plugin-api/fleets/${fleetId}/inventory`,
);
return response.data;
} catch (error) {
throw handleApiError(error, "refresh fleet inventory");
@@ -241,10 +254,13 @@ export async function runFleetPackageAction(
packageName?: string,
): Promise<{ results: FleetHostResult[] }> {
try {
const response = await authApi.post(`/fleets/${fleetId}/packages`, {
action,
...(packageName ? { package: packageName } : {}),
});
const response = await authApi.post(
`/plugin-api/fleets/${fleetId}/packages`,
{
action,
...(packageName ? { package: packageName } : {}),
},
);
return response.data;
} catch (error) {
throw handleApiError(error, "run fleet package action");
@@ -273,7 +289,10 @@ export async function shareFleet(
hostResults: FleetShareHostResult[];
}> {
try {
const response = await authApi.post(`/fleets/${fleetId}/share`, shareData);
const response = await authApi.post(
`/plugin-api/fleets/${fleetId}/share`,
shareData,
);
return response.data;
} catch (error) {
throw handleApiError(error, "share fleet");
+4 -2
View File
@@ -102,7 +102,7 @@ export async function executeSnippet(
export async function getNetworkTopology(): Promise<NetworkTopologyData | null> {
try {
const response = await authApi.get("/network-topology/");
const response = await authApi.get("/plugin-api/network-topology/");
return response.data;
} catch (error) {
throw handleApiError(error, "fetch network topology");
@@ -113,7 +113,9 @@ export async function saveNetworkTopology(
topology: NetworkTopologyData,
): Promise<{ success: boolean }> {
try {
const response = await authApi.post("/network-topology/", { topology });
const response = await authApi.post("/plugin-api/network-topology/", {
topology,
});
return response.data;
} catch (error) {
throw handleApiError(error, "save network topology");
+3 -3
View File
@@ -188,7 +188,7 @@ export async function discoverProxmoxGuests(
): Promise<ProxmoxDiscoverResult> {
try {
const response = await authApi.post(
"/proxmox/discover",
"/plugin-api/proxmox/discover",
{ hostId },
{ timeout: 120000 },
);
@@ -208,7 +208,7 @@ export function discoverProxmoxGuestsStream(
): () => void {
const baseURL = (authApi.defaults.baseURL || "").replace(/\/$/, "");
const source = new EventSource(
`${baseURL}/proxmox/discover/stream?hostId=${encodeURIComponent(
`${baseURL}/plugin-api/proxmox/discover/stream?hostId=${encodeURIComponent(
String(hostId),
)}`,
{ withCredentials: true },
@@ -257,7 +257,7 @@ export async function syncProxmoxGuests(
): Promise<ProxmoxSyncResult> {
try {
const response = await authApi.post(
"/proxmox/sync",
"/plugin-api/proxmox/sync",
{ hostId },
{ timeout: 120000 },
);