sapiopycommons 2025.9.5a726__py3-none-any.whl → 2025.9.8a728__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.
Potentially problematic release.
This version of sapiopycommons might be problematic. Click here for more details.
- sapiopycommons/ai/tool_service_base.py +25 -15
- sapiopycommons/files/temp_files.py +49 -0
- {sapiopycommons-2025.9.5a726.dist-info → sapiopycommons-2025.9.8a728.dist-info}/METADATA +1 -1
- {sapiopycommons-2025.9.5a726.dist-info → sapiopycommons-2025.9.8a728.dist-info}/RECORD +6 -5
- {sapiopycommons-2025.9.5a726.dist-info → sapiopycommons-2025.9.8a728.dist-info}/WHEEL +0 -0
- {sapiopycommons-2025.9.5a726.dist-info → sapiopycommons-2025.9.8a728.dist-info}/licenses/LICENSE +0 -0
|
@@ -29,6 +29,7 @@ from sapiopycommons.ai.protoapi.session.sapio_conn_info_pb2 import SapioUserSecr
|
|
|
29
29
|
from sapiopycommons.ai.protobuf_utils import ProtobufUtils
|
|
30
30
|
from sapiopycommons.ai.test_client import ContainerType
|
|
31
31
|
from sapiopycommons.files.file_util import FileUtil
|
|
32
|
+
from sapiopycommons.files.temp_files import TempFileHandler
|
|
32
33
|
from sapiopycommons.general.aliases import FieldMap, FieldValue
|
|
33
34
|
|
|
34
35
|
|
|
@@ -318,8 +319,8 @@ class ToolServiceBase(ToolServiceServicer, ABC):
|
|
|
318
319
|
# If the tool is not found, list all of the registered tools for this service so that the LLM can correct
|
|
319
320
|
# the tool it is requesting.
|
|
320
321
|
all_tool_names: str = "\n".join(registered_tools.keys())
|
|
321
|
-
msg: str = (f"Tool \"{find_tool}\" not found in the registered tools for this service. The registered
|
|
322
|
-
f"for this service are: \n{all_tool_names}")
|
|
322
|
+
msg: str = (f"Tool \"{find_tool}\" not found in the registered tools for this service. The registered "
|
|
323
|
+
f"tools for this service are: \n{all_tool_names}")
|
|
323
324
|
return False, msg, [], []
|
|
324
325
|
|
|
325
326
|
# Instantiate the tool class.
|
|
@@ -329,7 +330,8 @@ class ToolServiceBase(ToolServiceServicer, ABC):
|
|
|
329
330
|
tool.setup(user, request, context)
|
|
330
331
|
# Validate that the provided inputs match the tool's expected inputs.
|
|
331
332
|
if len(request.input) != len(tool.input_configs):
|
|
332
|
-
msg: str = f"Expected {len(tool.input_configs)} inputs for this tool, but got {len(request.input)}
|
|
333
|
+
msg: str = (f"Expected {len(tool.input_configs)} inputs for this tool, but got {len(request.input)} "
|
|
334
|
+
f"instead.")
|
|
333
335
|
else:
|
|
334
336
|
msg: str = tool.validate_input()
|
|
335
337
|
# If there is no error message, then the inputs are valid.
|
|
@@ -347,6 +349,9 @@ class ToolServiceBase(ToolServiceServicer, ABC):
|
|
|
347
349
|
except Exception as e:
|
|
348
350
|
tool.log_exception("Exception occurred during tool execution.", e)
|
|
349
351
|
return False, str(e), [], tool.logs
|
|
352
|
+
finally:
|
|
353
|
+
# Clean up any temporary files created by the tool.
|
|
354
|
+
tool.temp_data.cleanup()
|
|
350
355
|
|
|
351
356
|
|
|
352
357
|
class ToolBase(ABC):
|
|
@@ -366,6 +371,8 @@ class ToolBase(ABC):
|
|
|
366
371
|
logger: Logger
|
|
367
372
|
verbose_logging: bool
|
|
368
373
|
|
|
374
|
+
temp_data: TempFileHandler
|
|
375
|
+
|
|
369
376
|
user: SapioUser
|
|
370
377
|
request: ProcessStepRequestPbo
|
|
371
378
|
context: ServicerContext
|
|
@@ -403,6 +410,7 @@ class ToolBase(ABC):
|
|
|
403
410
|
self.output_configs = []
|
|
404
411
|
self._output_container_types = []
|
|
405
412
|
self.config_fields = []
|
|
413
|
+
self.temp_data = TempFileHandler()
|
|
406
414
|
self.logs = []
|
|
407
415
|
self.logger = logging.getLogger(f"ToolBase.{self._name}")
|
|
408
416
|
ensure_logger_initialized(self.logger)
|
|
@@ -528,8 +536,8 @@ class ToolBase(ABC):
|
|
|
528
536
|
"""
|
|
529
537
|
self.config_fields.append(ProtobufUtils.field_def_to_pbo(field))
|
|
530
538
|
|
|
531
|
-
def add_boolean_config_field(self, field_name: str, display_name: str, description: str,
|
|
532
|
-
optional: bool = False) -> None:
|
|
539
|
+
def add_boolean_config_field(self, field_name: str, display_name: str, description: str,
|
|
540
|
+
default_value: bool | None = None, optional: bool = False) -> None:
|
|
533
541
|
"""
|
|
534
542
|
Add a boolean configuration field to the tool. This field will be used to configure the tool in the plan
|
|
535
543
|
manager.
|
|
@@ -552,9 +560,9 @@ class ToolBase(ABC):
|
|
|
552
560
|
)
|
|
553
561
|
))
|
|
554
562
|
|
|
555
|
-
def add_double_config_field(self, field_name: str, display_name: str, description: str,
|
|
556
|
-
|
|
557
|
-
optional: bool = False) -> None:
|
|
563
|
+
def add_double_config_field(self, field_name: str, display_name: str, description: str,
|
|
564
|
+
default_value: float | None = None, min_value: float = -10.**120,
|
|
565
|
+
max_value: float = 10.**120, precision: int = 2, optional: bool = False) -> None:
|
|
558
566
|
"""
|
|
559
567
|
Add a double configuration field to the tool. This field will be used to configure the tool in the plan
|
|
560
568
|
manager.
|
|
@@ -584,7 +592,7 @@ class ToolBase(ABC):
|
|
|
584
592
|
))
|
|
585
593
|
|
|
586
594
|
def add_integer_config_field(self, field_name: str, display_name: str, description: str,
|
|
587
|
-
default_value: int, min_value: int = -2**31, max_value: int = 2**31-1,
|
|
595
|
+
default_value: int | None = None, min_value: int = -2**31, max_value: int = 2**31-1,
|
|
588
596
|
optional: bool = False) -> None:
|
|
589
597
|
"""
|
|
590
598
|
Add an integer configuration field to the tool. This field will be used to configure the tool in the plan
|
|
@@ -613,7 +621,8 @@ class ToolBase(ABC):
|
|
|
613
621
|
))
|
|
614
622
|
|
|
615
623
|
def add_string_config_field(self, field_name: str, display_name: str, description: str,
|
|
616
|
-
default_value: str, max_length: int = 1000, optional: bool = False)
|
|
624
|
+
default_value: str | None = None, max_length: int = 1000, optional: bool = False) \
|
|
625
|
+
-> None:
|
|
617
626
|
"""
|
|
618
627
|
Add a string configuration field to the tool. This field will be used to configure the tool in the plan
|
|
619
628
|
manager.
|
|
@@ -638,8 +647,9 @@ class ToolBase(ABC):
|
|
|
638
647
|
)
|
|
639
648
|
))
|
|
640
649
|
|
|
641
|
-
def add_list_config_field(self, field_name: str, display_name: str, description: str,
|
|
642
|
-
|
|
650
|
+
def add_list_config_field(self, field_name: str, display_name: str, description: str,
|
|
651
|
+
default_value: str | None = None, allowed_values: list[str] | None = None,
|
|
652
|
+
direct_edit: bool = False, optional: bool = False) -> None:
|
|
643
653
|
"""
|
|
644
654
|
Add a list configuration field to the tool. This field will be used to configure the tool in the plan
|
|
645
655
|
manager.
|
|
@@ -668,8 +678,8 @@ class ToolBase(ABC):
|
|
|
668
678
|
))
|
|
669
679
|
|
|
670
680
|
def add_multi_list_config_field(self, field_name: str, display_name: str, description: str,
|
|
671
|
-
default_value: list[str], allowed_values: list[str]
|
|
672
|
-
optional: bool = False) -> None:
|
|
681
|
+
default_value: list[str] | None = None, allowed_values: list[str] | None = None,
|
|
682
|
+
direct_edit: bool = False, optional: bool = False) -> None:
|
|
673
683
|
"""
|
|
674
684
|
Add a multi-select list configuration field to the tool. This field will be used to configure the tool in the
|
|
675
685
|
plan manager.
|
|
@@ -691,7 +701,7 @@ class ToolBase(ABC):
|
|
|
691
701
|
required=not optional,
|
|
692
702
|
editable=True,
|
|
693
703
|
selection_properties=SelectionPropertiesPbo(
|
|
694
|
-
default_value=",".join(default_value),
|
|
704
|
+
default_value=",".join(default_value) if default_value else None,
|
|
695
705
|
static_list_values=allowed_values,
|
|
696
706
|
multi_select=True,
|
|
697
707
|
direct_edit=direct_edit,
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import shutil
|
|
3
|
+
import tempfile
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
# FR-47422: Created class.
|
|
7
|
+
class TempFileHandler:
|
|
8
|
+
"""
|
|
9
|
+
A utility class to manage temporary files and directories.
|
|
10
|
+
"""
|
|
11
|
+
directories: list[str]
|
|
12
|
+
files: list[str]
|
|
13
|
+
|
|
14
|
+
def __init__(self) -> None:
|
|
15
|
+
self.directories = []
|
|
16
|
+
self.files = []
|
|
17
|
+
|
|
18
|
+
def create_temp_directory(self) -> str:
|
|
19
|
+
"""
|
|
20
|
+
:return: The path to a newly created temporary directory.
|
|
21
|
+
"""
|
|
22
|
+
directory: str = tempfile.mkdtemp()
|
|
23
|
+
self.directories.append(directory)
|
|
24
|
+
return directory
|
|
25
|
+
|
|
26
|
+
def create_temp_file(self, data: str | bytes, suffix: str = "") -> str:
|
|
27
|
+
"""
|
|
28
|
+
:param data: The data to write to the temporary file.
|
|
29
|
+
:param suffix: An optional suffix for the temporary file.
|
|
30
|
+
:return: The path to a newly created temporary file containing the provided data.
|
|
31
|
+
"""
|
|
32
|
+
mode: str = 'w' if isinstance(data, str) else 'wb'
|
|
33
|
+
with tempfile.NamedTemporaryFile(mode=mode, suffix=suffix, delete=False) as tmp_file:
|
|
34
|
+
tmp_file.write(data)
|
|
35
|
+
file_path: str = tmp_file.name
|
|
36
|
+
self.files.append(file_path)
|
|
37
|
+
return file_path
|
|
38
|
+
|
|
39
|
+
def cleanup(self) -> None:
|
|
40
|
+
"""
|
|
41
|
+
Delete all temporary files and directories created by this handler.
|
|
42
|
+
"""
|
|
43
|
+
for directory in self.directories:
|
|
44
|
+
if os.path.exists(directory):
|
|
45
|
+
shutil.rmtree(directory)
|
|
46
|
+
|
|
47
|
+
for file_path in self.files:
|
|
48
|
+
if os.path.exists(file_path):
|
|
49
|
+
os.remove(file_path)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: sapiopycommons
|
|
3
|
-
Version: 2025.9.
|
|
3
|
+
Version: 2025.9.8a728
|
|
4
4
|
Summary: Official Sapio Python API Utilities Package
|
|
5
5
|
Project-URL: Homepage, https://github.com/sapiosciences
|
|
6
6
|
Author-email: Jonathan Steck <jsteck@sapiosciences.com>, Yechen Qiao <yqiao@sapiosciences.com>
|
|
@@ -4,7 +4,7 @@ sapiopycommons/ai/converter_service_base.py,sha256=TMSyEekbbqMk9dRuAtLlSJ1sA1H8K
|
|
|
4
4
|
sapiopycommons/ai/protobuf_utils.py,sha256=cBjbxoFAwU02kNUxEce95WnMU2CMuDD-qFaeWgvQJMQ,24599
|
|
5
5
|
sapiopycommons/ai/server.py,sha256=jvmAcs4y8qp0d483wCAUgPlSBSoUUQvCjv_OvQXEGUs,4274
|
|
6
6
|
sapiopycommons/ai/test_client.py,sha256=iPhn7cvKNLmDAXrjpmIkZpW2pDWlUhJZHDLHJbEoWsg,15673
|
|
7
|
-
sapiopycommons/ai/tool_service_base.py,sha256=
|
|
7
|
+
sapiopycommons/ai/tool_service_base.py,sha256=AVW6Yf0l_l4x__dosIZyAJun4UmZAZaBJRYzNru_fD4,45806
|
|
8
8
|
sapiopycommons/ai/protoapi/fielddefinitions/fields_pb2.py,sha256=8tKXwLXcqFGdQHHSEBSi6Fd7dcaCFoOqmhjzqhenb_M,2372
|
|
9
9
|
sapiopycommons/ai/protoapi/fielddefinitions/fields_pb2.pyi,sha256=FwtXmNAf7iYGEFm4kbqb04v77jNHbZg18ZmEDhle_bU,1444
|
|
10
10
|
sapiopycommons/ai/protoapi/fielddefinitions/fields_pb2_grpc.py,sha256=uO25bcnfGqXpP4ggUur54Nr73Wj-DGWftExzLNcxdHI,931
|
|
@@ -66,6 +66,7 @@ sapiopycommons/files/file_data_handler.py,sha256=f96MlkMuQhUCi4oLnzJK5AiuElCp5jL
|
|
|
66
66
|
sapiopycommons/files/file_util.py,sha256=djouyGjsYgWzjz2OBRnSeMDgj6NrsJUm1a2J93J8Wco,31915
|
|
67
67
|
sapiopycommons/files/file_validator.py,sha256=ryg22-93csmRO_Pv0ZpWphNkB74xWZnHyJ23K56qLj0,28761
|
|
68
68
|
sapiopycommons/files/file_writer.py,sha256=hACVl0duCjP28gJ1NPljkjagNCLod0ygUlPbvUmRDNM,17605
|
|
69
|
+
sapiopycommons/files/temp_files.py,sha256=Puv59qtGwiXVJnTm4YuyeZPKw_leXDW906Uz_xbIt6A,1542
|
|
69
70
|
sapiopycommons/flowcyto/flow_cyto.py,sha256=vs9WhXXKz3urpjL8QKSk56B-NSmQR3O3x_WFBKoeO10,3227
|
|
70
71
|
sapiopycommons/flowcyto/flowcyto_data.py,sha256=mYKFuLbtpJ-EsQxLGtu4tNHVlygTxKixgJxJqD68F58,2596
|
|
71
72
|
sapiopycommons/general/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
@@ -98,7 +99,7 @@ sapiopycommons/webhook/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3
|
|
|
98
99
|
sapiopycommons/webhook/webhook_context.py,sha256=D793uLsb1691SalaPnBUk3rOSxn_hYLhdvkaIxjNXss,1909
|
|
99
100
|
sapiopycommons/webhook/webhook_handlers.py,sha256=7o_wXOruhT9auNh8OfhJAh4WhhiPKij67FMBSpGPICc,39939
|
|
100
101
|
sapiopycommons/webhook/webservice_handlers.py,sha256=cvW6Mk_110BzYqkbk63Kg7jWrltBCDALOlkJRu8h4VQ,14300
|
|
101
|
-
sapiopycommons-2025.9.
|
|
102
|
-
sapiopycommons-2025.9.
|
|
103
|
-
sapiopycommons-2025.9.
|
|
104
|
-
sapiopycommons-2025.9.
|
|
102
|
+
sapiopycommons-2025.9.8a728.dist-info/METADATA,sha256=6IMqQ6KDSTEcXMpbfbwpBSC_eGnhn-336JCdZkvNmR0,3142
|
|
103
|
+
sapiopycommons-2025.9.8a728.dist-info/WHEEL,sha256=C2FUgwZgiLbznR-k0b_5k3Ai_1aASOXDss3lzCUsUug,87
|
|
104
|
+
sapiopycommons-2025.9.8a728.dist-info/licenses/LICENSE,sha256=HyVuytGSiAUQ6ErWBHTqt1iSGHhLmlC8fO7jTCuR8dU,16725
|
|
105
|
+
sapiopycommons-2025.9.8a728.dist-info/RECORD,,
|
|
File without changes
|
{sapiopycommons-2025.9.5a726.dist-info → sapiopycommons-2025.9.8a728.dist-info}/licenses/LICENSE
RENAMED
|
File without changes
|