PraisonAI 2.2.99__tar.gz → 2.3.0__tar.gz

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.
Files changed (56) hide show
  1. {praisonai-2.2.99 → praisonai-2.3.0}/PKG-INFO +47 -13
  2. {praisonai-2.2.99 → praisonai-2.3.0}/PraisonAI.egg-info/PKG-INFO +47 -13
  3. {praisonai-2.2.99 → praisonai-2.3.0}/PraisonAI.egg-info/requires.txt +1 -1
  4. {praisonai-2.2.99 → praisonai-2.3.0}/README.md +45 -11
  5. {praisonai-2.2.99 → praisonai-2.3.0}/praisonai/cli.py +96 -0
  6. {praisonai-2.2.99 → praisonai-2.3.0}/praisonai/deploy.py +1 -1
  7. praisonai-2.3.0/praisonai/version.py +1 -0
  8. {praisonai-2.2.99 → praisonai-2.3.0}/pyproject.toml +1 -1
  9. {praisonai-2.2.99 → praisonai-2.3.0}/tests/test.py +5 -2
  10. praisonai-2.2.99/praisonai/version.py +0 -1
  11. {praisonai-2.2.99 → praisonai-2.3.0}/PraisonAI.egg-info/SOURCES.txt +0 -0
  12. {praisonai-2.2.99 → praisonai-2.3.0}/PraisonAI.egg-info/dependency_links.txt +0 -0
  13. {praisonai-2.2.99 → praisonai-2.3.0}/PraisonAI.egg-info/entry_points.txt +0 -0
  14. {praisonai-2.2.99 → praisonai-2.3.0}/PraisonAI.egg-info/top_level.txt +0 -0
  15. {praisonai-2.2.99 → praisonai-2.3.0}/praisonai/__init__.py +0 -0
  16. {praisonai-2.2.99 → praisonai-2.3.0}/praisonai/__main__.py +0 -0
  17. {praisonai-2.2.99 → praisonai-2.3.0}/praisonai/agents_generator.py +0 -0
  18. {praisonai-2.2.99 → praisonai-2.3.0}/praisonai/api/call.py +0 -0
  19. {praisonai-2.2.99 → praisonai-2.3.0}/praisonai/auto.py +0 -0
  20. {praisonai-2.2.99 → praisonai-2.3.0}/praisonai/chainlit_ui.py +0 -0
  21. {praisonai-2.2.99 → praisonai-2.3.0}/praisonai/inbuilt_tools/__init__.py +0 -0
  22. {praisonai-2.2.99 → praisonai-2.3.0}/praisonai/inbuilt_tools/autogen_tools.py +0 -0
  23. {praisonai-2.2.99 → praisonai-2.3.0}/praisonai/inc/__init__.py +0 -0
  24. {praisonai-2.2.99 → praisonai-2.3.0}/praisonai/inc/config.py +0 -0
  25. {praisonai-2.2.99 → praisonai-2.3.0}/praisonai/inc/models.py +0 -0
  26. {praisonai-2.2.99 → praisonai-2.3.0}/praisonai/scheduler.py +0 -0
  27. {praisonai-2.2.99 → praisonai-2.3.0}/praisonai/setup/__init__.py +0 -0
  28. {praisonai-2.2.99 → praisonai-2.3.0}/praisonai/setup/build.py +0 -0
  29. {praisonai-2.2.99 → praisonai-2.3.0}/praisonai/setup/post_install.py +0 -0
  30. {praisonai-2.2.99 → praisonai-2.3.0}/praisonai/setup/setup_conda_env.py +0 -0
  31. {praisonai-2.2.99 → praisonai-2.3.0}/praisonai/setup.py +0 -0
  32. {praisonai-2.2.99 → praisonai-2.3.0}/praisonai/test.py +0 -0
  33. {praisonai-2.2.99 → praisonai-2.3.0}/praisonai/train.py +0 -0
  34. {praisonai-2.2.99 → praisonai-2.3.0}/praisonai/train_vision.py +0 -0
  35. {praisonai-2.2.99 → praisonai-2.3.0}/praisonai/ui/agents.py +0 -0
  36. {praisonai-2.2.99 → praisonai-2.3.0}/praisonai/ui/callbacks.py +0 -0
  37. {praisonai-2.2.99 → praisonai-2.3.0}/praisonai/ui/chat.py +0 -0
  38. {praisonai-2.2.99 → praisonai-2.3.0}/praisonai/ui/code.py +0 -0
  39. {praisonai-2.2.99 → praisonai-2.3.0}/praisonai/ui/colab.py +0 -0
  40. {praisonai-2.2.99 → praisonai-2.3.0}/praisonai/ui/colab_chainlit.py +0 -0
  41. {praisonai-2.2.99 → praisonai-2.3.0}/praisonai/ui/components/aicoder.py +0 -0
  42. {praisonai-2.2.99 → praisonai-2.3.0}/praisonai/ui/context.py +0 -0
  43. {praisonai-2.2.99 → praisonai-2.3.0}/praisonai/ui/database_config.py +0 -0
  44. {praisonai-2.2.99 → praisonai-2.3.0}/praisonai/ui/db.py +0 -0
  45. {praisonai-2.2.99 → praisonai-2.3.0}/praisonai/ui/realtime.py +0 -0
  46. {praisonai-2.2.99 → praisonai-2.3.0}/praisonai/ui/realtimeclient/__init__.py +0 -0
  47. {praisonai-2.2.99 → praisonai-2.3.0}/praisonai/ui/realtimeclient/tools.py +0 -0
  48. {praisonai-2.2.99 → praisonai-2.3.0}/praisonai/ui/sql_alchemy.py +0 -0
  49. {praisonai-2.2.99 → praisonai-2.3.0}/praisonai/upload_vision.py +0 -0
  50. {praisonai-2.2.99 → praisonai-2.3.0}/setup.cfg +0 -0
  51. {praisonai-2.2.99 → praisonai-2.3.0}/tests/test_agents_playbook.py +0 -0
  52. {praisonai-2.2.99 → praisonai-2.3.0}/tests/test_basic.py +0 -0
  53. {praisonai-2.2.99 → praisonai-2.3.0}/tests/test_custom_tools_fix.py +0 -0
  54. {praisonai-2.2.99 → praisonai-2.3.0}/tests/test_double_api_fix.py +0 -0
  55. {praisonai-2.2.99 → praisonai-2.3.0}/tests/test_phase2_refactor.py +0 -0
  56. {praisonai-2.2.99 → praisonai-2.3.0}/tests/test_runner.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: PraisonAI
3
- Version: 2.2.99
3
+ Version: 2.3.0
4
4
  Summary: PraisonAI is an AI Agents Framework with Self Reflection. PraisonAI application combines PraisonAI Agents, AutoGen, and CrewAI into a low-code solution for building and managing multi-agent LLM systems, focusing on simplicity, customisation, and efficient human-agent collaboration.
5
5
  Author: Mervin Praison
6
6
  License: MIT
@@ -11,7 +11,7 @@ Description-Content-Type: text/markdown
11
11
  Requires-Dist: rich>=13.7
12
12
  Requires-Dist: markdown>=3.5
13
13
  Requires-Dist: pyparsing>=3.0.0
14
- Requires-Dist: praisonaiagents>=0.0.169
14
+ Requires-Dist: praisonaiagents>=0.0.170
15
15
  Requires-Dist: python-dotenv>=0.19.0
16
16
  Requires-Dist: instructor>=1.3.3
17
17
  Requires-Dist: PyYAML>=6.0
@@ -815,6 +815,47 @@ agent = Agent(tools=["my_tool"]) # Works automatically!
815
815
  ```
816
816
 
817
817
 
818
+ ## Prompt Expansion
819
+
820
+ Expand short prompts into detailed, actionable prompts:
821
+
822
+ ### CLI Usage
823
+
824
+ ```bash
825
+ # Expand a short prompt into detailed prompt
826
+ praisonai "write a movie script in 3 lines" --expand-prompt
827
+
828
+ # With verbose output
829
+ praisonai "blog about AI" --expand-prompt -v
830
+
831
+ # With tools for context gathering
832
+ praisonai "latest AI trends" --expand-prompt --expand-tools tools.py
833
+
834
+ # Combine with query rewrite
835
+ praisonai "AI news" --query-rewrite --expand-prompt
836
+ ```
837
+
838
+ ### Programmatic Usage
839
+
840
+ ```python
841
+ from praisonaiagents import PromptExpanderAgent, ExpandStrategy
842
+
843
+ # Basic usage
844
+ agent = PromptExpanderAgent()
845
+ result = agent.expand("write a movie script in 3 lines")
846
+ print(result.expanded_prompt)
847
+
848
+ # With specific strategy
849
+ result = agent.expand("blog about AI", strategy=ExpandStrategy.DETAILED)
850
+
851
+ # Available strategies: BASIC, DETAILED, STRUCTURED, CREATIVE, AUTO
852
+ ```
853
+
854
+ **Key Difference:**
855
+ - `--query-rewrite`: Optimizes queries for **search/retrieval** (RAG)
856
+ - `--expand-prompt`: Expands prompts for **detailed task execution**
857
+
858
+
818
859
  ## Development:
819
860
 
820
861
  Below is used for development only.
@@ -832,21 +873,14 @@ uv pip install -r pyproject.toml --extra code
832
873
  uv pip install -r pyproject.toml --extra "crewai,autogen"
833
874
  ```
834
875
 
835
- ### Version Bump
876
+ ### Bump and Release
836
877
 
837
878
  ```bash
838
- # From project root
839
- python src/praisonai/scripts/bump_version.py 2.2.96
879
+ # From project root - bumps version and releases in one command
880
+ python src/praisonai/scripts/bump_and_release.py 2.2.99
840
881
 
841
882
  # With praisonaiagents dependency
842
- python src/praisonai/scripts/bump_version.py 2.2.96 --agents 0.0.167
843
- ```
844
-
845
- ### Release
846
-
847
- ```bash
848
- # From project root (runs uv lock, build, git tag, gh release)
849
- python src/praisonai/scripts/release.py
883
+ python src/praisonai/scripts/bump_and_release.py 2.2.99 --agents 0.0.169
850
884
 
851
885
  # Then publish
852
886
  cd src/praisonai && uv publish
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: PraisonAI
3
- Version: 2.2.99
3
+ Version: 2.3.0
4
4
  Summary: PraisonAI is an AI Agents Framework with Self Reflection. PraisonAI application combines PraisonAI Agents, AutoGen, and CrewAI into a low-code solution for building and managing multi-agent LLM systems, focusing on simplicity, customisation, and efficient human-agent collaboration.
5
5
  Author: Mervin Praison
6
6
  License: MIT
@@ -11,7 +11,7 @@ Description-Content-Type: text/markdown
11
11
  Requires-Dist: rich>=13.7
12
12
  Requires-Dist: markdown>=3.5
13
13
  Requires-Dist: pyparsing>=3.0.0
14
- Requires-Dist: praisonaiagents>=0.0.169
14
+ Requires-Dist: praisonaiagents>=0.0.170
15
15
  Requires-Dist: python-dotenv>=0.19.0
16
16
  Requires-Dist: instructor>=1.3.3
17
17
  Requires-Dist: PyYAML>=6.0
@@ -815,6 +815,47 @@ agent = Agent(tools=["my_tool"]) # Works automatically!
815
815
  ```
816
816
 
817
817
 
818
+ ## Prompt Expansion
819
+
820
+ Expand short prompts into detailed, actionable prompts:
821
+
822
+ ### CLI Usage
823
+
824
+ ```bash
825
+ # Expand a short prompt into detailed prompt
826
+ praisonai "write a movie script in 3 lines" --expand-prompt
827
+
828
+ # With verbose output
829
+ praisonai "blog about AI" --expand-prompt -v
830
+
831
+ # With tools for context gathering
832
+ praisonai "latest AI trends" --expand-prompt --expand-tools tools.py
833
+
834
+ # Combine with query rewrite
835
+ praisonai "AI news" --query-rewrite --expand-prompt
836
+ ```
837
+
838
+ ### Programmatic Usage
839
+
840
+ ```python
841
+ from praisonaiagents import PromptExpanderAgent, ExpandStrategy
842
+
843
+ # Basic usage
844
+ agent = PromptExpanderAgent()
845
+ result = agent.expand("write a movie script in 3 lines")
846
+ print(result.expanded_prompt)
847
+
848
+ # With specific strategy
849
+ result = agent.expand("blog about AI", strategy=ExpandStrategy.DETAILED)
850
+
851
+ # Available strategies: BASIC, DETAILED, STRUCTURED, CREATIVE, AUTO
852
+ ```
853
+
854
+ **Key Difference:**
855
+ - `--query-rewrite`: Optimizes queries for **search/retrieval** (RAG)
856
+ - `--expand-prompt`: Expands prompts for **detailed task execution**
857
+
858
+
818
859
  ## Development:
819
860
 
820
861
  Below is used for development only.
@@ -832,21 +873,14 @@ uv pip install -r pyproject.toml --extra code
832
873
  uv pip install -r pyproject.toml --extra "crewai,autogen"
833
874
  ```
834
875
 
835
- ### Version Bump
876
+ ### Bump and Release
836
877
 
837
878
  ```bash
838
- # From project root
839
- python src/praisonai/scripts/bump_version.py 2.2.96
879
+ # From project root - bumps version and releases in one command
880
+ python src/praisonai/scripts/bump_and_release.py 2.2.99
840
881
 
841
882
  # With praisonaiagents dependency
842
- python src/praisonai/scripts/bump_version.py 2.2.96 --agents 0.0.167
843
- ```
844
-
845
- ### Release
846
-
847
- ```bash
848
- # From project root (runs uv lock, build, git tag, gh release)
849
- python src/praisonai/scripts/release.py
883
+ python src/praisonai/scripts/bump_and_release.py 2.2.99 --agents 0.0.169
850
884
 
851
885
  # Then publish
852
886
  cd src/praisonai && uv publish
@@ -1,7 +1,7 @@
1
1
  rich>=13.7
2
2
  markdown>=3.5
3
3
  pyparsing>=3.0.0
4
- praisonaiagents>=0.0.169
4
+ praisonaiagents>=0.0.170
5
5
  python-dotenv>=0.19.0
6
6
  instructor>=1.3.3
7
7
  PyYAML>=6.0
@@ -718,6 +718,47 @@ agent = Agent(tools=["my_tool"]) # Works automatically!
718
718
  ```
719
719
 
720
720
 
721
+ ## Prompt Expansion
722
+
723
+ Expand short prompts into detailed, actionable prompts:
724
+
725
+ ### CLI Usage
726
+
727
+ ```bash
728
+ # Expand a short prompt into detailed prompt
729
+ praisonai "write a movie script in 3 lines" --expand-prompt
730
+
731
+ # With verbose output
732
+ praisonai "blog about AI" --expand-prompt -v
733
+
734
+ # With tools for context gathering
735
+ praisonai "latest AI trends" --expand-prompt --expand-tools tools.py
736
+
737
+ # Combine with query rewrite
738
+ praisonai "AI news" --query-rewrite --expand-prompt
739
+ ```
740
+
741
+ ### Programmatic Usage
742
+
743
+ ```python
744
+ from praisonaiagents import PromptExpanderAgent, ExpandStrategy
745
+
746
+ # Basic usage
747
+ agent = PromptExpanderAgent()
748
+ result = agent.expand("write a movie script in 3 lines")
749
+ print(result.expanded_prompt)
750
+
751
+ # With specific strategy
752
+ result = agent.expand("blog about AI", strategy=ExpandStrategy.DETAILED)
753
+
754
+ # Available strategies: BASIC, DETAILED, STRUCTURED, CREATIVE, AUTO
755
+ ```
756
+
757
+ **Key Difference:**
758
+ - `--query-rewrite`: Optimizes queries for **search/retrieval** (RAG)
759
+ - `--expand-prompt`: Expands prompts for **detailed task execution**
760
+
761
+
721
762
  ## Development:
722
763
 
723
764
  Below is used for development only.
@@ -735,21 +776,14 @@ uv pip install -r pyproject.toml --extra code
735
776
  uv pip install -r pyproject.toml --extra "crewai,autogen"
736
777
  ```
737
778
 
738
- ### Version Bump
779
+ ### Bump and Release
739
780
 
740
781
  ```bash
741
- # From project root
742
- python src/praisonai/scripts/bump_version.py 2.2.96
782
+ # From project root - bumps version and releases in one command
783
+ python src/praisonai/scripts/bump_and_release.py 2.2.99
743
784
 
744
785
  # With praisonaiagents dependency
745
- python src/praisonai/scripts/bump_version.py 2.2.96 --agents 0.0.167
746
- ```
747
-
748
- ### Release
749
-
750
- ```bash
751
- # From project root (runs uv lock, build, git tag, gh release)
752
- python src/praisonai/scripts/release.py
786
+ python src/praisonai/scripts/bump_and_release.py 2.2.99 --agents 0.0.169
753
787
 
754
788
  # Then publish
755
789
  cd src/praisonai && uv publish
@@ -579,6 +579,8 @@ class PraisonAI:
579
579
  parser.add_argument("--research", action="store_true", help="Run deep research on a topic")
580
580
  parser.add_argument("--query-rewrite", action="store_true", help="Rewrite query for better results (works with any command)")
581
581
  parser.add_argument("--rewrite-tools", type=str, help="Tools for query rewriter (e.g., 'internet_search' or path to tools.py)")
582
+ parser.add_argument("--expand-prompt", action="store_true", help="Expand short prompt into detailed prompt (works with any command)")
583
+ parser.add_argument("--expand-tools", type=str, help="Tools for prompt expander (e.g., 'internet_search' or path to tools.py)")
582
584
  parser.add_argument("--tools", "-t", type=str, help="Path to tools.py file for research agent")
583
585
  parser.add_argument("--save", "-s", action="store_true", help="Save research output to file (output/research/)")
584
586
  parser.add_argument("--verbose", "-v", action="store_true", help="Enable verbose output for research")
@@ -839,12 +841,106 @@ class PraisonAI:
839
841
  verbose = getattr(self.args, 'verbose', False)
840
842
  return self._rewrite_query(query, rewrite_tools, verbose)
841
843
 
844
+ def _expand_prompt(self, prompt: str, expand_tools: str = None, verbose: bool = False) -> str:
845
+ """
846
+ Expand prompt using PromptExpanderAgent.
847
+
848
+ Args:
849
+ prompt: The prompt to expand
850
+ expand_tools: Tool names (comma-separated) or path to tools.py
851
+ verbose: Enable verbose output
852
+
853
+ Returns:
854
+ Expanded prompt or original if expansion fails
855
+ """
856
+ try:
857
+ from praisonaiagents import PromptExpanderAgent, ExpandStrategy
858
+ from rich import print
859
+
860
+ print("[bold cyan]Expanding prompt for detailed execution...[/bold cyan]")
861
+
862
+ # Load expand tools if specified
863
+ expand_tools_list = []
864
+ if expand_tools:
865
+ if os.path.isfile(expand_tools):
866
+ # Load from file
867
+ try:
868
+ import inspect
869
+ import importlib.util
870
+ spec = importlib.util.spec_from_file_location("expand_tools_module", expand_tools)
871
+ if spec and spec.loader:
872
+ module = importlib.util.module_from_spec(spec)
873
+ spec.loader.exec_module(module)
874
+ for name, obj in inspect.getmembers(module):
875
+ if inspect.isfunction(obj) and not name.startswith('_'):
876
+ expand_tools_list.append(obj)
877
+ if expand_tools_list:
878
+ print(f"[cyan]Loaded {len(expand_tools_list)} tools for prompt expander[/cyan]")
879
+ except Exception as e:
880
+ print(f"[yellow]Warning: Failed to load expand tools: {e}[/yellow]")
881
+ else:
882
+ # Treat as comma-separated tool names
883
+ try:
884
+ from praisonaiagents.tools import TOOL_MAPPINGS
885
+ import praisonaiagents.tools as tools_module
886
+
887
+ tool_names = [t.strip() for t in expand_tools.split(',')]
888
+ for tool_name in tool_names:
889
+ if tool_name in TOOL_MAPPINGS:
890
+ try:
891
+ tool = getattr(tools_module, tool_name)
892
+ expand_tools_list.append(tool)
893
+ except Exception as e:
894
+ print(f"[yellow]Warning: Failed to load expand tool '{tool_name}': {e}[/yellow]")
895
+ else:
896
+ print(f"[yellow]Warning: Unknown expand tool '{tool_name}'[/yellow]")
897
+ if expand_tools_list:
898
+ print(f"[cyan]Using expand tools: {', '.join(tool_names)}[/cyan]")
899
+ except ImportError:
900
+ print("[yellow]Warning: Could not import tools module[/yellow]")
901
+
902
+ expander = PromptExpanderAgent(
903
+ model="gpt-4o-mini",
904
+ verbose=verbose,
905
+ tools=expand_tools_list if expand_tools_list else None
906
+ )
907
+ result = expander.expand(prompt, strategy=ExpandStrategy.AUTO)
908
+ expanded = result.expanded_prompt
909
+
910
+ print(f"[cyan]Original:[/cyan] {prompt}")
911
+ print(f"[cyan]Expanded:[/cyan] {expanded}")
912
+
913
+ return expanded
914
+
915
+ except ImportError:
916
+ from rich import print
917
+ print("[yellow]Warning: PromptExpanderAgent not available, using original prompt[/yellow]")
918
+ return prompt
919
+ except Exception as e:
920
+ from rich import print
921
+ print(f"[yellow]Warning: Prompt expansion failed ({e}), using original prompt[/yellow]")
922
+ return prompt
923
+
924
+ def _expand_prompt_if_enabled(self, prompt: str) -> str:
925
+ """
926
+ Expand prompt using PromptExpanderAgent if --expand-prompt is enabled.
927
+ Returns the expanded prompt or original if expansion is disabled/fails.
928
+ """
929
+ if not hasattr(self, 'args') or not getattr(self.args, 'expand_prompt', False):
930
+ return prompt
931
+
932
+ expand_tools = getattr(self.args, 'expand_tools', None)
933
+ verbose = getattr(self.args, 'verbose', False)
934
+ return self._expand_prompt(prompt, expand_tools, verbose)
935
+
842
936
  def handle_direct_prompt(self, prompt):
843
937
  """
844
938
  Handle direct prompt by creating a single agent and running it.
845
939
  """
846
940
  # Apply query rewriting if enabled
847
941
  prompt = self._rewrite_query_if_enabled(prompt)
942
+ # Apply prompt expansion if enabled
943
+ prompt = self._expand_prompt_if_enabled(prompt)
848
944
 
849
945
  if PRAISONAI_AVAILABLE:
850
946
  agent_config = {
@@ -57,7 +57,7 @@ class CloudDeployer:
57
57
  file.write("FROM python:3.11-slim\n")
58
58
  file.write("WORKDIR /app\n")
59
59
  file.write("COPY . .\n")
60
- file.write("RUN pip install flask praisonai==2.2.99 gunicorn markdown\n")
60
+ file.write("RUN pip install flask praisonai==2.3.0 gunicorn markdown\n")
61
61
  file.write("EXPOSE 8080\n")
62
62
  file.write('CMD ["gunicorn", "-b", "0.0.0.0:8080", "api:app"]\n')
63
63
 
@@ -0,0 +1 @@
1
+ __version__ = "2.3.0"
@@ -12,7 +12,7 @@ dependencies = [
12
12
  "rich>=13.7",
13
13
  "markdown>=3.5",
14
14
  "pyparsing>=3.0.0",
15
- "praisonaiagents>=0.0.169",
15
+ "praisonaiagents>=0.0.170",
16
16
  "python-dotenv>=0.19.0",
17
17
  "instructor>=1.3.3",
18
18
  "PyYAML>=6.0",
@@ -59,8 +59,11 @@ class TestPraisonAICommandLine(unittest.TestCase):
59
59
  # In CI, it should be set by the workflow
60
60
  print("Warning: OPENAI_API_KEY not found in CLI test environment. API calls might fail if not mocked.")
61
61
 
62
- result = subprocess.run(command, shell=True, capture_output=True, text=True, env=env)
63
- return result.stdout + result.stderr
62
+ try:
63
+ result = subprocess.run(command, shell=True, capture_output=True, text=True, env=env, timeout=120)
64
+ return result.stdout + result.stderr
65
+ except subprocess.TimeoutExpired:
66
+ return "TIMEOUT: Command exceeded 120 seconds"
64
67
 
65
68
  @pytest.mark.real
66
69
  def test_praisonai_command(self):
@@ -1 +0,0 @@
1
- __version__ = "2.2.99"
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes