c795f8f873
Backend: - Create ToolInstance model with status tracking - Add Alembic migration for tool_instances table - Create Docker service for compose template rendering and container execution - Add CRUD API endpoints for tool instances - Add lifecycle endpoints (start/stop/restart) - Add user sessions endpoint for navigation - Register routers in main.py Frontend: - Create SessionsProvider with React context - Create sessions API client - Update AppShell with sessions section in navigation - Add session status indicators and polling - Add CSS for session navigation Quality gates: typecheck ✓, lint ✓, build ✓
98 lines
2.3 KiB
TypeScript
98 lines
2.3 KiB
TypeScript
import { apiClient } from "./client";
|
|
|
|
export interface ToolInstance {
|
|
id: string;
|
|
name: string;
|
|
display_name: string;
|
|
tool_type_id: string;
|
|
status: string;
|
|
url: string | null;
|
|
port: number | null;
|
|
created_at: string;
|
|
}
|
|
|
|
export interface Session {
|
|
id: string;
|
|
display_name: string;
|
|
tool_type_name: string;
|
|
tool_icon: string;
|
|
repository_name: string;
|
|
project_name: string;
|
|
status: string;
|
|
url: string | null;
|
|
}
|
|
|
|
export async function listInstances(
|
|
projectId: string,
|
|
repoId: string
|
|
): Promise<ToolInstance[]> {
|
|
const response = await apiClient.get(
|
|
`/projects/${projectId}/repositories/${repoId}/instances`
|
|
);
|
|
return response.data.instances;
|
|
}
|
|
|
|
export async function createInstance(
|
|
projectId: string,
|
|
repoId: string,
|
|
toolTypeId: string,
|
|
displayName?: string
|
|
): Promise<ToolInstance> {
|
|
const response = await apiClient.post(
|
|
`/projects/${projectId}/repositories/${repoId}/instances`,
|
|
{
|
|
tool_type_id: toolTypeId,
|
|
display_name: displayName,
|
|
}
|
|
);
|
|
return response.data;
|
|
}
|
|
|
|
export async function startInstance(
|
|
projectId: string,
|
|
repoId: string,
|
|
instanceId: string
|
|
): Promise<{ status: string; url?: string }> {
|
|
const response = await apiClient.post(
|
|
`/projects/${projectId}/repositories/${repoId}/instances/${instanceId}/start`
|
|
);
|
|
return response.data;
|
|
}
|
|
|
|
export async function stopInstance(
|
|
projectId: string,
|
|
repoId: string,
|
|
instanceId: string
|
|
): Promise<{ status: string }> {
|
|
const response = await apiClient.post(
|
|
`/projects/${projectId}/repositories/${repoId}/instances/${instanceId}/stop`
|
|
);
|
|
return response.data;
|
|
}
|
|
|
|
export async function restartInstance(
|
|
projectId: string,
|
|
repoId: string,
|
|
instanceId: string
|
|
): Promise<{ status: string; url?: string }> {
|
|
const response = await apiClient.post(
|
|
`/projects/${projectId}/repositories/${repoId}/instances/${instanceId}/restart`
|
|
);
|
|
return response.data;
|
|
}
|
|
|
|
export async function deleteInstance(
|
|
projectId: string,
|
|
repoId: string,
|
|
instanceId: string
|
|
): Promise<void> {
|
|
await apiClient.delete(
|
|
`/projects/${projectId}/repositories/${repoId}/instances/${instanceId}`
|
|
);
|
|
}
|
|
|
|
export async function getUserSessions(): Promise<Session[]> {
|
|
const response = await apiClient.get("/users/me/sessions");
|
|
return response.data.sessions;
|
|
}
|