Skip to content

Commit a264ec8

Browse files
authored
Merge pull request #26 from nextcloud/feat/tool-toggling
Feat: tool de-/activation
2 parents dec91cd + dc586ad commit a264ec8

File tree

20 files changed

+397
-136
lines changed

20 files changed

+397
-136
lines changed

ex_app/lib/agent.py

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@
1818
from ex_app.lib.tools import get_tools
1919
from ex_app.lib.memorysaver import MemorySaver
2020

21-
from langchain_community.tools import YouTubeSearchTool, DuckDuckGoSearchResults
2221

2322
# Dummy thread id as we return the whole state
2423
thread = {"configurable": {"thread_id": "thread-1"}}
@@ -47,8 +46,6 @@ def export_conversation(checkpointer):
4746

4847
def react(task, nc: Nextcloud):
4948
safe_tools, dangerous_tools = get_tools(nc)
50-
safe_tools.append(YouTubeSearchTool())
51-
safe_tools.append(DuckDuckGoSearchResults(output_format="list"))
5249

5350
model.bind_nextcloud(nc)
5451

ex_app/lib/all_tools/ai.py

Lines changed: 0 additions & 66 deletions
This file was deleted.

ex_app/lib/all_tools/audio2text.py

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
# SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors
2+
# SPDX-License-Identifier: AGPL-3.0-or-later
3+
from langchain_core.tools import tool
4+
from nc_py_api import Nextcloud
5+
6+
from ex_app.lib.all_tools.lib.files import get_file_id_from_file_url
7+
from ex_app.lib.all_tools.lib.task_processing import run_task
8+
from ex_app.lib.all_tools.lib.decorator import safe_tool
9+
10+
11+
def get_tools(nc: Nextcloud):
12+
13+
@tool
14+
@safe_tool
15+
def transcribe_file(file_url: str) -> str:
16+
"""
17+
Transcribe a media file stored inside the nextcloud
18+
:param file_url: The file URL to the media file in nextcloud (The user can input this using the smart picker for example)
19+
:return: the transcription result
20+
"""
21+
task_input = {
22+
'input': get_file_id_from_file_url(file_url),
23+
}
24+
task_output = run_task(nc, "core:audio2text", task_input).output
25+
return task_output['output']
26+
27+
return [
28+
transcribe_file,
29+
]
30+
31+
def get_category_name():
32+
return "Audio transcription"
33+
34+
def is_available(nc: Nextcloud):
35+
tasktypes = nc.ocs('GET', '/ocs/v2.php/taskprocessing/tasktypes')['types'].keys()
36+
return 'core:audio2text' in tasktypes

ex_app/lib/all_tools/calendar.py

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
import xml.etree.ElementTree as ET
1414
import vobject
1515

16-
from ex_app.lib.all_tools.lib.decorator import safe_tool, dangerous_tool
16+
from ex_app.lib.all_tools.lib.decorator import safe_tool, dangerous_tool, timed_memoize
1717
from ex_app.lib.all_tools.lib.freebusy_finder import find_available_slots, round_to_nearest_half_hour
1818
from ex_app.lib.logger import log
1919

@@ -239,4 +239,12 @@ def add_task(calendar_name: str, title: str, description: str, due_date: Optiona
239239
schedule_event,
240240
find_free_time_slot_in_calendar,
241241
add_task
242-
]
242+
]
243+
244+
def get_category_name():
245+
return "Calendar and Tasks"
246+
247+
@timed_memoize(5*60)
248+
def is_available(nc: Nextcloud):
249+
print('SHOULD DISAPPEAR')
250+
return 'calendar' in nc.apps.get_list()

ex_app/lib/all_tools/contacts.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,4 +89,10 @@ def find_details_of_current_user() -> dict[str, typing.Any]:
8989

9090
return [
9191
find_person_in_contacts, find_details_of_current_user
92-
]
92+
]
93+
94+
def get_category_name():
95+
return "Contacts"
96+
97+
def is_available(nc: Nextcloud):
98+
return True
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
# SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors
2+
# SPDX-License-Identifier: AGPL-3.0-or-later
3+
from langchain_core.tools import tool
4+
from nc_py_api import Nextcloud
5+
6+
from ex_app.lib.all_tools.lib.task_processing import run_task
7+
from ex_app.lib.all_tools.lib.decorator import safe_tool
8+
9+
10+
def get_tools(nc: Nextcloud):
11+
12+
@tool
13+
@safe_tool
14+
def ask_context_chat(question: str) -> str:
15+
"""
16+
Ask the context chat oracle, which knows all of the user's documents, a question about them
17+
:param question: The question to ask
18+
:return: the answer from context chat
19+
"""
20+
21+
task_input = {
22+
'prompt': question,
23+
'scopeType': 'none',
24+
'scopeList': [],
25+
'scopeListMeta': '',
26+
}
27+
task_output = run_task(nc, "context_chat:context_chat", task_input).output
28+
return task_output['output']
29+
30+
return [
31+
ask_context_chat,
32+
]
33+
34+
def get_category_name():
35+
return "Context chat"
36+
37+
def is_available(nc: Nextcloud):
38+
return 'context_chat' in nc.apps.get_list()

ex_app/lib/all_tools/deck.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,4 +60,10 @@ def add_card(deck_id: int, stack_id: int, title: str):
6060
return [
6161
list_decks,
6262
add_card
63-
]
63+
]
64+
65+
def get_category_name():
66+
return "Deck"
67+
68+
def is_available(nc: Nextcloud):
69+
return 'deck' in nc.capabilities

ex_app/lib/all_tools/doc-gen.py

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
# SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors
2+
# SPDX-License-Identifier: AGPL-3.0-or-later
3+
from langchain_core.tools import tool
4+
from nc_py_api import Nextcloud
5+
6+
from ex_app.lib.all_tools.lib.task_processing import run_task
7+
from ex_app.lib.all_tools.lib.decorator import safe_tool
8+
9+
10+
def get_tools(nc: Nextcloud):
11+
12+
@tool
13+
@safe_tool
14+
def generate_document(input: str, format: str) -> str:
15+
"""
16+
Generate a document with the input string as description
17+
:param text: the instructions for the document
18+
:param format: the format of the generated file, available are "text_document" and "spreadsheet_document"
19+
:return: a download link to the generated document
20+
"""
21+
tasktype = "richdocuments:text_to_" + format
22+
task_input = {
23+
'text': input,
24+
}
25+
task = run_task(nc, tasktype, task_input)
26+
return f"https://nextcloud.local/ocs/v2.php/apps/assistant/api/v1/task/{task.id}/output-file/{task.output['file']}/download"
27+
28+
return [
29+
generate_document,
30+
]
31+
32+
def get_category_name():
33+
return "Office document generation"
34+
35+
def is_available(nc: Nextcloud):
36+
return 'richdocuments' in nc.capabilities

ex_app/lib/all_tools/duckduckgo.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
# SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors
2+
# SPDX-License-Identifier: AGPL-3.0-or-later
3+
from langchain_core.tools import tool
4+
from nc_py_api import Nextcloud
5+
from langchain_community.tools import DuckDuckGoSearchResults
6+
7+
from ex_app.lib.all_tools.lib.decorator import safe_tool
8+
9+
10+
def get_tools(nc: Nextcloud):
11+
12+
web_search = DuckDuckGoSearchResults(output_format="list")
13+
return [
14+
web_search,
15+
]
16+
17+
def get_category_name():
18+
return "DuckDuckGo"
19+
20+
def is_available(nc: Nextcloud):
21+
return True

ex_app/lib/all_tools/files.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,4 +58,10 @@ def create_public_sharing_link(path: str):
5858
get_file_content,
5959
get_folder_tree,
6060
create_public_sharing_link,
61-
]
61+
]
62+
63+
def get_category_name():
64+
return "Files"
65+
66+
def is_available(nc: Nextcloud):
67+
return True

0 commit comments

Comments
 (0)