Files
multica/packages/core/runtimes/cloud-runtime.ts
Multica Eve 51b3c5291f feat: add env-gated cloud runtime launcher (MUL-2453) (#2995)
* feat: add env-gated cloud runtime launcher

Co-authored-by: multica-agent <github@multica.ai>

* fix: address cloud runtime frontend nits

Co-authored-by: multica-agent <github@multica.ai>

---------

Co-authored-by: Eve <eve@multica-ai.local>
Co-authored-by: multica-agent <github@multica.ai>
2026-05-21 15:41:31 +08:00

91 lines
2.2 KiB
TypeScript

import { queryOptions, useMutation, useQueryClient } from "@tanstack/react-query";
import { api } from "../api";
export interface CloudRuntimeNode {
id: string;
owner_id: string;
instance_id: string;
region: string;
instance_type: string;
image_id: string;
subnet_id: string;
name: string;
status: string;
tags: Record<string, string>;
metadata: Record<string, unknown>;
created_at: string;
updated_at: string;
}
export interface ListCloudRuntimeNodesParams {
limit?: number;
offset?: number;
}
export interface CreateCloudRuntimeNodeRequest {
instance_type: string;
name?: string;
region?: string;
image_id?: string;
subnet_id?: string;
key_name?: string;
iam_instance_profile?: string;
disk_size_gb?: number;
tags?: Record<string, string>;
}
export interface CreateCloudRuntimeNodeOptions {
userPAT?: string;
}
export const cloudRuntimeKeys = {
all: (wsId: string) => ["cloud-runtime", wsId] as const,
nodes: (wsId: string) => [...cloudRuntimeKeys.all(wsId), "nodes"] as const,
};
const PENDING_NODE_STATUSES = new Set([
"launching",
"pending",
"starting",
"stopping",
"rebooting",
"terminating",
]);
export function isCloudRuntimeNodePending(status: string): boolean {
return PENDING_NODE_STATUSES.has(status.toLowerCase());
}
export function cloudRuntimeNodeListOptions(
wsId: string,
params?: ListCloudRuntimeNodesParams,
) {
const limit = params?.limit ?? 20;
const offset = params?.offset ?? 0;
return queryOptions({
queryKey: [...cloudRuntimeKeys.nodes(wsId), { limit, offset }] as const,
queryFn: () => api.listCloudRuntimeNodes({ limit, offset }),
refetchInterval: (query) =>
query.state.data?.some((node) => isCloudRuntimeNodePending(node.status))
? 5000
: false,
staleTime: 15 * 1000,
});
}
export function useCreateCloudRuntimeNode(wsId: string) {
const qc = useQueryClient();
return useMutation({
mutationFn: ({
data,
userPAT,
}: {
data: CreateCloudRuntimeNodeRequest;
userPAT?: string;
}) => api.createCloudRuntimeNode(data, { userPAT }),
onSettled: () => {
qc.invalidateQueries({ queryKey: cloudRuntimeKeys.all(wsId) });
},
});
}