fix(web): route Mission Control API calls through orchestrator proxy (#747)
All checks were successful
ci/woodpecker/push/ci Pipeline was successful
All checks were successful
ci/woodpecker/push/ci Pipeline was successful
Co-authored-by: Jason Woltje <jason@diversecanvas.com> Co-committed-by: Jason Woltje <jason@diversecanvas.com>
This commit was merged in pull request #747.
This commit is contained in:
@@ -158,7 +158,9 @@ async function fetchAuditLog(
|
||||
}
|
||||
|
||||
try {
|
||||
return await apiGet<AuditLogResponse>(`/api/mission-control/audit-log?${params.toString()}`);
|
||||
return await apiGet<AuditLogResponse>(
|
||||
`/api/orchestrator/api/mission-control/audit-log?${params.toString()}`
|
||||
);
|
||||
} catch (error) {
|
||||
if (isRateLimitError(error)) {
|
||||
return createEmptyAuditLogResponse(page, "Rate limited - retrying...");
|
||||
|
||||
@@ -59,9 +59,12 @@ describe("BargeInInput", (): void => {
|
||||
await user.click(screen.getByRole("button", { name: "Send" }));
|
||||
|
||||
await waitFor((): void => {
|
||||
expect(mockApiPost).toHaveBeenCalledWith("/api/mission-control/sessions/session-1/inject", {
|
||||
content: "execute plan",
|
||||
});
|
||||
expect(mockApiPost).toHaveBeenCalledWith(
|
||||
"/api/orchestrator/api/mission-control/sessions/session-1/inject",
|
||||
{
|
||||
content: "execute plan",
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
expect(onSent).toHaveBeenCalledTimes(1);
|
||||
@@ -83,12 +86,18 @@ describe("BargeInInput", (): void => {
|
||||
|
||||
const calls = mockApiPost.mock.calls as [string, unknown?][];
|
||||
|
||||
expect(calls[0]).toEqual(["/api/mission-control/sessions/session-2/pause", undefined]);
|
||||
expect(calls[0]).toEqual([
|
||||
"/api/orchestrator/api/mission-control/sessions/session-2/pause",
|
||||
undefined,
|
||||
]);
|
||||
expect(calls[1]).toEqual([
|
||||
"/api/mission-control/sessions/session-2/inject",
|
||||
"/api/orchestrator/api/mission-control/sessions/session-2/inject",
|
||||
{ content: "hello world" },
|
||||
]);
|
||||
expect(calls[2]).toEqual(["/api/mission-control/sessions/session-2/resume", undefined]);
|
||||
expect(calls[2]).toEqual([
|
||||
"/api/orchestrator/api/mission-control/sessions/session-2/resume",
|
||||
undefined,
|
||||
]);
|
||||
});
|
||||
|
||||
it("submits with Enter and does not submit on Shift+Enter", async (): Promise<void> => {
|
||||
@@ -105,9 +114,12 @@ describe("BargeInInput", (): void => {
|
||||
fireEvent.keyDown(textarea, { key: "Enter", code: "Enter", shiftKey: false });
|
||||
|
||||
await waitFor((): void => {
|
||||
expect(mockApiPost).toHaveBeenCalledWith("/api/mission-control/sessions/session-3/inject", {
|
||||
content: "first",
|
||||
});
|
||||
expect(mockApiPost).toHaveBeenCalledWith(
|
||||
"/api/orchestrator/api/mission-control/sessions/session-3/inject",
|
||||
{
|
||||
content: "first",
|
||||
}
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -39,7 +39,7 @@ export function BargeInInput({ sessionId, onSent }: BargeInInputProps): React.JS
|
||||
}
|
||||
|
||||
const encodedSessionId = encodeURIComponent(sessionId);
|
||||
const baseEndpoint = `/api/mission-control/sessions/${encodedSessionId}`;
|
||||
const baseEndpoint = `/api/orchestrator/api/mission-control/sessions/${encodedSessionId}`;
|
||||
let didPause = false;
|
||||
let didInject = false;
|
||||
|
||||
|
||||
@@ -177,9 +177,12 @@ describe("GlobalAgentRoster", (): void => {
|
||||
fireEvent.click(screen.getByRole("button", { name: "Kill session killme12" }));
|
||||
|
||||
await waitFor((): void => {
|
||||
expect(mockApiPost).toHaveBeenCalledWith("/api/mission-control/sessions/killme123456/kill", {
|
||||
force: false,
|
||||
});
|
||||
expect(mockApiPost).toHaveBeenCalledWith(
|
||||
"/api/orchestrator/api/mission-control/sessions/killme123456/kill",
|
||||
{
|
||||
force: false,
|
||||
}
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -83,7 +83,7 @@ function groupByProvider(sessions: MissionControlSession[]): ProviderSessionGrou
|
||||
|
||||
async function fetchSessions(): Promise<MissionControlSession[]> {
|
||||
const payload = await apiGet<MissionControlSession[] | SessionsPayload>(
|
||||
"/api/mission-control/sessions"
|
||||
"/api/orchestrator/api/mission-control/sessions"
|
||||
);
|
||||
return Array.isArray(payload) ? payload : payload.sessions;
|
||||
}
|
||||
@@ -118,9 +118,12 @@ export function GlobalAgentRoster({
|
||||
|
||||
const killMutation = useMutation({
|
||||
mutationFn: async (sessionId: string): Promise<string> => {
|
||||
await apiPost<{ message: string }>(`/api/mission-control/sessions/${sessionId}/kill`, {
|
||||
force: false,
|
||||
});
|
||||
await apiPost<{ message: string }>(
|
||||
`/api/orchestrator/api/mission-control/sessions/${sessionId}/kill`,
|
||||
{
|
||||
force: false,
|
||||
}
|
||||
);
|
||||
return sessionId;
|
||||
},
|
||||
onSuccess: (): void => {
|
||||
|
||||
@@ -112,14 +112,20 @@ describe("KillAllDialog", (): void => {
|
||||
await user.click(screen.getByRole("button", { name: "Kill All Agents" }));
|
||||
|
||||
await waitFor((): void => {
|
||||
expect(mockApiPost).toHaveBeenCalledWith("/api/mission-control/sessions/internal-1/kill", {
|
||||
force: true,
|
||||
});
|
||||
expect(mockApiPost).toHaveBeenCalledWith(
|
||||
"/api/orchestrator/api/mission-control/sessions/internal-1/kill",
|
||||
{
|
||||
force: true,
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
expect(mockApiPost).not.toHaveBeenCalledWith("/api/mission-control/sessions/external-1/kill", {
|
||||
force: true,
|
||||
});
|
||||
expect(mockApiPost).not.toHaveBeenCalledWith(
|
||||
"/api/orchestrator/api/mission-control/sessions/external-1/kill",
|
||||
{
|
||||
force: true,
|
||||
}
|
||||
);
|
||||
expect(onComplete).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
@@ -141,12 +147,18 @@ describe("KillAllDialog", (): void => {
|
||||
await user.click(screen.getByRole("button", { name: "Kill All Agents" }));
|
||||
|
||||
await waitFor((): void => {
|
||||
expect(mockApiPost).toHaveBeenCalledWith("/api/mission-control/sessions/internal-2/kill", {
|
||||
force: true,
|
||||
});
|
||||
expect(mockApiPost).toHaveBeenCalledWith("/api/mission-control/sessions/external-2/kill", {
|
||||
force: true,
|
||||
});
|
||||
expect(mockApiPost).toHaveBeenCalledWith(
|
||||
"/api/orchestrator/api/mission-control/sessions/internal-2/kill",
|
||||
{
|
||||
force: true,
|
||||
}
|
||||
);
|
||||
expect(mockApiPost).toHaveBeenCalledWith(
|
||||
"/api/orchestrator/api/mission-control/sessions/external-2/kill",
|
||||
{
|
||||
force: true,
|
||||
}
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -96,9 +96,12 @@ export function KillAllDialog({ sessions, onComplete }: KillAllDialogProps): Rea
|
||||
|
||||
const killRequests = targetSessions.map(async (session) => {
|
||||
try {
|
||||
await apiPost<{ message: string }>(`/api/mission-control/sessions/${session.id}/kill`, {
|
||||
force: true,
|
||||
});
|
||||
await apiPost<{ message: string }>(
|
||||
`/api/orchestrator/api/mission-control/sessions/${session.id}/kill`,
|
||||
{
|
||||
force: true,
|
||||
}
|
||||
);
|
||||
return true;
|
||||
} catch {
|
||||
return false;
|
||||
|
||||
@@ -89,7 +89,7 @@ describe("PanelControls", (): void => {
|
||||
|
||||
await waitFor((): void => {
|
||||
expect(mockApiPost).toHaveBeenCalledWith(
|
||||
"/api/mission-control/sessions/session%20with%20space/pause",
|
||||
"/api/orchestrator/api/mission-control/sessions/session%20with%20space/pause",
|
||||
undefined
|
||||
);
|
||||
});
|
||||
@@ -114,9 +114,12 @@ describe("PanelControls", (): void => {
|
||||
await user.click(screen.getByRole("button", { name: "Confirm" }));
|
||||
|
||||
await waitFor((): void => {
|
||||
expect(mockApiPost).toHaveBeenCalledWith("/api/mission-control/sessions/session-4/kill", {
|
||||
force: false,
|
||||
});
|
||||
expect(mockApiPost).toHaveBeenCalledWith(
|
||||
"/api/orchestrator/api/mission-control/sessions/session-4/kill",
|
||||
{
|
||||
force: false,
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
expect(onStatusChange).toHaveBeenCalledWith("killed");
|
||||
@@ -137,9 +140,12 @@ describe("PanelControls", (): void => {
|
||||
await user.click(screen.getByRole("button", { name: "Confirm" }));
|
||||
|
||||
await waitFor((): void => {
|
||||
expect(mockApiPost).toHaveBeenCalledWith("/api/mission-control/sessions/session-5/kill", {
|
||||
force: true,
|
||||
});
|
||||
expect(mockApiPost).toHaveBeenCalledWith(
|
||||
"/api/orchestrator/api/mission-control/sessions/session-5/kill",
|
||||
{
|
||||
force: true,
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
expect(onStatusChange).toHaveBeenCalledWith("killed");
|
||||
|
||||
@@ -50,23 +50,23 @@ export function PanelControls({
|
||||
switch (action) {
|
||||
case "pause":
|
||||
await apiPost<{ message: string }>(
|
||||
`/api/mission-control/sessions/${encodeURIComponent(sessionId)}/pause`
|
||||
`/api/orchestrator/api/mission-control/sessions/${encodeURIComponent(sessionId)}/pause`
|
||||
);
|
||||
return { nextStatus: "paused" };
|
||||
case "resume":
|
||||
await apiPost<{ message: string }>(
|
||||
`/api/mission-control/sessions/${encodeURIComponent(sessionId)}/resume`
|
||||
`/api/orchestrator/api/mission-control/sessions/${encodeURIComponent(sessionId)}/resume`
|
||||
);
|
||||
return { nextStatus: "active" };
|
||||
case "graceful-kill":
|
||||
await apiPost<{ message: string }>(
|
||||
`/api/mission-control/sessions/${encodeURIComponent(sessionId)}/kill`,
|
||||
`/api/orchestrator/api/mission-control/sessions/${encodeURIComponent(sessionId)}/kill`,
|
||||
{ force: false }
|
||||
);
|
||||
return { nextStatus: "killed" };
|
||||
case "force-kill":
|
||||
await apiPost<{ message: string }>(
|
||||
`/api/mission-control/sessions/${encodeURIComponent(sessionId)}/kill`,
|
||||
`/api/orchestrator/api/mission-control/sessions/${encodeURIComponent(sessionId)}/kill`,
|
||||
{ force: true }
|
||||
);
|
||||
return { nextStatus: "killed" };
|
||||
|
||||
Reference in New Issue
Block a user