packer-release 0.23.0__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.
- packer/__init__.py +7 -0
- packer/actions.py +25 -0
- packer/assets/RELEASE.md +70 -0
- packer/assets/audio/sounds/new notification 1.wav +0 -0
- packer/assets/audio/sounds/new notification 2.wav +0 -0
- packer/assets/audio/sounds/new notification 3.wav +0 -0
- packer/assets/images/Packer icon.ico +0 -0
- packer/assets/images/Packer icon.png +0 -0
- packer/assets/integrity.json +1 -0
- packer/assets/version.json +5 -0
- packer/change.py +222 -0
- packer/config.py +360 -0
- packer/core.py +1131 -0
- packer/custom_modules/et.py +718 -0
- packer/custom_modules/etf.py +1071 -0
- packer/exceptions.py +156 -0
- packer/main.py +14 -0
- packer/paths.py +20 -0
- packer/setup.py +791 -0
- packer/ui/cli.py +382 -0
- packer/ui/tui.py +131 -0
- packer/utils.py +222 -0
- packer_release-0.23.0.dist-info/METADATA +151 -0
- packer_release-0.23.0.dist-info/RECORD +28 -0
- packer_release-0.23.0.dist-info/WHEEL +5 -0
- packer_release-0.23.0.dist-info/entry_points.txt +2 -0
- packer_release-0.23.0.dist-info/licenses/LICENSE +21 -0
- packer_release-0.23.0.dist-info/top_level.txt +1 -0
packer/__init__.py
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
from packer.core import Packer
|
|
2
|
+
from packer.setup import main as setup
|
|
3
|
+
from packer.change import main as commit_change
|
|
4
|
+
from packer.custom_modules.et import load_config, simple_merge_settings, normalize_settings_keys, tree
|
|
5
|
+
from packer.exceptions import Global_exception_handler
|
|
6
|
+
|
|
7
|
+
__all__ = ['load_config', 'Packer', 'setup', 'commit_change', 'simple_merge_settings', 'normalize_settings_keys', 'Global_exception_handler', 'tree']
|
packer/actions.py
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
from pathlib import Path
|
|
2
|
+
|
|
3
|
+
from packer.config import Project, all_settings, send_notification, exception_handler
|
|
4
|
+
import sys
|
|
5
|
+
|
|
6
|
+
from packer.core import Packer
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def run(new_version: dict, project_directory: Path, project_configuration: Project):
|
|
10
|
+
|
|
11
|
+
try:
|
|
12
|
+
packer = Packer(new_version, project_directory, **project_configuration.model_dump())
|
|
13
|
+
|
|
14
|
+
def packer_exception_handler(exc_type, exc_value, exc_traceback):
|
|
15
|
+
packer.revert_changes(False)
|
|
16
|
+
if all_settings.desktop_notifications:
|
|
17
|
+
send_notification('Packer encountered an error and reverted all changes.', 'error')
|
|
18
|
+
exception_handler.handle_exception(exc_type, exc_value, exc_traceback)
|
|
19
|
+
|
|
20
|
+
sys.excepthook = packer_exception_handler # replace the global exception handler with packer's to revert changes in case Packer was running.
|
|
21
|
+
|
|
22
|
+
packer.run()
|
|
23
|
+
except KeyboardInterrupt:
|
|
24
|
+
packer.print_and_log('Process interrupted by user!', [255, 255, 0], level=30)
|
|
25
|
+
packer.revert_changes()
|
packer/assets/RELEASE.md
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
# $program_name Update [$new_version]
|
|
2
|
+
|
|
3
|
+
$version_description
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
Available via:
|
|
8
|
+
|
|
9
|
+
* **GitHub:** [GitHub Releases](https://github.com/${github_repo_url}/releases/tag/${new_version})
|
|
10
|
+
* **Third-party website (GoFile):** [Archive]($gofile_download_url) (click the download button).
|
|
11
|
+
|
|
12
|
+
### Binary Downloads
|
|
13
|
+
|
|
14
|
+
When downloading, please choose the correct build for your operating system:
|
|
15
|
+
|
|
16
|
+
| File Name | Platform | Description |
|
|
17
|
+
| --- | --- | --- |
|
|
18
|
+
| `$program_name` | Linux/macOS | Executable for Unix-based systems. |
|
|
19
|
+
| `$program_name.exe` | Windows | Executable for Windows systems. |
|
|
20
|
+
|
|
21
|
+
### To install:
|
|
22
|
+
|
|
23
|
+
* **GitHub:**
|
|
24
|
+
Download the appropriate binary for your system from the [Releases page](https://github.com/${github_repo_url}/releases/tag/${new_version}).
|
|
25
|
+
* **Third-party website (GoFile):**
|
|
26
|
+
Head to the website [Archive]($gofile_download_url) and download the specific arhive with the appropriate version.
|
|
27
|
+
|
|
28
|
+
After installing, continue following instructions via the README.
|
|
29
|
+
|
|
30
|
+
## Changes in $new_version
|
|
31
|
+
|
|
32
|
+
$latest_changelog
|
|
33
|
+
|
|
34
|
+
[Full changelog](https://github.com/${github_repo_url}/blob/master/CHANGELOG.md)
|
|
35
|
+
|
|
36
|
+
## Tips
|
|
37
|
+
|
|
38
|
+
If you prefer to build from source via **GitHub**, you can clone the repository using:
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
git clone https://github.com/${github_repo_url} --depth 1
|
|
42
|
+
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
Using `--depth 1` creates a "shallow clone," which only downloads the latest commit, saving you significant time and storage space compared to a full repository clone.
|
|
46
|
+
|
|
47
|
+
While downloading the pre-compiled binaries (like `$program_name` or `$program_name.exe`) is usually the fastest way to get started, cloning the repository allows you to easily pull future updates with `git pull` as they are released.
|
|
48
|
+
|
|
49
|
+
## Verification
|
|
50
|
+
|
|
51
|
+
To ensure the integrity of the downloaded files, you can verify their SHA256 checksums.
|
|
52
|
+
|
|
53
|
+
### How to verify:
|
|
54
|
+
|
|
55
|
+
* **Windows (PowerShell):**
|
|
56
|
+
Open PowerShell and run the following command:
|
|
57
|
+
```powershell
|
|
58
|
+
Get-FileHash .\$program_name.exe -Algorithm SHA256
|
|
59
|
+
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
* **Linux/macOS (Terminal):**
|
|
64
|
+
Open your terminal and run:
|
|
65
|
+
```bash
|
|
66
|
+
sha256sum $program_name
|
|
67
|
+
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
Compare the resulting hash with the one provided in the GitHub release assets list to ensure it matches.
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"CWD": {"root_hash": "8630217fe25a8f5cffc622b9825526bc14ba74e1a5c0962da2eb4699b84232ea", "tree": {"files": {".gitignore": "d7ba4a10f60365e1b1ebad9c6df3aea7acbd0ae29b3732c614db22d65e0f89fc", "CHANGELOG.md": "bf7d79f61f5080f8bd48996e42d1a6cd14611f12ebb5e61d455391b054f3d84f", "LICENSE": "bf1c380e8205fa5c7872101cd09794e8c1d313d4326c2a7a21a9c150584d2f96", "README.md": "aa3284a20fe8f30bad89b895ccd5473ff6c4c66c4a098937a5a34f2a2ac64cd2", "main.spec": "cc61795424a36b70d1c9d1b0051e445c55610f1a45389206a8f6500855ccc00b", "pyproject.toml": "68e06cb39201354dae20165ec1494116310fa85687da883bb04814c5c84af062"}, ".github": {"workflows": {"files": {"build.yaml": "a5c406080d9bb26d57ef5a6c265ae145309171f3087a6daac63a97494ad196b6"}}}, "docs": {"files": {"CLI.md": "acfcc4d27a6789e3b90cd12ecbb94a7602bead7562cd123e5b68ee6add353fda", "MANUAL_REVERT.md": "ff061a209167f7ab303601ef3a49b147fad54616b955e53a73e103bd332eeac4", "PROJECT.md": "25021c22dfdd43b862f83ca182c528f92d6c5066e29488eeb1a20cea092051b5", "ROADMAP.md": "7aa1b20b64eda32e2482e649932d4bef3b98ebf58de6404f16d03bb018bde8a7", "SETTINGS.md": "0c3625de0701598340879af51261b970135f22ecedd3c677bb8bbdedd1e1be01"}}, "src": {"packer": {"files": {"__init__.py": "2f79f39d09df2cf1f2244835e20904c382ea1344851349a49908beb0a0a4e5a0", "actions.py": "062ec62bcd99b75d679a69aa01c1e9c1afba723bb4ef8480e5236df6de57a634", "change.py": "502cf95c317be92656611a15f9a4292e26d8ce5bf1f011454ab1ef58a8a07a7f", "config.py": "d07e0fd1aa831e649491a459f286f8dade61bbbe043084fd61fa95775607ee52", "core.py": "d9946fb705161189172168f71cbe60481bb656c639d28d77c62740a1498a3c7d", "exceptions.py": "cc4af0b3a01f920badae03f9cc4a702363594d8a77a7a3a0469418bd88b5bb87", "main.py": "5a6218853b4961eefe4100531614a4f889c8b8a6aef03c9071e13b0539f3a512", "paths.py": "691b5fb411de0194382b698754bc0b29969c401823547e5ad7eddfb5ade18322", "setup.py": "a2cecc29f53a8daac96629b015c3eeb0531d115499df7500e3918a1357f0f903", "utils.py": "715ebf84d5b611c97bdcd27e79d42a8259c9170d12902ffd1ff51cf8bea15e78"}, "assets": {"files": {"RELEASE.md": "22f25566487db873890765dd0d98059ad59358606db52daa175b2d0c0500f703", "integrity.json": "4b8972f0d88174e1db151260410eb0c2a16aa70293baef224ffe5ebff3009672", "version.json": "6a079cf0fad3cb40c726916a02a31997fb2c41e61de8192a8a919bccb5909931"}, "audio": {"sounds": {"files": {"new notification 1.wav": "47a227b0403611b4d650dd4322e8784ac8154ac80abbe73b1c259df755daf8da", "new notification 2.wav": "d7a0e41e28cdbaf92fcf77da82f1656c5284e79557f5bdd143d504bb00c3aa81", "new notification 3.wav": "0b3200bd3c279b4acc901c35cd899b1e3da62b6283bf34b8aea96fb82987dae4"}}}, "images": {"files": {"Packer icon.ico": "311cfef9f20c3d377bc3d3b19751a67f66e373cd4c6a5c80294e3dee3deca947", "Packer icon.png": "1d80eca39a6ff0e147ab8795fc6dc2d01b67e5a447780ba94dcee50f86ebd715"}}}, "custom_modules": {"files": {"et.py": "e4c6fb8d81b35f82f8dc6f4940fea9800e2bed2f7aaac1a7e84149852e8c3ce6", "etf.py": "885036a0b0ccd854eb4e4d93d4b2df815984d1a19f4c6ae628379e5ad731af94"}}, "ui": {"files": {"cli.py": "3775d67cf64fe28b39eabef33a5aa985a32b5e06fe2d3a14293d4b72ab8fac6e", "tui.py": "3a81c5e6bede48e2d31bac5ff950d7b110640bd17edcb4bdcf7789c2d77f8d40"}}}}}}}
|
packer/change.py
ADDED
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
from string import Template
|
|
2
|
+
from subprocess import run
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
from git import Repo
|
|
5
|
+
from ollama import chat
|
|
6
|
+
|
|
7
|
+
from packer.config import _input_via_text_editor, all_settings
|
|
8
|
+
|
|
9
|
+
def main(git_directory: str | Path = '.', modification_types: list[str] = ['c'], overall_description: str = None,
|
|
10
|
+
text_editor: str = all_settings.text_editor, wait_flag: str = all_settings.wait_flag,
|
|
11
|
+
ai_summary: bool = True,
|
|
12
|
+
check_todo: bool = True, todo_rel_path: str = '/dev/TODO.md', list_start_identifier: str = 'before committing', list_end_identifier: str = '#',
|
|
13
|
+
bullet_summary_prompt = all_settings.changes_summary_prompt, high_level_summary_prompt = all_settings.high_level_summary_prompt,
|
|
14
|
+
model: str = all_settings.model, verbose: bool = True):
|
|
15
|
+
'''
|
|
16
|
+
Opens a temporary file in the specified text editor for describing the project's modification
|
|
17
|
+
|
|
18
|
+
This function creates a temporary file, opens it in the specified text editor,
|
|
19
|
+
waits for the editor to close, and then removes the temporary file. Afterwards updates the changelog
|
|
20
|
+
and commits it with the commit message as the project's entered modification as the user had.
|
|
21
|
+
|
|
22
|
+
:param git_directory: The root directory of the project (default is '.')
|
|
23
|
+
:type git_directory: str | Path
|
|
24
|
+
:param modification_types: The types of modifications to record (a = added, c = changed, f = fixed) (default is ['c'])
|
|
25
|
+
:type modification_types: list[str]
|
|
26
|
+
:param overall_description: The overall description of the modifications, if there are multiple (default is None)
|
|
27
|
+
:type overall_description: str
|
|
28
|
+
:param ai_summary: Whether to generate an AI summary of the changes (default is True)
|
|
29
|
+
:type ai_summary: bool
|
|
30
|
+
:param check_todo: Whether to check for TODO items before committing (default is True)
|
|
31
|
+
:type check_todo: bool
|
|
32
|
+
:param todo_rel_path: The relative path to the TODO file (default is '/dev/TODO.md')
|
|
33
|
+
:type todo_rel_path: str
|
|
34
|
+
:param list_start_identifier: The identifier for the start of the TODO list (default is 'before committing')
|
|
35
|
+
:type list_start_identifier: str
|
|
36
|
+
:param list_end_identifier: The identifier for the end of the TODO list (default is '#')
|
|
37
|
+
:type list_end_identifier: str
|
|
38
|
+
:param verbose: Whether to print verbose output (default is True)
|
|
39
|
+
:type verbose: bool
|
|
40
|
+
:param bullet_summary_prompt: The prompt template for generating bullet point summaries (default is all_settings.changes_summary_prompt)
|
|
41
|
+
:type bullet_summary_prompt: list[dict]
|
|
42
|
+
:param high_level_summary_prompt: The prompt template for generating high-level summaries (default is all_settings.high_level_summary_prompt)
|
|
43
|
+
:type high_level_summary_prompt: list[dict]
|
|
44
|
+
:param model: The AI model to use for generating summaries (default is all_settings.model)
|
|
45
|
+
:type model: str
|
|
46
|
+
'''
|
|
47
|
+
|
|
48
|
+
def input_via_text_editor(message: str) -> str:
|
|
49
|
+
'''
|
|
50
|
+
Opens a temporary file in the specified text editor for user input.
|
|
51
|
+
|
|
52
|
+
:param message: The initial message to display in the text editor
|
|
53
|
+
:type message: str
|
|
54
|
+
:return: The user's input from the text editor
|
|
55
|
+
:rtype: str
|
|
56
|
+
'''
|
|
57
|
+
return _input_via_text_editor(message, text_editor=text_editor, wait_flag=wait_flag)
|
|
58
|
+
|
|
59
|
+
if check_todo:
|
|
60
|
+
with open(f'{git_directory}{todo_rel_path}') as f:
|
|
61
|
+
content = f.read().lower()
|
|
62
|
+
|
|
63
|
+
list_start = content.find(list_start_identifier)
|
|
64
|
+
list_end = content.find(list_end_identifier, list_start)
|
|
65
|
+
|
|
66
|
+
before_committing_list = content[list_start + len(list_start_identifier):list_end].lstrip(':').strip()
|
|
67
|
+
|
|
68
|
+
if before_committing_list:
|
|
69
|
+
print(f'{list_start_identifier} task/s found, please delete them from the list once finished!\nList:\n{before_committing_list}')
|
|
70
|
+
return
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
repo = Repo(git_directory)
|
|
74
|
+
diff_text = repo.git.diff(unified=3)
|
|
75
|
+
|
|
76
|
+
if ai_summary:
|
|
77
|
+
# Update prompts with runtime data
|
|
78
|
+
summary_data = {
|
|
79
|
+
'diff': diff_text,
|
|
80
|
+
'changes': ','.join(modification_types)
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
bullet_summary_prompt[1]['content'] = Template(bullet_summary_prompt[1 if bullet_summary_prompt[1]['role'] == 'user' else 0]['content']).substitute(summary_data)
|
|
84
|
+
if verbose:
|
|
85
|
+
print('Generating bullet summary...')
|
|
86
|
+
bullet_summary = chat(
|
|
87
|
+
model=model,
|
|
88
|
+
messages=bullet_summary_prompt
|
|
89
|
+
)['message']['content'].strip()
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
high_level_summary_data = {
|
|
93
|
+
'bullet_summary': bullet_summary
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
high_level_summary_prompt[1]['content'] = Template(high_level_summary_prompt[1 if high_level_summary_prompt[1]['role'] == 'user' else 0]['content']).substitute(high_level_summary_data)
|
|
97
|
+
if verbose:
|
|
98
|
+
print('Generating high level summary...')
|
|
99
|
+
high_level_summary = chat(
|
|
100
|
+
model=model,
|
|
101
|
+
messages=high_level_summary_prompt
|
|
102
|
+
)['message']['content'].strip()
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
with open(f'{git_directory}/CHANGELOG.md', 'r') as f:
|
|
107
|
+
full_changelog = f.read()
|
|
108
|
+
|
|
109
|
+
messages = []
|
|
110
|
+
|
|
111
|
+
for i, modification_type in enumerate(modification_types):
|
|
112
|
+
|
|
113
|
+
if ai_summary:
|
|
114
|
+
bullet_summary_list = bullet_summary.splitlines()
|
|
115
|
+
message = bullet_summary_list[i] if len(bullet_summary_list) > i else 'AI didn\'t generate anything...'
|
|
116
|
+
else:
|
|
117
|
+
message = ''
|
|
118
|
+
|
|
119
|
+
message = input_via_text_editor(message)
|
|
120
|
+
|
|
121
|
+
match modification_type:
|
|
122
|
+
case 'a':
|
|
123
|
+
modification_type = 'Added'
|
|
124
|
+
end = full_changelog.find('### Changed') - 2
|
|
125
|
+
case 'c':
|
|
126
|
+
end = full_changelog.find('### Fixed') - 2
|
|
127
|
+
modification_type = 'Changed'
|
|
128
|
+
case 'f':
|
|
129
|
+
end = full_changelog.find('---') - 2
|
|
130
|
+
modification_type = 'Fixed'
|
|
131
|
+
|
|
132
|
+
message = message.lstrip('-')
|
|
133
|
+
message = message.lstrip()
|
|
134
|
+
if message.lower().startswith(modification_type.lower()):
|
|
135
|
+
message = message[len(modification_type):].lstrip()
|
|
136
|
+
message = message.strip()
|
|
137
|
+
|
|
138
|
+
message = f'{message[:1].capitalize()}{message[1:]}'
|
|
139
|
+
if not message.endswith('.'):
|
|
140
|
+
message = f'{message}.'
|
|
141
|
+
|
|
142
|
+
messages.append([modification_type, message])
|
|
143
|
+
|
|
144
|
+
full_changelog = f'{full_changelog[0: end]}\n- {message} {full_changelog[end:]}'
|
|
145
|
+
with open(f'{git_directory}/CHANGELOG.md', 'w') as f:
|
|
146
|
+
f.write(full_changelog)
|
|
147
|
+
|
|
148
|
+
if len(messages) > 1:
|
|
149
|
+
git_message = f'feat: {input_via_text_editor(high_level_summary if ai_summary else overall_description)}\n\n'
|
|
150
|
+
for message in messages:
|
|
151
|
+
git_message += f'- {message[0]}: {message[1]}\n'
|
|
152
|
+
else:
|
|
153
|
+
git_message = f'{messages[0][0]}: {messages[0][1]}'
|
|
154
|
+
|
|
155
|
+
run(['git', 'add', '.'])
|
|
156
|
+
run(['git', 'commit', '-m', git_message.strip()])
|
|
157
|
+
run(['git', 'push'])
|
|
158
|
+
|
|
159
|
+
def tui(changes: list[str] | None = None, overall_description: str | None = None, ai_suggestions: bool = True):
|
|
160
|
+
'''
|
|
161
|
+
Launches a text-based user interface for creating project change logs and committing them.
|
|
162
|
+
|
|
163
|
+
This function is intended to be used as an entry point for a TUI that guides the user
|
|
164
|
+
through creating changelog entries and committing them to the repository.
|
|
165
|
+
|
|
166
|
+
:param changes: A list of modification types (a = added, c = changed, f = fixed) (default is None)
|
|
167
|
+
:type changes: list[str] | None
|
|
168
|
+
:param overall_description: An overall description of the modifications, if there are multiple (default is None)
|
|
169
|
+
:type overall_description: str | None
|
|
170
|
+
:param ai_suggestions: Whether to generate AI suggestions for the changes (default is True)
|
|
171
|
+
:type ai_suggestions: bool
|
|
172
|
+
'''
|
|
173
|
+
|
|
174
|
+
if ai_suggestions:
|
|
175
|
+
try:
|
|
176
|
+
print(f'AI suggestions:\n{generate_suggestions()}')
|
|
177
|
+
except KeyboardInterrupt:
|
|
178
|
+
print('Skipping AI suggestions...')
|
|
179
|
+
|
|
180
|
+
if not changes:
|
|
181
|
+
amount = int(input('Enter the amount of changes: '))
|
|
182
|
+
if amount > 1:
|
|
183
|
+
print('Enter each change idvidually, both in terminal and text editor.')
|
|
184
|
+
|
|
185
|
+
changes = []
|
|
186
|
+
for _ in range(amount):
|
|
187
|
+
changes.append(input('Enter the modification type [a, c, f] ').strip().lower())
|
|
188
|
+
|
|
189
|
+
if not overall_description:
|
|
190
|
+
if len(changes) > 1:
|
|
191
|
+
overall_description = input('High level description for all changes together [None]: ').strip()
|
|
192
|
+
else:
|
|
193
|
+
overall_description = None
|
|
194
|
+
|
|
195
|
+
return (changes, overall_description)
|
|
196
|
+
|
|
197
|
+
def generate_suggestions(git_directory: str | Path = '.', suggestions_prompt = all_settings.suggestions_prompt, model: str = all_settings.model, verbose: bool = True):
|
|
198
|
+
'''
|
|
199
|
+
Generates AI suggestions for the changes based on the current git diff.
|
|
200
|
+
|
|
201
|
+
:param git_directory: The root directory of the project (default is '.')
|
|
202
|
+
:type git_directory: str | Path
|
|
203
|
+
:param suggestions_prompt: The prompt template for generating AI suggestions (default is all_settings.suggestions_prompt)
|
|
204
|
+
:type suggestions_prompt: list[dict]
|
|
205
|
+
:param model: The AI model to use for generating suggestions (default is all_settings.model)
|
|
206
|
+
:type model: str
|
|
207
|
+
'''
|
|
208
|
+
repo = Repo(git_directory)
|
|
209
|
+
diff_text = repo.git.diff(unified=3)
|
|
210
|
+
|
|
211
|
+
suggestions_prompt[1]['content'] = Template(suggestions_prompt[1 if suggestions_prompt[1]['role'] == 'user' else 0]['content']).substitute({'diff': diff_text})
|
|
212
|
+
|
|
213
|
+
if verbose:
|
|
214
|
+
print('Generating AI suggestions...')
|
|
215
|
+
return chat(
|
|
216
|
+
model=model,
|
|
217
|
+
messages=suggestions_prompt
|
|
218
|
+
)['message']['content'].strip()
|
|
219
|
+
|
|
220
|
+
if __name__ == '__main__':
|
|
221
|
+
output = tui()
|
|
222
|
+
main(modification_types=output[0], overall_description=output[1])
|