Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62 changes: 58 additions & 4 deletions ex_app/lib/all_tools/files.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
# SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors
# SPDX-License-Identifier: AGPL-3.0-or-later
import niquests
from langchain_core.tools import tool
from nc_py_api import AsyncNextcloudApp
import niquests
from nc_py_api.files.files_async import AsyncFilesAPI, FsNode

from ex_app.lib.all_tools.lib.decorator import dangerous_tool, safe_tool
from ex_app.lib.all_tools.lib.files import get_file_id_from_file_url

from ex_app.lib.all_tools.lib.decorator import safe_tool, dangerous_tool


async def get_tools(nc: AsyncNextcloudApp):

Expand Down Expand Up @@ -50,11 +50,64 @@ async def get_file_content_by_file_link(file_url: str):

return response.text

def __format_fs_node(fsnode: FsNode) -> dict:
# todo: permissions info
return {
'path': fsnode.user_path,
'file_id': fsnode.info.fileid,
'etag': fsnode.etag.replace('"', '').replace("'", ''),

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should not manipulate the etag. If those quotes are not wanted, it's a bug in server IMHO

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that's just the webdav api. All the etags in the oc_filecache table are without double quotes.
Maybe it's fine to do this, or just remove the quotes from the front and back.
Created an issue here to discuss the approach in nc_py_api: cloud-py-api/nc_py_api#448

'bytes': fsnode.info.size,
'creation_date': fsnode.info.creation_date.isoformat(),
'last_modified': fsnode.info.last_modified.isoformat(),
'mimetype': fsnode.info.mimetype,
'is_shared': fsnode.is_shared,
'is_favourite': fsnode.info.favorite,
'is_version': fsnode.info.is_version,
'trash_info': {
'in_trash': fsnode.info.in_trash,
**({
'trashbin_filename': fsnode.info.trashbin_filename,
'original_location': fsnode.info.trashbin_original_location,
'deletion_time': fsnode.info.trashbin_deletion_time,
} if fsnode.info.in_trash else {}),
},
'lock_info': {
'is_locked': fsnode.lock_info.is_locked,
**({
'owner': fsnode.lock_info.owner,
'owner_display_name': fsnode.lock_info.owner_display_name,
'type': fsnode.lock_info.type.name,
'creation_time': fsnode.lock_info.lock_creation_time,
'ttl': fsnode.lock_info.lock_ttl,
'locked_by_app': fsnode.lock_info.owner_editor,
} if fsnode.lock_info.is_locked else {}),
},
}


@tool
@safe_tool
async def get_file_tree(path: str = '/', include_metadata = False, depth: int = 1):
Comment thread
kyteinsky marked this conversation as resolved.
"""
Get the file tree of the user (lists the folders and files the user has in Nextcloud Files)
:param path: the path to enumerate. It should be relative to the root directory like /Media and NOT /userid/files/Media
:param include_metadata: include the etag, file/folder id, last modified times, etc. with the file/folder paths
:param depth: how many directory levels should be included in output. Default = 1 (only specified directory). Max depth = 5.
:return:
"""

files_handle = AsyncFilesAPI(nc._session)
fsnode_list = await files_handle.listdir(path, min(5, depth))
if include_metadata:
return [__format_fs_node(fsnode) for fsnode in fsnode_list]

return [fsnode.user_path for fsnode in fsnode_list]

@tool
@safe_tool
async def get_folder_tree(depth: int):
"""
Get the folder tree of the user (lists the files the user has in Nextcloud Files)
Get the folder tree of the user (lists only the folders the user has in Nextcloud Files)
:param depth: the depth of the returned folder tree
:return:
"""
Expand Down Expand Up @@ -163,6 +216,7 @@ async def delete_file(path: str):
return [
get_file_content,
get_file_content_by_file_link,
get_file_tree,
get_folder_tree,
create_public_sharing_link,
upload_file,
Expand Down
Loading