remote-coder 0.4.1__tar.gz → 0.4.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 (123) hide show
  1. remote_coder-0.4.2/PKG-INFO +520 -0
  2. remote_coder-0.4.2/README.md +298 -0
  3. {remote_coder-0.4.1 → remote_coder-0.4.2}/app/__init__.py +1 -1
  4. {remote_coder-0.4.1 → remote_coder-0.4.2}/app/admin/router.py +12 -0
  5. {remote_coder-0.4.1 → remote_coder-0.4.2}/app/admin/static/i18n.js +20 -0
  6. {remote_coder-0.4.1 → remote_coder-0.4.2}/app/admin/templates/admin.html +126 -0
  7. remote_coder-0.4.2/app/cli.py +133 -0
  8. {remote_coder-0.4.1 → remote_coder-0.4.2}/app/config.py +1 -1
  9. remote_coder-0.4.2/app/diagnostics.py +37 -0
  10. {remote_coder-0.4.1 → remote_coder-0.4.2}/pyproject.toml +11 -11
  11. remote_coder-0.4.2/remote_coder.egg-info/PKG-INFO +520 -0
  12. {remote_coder-0.4.1 → remote_coder-0.4.2}/remote_coder.egg-info/SOURCES.txt +2 -0
  13. remote_coder-0.4.2/remote_coder.egg-info/requires.txt +12 -0
  14. {remote_coder-0.4.1 → remote_coder-0.4.2}/tests/test_admin_router.py +34 -0
  15. {remote_coder-0.4.1 → remote_coder-0.4.2}/tests/test_cli.py +3 -36
  16. remote_coder-0.4.2/tests/test_diagnostics.py +32 -0
  17. remote_coder-0.4.1/PKG-INFO +0 -520
  18. remote_coder-0.4.1/README.md +0 -298
  19. remote_coder-0.4.1/app/cli.py +0 -238
  20. remote_coder-0.4.1/remote_coder.egg-info/PKG-INFO +0 -520
  21. remote_coder-0.4.1/remote_coder.egg-info/requires.txt +0 -12
  22. {remote_coder-0.4.1 → remote_coder-0.4.2}/LICENSE +0 -0
  23. {remote_coder-0.4.1 → remote_coder-0.4.2}/app/admin/__init__.py +0 -0
  24. {remote_coder-0.4.1 → remote_coder-0.4.2}/app/admin/advanced_settings.py +0 -0
  25. {remote_coder-0.4.1 → remote_coder-0.4.2}/app/admin/database_browser.py +0 -0
  26. {remote_coder-0.4.1 → remote_coder-0.4.2}/app/admin/static/icons/advanced.svg +0 -0
  27. {remote_coder-0.4.1 → remote_coder-0.4.2}/app/admin/static/icons/database.svg +0 -0
  28. {remote_coder-0.4.1 → remote_coder-0.4.2}/app/admin/static/icons/download.svg +0 -0
  29. {remote_coder-0.4.1 → remote_coder-0.4.2}/app/admin/static/icons/home.svg +0 -0
  30. {remote_coder-0.4.1 → remote_coder-0.4.2}/app/admin/static/icons/logs.svg +0 -0
  31. {remote_coder-0.4.1 → remote_coder-0.4.2}/app/admin/static/icons/projects.svg +0 -0
  32. {remote_coder-0.4.1 → remote_coder-0.4.2}/app/admin/static/summary.js +0 -0
  33. {remote_coder-0.4.1 → remote_coder-0.4.2}/app/admin/templates/advanced.html +0 -0
  34. {remote_coder-0.4.1 → remote_coder-0.4.2}/app/admin/templates/database.html +0 -0
  35. {remote_coder-0.4.1 → remote_coder-0.4.2}/app/admin/templates/logs.html +0 -0
  36. {remote_coder-0.4.1 → remote_coder-0.4.2}/app/admin/templates/projects.html +0 -0
  37. {remote_coder-0.4.1 → remote_coder-0.4.2}/app/ai/__init__.py +0 -0
  38. {remote_coder-0.4.1 → remote_coder-0.4.2}/app/ai/base.py +0 -0
  39. {remote_coder-0.4.1 → remote_coder-0.4.2}/app/ai/claude.py +0 -0
  40. {remote_coder-0.4.1 → remote_coder-0.4.2}/app/ai/codex.py +0 -0
  41. {remote_coder-0.4.1 → remote_coder-0.4.2}/app/ai/factory.py +0 -0
  42. {remote_coder-0.4.1 → remote_coder-0.4.2}/app/ai/gemini.py +0 -0
  43. {remote_coder-0.4.1 → remote_coder-0.4.2}/app/ai/model_catalog.py +0 -0
  44. {remote_coder-0.4.1 → remote_coder-0.4.2}/app/ai/usage.py +0 -0
  45. {remote_coder-0.4.1 → remote_coder-0.4.2}/app/git/__init__.py +0 -0
  46. {remote_coder-0.4.1 → remote_coder-0.4.2}/app/git/ai_commit.py +0 -0
  47. {remote_coder-0.4.1 → remote_coder-0.4.2}/app/git/branch_naming.py +0 -0
  48. {remote_coder-0.4.1 → remote_coder-0.4.2}/app/git/commit_message.py +0 -0
  49. {remote_coder-0.4.1 → remote_coder-0.4.2}/app/git/service.py +0 -0
  50. {remote_coder-0.4.1 → remote_coder-0.4.2}/app/jobs/__init__.py +0 -0
  51. {remote_coder-0.4.1 → remote_coder-0.4.2}/app/jobs/manager.py +0 -0
  52. {remote_coder-0.4.1 → remote_coder-0.4.2}/app/jobs/schemas.py +0 -0
  53. {remote_coder-0.4.1 → remote_coder-0.4.2}/app/jobs/store.py +0 -0
  54. {remote_coder-0.4.1 → remote_coder-0.4.2}/app/main.py +0 -0
  55. {remote_coder-0.4.1 → remote_coder-0.4.2}/app/models.py +0 -0
  56. {remote_coder-0.4.1 → remote_coder-0.4.2}/app/monitoring/__init__.py +0 -0
  57. {remote_coder-0.4.1 → remote_coder-0.4.2}/app/monitoring/code.py +0 -0
  58. {remote_coder-0.4.1 → remote_coder-0.4.2}/app/monitoring/events.py +0 -0
  59. {remote_coder-0.4.1 → remote_coder-0.4.2}/app/monitoring/git.py +0 -0
  60. {remote_coder-0.4.1 → remote_coder-0.4.2}/app/monitoring/log_buffer.py +0 -0
  61. {remote_coder-0.4.1 → remote_coder-0.4.2}/app/monitoring/memory.py +0 -0
  62. {remote_coder-0.4.1 → remote_coder-0.4.2}/app/monitoring/model.py +0 -0
  63. {remote_coder-0.4.1 → remote_coder-0.4.2}/app/projects/__init__.py +0 -0
  64. {remote_coder-0.4.1 → remote_coder-0.4.2}/app/projects/registry.py +0 -0
  65. {remote_coder-0.4.1 → remote_coder-0.4.2}/app/security/__init__.py +0 -0
  66. {remote_coder-0.4.1 → remote_coder-0.4.2}/app/security/auth.py +0 -0
  67. {remote_coder-0.4.1 → remote_coder-0.4.2}/app/system_startup.py +0 -0
  68. {remote_coder-0.4.1 → remote_coder-0.4.2}/app/telegram/__init__.py +0 -0
  69. {remote_coder-0.4.1 → remote_coder-0.4.2}/app/telegram/bot_instances.py +0 -0
  70. {remote_coder-0.4.1 → remote_coder-0.4.2}/app/telegram/commands/__init__.py +0 -0
  71. {remote_coder-0.4.1 → remote_coder-0.4.2}/app/telegram/commands/base.py +0 -0
  72. {remote_coder-0.4.1 → remote_coder-0.4.2}/app/telegram/commands/branch.py +0 -0
  73. {remote_coder-0.4.1 → remote_coder-0.4.2}/app/telegram/commands/clear_stop.py +0 -0
  74. {remote_coder-0.4.1 → remote_coder-0.4.2}/app/telegram/commands/fix.py +0 -0
  75. {remote_coder-0.4.1 → remote_coder-0.4.2}/app/telegram/commands/model.py +0 -0
  76. {remote_coder-0.4.1 → remote_coder-0.4.2}/app/telegram/commands/monitor.py +0 -0
  77. {remote_coder-0.4.1 → remote_coder-0.4.2}/app/telegram/commands/registry.py +0 -0
  78. {remote_coder-0.4.1 → remote_coder-0.4.2}/app/telegram/commands/status.py +0 -0
  79. {remote_coder-0.4.1 → remote_coder-0.4.2}/app/telegram/commands/system.py +0 -0
  80. {remote_coder-0.4.1 → remote_coder-0.4.2}/app/telegram/confirmations.py +0 -0
  81. {remote_coder-0.4.1 → remote_coder-0.4.2}/app/telegram/conversation.py +0 -0
  82. {remote_coder-0.4.1 → remote_coder-0.4.2}/app/telegram/i18n.py +0 -0
  83. {remote_coder-0.4.1 → remote_coder-0.4.2}/app/telegram/model_preferences.py +0 -0
  84. {remote_coder-0.4.1 → remote_coder-0.4.2}/app/telegram/notifier.py +0 -0
  85. {remote_coder-0.4.1 → remote_coder-0.4.2}/app/telegram/parser.py +0 -0
  86. {remote_coder-0.4.1 → remote_coder-0.4.2}/app/telegram/webhook.py +0 -0
  87. {remote_coder-0.4.1 → remote_coder-0.4.2}/app/telegram/webhook_registration.py +0 -0
  88. {remote_coder-0.4.1 → remote_coder-0.4.2}/app/tunnel.py +0 -0
  89. {remote_coder-0.4.1 → remote_coder-0.4.2}/remote_coder.egg-info/dependency_links.txt +0 -0
  90. {remote_coder-0.4.1 → remote_coder-0.4.2}/remote_coder.egg-info/entry_points.txt +0 -0
  91. {remote_coder-0.4.1 → remote_coder-0.4.2}/remote_coder.egg-info/top_level.txt +0 -0
  92. {remote_coder-0.4.1 → remote_coder-0.4.2}/setup.cfg +0 -0
  93. {remote_coder-0.4.1 → remote_coder-0.4.2}/tests/test_ai_base.py +0 -0
  94. {remote_coder-0.4.1 → remote_coder-0.4.2}/tests/test_ai_commit.py +0 -0
  95. {remote_coder-0.4.1 → remote_coder-0.4.2}/tests/test_ai_factory.py +0 -0
  96. {remote_coder-0.4.1 → remote_coder-0.4.2}/tests/test_auth.py +0 -0
  97. {remote_coder-0.4.1 → remote_coder-0.4.2}/tests/test_bot_instance_manager.py +0 -0
  98. {remote_coder-0.4.1 → remote_coder-0.4.2}/tests/test_branch_naming.py +0 -0
  99. {remote_coder-0.4.1 → remote_coder-0.4.2}/tests/test_claude_runner.py +0 -0
  100. {remote_coder-0.4.1 → remote_coder-0.4.2}/tests/test_codex_runner.py +0 -0
  101. {remote_coder-0.4.1 → remote_coder-0.4.2}/tests/test_command_parser.py +0 -0
  102. {remote_coder-0.4.1 → remote_coder-0.4.2}/tests/test_commands.py +0 -0
  103. {remote_coder-0.4.1 → remote_coder-0.4.2}/tests/test_commit_message_formatter.py +0 -0
  104. {remote_coder-0.4.1 → remote_coder-0.4.2}/tests/test_config.py +0 -0
  105. {remote_coder-0.4.1 → remote_coder-0.4.2}/tests/test_conversation_store.py +0 -0
  106. {remote_coder-0.4.1 → remote_coder-0.4.2}/tests/test_database_browser.py +0 -0
  107. {remote_coder-0.4.1 → remote_coder-0.4.2}/tests/test_event_logger.py +0 -0
  108. {remote_coder-0.4.1 → remote_coder-0.4.2}/tests/test_gemini_runner.py +0 -0
  109. {remote_coder-0.4.1 → remote_coder-0.4.2}/tests/test_git_service.py +0 -0
  110. {remote_coder-0.4.1 → remote_coder-0.4.2}/tests/test_i18n.py +0 -0
  111. {remote_coder-0.4.1 → remote_coder-0.4.2}/tests/test_job_manager.py +0 -0
  112. {remote_coder-0.4.1 → remote_coder-0.4.2}/tests/test_job_status.py +0 -0
  113. {remote_coder-0.4.1 → remote_coder-0.4.2}/tests/test_job_store.py +0 -0
  114. {remote_coder-0.4.1 → remote_coder-0.4.2}/tests/test_log_buffer.py +0 -0
  115. {remote_coder-0.4.1 → remote_coder-0.4.2}/tests/test_monitoring.py +0 -0
  116. {remote_coder-0.4.1 → remote_coder-0.4.2}/tests/test_notifier.py +0 -0
  117. {remote_coder-0.4.1 → remote_coder-0.4.2}/tests/test_project_registry.py +0 -0
  118. {remote_coder-0.4.1 → remote_coder-0.4.2}/tests/test_project_scoped_state.py +0 -0
  119. {remote_coder-0.4.1 → remote_coder-0.4.2}/tests/test_system_startup.py +0 -0
  120. {remote_coder-0.4.1 → remote_coder-0.4.2}/tests/test_tunnel.py +0 -0
  121. {remote_coder-0.4.1 → remote_coder-0.4.2}/tests/test_webhook.py +0 -0
  122. {remote_coder-0.4.1 → remote_coder-0.4.2}/tests/test_webhook_multibot.py +0 -0
  123. {remote_coder-0.4.1 → remote_coder-0.4.2}/tests/test_webhook_registration.py +0 -0
@@ -0,0 +1,520 @@
1
+ Metadata-Version: 2.4
2
+ Name: remote-coder
3
+ Version: 0.4.2
4
+ Summary: Telegram-based remote AI coding automation server
5
+ Author: Remote AI Coder contributors
6
+ License: Apache License
7
+ Version 2.0, January 2004
8
+ http://www.apache.org/licenses/
9
+
10
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
11
+
12
+ 1. Definitions.
13
+
14
+ "License" shall mean the terms and conditions for use, reproduction,
15
+ and distribution as defined by Sections 1 through 9 of this document.
16
+
17
+ "Licensor" shall mean the copyright owner or entity authorized by
18
+ the copyright owner that is granting the License.
19
+
20
+ "Legal Entity" shall mean the union of the acting entity and all
21
+ other entities that control, are controlled by, or are under common
22
+ control with that entity. For the purposes of this definition,
23
+ "control" means (i) the power, direct or indirect, to cause the
24
+ direction or management of such entity, whether by contract or
25
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
26
+ outstanding shares, or (iii) beneficial ownership of such entity.
27
+
28
+ "You" (or "Your") shall mean an individual or Legal Entity
29
+ exercising permissions granted by this License.
30
+
31
+ "Source" form shall mean the preferred form for making modifications,
32
+ including but not limited to software source code, documentation
33
+ source, and configuration files.
34
+
35
+ "Object" form shall mean any form resulting from mechanical
36
+ transformation or translation of a Source form, including but
37
+ not limited to compiled object code, generated documentation,
38
+ and conversions to other media types.
39
+
40
+ "Work" shall mean the work of authorship, whether in Source or
41
+ Object form, made available under the License, as indicated by a
42
+ copyright notice that is included in or attached to the work
43
+ (an example is provided in the Appendix below).
44
+
45
+ "Derivative Works" shall mean any work, whether in Source or Object
46
+ form, that is based on (or derived from) the Work and for which the
47
+ editorial revisions, annotations, elaborations, or other modifications
48
+ represent, as a whole, an original work of authorship. For the purposes
49
+ of this License, Derivative Works shall not include works that remain
50
+ separable from, or merely link (or bind by name) to the interfaces of,
51
+ the Work and Derivative Works thereof.
52
+
53
+ "Contribution" shall mean any work of authorship, including
54
+ the original version of the Work and any modifications or additions
55
+ to that Work or Derivative Works thereof, that is intentionally
56
+ submitted to Licensor for inclusion in the Work by the copyright owner
57
+ or by an individual or Legal Entity authorized to submit on behalf of
58
+ the copyright owner. For the purposes of this definition, "submitted"
59
+ means any form of electronic, verbal, or written communication sent
60
+ to the Licensor or its representatives, including but not limited to
61
+ communication on electronic mailing lists, source code control systems,
62
+ and issue tracking systems that are managed by, or on behalf of, the
63
+ Licensor for the purpose of discussing and improving the Work, but
64
+ excluding communication that is conspicuously marked or otherwise
65
+ designated in writing by the copyright owner as "Not a Contribution."
66
+
67
+ "Contributor" shall mean Licensor and any individual or Legal Entity
68
+ on behalf of whom a Contribution has been received by Licensor and
69
+ subsequently incorporated within the Work.
70
+
71
+ 2. Grant of Copyright License. Subject to the terms and conditions of
72
+ this License, each Contributor hereby grants to You a perpetual,
73
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
74
+ copyright license to reproduce, prepare Derivative Works of,
75
+ publicly display, publicly perform, sublicense, and distribute the
76
+ Work and such Derivative Works in Source or Object form.
77
+
78
+ 3. Grant of Patent License. Subject to the terms and conditions of
79
+ this License, each Contributor hereby grants to You a perpetual,
80
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
81
+ (except as stated in this section) patent license to make, have made,
82
+ use, offer to sell, sell, import, and otherwise transfer the Work,
83
+ where such license applies only to those patent claims licensable
84
+ by such Contributor that are necessarily infringed by their
85
+ Contribution(s) alone or by combination of their Contribution(s)
86
+ with the Work to which such Contribution(s) was submitted. If You
87
+ institute patent litigation against any entity (including a
88
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
89
+ or a Contribution incorporated within the Work constitutes direct
90
+ or contributory patent infringement, then any patent licenses
91
+ granted to You under this License for that Work shall terminate
92
+ as of the date such litigation is filed.
93
+
94
+ 4. Redistribution. You may reproduce and distribute copies of the
95
+ Work or Derivative Works thereof in any medium, with or without
96
+ modifications, and in Source or Object form, provided that You
97
+ meet the following conditions:
98
+
99
+ (a) You must give any other recipients of the Work or
100
+ Derivative Works a copy of this License; and
101
+
102
+ (b) You must cause any modified files to carry prominent notices
103
+ stating that You changed the files; and
104
+
105
+ (c) You must retain, in the Source form of any Derivative Works
106
+ that You distribute, all copyright, patent, trademark, and
107
+ attribution notices from the Source form of the Work,
108
+ excluding those notices that do not pertain to any part of
109
+ the Derivative Works; and
110
+
111
+ (d) If the Work includes a "NOTICE" text file as part of its
112
+ distribution, then any Derivative Works that You distribute must
113
+ include a readable copy of the attribution notices contained
114
+ within such NOTICE file, excluding those notices that do not
115
+ pertain to any part of the Derivative Works, in at least one
116
+ of the following places: within a NOTICE text file distributed
117
+ as part of the Derivative Works; within the Source form or
118
+ documentation, if provided along with the Derivative Works; or,
119
+ within a display generated by the Derivative Works, if and
120
+ wherever such third-party notices normally appear. The contents
121
+ of the NOTICE file are for informational purposes only and
122
+ do not modify the License. You may add Your own attribution
123
+ notices within Derivative Works that You distribute, alongside
124
+ or as an addendum to the NOTICE text from the Work, provided
125
+ that such additional attribution notices cannot be construed
126
+ as modifying the License.
127
+
128
+ You may add Your own copyright statement to Your modifications and
129
+ may provide additional or different license terms and conditions
130
+ for use, reproduction, or distribution of Your modifications, or
131
+ for any such Derivative Works as a whole, provided Your use,
132
+ reproduction, and distribution of the Work otherwise complies with
133
+ the conditions stated in this License.
134
+
135
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
136
+ any Contribution intentionally submitted for inclusion in the Work
137
+ by You to the Licensor shall be under the terms and conditions of
138
+ this License, without any additional terms or conditions.
139
+ Notwithstanding the above, nothing herein shall supersede or modify
140
+ the terms of any separate license agreement you may have executed
141
+ with Licensor regarding such Contributions.
142
+
143
+ 6. Trademarks. This License does not grant permission to use the trade
144
+ names, trademarks, service marks, or product names of the Licensor,
145
+ except as required for reasonable and customary use in describing the
146
+ origin of the Work and reproducing the content of the NOTICE file.
147
+
148
+ 7. Disclaimer of Warranty. Unless required by applicable law or
149
+ agreed to in writing, Licensor provides the Work (and each
150
+ Contributor provides its Contributions) on an "AS IS" BASIS,
151
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
152
+ implied, including, without limitation, any warranties or conditions
153
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
154
+ PARTICULAR PURPOSE. You are solely responsible for determining the
155
+ appropriateness of using or redistributing the Work and assume any
156
+ risks associated with Your exercise of permissions under this License.
157
+
158
+ 8. Limitation of Liability. In no event and under no legal theory,
159
+ whether in tort (including negligence), contract, or otherwise,
160
+ unless required by applicable law (such as deliberate and grossly
161
+ negligent acts) or agreed to in writing, shall any Contributor be
162
+ liable to You for damages, including any direct, indirect, special,
163
+ incidental, or consequential damages of any character arising as a
164
+ result of this License or out of the use or inability to use the
165
+ Work (including but not limited to damages for loss of goodwill,
166
+ work stoppage, computer failure or malfunction, or any and all
167
+ other commercial damages or losses), even if such Contributor
168
+ has been advised of the possibility of such damages.
169
+
170
+ 9. Accepting Warranty or Additional Liability. While redistributing
171
+ the Work or Derivative Works thereof, You may choose to offer,
172
+ and charge a fee for, acceptance of support, warranty, indemnity,
173
+ or other liability obligations and/or rights consistent with this
174
+ License. However, in accepting such obligations, You may act only
175
+ on Your own behalf and on Your sole responsibility, not on behalf
176
+ of any other Contributor, and only if You agree to indemnify,
177
+ defend, and hold each Contributor harmless for any liability
178
+ incurred by, or claims asserted against, such Contributor by reason
179
+ of your accepting any such warranty or additional liability.
180
+
181
+ END OF TERMS AND CONDITIONS
182
+
183
+ APPENDIX: How to apply the Apache License to your work.
184
+
185
+ To apply the Apache License to your work, attach the following
186
+ boilerplate notice, with the fields enclosed by brackets "[]"
187
+ replaced with your own identifying information. (Don't include
188
+ the brackets!) The text should be enclosed in the appropriate
189
+ comment syntax for the file format. We also recommend that a
190
+ file or class name and description of purpose be included on the
191
+ same "printed page" as the copyright notice for easier
192
+ identification within third-party archives.
193
+
194
+ Copyright 2026 maroomir
195
+
196
+ Licensed under the Apache License, Version 2.0 (the "License");
197
+ you may not use this file except in compliance with the License.
198
+ You may obtain a copy of the License at
199
+
200
+ http://www.apache.org/licenses/LICENSE-2.0
201
+
202
+ Unless required by applicable law or agreed to in writing, software
203
+ distributed under the License is distributed on an "AS IS" BASIS,
204
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
205
+ See the License for the specific language governing permissions and
206
+ limitations under the License.
207
+ Requires-Python: >=3.11
208
+ Description-Content-Type: text/markdown
209
+ License-File: LICENSE
210
+ Requires-Dist: fastapi<1.0,>=0.115
211
+ Requires-Dist: httpx<1.0,>=0.27
212
+ Requires-Dist: pydantic<3.0,>=2.7
213
+ Requires-Dist: pydantic-settings<3.0,>=2.3
214
+ Requires-Dist: python-dotenv<2.0,>=1.0
215
+ Requires-Dist: pyyaml<7.0,>=6.0
216
+ Requires-Dist: uvicorn[standard]<1.0,>=0.30
217
+ Provides-Extra: dev
218
+ Requires-Dist: pytest<10.0,>=8.0; extra == "dev"
219
+ Requires-Dist: pytest-asyncio<2.0,>=0.23; extra == "dev"
220
+ Requires-Dist: respx<1.0,>=0.21; extra == "dev"
221
+ Dynamic: license-file
222
+
223
+ # Remote AI Coder
224
+
225
+ An MVP that runs AI coding tasks on your local development machine through Telegram messages and reports Git branch/commit results back as notifications.
226
+
227
+ > [!WARNING]
228
+ > This project runs AI CLI and Git operations on your local machine via Telegram messages. Do not expose the server or admin UI directly to the public internet. Always configure the Telegram allowlist (and optionally a webhook secret) and use it only in a private, trusted environment.
229
+
230
+ ## Multi-bot model (summary)
231
+
232
+ - **Each registered project gets its own Telegram bot.** There is no `/project` command to switch the target repository from chat.
233
+ - Each bot has a distinct webhook path: `POST /telegram/webhook/{first 16 hex chars of SHA-256(bot token)}` (the token itself is never placed in the URL).
234
+ - Bot token, allowed Chat/User IDs, and an optional webhook secret are stored in the **project registry** (`projects.json`, etc.). **Tokens are stored in plain text**, so keep strict file permissions and a careful backup policy.
235
+ - See [`docs/multi-bot-setup.md`](docs/multi-bot-setup.md) for the full procedure.
236
+ - When a project is **disabled or deleted**, the server stops routing updates arriving with that token hash prefix. Even if an old URL remains registered on Telegram, this app ignores it. To clear or repoint a bot's webhook, call the Bot API `deleteWebhook` or re-run [`scripts/set_webhook.py`](scripts/set_webhook.py) against the current registry.
237
+
238
+ ## Publishing / security notes
239
+
240
+ - Never commit `TELEGRAM_BOT_TOKEN` (optional seed), the registry `bot_token`, Chat/User IDs, webhook secrets, AI API keys, or personal paths to code or docs.
241
+ - `.env`, `.remote-coder/` (especially `projects.json`), worktrees, logs, and the SQLite conversation-memory file are local-only data. This repository's `.gitignore` excludes them by default.
242
+ - The admin UI (`/`, `/projects`, `/advanced`, `/logs`, `/database`) is designed for localhost only. Do not expose it externally via reverse proxy, ngrok, port forwarding, etc.
243
+ - Options such as Claude `--dangerously-skip-permissions`, Gemini `--approval-mode yolo`, and Codex `danger-full-access` can modify local files. Use them only after restricting the allowed projects and trusted users.
244
+ - The conversation-memory SQLite may store users' Telegram requests and Job summaries. Do not paste sensitive code into messages, and clean up with `/clear memory` or the admin UI advanced settings when needed.
245
+
246
+ See [`SECURITY.md`](SECURITY.md) for vulnerability reporting and pre-publication review steps.
247
+
248
+ ## Prerequisites
249
+
250
+ - Python 3.11+ or Conda
251
+ - A Telegram Bot Token (BotFather) per project, plus allowed Chat IDs (required) and User IDs (optional)
252
+ - An HTTPS tunnel tool (e.g. ngrok for development)
253
+ - At least one of: Claude Code CLI, Codex CLI, Gemini CLI
254
+ - A target Git project and a local directory for worktrees
255
+
256
+ ## Quick start (recommended)
257
+
258
+ Install with a single `pip` command — no separate Conda environment required. This installs the `remote-coder` CLI; check prerequisites (ngrok, AI CLIs) with `remote-coder doctor`.
259
+
260
+ ```bash
261
+ pip install remote-coder
262
+ ```
263
+
264
+ > Before the first PyPI release, install straight from the git source (this is still `pip`):
265
+ >
266
+ > ```bash
267
+ > pip install git+https://github.com/maroomir/remote-coder.git
268
+ > ```
269
+
270
+ After installing, start the server and finish setup in the browser:
271
+
272
+ ```bash
273
+ remote-coder up # ngrok tunnel + Telegram webhook registration + server, all at once (stop: Ctrl+C)
274
+ ```
275
+
276
+ - On the first run (no projects yet), open the local admin UI at **http://127.0.0.1:8000/** and use the **First-time setup** card to add your first project (bot token, allowed Chat IDs, target repo path). The bot goes live as soon as the project is saved.
277
+ - The project registry (`projects.json` under `REMOTE_CODER_HOME`, default `~/.remote-coder`) is the source of truth; the admin UI writes to it. A global `REMOTE_CODER_HOME/.env` is optional and used only to seed the first project.
278
+ - Prerequisites: `ngrok` (after installing, run `ngrok config add-authtoken <token>`) and at least one AI CLI (`claude`/`codex`/`gemini`). Check them with `remote-coder doctor` or in the setup card.
279
+ - To run the server only, without a tunnel: `remote-coder up --no-tunnel`.
280
+
281
+ ### Other installation methods
282
+
283
+ If you prefer isolated installs, use [pipx](https://pipx.pypa.io/) or [uv](https://docs.astral.sh/uv/). (Before the PyPI release, use `git+https://github.com/maroomir/remote-coder.git` instead of the package name.)
284
+
285
+ ```bash
286
+ pipx install remote-coder
287
+ uv tool install remote-coder
288
+ ```
289
+
290
+ There is also an install script that handles prerequisite checks in one go (isolated install via uv):
291
+
292
+ ```bash
293
+ curl -fsSL https://raw.githubusercontent.com/maroomir/remote-coder/main/scripts/install.sh | bash
294
+ ```
295
+
296
+ ### Development install
297
+
298
+ Editable install from a source checkout:
299
+
300
+ ```bash
301
+ python -m pip install -e ".[dev]"
302
+ remote-coder up --no-tunnel --reload
303
+ ```
304
+
305
+ `remote-coder up --no-tunnel` runs the server only, without tunnel/webhook registration — equivalent to `uvicorn app.main:app`.
306
+
307
+ ### Building distribution packages
308
+
309
+ ```bash
310
+ python -m pip install build
311
+ python -m build
312
+ ```
313
+
314
+ Outputs are `dist/remote_coder-<version>.tar.gz` and `dist/remote_coder-<version>-py3-none-any.whl`. Pushing a tag (`vX.Y.Z`) makes GitHub Actions build, publish to PyPI (Trusted Publishing), and create a GitHub Release automatically.
315
+
316
+ ### Homebrew distribution
317
+
318
+ Since this is a CLI/server package, a Formula (`brew install remote-coder`) is a better fit than a macOS app-bundle Cask. A draft Formula is at [`packaging/homebrew/remote-coder.rb`](packaging/homebrew/remote-coder.rb).
319
+
320
+ After a release you still need to:
321
+
322
+ - Replace `homepage` with the actual repository URL
323
+ - Replace `url` with the `remote_coder-<version>.tar.gz` URL from PyPI or the GitHub Release
324
+ - Replace `sha256` with the value from `shasum -a 256 dist/remote_coder-<version>.tar.gz`
325
+ - Generate the Python dependency `resource` blocks with a tool like `brew pypi-poet remote-coder` and add them to the Formula
326
+
327
+ > Sections "1) – 3)" below are for **developers/contributors** who work directly from the repository or handle configuration manually instead of using `remote-coder up` plus the admin UI. Skip them if the quick start is enough.
328
+
329
+ ## 1) Environment setup (Conda, for developers/contributors)
330
+
331
+ ```bash
332
+ conda env create -f environment.yml
333
+ conda activate remote-coder
334
+ ```
335
+
336
+ ## 2) Configuration
337
+
338
+ Copy and edit this `.env` only when configuring manually instead of using the admin UI. The `.env` is optional and seeds the first project when the registry is empty. (When running globally, `REMOTE_CODER_HOME/.env` takes precedence; when developing inside the repo, the current directory's `.env` takes precedence.)
339
+
340
+ ```bash
341
+ cp .env.example .env
342
+ ```
343
+
344
+ Fill in the following values in `.env`:
345
+
346
+ - Optional (initial seed): `TELEGRAM_BOT_TOKEN`, `TELEGRAM_ALLOWED_CHAT_IDS`, `TELEGRAM_ALLOWED_USER_IDS`, `TELEGRAM_WEBHOOK_SECRET` — used only to create the first project when the registry is empty. Production settings prefer the **per-project** fields in the admin UI or `projects.json`.
347
+ - Optional: `GIT_REMOTE_NAME` (default `origin`) — used for push after commit and for `/rebase`, `/pr`, `/clear`
348
+ - Optional: `PROJECTS_CONFIG_PATH` — path to the registry file (JSON or `.yaml`) for multiple Git projects
349
+ - Optional: `CONVERSATION_DB_PATH` — SQLite path for per-project + per-chat conversation memory (defaults to `PROJECT_ROOT/.remote-coder/conversations.sqlite3`)
350
+ - Optional: `CONVERSATION_RECENT_LIMIT` — number of recent records appended to the runner for ambiguous follow-ups (default `10`)
351
+ - Optional: `CODEX_SANDBOX` — the Codex `codex exec --sandbox` value (`read-only`, `workspace-write`, `danger-full-access`). Default `workspace-write` (files can be edited in the Job worktree)
352
+ - Optional: to use Gemini, install the Gemini CLI with `npm install -g @google/gemini-cli` and make sure `gemini` is on your PATH
353
+ - Initial seed (one-time): `DEFAULT_PROJECT`, `PROJECT_ROOT`, `WORKTREE_BASE_DIR`
354
+
355
+ If you were using a single `.env` before → move each project's `bot_token`/allowlist into the admin UI, or clean sensitive values from `.env` after the seed is created. See the migration section in [`docs/multi-bot-setup.md`](docs/multi-bot-setup.md).
356
+
357
+ ## 2.5) Local admin UI (project registration)
358
+
359
+ After starting the server, open it in a browser **on the same machine**.
360
+
361
+ - Admin hub: `http://127.0.0.1:8000/` (summary, navigation to other pages)
362
+ - Project registration: `http://127.0.0.1:8000/projects` (list, add/edit/delete, fallback defaults, **bot token / allowlist / webhook secret**, per-bot webhook path. While `remote-coder up` is running, the Telegram webhook and `/` command menu for active projects you add/edit are refreshed immediately)
363
+ - Advanced settings: `http://127.0.0.1:8000/advanced`
364
+ - Server logs: `http://127.0.0.1:8000/logs` (in-memory ring buffer for the `app` logger; auto-refresh, category and `chat_id`/`job_id` filters)
365
+ - Data browser: `http://127.0.0.1:8000/database` (browse the conversation-memory SQLite tables, export CSV)
366
+ - The natural-language task target is **bound to its bot**. The `project:` token is not supported.
367
+ - If `PROJECTS_CONFIG_PATH` is unset, the default path `PROJECT_ROOT/.remote-coder/projects.json` is used.
368
+ - If the registry file is missing, it is created automatically from the `.env` seed values (`DEFAULT_PROJECT`, `PROJECT_ROOT`, `WORKTREE_BASE_DIR`).
369
+
370
+ ### Server log (event) logger naming convention
371
+
372
+ Entries shown in the admin UI `/logs` and the API `GET /api/logs` are recorded by `app` package loggers. The main logger names and their purposes:
373
+
374
+ | Logger name | Purpose |
375
+ |-------------|---------|
376
+ | `app.telegram.inbound` | Webhook receipt, empty-message skips |
377
+ | `app.telegram.outbound` | `sendMessage` success/failure, Job intake/result notifications |
378
+ | `app.telegram.command` | Slash-command handling, natural-language Job intake, state changes like `/init`/`/clear` confirmations |
379
+ | `app.security.auth` | Webhook secret mismatch, allowlist rejection |
380
+ | `app.jobs.lifecycle` | Job submission, stages (`git_worktree`/`runner`/…), success, failure |
381
+ | `app.git.service` | Git adapter: worktree creation, commit, push, cleanup, rebase integration |
382
+ | `app.ai.claude` / `app.ai.codex` / `app.ai.gemini` | Runner start/end/timeout |
383
+
384
+ Structured fields (`category`, `chat_id`, `user_id`, `project`, `job_id`) can be filtered/badged in the UI. In code, use `app.monitoring.events.EventLogger` and the `app.monitoring.log_buffer.LOG_RECORD_CONTEXT_KEYS` whitelist.
385
+
386
+ ### Advanced settings (dangerous options)
387
+
388
+ On the admin UI **Advanced settings** page (`http://127.0.0.1:8000/advanced`) you can read and save the global settings file `PROJECT_ROOT/.remote-coder/advanced_settings.json`. **Interface language** (`ui_language`): the default is **English**, and it governs not only the Telegram bot's messages and button labels but the **entire admin UI** (`/`, `/projects`, `/advanced`, `/logs`, `/database`). Switching to **Korean**, saving, and refreshing renders both the admin UI and Telegram responses in Korean. (The admin UI renders English by default and overlays Korean on the client.)
389
+
390
+ Defaults differ per option (e.g. server-lifecycle Telegram notifications are on by default; `git pull` on server start is off by default); an option left off behaves as if that feature is disabled. Keys used only by older versions are ignored on load (e.g. the removed `auto_pull_on_project_switch`).
391
+
392
+ > [!WARNING]
393
+ > The "immediately apply the request result to main/master and push" option auto-merges AI changes into the integration branch. Unless this is a personal experimental repository, keep the default (off) and verify remote branch protection and your backup policy before enabling it.
394
+
395
+ - **Immediately apply the request result to main/master and push**: When a Job succeeds through commit and branch push, similar to `/rebase`, it fast-forward-merges that branch into the integration branch (`main` or `master`) and pushes to the remote. If integration fails (conflict, non-ff, etc.), the Job is recorded as failed.
396
+ - **SQLite conversation-memory size limit**: When enabled, it targets the whole `conversation_entries` table and deletes oldest rows first. At least one of **max row count** and **max DB size (bytes)** must be a positive number; if both are set, it first meets the row-count limit, then repeats delete/`VACUUM` to meet the size limit. `message_branch_links` orphan links are cleaned up.
397
+
398
+ ## 3) Run it all at once
399
+
400
+ With the installed CLI, `remote-coder up` handles ngrok startup, webhook registration, and server start in one command. It passes the public ngrok URL to the server as `TELEGRAM_WEBHOOK_PUBLIC_BASE_URL`, so even without restarting the server, the Telegram webhook and `/` command menu for active projects you add/edit in the admin UI are refreshed immediately.
401
+
402
+ ```bash
403
+ remote-coder up
404
+ ```
405
+
406
+ For multi-bot setups, you can also pass just the public HTTPS Base URL to register the webhook and command menu for each active project with `python scripts/set_webhook.py <URL>`.
407
+
408
+ On Windows PowerShell you can use the following script:
409
+
410
+ ```powershell
411
+ .\run.ps1
412
+ ```
413
+
414
+ Or use the batch wrapper that auto-bypasses the PowerShell execution policy:
415
+
416
+ ```bat
417
+ run.bat
418
+ ```
419
+
420
+ On Windows, `ngrok.exe` must be installed and runnable from PATH before running. Verify:
421
+
422
+ ```powershell
423
+ ngrok version
424
+ ```
425
+
426
+ - After running the script, just message the bot on Telegram and it works.
427
+ - Press `Ctrl+C` to stop the server, which also terminates ngrok.
428
+
429
+ ## 4) Supported commands (MVP)
430
+
431
+ Refreshing the Telegram registration with `remote-coder up` or `python scripts/set_webhook.py <URL>` registers the same `/` command menu on each project bot that you would configure in BotFather.
432
+
433
+ - `/start` : Inline menu hub (shortcut buttons for model, monitor, clear, admin items)
434
+ - `/help` : Command help (inline buttons for model, monitor, clear items)
435
+ - `/model` : Show the default model (select via inline buttons)
436
+ - `/model claude` : Change this chat's default model to claude
437
+ - `/model codex` : Change this chat's default model to codex
438
+ - `/model gemini` : Change this chat's default model to gemini
439
+ - `/status` : Select from the recent Job list via inline buttons
440
+ - `/status <job_id>` : Query job status
441
+ - `/init` : Reset this chat's default-model override, `/clear`, and natural-language Job confirmation-pending state (the bot-bound project is unchanged; SQLite and Git are untouched)
442
+ - `/reports` : SQL-aggregate the SQLite conversation memory for the current chat + current working project into a summary report
443
+ - `/branch` : Show the currently checked-out branch of this chat's **bound project** repository
444
+ - `/branch <name>` : `git switch` only when a local branch exists in the bound project (errors if missing; does not auto-create branches that exist only on the remote)
445
+ - `/pull` : Fetch all branch info from the remote and pull the current branch. Also attempts fast-forward updates for other local branches (including main) that are not checked out.
446
+ - `/rebase` : Select a branch that exists both locally and on the remote (excluding main/master) via inline buttons, then rebase onto `main` (or `master`) → fast-forward merge → push to remote
447
+ - `/rebase <branch>` : Rebase a directly specified branch
448
+ - `/pr` : Select a local branch via inline buttons and create a GitHub Pull Request. The PR body includes the requests and AI results exchanged while working on that branch. Requires the GitHub CLI (`gh`) (`gh auth login`).
449
+ - `/pr <branch>` : Create a PR for a directly specified branch
450
+ - `/clear branch` : Clean up `remote-*` local/remote branches and their linked worktrees, **only in this bot's bound project**
451
+ - `/clear worktrees` : Clean up the managed worktrees of **this bot's project** + prune stale entries
452
+ - `/clear memory` : Delete only the conversation memory (SQLite) of **this bot's project + the current chat**
453
+ - `/stop` : Select an in-progress Job from a list via inline buttons to cancel it
454
+ - `/stop <job_id>` : Force-stop the specified Job (only for queued/running states)
455
+ - `/fix` : Rework a previous Job's commit message (`commit`) or source (`source`). Overwrites the existing commit with `git commit --amend` and reflects it to the remote with `git push --force-with-lease`. The commit trailer `committed by remote-coder: <id>` keeps the **original Job ID**.
456
+ - `/fix commit <job_id>` : Regenerate only the AI commit message and preview it → amend on `y`/`Y` confirmation
457
+ - `/fix source <job_id>` : Take a follow-up message as fix instructions and re-run the AI in the same branch worktree → amend + push on `y`/`Y` confirmation
458
+ - Replying to a previous bot message with `fix: <instruction>` (or `수정: <instruction>`) immediately shows a source-mode fix confirmation for that Job. The target Job must be in `SUCCEEDED + branch + commit` state.
459
+ - `/monitor model` : Based on the current chat's default model, a CLI probe (Claude `claude auth status` / Codex `codex --version` / Gemini `gemini --version`) plus a usage summary observed from local CLI logs. If a Codex session log has `rate_limits`, it shows the 5-hour/weekly remaining rates and reset times; Claude/Gemini show per-model token/request details from local transcript/chat logs.
460
+ - `/monitor memory` : SQLite conversation-memory row counts, rows per role, and DB file size for this chat + current **bound project**
461
+ - `/monitor branch` : Branch summary of the bound project repository (local/remote counts and lists)
462
+ - `/monitor worktrees` : Linked worktree list, detached count, and Remote Coder managed candidate summary
463
+ - `/monitor code` : Estimated code file/line counts based on the bound project root (extension whitelist; excludes `.git`, `node_modules`, etc.)
464
+ - `/monitor project` : Summary of the project record **bound to this bot** (name, enabled state, path, default model, worktree directory)
465
+ - Natural-language message: After agent/plan/ask parsing succeeds, it shows the current project, working branch, model in use, and mode, then creates an AI task (Job) after receiving `y`/`Y` (or an inline confirmation button when advanced settings enable it). Messages starting with the `plan:`/`ask:`/`계획:`/`질문:` prefix (colon `:` or `:`) or `/plan`/`/ask` run in **read-only** plan/ask mode and do not commit/push when the Job runs.
466
+
467
+ e.g. `plan: just outline how to refactor the login flow`, `/plan model: codex risks only`, `ask: what's the test command in this repo?`, `/ask the role of JobManager`
468
+
469
+ Notes:
470
+
471
+ - A per-chat default model overridden with `/model` is in-memory. On server restart it reverts to the project's `default_model` in the registry.
472
+ - The **bound project is always the name bound to this bot instance**. **`/branch`, `/rebase`, `/monitor memory|branch|worktrees|code|project`, etc. operate against that repository.**
473
+ - `/init` reverts the per-chat model override and confirmation-pending state (without touching the conversation-memory SQLite or Git repository).
474
+ - An AI Job creates a detached worktree from the **current `HEAD` commit** of the **project repository used for the request**, then runs. It creates a working branch and commits **only when the working tree has changes**. If there is a commit, it pushes to `GIT_REMOTE_NAME` (default `origin`). To change the repository branch, switch the local branch first with `/branch <name>`.
475
+ - Auto-generated commit messages use the following format:
476
+
477
+ ```text
478
+ type: title
479
+ - contents1
480
+ - contents2
481
+
482
+ committed by remote-coder: job-id
483
+ ```
484
+
485
+ `title` summarizes the functional change in one line, and the first body item describes what the AI agent changed — not the user's raw request or a list of recently modified files. The list of changed files is shown separately in the Job result notification.
486
+
487
+ - In natural-language messages you can also use the tokens `model: codex`, `model: gemini`, `branch: my-branch`, `no commit`. (The `branch:` value is validated by the same rules as `/branch`. In `plan:`/`ask:` mode, `branch:` and `no commit` are ignored.)
488
+ - Natural-language requests do not run immediately after parsing. The confirmation message shows the current project, working branch, and model/mode, and a Job is created only after `y` or `Y` (or an inline confirmation). If a new parseable natural-language message arrives while a confirmation is pending, it silently replaces the previous pending one; if an unparseable input arrives, the pending one is canceled.
489
+ - **Conversation memory (SQLite)**: User messages and Job intake/result summaries accumulate in SQLite per the same Telegram chat + same working project. It persists across server restarts. If you previously sent a specific instruction and then send a short follow-up like "start the task", "go ahead", "do that", or "begin", it merges recent records into an AI instruction. If there is no context, the bot sends a guidance message.
490
+ - **Reply chains**: For each natural-language request sent as a reply to a previous message, the bodies of ancestor messages remaining in SQLite and the Job-result summaries linked to each message are prepended to the Codex/Claude instruction as a `[Reply chain context]` block. (Restored only if the bot received and stored those messages.)
491
+ - You can pass a recent display count, like `/reports 7`. The allowed range is `1–10`, default `5`.
492
+ - Writability is checked right after worktree creation. If the AI output contains expressions like read-only/cannot-modify and there is no Git change, it is treated as a **failure**, not a success.
493
+ - Task completion/failure messages include a summary of the AI execution result (`stdout`/`stderr`).
494
+ - The full raw output is available in the worktree log file (`WORKTREE_BASE_DIR/_logs/<job_id>.log`).
495
+
496
+ ## 5) Per-model usage guides
497
+
498
+ - Multi-bot / webhook / migration: [`docs/multi-bot-setup.md`](docs/multi-bot-setup.md)
499
+ - Claude users: [`docs/claude-guide.md`](docs/claude-guide.md)
500
+ - Codex users: [`docs/codex-guide.md`](docs/codex-guide.md)
501
+ - Gemini users: [`docs/gemini-guide.md`](docs/gemini-guide.md)
502
+ - When a worktree fails as read-only: [`docs/read-only-workspace.md`](docs/read-only-workspace.md)
503
+
504
+ **Runner operation notes:** The Gemini CLI is wired primarily for non-interactive execution, so expectations may differ from an interactive TUI. The Codex CLI may restrict network or some tool calls depending on its sandbox/approval policy.
505
+
506
+ ## 6) Tests
507
+
508
+ Multi-bot routing, notification isolation, and project-scoped state are covered by `tests/test_webhook_multibot.py`, `tests/test_bot_instance_manager.py`, `tests/test_project_scoped_state.py`, etc.
509
+
510
+ ```bash
511
+ conda activate remote-coder
512
+ PYTEST_DISABLE_PLUGIN_AUTOLOAD=1 pytest -q -p pytest_asyncio.plugin -p respx.fixtures
513
+ ```
514
+
515
+ ## 7) Public repository management
516
+
517
+ - License: [Apache License 2.0](LICENSE)
518
+ - How to contribute: [CONTRIBUTING.md](CONTRIBUTING.md)
519
+ - Security policy: [SECURITY.md](SECURITY.md)
520
+ - Before opening a Pull Request, run `PYTEST_DISABLE_PLUGIN_AUTOLOAD=1 conda run -n remote-coder pytest -q -p pytest_asyncio.plugin -p respx.fixtures`.