|
1 | | -import { ChevronsUpDown } from "lucide-react"; |
| 1 | +import { ChevronsUpDown, ExternalLink } from "lucide-react"; |
2 | 2 |
|
3 | 3 | import type { GetContainerExecutionStateResponse } from "@/api/types.gen"; |
4 | 4 | import { Button } from "@/components/ui/button"; |
@@ -50,6 +50,7 @@ export const ExecutionDetails = ({ |
50 | 50 | } |
51 | 51 |
|
52 | 52 | const podName = executionPodName(containerState); |
| 53 | + const executionJobLinks = getExecutionJobLinks(containerState); |
53 | 54 |
|
54 | 55 | return ( |
55 | 56 | <div className="flex flex-col px-3 py-2"> |
@@ -150,6 +151,29 @@ export const ExecutionDetails = ({ |
150 | 151 | </span> |
151 | 152 | </div> |
152 | 153 | )} |
| 154 | + {executionJobLinks && ( |
| 155 | + <> |
| 156 | + {executionJobLinks.map((linkInfo) => ( |
| 157 | + <div |
| 158 | + key={linkInfo.name} |
| 159 | + className="flex text-xs items-center gap-2" |
| 160 | + > |
| 161 | + <span className="font-medium text-foreground min-w-fit"> |
| 162 | + {linkInfo.name}: |
| 163 | + </span> |
| 164 | + <a |
| 165 | + href={linkInfo.url} |
| 166 | + className="text-sky-500 hover:underline flex items-center gap-1" |
| 167 | + target="_blank" |
| 168 | + rel="noopener noreferrer" |
| 169 | + > |
| 170 | + {linkInfo.value} |
| 171 | + <ExternalLink className="size-3 flex-shrink-0" /> |
| 172 | + </a> |
| 173 | + </div> |
| 174 | + ))} |
| 175 | + </> |
| 176 | + )} |
153 | 177 |
|
154 | 178 | {!isLoadingContainerState && |
155 | 179 | !containerState && |
@@ -191,3 +215,38 @@ function executionPodName( |
191 | 215 |
|
192 | 216 | return null; |
193 | 217 | } |
| 218 | + |
| 219 | +interface ExecutionLinkItem { |
| 220 | + name: string; |
| 221 | + value: string; |
| 222 | + url?: string; |
| 223 | +} |
| 224 | + |
| 225 | +function getExecutionJobLinks( |
| 226 | + containerState?: GetContainerExecutionStateResponse, |
| 227 | +): Array<ExecutionLinkItem> | null { |
| 228 | + if (!containerState || !("debug_info" in containerState)) { |
| 229 | + return null; |
| 230 | + } |
| 231 | + |
| 232 | + const debugInfo = containerState.debug_info as Record<string, any>; |
| 233 | + |
| 234 | + const result = Array<ExecutionLinkItem>(); |
| 235 | + |
| 236 | + const huggingfaceJob = debugInfo.huggingface_job as Record<string, any>; |
| 237 | + if ( |
| 238 | + huggingfaceJob && |
| 239 | + typeof huggingfaceJob === "object" && |
| 240 | + typeof huggingfaceJob.id === "string" && |
| 241 | + typeof huggingfaceJob.namespace === "string" |
| 242 | + ) { |
| 243 | + const url = `https://huggingface.co/jobs/${huggingfaceJob.namespace}/${huggingfaceJob.id}`; |
| 244 | + result.push({ |
| 245 | + name: "HuggingFace Job", |
| 246 | + value: huggingfaceJob.id, |
| 247 | + url: url, |
| 248 | + }); |
| 249 | + } |
| 250 | + |
| 251 | + return result; |
| 252 | +} |
0 commit comments