Spaces:
Running
on
CPU Upgrade
Running
on
CPU Upgrade
Commit
·
231dcea
1
Parent(s):
531b15c
track the org jobs
Browse files
ui/src/app/api/hf-jobs/route.ts
CHANGED
|
@@ -16,7 +16,8 @@ export async function POST(request: NextRequest) {
|
|
| 16 |
return NextResponse.json({ error: 'Token and job ID required' }, { status: 400 });
|
| 17 |
}
|
| 18 |
|
| 19 |
-
const
|
|
|
|
| 20 |
return NextResponse.json({ status: jobStatus });
|
| 21 |
} catch (error: any) {
|
| 22 |
console.error('Job status check error:', error);
|
|
@@ -904,13 +905,19 @@ async function submitHFJobUV(token: string, hardware: string, scriptPath: string
|
|
| 904 |
});
|
| 905 |
}
|
| 906 |
|
| 907 |
-
async function checkHFJobStatus(token: string, jobId: string): Promise<any> {
|
| 908 |
return new Promise((resolve, reject) => {
|
| 909 |
console.log(`Checking HF Job status for: ${jobId}`);
|
| 910 |
-
|
| 911 |
-
|
| 912 |
-
|
| 913 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 914 |
env: {
|
| 915 |
...process.env,
|
| 916 |
HF_TOKEN: token
|
|
|
|
| 16 |
return NextResponse.json({ error: 'Token and job ID required' }, { status: 400 });
|
| 17 |
}
|
| 18 |
|
| 19 |
+
const jobNamespaceOverride = jobConfig?.hf_job_namespace;
|
| 20 |
+
const jobStatus = await checkHFJobStatus(token, jobConfig.hf_job_id, jobNamespaceOverride);
|
| 21 |
return NextResponse.json({ status: jobStatus });
|
| 22 |
} catch (error: any) {
|
| 23 |
console.error('Job status check error:', error);
|
|
|
|
| 905 |
});
|
| 906 |
}
|
| 907 |
|
| 908 |
+
async function checkHFJobStatus(token: string, jobId: string, jobNamespace?: string): Promise<any> {
|
| 909 |
return new Promise((resolve, reject) => {
|
| 910 |
console.log(`Checking HF Job status for: ${jobId}`);
|
| 911 |
+
const args = ['jobs', 'inspect'];
|
| 912 |
+
|
| 913 |
+
if (jobNamespace) {
|
| 914 |
+
console.log(`Using namespace override for status check: ${jobNamespace}`);
|
| 915 |
+
args.push('--namespace', jobNamespace);
|
| 916 |
+
}
|
| 917 |
+
|
| 918 |
+
args.push(jobId);
|
| 919 |
+
|
| 920 |
+
const childProcess = spawn('hf', args, {
|
| 921 |
env: {
|
| 922 |
...process.env,
|
| 923 |
HF_TOKEN: token
|
ui/src/components/HFJobStatus.tsx
CHANGED
|
@@ -7,10 +7,25 @@ import { Button } from '@headlessui/react';
|
|
| 7 |
interface HFJobStatusProps {
|
| 8 |
hfJobId: string;
|
| 9 |
hfJobUrl?: string;
|
|
|
|
| 10 |
}
|
| 11 |
|
| 12 |
-
|
| 13 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 14 |
|
| 15 |
if (error) {
|
| 16 |
return (
|
|
@@ -122,4 +137,4 @@ export default function HFJobStatus({ hfJobId, hfJobUrl }: HFJobStatusProps) {
|
|
| 122 |
)}
|
| 123 |
</div>
|
| 124 |
);
|
| 125 |
-
}
|
|
|
|
| 7 |
interface HFJobStatusProps {
|
| 8 |
hfJobId: string;
|
| 9 |
hfJobUrl?: string;
|
| 10 |
+
hfJobNamespace?: string;
|
| 11 |
}
|
| 12 |
|
| 13 |
+
const extractNamespaceFromUrl = (url?: string) => {
|
| 14 |
+
if (!url) {
|
| 15 |
+
return undefined;
|
| 16 |
+
}
|
| 17 |
+
try {
|
| 18 |
+
const match = url.match(/\/jobs\/([^\/]+)\//);
|
| 19 |
+
return match?.[1];
|
| 20 |
+
} catch (error) {
|
| 21 |
+
console.warn('Failed to derive HF job namespace from URL:', error);
|
| 22 |
+
return undefined;
|
| 23 |
+
}
|
| 24 |
+
};
|
| 25 |
+
|
| 26 |
+
export default function HFJobStatus({ hfJobId, hfJobUrl, hfJobNamespace }: HFJobStatusProps) {
|
| 27 |
+
const derivedNamespace = hfJobNamespace || extractNamespaceFromUrl(hfJobUrl);
|
| 28 |
+
const { status, loading, error } = useHFJobStatus(hfJobId, derivedNamespace);
|
| 29 |
|
| 30 |
if (error) {
|
| 31 |
return (
|
|
|
|
| 137 |
)}
|
| 138 |
</div>
|
| 139 |
);
|
| 140 |
+
}
|
ui/src/components/HFJobsWorkflow.tsx
CHANGED
|
@@ -409,6 +409,7 @@ export default function HFJobsWorkflow({ jobConfig, onComplete, hackathonEligibl
|
|
| 409 |
is_hf_job: true,
|
| 410 |
training_backend: 'hf-jobs',
|
| 411 |
hf_job_submitted: true,
|
|
|
|
| 412 |
},
|
| 413 |
info: response.data.message || 'HF Job submitted',
|
| 414 |
status: 'submitted',
|
|
@@ -437,6 +438,7 @@ export default function HFJobsWorkflow({ jobConfig, onComplete, hackathonEligibl
|
|
| 437 |
is_hf_job: true,
|
| 438 |
training_backend: 'hf-jobs',
|
| 439 |
hf_job_submitted: true,
|
|
|
|
| 440 |
},
|
| 441 |
info: response.data.message || 'HF Job submitted',
|
| 442 |
status: 'submitted',
|
|
|
|
| 409 |
is_hf_job: true,
|
| 410 |
training_backend: 'hf-jobs',
|
| 411 |
hf_job_submitted: true,
|
| 412 |
+
hf_job_namespace: jobNamespace,
|
| 413 |
},
|
| 414 |
info: response.data.message || 'HF Job submitted',
|
| 415 |
status: 'submitted',
|
|
|
|
| 438 |
is_hf_job: true,
|
| 439 |
training_backend: 'hf-jobs',
|
| 440 |
hf_job_submitted: true,
|
| 441 |
+
hf_job_namespace: jobNamespace,
|
| 442 |
},
|
| 443 |
info: response.data.message || 'HF Job submitted',
|
| 444 |
status: 'submitted',
|
ui/src/components/JobOverview.tsx
CHANGED
|
@@ -109,6 +109,7 @@ export default function JobOverview({ job }: JobOverviewProps) {
|
|
| 109 |
<HFJobStatus
|
| 110 |
hfJobId={jobConfig.hf_job_id}
|
| 111 |
hfJobUrl={jobConfig.hf_job_url}
|
|
|
|
| 112 |
/>
|
| 113 |
) : isHFJob && !hfJobSubmitted ? (
|
| 114 |
<span className="px-3 py-1 rounded-full text-sm bg-yellow-500/10 text-yellow-500">
|
|
|
|
| 109 |
<HFJobStatus
|
| 110 |
hfJobId={jobConfig.hf_job_id}
|
| 111 |
hfJobUrl={jobConfig.hf_job_url}
|
| 112 |
+
hfJobNamespace={jobConfig.hf_job_namespace}
|
| 113 |
/>
|
| 114 |
) : isHFJob && !hfJobSubmitted ? (
|
| 115 |
<span className="px-3 py-1 rounded-full text-sm bg-yellow-500/10 text-yellow-500">
|
ui/src/components/JobsTable.tsx
CHANGED
|
@@ -99,6 +99,7 @@ export default function JobsTable({ onlyActive = false }: JobsTableProps) {
|
|
| 99 |
<HFJobStatus
|
| 100 |
hfJobId={jobConfig.hf_job_id}
|
| 101 |
hfJobUrl={jobConfig.hf_job_url}
|
|
|
|
| 102 |
/>
|
| 103 |
);
|
| 104 |
} else {
|
|
|
|
| 99 |
<HFJobStatus
|
| 100 |
hfJobId={jobConfig.hf_job_id}
|
| 101 |
hfJobUrl={jobConfig.hf_job_url}
|
| 102 |
+
hfJobNamespace={jobConfig.hf_job_namespace}
|
| 103 |
/>
|
| 104 |
);
|
| 105 |
} else {
|
ui/src/hooks/useHFJobStatus.tsx
CHANGED
|
@@ -12,7 +12,7 @@ interface HFJobStatus {
|
|
| 12 |
url: string;
|
| 13 |
}
|
| 14 |
|
| 15 |
-
export function useHFJobStatus(hfJobId: string | null, refreshInterval = 30000) {
|
| 16 |
const [status, setStatus] = useState<HFJobStatus | null>(null);
|
| 17 |
const [loading, setLoading] = useState(false);
|
| 18 |
const [error, setError] = useState<string | null>(null);
|
|
@@ -31,7 +31,10 @@ export function useHFJobStatus(hfJobId: string | null, refreshInterval = 30000)
|
|
| 31 |
const response = await apiClient.post('/api/hf-jobs', {
|
| 32 |
action: 'checkStatus',
|
| 33 |
token,
|
| 34 |
-
jobConfig: {
|
|
|
|
|
|
|
|
|
|
| 35 |
});
|
| 36 |
|
| 37 |
if (response.data.status) {
|
|
@@ -52,7 +55,7 @@ export function useHFJobStatus(hfJobId: string | null, refreshInterval = 30000)
|
|
| 52 |
const interval = setInterval(fetchStatus, refreshInterval);
|
| 53 |
|
| 54 |
return () => clearInterval(interval);
|
| 55 |
-
}, [hfJobId, token, refreshInterval]);
|
| 56 |
|
| 57 |
return { status, loading, error, refetch: () => {
|
| 58 |
if (hfJobId && token) {
|
|
|
|
| 12 |
url: string;
|
| 13 |
}
|
| 14 |
|
| 15 |
+
export function useHFJobStatus(hfJobId: string | null, hfJobNamespace?: string, refreshInterval = 30000) {
|
| 16 |
const [status, setStatus] = useState<HFJobStatus | null>(null);
|
| 17 |
const [loading, setLoading] = useState(false);
|
| 18 |
const [error, setError] = useState<string | null>(null);
|
|
|
|
| 31 |
const response = await apiClient.post('/api/hf-jobs', {
|
| 32 |
action: 'checkStatus',
|
| 33 |
token,
|
| 34 |
+
jobConfig: {
|
| 35 |
+
hf_job_id: hfJobId,
|
| 36 |
+
hf_job_namespace: hfJobNamespace,
|
| 37 |
+
},
|
| 38 |
});
|
| 39 |
|
| 40 |
if (response.data.status) {
|
|
|
|
| 55 |
const interval = setInterval(fetchStatus, refreshInterval);
|
| 56 |
|
| 57 |
return () => clearInterval(interval);
|
| 58 |
+
}, [hfJobId, hfJobNamespace, token, refreshInterval]);
|
| 59 |
|
| 60 |
return { status, loading, error, refetch: () => {
|
| 61 |
if (hfJobId && token) {
|
ui/src/types.ts
CHANGED
|
@@ -199,6 +199,14 @@ export interface JobConfig {
|
|
| 199 |
job: string;
|
| 200 |
config: ConfigObject;
|
| 201 |
meta: MetaConfig;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 202 |
}
|
| 203 |
|
| 204 |
export interface ConfigDoc {
|
|
|
|
| 199 |
job: string;
|
| 200 |
config: ConfigObject;
|
| 201 |
meta: MetaConfig;
|
| 202 |
+
is_hf_job?: boolean;
|
| 203 |
+
hf_job_id?: string;
|
| 204 |
+
hf_job_url?: string | null;
|
| 205 |
+
hf_job_namespace?: string;
|
| 206 |
+
dataset_repo?: string;
|
| 207 |
+
hardware?: string;
|
| 208 |
+
training_backend?: string;
|
| 209 |
+
hf_job_submitted?: boolean;
|
| 210 |
}
|
| 211 |
|
| 212 |
export interface ConfigDoc {
|