flowyml 1.2.0__py3-none-any.whl → 1.4.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- flowyml/__init__.py +3 -0
- flowyml/assets/base.py +10 -0
- flowyml/assets/metrics.py +6 -0
- flowyml/cli/main.py +108 -2
- flowyml/cli/run.py +9 -2
- flowyml/core/execution_status.py +52 -0
- flowyml/core/hooks.py +106 -0
- flowyml/core/observability.py +210 -0
- flowyml/core/orchestrator.py +274 -0
- flowyml/core/pipeline.py +193 -231
- flowyml/core/project.py +34 -2
- flowyml/core/remote_orchestrator.py +109 -0
- flowyml/core/resources.py +34 -17
- flowyml/core/retry_policy.py +80 -0
- flowyml/core/scheduler.py +9 -9
- flowyml/core/scheduler_config.py +2 -3
- flowyml/core/step.py +18 -1
- flowyml/core/submission_result.py +53 -0
- flowyml/integrations/keras.py +95 -22
- flowyml/monitoring/alerts.py +2 -2
- flowyml/stacks/__init__.py +15 -0
- flowyml/stacks/aws.py +599 -0
- flowyml/stacks/azure.py +295 -0
- flowyml/stacks/bridge.py +9 -9
- flowyml/stacks/components.py +24 -2
- flowyml/stacks/gcp.py +158 -11
- flowyml/stacks/local.py +5 -0
- flowyml/stacks/plugins.py +2 -2
- flowyml/stacks/registry.py +21 -0
- flowyml/storage/artifacts.py +15 -5
- flowyml/storage/materializers/__init__.py +2 -0
- flowyml/storage/materializers/base.py +33 -0
- flowyml/storage/materializers/cloudpickle.py +74 -0
- flowyml/storage/metadata.py +3 -881
- flowyml/storage/remote.py +590 -0
- flowyml/storage/sql.py +911 -0
- flowyml/ui/backend/dependencies.py +28 -0
- flowyml/ui/backend/main.py +43 -80
- flowyml/ui/backend/routers/assets.py +483 -17
- flowyml/ui/backend/routers/client.py +46 -0
- flowyml/ui/backend/routers/execution.py +13 -2
- flowyml/ui/backend/routers/experiments.py +97 -14
- flowyml/ui/backend/routers/metrics.py +168 -0
- flowyml/ui/backend/routers/pipelines.py +77 -12
- flowyml/ui/backend/routers/projects.py +33 -7
- flowyml/ui/backend/routers/runs.py +221 -12
- flowyml/ui/backend/routers/schedules.py +5 -21
- flowyml/ui/backend/routers/stats.py +14 -0
- flowyml/ui/backend/routers/traces.py +37 -53
- flowyml/ui/frontend/dist/assets/index-DcYwrn2j.css +1 -0
- flowyml/ui/frontend/dist/assets/index-Dlz_ygOL.js +592 -0
- flowyml/ui/frontend/dist/index.html +2 -2
- flowyml/ui/frontend/src/App.jsx +4 -1
- flowyml/ui/frontend/src/app/assets/page.jsx +260 -230
- flowyml/ui/frontend/src/app/dashboard/page.jsx +38 -7
- flowyml/ui/frontend/src/app/experiments/page.jsx +61 -314
- flowyml/ui/frontend/src/app/observability/page.jsx +277 -0
- flowyml/ui/frontend/src/app/pipelines/page.jsx +79 -402
- flowyml/ui/frontend/src/app/projects/[projectId]/_components/ProjectArtifactsList.jsx +151 -0
- flowyml/ui/frontend/src/app/projects/[projectId]/_components/ProjectExperimentsList.jsx +145 -0
- flowyml/ui/frontend/src/app/projects/[projectId]/_components/ProjectHeader.jsx +45 -0
- flowyml/ui/frontend/src/app/projects/[projectId]/_components/ProjectHierarchy.jsx +467 -0
- flowyml/ui/frontend/src/app/projects/[projectId]/_components/ProjectMetricsPanel.jsx +253 -0
- flowyml/ui/frontend/src/app/projects/[projectId]/_components/ProjectPipelinesList.jsx +105 -0
- flowyml/ui/frontend/src/app/projects/[projectId]/_components/ProjectRelations.jsx +189 -0
- flowyml/ui/frontend/src/app/projects/[projectId]/_components/ProjectRunsList.jsx +136 -0
- flowyml/ui/frontend/src/app/projects/[projectId]/_components/ProjectTabs.jsx +95 -0
- flowyml/ui/frontend/src/app/projects/[projectId]/page.jsx +326 -0
- flowyml/ui/frontend/src/app/projects/page.jsx +13 -3
- flowyml/ui/frontend/src/app/runs/[runId]/page.jsx +79 -10
- flowyml/ui/frontend/src/app/runs/page.jsx +82 -424
- flowyml/ui/frontend/src/app/settings/page.jsx +1 -0
- flowyml/ui/frontend/src/app/tokens/page.jsx +62 -16
- flowyml/ui/frontend/src/components/AssetDetailsPanel.jsx +373 -0
- flowyml/ui/frontend/src/components/AssetLineageGraph.jsx +291 -0
- flowyml/ui/frontend/src/components/AssetStatsDashboard.jsx +302 -0
- flowyml/ui/frontend/src/components/AssetTreeHierarchy.jsx +477 -0
- flowyml/ui/frontend/src/components/ExperimentDetailsPanel.jsx +227 -0
- flowyml/ui/frontend/src/components/NavigationTree.jsx +401 -0
- flowyml/ui/frontend/src/components/PipelineDetailsPanel.jsx +239 -0
- flowyml/ui/frontend/src/components/PipelineGraph.jsx +67 -3
- flowyml/ui/frontend/src/components/ProjectSelector.jsx +115 -0
- flowyml/ui/frontend/src/components/RunDetailsPanel.jsx +298 -0
- flowyml/ui/frontend/src/components/header/Header.jsx +48 -1
- flowyml/ui/frontend/src/components/plugins/ZenMLIntegration.jsx +106 -0
- flowyml/ui/frontend/src/components/sidebar/Sidebar.jsx +52 -26
- flowyml/ui/frontend/src/components/ui/DataView.jsx +35 -17
- flowyml/ui/frontend/src/components/ui/ErrorBoundary.jsx +118 -0
- flowyml/ui/frontend/src/contexts/ProjectContext.jsx +2 -2
- flowyml/ui/frontend/src/contexts/ToastContext.jsx +116 -0
- flowyml/ui/frontend/src/layouts/MainLayout.jsx +5 -1
- flowyml/ui/frontend/src/router/index.jsx +4 -0
- flowyml/ui/frontend/src/utils/date.js +10 -0
- flowyml/ui/frontend/src/utils/downloads.js +11 -0
- flowyml/utils/config.py +6 -0
- flowyml/utils/stack_config.py +45 -3
- {flowyml-1.2.0.dist-info → flowyml-1.4.0.dist-info}/METADATA +44 -4
- flowyml-1.4.0.dist-info/RECORD +200 -0
- {flowyml-1.2.0.dist-info → flowyml-1.4.0.dist-info}/licenses/LICENSE +1 -1
- flowyml/ui/frontend/dist/assets/index-DFNQnrUj.js +0 -448
- flowyml/ui/frontend/dist/assets/index-pWI271rZ.css +0 -1
- flowyml-1.2.0.dist-info/RECORD +0 -159
- {flowyml-1.2.0.dist-info → flowyml-1.4.0.dist-info}/WHEEL +0 -0
- {flowyml-1.2.0.dist-info → flowyml-1.4.0.dist-info}/entry_points.txt +0 -0
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import React, { useEffect, useState, useMemo } from 'react';
|
|
2
2
|
import { fetchApi } from '../../../utils/api';
|
|
3
|
+
import { downloadArtifactById } from '../../../utils/downloads';
|
|
3
4
|
import { useParams, Link } from 'react-router-dom';
|
|
4
|
-
import { CheckCircle, XCircle, Clock, Calendar, Package, ArrowRight, BarChart2, FileText, Database, Box, ChevronRight, Activity, Layers, Code2, Terminal, Info, X, Maximize2, TrendingUp, Download, ArrowDownCircle, ArrowUpCircle, Tag, Zap, AlertCircle, FolderPlus } from 'lucide-react';
|
|
5
|
+
import { CheckCircle, XCircle, Clock, Calendar, Package, ArrowRight, BarChart2, FileText, Database, Box, ChevronRight, Activity, Layers, Code2, Terminal, Info, X, Maximize2, TrendingUp, Download, ArrowDownCircle, ArrowUpCircle, Tag, Zap, AlertCircle, FolderPlus, Cloud, Server } from 'lucide-react';
|
|
5
6
|
import { Card } from '../../../components/ui/Card';
|
|
6
7
|
import { Badge } from '../../../components/ui/Badge';
|
|
7
8
|
import { Button } from '../../../components/ui/Button';
|
|
@@ -19,6 +20,43 @@ export function RunDetails() {
|
|
|
19
20
|
const [selectedStep, setSelectedStep] = useState(null);
|
|
20
21
|
const [activeTab, setActiveTab] = useState('overview');
|
|
21
22
|
const [selectedArtifact, setSelectedArtifact] = useState(null);
|
|
23
|
+
const [cloudStatus, setCloudStatus] = useState(null);
|
|
24
|
+
const [isPolling, setIsPolling] = useState(false);
|
|
25
|
+
|
|
26
|
+
// Fetch cloud status for remote runs
|
|
27
|
+
useEffect(() => {
|
|
28
|
+
if (!run) return;
|
|
29
|
+
|
|
30
|
+
const fetchCloudStatus = async () => {
|
|
31
|
+
try {
|
|
32
|
+
const res = await fetchApi(`/api/runs/${runId}/cloud-status`);
|
|
33
|
+
const data = await res.json();
|
|
34
|
+
setCloudStatus(data);
|
|
35
|
+
|
|
36
|
+
// Continue polling if run is remote and not finished
|
|
37
|
+
if (data.is_remote && data.cloud_status && !data.cloud_status.is_finished) {
|
|
38
|
+
setIsPolling(true);
|
|
39
|
+
} else {
|
|
40
|
+
setIsPolling(false);
|
|
41
|
+
}
|
|
42
|
+
} catch (error) {
|
|
43
|
+
console.error('Failed to fetch cloud status:', error);
|
|
44
|
+
setIsPolling(false);
|
|
45
|
+
}
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
fetchCloudStatus();
|
|
49
|
+
|
|
50
|
+
// Poll every 5 seconds if remote and not finished
|
|
51
|
+
let interval;
|
|
52
|
+
if (isPolling) {
|
|
53
|
+
interval = setInterval(fetchCloudStatus, 5000);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
return () => {
|
|
57
|
+
if (interval) clearInterval(interval);
|
|
58
|
+
};
|
|
59
|
+
}, [runId, run, isPolling]);
|
|
22
60
|
|
|
23
61
|
useEffect(() => {
|
|
24
62
|
const fetchData = async () => {
|
|
@@ -94,13 +132,25 @@ export function RunDetails() {
|
|
|
94
132
|
<p className="text-slate-500 mt-1 flex items-center gap-2">
|
|
95
133
|
<Layers size={16} />
|
|
96
134
|
Pipeline: <span className="font-medium text-slate-700">{run.pipeline_name}</span>
|
|
135
|
+
{cloudStatus?.is_remote && (
|
|
136
|
+
<Badge variant="secondary" className="text-xs bg-blue-50 text-blue-600 flex items-center gap-1">
|
|
137
|
+
<Cloud size={12} />
|
|
138
|
+
{cloudStatus.orchestrator_type}
|
|
139
|
+
</Badge>
|
|
140
|
+
)}
|
|
141
|
+
{cloudStatus?.is_remote && isPolling && (
|
|
142
|
+
<span className="text-xs text-amber-600 flex items-center gap-1 animate-pulse">
|
|
143
|
+
<Activity size={12} />
|
|
144
|
+
Live
|
|
145
|
+
</span>
|
|
146
|
+
)}
|
|
97
147
|
</p>
|
|
98
148
|
</div>
|
|
99
149
|
<div className="flex flex-col items-end gap-2">
|
|
100
150
|
<div className="flex items-center gap-2">
|
|
101
151
|
<SimpleProjectSelector runId={run.run_id} currentProject={run.project} />
|
|
102
152
|
<Badge variant={statusVariant} className="text-sm px-4 py-1.5 uppercase tracking-wide shadow-sm">
|
|
103
|
-
{run.status}
|
|
153
|
+
{cloudStatus?.cloud_status?.status || run.status}
|
|
104
154
|
</Badge>
|
|
105
155
|
</div>
|
|
106
156
|
<span className="text-xs text-slate-400 font-mono">ID: {run.run_id}</span>
|
|
@@ -480,6 +530,16 @@ function ArtifactsTab({ artifacts, onArtifactClick }) {
|
|
|
480
530
|
<p className="text-xs text-slate-500 truncate">{art.type}</p>
|
|
481
531
|
</div>
|
|
482
532
|
<div className="flex items-center gap-2">
|
|
533
|
+
<button
|
|
534
|
+
className="p-2 rounded-lg hover:bg-white transition-colors text-slate-400 hover:text-primary-600 disabled:opacity-40"
|
|
535
|
+
onClick={(e) => {
|
|
536
|
+
e.stopPropagation();
|
|
537
|
+
downloadArtifactById(art.artifact_id);
|
|
538
|
+
}}
|
|
539
|
+
disabled={!art.artifact_id}
|
|
540
|
+
>
|
|
541
|
+
<Download size={14} />
|
|
542
|
+
</button>
|
|
483
543
|
<Maximize2 size={14} className="text-slate-300 group-hover:text-primary-400 transition-colors" />
|
|
484
544
|
<ArrowRight size={14} className="text-slate-300 group-hover:text-primary-400 opacity-0 group-hover:opacity-100 transition-all" />
|
|
485
545
|
</div>
|
|
@@ -526,12 +586,21 @@ function ArtifactModal({ artifact, onClose }) {
|
|
|
526
586
|
<p className="text-sm text-slate-500">{artifact.type}</p>
|
|
527
587
|
</div>
|
|
528
588
|
</div>
|
|
529
|
-
<
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
589
|
+
<div className="flex items-center gap-2">
|
|
590
|
+
<button
|
|
591
|
+
onClick={() => downloadArtifactById(artifact.artifact_id)}
|
|
592
|
+
className="inline-flex items-center gap-2 px-3 py-2 rounded-lg bg-primary-600 text-white text-sm font-semibold hover:bg-primary-500 transition-colors disabled:opacity-50"
|
|
593
|
+
disabled={!artifact.artifact_id}
|
|
594
|
+
>
|
|
595
|
+
<Download size={16} /> Download
|
|
596
|
+
</button>
|
|
597
|
+
<button
|
|
598
|
+
onClick={onClose}
|
|
599
|
+
className="p-2 hover:bg-white rounded-lg transition-colors"
|
|
600
|
+
>
|
|
601
|
+
<X size={20} className="text-slate-400" />
|
|
602
|
+
</button>
|
|
603
|
+
</div>
|
|
535
604
|
</div>
|
|
536
605
|
|
|
537
606
|
{/* Content */}
|
|
@@ -663,8 +732,8 @@ function SimpleProjectSelector({ runId, currentProject }) {
|
|
|
663
732
|
onClick={() => handleSelectProject(p.name)}
|
|
664
733
|
disabled={updating}
|
|
665
734
|
className={`w-full text-left px-3 py-2 text-sm rounded-lg transition-colors ${p.name === currentProject
|
|
666
|
-
|
|
667
|
-
|
|
735
|
+
? 'bg-primary-50 dark:bg-primary-900/20 text-primary-700 dark:text-primary-300 font-medium'
|
|
736
|
+
: 'text-slate-700 dark:text-slate-200 hover:bg-slate-50 dark:hover:bg-slate-700'
|
|
668
737
|
}`}
|
|
669
738
|
>
|
|
670
739
|
{p.name} {p.name === currentProject && '✓'}
|