sahya-code 1.0.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (238) hide show
  1. sahya_code-1.0.0/PKG-INFO +158 -0
  2. sahya_code-1.0.0/README.md +122 -0
  3. sahya_code-1.0.0/pyproject.toml +122 -0
  4. sahya_code-1.0.0/src/sahya_code/CHANGELOG.md +108 -0
  5. sahya_code-1.0.0/src/sahya_code/__init__.py +29 -0
  6. sahya_code-1.0.0/src/sahya_code/__main__.py +30 -0
  7. sahya_code-1.0.0/src/sahya_code/acp/AGENTS.md +92 -0
  8. sahya_code-1.0.0/src/sahya_code/acp/__init__.py +13 -0
  9. sahya_code-1.0.0/src/sahya_code/acp/convert.py +128 -0
  10. sahya_code-1.0.0/src/sahya_code/acp/kaos.py +291 -0
  11. sahya_code-1.0.0/src/sahya_code/acp/mcp.py +46 -0
  12. sahya_code-1.0.0/src/sahya_code/acp/server.py +457 -0
  13. sahya_code-1.0.0/src/sahya_code/acp/session.py +496 -0
  14. sahya_code-1.0.0/src/sahya_code/acp/tools.py +167 -0
  15. sahya_code-1.0.0/src/sahya_code/acp/types.py +13 -0
  16. sahya_code-1.0.0/src/sahya_code/acp/version.py +45 -0
  17. sahya_code-1.0.0/src/sahya_code/agents/default/agent.yaml +36 -0
  18. sahya_code-1.0.0/src/sahya_code/agents/default/coder.yaml +25 -0
  19. sahya_code-1.0.0/src/sahya_code/agents/default/explore.yaml +46 -0
  20. sahya_code-1.0.0/src/sahya_code/agents/default/plan.yaml +30 -0
  21. sahya_code-1.0.0/src/sahya_code/agents/default/system.md +160 -0
  22. sahya_code-1.0.0/src/sahya_code/agents/okabe/agent.yaml +22 -0
  23. sahya_code-1.0.0/src/sahya_code/agentspec.py +160 -0
  24. sahya_code-1.0.0/src/sahya_code/app.py +540 -0
  25. sahya_code-1.0.0/src/sahya_code/approval_runtime/__init__.py +29 -0
  26. sahya_code-1.0.0/src/sahya_code/approval_runtime/models.py +42 -0
  27. sahya_code-1.0.0/src/sahya_code/approval_runtime/runtime.py +189 -0
  28. sahya_code-1.0.0/src/sahya_code/auth/__init__.py +5 -0
  29. sahya_code-1.0.0/src/sahya_code/auth/oauth.py +804 -0
  30. sahya_code-1.0.0/src/sahya_code/auth/platforms.py +293 -0
  31. sahya_code-1.0.0/src/sahya_code/background/__init__.py +36 -0
  32. sahya_code-1.0.0/src/sahya_code/background/agent_runner.py +209 -0
  33. sahya_code-1.0.0/src/sahya_code/background/ids.py +19 -0
  34. sahya_code-1.0.0/src/sahya_code/background/manager.py +580 -0
  35. sahya_code-1.0.0/src/sahya_code/background/models.py +105 -0
  36. sahya_code-1.0.0/src/sahya_code/background/store.py +196 -0
  37. sahya_code-1.0.0/src/sahya_code/background/summary.py +66 -0
  38. sahya_code-1.0.0/src/sahya_code/background/worker.py +209 -0
  39. sahya_code-1.0.0/src/sahya_code/cli/__init__.py +932 -0
  40. sahya_code-1.0.0/src/sahya_code/cli/__main__.py +8 -0
  41. sahya_code-1.0.0/src/sahya_code/cli/_lazy_group.py +222 -0
  42. sahya_code-1.0.0/src/sahya_code/cli/export.py +74 -0
  43. sahya_code-1.0.0/src/sahya_code/cli/info.py +62 -0
  44. sahya_code-1.0.0/src/sahya_code/cli/mcp.py +349 -0
  45. sahya_code-1.0.0/src/sahya_code/cli/plugin.py +302 -0
  46. sahya_code-1.0.0/src/sahya_code/cli/toad.py +73 -0
  47. sahya_code-1.0.0/src/sahya_code/cli/vis.py +38 -0
  48. sahya_code-1.0.0/src/sahya_code/cli/web.py +80 -0
  49. sahya_code-1.0.0/src/sahya_code/config.py +391 -0
  50. sahya_code-1.0.0/src/sahya_code/constant.py +33 -0
  51. sahya_code-1.0.0/src/sahya_code/exception.py +43 -0
  52. sahya_code-1.0.0/src/sahya_code/hooks/__init__.py +4 -0
  53. sahya_code-1.0.0/src/sahya_code/hooks/config.py +34 -0
  54. sahya_code-1.0.0/src/sahya_code/hooks/engine.py +310 -0
  55. sahya_code-1.0.0/src/sahya_code/hooks/events.py +190 -0
  56. sahya_code-1.0.0/src/sahya_code/hooks/runner.py +89 -0
  57. sahya_code-1.0.0/src/sahya_code/llm.py +306 -0
  58. sahya_code-1.0.0/src/sahya_code/metadata.py +79 -0
  59. sahya_code-1.0.0/src/sahya_code/notifications/__init__.py +33 -0
  60. sahya_code-1.0.0/src/sahya_code/notifications/llm.py +77 -0
  61. sahya_code-1.0.0/src/sahya_code/notifications/manager.py +145 -0
  62. sahya_code-1.0.0/src/sahya_code/notifications/models.py +50 -0
  63. sahya_code-1.0.0/src/sahya_code/notifications/notifier.py +41 -0
  64. sahya_code-1.0.0/src/sahya_code/notifications/store.py +99 -0
  65. sahya_code-1.0.0/src/sahya_code/notifications/wire.py +21 -0
  66. sahya_code-1.0.0/src/sahya_code/plugin/__init__.py +124 -0
  67. sahya_code-1.0.0/src/sahya_code/plugin/manager.py +153 -0
  68. sahya_code-1.0.0/src/sahya_code/plugin/tool.py +173 -0
  69. sahya_code-1.0.0/src/sahya_code/prompts/__init__.py +6 -0
  70. sahya_code-1.0.0/src/sahya_code/prompts/compact.md +73 -0
  71. sahya_code-1.0.0/src/sahya_code/prompts/init.md +21 -0
  72. sahya_code-1.0.0/src/sahya_code/py.typed +0 -0
  73. sahya_code-1.0.0/src/sahya_code/session.py +293 -0
  74. sahya_code-1.0.0/src/sahya_code/session_state.py +42 -0
  75. sahya_code-1.0.0/src/sahya_code/share.py +28 -0
  76. sahya_code-1.0.0/src/sahya_code/skill/__init__.py +311 -0
  77. sahya_code-1.0.0/src/sahya_code/skill/flow/__init__.py +99 -0
  78. sahya_code-1.0.0/src/sahya_code/skill/flow/d2.py +482 -0
  79. sahya_code-1.0.0/src/sahya_code/skill/flow/mermaid.py +266 -0
  80. sahya_code-1.0.0/src/sahya_code/skills/kimi-cli-help/SKILL.md +55 -0
  81. sahya_code-1.0.0/src/sahya_code/skills/skill-creator/SKILL.md +367 -0
  82. sahya_code-1.0.0/src/sahya_code/soul/__init__.py +288 -0
  83. sahya_code-1.0.0/src/sahya_code/soul/agent.py +423 -0
  84. sahya_code-1.0.0/src/sahya_code/soul/approval.py +171 -0
  85. sahya_code-1.0.0/src/sahya_code/soul/compaction.py +189 -0
  86. sahya_code-1.0.0/src/sahya_code/soul/context.py +239 -0
  87. sahya_code-1.0.0/src/sahya_code/soul/denwarenji.py +39 -0
  88. sahya_code-1.0.0/src/sahya_code/soul/dynamic_injection.py +66 -0
  89. sahya_code-1.0.0/src/sahya_code/soul/dynamic_injections/__init__.py +0 -0
  90. sahya_code-1.0.0/src/sahya_code/soul/dynamic_injections/plan_mode.py +238 -0
  91. sahya_code-1.0.0/src/sahya_code/soul/dynamic_injections/yolo_mode.py +41 -0
  92. sahya_code-1.0.0/src/sahya_code/soul/message.py +92 -0
  93. sahya_code-1.0.0/src/sahya_code/soul/sahyasoul.py +1220 -0
  94. sahya_code-1.0.0/src/sahya_code/soul/slash.py +285 -0
  95. sahya_code-1.0.0/src/sahya_code/soul/toolset.py +610 -0
  96. sahya_code-1.0.0/src/sahya_code/subagents/__init__.py +21 -0
  97. sahya_code-1.0.0/src/sahya_code/subagents/builder.py +42 -0
  98. sahya_code-1.0.0/src/sahya_code/subagents/core.py +86 -0
  99. sahya_code-1.0.0/src/sahya_code/subagents/git_context.py +170 -0
  100. sahya_code-1.0.0/src/sahya_code/subagents/models.py +54 -0
  101. sahya_code-1.0.0/src/sahya_code/subagents/output.py +71 -0
  102. sahya_code-1.0.0/src/sahya_code/subagents/registry.py +28 -0
  103. sahya_code-1.0.0/src/sahya_code/subagents/runner.py +370 -0
  104. sahya_code-1.0.0/src/sahya_code/subagents/store.py +148 -0
  105. sahya_code-1.0.0/src/sahya_code/tools/AGENTS.md +5 -0
  106. sahya_code-1.0.0/src/sahya_code/tools/__init__.py +105 -0
  107. sahya_code-1.0.0/src/sahya_code/tools/agent/__init__.py +276 -0
  108. sahya_code-1.0.0/src/sahya_code/tools/agent/description.md +41 -0
  109. sahya_code-1.0.0/src/sahya_code/tools/ask_user/__init__.py +154 -0
  110. sahya_code-1.0.0/src/sahya_code/tools/ask_user/description.md +19 -0
  111. sahya_code-1.0.0/src/sahya_code/tools/background/__init__.py +318 -0
  112. sahya_code-1.0.0/src/sahya_code/tools/background/list.md +10 -0
  113. sahya_code-1.0.0/src/sahya_code/tools/background/output.md +11 -0
  114. sahya_code-1.0.0/src/sahya_code/tools/background/stop.md +8 -0
  115. sahya_code-1.0.0/src/sahya_code/tools/display.py +46 -0
  116. sahya_code-1.0.0/src/sahya_code/tools/dmail/__init__.py +38 -0
  117. sahya_code-1.0.0/src/sahya_code/tools/dmail/dmail.md +17 -0
  118. sahya_code-1.0.0/src/sahya_code/tools/file/__init__.py +30 -0
  119. sahya_code-1.0.0/src/sahya_code/tools/file/glob.md +17 -0
  120. sahya_code-1.0.0/src/sahya_code/tools/file/glob.py +156 -0
  121. sahya_code-1.0.0/src/sahya_code/tools/file/grep.md +5 -0
  122. sahya_code-1.0.0/src/sahya_code/tools/file/grep_local.py +524 -0
  123. sahya_code-1.0.0/src/sahya_code/tools/file/plan_mode.py +45 -0
  124. sahya_code-1.0.0/src/sahya_code/tools/file/read.md +14 -0
  125. sahya_code-1.0.0/src/sahya_code/tools/file/read.py +189 -0
  126. sahya_code-1.0.0/src/sahya_code/tools/file/read_media.md +24 -0
  127. sahya_code-1.0.0/src/sahya_code/tools/file/read_media.py +215 -0
  128. sahya_code-1.0.0/src/sahya_code/tools/file/replace.md +7 -0
  129. sahya_code-1.0.0/src/sahya_code/tools/file/replace.py +193 -0
  130. sahya_code-1.0.0/src/sahya_code/tools/file/utils.py +257 -0
  131. sahya_code-1.0.0/src/sahya_code/tools/file/write.md +5 -0
  132. sahya_code-1.0.0/src/sahya_code/tools/file/write.py +175 -0
  133. sahya_code-1.0.0/src/sahya_code/tools/plan/__init__.py +325 -0
  134. sahya_code-1.0.0/src/sahya_code/tools/plan/description.md +25 -0
  135. sahya_code-1.0.0/src/sahya_code/tools/plan/enter.py +183 -0
  136. sahya_code-1.0.0/src/sahya_code/tools/plan/enter_description.md +30 -0
  137. sahya_code-1.0.0/src/sahya_code/tools/plan/heroes.py +277 -0
  138. sahya_code-1.0.0/src/sahya_code/tools/shell/__init__.py +235 -0
  139. sahya_code-1.0.0/src/sahya_code/tools/shell/bash.md +35 -0
  140. sahya_code-1.0.0/src/sahya_code/tools/shell/powershell.md +30 -0
  141. sahya_code-1.0.0/src/sahya_code/tools/test.py +55 -0
  142. sahya_code-1.0.0/src/sahya_code/tools/think/__init__.py +21 -0
  143. sahya_code-1.0.0/src/sahya_code/tools/think/think.md +1 -0
  144. sahya_code-1.0.0/src/sahya_code/tools/todo/__init__.py +33 -0
  145. sahya_code-1.0.0/src/sahya_code/tools/todo/set_todo_list.md +15 -0
  146. sahya_code-1.0.0/src/sahya_code/tools/utils.py +199 -0
  147. sahya_code-1.0.0/src/sahya_code/tools/web/__init__.py +4 -0
  148. sahya_code-1.0.0/src/sahya_code/tools/web/fetch.md +1 -0
  149. sahya_code-1.0.0/src/sahya_code/tools/web/fetch.py +173 -0
  150. sahya_code-1.0.0/src/sahya_code/tools/web/search.md +1 -0
  151. sahya_code-1.0.0/src/sahya_code/tools/web/search.py +146 -0
  152. sahya_code-1.0.0/src/sahya_code/ui/__init__.py +0 -0
  153. sahya_code-1.0.0/src/sahya_code/ui/acp/__init__.py +99 -0
  154. sahya_code-1.0.0/src/sahya_code/ui/print/__init__.py +167 -0
  155. sahya_code-1.0.0/src/sahya_code/ui/print/visualize.py +185 -0
  156. sahya_code-1.0.0/src/sahya_code/ui/shell/__init__.py +991 -0
  157. sahya_code-1.0.0/src/sahya_code/ui/shell/approval_panel.py +481 -0
  158. sahya_code-1.0.0/src/sahya_code/ui/shell/console.py +105 -0
  159. sahya_code-1.0.0/src/sahya_code/ui/shell/debug.py +190 -0
  160. sahya_code-1.0.0/src/sahya_code/ui/shell/echo.py +17 -0
  161. sahya_code-1.0.0/src/sahya_code/ui/shell/export_import.py +111 -0
  162. sahya_code-1.0.0/src/sahya_code/ui/shell/keyboard.py +300 -0
  163. sahya_code-1.0.0/src/sahya_code/ui/shell/mcp_status.py +111 -0
  164. sahya_code-1.0.0/src/sahya_code/ui/shell/oauth.py +143 -0
  165. sahya_code-1.0.0/src/sahya_code/ui/shell/placeholders.py +530 -0
  166. sahya_code-1.0.0/src/sahya_code/ui/shell/prompt.py +2124 -0
  167. sahya_code-1.0.0/src/sahya_code/ui/shell/question_panel.py +586 -0
  168. sahya_code-1.0.0/src/sahya_code/ui/shell/replay.py +210 -0
  169. sahya_code-1.0.0/src/sahya_code/ui/shell/setup.py +212 -0
  170. sahya_code-1.0.0/src/sahya_code/ui/shell/slash.py +716 -0
  171. sahya_code-1.0.0/src/sahya_code/ui/shell/startup.py +32 -0
  172. sahya_code-1.0.0/src/sahya_code/ui/shell/task_browser.py +486 -0
  173. sahya_code-1.0.0/src/sahya_code/ui/shell/update.py +217 -0
  174. sahya_code-1.0.0/src/sahya_code/ui/shell/usage.py +281 -0
  175. sahya_code-1.0.0/src/sahya_code/ui/shell/visualize.py +1497 -0
  176. sahya_code-1.0.0/src/sahya_code/ui/theme.py +238 -0
  177. sahya_code-1.0.0/src/sahya_code/utils/__init__.py +0 -0
  178. sahya_code-1.0.0/src/sahya_code/utils/aiohttp.py +24 -0
  179. sahya_code-1.0.0/src/sahya_code/utils/aioqueue.py +72 -0
  180. sahya_code-1.0.0/src/sahya_code/utils/broadcast.py +37 -0
  181. sahya_code-1.0.0/src/sahya_code/utils/changelog.py +108 -0
  182. sahya_code-1.0.0/src/sahya_code/utils/clipboard.py +169 -0
  183. sahya_code-1.0.0/src/sahya_code/utils/datetime.py +37 -0
  184. sahya_code-1.0.0/src/sahya_code/utils/diff.py +135 -0
  185. sahya_code-1.0.0/src/sahya_code/utils/editor.py +91 -0
  186. sahya_code-1.0.0/src/sahya_code/utils/environment.py +58 -0
  187. sahya_code-1.0.0/src/sahya_code/utils/envvar.py +12 -0
  188. sahya_code-1.0.0/src/sahya_code/utils/export.py +696 -0
  189. sahya_code-1.0.0/src/sahya_code/utils/frontmatter.py +50 -0
  190. sahya_code-1.0.0/src/sahya_code/utils/io.py +27 -0
  191. sahya_code-1.0.0/src/sahya_code/utils/logging.py +124 -0
  192. sahya_code-1.0.0/src/sahya_code/utils/media_tags.py +29 -0
  193. sahya_code-1.0.0/src/sahya_code/utils/message.py +24 -0
  194. sahya_code-1.0.0/src/sahya_code/utils/path.py +140 -0
  195. sahya_code-1.0.0/src/sahya_code/utils/proctitle.py +33 -0
  196. sahya_code-1.0.0/src/sahya_code/utils/pyinstaller.py +32 -0
  197. sahya_code-1.0.0/src/sahya_code/utils/rich/__init__.py +33 -0
  198. sahya_code-1.0.0/src/sahya_code/utils/rich/columns.py +99 -0
  199. sahya_code-1.0.0/src/sahya_code/utils/rich/diff_render.py +436 -0
  200. sahya_code-1.0.0/src/sahya_code/utils/rich/markdown.py +900 -0
  201. sahya_code-1.0.0/src/sahya_code/utils/rich/markdown_sample.md +108 -0
  202. sahya_code-1.0.0/src/sahya_code/utils/rich/markdown_sample_short.md +2 -0
  203. sahya_code-1.0.0/src/sahya_code/utils/rich/syntax.py +114 -0
  204. sahya_code-1.0.0/src/sahya_code/utils/server.py +121 -0
  205. sahya_code-1.0.0/src/sahya_code/utils/signals.py +43 -0
  206. sahya_code-1.0.0/src/sahya_code/utils/slashcmd.py +124 -0
  207. sahya_code-1.0.0/src/sahya_code/utils/string.py +22 -0
  208. sahya_code-1.0.0/src/sahya_code/utils/subprocess_env.py +73 -0
  209. sahya_code-1.0.0/src/sahya_code/utils/term.py +168 -0
  210. sahya_code-1.0.0/src/sahya_code/utils/typing.py +20 -0
  211. sahya_code-1.0.0/src/sahya_code/vis/__init__.py +0 -0
  212. sahya_code-1.0.0/src/sahya_code/vis/api/__init__.py +5 -0
  213. sahya_code-1.0.0/src/sahya_code/vis/api/sessions.py +692 -0
  214. sahya_code-1.0.0/src/sahya_code/vis/api/statistics.py +209 -0
  215. sahya_code-1.0.0/src/sahya_code/vis/api/system.py +19 -0
  216. sahya_code-1.0.0/src/sahya_code/vis/app.py +175 -0
  217. sahya_code-1.0.0/src/sahya_code/web/__init__.py +5 -0
  218. sahya_code-1.0.0/src/sahya_code/web/api/__init__.py +15 -0
  219. sahya_code-1.0.0/src/sahya_code/web/api/config.py +208 -0
  220. sahya_code-1.0.0/src/sahya_code/web/api/open_in.py +197 -0
  221. sahya_code-1.0.0/src/sahya_code/web/api/sessions.py +1392 -0
  222. sahya_code-1.0.0/src/sahya_code/web/app.py +412 -0
  223. sahya_code-1.0.0/src/sahya_code/web/auth.py +191 -0
  224. sahya_code-1.0.0/src/sahya_code/web/models.py +98 -0
  225. sahya_code-1.0.0/src/sahya_code/web/runner/__init__.py +5 -0
  226. sahya_code-1.0.0/src/sahya_code/web/runner/messages.py +57 -0
  227. sahya_code-1.0.0/src/sahya_code/web/runner/process.py +745 -0
  228. sahya_code-1.0.0/src/sahya_code/web/runner/worker.py +87 -0
  229. sahya_code-1.0.0/src/sahya_code/web/store/__init__.py +1 -0
  230. sahya_code-1.0.0/src/sahya_code/web/store/sessions.py +517 -0
  231. sahya_code-1.0.0/src/sahya_code/wire/__init__.py +148 -0
  232. sahya_code-1.0.0/src/sahya_code/wire/file.py +151 -0
  233. sahya_code-1.0.0/src/sahya_code/wire/jsonrpc.py +263 -0
  234. sahya_code-1.0.0/src/sahya_code/wire/protocol.py +2 -0
  235. sahya_code-1.0.0/src/sahya_code/wire/root_hub.py +27 -0
  236. sahya_code-1.0.0/src/sahya_code/wire/serde.py +26 -0
  237. sahya_code-1.0.0/src/sahya_code/wire/server.py +1029 -0
  238. sahya_code-1.0.0/src/sahya_code/wire/types.py +674 -0
@@ -0,0 +1,158 @@
1
+ Metadata-Version: 2.3
2
+ Name: sahya-code
3
+ Version: 1.0.0
4
+ Summary: Sahya Code - Your AI coding companion.
5
+ Requires-Dist: agent-client-protocol==0.8.0
6
+ Requires-Dist: aiofiles>=24.0,<26.0
7
+ Requires-Dist: aiohttp==3.13.3
8
+ Requires-Dist: typer==0.21.1
9
+ Requires-Dist: kosong[contrib]==0.47.0
10
+ Requires-Dist: loguru>=0.6.0,<0.8
11
+ Requires-Dist: prompt-toolkit==3.0.52
12
+ Requires-Dist: pillow==12.1.0
13
+ Requires-Dist: pyyaml==6.0.3
14
+ Requires-Dist: rich==14.2.0
15
+ Requires-Dist: ripgrepy==2.2.0
16
+ Requires-Dist: streamingjson==0.0.5
17
+ Requires-Dist: trafilatura==2.0.0
18
+ Requires-Dist: lxml==6.0.2
19
+ Requires-Dist: tenacity==9.1.2
20
+ Requires-Dist: fastmcp==2.12.5
21
+ Requires-Dist: pydantic==2.12.5
22
+ Requires-Dist: httpx[socks]==0.28.1
23
+ Requires-Dist: pykaos==0.7.0
24
+ Requires-Dist: batrachian-toad==0.5.23 ; python_full_version >= '3.14'
25
+ Requires-Dist: tomlkit==0.14.0
26
+ Requires-Dist: jinja2==3.1.6
27
+ Requires-Dist: pyobjc-framework-cocoa>=12.1 ; sys_platform == 'darwin'
28
+ Requires-Dist: fastapi>=0.115.0
29
+ Requires-Dist: uvicorn[standard]>=0.32.0
30
+ Requires-Dist: scalar-fastapi>=1.5.0
31
+ Requires-Dist: websockets>=14.0
32
+ Requires-Dist: keyring>=25.7.0
33
+ Requires-Dist: setproctitle>=1.3.0
34
+ Requires-Python: >=3.12
35
+ Description-Content-Type: text/markdown
36
+
37
+ # Sahya Code
38
+
39
+ Sahya Code is a CLI-based AI coding agent that helps you write, edit, and understand code through natural language interaction. It is a customized fork of [kimi-cli](https://github.com/MoonshotAI/kimi-cli), pre-configured to work with LiteLLM endpoints.
40
+
41
+ ## Features
42
+
43
+ - 🤖 AI-powered coding assistance
44
+ - 📝 Code reading, writing, and editing
45
+ - 🔍 Web search and fetch capabilities
46
+ - 🐚 Shell command execution
47
+ - 🔧 Extensible tool system with MCP support
48
+ - 💻 Terminal UI with rich formatting
49
+ - 🌐 Web interface for browser-based interaction
50
+
51
+ ## Installation
52
+
53
+ ```bash
54
+ pip install sahya-code
55
+ ```
56
+
57
+ ## Configuration
58
+
59
+ ### API Key
60
+
61
+ Set your API key as an environment variable:
62
+
63
+ ```bash
64
+ export SAHYA_API_KEY="sk-VBkuXAOO7e2kV5-uWpz84A"
65
+ ```
66
+
67
+ Or configure interactively on first run using the setup wizard.
68
+
69
+ ### Custom Endpoint
70
+
71
+ Sahya Code uses a LiteLLM-compatible endpoint by default:
72
+ - **URL:** `https://llm.nexiant.ai`
73
+ - **Protocol:** OpenAI-compatible API
74
+
75
+ To use a different endpoint:
76
+
77
+ ```bash
78
+ export SAHYA_BASE_URL="https://your-endpoint.com"
79
+ ```
80
+
81
+ ### Configuration File
82
+
83
+ You can also configure via the config file at `~/.local/share/sahya-code/config.toml`:
84
+
85
+ ```toml
86
+ default_model = "default"
87
+
88
+ [models.default]
89
+ provider = "sahya"
90
+ model = "kimi-k2.5"
91
+ max_context_size = 256000
92
+ capabilities = ["image_in", "thinking"]
93
+
94
+ [providers.sahya]
95
+ type = "openai_legacy"
96
+ base_url = "https://llm.nexiant.ai"
97
+ api_key = "sk-VBkuXAOO7e2kV5-uWpz84A"
98
+ ```
99
+
100
+ ## Usage
101
+
102
+ Start Sahya Code:
103
+
104
+ ```bash
105
+ sahya
106
+ ```
107
+
108
+ Or with a specific prompt:
109
+
110
+ ```bash
111
+ sahya "Explain this codebase to me"
112
+ ```
113
+
114
+ ### Available Commands
115
+
116
+ ```bash
117
+ sahya --help # Show help
118
+ sahya --version # Show version
119
+ sahya web # Start web interface
120
+ sahya mcp list # List MCP servers
121
+ sahya mcp add <name> ... # Add MCP server
122
+ ```
123
+
124
+ ### Interactive Commands
125
+
126
+ Once in the shell, you can use:
127
+
128
+ - `Ctrl+X` - Toggle between agent mode and shell mode
129
+ - `/help` - Show available slash commands
130
+ - `/exit` or `Ctrl+D` - Exit
131
+
132
+ ## Environment Variables
133
+
134
+ | Variable | Description | Default |
135
+ |----------|-------------|---------|
136
+ | `SAHYA_API_KEY` | API key for authentication | Required |
137
+ | `SAHYA_BASE_URL` | LiteLLM endpoint URL | `https://llm.nexiant.ai` |
138
+ | `SAHYA_SHARE_DIR` | Config and data directory | `~/.local/share/sahya-code` |
139
+ | `SAHYA_CACHE_DIR` | Cache directory | `~/.cache/sahya-code` |
140
+
141
+ ## Documentation
142
+
143
+ - [ARCHITECTURE.md](ARCHITECTURE.md) - System architecture and design
144
+ - [CHANGELOG.md](CHANGELOG.md) - Version history
145
+ - [TODOLIST.md](TODOLIST.md) - Development roadmap
146
+
147
+ ## Requirements
148
+
149
+ - Python 3.12 or higher
150
+ - API key for the LiteLLM endpoint
151
+
152
+ ## Acknowledgments
153
+
154
+ Sahya Code is based on [kimi-cli](https://github.com/MoonshotAI/kimi-cli) by Moonshot AI.
155
+
156
+ ## License
157
+
158
+ [Apache License 2.0](LICENSE)
@@ -0,0 +1,122 @@
1
+ # Sahya Code
2
+
3
+ Sahya Code is a CLI-based AI coding agent that helps you write, edit, and understand code through natural language interaction. It is a customized fork of [kimi-cli](https://github.com/MoonshotAI/kimi-cli), pre-configured to work with LiteLLM endpoints.
4
+
5
+ ## Features
6
+
7
+ - 🤖 AI-powered coding assistance
8
+ - 📝 Code reading, writing, and editing
9
+ - 🔍 Web search and fetch capabilities
10
+ - 🐚 Shell command execution
11
+ - 🔧 Extensible tool system with MCP support
12
+ - 💻 Terminal UI with rich formatting
13
+ - 🌐 Web interface for browser-based interaction
14
+
15
+ ## Installation
16
+
17
+ ```bash
18
+ pip install sahya-code
19
+ ```
20
+
21
+ ## Configuration
22
+
23
+ ### API Key
24
+
25
+ Set your API key as an environment variable:
26
+
27
+ ```bash
28
+ export SAHYA_API_KEY="sk-VBkuXAOO7e2kV5-uWpz84A"
29
+ ```
30
+
31
+ Or configure interactively on first run using the setup wizard.
32
+
33
+ ### Custom Endpoint
34
+
35
+ Sahya Code uses a LiteLLM-compatible endpoint by default:
36
+ - **URL:** `https://llm.nexiant.ai`
37
+ - **Protocol:** OpenAI-compatible API
38
+
39
+ To use a different endpoint:
40
+
41
+ ```bash
42
+ export SAHYA_BASE_URL="https://your-endpoint.com"
43
+ ```
44
+
45
+ ### Configuration File
46
+
47
+ You can also configure via the config file at `~/.local/share/sahya-code/config.toml`:
48
+
49
+ ```toml
50
+ default_model = "default"
51
+
52
+ [models.default]
53
+ provider = "sahya"
54
+ model = "kimi-k2.5"
55
+ max_context_size = 256000
56
+ capabilities = ["image_in", "thinking"]
57
+
58
+ [providers.sahya]
59
+ type = "openai_legacy"
60
+ base_url = "https://llm.nexiant.ai"
61
+ api_key = "sk-VBkuXAOO7e2kV5-uWpz84A"
62
+ ```
63
+
64
+ ## Usage
65
+
66
+ Start Sahya Code:
67
+
68
+ ```bash
69
+ sahya
70
+ ```
71
+
72
+ Or with a specific prompt:
73
+
74
+ ```bash
75
+ sahya "Explain this codebase to me"
76
+ ```
77
+
78
+ ### Available Commands
79
+
80
+ ```bash
81
+ sahya --help # Show help
82
+ sahya --version # Show version
83
+ sahya web # Start web interface
84
+ sahya mcp list # List MCP servers
85
+ sahya mcp add <name> ... # Add MCP server
86
+ ```
87
+
88
+ ### Interactive Commands
89
+
90
+ Once in the shell, you can use:
91
+
92
+ - `Ctrl+X` - Toggle between agent mode and shell mode
93
+ - `/help` - Show available slash commands
94
+ - `/exit` or `Ctrl+D` - Exit
95
+
96
+ ## Environment Variables
97
+
98
+ | Variable | Description | Default |
99
+ |----------|-------------|---------|
100
+ | `SAHYA_API_KEY` | API key for authentication | Required |
101
+ | `SAHYA_BASE_URL` | LiteLLM endpoint URL | `https://llm.nexiant.ai` |
102
+ | `SAHYA_SHARE_DIR` | Config and data directory | `~/.local/share/sahya-code` |
103
+ | `SAHYA_CACHE_DIR` | Cache directory | `~/.cache/sahya-code` |
104
+
105
+ ## Documentation
106
+
107
+ - [ARCHITECTURE.md](ARCHITECTURE.md) - System architecture and design
108
+ - [CHANGELOG.md](CHANGELOG.md) - Version history
109
+ - [TODOLIST.md](TODOLIST.md) - Development roadmap
110
+
111
+ ## Requirements
112
+
113
+ - Python 3.12 or higher
114
+ - API key for the LiteLLM endpoint
115
+
116
+ ## Acknowledgments
117
+
118
+ Sahya Code is based on [kimi-cli](https://github.com/MoonshotAI/kimi-cli) by Moonshot AI.
119
+
120
+ ## License
121
+
122
+ [Apache License 2.0](LICENSE)
@@ -0,0 +1,122 @@
1
+ [project]
2
+ name = "sahya-code"
3
+ version = "1.0.0"
4
+ description = "Sahya Code - Your AI coding companion."
5
+ readme = "README.md"
6
+ requires-python = ">=3.12"
7
+ dependencies = [
8
+ "agent-client-protocol==0.8.0",
9
+ "aiofiles>=24.0,<26.0",
10
+ "aiohttp==3.13.3",
11
+ "typer==0.21.1",
12
+ "kosong[contrib]==0.47.0",
13
+ "loguru>=0.6.0,<0.8",
14
+ "prompt-toolkit==3.0.52",
15
+ "pillow==12.1.0",
16
+ "pyyaml==6.0.3",
17
+ "rich==14.2.0",
18
+ "ripgrepy==2.2.0",
19
+ "streamingjson==0.0.5",
20
+ "trafilatura==2.0.0",
21
+ "lxml==6.0.2",
22
+ "tenacity==9.1.2",
23
+ "fastmcp==2.12.5",
24
+ "pydantic==2.12.5",
25
+ "httpx[socks]==0.28.1",
26
+ "pykaos==0.7.0",
27
+ "batrachian-toad==0.5.23; python_version >= \"3.14\"",
28
+ "tomlkit==0.14.0",
29
+ "jinja2==3.1.6",
30
+ "pyobjc-framework-cocoa>=12.1 ; sys_platform == \"darwin\"",
31
+ "fastapi>=0.115.0",
32
+ "uvicorn[standard]>=0.32.0",
33
+ "scalar-fastapi>=1.5.0",
34
+ "websockets>=14.0",
35
+ "keyring>=25.7.0",
36
+ "setproctitle>=1.3.0",
37
+ ]
38
+
39
+ [dependency-groups]
40
+ dev = [
41
+ "pyinstaller==6.18.0",
42
+ "inline-snapshot[black]>=0.31.1",
43
+ "pyright>=1.1.407",
44
+ "ty>=0.0.9",
45
+ "pytest>=9.0.2",
46
+ "pytest-asyncio>=1.3.0",
47
+ "ruff>=0.14.10",
48
+ ]
49
+
50
+ [build-system]
51
+ requires = ["uv_build>=0.8.5,<0.10.0"]
52
+ build-backend = "uv_build"
53
+
54
+ [tool.uv.build-backend]
55
+ module-name = ["sahya_code"]
56
+ source-exclude = ["examples/**/*", "tests/**/*", "src/sahya_code/deps/**/*"]
57
+
58
+ [tool.uv.workspace]
59
+ members = [
60
+ "packages/kosong",
61
+ "packages/kaos",
62
+ "packages/kimi-code",
63
+ "sdks/kimi-sdk",
64
+ ]
65
+
66
+ [tool.uv.sources]
67
+ kosong = { workspace = true }
68
+ pykaos = { workspace = true }
69
+ sahya-code = { workspace = true }
70
+
71
+ [project.scripts]
72
+ sahya = "sahya_code.__main__:main"
73
+ sahya-code = "sahya_code.__main__:main"
74
+
75
+ [tool.ruff]
76
+ line-length = 100
77
+
78
+ [tool.ruff.lint]
79
+ select = [
80
+ "E",
81
+ "F",
82
+ "UP",
83
+ "B",
84
+ "SIM",
85
+ "I",
86
+ ]
87
+
88
+ [tool.ruff.lint.per-file-ignores]
89
+ "tests/**/*.py" = ["E501"]
90
+ "tests_e2e/**/*.py" = ["E501"]
91
+ "src/sahya_code/web/api/**/*.py" = ["B008"]
92
+
93
+ [tool.pyright]
94
+ typeCheckingMode = "standard"
95
+ pythonVersion = "3.14"
96
+ include = [
97
+ "src/**/*.py",
98
+ "tests/**/*.py",
99
+ "tests_ai/scripts/**/*.py",
100
+ "tests_e2e/**/*.py",
101
+ ]
102
+ strict = ["src/sahya_code/**/*.py"]
103
+
104
+ [tool.ty.environment]
105
+ python-version = "3.14"
106
+
107
+ [tool.ty.src]
108
+ include = [
109
+ "src/**/*.py",
110
+ "tests/**/*.py",
111
+ "tests_ai/scripts/**/*.py",
112
+ "tests_e2e/**/*.py",
113
+ ]
114
+
115
+ [tool.typos.files]
116
+ extend-exclude = ["kimi.spec", "pyinstaller.py"]
117
+
118
+ [tool.typos.default.extend-words]
119
+ datas = "datas"
120
+ Seeked = "Seeked"
121
+ seeked = "seeked"
122
+ iterm = "iterm"
@@ -0,0 +1,108 @@
1
+ # Changelog
2
+
3
+ All notable changes to Sahya Code will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ## [1.0.0] - 2026-04-01
9
+
10
+ ### Added
11
+ - Initial release based on kimi-cli v1.28.0
12
+ - Custom LiteLLM endpoint support (https://llm.nexiant.ai)
13
+ - API key authentication via SAHYA_API_KEY environment variable
14
+ - Full rebranding from Kimi Code CLI to Sahya Code
15
+ - Pre-configured OpenAI-compatible provider for LiteLLM proxy
16
+ - Support for SAHYA_BASE_URL environment variable
17
+
18
+ ### Changed
19
+ - **Package name:** `kimi-cli` → `sahya-code`
20
+ - **Module name:** `kimi_cli` → `sahya_code`
21
+ - **CLI command:** `kimi` → `sahya`
22
+ - **Config directory:** `~/.local/share/kimi` → `~/.local/share/sahya-code`
23
+ - **Log file:** `kimi.log` → `sahya.log`
24
+ - **Environment variable prefix:** `KIMI_*` → `SAHYA_*`
25
+ - **Main class:** `KimiCLI` → `SahyaCode`
26
+ - **Soul class:** `KimiSoul` → `SahyaSoul`
27
+ - **User agent:** `KimiCLI/*` → `SahyaCode/*`
28
+ - **Application name:** "Kimi Code CLI" → "Sahya Code"
29
+
30
+ ### Configuration
31
+
32
+ #### Default Provider
33
+ - Type: `openai_legacy` (OpenAI-compatible API for LiteLLM)
34
+ - Endpoint: `https://llm.nexiant.ai`
35
+ - Default Model: `kimi-k2.5`
36
+ - Authentication: API key via `SAHYA_API_KEY`
37
+
38
+ #### Environment Variables
39
+ - `SAHYA_API_KEY` - API key for authentication (required)
40
+ - `SAHYA_BASE_URL` - Endpoint URL override (optional)
41
+ - `SAHYA_SHARE_DIR` - Custom share directory (optional)
42
+ - `SAHYA_CACHE_DIR` - Custom cache directory (optional)
43
+
44
+ #### Config File Location
45
+ - Default: `~/.local/share/sahya-code/config.toml`
46
+ - Format: TOML (JSON also supported)
47
+
48
+ ### Removed
49
+ - Kimi-specific default configurations
50
+ - Moonshot AI-specific provider defaults
51
+ - Kimi-specific environment variable fallbacks
52
+
53
+ ### Dependencies
54
+ Same as kimi-cli v1.28.0:
55
+ - Python >= 3.12
56
+ - kosong[contrib] == 0.47.0
57
+ - pydantic == 2.12.5
58
+ - typer == 0.21.1
59
+ - And other dependencies (see pyproject.toml)
60
+
61
+ ## Original kimi-cli History
62
+
63
+ For complete history of the original project, see:
64
+ https://github.com/MoonshotAI/kimi-cli/blob/main/CHANGELOG.md
65
+
66
+ ---
67
+
68
+ ## Migration Guide
69
+
70
+ ### From kimi-cli to sahya-code
71
+
72
+ 1. **Uninstall kimi-cli:**
73
+ ```bash
74
+ pip uninstall kimi-cli
75
+ ```
76
+
77
+ 2. **Install sahya-code:**
78
+ ```bash
79
+ pip install sahya-code
80
+ ```
81
+
82
+ 3. **Update environment variables:**
83
+ ```bash
84
+ # Old
85
+ export KIMI_API_KEY="..."
86
+
87
+ # New
88
+ export SAHYA_API_KEY="..."
89
+ ```
90
+
91
+ 4. **Migrate configuration:**
92
+ ```bash
93
+ # Copy old config (optional)
94
+ mkdir -p ~/.local/share/sahya-code
95
+ cp ~/.local/share/kimi/config.toml ~/.local/share/sahya-code/config.toml
96
+
97
+ # Update config values
98
+ sed -i '' 's/kimi/sahya/g' ~/.local/share/sahya-code/config.toml
99
+ ```
100
+
101
+ 5. **Update aliases:**
102
+ ```bash
103
+ # Old
104
+ alias ai='kimi'
105
+
106
+ # New
107
+ alias ai='sahya'
108
+ ```
@@ -0,0 +1,29 @@
1
+ from __future__ import annotations
2
+
3
+ from typing import Any, cast
4
+
5
+
6
+ class _LazyLogger:
7
+ """Import loguru only when logging is actually used."""
8
+
9
+ def __init__(self) -> None:
10
+ self._logger: Any | None = None
11
+
12
+ def _get(self) -> Any:
13
+ if self._logger is None:
14
+ from loguru import logger as real_logger
15
+
16
+ # Disable logging by default for library usage.
17
+ # Application entry points (e.g., sahya_code.cli) should call logger.enable("sahya_code")
18
+ # to enable logging.
19
+ real_logger.disable("sahya_code")
20
+ self._logger = real_logger
21
+ return self._logger
22
+
23
+ def __getattr__(self, name: str) -> Any:
24
+ return getattr(self._get(), name)
25
+
26
+
27
+ logger = cast(Any, _LazyLogger())
28
+
29
+ __all__ = ["logger"]
@@ -0,0 +1,30 @@
1
+ from __future__ import annotations
2
+
3
+ import sys
4
+ from collections.abc import Sequence
5
+ from pathlib import Path
6
+
7
+
8
+ def _prog_name() -> str:
9
+ return Path(sys.argv[0]).name or "sahya"
10
+
11
+
12
+ def main(argv: Sequence[str] | None = None) -> int | str | None:
13
+ args = list(sys.argv[1:] if argv is None else argv)
14
+
15
+ if len(args) == 1 and args[0] in {"--version", "-V"}:
16
+ from sahya_code.constant import get_version
17
+
18
+ print(f"sahya, version {get_version()}")
19
+ return 0
20
+
21
+ from sahya_code.cli import cli
22
+
23
+ try:
24
+ return cli(args=args, prog_name=_prog_name())
25
+ except SystemExit as exc:
26
+ return exc.code
27
+
28
+
29
+ if __name__ == "__main__":
30
+ raise SystemExit(main())
@@ -0,0 +1,92 @@
1
+ # ACP Integration Notes (kimi-cli)
2
+
3
+ ## Protocol summary (ACP overview)
4
+ - ACP is JSON-RPC 2.0 with request/response methods plus one-way notifications.
5
+ - Typical flow: `initialize` -> optional `authenticate` -> `session/new` or `session/load`
6
+ -> `session/prompt`
7
+ with `session/update` notifications and optional `session/cancel`.
8
+ - Clients provide `session/request_permission` and optional terminal/filesystem methods.
9
+ - All ACP file paths must be absolute; line numbers are 1-based.
10
+
11
+ ## Entry points and server modes
12
+ - **Single-session server**: `KimiCLI.run_acp()` uses `ACP` -> `ACPServerSingleSession`.
13
+ - Code: `src/kimi_cli/app.py`, `src/kimi_cli/ui/acp/__init__.py`.
14
+ - Used when running CLI with `--acp` UI mode.
15
+ - **Multi-session server**: `acp_main()` runs `ACPServer` with `use_unstable_protocol=True`.
16
+ - Code: `src/kimi_cli/acp/__init__.py`, `src/kimi_cli/acp/server.py`.
17
+ - Exposed via the `kimi acp` command in `src/kimi_cli/cli/__init__.py`.
18
+
19
+ ## Capabilities advertised
20
+ - `prompt_capabilities`: `embedded_context=False`, `image=True`, `audio=False`.
21
+ - `mcp_capabilities`: `http=True`, `sse=False`.
22
+ - Single-session: `load_session=False`, no session list capabilities.
23
+ - Multi-session: `load_session=True`, `session_capabilities.list` supported.
24
+ - `auth_methods=[]` (no authentication methods advertised).
25
+
26
+ ## Session lifecycle (implemented behavior)
27
+ - `session/new`
28
+ - Multi-session: creates a persisted `Session`, builds `KimiCLI`, stores `ACPSession`.
29
+ - Single-session: wraps the existing `Soul` into a `Wire` loop and creates `ACPSession`.
30
+ - Both send `AvailableCommandsUpdate` for slash commands on session creation.
31
+ - MCP servers passed by ACP are converted via `acp_mcp_servers_to_mcp_config`.
32
+ - `session/load`
33
+ - Multi-session only: loads by `Session.find`, then builds `KimiCLI` and `ACPSession`.
34
+ - No history replay yet (TODO).
35
+ - Single-session: not implemented.
36
+ - `session/list`
37
+ - Multi-session only: lists sessions via `Session.list`, no pagination.
38
+ - Single-session: not implemented.
39
+ - `session/prompt`
40
+ - Uses `ACPSession.prompt()` to stream updates and produce a `stop_reason`.
41
+ - Stop reasons: `end_turn`, `max_turn_requests`, `cancelled`.
42
+ - `session/cancel`
43
+ - Sets the per-turn cancel event to stop the prompt.
44
+
45
+ ## Streaming updates and content mapping
46
+ - Text chunks -> `AgentMessageChunk`.
47
+ - Think chunks -> `AgentThoughtChunk`.
48
+ - Tool calls:
49
+ - Start -> `ToolCallStart` with JSON args as text content.
50
+ - Streaming args -> `ToolCallProgress` with updated title/args.
51
+ - Results -> `ToolCallProgress` with `completed` or `failed`.
52
+ - Tool call IDs are prefixed with turn ID to avoid collisions across turns.
53
+ - Plan updates:
54
+ - `TodoDisplayBlock` is converted into `AgentPlanUpdate`.
55
+ - Available commands:
56
+ - `AvailableCommandsUpdate` is sent right after session creation.
57
+
58
+ ## Prompt/content conversion
59
+ - Incoming prompt blocks:
60
+ - Supported: `TextContentBlock`, `ImageContentBlock` (converted to data URL).
61
+ - Unsupported types are logged and ignored.
62
+ - Tool result display blocks:
63
+ - `DiffDisplayBlock` -> `FileEditToolCallContent`.
64
+ - `HideOutputDisplayBlock` suppresses tool output in ACP (used by terminal tool).
65
+
66
+ ## Tool integration and permission flow
67
+ - ACP sessions use `ACPKaos` to route filesystem reads/writes through ACP clients.
68
+ - If the client advertises `terminal` capability, the `Shell` tool is replaced by an
69
+ ACP-backed `Terminal` tool.
70
+ - Uses ACP `terminal/create`, waits for exit, streams `TerminalToolCallContent`,
71
+ then releases the terminal handle.
72
+ - Approval requests in the core tool system are bridged to ACP
73
+ `session/request_permission` with allow-once/allow-always/reject options.
74
+
75
+ ## Current gaps / not implemented
76
+ - `authenticate` method (not used by current Zed ACP client).
77
+ - `session/set_mode` and `session/set_model` (no multi-mode/model switching in kimi-cli).
78
+ - `ext_method` / `ext_notification` for custom ACP extensions are stubbed.
79
+ - Single-session server does not implement `session/load` or `session/list`.
80
+
81
+ ## Filesystem (ACP client-backed)
82
+ - When the client advertises `fs.readTextFile` / `fs.writeTextFile`, `ACPKaos` routes
83
+ reads and writes through ACP `fs/*` methods.
84
+ - `ReadFile` uses `KaosPath.read_lines`, which `ACPKaos` implements via ACP reads.
85
+ - `ReadMediaFile` uses `KaosPath.read_bytes` to load image/video payloads through ACP reads.
86
+ - `WriteFile` uses `KaosPath.read_text/write_text/append_text` and still generates diffs
87
+ and approvals in the tool layer.
88
+
89
+ ## Zed-specific notes (as of current integration)
90
+ - Zed does not currently call `authenticate`.
91
+ - Zed’s external agent server session management is not yet available, so
92
+ `session/load` is not exercised in practice.
@@ -0,0 +1,13 @@
1
+ def acp_main() -> None:
2
+ """Entry point for the multi-session ACP server."""
3
+ import asyncio
4
+
5
+ import acp
6
+
7
+ from sahya_code.acp.server import ACPServer
8
+ from sahya_code.app import enable_logging
9
+ from sahya_code.utils.logging import logger
10
+
11
+ enable_logging()
12
+ logger.info("Starting ACP server on stdio")
13
+ asyncio.run(acp.run_agent(ACPServer(), use_unstable_protocol=True))