waldiez 0.4.6__py3-none-any.whl → 0.4.8__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 waldiez might be problematic. Click here for more details.
- waldiez/__init__.py +5 -5
- waldiez/_version.py +1 -1
- waldiez/cli.py +112 -73
- waldiez/exporter.py +61 -19
- waldiez/exporting/__init__.py +25 -6
- waldiez/exporting/agent/__init__.py +7 -3
- waldiez/exporting/agent/code_execution.py +114 -0
- waldiez/exporting/agent/exporter.py +354 -0
- waldiez/exporting/agent/extras/__init__.py +15 -0
- waldiez/exporting/agent/extras/captain_agent_extras.py +315 -0
- waldiez/exporting/agent/extras/group/target.py +178 -0
- waldiez/exporting/agent/extras/group_manager_agent_extas.py +500 -0
- waldiez/exporting/agent/extras/group_member_extras.py +181 -0
- waldiez/exporting/agent/extras/handoffs/__init__.py +19 -0
- waldiez/exporting/agent/extras/handoffs/after_work.py +78 -0
- waldiez/exporting/agent/extras/handoffs/available.py +74 -0
- waldiez/exporting/agent/extras/handoffs/condition.py +158 -0
- waldiez/exporting/agent/extras/handoffs/handoff.py +171 -0
- waldiez/exporting/agent/extras/handoffs/target.py +189 -0
- waldiez/exporting/agent/extras/rag/__init__.py +10 -0
- waldiez/exporting/agent/{utils/rag_user/chroma_utils.py → extras/rag/chroma_extras.py} +16 -15
- waldiez/exporting/agent/{utils/rag_user/mongo_utils.py → extras/rag/mongo_extras.py} +10 -10
- waldiez/exporting/agent/{utils/rag_user/pgvector_utils.py → extras/rag/pgvector_extras.py} +13 -13
- waldiez/exporting/agent/{utils/rag_user/qdrant_utils.py → extras/rag/qdrant_extras.py} +13 -13
- waldiez/exporting/agent/{utils/rag_user/vector_db.py → extras/rag/vector_db_extras.py} +59 -46
- waldiez/exporting/agent/extras/rag_user_proxy_agent_extras.py +245 -0
- waldiez/exporting/agent/extras/reasoning_agent_extras.py +88 -0
- waldiez/exporting/agent/factory.py +95 -0
- waldiez/exporting/agent/processor.py +150 -0
- waldiez/exporting/agent/system_message.py +36 -0
- waldiez/exporting/agent/termination.py +50 -0
- waldiez/exporting/chats/__init__.py +7 -3
- waldiez/exporting/chats/exporter.py +97 -0
- waldiez/exporting/chats/factory.py +65 -0
- waldiez/exporting/chats/processor.py +226 -0
- waldiez/exporting/chats/utils/__init__.py +6 -5
- waldiez/exporting/chats/utils/common.py +11 -45
- waldiez/exporting/chats/utils/group.py +55 -0
- waldiez/exporting/chats/utils/nested.py +37 -52
- waldiez/exporting/chats/utils/sequential.py +72 -61
- waldiez/exporting/chats/utils/{single_chat.py → single.py} +48 -50
- waldiez/exporting/core/__init__.py +196 -0
- waldiez/exporting/core/constants.py +17 -0
- waldiez/exporting/core/content.py +69 -0
- waldiez/exporting/core/context.py +244 -0
- waldiez/exporting/core/enums.py +89 -0
- waldiez/exporting/core/errors.py +19 -0
- waldiez/exporting/core/exporter.py +390 -0
- waldiez/exporting/core/exporters.py +67 -0
- waldiez/exporting/core/extras/__init__.py +39 -0
- waldiez/exporting/core/extras/agent_extras/__init__.py +27 -0
- waldiez/exporting/core/extras/agent_extras/captain_extras.py +57 -0
- waldiez/exporting/core/extras/agent_extras/group_manager_extras.py +102 -0
- waldiez/exporting/core/extras/agent_extras/rag_user_extras.py +53 -0
- waldiez/exporting/core/extras/agent_extras/reasoning_extras.py +68 -0
- waldiez/exporting/core/extras/agent_extras/standard_extras.py +263 -0
- waldiez/exporting/core/extras/base.py +241 -0
- waldiez/exporting/core/extras/chat_extras.py +118 -0
- waldiez/exporting/core/extras/flow_extras.py +70 -0
- waldiez/exporting/core/extras/model_extras.py +73 -0
- waldiez/exporting/core/extras/path_resolver.py +93 -0
- waldiez/exporting/core/extras/serializer.py +138 -0
- waldiez/exporting/core/extras/tool_extras.py +82 -0
- waldiez/exporting/core/protocols.py +259 -0
- waldiez/exporting/core/result.py +705 -0
- waldiez/exporting/core/types.py +329 -0
- waldiez/exporting/core/utils/__init__.py +11 -0
- waldiez/exporting/core/utils/comment.py +33 -0
- waldiez/exporting/core/utils/llm_config.py +117 -0
- waldiez/exporting/core/validation.py +96 -0
- waldiez/exporting/flow/__init__.py +6 -2
- waldiez/exporting/flow/execution_generator.py +193 -0
- waldiez/exporting/flow/exporter.py +107 -0
- waldiez/exporting/flow/factory.py +94 -0
- waldiez/exporting/flow/file_generator.py +214 -0
- waldiez/exporting/flow/merger.py +387 -0
- waldiez/exporting/flow/orchestrator.py +411 -0
- waldiez/exporting/flow/utils/__init__.py +9 -36
- waldiez/exporting/flow/utils/common.py +206 -0
- waldiez/exporting/flow/utils/importing.py +373 -0
- waldiez/exporting/flow/utils/linting.py +200 -0
- waldiez/exporting/flow/utils/{logging_utils.py → logging.py} +23 -9
- waldiez/exporting/models/__init__.py +3 -1
- waldiez/exporting/models/exporter.py +233 -0
- waldiez/exporting/models/factory.py +66 -0
- waldiez/exporting/models/processor.py +139 -0
- waldiez/exporting/tools/__init__.py +11 -0
- waldiez/exporting/tools/exporter.py +207 -0
- waldiez/exporting/tools/factory.py +57 -0
- waldiez/exporting/tools/processor.py +248 -0
- waldiez/exporting/tools/registration.py +133 -0
- waldiez/io/__init__.py +128 -0
- waldiez/io/_ws.py +199 -0
- waldiez/io/models/__init__.py +60 -0
- waldiez/io/models/base.py +66 -0
- waldiez/io/models/constants.py +78 -0
- waldiez/io/models/content/__init__.py +23 -0
- waldiez/io/models/content/audio.py +43 -0
- waldiez/io/models/content/base.py +45 -0
- waldiez/io/models/content/file.py +43 -0
- waldiez/io/models/content/image.py +96 -0
- waldiez/io/models/content/text.py +37 -0
- waldiez/io/models/content/video.py +43 -0
- waldiez/io/models/user_input.py +269 -0
- waldiez/io/models/user_response.py +215 -0
- waldiez/io/mqtt.py +681 -0
- waldiez/io/redis.py +782 -0
- waldiez/io/structured.py +419 -0
- waldiez/io/utils.py +184 -0
- waldiez/io/ws.py +298 -0
- waldiez/logger.py +481 -0
- waldiez/models/__init__.py +108 -51
- waldiez/models/agents/__init__.py +34 -70
- waldiez/models/agents/agent/__init__.py +10 -4
- waldiez/models/agents/agent/agent.py +466 -65
- waldiez/models/agents/agent/agent_data.py +119 -47
- waldiez/models/agents/agent/agent_type.py +13 -2
- waldiez/models/agents/agent/code_execution.py +12 -12
- waldiez/models/agents/agent/human_input_mode.py +8 -0
- waldiez/models/agents/agent/{linked_skill.py → linked_tool.py} +7 -7
- waldiez/models/agents/agent/nested_chat.py +35 -7
- waldiez/models/agents/agent/termination_message.py +30 -22
- waldiez/models/agents/{swarm_agent → agent}/update_system_message.py +22 -22
- waldiez/models/agents/agents.py +58 -63
- waldiez/models/agents/assistant/assistant.py +4 -4
- waldiez/models/agents/assistant/assistant_data.py +13 -1
- waldiez/models/agents/{captain_agent → captain}/captain_agent.py +5 -5
- waldiez/models/agents/{captain_agent → captain}/captain_agent_data.py +5 -5
- waldiez/models/agents/extra_requirements.py +11 -16
- waldiez/models/agents/group_manager/group_manager.py +103 -13
- waldiez/models/agents/group_manager/group_manager_data.py +36 -14
- waldiez/models/agents/group_manager/speakers.py +77 -24
- waldiez/models/agents/{rag_user → rag_user_proxy}/__init__.py +16 -16
- waldiez/models/agents/rag_user_proxy/rag_user_proxy.py +64 -0
- waldiez/models/agents/{rag_user/rag_user_data.py → rag_user_proxy/rag_user_proxy_data.py} +6 -5
- waldiez/models/agents/{rag_user → rag_user_proxy}/retrieve_config.py +182 -114
- waldiez/models/agents/{rag_user → rag_user_proxy}/vector_db_config.py +13 -13
- waldiez/models/agents/reasoning/reasoning_agent.py +6 -6
- waldiez/models/agents/reasoning/reasoning_agent_data.py +110 -63
- waldiez/models/agents/reasoning/reasoning_agent_reason_config.py +38 -10
- waldiez/models/agents/user_proxy/user_proxy.py +11 -7
- waldiez/models/agents/user_proxy/user_proxy_data.py +2 -2
- waldiez/models/chat/__init__.py +2 -1
- waldiez/models/chat/chat.py +166 -87
- waldiez/models/chat/chat_data.py +99 -136
- waldiez/models/chat/chat_message.py +33 -23
- waldiez/models/chat/chat_nested.py +31 -30
- waldiez/models/chat/chat_summary.py +10 -8
- waldiez/models/common/__init__.py +52 -2
- waldiez/models/common/ag2_version.py +1 -1
- waldiez/models/common/base.py +38 -7
- waldiez/models/common/dict_utils.py +42 -17
- waldiez/models/common/handoff.py +459 -0
- waldiez/models/common/id_generator.py +19 -0
- waldiez/models/common/method_utils.py +130 -68
- waldiez/{exporting/base/utils → models/common}/naming.py +38 -61
- waldiez/models/common/waldiez_version.py +37 -0
- waldiez/models/flow/__init__.py +9 -2
- waldiez/models/flow/connection.py +18 -0
- waldiez/models/flow/flow.py +311 -215
- waldiez/models/flow/flow_data.py +207 -40
- waldiez/models/flow/info.py +85 -0
- waldiez/models/flow/naming.py +131 -0
- waldiez/models/model/__init__.py +7 -1
- waldiez/models/model/extra_requirements.py +3 -12
- waldiez/models/model/model.py +76 -21
- waldiez/models/model/model_data.py +108 -20
- waldiez/models/tool/__init__.py +16 -0
- waldiez/models/tool/extra_requirements.py +36 -0
- waldiez/models/{skill/skill.py → tool/tool.py} +88 -88
- waldiez/models/tool/tool_data.py +51 -0
- waldiez/models/tool/tool_type.py +8 -0
- waldiez/models/waldiez.py +97 -80
- waldiez/runner.py +114 -49
- waldiez/running/__init__.py +1 -1
- waldiez/running/environment.py +49 -68
- waldiez/running/gen_seq_diagram.py +16 -14
- waldiez/running/running.py +53 -34
- waldiez/utils/__init__.py +0 -4
- waldiez/utils/cli_extras/jupyter.py +5 -3
- waldiez/utils/cli_extras/runner.py +6 -4
- waldiez/utils/cli_extras/studio.py +6 -4
- waldiez/utils/conflict_checker.py +15 -9
- waldiez/utils/flaml_warnings.py +5 -5
- {waldiez-0.4.6.dist-info → waldiez-0.4.8.dist-info}/METADATA +235 -91
- waldiez-0.4.8.dist-info/RECORD +200 -0
- waldiez/exporting/agent/agent_exporter.py +0 -297
- waldiez/exporting/agent/utils/__init__.py +0 -23
- waldiez/exporting/agent/utils/captain_agent.py +0 -263
- waldiez/exporting/agent/utils/code_execution.py +0 -65
- waldiez/exporting/agent/utils/group_manager.py +0 -220
- waldiez/exporting/agent/utils/rag_user/__init__.py +0 -7
- waldiez/exporting/agent/utils/rag_user/rag_user.py +0 -209
- waldiez/exporting/agent/utils/reasoning.py +0 -36
- waldiez/exporting/agent/utils/swarm_agent.py +0 -469
- waldiez/exporting/agent/utils/teachability.py +0 -41
- waldiez/exporting/agent/utils/termination_message.py +0 -44
- waldiez/exporting/base/__init__.py +0 -25
- waldiez/exporting/base/agent_position.py +0 -75
- waldiez/exporting/base/base_exporter.py +0 -118
- waldiez/exporting/base/export_position.py +0 -48
- waldiez/exporting/base/import_position.py +0 -23
- waldiez/exporting/base/mixin.py +0 -137
- waldiez/exporting/base/utils/__init__.py +0 -18
- waldiez/exporting/base/utils/comments.py +0 -96
- waldiez/exporting/base/utils/path_check.py +0 -68
- waldiez/exporting/base/utils/to_string.py +0 -84
- waldiez/exporting/chats/chats_exporter.py +0 -240
- waldiez/exporting/chats/utils/swarm.py +0 -210
- waldiez/exporting/flow/flow_exporter.py +0 -528
- waldiez/exporting/flow/utils/agent_utils.py +0 -204
- waldiez/exporting/flow/utils/chat_utils.py +0 -71
- waldiez/exporting/flow/utils/def_main.py +0 -77
- waldiez/exporting/flow/utils/flow_content.py +0 -202
- waldiez/exporting/flow/utils/flow_names.py +0 -116
- waldiez/exporting/flow/utils/importing_utils.py +0 -227
- waldiez/exporting/models/models_exporter.py +0 -199
- waldiez/exporting/models/utils.py +0 -174
- waldiez/exporting/skills/__init__.py +0 -9
- waldiez/exporting/skills/skills_exporter.py +0 -176
- waldiez/exporting/skills/utils.py +0 -369
- waldiez/models/agents/agent/teachability.py +0 -70
- waldiez/models/agents/rag_user/rag_user.py +0 -60
- waldiez/models/agents/swarm_agent/__init__.py +0 -50
- waldiez/models/agents/swarm_agent/after_work.py +0 -179
- waldiez/models/agents/swarm_agent/on_condition.py +0 -105
- waldiez/models/agents/swarm_agent/on_condition_available.py +0 -142
- waldiez/models/agents/swarm_agent/on_condition_target.py +0 -40
- waldiez/models/agents/swarm_agent/swarm_agent.py +0 -107
- waldiez/models/agents/swarm_agent/swarm_agent_data.py +0 -124
- waldiez/models/flow/utils.py +0 -232
- waldiez/models/skill/__init__.py +0 -16
- waldiez/models/skill/extra_requirements.py +0 -36
- waldiez/models/skill/skill_data.py +0 -53
- waldiez/models/skill/skill_type.py +0 -8
- waldiez/utils/pysqlite3_checker.py +0 -308
- waldiez/utils/rdps_checker.py +0 -122
- waldiez-0.4.6.dist-info/RECORD +0 -149
- /waldiez/models/agents/{captain_agent → captain}/__init__.py +0 -0
- /waldiez/models/agents/{captain_agent → captain}/captain_agent_lib_entry.py +0 -0
- {waldiez-0.4.6.dist-info → waldiez-0.4.8.dist-info}/WHEEL +0 -0
- {waldiez-0.4.6.dist-info → waldiez-0.4.8.dist-info}/entry_points.txt +0 -0
- {waldiez-0.4.6.dist-info → waldiez-0.4.8.dist-info}/licenses/LICENSE +0 -0
- {waldiez-0.4.6.dist-info → waldiez-0.4.8.dist-info}/licenses/NOTICE.md +0 -0
|
@@ -0,0 +1,373 @@
|
|
|
1
|
+
# SPDX-License-Identifier: Apache-2.0.
|
|
2
|
+
# Copyright (c) 2024 - 2025 Waldiez and contributors.
|
|
3
|
+
"""Get the standard imports for the flow exporter."""
|
|
4
|
+
|
|
5
|
+
from typing import Optional
|
|
6
|
+
|
|
7
|
+
from waldiez.exporting.core import ImportPosition
|
|
8
|
+
|
|
9
|
+
BUILTIN_IMPORTS = [
|
|
10
|
+
"import csv",
|
|
11
|
+
"import importlib",
|
|
12
|
+
"import json",
|
|
13
|
+
"import os",
|
|
14
|
+
"import sqlite3",
|
|
15
|
+
"import sys",
|
|
16
|
+
"from dataclasses import asdict",
|
|
17
|
+
"from pprint import pprint",
|
|
18
|
+
"from types import ModuleType",
|
|
19
|
+
]
|
|
20
|
+
TYPING_IMPORT_NAMES = [
|
|
21
|
+
"Annotated",
|
|
22
|
+
"Any",
|
|
23
|
+
"Callable",
|
|
24
|
+
"Dict",
|
|
25
|
+
"List",
|
|
26
|
+
"Optional",
|
|
27
|
+
"Set",
|
|
28
|
+
"Tuple",
|
|
29
|
+
"Union",
|
|
30
|
+
]
|
|
31
|
+
# pylint: disable=inconsistent-quotes
|
|
32
|
+
TYPING_IMPORTS = [f"from typing import {', '.join(TYPING_IMPORT_NAMES)}"]
|
|
33
|
+
COMMON_AUTOGEN_IMPORTS = [
|
|
34
|
+
"from autogen import Agent",
|
|
35
|
+
"from autogen import Cache",
|
|
36
|
+
"from autogen import ConversableAgent",
|
|
37
|
+
"from autogen import ChatResult",
|
|
38
|
+
"from autogen import GroupChat",
|
|
39
|
+
"from autogen import runtime_logging",
|
|
40
|
+
]
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
def get_sorted_imports(collected_imports: list[str]) -> list[str]:
|
|
44
|
+
"""Get the sorted imports.
|
|
45
|
+
|
|
46
|
+
Parameters
|
|
47
|
+
----------
|
|
48
|
+
collected_imports : list[str]
|
|
49
|
+
The collected imports.
|
|
50
|
+
|
|
51
|
+
Returns
|
|
52
|
+
-------
|
|
53
|
+
list[str]
|
|
54
|
+
The sorted imports.
|
|
55
|
+
"""
|
|
56
|
+
# Remove duplicates while preserving order by converting to dict
|
|
57
|
+
unique_imports = list(dict.fromkeys(collected_imports))
|
|
58
|
+
|
|
59
|
+
sorted_imports = sorted(
|
|
60
|
+
[imp for imp in unique_imports if imp.startswith("import ")]
|
|
61
|
+
) + sorted([imp for imp in unique_imports if imp.startswith("from ")])
|
|
62
|
+
return sorted_imports
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
def sort_imports(
|
|
66
|
+
all_imports: list[tuple[str, ImportPosition]],
|
|
67
|
+
) -> tuple[list[str], list[str], list[str], list[str], bool]:
|
|
68
|
+
"""Sort the imports.
|
|
69
|
+
|
|
70
|
+
Parameters
|
|
71
|
+
----------
|
|
72
|
+
all_imports : list[tuple[str, ImportPosition]]
|
|
73
|
+
All the imports.
|
|
74
|
+
|
|
75
|
+
Returns
|
|
76
|
+
-------
|
|
77
|
+
tuple[list[str], list[str], list[str], list[str], bool]
|
|
78
|
+
The sorted imports and a flag if we got `import autogen`.
|
|
79
|
+
"""
|
|
80
|
+
builtin_imports: list[str] = BUILTIN_IMPORTS.copy() + TYPING_IMPORTS.copy()
|
|
81
|
+
third_party_imports: list[str] = []
|
|
82
|
+
local_imports: list[str] = []
|
|
83
|
+
autogen_imports: list[str] = COMMON_AUTOGEN_IMPORTS.copy()
|
|
84
|
+
got_import_autogen = False
|
|
85
|
+
|
|
86
|
+
for import_string, position in all_imports:
|
|
87
|
+
if "import autogen" in import_string:
|
|
88
|
+
got_import_autogen = True
|
|
89
|
+
continue
|
|
90
|
+
if import_string.startswith("from autogen"):
|
|
91
|
+
autogen_imports.append(import_string)
|
|
92
|
+
continue
|
|
93
|
+
if position == ImportPosition.BUILTINS:
|
|
94
|
+
builtin_imports.append(import_string)
|
|
95
|
+
elif position == ImportPosition.THIRD_PARTY:
|
|
96
|
+
third_party_imports.append(import_string)
|
|
97
|
+
elif position == ImportPosition.LOCAL: # pragma: no branch
|
|
98
|
+
local_imports.append(import_string)
|
|
99
|
+
|
|
100
|
+
autogen_imports = clean_and_group_autogen_imports(autogen_imports)
|
|
101
|
+
third_party_imports = ensure_np_import(third_party_imports)
|
|
102
|
+
sorted_builtins = get_sorted_imports(builtin_imports)
|
|
103
|
+
sorted_third_party = get_sorted_imports(third_party_imports)
|
|
104
|
+
sorted_locals = get_sorted_imports(local_imports)
|
|
105
|
+
|
|
106
|
+
return (
|
|
107
|
+
sorted_builtins,
|
|
108
|
+
sorted(autogen_imports),
|
|
109
|
+
sorted_third_party,
|
|
110
|
+
sorted_locals,
|
|
111
|
+
got_import_autogen,
|
|
112
|
+
)
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
def clean_and_group_autogen_imports(autogen_imports: list[str]) -> list[str]:
|
|
116
|
+
"""Cleanup and group autogen imports.
|
|
117
|
+
|
|
118
|
+
Parameters
|
|
119
|
+
----------
|
|
120
|
+
autogen_imports : list[str]
|
|
121
|
+
List of autogen import statements
|
|
122
|
+
|
|
123
|
+
Returns
|
|
124
|
+
-------
|
|
125
|
+
list[str]
|
|
126
|
+
Cleaned and grouped autogen imports
|
|
127
|
+
"""
|
|
128
|
+
# Group imports by module path
|
|
129
|
+
import_groups: dict[str, set[str]] = {}
|
|
130
|
+
direct_imports: set[str] = set()
|
|
131
|
+
|
|
132
|
+
for imp in autogen_imports:
|
|
133
|
+
imp = imp.strip()
|
|
134
|
+
if not imp:
|
|
135
|
+
continue
|
|
136
|
+
|
|
137
|
+
if imp.startswith("import autogen"):
|
|
138
|
+
direct_imports.add(imp)
|
|
139
|
+
continue
|
|
140
|
+
|
|
141
|
+
# Parse "from autogen.module import items"
|
|
142
|
+
if imp.startswith("from autogen"): # pragma: no branch
|
|
143
|
+
parts = imp.split(" import ")
|
|
144
|
+
if len(parts) == 2: # pragma: no branch
|
|
145
|
+
module_path = parts[0] # "from autogen.module"
|
|
146
|
+
items = parts[1].strip()
|
|
147
|
+
|
|
148
|
+
if module_path not in import_groups:
|
|
149
|
+
import_groups[module_path] = set()
|
|
150
|
+
|
|
151
|
+
# Handle multiple imports in one line
|
|
152
|
+
for item in items.split(","):
|
|
153
|
+
import_groups[module_path].add(item.strip())
|
|
154
|
+
|
|
155
|
+
# Build cleaned import list
|
|
156
|
+
cleaned_imports: list[str] = []
|
|
157
|
+
|
|
158
|
+
# Add direct imports first
|
|
159
|
+
cleaned_imports.extend(sorted(direct_imports))
|
|
160
|
+
|
|
161
|
+
# Add grouped imports, sorted by module path
|
|
162
|
+
for module_path in sorted(import_groups.keys()):
|
|
163
|
+
sorted_items = sorted(import_groups[module_path])
|
|
164
|
+
items_str = ", ".join(sorted_items)
|
|
165
|
+
import_statement = f"{module_path} import {items_str}"
|
|
166
|
+
cleaned_imports.append(import_statement)
|
|
167
|
+
|
|
168
|
+
return cleaned_imports
|
|
169
|
+
|
|
170
|
+
|
|
171
|
+
def get_the_imports_string(
|
|
172
|
+
all_imports: list[tuple[str, ImportPosition]],
|
|
173
|
+
is_async: bool,
|
|
174
|
+
) -> str:
|
|
175
|
+
"""Get the final imports string.
|
|
176
|
+
|
|
177
|
+
Parameters
|
|
178
|
+
----------
|
|
179
|
+
all_imports : list[tuple[str, ImportPosition]]
|
|
180
|
+
All the imports.
|
|
181
|
+
is_async : bool
|
|
182
|
+
If the flow is async.
|
|
183
|
+
|
|
184
|
+
Returns
|
|
185
|
+
-------
|
|
186
|
+
str
|
|
187
|
+
The final imports string.
|
|
188
|
+
"""
|
|
189
|
+
(
|
|
190
|
+
builtin_imports,
|
|
191
|
+
autogen_imports,
|
|
192
|
+
third_party_imports,
|
|
193
|
+
local_imports,
|
|
194
|
+
got_import_autogen,
|
|
195
|
+
) = sort_imports(all_imports)
|
|
196
|
+
|
|
197
|
+
# Get the final imports string.
|
|
198
|
+
# Making sure that there are two lines
|
|
199
|
+
# after each import section
|
|
200
|
+
# (builtin, third party, local)
|
|
201
|
+
final_string = "\n".join(builtin_imports) + "\n"
|
|
202
|
+
while not final_string.endswith("\n\n"):
|
|
203
|
+
final_string += "\n"
|
|
204
|
+
|
|
205
|
+
if is_async:
|
|
206
|
+
final_string += (
|
|
207
|
+
"\nimport aiofiles"
|
|
208
|
+
"\nimport aiosqlite"
|
|
209
|
+
"\nimport anyio"
|
|
210
|
+
"\nimport nest_asyncio"
|
|
211
|
+
"\nfrom aiocsv import AsyncDictWriter\n"
|
|
212
|
+
)
|
|
213
|
+
|
|
214
|
+
if got_import_autogen:
|
|
215
|
+
final_string += "\nimport autogen # type: ignore\n"
|
|
216
|
+
|
|
217
|
+
if autogen_imports: # pragma: no branch
|
|
218
|
+
final_string += "\n".join(autogen_imports) + "\n"
|
|
219
|
+
|
|
220
|
+
if third_party_imports: # pragma: no branch
|
|
221
|
+
final_string += "\n".join(third_party_imports) + "\n"
|
|
222
|
+
|
|
223
|
+
while not final_string.endswith("\n\n"):
|
|
224
|
+
final_string += "\n"
|
|
225
|
+
|
|
226
|
+
if local_imports:
|
|
227
|
+
final_string += "\n".join(local_imports) + "\n"
|
|
228
|
+
|
|
229
|
+
while not final_string.endswith("\n\n"):
|
|
230
|
+
final_string += "\n"
|
|
231
|
+
|
|
232
|
+
if is_async:
|
|
233
|
+
final_string += (
|
|
234
|
+
"# pylint: disable=broad-exception-caught\n"
|
|
235
|
+
"try:\n"
|
|
236
|
+
" nest_asyncio.apply() # pyright: ignore\n"
|
|
237
|
+
"except BaseException:\n"
|
|
238
|
+
" pass # maybe on uvloop?\n"
|
|
239
|
+
)
|
|
240
|
+
|
|
241
|
+
return final_string.replace("\n\n\n", "\n\n") # avoid too many newlines
|
|
242
|
+
|
|
243
|
+
|
|
244
|
+
def ensure_np_import(third_party_imports: list[str]) -> list[str]:
|
|
245
|
+
"""Ensure numpy is imported.
|
|
246
|
+
|
|
247
|
+
Parameters
|
|
248
|
+
----------
|
|
249
|
+
third_party_imports : list[str]
|
|
250
|
+
The third party imports.
|
|
251
|
+
|
|
252
|
+
Returns
|
|
253
|
+
-------
|
|
254
|
+
list[str]
|
|
255
|
+
The third party imports with numpy.
|
|
256
|
+
"""
|
|
257
|
+
if (
|
|
258
|
+
not third_party_imports
|
|
259
|
+
or "import numpy as np" not in third_party_imports
|
|
260
|
+
):
|
|
261
|
+
third_party_imports.append("import numpy as np")
|
|
262
|
+
return third_party_imports
|
|
263
|
+
|
|
264
|
+
|
|
265
|
+
def gather_imports(
|
|
266
|
+
model_imports: Optional[list[tuple[str, ImportPosition]]] = None,
|
|
267
|
+
tool_imports: Optional[list[tuple[str, ImportPosition]]] = None,
|
|
268
|
+
chat_imports: Optional[list[tuple[str, ImportPosition]]] = None,
|
|
269
|
+
agent_imports: Optional[list[tuple[str, ImportPosition]]] = None,
|
|
270
|
+
) -> list[tuple[str, ImportPosition]]:
|
|
271
|
+
"""Gather all the imports.
|
|
272
|
+
|
|
273
|
+
Parameters
|
|
274
|
+
----------
|
|
275
|
+
model_imports : tuple[str, ImportPosition]
|
|
276
|
+
The model imports.
|
|
277
|
+
tool_imports : tuple[str, ImportPosition]
|
|
278
|
+
The tool imports.
|
|
279
|
+
chat_imports : tuple[str, ImportPosition]
|
|
280
|
+
The chat imports.
|
|
281
|
+
agent_imports : tuple[str, ImportPosition]
|
|
282
|
+
The agent imports.
|
|
283
|
+
|
|
284
|
+
Returns
|
|
285
|
+
-------
|
|
286
|
+
tuple[str, ImportPosition]
|
|
287
|
+
The gathered imports.
|
|
288
|
+
"""
|
|
289
|
+
all_imports: list[tuple[str, ImportPosition]] = []
|
|
290
|
+
for import_statement in BUILTIN_IMPORTS:
|
|
291
|
+
all_imports.append(
|
|
292
|
+
(
|
|
293
|
+
import_statement,
|
|
294
|
+
ImportPosition.BUILTINS,
|
|
295
|
+
)
|
|
296
|
+
)
|
|
297
|
+
if model_imports:
|
|
298
|
+
all_imports.extend(model_imports)
|
|
299
|
+
if tool_imports:
|
|
300
|
+
all_imports.extend(tool_imports)
|
|
301
|
+
if chat_imports:
|
|
302
|
+
all_imports.extend(chat_imports)
|
|
303
|
+
if agent_imports:
|
|
304
|
+
all_imports.extend(agent_imports)
|
|
305
|
+
all_imports = deduplicate_imports(all_imports)
|
|
306
|
+
one_line_typing_imports: list[tuple[str, ImportPosition]] = []
|
|
307
|
+
final_imports: list[tuple[str, ImportPosition]] = []
|
|
308
|
+
for import_tuple in all_imports:
|
|
309
|
+
if import_tuple[0].startswith("from typing import "):
|
|
310
|
+
one_line_typing_imports.append(import_tuple)
|
|
311
|
+
else:
|
|
312
|
+
final_imports.append(import_tuple)
|
|
313
|
+
final_typing_imports = get_the_typing_imports(one_line_typing_imports)
|
|
314
|
+
final_imports.insert(1, (final_typing_imports, ImportPosition.BUILTINS))
|
|
315
|
+
return final_imports
|
|
316
|
+
|
|
317
|
+
|
|
318
|
+
def get_the_typing_imports(
|
|
319
|
+
one_line_typing_imports: list[tuple[str, ImportPosition]],
|
|
320
|
+
) -> str:
|
|
321
|
+
"""Get the typing imports as a single line.
|
|
322
|
+
|
|
323
|
+
Parameters
|
|
324
|
+
----------
|
|
325
|
+
one_line_typing_imports : list[tuple[str, ImportPosition]]
|
|
326
|
+
The one line typing imports.
|
|
327
|
+
|
|
328
|
+
Returns
|
|
329
|
+
-------
|
|
330
|
+
str
|
|
331
|
+
The final typing imports string.
|
|
332
|
+
"""
|
|
333
|
+
# merge the ones found in the imports
|
|
334
|
+
# with the default ones
|
|
335
|
+
typing_imports: set[str] = set(TYPING_IMPORT_NAMES)
|
|
336
|
+
for import_tuple in one_line_typing_imports:
|
|
337
|
+
if import_tuple[0].startswith(
|
|
338
|
+
"from typing import "
|
|
339
|
+
): # pragma: no branch
|
|
340
|
+
# extract the names from the import statement
|
|
341
|
+
names = import_tuple[0].split("from typing import ")[1]
|
|
342
|
+
for name in names.split(","):
|
|
343
|
+
typing_imports.add(name.strip())
|
|
344
|
+
# create the final import statement
|
|
345
|
+
final_typing_imports = (
|
|
346
|
+
f"from typing import {', '.join(sorted(typing_imports))}"
|
|
347
|
+
)
|
|
348
|
+
return final_typing_imports.strip()
|
|
349
|
+
|
|
350
|
+
|
|
351
|
+
def deduplicate_imports(
|
|
352
|
+
imports: list[tuple[str, ImportPosition]],
|
|
353
|
+
) -> list[tuple[str, ImportPosition]]:
|
|
354
|
+
"""Deduplicate imports while preserving order.
|
|
355
|
+
|
|
356
|
+
Parameters
|
|
357
|
+
----------
|
|
358
|
+
imports : list[tuple[str, ImportPosition]]
|
|
359
|
+
The imports to deduplicate.
|
|
360
|
+
|
|
361
|
+
Returns
|
|
362
|
+
-------
|
|
363
|
+
list[tuple[str, ImportPosition]]
|
|
364
|
+
The deduplicated imports.
|
|
365
|
+
"""
|
|
366
|
+
# Remove duplicates while preserving order
|
|
367
|
+
seen: set[tuple[str, ImportPosition]] = set()
|
|
368
|
+
deduplicated_imports: list[tuple[str, ImportPosition]] = []
|
|
369
|
+
for import_tuple in imports:
|
|
370
|
+
if import_tuple not in seen:
|
|
371
|
+
seen.add(import_tuple)
|
|
372
|
+
deduplicated_imports.append(import_tuple)
|
|
373
|
+
return deduplicated_imports
|
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
# SPDX-License-Identifier: Apache-2.0.
|
|
2
|
+
# Copyright (c) 2024 - 2025 Waldiez and contributors.
|
|
3
|
+
"""Linting comments to include in the generated code."""
|
|
4
|
+
|
|
5
|
+
import math
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def split_linter_comment(
|
|
9
|
+
prefix: str,
|
|
10
|
+
rules: list[str],
|
|
11
|
+
max_lines: int = 3,
|
|
12
|
+
) -> str:
|
|
13
|
+
"""Split linter comment.
|
|
14
|
+
|
|
15
|
+
Parameters
|
|
16
|
+
----------
|
|
17
|
+
prefix : str
|
|
18
|
+
The prefix for the comment, e.g., "# pylint: disable=" or "# pyright: ".
|
|
19
|
+
rules : list[str]
|
|
20
|
+
The list of linter rules to include in the comment.
|
|
21
|
+
max_lines : int, optional
|
|
22
|
+
The maximum number of lines to split the comment into, by default 3.
|
|
23
|
+
|
|
24
|
+
Returns
|
|
25
|
+
-------
|
|
26
|
+
str
|
|
27
|
+
The formatted comment string with the rules split into lines.
|
|
28
|
+
"""
|
|
29
|
+
# Calculate minimum number of rules per line to not exceed max_lines
|
|
30
|
+
rules_per_line = max(1, math.ceil(len(rules) / max_lines))
|
|
31
|
+
# pylint: disable=inconsistent-quotes
|
|
32
|
+
lines = [
|
|
33
|
+
f"{prefix}{','.join(rules[i : i + rules_per_line])}"
|
|
34
|
+
for i in range(0, len(rules), rules_per_line)
|
|
35
|
+
]
|
|
36
|
+
return "\n".join(lines) + "\n"
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
PYLINT_RULES = [
|
|
40
|
+
"line-too-long",
|
|
41
|
+
"unknown-option-value",
|
|
42
|
+
"unused-argument",
|
|
43
|
+
"unused-import",
|
|
44
|
+
"unused-variable",
|
|
45
|
+
"invalid-name",
|
|
46
|
+
"import-error",
|
|
47
|
+
"import-outside-toplevel",
|
|
48
|
+
"inconsistent-quotes",
|
|
49
|
+
"missing-function-docstring",
|
|
50
|
+
"missing-param-doc",
|
|
51
|
+
"missing-return-doc",
|
|
52
|
+
"ungrouped-imports",
|
|
53
|
+
"unnecessary-lambda-assignment",
|
|
54
|
+
"too-many-arguments",
|
|
55
|
+
"too-many-locals",
|
|
56
|
+
"too-many-try-statements",
|
|
57
|
+
"broad-exception-caught",
|
|
58
|
+
]
|
|
59
|
+
PYRIGHT_RULES = [
|
|
60
|
+
"reportUnusedImport",
|
|
61
|
+
"reportMissingTypeStubs",
|
|
62
|
+
"reportUnknownArgumentType",
|
|
63
|
+
"reportUnknownMemberType",
|
|
64
|
+
"reportUnknownLambdaType",
|
|
65
|
+
"reportUnnecessaryIsInstance",
|
|
66
|
+
"reportUnknownVariableType",
|
|
67
|
+
]
|
|
68
|
+
|
|
69
|
+
MYPY_RULES = [
|
|
70
|
+
"import-untyped",
|
|
71
|
+
"no-redef",
|
|
72
|
+
"unused-ignore",
|
|
73
|
+
"import-not-found",
|
|
74
|
+
]
|
|
75
|
+
|
|
76
|
+
FLAKE8_RULES = ["E501"]
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
def get_flake8_ignore_comment(rules: list[str] | None = None) -> str:
|
|
80
|
+
"""Get the flake8 ignore comment string.
|
|
81
|
+
|
|
82
|
+
Parameters
|
|
83
|
+
----------
|
|
84
|
+
rules : Optional[list[str]], optional
|
|
85
|
+
The flake8 rules to ignore, by default None.
|
|
86
|
+
|
|
87
|
+
Returns
|
|
88
|
+
-------
|
|
89
|
+
str
|
|
90
|
+
The flake8 ignore comment string.
|
|
91
|
+
|
|
92
|
+
Example
|
|
93
|
+
-------
|
|
94
|
+
```python
|
|
95
|
+
>>> get_flake8_ignore_comment(["E501", "F401"])
|
|
96
|
+
|
|
97
|
+
# flake8: noqa: E501, F401
|
|
98
|
+
```
|
|
99
|
+
"""
|
|
100
|
+
if not rules:
|
|
101
|
+
rules = FLAKE8_RULES
|
|
102
|
+
prefix = "# flake8: noqa: "
|
|
103
|
+
output = ", ".join(rules)
|
|
104
|
+
return prefix + output + "\n"
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
def get_pylint_ignore_comment(rules: list[str] | None = None) -> str:
|
|
108
|
+
"""Get the pylint ignore comment string.
|
|
109
|
+
|
|
110
|
+
Parameters
|
|
111
|
+
----------
|
|
112
|
+
rules : Optional[list[str]], optional
|
|
113
|
+
The pylint rules to ignore, by default None.
|
|
114
|
+
|
|
115
|
+
Returns
|
|
116
|
+
-------
|
|
117
|
+
str
|
|
118
|
+
The pylint ignore comment string.
|
|
119
|
+
|
|
120
|
+
Example
|
|
121
|
+
-------
|
|
122
|
+
```python
|
|
123
|
+
>>> get_pylint_ignore_comment(True, ["invalid-name", "line-too-long"])
|
|
124
|
+
|
|
125
|
+
# pylint: disable=invalid-name, line-too-long
|
|
126
|
+
```
|
|
127
|
+
"""
|
|
128
|
+
if not rules:
|
|
129
|
+
rules = PYLINT_RULES
|
|
130
|
+
prefix = "# pylint: disable="
|
|
131
|
+
return split_linter_comment(
|
|
132
|
+
prefix,
|
|
133
|
+
rules,
|
|
134
|
+
max_lines=3,
|
|
135
|
+
)
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
def get_pyright_ignore_comment(rules: list[str] | None = None) -> str:
|
|
139
|
+
"""Get the pyright ignore comment string.
|
|
140
|
+
|
|
141
|
+
Parameters
|
|
142
|
+
----------
|
|
143
|
+
rules : Optional[list[str]], optional
|
|
144
|
+
The pyright rules to ignore, by default None.
|
|
145
|
+
|
|
146
|
+
Returns
|
|
147
|
+
-------
|
|
148
|
+
str
|
|
149
|
+
The pyright ignore comment string.
|
|
150
|
+
|
|
151
|
+
Example
|
|
152
|
+
-------
|
|
153
|
+
```python
|
|
154
|
+
>>> get_pyright_ignore_comment(
|
|
155
|
+
... True,
|
|
156
|
+
... ["reportUnusedImport", "reportMissingTypeStubs"]
|
|
157
|
+
... )
|
|
158
|
+
|
|
159
|
+
# pyright: reportUnusedImport=false, reportMissingTypeStubs=false
|
|
160
|
+
```
|
|
161
|
+
"""
|
|
162
|
+
if not rules:
|
|
163
|
+
rules = PYRIGHT_RULES
|
|
164
|
+
prefix = "# pyright: "
|
|
165
|
+
output = split_linter_comment(
|
|
166
|
+
prefix,
|
|
167
|
+
[f"{rule}=false" for rule in rules],
|
|
168
|
+
max_lines=3,
|
|
169
|
+
)
|
|
170
|
+
return output
|
|
171
|
+
|
|
172
|
+
|
|
173
|
+
def get_mypy_ignore_comment(rules: list[str] | None = None) -> str:
|
|
174
|
+
"""Get the mypy ignore comment string.
|
|
175
|
+
|
|
176
|
+
Parameters
|
|
177
|
+
----------
|
|
178
|
+
rules : Optional[list[str]], optional
|
|
179
|
+
The mypy rules to ignore, by default None.
|
|
180
|
+
|
|
181
|
+
Returns
|
|
182
|
+
-------
|
|
183
|
+
str
|
|
184
|
+
The mypy ignore comment string.
|
|
185
|
+
|
|
186
|
+
Example
|
|
187
|
+
-------
|
|
188
|
+
```python
|
|
189
|
+
>>> get_mypy_ignore_comment(["import-untyped", "no-redef"])
|
|
190
|
+
|
|
191
|
+
# mypy: disable-error-code="import-untyped,no-redef"
|
|
192
|
+
```
|
|
193
|
+
"""
|
|
194
|
+
if rules is None:
|
|
195
|
+
rules = MYPY_RULES
|
|
196
|
+
if not rules:
|
|
197
|
+
return "# type: ignore\n"
|
|
198
|
+
prefix = "# mypy: disable-error-code="
|
|
199
|
+
content = ", ".join(rules)
|
|
200
|
+
return prefix + f'"{content}"\n'
|
|
@@ -15,16 +15,18 @@ get_sqlite_to_csv_call_string
|
|
|
15
15
|
Get the string to call the sqlite to csv conversion.
|
|
16
16
|
"""
|
|
17
17
|
|
|
18
|
+
from ...core import get_comment
|
|
18
19
|
|
|
19
|
-
|
|
20
|
+
|
|
21
|
+
def get_start_logging(is_async: bool, for_notebook: bool) -> str:
|
|
20
22
|
r"""Get the logging start call string.
|
|
21
23
|
|
|
22
24
|
Parameters
|
|
23
25
|
----------
|
|
24
26
|
is_async : bool
|
|
25
27
|
Whether to use async mode.
|
|
26
|
-
|
|
27
|
-
|
|
28
|
+
for_notebook : bool
|
|
29
|
+
Whether the logging is for a notebook or a script.
|
|
28
30
|
|
|
29
31
|
Returns
|
|
30
32
|
-------
|
|
@@ -42,17 +44,26 @@ def get_start_logging(is_async: bool, tabs: int = 0) -> str:
|
|
|
42
44
|
config={"dbname": "flow.db"},
|
|
43
45
|
)
|
|
44
46
|
"""
|
|
45
|
-
tab = "
|
|
47
|
+
tab = ""
|
|
48
|
+
comment = get_comment(
|
|
49
|
+
"Start logging.",
|
|
50
|
+
for_notebook=for_notebook,
|
|
51
|
+
)
|
|
46
52
|
if is_async is False:
|
|
47
53
|
return f'''
|
|
54
|
+
{tab}{comment}
|
|
48
55
|
{tab}def start_logging() -> None:
|
|
49
56
|
{tab} """Start logging."""
|
|
50
57
|
{tab} runtime_logging.start(
|
|
51
58
|
{tab} logger_type="sqlite",
|
|
52
59
|
{tab} config={{"dbname": "flow.db"}},
|
|
53
60
|
{tab} )
|
|
61
|
+
{tab}
|
|
62
|
+
{tab}
|
|
63
|
+
{tab}start_logging()
|
|
54
64
|
'''
|
|
55
65
|
return f'''
|
|
66
|
+
{tab}{comment}
|
|
56
67
|
{tab}def start_logging() -> None:
|
|
57
68
|
{tab} """Start logging."""
|
|
58
69
|
{tab} # pylint: disable=import-outside-toplevel
|
|
@@ -65,6 +76,9 @@ def get_start_logging(is_async: bool, tabs: int = 0) -> str:
|
|
|
65
76
|
{tab} "sqlite",
|
|
66
77
|
{tab} {{"dbname": "flow.db"}},
|
|
67
78
|
{tab} )
|
|
79
|
+
{tab}
|
|
80
|
+
{tab}
|
|
81
|
+
{tab}start_logging()
|
|
68
82
|
'''
|
|
69
83
|
|
|
70
84
|
|
|
@@ -146,7 +160,7 @@ def get_sync_sqlite_out() -> str:
|
|
|
146
160
|
content += ' json_file = csv_file.replace(".csv", ".json")\n'
|
|
147
161
|
content += ' with open(json_file, "w", encoding="utf-8") as file:\n'
|
|
148
162
|
content += " json.dump(data, file, indent=4, ensure_ascii=False)\n"
|
|
149
|
-
content += "\n
|
|
163
|
+
content += "\n"
|
|
150
164
|
return content
|
|
151
165
|
|
|
152
166
|
|
|
@@ -231,7 +245,7 @@ def get_async_sqlite_out() -> str:
|
|
|
231
245
|
content += ' json_file = csv_file.replace(".csv", ".json")\n'
|
|
232
246
|
content += ' async with aiofiles.open(json_file, "w", encoding="utf-8") as file:\n'
|
|
233
247
|
content += " await file.write(json.dumps(data, indent=4, ensure_ascii=False))\n"
|
|
234
|
-
content += "\n
|
|
248
|
+
content += "\n"
|
|
235
249
|
return content
|
|
236
250
|
|
|
237
251
|
|
|
@@ -312,15 +326,15 @@ def get_sqlite_out_call(tabs: int, is_async: bool) -> str:
|
|
|
312
326
|
return content
|
|
313
327
|
|
|
314
328
|
|
|
315
|
-
def get_stop_logging(
|
|
329
|
+
def get_stop_logging(is_async: bool, tabs: int = 0) -> str:
|
|
316
330
|
r"""Get the function to stop logging and gather logs.
|
|
317
331
|
|
|
318
332
|
Parameters
|
|
319
333
|
----------
|
|
320
|
-
tabs : int
|
|
321
|
-
The number of tabs to use for indentation
|
|
322
334
|
is_async : bool
|
|
323
335
|
Whether to use async mode
|
|
336
|
+
tabs : int, optional
|
|
337
|
+
The number of tabs to use for indentation, by default 0
|
|
324
338
|
|
|
325
339
|
Returns
|
|
326
340
|
-------
|
|
@@ -2,8 +2,10 @@
|
|
|
2
2
|
# Copyright (c) 2024 - 2025 Waldiez and contributors.
|
|
3
3
|
"""Models (llm_configs) exporter."""
|
|
4
4
|
|
|
5
|
-
from .
|
|
5
|
+
from .exporter import ModelsExporter
|
|
6
|
+
from .factory import create_models_exporter
|
|
6
7
|
|
|
7
8
|
__all__ = [
|
|
8
9
|
"ModelsExporter",
|
|
10
|
+
"create_models_exporter",
|
|
9
11
|
]
|