|
6773 | 6773 | [ |
6774 | 6774 | "files_and_knowledge", |
6775 | 6775 | { |
| 6776 | + "Directory": { |
| 6777 | + "base_classes": [ |
| 6778 | + "Table" |
| 6779 | + ], |
| 6780 | + "beta": false, |
| 6781 | + "conditional_paths": [], |
| 6782 | + "custom_fields": {}, |
| 6783 | + "description": "Recursively load files from a directory.", |
| 6784 | + "display_name": "Directory", |
| 6785 | + "documentation": "https://docs.langflow.org/directory", |
| 6786 | + "edited": false, |
| 6787 | + "field_order": [ |
| 6788 | + "path", |
| 6789 | + "types", |
| 6790 | + "depth", |
| 6791 | + "max_concurrency", |
| 6792 | + "load_hidden", |
| 6793 | + "recursive", |
| 6794 | + "silent_errors", |
| 6795 | + "use_multithreading" |
| 6796 | + ], |
| 6797 | + "frozen": false, |
| 6798 | + "icon": "folder", |
| 6799 | + "legacy": true, |
| 6800 | + "metadata": { |
| 6801 | + "code_hash": "e05a90393ad4", |
| 6802 | + "dependencies": { |
| 6803 | + "dependencies": [ |
| 6804 | + { |
| 6805 | + "name": "lfx", |
| 6806 | + "version": null |
| 6807 | + } |
| 6808 | + ], |
| 6809 | + "total_dependencies": 1 |
| 6810 | + }, |
| 6811 | + "module": "lfx.components.files_and_knowledge.directory.DirectoryComponent" |
| 6812 | + }, |
| 6813 | + "minimized": false, |
| 6814 | + "output_types": [], |
| 6815 | + "outputs": [ |
| 6816 | + { |
| 6817 | + "allows_loop": false, |
| 6818 | + "cache": true, |
| 6819 | + "display_name": "Loaded Files", |
| 6820 | + "group_outputs": false, |
| 6821 | + "method": "as_dataframe", |
| 6822 | + "name": "dataframe", |
| 6823 | + "selected": "Table", |
| 6824 | + "tool_mode": true, |
| 6825 | + "types": [ |
| 6826 | + "Table" |
| 6827 | + ], |
| 6828 | + "value": "__UNDEFINED__" |
| 6829 | + } |
| 6830 | + ], |
| 6831 | + "pinned": false, |
| 6832 | + "replacement": [ |
| 6833 | + "data.File" |
| 6834 | + ], |
| 6835 | + "template": { |
| 6836 | + "_type": "Component", |
| 6837 | + "code": { |
| 6838 | + "advanced": true, |
| 6839 | + "api_editable": false, |
| 6840 | + "dynamic": true, |
| 6841 | + "fileTypes": [], |
| 6842 | + "file_path": "", |
| 6843 | + "info": "", |
| 6844 | + "list": false, |
| 6845 | + "load_from_db": false, |
| 6846 | + "multiline": true, |
| 6847 | + "name": "code", |
| 6848 | + "password": false, |
| 6849 | + "placeholder": "", |
| 6850 | + "required": true, |
| 6851 | + "show": true, |
| 6852 | + "title_case": false, |
| 6853 | + "type": "code", |
| 6854 | + "value": "from pathlib import Path, PurePath, PureWindowsPath\n\nfrom lfx.base.data.utils import TEXT_FILE_TYPES, parallel_load_data, parse_text_file_to_data, retrieve_file_paths\nfrom lfx.custom.custom_component.component import Component\nfrom lfx.io import BoolInput, IntInput, MessageTextInput, MultiselectInput\nfrom lfx.schema.data import Data\nfrom lfx.schema.dataframe import DataFrame\nfrom lfx.services.deps import get_settings_service\nfrom lfx.template.field.base import Output\nfrom lfx.utils.file_path_security import component_file_access_scopes, enforce_local_file_access\n\n\nclass DirectoryComponent(Component):\n display_name = \"Directory\"\n description = \"Recursively load files from a directory.\"\n documentation: str = \"https://docs.langflow.org/directory\"\n icon = \"folder\"\n name = \"Directory\"\n legacy = True\n replacement = [\"data.File\"]\n\n inputs = [\n MessageTextInput(\n name=\"path\",\n display_name=\"Path\",\n info=\"Path to the directory to load files from. Defaults to current directory ('.')\",\n value=\".\",\n tool_mode=True,\n ),\n MultiselectInput(\n name=\"types\",\n display_name=\"File Types\",\n info=\"File types to load. Select one or more types or leave empty to load all supported types.\",\n options=TEXT_FILE_TYPES,\n value=[],\n ),\n IntInput(\n name=\"depth\",\n display_name=\"Depth\",\n info=\"Depth to search for files.\",\n value=0,\n ),\n IntInput(\n name=\"max_concurrency\",\n display_name=\"Max Concurrency\",\n advanced=True,\n info=\"Maximum concurrency for loading files.\",\n value=2,\n ),\n BoolInput(\n name=\"load_hidden\",\n display_name=\"Load Hidden\",\n advanced=True,\n info=\"If true, hidden files will be loaded.\",\n ),\n BoolInput(\n name=\"recursive\",\n display_name=\"Recursive\",\n advanced=True,\n info=\"If true, the search will be recursive.\",\n ),\n BoolInput(\n name=\"silent_errors\",\n display_name=\"Silent Errors\",\n advanced=True,\n info=\"If true, errors will not raise an exception.\",\n ),\n BoolInput(\n name=\"use_multithreading\",\n display_name=\"Use Multithreading\",\n advanced=True,\n info=\"If true, multithreading will be used.\",\n ),\n ]\n\n outputs = [\n Output(display_name=\"Loaded Files\", name=\"dataframe\", method=\"as_dataframe\"),\n ]\n\n @staticmethod\n def _has_parent_reference(path: str) -> bool:\n path_parts = (*PurePath(path).parts, *PureWindowsPath(path).parts)\n return any(part == \"..\" for part in path_parts)\n\n def _allowed_roots(self) -> list[Path]:\n roots = {Path.cwd().resolve()}\n configured_roots = getattr(get_settings_service().settings, \"directory_component_allowed_roots\", []) or []\n for root in configured_roots:\n if root:\n roots.add(Path(root).expanduser().resolve())\n return list(roots)\n\n def _resolve_directory_path(self, path: str) -> str:\n path = str(path or \".\").strip()\n # Reject null bytes and parent references outright. A drive-absolute or UNC\n # path (e.g. ``D:\\\\shared\\\\docs``) is NOT blanket-rejected here: canonicalization\n # plus the ``_allowed_roots()`` containment check below decides whether it is\n # allowed, so operator-configured roots on another drive remain reachable.\n if \"\\x00\" in path or self._has_parent_reference(path):\n msg = \"Directory path escapes the allowed root.\"\n raise ValueError(msg)\n\n resolved_path = Path(self.resolve_path(path)).expanduser().resolve()\n if not any(resolved_path == root or resolved_path.is_relative_to(root) for root in self._allowed_roots()):\n msg = \"Directory path escapes the allowed root.\"\n raise ValueError(msg)\n return str(resolved_path)\n\n def load_directory(self) -> list[Data]:\n path = self.path\n types = self.types\n depth = self.depth\n max_concurrency = self.max_concurrency\n load_hidden = self.load_hidden\n recursive = self.recursive\n silent_errors = self.silent_errors\n use_multithreading = self.use_multithreading\n\n resolved_path = self._resolve_directory_path(path)\n\n # Security: confine directory reads to the storage dir in restricted (multi-tenant)\n # mode so a tenant cannot recursively read arbitrary server directories.\n resolved_path = str(enforce_local_file_access(resolved_path, scope_ids=component_file_access_scopes(self)))\n\n # If no types are specified, use all supported types\n if not types:\n types = TEXT_FILE_TYPES\n\n # Check if all specified types are valid\n invalid_types = [t for t in types if t not in TEXT_FILE_TYPES]\n if invalid_types:\n msg = f\"Invalid file types specified: {invalid_types}. Valid types are: {TEXT_FILE_TYPES}\"\n raise ValueError(msg)\n\n valid_types = types\n\n file_paths = retrieve_file_paths(\n resolved_path, load_hidden=load_hidden, recursive=recursive, depth=depth, types=valid_types\n )\n\n loaded_data = []\n if use_multithreading:\n loaded_data = parallel_load_data(file_paths, silent_errors=silent_errors, max_concurrency=max_concurrency)\n else:\n loaded_data = [parse_text_file_to_data(file_path, silent_errors=silent_errors) for file_path in file_paths]\n\n valid_data = [x for x in loaded_data if x is not None and isinstance(x, Data)]\n self.status = valid_data\n return valid_data\n\n def as_dataframe(self) -> DataFrame:\n return DataFrame(self.load_directory())\n" |
| 6855 | + }, |
| 6856 | + "depth": { |
| 6857 | + "_input_type": "IntInput", |
| 6858 | + "advanced": false, |
| 6859 | + "api_editable": false, |
| 6860 | + "display_name": "Depth", |
| 6861 | + "dynamic": false, |
| 6862 | + "info": "Depth to search for files.", |
| 6863 | + "list": false, |
| 6864 | + "list_add_label": "Add More", |
| 6865 | + "name": "depth", |
| 6866 | + "override_skip": false, |
| 6867 | + "placeholder": "", |
| 6868 | + "required": false, |
| 6869 | + "show": true, |
| 6870 | + "title_case": false, |
| 6871 | + "tool_mode": false, |
| 6872 | + "trace_as_metadata": true, |
| 6873 | + "track_in_telemetry": true, |
| 6874 | + "type": "int", |
| 6875 | + "value": 0 |
| 6876 | + }, |
| 6877 | + "load_hidden": { |
| 6878 | + "_input_type": "BoolInput", |
| 6879 | + "advanced": true, |
| 6880 | + "api_editable": false, |
| 6881 | + "display_name": "Load Hidden", |
| 6882 | + "dynamic": false, |
| 6883 | + "info": "If true, hidden files will be loaded.", |
| 6884 | + "list": false, |
| 6885 | + "list_add_label": "Add More", |
| 6886 | + "name": "load_hidden", |
| 6887 | + "override_skip": false, |
| 6888 | + "placeholder": "", |
| 6889 | + "required": false, |
| 6890 | + "show": true, |
| 6891 | + "title_case": false, |
| 6892 | + "tool_mode": false, |
| 6893 | + "trace_as_metadata": true, |
| 6894 | + "track_in_telemetry": true, |
| 6895 | + "type": "bool", |
| 6896 | + "value": false |
| 6897 | + }, |
| 6898 | + "max_concurrency": { |
| 6899 | + "_input_type": "IntInput", |
| 6900 | + "advanced": true, |
| 6901 | + "api_editable": false, |
| 6902 | + "display_name": "Max Concurrency", |
| 6903 | + "dynamic": false, |
| 6904 | + "info": "Maximum concurrency for loading files.", |
| 6905 | + "list": false, |
| 6906 | + "list_add_label": "Add More", |
| 6907 | + "name": "max_concurrency", |
| 6908 | + "override_skip": false, |
| 6909 | + "placeholder": "", |
| 6910 | + "required": false, |
| 6911 | + "show": true, |
| 6912 | + "title_case": false, |
| 6913 | + "tool_mode": false, |
| 6914 | + "trace_as_metadata": true, |
| 6915 | + "track_in_telemetry": true, |
| 6916 | + "type": "int", |
| 6917 | + "value": 2 |
| 6918 | + }, |
| 6919 | + "path": { |
| 6920 | + "_input_type": "MessageTextInput", |
| 6921 | + "advanced": false, |
| 6922 | + "api_editable": false, |
| 6923 | + "display_name": "Path", |
| 6924 | + "dynamic": false, |
| 6925 | + "info": "Path to the directory to load files from. Defaults to current directory ('.')", |
| 6926 | + "input_types": [ |
| 6927 | + "Message" |
| 6928 | + ], |
| 6929 | + "list": false, |
| 6930 | + "list_add_label": "Add More", |
| 6931 | + "load_from_db": false, |
| 6932 | + "name": "path", |
| 6933 | + "override_skip": false, |
| 6934 | + "placeholder": "", |
| 6935 | + "required": false, |
| 6936 | + "show": true, |
| 6937 | + "title_case": false, |
| 6938 | + "tool_mode": true, |
| 6939 | + "trace_as_input": true, |
| 6940 | + "trace_as_metadata": true, |
| 6941 | + "track_in_telemetry": false, |
| 6942 | + "type": "str", |
| 6943 | + "value": "." |
| 6944 | + }, |
| 6945 | + "recursive": { |
| 6946 | + "_input_type": "BoolInput", |
| 6947 | + "advanced": true, |
| 6948 | + "api_editable": false, |
| 6949 | + "display_name": "Recursive", |
| 6950 | + "dynamic": false, |
| 6951 | + "info": "If true, the search will be recursive.", |
| 6952 | + "list": false, |
| 6953 | + "list_add_label": "Add More", |
| 6954 | + "name": "recursive", |
| 6955 | + "override_skip": false, |
| 6956 | + "placeholder": "", |
| 6957 | + "required": false, |
| 6958 | + "show": true, |
| 6959 | + "title_case": false, |
| 6960 | + "tool_mode": false, |
| 6961 | + "trace_as_metadata": true, |
| 6962 | + "track_in_telemetry": true, |
| 6963 | + "type": "bool", |
| 6964 | + "value": false |
| 6965 | + }, |
| 6966 | + "silent_errors": { |
| 6967 | + "_input_type": "BoolInput", |
| 6968 | + "advanced": true, |
| 6969 | + "api_editable": false, |
| 6970 | + "display_name": "Silent Errors", |
| 6971 | + "dynamic": false, |
| 6972 | + "info": "If true, errors will not raise an exception.", |
| 6973 | + "list": false, |
| 6974 | + "list_add_label": "Add More", |
| 6975 | + "name": "silent_errors", |
| 6976 | + "override_skip": false, |
| 6977 | + "placeholder": "", |
| 6978 | + "required": false, |
| 6979 | + "show": true, |
| 6980 | + "title_case": false, |
| 6981 | + "tool_mode": false, |
| 6982 | + "trace_as_metadata": true, |
| 6983 | + "track_in_telemetry": true, |
| 6984 | + "type": "bool", |
| 6985 | + "value": false |
| 6986 | + }, |
| 6987 | + "types": { |
| 6988 | + "_input_type": "MultiselectInput", |
| 6989 | + "advanced": false, |
| 6990 | + "api_editable": false, |
| 6991 | + "combobox": false, |
| 6992 | + "display_name": "File Types", |
| 6993 | + "dynamic": false, |
| 6994 | + "info": "File types to load. Select one or more types or leave empty to load all supported types.", |
| 6995 | + "list": true, |
| 6996 | + "list_add_label": "Add More", |
| 6997 | + "name": "types", |
| 6998 | + "options": [ |
| 6999 | + "csv", |
| 7000 | + "json", |
| 7001 | + "pdf", |
| 7002 | + "txt", |
| 7003 | + "md", |
| 7004 | + "mdx", |
| 7005 | + "yaml", |
| 7006 | + "yml", |
| 7007 | + "xml", |
| 7008 | + "html", |
| 7009 | + "htm", |
| 7010 | + "docx", |
| 7011 | + "py", |
| 7012 | + "sh", |
| 7013 | + "sql", |
| 7014 | + "js", |
| 7015 | + "ts", |
| 7016 | + "tsx" |
| 7017 | + ], |
| 7018 | + "override_skip": false, |
| 7019 | + "placeholder": "", |
| 7020 | + "required": false, |
| 7021 | + "show": true, |
| 7022 | + "title_case": false, |
| 7023 | + "toggle": false, |
| 7024 | + "tool_mode": false, |
| 7025 | + "trace_as_metadata": true, |
| 7026 | + "track_in_telemetry": false, |
| 7027 | + "type": "str", |
| 7028 | + "value": [] |
| 7029 | + }, |
| 7030 | + "use_multithreading": { |
| 7031 | + "_input_type": "BoolInput", |
| 7032 | + "advanced": true, |
| 7033 | + "api_editable": false, |
| 7034 | + "display_name": "Use Multithreading", |
| 7035 | + "dynamic": false, |
| 7036 | + "info": "If true, multithreading will be used.", |
| 7037 | + "list": false, |
| 7038 | + "list_add_label": "Add More", |
| 7039 | + "name": "use_multithreading", |
| 7040 | + "override_skip": false, |
| 7041 | + "placeholder": "", |
| 7042 | + "required": false, |
| 7043 | + "show": true, |
| 7044 | + "title_case": false, |
| 7045 | + "tool_mode": false, |
| 7046 | + "trace_as_metadata": true, |
| 7047 | + "track_in_telemetry": true, |
| 7048 | + "type": "bool", |
| 7049 | + "value": false |
| 7050 | + } |
| 7051 | + }, |
| 7052 | + "tool_mode": false |
| 7053 | + }, |
6776 | 7054 | "File": { |
6777 | 7055 | "base_classes": [ |
6778 | 7056 | "Message" |
|
32374 | 32652 | ] |
32375 | 32653 | ], |
32376 | 32654 | "metadata": { |
32377 | | - "num_components": 130, |
| 32655 | + "num_components": 131, |
32378 | 32656 | "num_modules": 17 |
32379 | 32657 | }, |
32380 | | - "sha256": "120ebae4cae40cd1626d6d8535b3a1e163d7560a4f1060b91896b0c63d1dc34a", |
| 32658 | + "sha256": "9f6538b9bac394b60d3cc497ab82e3644260468273e9dbd95301d12fc07682ff", |
32381 | 32659 | "version": "1.11.0" |
32382 | 32660 | } |
0 commit comments