osa_tool 0.2.1__tar.gz → 0.2.2__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 (88) hide show
  1. {osa_tool-0.2.1 → osa_tool-0.2.2}/PKG-INFO +47 -43
  2. {osa_tool-0.2.1 → osa_tool-0.2.2}/README.md +44 -41
  3. {osa_tool-0.2.1 → osa_tool-0.2.2}/osa_tool/aboutgen/about_generator.py +9 -5
  4. {osa_tool-0.2.1 → osa_tool-0.2.2}/osa_tool/analytics/metadata.py +3 -2
  5. {osa_tool-0.2.1 → osa_tool-0.2.2}/osa_tool/analytics/prompt_builder.py +5 -5
  6. {osa_tool-0.2.1 → osa_tool-0.2.2}/osa_tool/analytics/report_maker.py +2 -2
  7. {osa_tool-0.2.1 → osa_tool-0.2.2}/osa_tool/analytics/run_report_gen.py +2 -2
  8. {osa_tool-0.2.1 → osa_tool-0.2.2}/osa_tool/arguments_parser.py +35 -21
  9. {osa_tool-0.2.1 → osa_tool-0.2.2}/osa_tool/config/settings/arguments.yaml +8 -47
  10. {osa_tool-0.2.1 → osa_tool-0.2.2}/osa_tool/config/settings/config.toml +24 -26
  11. {osa_tool-0.2.1 → osa_tool-0.2.2}/osa_tool/config/settings.py +3 -5
  12. osa_tool-0.2.2/osa_tool/docs/templates/ci_config.toml +45 -0
  13. {osa_tool-0.2.1 → osa_tool-0.2.2}/osa_tool/git_agent/git_agent.py +1 -1
  14. {osa_tool-0.2.1 → osa_tool-0.2.2}/osa_tool/models/models.py +5 -4
  15. {osa_tool-0.2.1 → osa_tool-0.2.2}/osa_tool/osatreesitter/docgen.py +396 -162
  16. {osa_tool-0.2.1 → osa_tool-0.2.2}/osa_tool/readmegen/context/dependencies.py +12 -9
  17. {osa_tool-0.2.1 → osa_tool-0.2.2}/osa_tool/readmegen/models/llm_service.py +14 -17
  18. {osa_tool-0.2.1 → osa_tool-0.2.2}/osa_tool/run.py +67 -14
  19. {osa_tool-0.2.1 → osa_tool-0.2.2}/osa_tool/scheduler/README.md +60 -58
  20. {osa_tool-0.2.1 → osa_tool-0.2.2}/osa_tool/utils.py +7 -2
  21. {osa_tool-0.2.1 → osa_tool-0.2.2}/pyproject.toml +4 -3
  22. {osa_tool-0.2.1 → osa_tool-0.2.2}/LICENSE +0 -0
  23. {osa_tool-0.2.1 → osa_tool-0.2.2}/osa_tool/__init__.py +0 -0
  24. {osa_tool-0.2.1 → osa_tool-0.2.2}/osa_tool/aboutgen/__init__.py +0 -0
  25. {osa_tool-0.2.1 → osa_tool-0.2.2}/osa_tool/aboutgen/prompts_about_config.py +0 -0
  26. {osa_tool-0.2.1 → osa_tool-0.2.2}/osa_tool/analytics/__init__.py +0 -0
  27. {osa_tool-0.2.1 → osa_tool-0.2.2}/osa_tool/analytics/report_generator.py +0 -0
  28. {osa_tool-0.2.1 → osa_tool-0.2.2}/osa_tool/analytics/sourcerank.py +0 -0
  29. {osa_tool-0.2.1 → osa_tool-0.2.2}/osa_tool/config/__init__.py +0 -0
  30. {osa_tool-0.2.1 → osa_tool-0.2.2}/osa_tool/config/settings/prompt_for_analysis.toml +0 -0
  31. {osa_tool-0.2.1 → osa_tool-0.2.2}/osa_tool/config/settings/prompt_for_scheduler.toml +0 -0
  32. {osa_tool-0.2.1 → osa_tool-0.2.2}/osa_tool/config/settings/prompts.toml +0 -0
  33. {osa_tool-0.2.1 → osa_tool-0.2.2}/osa_tool/config/settings/prompts_about_section.toml +0 -0
  34. {osa_tool-0.2.1 → osa_tool-0.2.2}/osa_tool/config/settings/prompts_article.toml +0 -0
  35. {osa_tool-0.2.1 → osa_tool-0.2.2}/osa_tool/config/templates/template.toml +0 -0
  36. {osa_tool-0.2.1 → osa_tool-0.2.2}/osa_tool/convertion/__init__.py +0 -0
  37. {osa_tool-0.2.1 → osa_tool-0.2.2}/osa_tool/convertion/notebook_converter.py +0 -0
  38. {osa_tool-0.2.1 → osa_tool-0.2.2}/osa_tool/docs/images/osa_logo.PNG +0 -0
  39. {osa_tool-0.2.1 → osa_tool-0.2.2}/osa_tool/docs/images/osa_logo_transparent.PNG +0 -0
  40. {osa_tool-0.2.1 → osa_tool-0.2.2}/osa_tool/docs/templates/community.toml +0 -0
  41. {osa_tool-0.2.1 → osa_tool-0.2.2}/osa_tool/docs/templates/contributing.toml +0 -0
  42. {osa_tool-0.2.1 → osa_tool-0.2.2}/osa_tool/docs/templates/licenses.toml +0 -0
  43. {osa_tool-0.2.1 → osa_tool-0.2.2}/osa_tool/docs/templates/mkdocs.yml +0 -0
  44. {osa_tool-0.2.1 → osa_tool-0.2.2}/osa_tool/docs_generator/__init__.py +0 -0
  45. {osa_tool-0.2.1 → osa_tool-0.2.2}/osa_tool/docs_generator/community.py +0 -0
  46. {osa_tool-0.2.1 → osa_tool-0.2.2}/osa_tool/docs_generator/contributing.py +0 -0
  47. {osa_tool-0.2.1 → osa_tool-0.2.2}/osa_tool/docs_generator/docs_run.py +0 -0
  48. {osa_tool-0.2.1 → osa_tool-0.2.2}/osa_tool/docs_generator/license.py +0 -0
  49. {osa_tool-0.2.1 → osa_tool-0.2.2}/osa_tool/git_agent/__init__.py +0 -0
  50. {osa_tool-0.2.1 → osa_tool-0.2.2}/osa_tool/github_workflow/README.md +0 -0
  51. {osa_tool-0.2.1 → osa_tool-0.2.2}/osa_tool/github_workflow/__init__.py +0 -0
  52. {osa_tool-0.2.1 → osa_tool-0.2.2}/osa_tool/github_workflow/generator.py +0 -0
  53. {osa_tool-0.2.1 → osa_tool-0.2.2}/osa_tool/github_workflow/providers/black.py +0 -0
  54. {osa_tool-0.2.1 → osa_tool-0.2.2}/osa_tool/github_workflow/providers/unit_test.py +0 -0
  55. {osa_tool-0.2.1 → osa_tool-0.2.2}/osa_tool/models/__init__.py +0 -0
  56. {osa_tool-0.2.1 → osa_tool-0.2.2}/osa_tool/organization/repo_organizer.py +0 -0
  57. {osa_tool-0.2.1 → osa_tool-0.2.2}/osa_tool/osatreesitter/__init__.py +0 -0
  58. {osa_tool-0.2.1 → osa_tool-0.2.2}/osa_tool/osatreesitter/osa_treesitter.py +0 -0
  59. {osa_tool-0.2.1 → osa_tool-0.2.2}/osa_tool/readmegen/__init__.py +0 -0
  60. {osa_tool-0.2.1 → osa_tool-0.2.2}/osa_tool/readmegen/context/__init__.py +0 -0
  61. {osa_tool-0.2.1 → osa_tool-0.2.2}/osa_tool/readmegen/context/article_content.py +0 -0
  62. {osa_tool-0.2.1 → osa_tool-0.2.2}/osa_tool/readmegen/context/article_path.py +0 -0
  63. {osa_tool-0.2.1 → osa_tool-0.2.2}/osa_tool/readmegen/context/files_contents.py +0 -0
  64. {osa_tool-0.2.1 → osa_tool-0.2.2}/osa_tool/readmegen/context/pypi_status_checker.py +0 -0
  65. {osa_tool-0.2.1 → osa_tool-0.2.2}/osa_tool/readmegen/generator/__init__.py +0 -0
  66. {osa_tool-0.2.1 → osa_tool-0.2.2}/osa_tool/readmegen/generator/base_builder.py +0 -0
  67. {osa_tool-0.2.1 → osa_tool-0.2.2}/osa_tool/readmegen/generator/builder.py +0 -0
  68. {osa_tool-0.2.1 → osa_tool-0.2.2}/osa_tool/readmegen/generator/builder_article.py +0 -0
  69. {osa_tool-0.2.1 → osa_tool-0.2.2}/osa_tool/readmegen/generator/header.py +0 -0
  70. {osa_tool-0.2.1 → osa_tool-0.2.2}/osa_tool/readmegen/generator/icons/shieldsio_icons.json +0 -0
  71. {osa_tool-0.2.1 → osa_tool-0.2.2}/osa_tool/readmegen/generator/installation.py +0 -0
  72. {osa_tool-0.2.1 → osa_tool-0.2.2}/osa_tool/readmegen/models/__init__.py +0 -0
  73. {osa_tool-0.2.1 → osa_tool-0.2.2}/osa_tool/readmegen/postprocessor/__init__.py +0 -0
  74. {osa_tool-0.2.1 → osa_tool-0.2.2}/osa_tool/readmegen/postprocessor/readme_refiner.py +0 -0
  75. {osa_tool-0.2.1 → osa_tool-0.2.2}/osa_tool/readmegen/postprocessor/response_cleaner.py +0 -0
  76. {osa_tool-0.2.1 → osa_tool-0.2.2}/osa_tool/readmegen/prompts/__init__.py +0 -0
  77. {osa_tool-0.2.1 → osa_tool-0.2.2}/osa_tool/readmegen/prompts/prompts_builder.py +0 -0
  78. {osa_tool-0.2.1 → osa_tool-0.2.2}/osa_tool/readmegen/readme_core.py +0 -0
  79. {osa_tool-0.2.1 → osa_tool-0.2.2}/osa_tool/readmegen/utils.py +0 -0
  80. {osa_tool-0.2.1 → osa_tool-0.2.2}/osa_tool/scheduler/__init__.py +0 -0
  81. {osa_tool-0.2.1 → osa_tool-0.2.2}/osa_tool/scheduler/prompts.py +0 -0
  82. {osa_tool-0.2.1 → osa_tool-0.2.2}/osa_tool/scheduler/scheduler.py +0 -0
  83. {osa_tool-0.2.1 → osa_tool-0.2.2}/osa_tool/scheduler/workflow_manager.py +0 -0
  84. {osa_tool-0.2.1 → osa_tool-0.2.2}/osa_tool/translation/__init__.py +0 -0
  85. {osa_tool-0.2.1 → osa_tool-0.2.2}/osa_tool/translation/dir_translator.py +0 -0
  86. {osa_tool-0.2.1 → osa_tool-0.2.2}/osa_tool/ui/__init__.py +0 -0
  87. {osa_tool-0.2.1 → osa_tool-0.2.2}/osa_tool/ui/plan_editor.py +0 -0
  88. {osa_tool-0.2.1 → osa_tool-0.2.2}/osa_tool/ui/web_plan_editor.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: osa_tool
3
- Version: 0.2.1
3
+ Version: 0.2.2
4
4
  Summary: Tool that just makes your open source project better!
5
5
  License: BSD-3-Clause
6
6
  Author: ITMO-NSS-team
@@ -12,7 +12,7 @@ Classifier: Programming Language :: Python :: 3.10
12
12
  Classifier: Programming Language :: Python :: 3.11
13
13
  Classifier: Programming Language :: Python :: 3.12
14
14
  Classifier: Programming Language :: Python :: 3.13
15
- Requires-Dist: ProtoLLM (>=0.1.2)
15
+ Requires-Dist: ProtoLLM (>=0.1.5)
16
16
  Requires-Dist: PyYAML (==6.0.2)
17
17
  Requires-Dist: Pygments (==2.19.1)
18
18
  Requires-Dist: aiofiles (>=24.1.0,<25.0.0)
@@ -60,6 +60,7 @@ Requires-Dist: pydantic (>=2.9.0,<2.11.0)
60
60
  Requires-Dist: pydantic-extra-types (==2.9.0)
61
61
  Requires-Dist: pydantic_core (>=2.23.4,<2.24.0)
62
62
  Requires-Dist: pytest (==8.3.4)
63
+ Requires-Dist: pytest-asyncio (==1.1.0)
63
64
  Requires-Dist: pytest-mock (==3.14.0)
64
65
  Requires-Dist: python-dotenv (==1.0.1)
65
66
  Requires-Dist: qrcode (==8.0)
@@ -121,13 +122,15 @@ It also generates advices and recommendations for the repository.
121
122
 
122
123
  OSA is currently under development, so not all features are implemented.
123
124
 
125
+
126
+
124
127
  ---
125
128
 
126
129
  ## How it works?
127
130
 
128
- Here is a short demo:
131
+ Here is a short video:
129
132
 
130
- ![Animation](./docs/images/osa_demo.gif)
133
+ [![Watch the video](./docs/images/osa_preview.png)](https://www.youtube.com/watch?v=LDSb7JJgKoY)
131
134
 
132
135
  ---
133
136
 
@@ -220,23 +223,29 @@ docker build --build-arg GIT_USER_NAME="your-user-name" --build-arg GIT_USER_EMA
220
223
 
221
224
  OSA requires Python 3.10 or higher.
222
225
 
223
- File `.env` is required to specify GitHub/GitLab/Gitverse token (GIT_TOKEN) and LLM API key (OPENAI_API_KEY or VSE_GPT_KEY)
226
+ File `.env` is required to specify GitHub/GitLab/Gitverse token (GIT_TOKEN) and LLM API key (OPENAI_API_KEY or
227
+ AUTHORIZATION_KEY)
224
228
 
225
229
  When running `osa-tool` from CLI, you need to set the GIT_TOKEN and API key first:
226
230
 
227
- ```commandline
231
+ ```sh
232
+ # Linux / macOS (bash/zsh)
228
233
  export OPENAI_API_KEY=<your_api_key>
229
234
  export GIT_TOKEN=<your_git_token>
235
+
236
+ # Windows (PowerShell)
237
+ setx OPENAI_API_KEY "<your_api_key>"
238
+ setx GIT_TOKEN "<your_git_token>"
230
239
  ```
231
240
 
232
241
  ### Tokens
233
242
 
234
- | Token name | Description | Mandatory |
235
- |------------------|--------------------------------------------------------------------------------------------------------------------|-----------|
236
- | `GIT_TOKEN` | Personal GitHub/GitLab/Gitverse token used to clone private repositories, access metadata, and interact with its API. | Yes |
237
- | `OPENAI_API_KEY` | API key for accessing [OpenAI](https://platform.openai.com/docs/api-reference/introduction)'s language models. | No |
238
- | `VSE_GPT_KEY` | API key for [vsegpt](https://vsegpt.ru/Docs/API) LLM provider compatible with OpenAI's API format. | No |
239
- | `X-API-Key` | API key for the [pepy.tech](https://pepy.tech/pepy-api) REST API, used to fetch Python package download statistics | No |
243
+ | Token name | Description | Mandatory |
244
+ |---------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-----------|
245
+ | `GIT_TOKEN` | Personal GitHub/GitLab/Gitverse token used to clone private repositories, access metadata, and interact with its API. | Yes |
246
+ | `OPENAI_API_KEY` | API key for accessing [OpenAI](https://platform.openai.com/docs/api-reference/introduction), [vsegpt](https://vsegpt.ru/Docs/API) and [openrouter](https://openrouter.ai/) providers | No |
247
+ | `AUTHORIZATION_KEY` | API key for [gigachat](https://developers.sber.ru/portal/products/gigachat-api) provider | No |
248
+ | `X-API-Key` | API key for the [pepy.tech](https://pepy.tech/pepy-api) REST API, used to fetch Python package download statistics | No |
240
249
 
241
250
  ### Usage
242
251
 
@@ -274,15 +283,14 @@ documentation, see the [GitHub Action Workflow Generator README](./osa_tool/gith
274
283
  | `--api` | LLM API service provider | `itmo` |
275
284
  | `--base-url` | URL of the provider compatible with API OpenAI | `https://api.openai.com/v1` |
276
285
  | `--model` | Specific LLM model to use | `gpt-3.5-turbo` |
286
+ | `--top_p` | Nucleus sampling probability | `None` |
287
+ | `--temperature` | Sampling temperature to use for the LLM output (0 = deterministic, 1 = creative). | `None` |
288
+ | `--max_tokens` | Maximum number of tokens the model can generate in a single response | `None` |
277
289
  | `--article` | Link to the pdf file of the article | `None` |
278
- | `--translate-dirs` | Enable automatic translation of the directory name into English | `disabled` |
279
290
  | `-m`, `--mode` | Operation mode for repository processing: `basic`, `auto` (default), or `advanced`. | `auto` |
280
291
  | `--delete-dir` | Enable deleting the downloaded repository after processing | `disabled` |
281
292
  | `--no-fork` | Avoid create fork for target repository | `False` |
282
293
  | `--no-pull-request` | Avoid create pull request for target repository | `False` |
283
- | `--top_p` | Nucleus sampling probability | `null` |
284
- | `--temperature` | Sampling temperature to use for the LLM output (0 = deterministic, 1 = creative). | `null` |
285
- | `--max_tokens` | Maximum number of tokens the model can generate in a single response | `null` |
286
294
 
287
295
  To learn how to work with the interactive CLI and view descriptions of all available keys, visit
288
296
  the [CLI usage guide](./osa_tool/scheduler/README.md).
@@ -293,19 +301,17 @@ the [CLI usage guide](./osa_tool/scheduler/README.md).
293
301
 
294
302
  Examples of generated README files are available in [examples](https://github.com/aimclub/OSA/tree/main/examples).
295
303
 
296
- URL of the GitHub/GitLab/Gitverse repository, LLM API service provider (*optional*) and Specific LLM model to use (*optional*) are
297
- required to use the generator.
304
+ URL of the GitHub/GitLab/Gitverse repository, LLM API service provider (*optional*) and Specific LLM model to use
305
+ (*optional*) are required to use the generator.
298
306
 
299
- To see available models go there:
300
-
301
- 1. [VseGpt](https://vsegpt.ru/Docs/Models)
302
- 2. [OpenAI](https://platform.openai.com/docs/models)
303
- 3. [Ollama](https://ollama.com/library)
307
+ Supported LLM providers are available as part of the [ProtoLLM](https://github.com/aimclub/ProtoLLM/)
308
+ ecosystem. See the [connectors directory](https://github.com/aimclub/ProtoLLM/tree/main/protollm/connectors) for the
309
+ full list.
304
310
 
305
311
  Local ITMO model:
306
312
 
307
313
  ```sh
308
- python -m osa_tool.run -r https://github.com/aimclub/OSA --base_url [ITMO_MODEL_URL]
314
+ python -m osa_tool.run -r https://github.com/aimclub/OSA --base-url [ITMO_MODEL_URL]
309
315
  ```
310
316
 
311
317
  For this API provider itmo model url must be specified in dotenv (ITMO_MODEL_URL=) or in the --base-url argument.
@@ -322,6 +328,12 @@ VseGPT:
322
328
  python -m osa_tool.run -r https://github.com/aimclub/OSA --api openai --base-url https://api.vsegpt.ru/v1 --model openai/gpt-3.5-turbo
323
329
  ```
324
330
 
331
+ Openrouter:
332
+
333
+ ```sh
334
+ python -m osa_tool.run -r https://github.com/aimclub/OSA --api openai --base-url https://openrouter.ai/api/v1 --model qwen/qwen3-30b-a3b-instruct-2507
335
+ ```
336
+
325
337
  Ollama:
326
338
 
327
339
  ```sh
@@ -338,7 +350,8 @@ Detailed description of OSA API is available [here](https://aimclub.github.io/OS
338
350
 
339
351
  ## Chat with developers: OSA_helpdesk
340
352
 
341
- In our Telegram chat [OSA_helpdesk](t.me/osa_helpdesk) you can ask questions about working with OSA and find the latest news about the project.
353
+ In our Telegram chat [OSA_helpdesk](t.me/osa_helpdesk) you can ask questions about working with OSA and find the latest
354
+ news about the project.
342
355
 
343
356
  ---
344
357
 
@@ -385,29 +398,20 @@ for their code that we used as a foundation for our own version of README genera
385
398
 
386
399
  If you use this software, please cite it as below.
387
400
 
388
- ### APA format
401
+ ### Simple format
389
402
 
390
- ITMO, NSS Lab (2025). Open-Source-Advisor repository [Computer software]. https://github.com/aimclub/OSA
403
+ Nikitin N. et al. An LLM-Powered Tool for Enhancing Scientific Open-Source Repositories // Championing Open-source DEvelopment in ML Workshop@ ICML25.
391
404
 
392
405
  ### BibTeX format
393
406
 
394
- @misc{Open-Source-Advisor,
395
-
396
- author = {ITMO, NSS Lab},
397
-
398
- title = {Open-Source-Advisor repository},
399
-
400
- year = {2025},
401
-
402
- publisher = {github.com},
403
-
404
- journal = {github.com repository},
405
-
406
- howpublished = {\url{https://github.com/aimclub/OSA.git}},
407
-
408
- url = {https://github.com/aimclub/OSA.git}
407
+ @inproceedings{nikitinllm,
408
+ title={An LLM-Powered Tool for Enhancing Scientific Open-Source Repositories},
409
+ author={Nikitin, Nikolay and Getmanov, Andrey and Popov, Zakhar and
410
+ Ulyanova Ekaterina and Aksenkin, Yaroslav and
411
+ Sokolov, Ilya and Boukhanovsky, Alexander},
412
+ booktitle={Championing Open-source DEvelopment in ML Workshop@ ICML25}
409
413
 
410
- }
414
+ }
411
415
 
412
416
  ---
413
417
 
@@ -36,13 +36,15 @@ It also generates advices and recommendations for the repository.
36
36
 
37
37
  OSA is currently under development, so not all features are implemented.
38
38
 
39
+
40
+
39
41
  ---
40
42
 
41
43
  ## How it works?
42
44
 
43
- Here is a short demo:
45
+ Here is a short video:
44
46
 
45
- ![Animation](./docs/images/osa_demo.gif)
47
+ [![Watch the video](./docs/images/osa_preview.png)](https://www.youtube.com/watch?v=LDSb7JJgKoY)
46
48
 
47
49
  ---
48
50
 
@@ -135,23 +137,29 @@ docker build --build-arg GIT_USER_NAME="your-user-name" --build-arg GIT_USER_EMA
135
137
 
136
138
  OSA requires Python 3.10 or higher.
137
139
 
138
- File `.env` is required to specify GitHub/GitLab/Gitverse token (GIT_TOKEN) and LLM API key (OPENAI_API_KEY or VSE_GPT_KEY)
140
+ File `.env` is required to specify GitHub/GitLab/Gitverse token (GIT_TOKEN) and LLM API key (OPENAI_API_KEY or
141
+ AUTHORIZATION_KEY)
139
142
 
140
143
  When running `osa-tool` from CLI, you need to set the GIT_TOKEN and API key first:
141
144
 
142
- ```commandline
145
+ ```sh
146
+ # Linux / macOS (bash/zsh)
143
147
  export OPENAI_API_KEY=<your_api_key>
144
148
  export GIT_TOKEN=<your_git_token>
149
+
150
+ # Windows (PowerShell)
151
+ setx OPENAI_API_KEY "<your_api_key>"
152
+ setx GIT_TOKEN "<your_git_token>"
145
153
  ```
146
154
 
147
155
  ### Tokens
148
156
 
149
- | Token name | Description | Mandatory |
150
- |------------------|--------------------------------------------------------------------------------------------------------------------|-----------|
151
- | `GIT_TOKEN` | Personal GitHub/GitLab/Gitverse token used to clone private repositories, access metadata, and interact with its API. | Yes |
152
- | `OPENAI_API_KEY` | API key for accessing [OpenAI](https://platform.openai.com/docs/api-reference/introduction)'s language models. | No |
153
- | `VSE_GPT_KEY` | API key for [vsegpt](https://vsegpt.ru/Docs/API) LLM provider compatible with OpenAI's API format. | No |
154
- | `X-API-Key` | API key for the [pepy.tech](https://pepy.tech/pepy-api) REST API, used to fetch Python package download statistics | No |
157
+ | Token name | Description | Mandatory |
158
+ |---------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-----------|
159
+ | `GIT_TOKEN` | Personal GitHub/GitLab/Gitverse token used to clone private repositories, access metadata, and interact with its API. | Yes |
160
+ | `OPENAI_API_KEY` | API key for accessing [OpenAI](https://platform.openai.com/docs/api-reference/introduction), [vsegpt](https://vsegpt.ru/Docs/API) and [openrouter](https://openrouter.ai/) providers | No |
161
+ | `AUTHORIZATION_KEY` | API key for [gigachat](https://developers.sber.ru/portal/products/gigachat-api) provider | No |
162
+ | `X-API-Key` | API key for the [pepy.tech](https://pepy.tech/pepy-api) REST API, used to fetch Python package download statistics | No |
155
163
 
156
164
  ### Usage
157
165
 
@@ -189,15 +197,14 @@ documentation, see the [GitHub Action Workflow Generator README](./osa_tool/gith
189
197
  | `--api` | LLM API service provider | `itmo` |
190
198
  | `--base-url` | URL of the provider compatible with API OpenAI | `https://api.openai.com/v1` |
191
199
  | `--model` | Specific LLM model to use | `gpt-3.5-turbo` |
200
+ | `--top_p` | Nucleus sampling probability | `None` |
201
+ | `--temperature` | Sampling temperature to use for the LLM output (0 = deterministic, 1 = creative). | `None` |
202
+ | `--max_tokens` | Maximum number of tokens the model can generate in a single response | `None` |
192
203
  | `--article` | Link to the pdf file of the article | `None` |
193
- | `--translate-dirs` | Enable automatic translation of the directory name into English | `disabled` |
194
204
  | `-m`, `--mode` | Operation mode for repository processing: `basic`, `auto` (default), or `advanced`. | `auto` |
195
205
  | `--delete-dir` | Enable deleting the downloaded repository after processing | `disabled` |
196
206
  | `--no-fork` | Avoid create fork for target repository | `False` |
197
207
  | `--no-pull-request` | Avoid create pull request for target repository | `False` |
198
- | `--top_p` | Nucleus sampling probability | `null` |
199
- | `--temperature` | Sampling temperature to use for the LLM output (0 = deterministic, 1 = creative). | `null` |
200
- | `--max_tokens` | Maximum number of tokens the model can generate in a single response | `null` |
201
208
 
202
209
  To learn how to work with the interactive CLI and view descriptions of all available keys, visit
203
210
  the [CLI usage guide](./osa_tool/scheduler/README.md).
@@ -208,19 +215,17 @@ the [CLI usage guide](./osa_tool/scheduler/README.md).
208
215
 
209
216
  Examples of generated README files are available in [examples](https://github.com/aimclub/OSA/tree/main/examples).
210
217
 
211
- URL of the GitHub/GitLab/Gitverse repository, LLM API service provider (*optional*) and Specific LLM model to use (*optional*) are
212
- required to use the generator.
218
+ URL of the GitHub/GitLab/Gitverse repository, LLM API service provider (*optional*) and Specific LLM model to use
219
+ (*optional*) are required to use the generator.
213
220
 
214
- To see available models go there:
215
-
216
- 1. [VseGpt](https://vsegpt.ru/Docs/Models)
217
- 2. [OpenAI](https://platform.openai.com/docs/models)
218
- 3. [Ollama](https://ollama.com/library)
221
+ Supported LLM providers are available as part of the [ProtoLLM](https://github.com/aimclub/ProtoLLM/)
222
+ ecosystem. See the [connectors directory](https://github.com/aimclub/ProtoLLM/tree/main/protollm/connectors) for the
223
+ full list.
219
224
 
220
225
  Local ITMO model:
221
226
 
222
227
  ```sh
223
- python -m osa_tool.run -r https://github.com/aimclub/OSA --base_url [ITMO_MODEL_URL]
228
+ python -m osa_tool.run -r https://github.com/aimclub/OSA --base-url [ITMO_MODEL_URL]
224
229
  ```
225
230
 
226
231
  For this API provider itmo model url must be specified in dotenv (ITMO_MODEL_URL=) or in the --base-url argument.
@@ -237,6 +242,12 @@ VseGPT:
237
242
  python -m osa_tool.run -r https://github.com/aimclub/OSA --api openai --base-url https://api.vsegpt.ru/v1 --model openai/gpt-3.5-turbo
238
243
  ```
239
244
 
245
+ Openrouter:
246
+
247
+ ```sh
248
+ python -m osa_tool.run -r https://github.com/aimclub/OSA --api openai --base-url https://openrouter.ai/api/v1 --model qwen/qwen3-30b-a3b-instruct-2507
249
+ ```
250
+
240
251
  Ollama:
241
252
 
242
253
  ```sh
@@ -253,7 +264,8 @@ Detailed description of OSA API is available [here](https://aimclub.github.io/OS
253
264
 
254
265
  ## Chat with developers: OSA_helpdesk
255
266
 
256
- In our Telegram chat [OSA_helpdesk](t.me/osa_helpdesk) you can ask questions about working with OSA and find the latest news about the project.
267
+ In our Telegram chat [OSA_helpdesk](t.me/osa_helpdesk) you can ask questions about working with OSA and find the latest
268
+ news about the project.
257
269
 
258
270
  ---
259
271
 
@@ -300,28 +312,19 @@ for their code that we used as a foundation for our own version of README genera
300
312
 
301
313
  If you use this software, please cite it as below.
302
314
 
303
- ### APA format
315
+ ### Simple format
304
316
 
305
- ITMO, NSS Lab (2025). Open-Source-Advisor repository [Computer software]. https://github.com/aimclub/OSA
317
+ Nikitin N. et al. An LLM-Powered Tool for Enhancing Scientific Open-Source Repositories // Championing Open-source DEvelopment in ML Workshop@ ICML25.
306
318
 
307
319
  ### BibTeX format
308
320
 
309
- @misc{Open-Source-Advisor,
310
-
311
- author = {ITMO, NSS Lab},
312
-
313
- title = {Open-Source-Advisor repository},
314
-
315
- year = {2025},
316
-
317
- publisher = {github.com},
318
-
319
- journal = {github.com repository},
320
-
321
- howpublished = {\url{https://github.com/aimclub/OSA.git}},
322
-
323
- url = {https://github.com/aimclub/OSA.git}
321
+ @inproceedings{nikitinllm,
322
+ title={An LLM-Powered Tool for Enhancing Scientific Open-Source Repositories},
323
+ author={Nikitin, Nikolay and Getmanov, Andrey and Popov, Zakhar and
324
+ Ulyanova Ekaterina and Aksenkin, Yaroslav and
325
+ Sokolov, Ilya and Boukhanovsky, Alexander},
326
+ booktitle={Championing Open-source DEvelopment in ML Workshop@ ICML25}
324
327
 
325
- }
328
+ }
326
329
 
327
330
  ---
@@ -137,7 +137,7 @@ class AboutGenerator:
137
137
  topics = [topic.strip().lower().replace(" ", "-") for topic in response.split(",") if topic.strip()]
138
138
  logger.debug(f"Generated topics from LLM: {topics}")
139
139
  validated_topics = self._validate_topics(topics)
140
- return list(set([*existing_topics, *validated_topics]))
140
+ return list({*existing_topics, *validated_topics})
141
141
  except Exception as e:
142
142
  logger.error(f"Error generating topics: {e}")
143
143
  return []
@@ -161,7 +161,8 @@ class AboutGenerator:
161
161
  logger.warning(f"Topic validation not implemented for platform: {self.platform}")
162
162
  return topics
163
163
 
164
- def _validate_github_topics(self, topics: List[str]) -> List[str]:
164
+ @staticmethod
165
+ def _validate_github_topics(topics: List[str]) -> List[str]:
165
166
  """Validates topics against GitHub Topics API.
166
167
 
167
168
  Args:
@@ -205,7 +206,8 @@ class AboutGenerator:
205
206
  logger.info(f"Validated {len(validated_topics)} topics out of {len(topics)}.")
206
207
  return validated_topics
207
208
 
208
- def _validate_gitlab_topics(self, topics: List[str]) -> List[str]:
209
+ @staticmethod
210
+ def _validate_gitlab_topics(topics: List[str]) -> List[str]:
209
211
  """Validates topics against GitLab Topics API.
210
212
 
211
213
  Args:
@@ -243,7 +245,8 @@ class AboutGenerator:
243
245
  logger.info(f"Validated {len(validated_topics)} topics out of {len(topics)}.")
244
246
  return validated_topics
245
247
 
246
- def _validate_gitverse_topics(self, topics: List[str]) -> List[str]:
248
+ @staticmethod
249
+ def _validate_gitverse_topics(topics: List[str]) -> List[str]:
247
250
  """Validates topics for Gitverse platform.
248
251
 
249
252
  Args:
@@ -285,7 +288,8 @@ class AboutGenerator:
285
288
 
286
289
  return candidates[0] if candidates else ""
287
290
 
288
- def _extract_readme_urls(self, readme_content: str) -> List[str]:
291
+ @staticmethod
292
+ def _extract_readme_urls(readme_content: str) -> List[str]:
289
293
  """Extract all absolute URLs from README content"""
290
294
  logger.info("Extracting URLs from README.")
291
295
  url_pattern = r"(?:http|ftp|https):\/\/(?:[\w_-]+(?:(?:\.[\w_-]+)+))(?:[\w.,@?^=%&:\/~+#-]*[\w@?^=%&\/~+#-])"
@@ -171,6 +171,7 @@ def _parse_repository_metadata_gitlab(repo_data: dict) -> RepositoryMetadata:
171
171
  def _parse_repository_metadata_gitverse(repo_data: dict) -> RepositoryMetadata:
172
172
  """Parse Gitverse API response into RepositoryMetadata."""
173
173
  owner_info = repo_data.get("owner", {}) or {}
174
+ license_info = repo_data.get("license") or {}
174
175
 
175
176
  return RepositoryMetadata(
176
177
  name=repo_data.get("name", ""),
@@ -200,8 +201,8 @@ def _parse_repository_metadata_gitverse(repo_data: dict) -> RepositoryMetadata:
200
201
  has_projects=repo_data.get("has_projects", False),
201
202
  is_private=repo_data.get("private", False),
202
203
  homepage_url=repo_data.get("homepage", ""),
203
- license_name=repo_data.get("license", {}).get("name", ""),
204
- license_url=repo_data.get("license", {}).get("url", ""),
204
+ license_name=license_info.get("name", ""),
205
+ license_url=license_info.get("url", ""),
205
206
  platform="gitverse",
206
207
  )
207
208
 
@@ -1,7 +1,7 @@
1
- from pydantic import BaseModel, Field
2
- from typing import List
3
1
  from enum import Enum
4
2
 
3
+ from pydantic import BaseModel, Field
4
+
5
5
 
6
6
  class YesNoPartial(str, Enum):
7
7
  YES = "Yes"
@@ -12,7 +12,7 @@ class YesNoPartial(str, Enum):
12
12
 
13
13
  class RepositoryStructure(BaseModel):
14
14
  compliance: str = Field("Unknown", description="Compliance with standard structure")
15
- missing_files: List[str] = Field(
15
+ missing_files: list[str] = Field(
16
16
  default_factory=list,
17
17
  description="List of missing critical files that impact project usability and clarity",
18
18
  )
@@ -45,11 +45,11 @@ class CodeDocumentation(BaseModel):
45
45
 
46
46
 
47
47
  class OverallAssessment(BaseModel):
48
- key_shortcomings: List[str] = Field(
48
+ key_shortcomings: list[str] = Field(
49
49
  default_factory=lambda: ["There are no critical issues"],
50
50
  description="List of the most significant and critical issues that need to be addressed",
51
51
  )
52
- recommendations: List[str] = Field(
52
+ recommendations: list[str] = Field(
53
53
  default_factory=lambda: ["No recommendations"],
54
54
  description="Specific improvements to address issues or optimize the process",
55
55
  )
@@ -14,6 +14,7 @@ from reportlab.platypus import (
14
14
  Spacer,
15
15
  Table,
16
16
  TableStyle,
17
+ Flowable,
17
18
  )
18
19
 
19
20
  from osa_tool.analytics.metadata import load_data_metadata
@@ -247,7 +248,7 @@ class ReportGenerator:
247
248
  )
248
249
  return bullet_list
249
250
 
250
- def body_second_part(self) -> list:
251
+ def body_second_part(self) -> list[Flowable]:
251
252
  """
252
253
  Generates the second part of the report, which contains the analysis of the repository.
253
254
 
@@ -353,7 +354,6 @@ class ReportGenerator:
353
354
  pagesize=A4,
354
355
  topMargin=50,
355
356
  bottomMargin=40,
356
- leftMaring=10,
357
357
  )
358
358
  doc.build(
359
359
  [
@@ -6,7 +6,7 @@ import pandas as pd
6
6
 
7
7
  from osa_tool.analytics.report_maker import ReportGenerator
8
8
  from osa_tool.analytics.sourcerank import SourceRank
9
- from osa_tool.github_agent.github_agent import GithubAgent
9
+ from osa_tool.git_agent.git_agent import GitAgent
10
10
  from osa_tool.readmegen.context.pypi_status_checker import PyPiPackageInspector
11
11
  from osa_tool.run import load_configuration
12
12
  from osa_tool.utils import logger, rich_section, delete_repository
@@ -78,7 +78,7 @@ def main():
78
78
  )
79
79
 
80
80
  # Clone the repository
81
- github_agent = GithubAgent(repo_url)
81
+ github_agent = GitAgent(repo_url)
82
82
  github_agent.clone_repository()
83
83
 
84
84
  # Initialize analytics and generate report
@@ -1,20 +1,22 @@
1
1
  import argparse
2
+ from typing import Any
2
3
 
4
+ import tomli
3
5
  import yaml
4
6
 
7
+ from osa_tool.utils import build_arguments_path, build_config_path
5
8
 
6
- def build_parser_from_yaml(yaml_path: str) -> argparse.ArgumentParser:
9
+
10
+ def build_parser_from_yaml() -> argparse.ArgumentParser:
7
11
  """
8
12
  Build an ArgumentParser based on a YAML configuration file.
9
13
 
10
- Args:
11
- yaml_path: Path to the YAML file defining CLI arguments.
12
-
13
14
  Returns:
14
15
  argparse.ArgumentParser: Configured argument parser.
15
16
  """
16
17
 
17
- config = read_arguments_file(yaml_path)
18
+ config_yaml = read_arguments_file(build_arguments_path())
19
+ config_toml = read_config_file(build_config_path())
18
20
 
19
21
  parser = argparse.ArgumentParser(
20
22
  description="Generated CLI parser from YAML configuration",
@@ -26,39 +28,34 @@ def build_parser_from_yaml(yaml_path: str) -> argparse.ArgumentParser:
26
28
  aliases = options.get("aliases", [])
27
29
  arg_type = options.get("type", "str")
28
30
  description = options.get("description", "")
29
- default = options.get("default")
30
31
  choices = options.get("choices")
31
-
32
+ default = get_default_from_config(config_toml, key)
32
33
  kwargs = {"help": description}
33
34
 
34
35
  if arg_type == "flag":
35
36
  kwargs["action"] = "store_true"
36
- if default is not None:
37
- kwargs["default"] = default
37
+ kwargs["default"] = default
38
38
  elif arg_type == "str":
39
39
  kwargs["type"] = str
40
- if default is not None:
41
- kwargs["default"] = default
40
+ kwargs["default"] = default
42
41
  if choices:
43
42
  kwargs["choices"] = choices
44
43
  elif arg_type == "int":
45
44
  kwargs["type"] = int
46
- if default is not None:
47
- kwargs["default"] = default
45
+ kwargs["default"] = default
48
46
  elif arg_type == "list":
49
47
  kwargs["nargs"] = "+"
50
48
  kwargs["type"] = str
51
- if default is not None:
52
- kwargs["default"] = default
49
+ kwargs["default"] = default
53
50
  else:
54
51
  raise ValueError(f"Unsupported type '{arg_type}' for argument '{key}'")
55
52
 
56
53
  group.add_argument(*aliases, **kwargs)
57
54
 
58
- core_args = {k: v for k, v in config.items() if not isinstance(v, dict) or "type" in v}
55
+ core_args = {k: v for k, v in config_yaml.items() if not isinstance(v, dict) or "type" in v}
59
56
  add_arguments(parser, core_args)
60
57
 
61
- for group_name, group_args in config.items():
58
+ for group_name, group_args in config_yaml.items():
62
59
  if isinstance(group_args, dict) and "type" not in group_args:
63
60
  arg_group = parser.add_argument_group(f"{group_name} arguments")
64
61
  add_arguments(arg_group, group_args)
@@ -66,8 +63,8 @@ def build_parser_from_yaml(yaml_path: str) -> argparse.ArgumentParser:
66
63
  return parser
67
64
 
68
65
 
69
- def get_keys_from_group_in_yaml(yaml_path, group_name) -> list:
70
- data = read_arguments_file(yaml_path)
66
+ def get_keys_from_group_in_yaml(group_name: str) -> list:
67
+ data = read_arguments_file(build_arguments_path())
71
68
  keys = []
72
69
  for key, params in data.items():
73
70
  if key == group_name:
@@ -75,7 +72,7 @@ def get_keys_from_group_in_yaml(yaml_path, group_name) -> list:
75
72
  return keys
76
73
 
77
74
 
78
- def read_arguments_file_flat(yaml_path) -> dict:
75
+ def read_arguments_file_flat(yaml_path: str) -> dict:
79
76
  """
80
77
  Read YAML arguments file and flatten nested groups into a single dict.
81
78
  """
@@ -92,7 +89,24 @@ def read_arguments_file_flat(yaml_path) -> dict:
92
89
  return flat_data
93
90
 
94
91
 
95
- def read_arguments_file(yaml_path) -> dict:
92
+ def get_default_from_config(config: dict, key: str) -> Any:
93
+ """
94
+ Find default value for a key in config dict by searching all top-level sections.
95
+ """
96
+ for section, values in config.items():
97
+ if isinstance(values, dict) and key in values:
98
+ return values[key]
99
+ return None
100
+
101
+
102
+ def read_arguments_file(yaml_path: str) -> dict:
96
103
  with open(yaml_path, "r", encoding="utf-8") as f:
97
104
  data = yaml.safe_load(f)
98
105
  return data
106
+
107
+
108
+ def read_config_file(toml_path: str) -> dict[str, Any]:
109
+ """Load TOML config as a nested dict."""
110
+ with open(toml_path, "rb") as f:
111
+ data = tomli.load(f)
112
+ return {k.lower(): v for k, v in data.items()}