janito 0.6.0__py3-none-any.whl → 0.7.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.
Files changed (54) hide show
  1. janito/__main__.py +37 -30
  2. janito/agents/__init__.py +8 -2
  3. janito/agents/agent.py +10 -3
  4. janito/agents/claudeai.py +13 -23
  5. janito/agents/openai.py +5 -1
  6. janito/change/analysis/analyze.py +8 -7
  7. janito/change/analysis/prompts.py +4 -12
  8. janito/change/analysis/view/terminal.py +21 -11
  9. janito/change/applier/text.py +7 -5
  10. janito/change/core.py +22 -29
  11. janito/change/parser.py +0 -2
  12. janito/change/prompts.py +16 -21
  13. janito/change/validator.py +27 -9
  14. janito/change/viewer/content.py +1 -1
  15. janito/change/viewer/panels.py +93 -115
  16. janito/change/viewer/styling.py +15 -4
  17. janito/cli/commands.py +63 -20
  18. janito/common.py +44 -18
  19. janito/config.py +44 -44
  20. janito/prompt.py +36 -0
  21. janito/qa.py +5 -14
  22. janito/search_replace/README.md +63 -17
  23. janito/search_replace/__init__.py +2 -1
  24. janito/search_replace/core.py +15 -14
  25. janito/search_replace/logger.py +35 -0
  26. janito/search_replace/searcher.py +160 -48
  27. janito/search_replace/strategy_result.py +10 -0
  28. janito/shell/__init__.py +15 -16
  29. janito/shell/commands.py +38 -97
  30. janito/shell/processor.py +7 -27
  31. janito/shell/prompt.py +48 -0
  32. janito/shell/registry.py +60 -0
  33. janito/workspace/__init__.py +4 -5
  34. janito/workspace/analysis.py +2 -2
  35. janito/workspace/show.py +141 -0
  36. janito/workspace/stats.py +43 -0
  37. janito/workspace/types.py +98 -0
  38. janito/workspace/workset.py +108 -0
  39. janito/workspace/workspace.py +114 -0
  40. janito-0.7.0.dist-info/METADATA +167 -0
  41. {janito-0.6.0.dist-info → janito-0.7.0.dist-info}/RECORD +44 -43
  42. janito/change/viewer/pager.py +0 -56
  43. janito/cli/handlers/ask.py +0 -22
  44. janito/cli/handlers/demo.py +0 -22
  45. janito/cli/handlers/request.py +0 -24
  46. janito/cli/handlers/scan.py +0 -9
  47. janito/prompts.py +0 -2
  48. janito/shell/handlers.py +0 -122
  49. janito/workspace/manager.py +0 -48
  50. janito/workspace/scan.py +0 -232
  51. janito-0.6.0.dist-info/METADATA +0 -185
  52. {janito-0.6.0.dist-info → janito-0.7.0.dist-info}/WHEEL +0 -0
  53. {janito-0.6.0.dist-info → janito-0.7.0.dist-info}/entry_points.txt +0 -0
  54. {janito-0.6.0.dist-info → janito-0.7.0.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,167 @@
1
+ Metadata-Version: 2.4
2
+ Name: janito
3
+ Version: 0.7.0
4
+ Summary: A CLI tool for software development tasks powered by AI
5
+ Project-URL: Homepage, https://github.com/joaompinto/janito
6
+ Project-URL: Repository, https://github.com/joaompinto/janito.git
7
+ Author-email: João Pinto <lamego.pinto@gmail.com>
8
+ License: MIT
9
+ License-File: LICENSE
10
+ Classifier: Development Status :: 4 - Beta
11
+ Classifier: Environment :: Console
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: License :: OSI Approved :: MIT License
14
+ Classifier: Programming Language :: Python :: 3.8
15
+ Classifier: Programming Language :: Python :: 3.9
16
+ Classifier: Programming Language :: Python :: 3.10
17
+ Classifier: Topic :: Software Development
18
+ Requires-Python: >=3.8
19
+ Requires-Dist: anthropic
20
+ Requires-Dist: pathspec
21
+ Requires-Dist: rich
22
+ Requires-Dist: tomli
23
+ Requires-Dist: typer
24
+ Description-Content-Type: text/markdown
25
+
26
+ # Janito
27
+
28
+ [![PyPI version](https://badge.fury.io/py/janito.svg)](https://badge.fury.io/py/janito)
29
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
30
+
31
+ AI-powered CLI tool for code modifications and analysis. Janito helps you modify, analyze, and understand your codebase using natural language commands.
32
+
33
+ ## Table of Contents
34
+
35
+ - [Features](#features)
36
+ - [Installation](#installation)
37
+ - [Usage](#usage)
38
+ - [Basic Commands](#basic-commands)
39
+ - [Examples](#examples)
40
+ - [Configuration](#configuration)
41
+ - [Development](#development)
42
+ - [License](#license)
43
+
44
+ ## Features
45
+
46
+ - 🤖 AI-powered code analysis and modifications
47
+ - 🔄 Incremental code changes with search/replace operations
48
+ - 🎯 Precise text modifications with context matching
49
+ - 💬 Natural language interface for code operations
50
+ - 🔍 Interactive code exploration
51
+ - 📝 Automatic documentation generation
52
+ - ⚡ Fast and efficient codebase navigation
53
+ - 💾 Smart Claude AI prompt caching for faster responses
54
+
55
+ ## Installation
56
+
57
+ ### Prerequisites
58
+
59
+ - Python 3.8 or higher
60
+ - Anthropic API key (with smart caching to reduce API costs)
61
+
62
+ ### Install via pip
63
+
64
+ ```bash
65
+ pip install janito
66
+ ```
67
+
68
+ ### Set up API key
69
+
70
+ ```bash
71
+ export ANTHROPIC_API_KEY=your_api_key_here
72
+ ```
73
+
74
+ ## Usage
75
+
76
+ ### Basic Commands
77
+
78
+ Janito supports incremental code changes through precise text operations:
79
+ - Search and replace with context matching
80
+ - Delete specific code blocks
81
+ - File operations (create, replace, rename, move, remove)
82
+
83
+ ```bash
84
+ # Start interactive shell
85
+ janito
86
+
87
+ # Modify code with natural language
88
+ janito "add docstrings to this file"
89
+
90
+ # Ask questions about the codebase
91
+ janito --ask "explain the main function in this file"
92
+
93
+ # Preview files that would be analyzed
94
+ janito --scan
95
+ ```
96
+
97
+ ### Examples
98
+
99
+ 1. Add documentation to a file:
100
+ ```bash
101
+ janito "add docstrings to all functions in src/main.py"
102
+ ```
103
+
104
+ 2. Analyze code structure:
105
+ ```bash
106
+ janito --ask "what are the main classes in this project?"
107
+ ```
108
+
109
+ 3. Refactor code:
110
+ ```bash
111
+ janito "convert this function to use async/await"
112
+ ```
113
+
114
+ 4. Generate tests:
115
+ ```bash
116
+ janito "create unit tests for the User class"
117
+ ```
118
+
119
+ ## Configuration
120
+
121
+ ### Environment Variables
122
+
123
+ - `ANTHROPIC_API_KEY`: Anthropic API key for Claude AI
124
+ - `JANITO_TEST_CMD`: Default test command to run after changes
125
+
126
+ ### Command Line Options
127
+
128
+ - `-w, --workspace_dir`: Set working directory
129
+ - `-i, --include`: Additional paths to include
130
+ - `--debug`: Show debug information
131
+ - `--verbose`: Show verbose output
132
+ - `--auto-apply`: Apply changes without confirmation
133
+
134
+ ## Development
135
+
136
+ ### Setting up Development Environment
137
+
138
+ ```bash
139
+ # Clone the repository
140
+ git clone https://github.com/joaompinto/janito.git
141
+ cd janito
142
+
143
+ # Create and activate virtual environment
144
+ python -m venv venv
145
+ source venv/bin/activate # On Windows: venv\Scripts\activate
146
+
147
+ # Install development dependencies
148
+ pip install -e ".[dev]"
149
+ ```
150
+
151
+ ### Running Tests
152
+
153
+ ```bash
154
+ pytest
155
+ ```
156
+
157
+ ### Contributing
158
+
159
+ 1. Fork the repository
160
+ 2. Create a feature branch
161
+ 3. Commit your changes
162
+ 4. Push to the branch
163
+ 5. Create a Pull Request
164
+
165
+ ## License
166
+
167
+ MIT License - see [LICENSE](LICENSE)
@@ -1,46 +1,45 @@
1
1
  janito/__init__.py,sha256=Svp3i5NGeapDV4xB-CDu9TjqEzvsnjQwSzdmDT9DDqc,47
2
- janito/__main__.py,sha256=MChFWxE8OPLe8QsdG1nxS1l5s0oZkJoJUlX3IRqEklk,5069
3
- janito/common.py,sha256=jGoA1RyglPBpTQJcDdCj6Ar-h8Eh6U7ZOlgJjvdm91M,2076
4
- janito/config.py,sha256=B5S6mmnQi2HMA_F6FuGREdbHTj_vdi2cl1WzfFBaiJc,3134
5
- janito/prompts.py,sha256=VNC_1orab53YbdKIfnDub_r2PGQbwLn3hUZL0TcSvJQ,201
6
- janito/qa.py,sha256=4zXuEg48ogyXmL_jZpJWo4xT0cPY7LG4dUvF-_mvGIc,1959
2
+ janito/__main__.py,sha256=l20_V0iIX_8yjJeP-THirJATybgCbmikzu5colMb1P0,5544
3
+ janito/common.py,sha256=VaFTF5VM6dClNGFVC1A9b-EbpqcqrQpybl6eidl8T9c,3381
4
+ janito/config.py,sha256=f0chVHjfds62W-wUDPLlshxh8W1VviqHw2kbm-_qLSA,3126
5
+ janito/prompt.py,sha256=Rd6I0C4y0uSgWCggoLJiSiET9vT3nlgtwfSKo06jMDc,1011
6
+ janito/qa.py,sha256=8MBQnKgUGErgJ3XWE2cd9WvSAHyke-AL5jO8iPhfhng,1794
7
7
  janito/review.py,sha256=5Oc6BfxMGNmKbIeDP5_EiAKUDeQwVOD0YL7iqfgJLRE,471
8
8
  janito/version.py,sha256=ylfPwGtdY8dEOFJ-DB9gKUQLggqRCvoLxhpnwjzCM94,739
9
- janito/agents/__init__.py,sha256=I_N-11HvV76yUfDOV_43U5tXz5e5kSnQamCQJE9OXXQ,510
10
- janito/agents/agent.py,sha256=3uGiUrvj9oCW6_oK-oMQQJ77K8jZFv7mAdXlIG1dxNY,751
11
- janito/agents/claudeai.py,sha256=zPySDG70ATKWPvzB4CKpaK9E8pbmzOhCE1i8ESwaE0o,1908
12
- janito/agents/openai.py,sha256=tNtlzFJMWFv38Z62opR23u6xXlZ9L4xX_mf2f3wjrLU,2082
9
+ janito/agents/__init__.py,sha256=o4CL_6UkTx62W9VyOshecAgnPrlBeiDqH3l82RKN2gA,755
10
+ janito/agents/agent.py,sha256=81Bx9I6U0U-KDFMKkV0Q-ZlzCxbuJBUHGKUHqG45S_E,927
11
+ janito/agents/claudeai.py,sha256=WWCFWJ4T6v6dPZubpGgsQTzgd9lB4ViNm29FC66wl_U,1608
12
+ janito/agents/openai.py,sha256=VdskCojBIbRvKTjiVqwn1f3rfGHynUFDaIvnlwRYs1c,2282
13
13
  janito/agents/test.py,sha256=xoN1q9DUSYpUbnvTP1qZsEfxYrZfocJlt9DkIuMDvvY,1552
14
14
  janito/change/__init__.py,sha256=vGn9qudqiusp4LsR2zzr3mbb4dhXvcGBY2NNzl1JC5M,955
15
15
  janito/change/__main__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
16
- janito/change/core.py,sha256=TGlNQBZm2TdEPtWZSUV5kldxv1y4urL2YkeOn1wDxTk,4070
16
+ janito/change/core.py,sha256=fTAFv3FwYgPxwhuMOSigglYX0l30KY6X17L_VxBviB4,3871
17
17
  janito/change/history.py,sha256=rbprE1lnOl5We85c-VsDnHAiGphW0t2fA7zu4N9uulw,1405
18
18
  janito/change/operations.py,sha256=5HeUvFa503Foemngu-ShomPn9W82XH-gLlTfXxAZoEw,165
19
- janito/change/parser.py,sha256=hrwJXn318mfiw1zWiLN9Frdsp5BKpg83YToCkSyHtQw,11242
19
+ janito/change/parser.py,sha256=EYQgy1L8yWNPTgdVNWeiXFbAtzPJNBwU15-dE4ThG68,11169
20
20
  janito/change/play.py,sha256=ZzYp-eaIBn578EiPB9uVR-G-mxXiK_hD_GI15htb0DU,1835
21
21
  janito/change/preview.py,sha256=xfwo0q7jAx-U92U3iEwDDlsZnzndj7fshq8OLgjv3Vw,2720
22
- janito/change/prompts.py,sha256=e0uxXRRz1U1AJS-6pDcoOGJjothJNBhvixtGGYkPyWc,4372
22
+ janito/change/prompts.py,sha256=00HcNIEZwLCEY1SvT5unaIiAkCoiSCG-DYk94YmWcPQ,4345
23
23
  janito/change/test.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
24
- janito/change/validator.py,sha256=WxGruFjH9yAsHTOWWIJFpPurrWHNNXE69JogDmraF9A,10310
24
+ janito/change/validator.py,sha256=sd8QXruxQPdG-rVCM6NIXsVmK50ytzrtsx2J3is06Ww,10943
25
25
  janito/change/analysis/__init__.py,sha256=yg9LhcC1nCvleGt4cnQMuJYCARXBZNvmXaT23S3szJo,593
26
26
  janito/change/analysis/__main__.py,sha256=M6JmJnZfOKB0OB29EpzzfbNZu7cusKT92KQhmnaWd5c,196
27
- janito/change/analysis/analyze.py,sha256=eAmqn492W_M9TwizMMlRETq3S9XiDSdXL9alKURgtBw,1655
27
+ janito/change/analysis/analyze.py,sha256=CRpfRn_3KQHNdTZ1wQtsSafzmJzPblNggEf-ZkiTEzw,1760
28
28
  janito/change/analysis/formatting.py,sha256=VqDL6fBzvVm5pdDN4fX9nQQP1wZwhlxDKyaMlDj9ju4,2602
29
29
  janito/change/analysis/options.py,sha256=JNyXCFjOxS1Qm1oqqn8JSXrF4KQ9MotclfKMLD7dZFc,2957
30
- janito/change/analysis/prompts.py,sha256=672fztoXENLMms2_wdjaMSczIOzJe9J7tMInDQQh7Bo,3303
30
+ janito/change/analysis/prompts.py,sha256=UmuJzrdxpEpL3EcgrsJO4OwKWDWMlFucd162Oje-7F4,2962
31
31
  janito/change/analysis/view/__init__.py,sha256=oQd_ClbL7sWmb8jbie74qRrn09CIUTxLH18b02PJFLk,204
32
- janito/change/analysis/view/terminal.py,sha256=7_pjYehUgzo7kOY15AgNyf1JClEy85YtgCr54VxJiOg,6105
32
+ janito/change/analysis/view/terminal.py,sha256=IxsIZG7IJQwfJ1dtZDCga7E7Qq3u5EI5lPszbvi82u4,6598
33
33
  janito/change/applier/__init__.py,sha256=KdViLadNAWcSUbJcsfAt66cDJpaqYGIHdzSDKZjzsEw,183
34
34
  janito/change/applier/file.py,sha256=NQnoywcVXAxLU0xipsByajs2SCRtsSqFPO8tlJl1J2w,2420
35
35
  janito/change/applier/main.py,sha256=Ua-0tmOHYImSlYzmRPppz9stg50bGM1AFFUdQEFMxhY,6644
36
- janito/change/applier/text.py,sha256=l4vmFh1UVnzvm0W09w_m3HrbfYHIIgcNrqUw7Xld2SI,10868
36
+ janito/change/applier/text.py,sha256=cORCCLZdph31tJ2Jr5bueRTawrBr-m2csaGYmJexD2I,11031
37
37
  janito/change/applier/workspace_dir.py,sha256=whiuIIYyDHh2m-K_ZRMZGvMMQ1nh6lzXaWGhnFK1B1o,2443
38
38
  janito/change/viewer/__init__.py,sha256=tj-rIVbuAm80B7-no-YgdxbtkDlwRK_0hqUfIDtDOAc,250
39
- janito/change/viewer/content.py,sha256=SwYkLtsQXI0SCuHKD033XzxwnGQ_MmYckoDpnvJzA0s,2010
39
+ janito/change/viewer/content.py,sha256=iHRjhbpTJMi9v0W91XLogDfbVQEwLg04hlfYJOochzo,2036
40
40
  janito/change/viewer/diff.py,sha256=OzaocnrnH4RCdzZPjT05pEmFJLcd_EgpKhRiAXJrvpc,1815
41
- janito/change/viewer/pager.py,sha256=oJFk1ulswrTs7Az09hHSS37SxyN2cvSVFZ_OxA2Z7os,1738
42
- janito/change/viewer/panels.py,sha256=1T9gZTmNud_LI2QmtYLL2xYUNeb0CpzL8xJRusmrX5U,22421
43
- janito/change/viewer/styling.py,sha256=vpOT0noD4Br-veZ8SuNihg_4RB55TZen-h3L7lX4IhM,3715
41
+ janito/change/viewer/panels.py,sha256=9i-b_vhpDK8cnh1qJ78xtg7cHxvOIMpvotdgK5oHNtU,21612
42
+ janito/change/viewer/styling.py,sha256=6i3xdnj4s5YkSH58oMgfgwZ3nD8T1tI-4Zy7HvcuoMg,4204
44
43
  janito/change/viewer/themes.py,sha256=HISrK7-qR0m4dGZqFmC5loW2E1RSwAicP0mnpZvbSv0,1470
45
44
  janito/clear_statement_parser/clear_statement_format.txt,sha256=_5iQylnCqgBaMVFVgx33QvEColV16oOwl1W4scu_-zc,13497
46
45
  janito/clear_statement_parser/examples.txt,sha256=NnxDraTpCPZCjJjL2HvCMtA1NxBY7C0l3b5v61Y-5iY,8547
@@ -48,34 +47,33 @@ janito/clear_statement_parser/models.py,sha256=b7-lLHfQLI4q5dtaF4BVCwE9DI2xWwVQA
48
47
  janito/clear_statement_parser/parser.py,sha256=KO7Bj0pEl7iPH3FQ3knTGSLMGqKS_pXe3_eqfEHBtXw,20847
49
48
  janito/cli/__init__.py,sha256=3gyMSaEAH2N4mXfZTLsHXKxXDxdhlYUeAPYQuhnOVBE,77
50
49
  janito/cli/base.py,sha256=WKFSxX5FKk5Se5QUZ0X3_fAQVIWG6OEGKAXKebWiRaM,1188
51
- janito/cli/commands.py,sha256=RP9VZYfW7vLK6xitLvp0kBQFdyEWfxHOCh91FaakRwI,1491
50
+ janito/cli/commands.py,sha256=SlS39cSKEbM1oRup96ys9SlR59JxidJp6rnR-JeRk80,2823
52
51
  janito/cli/functions.py,sha256=7DSFQaxKJ7JvkA8-wPuifogGk9NvqTUqC24nU2UUbVM,4143
53
52
  janito/cli/history.py,sha256=UIP_6UiGnJXmBke5hYqKXQVsOPrtKeyfBXW8vDxIoHQ,2114
54
53
  janito/cli/registry.py,sha256=R1sI45YonxjMSLhAle7Dt18X_devrMsLt0ljb-rNza4,690
55
- janito/cli/handlers/ask.py,sha256=jmD-XoP1-ldKlfNNu1WCja9NM7zJgPB3eOaglKOa7dE,829
56
- janito/cli/handlers/demo.py,sha256=TCjN2nVUTivUDvlRxJDhx-rZnfQDR0H_6Yuteq-zkQ0,725
57
- janito/cli/handlers/request.py,sha256=ytmmTSFzHoDPmOm-fWUEa6lkZRwL7e1VjcfJntoyvW8,1083
58
- janito/cli/handlers/scan.py,sha256=zg4AVsFTYkNtUrLA5uCi1Gr6gxDD8PbnFP0eozPtRVw,296
59
54
  janito/demo/__init__.py,sha256=vIGC6fs44yzuSK3-RgYnnanBtZwnW52ivdVbA8Yc8Lk,108
60
55
  janito/demo/data.py,sha256=t208Kixcc3J6xbn43P2OSpqkpcRrrFoEXZ44oOQMcCE,415
61
56
  janito/demo/mock_data.py,sha256=mBg-qF8GcRx7M40IGXGytQJOWihEUm51CJqcez1BKIk,695
62
57
  janito/demo/operations.py,sha256=6QXFsrMVJqX30Y19nBD8fxTj5I6MJN4duQ2qwVG_lHY,1392
63
58
  janito/demo/runner.py,sha256=Xv6v8QVlIkEnlSaNU-Jt6Yjl_NbNg_g8DMZnp8kiFGQ,2385
64
59
  janito/demo/scenarios.py,sha256=xKW6cAL3tSHWP76fvbKHf2HyruhamAzHY1VaTVCkM8o,1060
65
- janito/search_replace/README.md,sha256=Hat8Auac9dQY21Q1y3YVy97pqTwhBCaLTDZ64cI5hrg,3402
66
- janito/search_replace/__init__.py,sha256=apCtIPg44VVzGOKxCievdYAma6nfDGMl1ky-ZBQqjUc,257
60
+ janito/search_replace/README.md,sha256=ctN4ubykUdUMaqHtM9TGM31pCrdyCKiwfHn03b0cwBw,4614
61
+ janito/search_replace/__init__.py,sha256=7Er1wQRTqJ9fE7qFgzwnnhGHiEPWHel3KslOSWWDW5Q,319
67
62
  janito/search_replace/__main__.py,sha256=i0Wz387fqgiHq46QXCXpU9wnwdJYinjyY6HyoJJr_xw,520
68
- janito/search_replace/core.py,sha256=6xy1K9aq3-rddXS2ae158cAXP_B2-QWRbrSalTkjscw,5811
63
+ janito/search_replace/core.py,sha256=wxx-f0SCMmNfxymfobUlhQizcFyS1rD6RnMx0YekEQs,5904
64
+ janito/search_replace/logger.py,sha256=eJR1FA-KiGfZTo416NmGCdlpp3Cgaq7jj-CDFsAGqSU,1052
69
65
  janito/search_replace/parser.py,sha256=wFr5Dc7Im6oh4AcVUkpwKIc0Gf5oNBCYKT2lhexmyQg,2123
70
66
  janito/search_replace/play.py,sha256=vmEqbna8CAEYk4B6Og0eETCRAYRmrBSnFTdiXopsH3M,1820
71
67
  janito/search_replace/replacer.py,sha256=7MKO9PpbAMUqmnxDk1mqkZ_yWE13QwjDfvjT0uU4ypA,1556
72
- janito/search_replace/searcher.py,sha256=M9vzcWlfQV7ZoKQ83tLQWUtW1KPP4MOlBIEBISEh_jU,13004
73
- janito/shell/__init__.py,sha256=Rb6AKmUZpjsYT9bO5spU3_SdPoOoNInPKCl-Ei_qHUc,1272
68
+ janito/search_replace/searcher.py,sha256=F23WQ14myJ4pCIpDgS0wCFM4poimrlXBz7_XF3lmTZg,17228
69
+ janito/search_replace/strategy_result.py,sha256=-XaT7blkoADV7VjFJZWTm2VztADojHmYn1dAvUBIVyw,293
70
+ janito/shell/__init__.py,sha256=TFZi_TSEefpGXQwYcavsgJ0mX8d--wzNk-7qLgqmnOI,1158
74
71
  janito/shell/bus.py,sha256=xRl2-zlJsa0KPL2aSVtVJy9xH6GLw_7tEplvMIY5eCk,1041
75
- janito/shell/commands.py,sha256=b0J0lh2Q8HMcIldNThOnqIFAVUGAKwURThHBlP-K5tc,6797
76
- janito/shell/handlers.py,sha256=aiS1ASNyhZNEuzUCkhqeH1_eIpBX6R3yKjYiBmG8jQI,3978
72
+ janito/shell/commands.py,sha256=pjiJhf7jZB0TORDEewyFEKjjKiSus2VRLZdvs3BiQpg,4997
77
73
  janito/shell/history.py,sha256=EMSbdW9ccHQ__WA-WM5VHjnu_ihTk-4sCpQXmi7e8iI,706
78
- janito/shell/processor.py,sha256=ueT-x4bGM7XiblweaGD5KnnQEPc5kU9cHw8LWwHpZaI,1988
74
+ janito/shell/processor.py,sha256=GvINV9eR2JLG9lZ0ZbVIfGz6E6575iMhtst4oN5qwKw,1102
75
+ janito/shell/prompt.py,sha256=zyHXbuugu8kyVtqbg3SvIWwpCQpv1qHtEBE2jbhNY8I,1744
76
+ janito/shell/registry.py,sha256=5nDeTQ8rl5ZAEaR6RefZOuf9k5wB0T20QIJV1hTciI4,2339
79
77
  janito/tui/__init__.py,sha256=5u1TfGO99LmCtC8ilpXahkXWVJSWtBACqU_O8VtJewI,773
80
78
  janito/tui/base.py,sha256=qU_8i0aQ3sWIkgnKQDUGr3bhypDzSdqYCkNGFfRbIos,692
81
79
  janito/tui/flows/__init__.py,sha256=uI8MtTdIe2BWqbqcfJNnBdhxZcwc207wVjIWusGuDq4,161
@@ -84,12 +82,15 @@ janito/tui/flows/content.py,sha256=mAi4R0ncpC_PzjETqqH9kvy2n1xRKWLhNX5xqPgQjoM,4
84
82
  janito/tui/flows/selection.py,sha256=PcrcY8hTl3ljZOmLYA_I3r3CVRdqKfqFlRxZSgS9rDo,4031
85
83
  janito/tui/screens/__init__.py,sha256=YZ8NVoXMs7c_aT1NuIBiZrkLfXCzaQ85yMKZ_Uh6wlE,69
86
84
  janito/tui/screens/app.py,sha256=XEiADppmDOYkjR1p7sH6N7Zqqm7RWvXSd5_udlAdvbA,92
87
- janito/workspace/__init__.py,sha256=vNDbXn36jSTp2OuMwLjil8eQJwXgorlBqHapOTPwnRg,260
88
- janito/workspace/analysis.py,sha256=Ag4mbOZPyRtm2BvbP7b9c5ZuGLs0vUBWFjormKf-jRc,4088
89
- janito/workspace/manager.py,sha256=GN3mGBO9-758vBsg9QBuEPu5N2QDkK4vZxD1dAGeBgg,1658
90
- janito/workspace/scan.py,sha256=BCYoTjEErbH9nULwFDPCqSGOvR13H01l08ZgNq7jJiY,8804
91
- janito-0.6.0.dist-info/METADATA,sha256=XH8_sffSXi-YqQxVeYgNoT1Yy8HtFIK26KM7AoxAiUE,4574
92
- janito-0.6.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
93
- janito-0.6.0.dist-info/entry_points.txt,sha256=wIo5zZxbmu4fC-ZMrsKD0T0vq7IqkOOLYhrqRGypkx4,48
94
- janito-0.6.0.dist-info/licenses/LICENSE,sha256=xLIUXRPjtsgQml2zD1Pn4LpgiyZ49raw6jZDlO_gZdo,1062
95
- janito-0.6.0.dist-info/RECORD,,
85
+ janito/workspace/__init__.py,sha256=BV-O8czw125wprurtIOm-DNA01ZpSojNTYGBWZx14Cw,111
86
+ janito/workspace/analysis.py,sha256=pJ6fe7P8Ex1WXlZfhjr_73ZJpPfkjxt9BMoH6aSMLh8,4084
87
+ janito/workspace/show.py,sha256=nyHBM4xTYQL61axXemq0b4O6sHtS00EQQSoeT2PdCnc,4932
88
+ janito/workspace/stats.py,sha256=KcLouvJ3xqDIf1qTZaZeAaojeuixkBNcooob2twqFPg,1325
89
+ janito/workspace/types.py,sha256=qPZj8DCC38ygFB9am2j4sXsw-cmtMMG60aAOjoVPxr0,3450
90
+ janito/workspace/workset.py,sha256=my9HBWdGz09zHGR1BmwYiPxr-rNHH-pDEs_YVNVHd64,3903
91
+ janito/workspace/workspace.py,sha256=dDx78YQjTCHoiTu7gP4n2TdFnNbmFBOC-n07ka7YKEQ,4509
92
+ janito-0.7.0.dist-info/METADATA,sha256=7KpfpqDHPRgcU2dgvHoqX6JzQyhl_1Fnih_6zpmL6gE,3990
93
+ janito-0.7.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
94
+ janito-0.7.0.dist-info/entry_points.txt,sha256=wIo5zZxbmu4fC-ZMrsKD0T0vq7IqkOOLYhrqRGypkx4,48
95
+ janito-0.7.0.dist-info/licenses/LICENSE,sha256=xLIUXRPjtsgQml2zD1Pn4LpgiyZ49raw6jZDlO_gZdo,1062
96
+ janito-0.7.0.dist-info/RECORD,,
@@ -1,56 +0,0 @@
1
- from rich.console import Console
2
- import shutil
3
- from typing import Optional
4
-
5
- def wait_for_enter(console: Console):
6
- """Wait for ENTER key press to continue with progress indicator"""
7
- console.print("\n[yellow]More content to show[/yellow]")
8
- console.print("[dim]Press ENTER to continue...[/dim]", end="")
9
- try:
10
- input()
11
- console.print() # Just add a newline
12
- except KeyboardInterrupt:
13
- console.print() # Just add a newline
14
- raise KeyboardInterrupt
15
-
16
- # Track current file being displayed
17
- _current_file = None
18
-
19
- def set_current_file(filename: str) -> None:
20
- """Set the current file being displayed"""
21
- global _current_file
22
- _current_file = filename
23
-
24
- def get_current_file() -> Optional[str]:
25
- """Get the current file being displayed"""
26
- return _current_file
27
-
28
- def check_pager(console: Console, height: int, content_height: Optional[int] = None) -> int:
29
- """Check if we need to pause and wait for user input
30
-
31
- Args:
32
- console: Rich console instance
33
- height: Current accumulated height
34
- content_height: Optional height of content to be displayed next
35
-
36
- Returns:
37
- New accumulated height
38
- """
39
- # Get current file being displayed
40
- current_file = get_current_file()
41
- if not current_file:
42
- return height
43
-
44
- term_height = shutil.get_terminal_size().lines
45
- margin = 5 # Add margin to prevent too early paging
46
- available_height = term_height - margin
47
-
48
- # Calculate total height including upcoming content
49
- total_height = height + (content_height or 0)
50
-
51
- # Only page if we're at a file boundary or content won't fit
52
- if total_height > available_height:
53
- wait_for_enter(console)
54
- return 0
55
-
56
- return height
@@ -1,22 +0,0 @@
1
- from pathlib import Path
2
- from typing import Optional
3
- from rich.console import Console
4
- from janito.config import config
5
- from janito.qa import ask_question, display_answer
6
- from janito.workspace.scan import collect_files_content
7
- from ..base import BaseCLIHandler
8
-
9
- class AskHandler(BaseCLIHandler):
10
- def handle(self, question: str):
11
- """Process a question about the codebase"""
12
- paths_to_scan = [config.workspace_dir] if not config.include else config.include
13
- files_content = collect_files_content(paths_to_scan)
14
-
15
- if config.tui:
16
- answer = ask_question(question, files_content)
17
- from janito.tui import TuiApp
18
- app = TuiApp(content=answer)
19
- app.run()
20
- else:
21
- answer = ask_question(question, files_content)
22
- display_answer(answer)
@@ -1,22 +0,0 @@
1
- from rich.console import Console
2
- from janito.demo import DemoRunner
3
- from janito.demo.data import get_demo_scenarios
4
- from ..base import BaseCLIHandler
5
-
6
- class DemoHandler(BaseCLIHandler):
7
- def handle(self):
8
- """Run demo scenarios"""
9
- runner = DemoRunner()
10
-
11
- # Add predefined scenarios
12
- for scenario in get_demo_scenarios():
13
- runner.add_scenario(scenario)
14
-
15
- # Preview and run scenarios
16
- self.console.print("\n[bold cyan]Demo Scenarios Preview:[/bold cyan]")
17
- runner.preview_changes()
18
-
19
- self.console.print("\n[bold cyan]Running Demo Scenarios:[/bold cyan]")
20
- runner.run_all()
21
-
22
- self.console.print("\n[green]Demo completed successfully![/green]")
@@ -1,24 +0,0 @@
1
- from pathlib import Path
2
- from rich.console import Console
3
- from janito.config import config
4
- from janito.workspace import is_dir_empty
5
- from janito.change.core import process_change_request
6
- from ..base import BaseCLIHandler
7
-
8
- class RequestHandler(BaseCLIHandler):
9
- def handle(self, request: str, preview_only: bool = False):
10
- """Process a modification request"""
11
- is_empty = is_dir_empty(config.workspace_dir)
12
- if is_empty and not config.include:
13
- self.console.print("\n[bold blue]Empty directory - will create new files as needed[/bold blue]")
14
-
15
- success, history_file = process_change_request(request, preview_only)
16
-
17
- if success and history_file and config.verbose:
18
- try:
19
- rel_path = history_file.relative_to(config.workspace_dir)
20
- self.console.print(f"\nChanges saved to: ./{rel_path}")
21
- except ValueError:
22
- self.console.print(f"\nChanges saved to: {history_file}")
23
- elif not success:
24
- self.console.print("[red]Failed to process change request[/red]")
@@ -1,9 +0,0 @@
1
- from pathlib import Path
2
- from typing import List
3
- from janito.workspace import preview_scan
4
- from ..base import BaseCLIHandler
5
-
6
- class ScanHandler(BaseCLIHandler):
7
- def handle(self, paths_to_scan: List[Path]):
8
- """Preview files that would be analyzed"""
9
- preview_scan(paths_to_scan)
janito/prompts.py DELETED
@@ -1,2 +0,0 @@
1
- # Core system prompt focused on role and purpose
2
- SYSTEM_PROMPT = """I am Janito, your friendly software development buddy. I help you with coding tasks while being clear and concise in my responses."""
janito/shell/handlers.py DELETED
@@ -1,122 +0,0 @@
1
- """Command handlers for Janito shell."""
2
- from pathlib import Path
3
- from rich.console import Console
4
- from rich.table import Table
5
- from prompt_toolkit import PromptSession
6
- from prompt_toolkit.completion import PathCompleter
7
- from prompt_toolkit.shortcuts import clear as ptk_clear
8
- from janito.config import config
9
- from janito.scan import collect_files_content
10
- from janito.scan.analysis import analyze_workspace_content
11
- from .registry import CommandRegistry, get_path_completer
12
-
13
- def handle_request(args: str) -> None:
14
- """Handle a change request."""
15
- if not args:
16
- Console().print("[red]Error: Change request required[/red]")
17
- return
18
- from janito.cli.commands import handle_request as cli_handle_request
19
- cli_handle_request(args)
20
-
21
- def handle_exit(_: str) -> None:
22
- """Handle exit command."""
23
- raise EOFError()
24
-
25
- def handle_clear(_: str) -> None:
26
- """Handle clear command to clear terminal screen."""
27
- ptk_clear()
28
-
29
- def handle_ask(args: str) -> None:
30
- """Handle ask command."""
31
- if not args:
32
- Console().print("[red]Error: Question required[/red]")
33
- return
34
- from janito.cli.commands import handle_ask as cli_handle_ask
35
- cli_handle_ask(args)
36
-
37
- def handle_help(args: str) -> None:
38
- """Handle help command."""
39
- console = Console()
40
- registry = CommandRegistry()
41
-
42
- command = args.strip() if args else None
43
- if command and (cmd := registry.get_command(command)):
44
- console.print(f"\n[bold]{command}[/bold]: {cmd.description}")
45
- if cmd.usage:
46
- console.print(f"Usage: {cmd.usage}")
47
- return
48
-
49
- table = Table(title="Available Commands")
50
- table.add_column("Command", style="cyan")
51
- table.add_column("Description")
52
-
53
- for name, cmd in sorted(registry.get_commands().items()):
54
- table.add_row(name, cmd.description)
55
-
56
- console.print(table)
57
-
58
- def handle_include(args: str) -> None:
59
- """Handle include command with path completion."""
60
- console = Console()
61
- session = PromptSession()
62
- completer = PathCompleter()
63
-
64
- # If no args provided, prompt with completion
65
- if not args:
66
- try:
67
- args = session.prompt("Enter paths (space separated): ", completer=completer)
68
- except (KeyboardInterrupt, EOFError):
69
- return
70
-
71
- paths = [p.strip() for p in args.split() if p.strip()]
72
- if not paths:
73
- console.print("[red]Error: At least one path required[/red]")
74
- return
75
-
76
- resolved_paths = []
77
- for path_str in paths:
78
- path = Path(path_str)
79
- if not path.is_absolute():
80
- path = config.workdir / path
81
- resolved_paths.append(path.resolve())
82
-
83
- config.set_include(resolved_paths)
84
- content = collect_files_content(resolved_paths)
85
- analyze_workspace_content(content)
86
-
87
- console.print(f"[green]Updated include paths:[/green]")
88
- for path in resolved_paths:
89
- console.print(f" {path}")
90
-
91
- def handle_rinclude(args: str) -> None:
92
- """Handle rinclude command with recursive path scanning."""
93
- console = Console()
94
- session = PromptSession()
95
- completer = get_path_completer(only_directories=True)
96
-
97
- if not args:
98
- try:
99
- args = session.prompt("Enter directory paths (space separated): ", completer=completer)
100
- except (KeyboardInterrupt, EOFError):
101
- return
102
-
103
- paths = [p.strip() for p in args.split() if p.strip()]
104
- if not paths:
105
- console.print("[red]Error: At least one path required[/red]")
106
- return
107
-
108
- resolved_paths = []
109
- for path_str in paths:
110
- path = Path(path_str)
111
- if not path.is_absolute():
112
- path = config.workdir / path
113
- resolved_paths.append(path.resolve())
114
-
115
- config.set_recursive(resolved_paths)
116
- config.set_include(resolved_paths)
117
- content = collect_files_content(resolved_paths)
118
- analyze_workspace_content(content)
119
-
120
- console.print(f"[green]Updated recursive include paths:[/green]")
121
- for path in resolved_paths:
122
- console.print(f" {path}")
@@ -1,48 +0,0 @@
1
- from pathlib import Path
2
- from typing import Dict, List, Optional, Set
3
- from collections import defaultdict
4
-
5
- class WorkspaceManager:
6
- """Manages workspace state and operations using singleton pattern."""
7
- _instance = None
8
-
9
- def __init__(self):
10
- if WorkspaceManager._instance is not None:
11
- raise RuntimeError("Use WorkspaceManager.get_instance() instead")
12
- self.content: str = ""
13
- self.scan_completed: bool = False
14
- self._analyzed: bool = False
15
-
16
- @classmethod
17
- def get_instance(cls) -> "WorkspaceManager":
18
- """Get singleton instance of WorkspaceManager."""
19
- if cls._instance is None:
20
- cls._instance = cls()
21
- return cls._instance
22
-
23
- def collect_content(self, paths: List[Path]) -> None:
24
- """Collect and store content from specified paths."""
25
- from .scan import _scan_paths
26
- content_parts, _, _, _ = _scan_paths(paths)
27
- self.content = "\n".join(content_parts)
28
- self.scan_completed = True
29
- self._analyzed = False
30
-
31
- def analyze(self) -> None:
32
- """Analyze workspace content and update statistics."""
33
- from .analysis import analyze_workspace_content
34
- if not self.scan_completed:
35
- return
36
- if not self._analyzed and self.content:
37
- analyze_workspace_content(self.content)
38
- self._analyzed = True
39
-
40
- def get_content(self) -> str:
41
- """Get collected workspace content."""
42
- return self.content
43
-
44
- def clear(self) -> None:
45
- """Clear workspace content and stats."""
46
- self.content = ""
47
- self.scan_completed = False
48
- self._analyzed = False