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.
- sahya_code-1.0.0/PKG-INFO +158 -0
- sahya_code-1.0.0/README.md +122 -0
- sahya_code-1.0.0/pyproject.toml +122 -0
- sahya_code-1.0.0/src/sahya_code/CHANGELOG.md +108 -0
- sahya_code-1.0.0/src/sahya_code/__init__.py +29 -0
- sahya_code-1.0.0/src/sahya_code/__main__.py +30 -0
- sahya_code-1.0.0/src/sahya_code/acp/AGENTS.md +92 -0
- sahya_code-1.0.0/src/sahya_code/acp/__init__.py +13 -0
- sahya_code-1.0.0/src/sahya_code/acp/convert.py +128 -0
- sahya_code-1.0.0/src/sahya_code/acp/kaos.py +291 -0
- sahya_code-1.0.0/src/sahya_code/acp/mcp.py +46 -0
- sahya_code-1.0.0/src/sahya_code/acp/server.py +457 -0
- sahya_code-1.0.0/src/sahya_code/acp/session.py +496 -0
- sahya_code-1.0.0/src/sahya_code/acp/tools.py +167 -0
- sahya_code-1.0.0/src/sahya_code/acp/types.py +13 -0
- sahya_code-1.0.0/src/sahya_code/acp/version.py +45 -0
- sahya_code-1.0.0/src/sahya_code/agents/default/agent.yaml +36 -0
- sahya_code-1.0.0/src/sahya_code/agents/default/coder.yaml +25 -0
- sahya_code-1.0.0/src/sahya_code/agents/default/explore.yaml +46 -0
- sahya_code-1.0.0/src/sahya_code/agents/default/plan.yaml +30 -0
- sahya_code-1.0.0/src/sahya_code/agents/default/system.md +160 -0
- sahya_code-1.0.0/src/sahya_code/agents/okabe/agent.yaml +22 -0
- sahya_code-1.0.0/src/sahya_code/agentspec.py +160 -0
- sahya_code-1.0.0/src/sahya_code/app.py +540 -0
- sahya_code-1.0.0/src/sahya_code/approval_runtime/__init__.py +29 -0
- sahya_code-1.0.0/src/sahya_code/approval_runtime/models.py +42 -0
- sahya_code-1.0.0/src/sahya_code/approval_runtime/runtime.py +189 -0
- sahya_code-1.0.0/src/sahya_code/auth/__init__.py +5 -0
- sahya_code-1.0.0/src/sahya_code/auth/oauth.py +804 -0
- sahya_code-1.0.0/src/sahya_code/auth/platforms.py +293 -0
- sahya_code-1.0.0/src/sahya_code/background/__init__.py +36 -0
- sahya_code-1.0.0/src/sahya_code/background/agent_runner.py +209 -0
- sahya_code-1.0.0/src/sahya_code/background/ids.py +19 -0
- sahya_code-1.0.0/src/sahya_code/background/manager.py +580 -0
- sahya_code-1.0.0/src/sahya_code/background/models.py +105 -0
- sahya_code-1.0.0/src/sahya_code/background/store.py +196 -0
- sahya_code-1.0.0/src/sahya_code/background/summary.py +66 -0
- sahya_code-1.0.0/src/sahya_code/background/worker.py +209 -0
- sahya_code-1.0.0/src/sahya_code/cli/__init__.py +932 -0
- sahya_code-1.0.0/src/sahya_code/cli/__main__.py +8 -0
- sahya_code-1.0.0/src/sahya_code/cli/_lazy_group.py +222 -0
- sahya_code-1.0.0/src/sahya_code/cli/export.py +74 -0
- sahya_code-1.0.0/src/sahya_code/cli/info.py +62 -0
- sahya_code-1.0.0/src/sahya_code/cli/mcp.py +349 -0
- sahya_code-1.0.0/src/sahya_code/cli/plugin.py +302 -0
- sahya_code-1.0.0/src/sahya_code/cli/toad.py +73 -0
- sahya_code-1.0.0/src/sahya_code/cli/vis.py +38 -0
- sahya_code-1.0.0/src/sahya_code/cli/web.py +80 -0
- sahya_code-1.0.0/src/sahya_code/config.py +391 -0
- sahya_code-1.0.0/src/sahya_code/constant.py +33 -0
- sahya_code-1.0.0/src/sahya_code/exception.py +43 -0
- sahya_code-1.0.0/src/sahya_code/hooks/__init__.py +4 -0
- sahya_code-1.0.0/src/sahya_code/hooks/config.py +34 -0
- sahya_code-1.0.0/src/sahya_code/hooks/engine.py +310 -0
- sahya_code-1.0.0/src/sahya_code/hooks/events.py +190 -0
- sahya_code-1.0.0/src/sahya_code/hooks/runner.py +89 -0
- sahya_code-1.0.0/src/sahya_code/llm.py +306 -0
- sahya_code-1.0.0/src/sahya_code/metadata.py +79 -0
- sahya_code-1.0.0/src/sahya_code/notifications/__init__.py +33 -0
- sahya_code-1.0.0/src/sahya_code/notifications/llm.py +77 -0
- sahya_code-1.0.0/src/sahya_code/notifications/manager.py +145 -0
- sahya_code-1.0.0/src/sahya_code/notifications/models.py +50 -0
- sahya_code-1.0.0/src/sahya_code/notifications/notifier.py +41 -0
- sahya_code-1.0.0/src/sahya_code/notifications/store.py +99 -0
- sahya_code-1.0.0/src/sahya_code/notifications/wire.py +21 -0
- sahya_code-1.0.0/src/sahya_code/plugin/__init__.py +124 -0
- sahya_code-1.0.0/src/sahya_code/plugin/manager.py +153 -0
- sahya_code-1.0.0/src/sahya_code/plugin/tool.py +173 -0
- sahya_code-1.0.0/src/sahya_code/prompts/__init__.py +6 -0
- sahya_code-1.0.0/src/sahya_code/prompts/compact.md +73 -0
- sahya_code-1.0.0/src/sahya_code/prompts/init.md +21 -0
- sahya_code-1.0.0/src/sahya_code/py.typed +0 -0
- sahya_code-1.0.0/src/sahya_code/session.py +293 -0
- sahya_code-1.0.0/src/sahya_code/session_state.py +42 -0
- sahya_code-1.0.0/src/sahya_code/share.py +28 -0
- sahya_code-1.0.0/src/sahya_code/skill/__init__.py +311 -0
- sahya_code-1.0.0/src/sahya_code/skill/flow/__init__.py +99 -0
- sahya_code-1.0.0/src/sahya_code/skill/flow/d2.py +482 -0
- sahya_code-1.0.0/src/sahya_code/skill/flow/mermaid.py +266 -0
- sahya_code-1.0.0/src/sahya_code/skills/kimi-cli-help/SKILL.md +55 -0
- sahya_code-1.0.0/src/sahya_code/skills/skill-creator/SKILL.md +367 -0
- sahya_code-1.0.0/src/sahya_code/soul/__init__.py +288 -0
- sahya_code-1.0.0/src/sahya_code/soul/agent.py +423 -0
- sahya_code-1.0.0/src/sahya_code/soul/approval.py +171 -0
- sahya_code-1.0.0/src/sahya_code/soul/compaction.py +189 -0
- sahya_code-1.0.0/src/sahya_code/soul/context.py +239 -0
- sahya_code-1.0.0/src/sahya_code/soul/denwarenji.py +39 -0
- sahya_code-1.0.0/src/sahya_code/soul/dynamic_injection.py +66 -0
- sahya_code-1.0.0/src/sahya_code/soul/dynamic_injections/__init__.py +0 -0
- sahya_code-1.0.0/src/sahya_code/soul/dynamic_injections/plan_mode.py +238 -0
- sahya_code-1.0.0/src/sahya_code/soul/dynamic_injections/yolo_mode.py +41 -0
- sahya_code-1.0.0/src/sahya_code/soul/message.py +92 -0
- sahya_code-1.0.0/src/sahya_code/soul/sahyasoul.py +1220 -0
- sahya_code-1.0.0/src/sahya_code/soul/slash.py +285 -0
- sahya_code-1.0.0/src/sahya_code/soul/toolset.py +610 -0
- sahya_code-1.0.0/src/sahya_code/subagents/__init__.py +21 -0
- sahya_code-1.0.0/src/sahya_code/subagents/builder.py +42 -0
- sahya_code-1.0.0/src/sahya_code/subagents/core.py +86 -0
- sahya_code-1.0.0/src/sahya_code/subagents/git_context.py +170 -0
- sahya_code-1.0.0/src/sahya_code/subagents/models.py +54 -0
- sahya_code-1.0.0/src/sahya_code/subagents/output.py +71 -0
- sahya_code-1.0.0/src/sahya_code/subagents/registry.py +28 -0
- sahya_code-1.0.0/src/sahya_code/subagents/runner.py +370 -0
- sahya_code-1.0.0/src/sahya_code/subagents/store.py +148 -0
- sahya_code-1.0.0/src/sahya_code/tools/AGENTS.md +5 -0
- sahya_code-1.0.0/src/sahya_code/tools/__init__.py +105 -0
- sahya_code-1.0.0/src/sahya_code/tools/agent/__init__.py +276 -0
- sahya_code-1.0.0/src/sahya_code/tools/agent/description.md +41 -0
- sahya_code-1.0.0/src/sahya_code/tools/ask_user/__init__.py +154 -0
- sahya_code-1.0.0/src/sahya_code/tools/ask_user/description.md +19 -0
- sahya_code-1.0.0/src/sahya_code/tools/background/__init__.py +318 -0
- sahya_code-1.0.0/src/sahya_code/tools/background/list.md +10 -0
- sahya_code-1.0.0/src/sahya_code/tools/background/output.md +11 -0
- sahya_code-1.0.0/src/sahya_code/tools/background/stop.md +8 -0
- sahya_code-1.0.0/src/sahya_code/tools/display.py +46 -0
- sahya_code-1.0.0/src/sahya_code/tools/dmail/__init__.py +38 -0
- sahya_code-1.0.0/src/sahya_code/tools/dmail/dmail.md +17 -0
- sahya_code-1.0.0/src/sahya_code/tools/file/__init__.py +30 -0
- sahya_code-1.0.0/src/sahya_code/tools/file/glob.md +17 -0
- sahya_code-1.0.0/src/sahya_code/tools/file/glob.py +156 -0
- sahya_code-1.0.0/src/sahya_code/tools/file/grep.md +5 -0
- sahya_code-1.0.0/src/sahya_code/tools/file/grep_local.py +524 -0
- sahya_code-1.0.0/src/sahya_code/tools/file/plan_mode.py +45 -0
- sahya_code-1.0.0/src/sahya_code/tools/file/read.md +14 -0
- sahya_code-1.0.0/src/sahya_code/tools/file/read.py +189 -0
- sahya_code-1.0.0/src/sahya_code/tools/file/read_media.md +24 -0
- sahya_code-1.0.0/src/sahya_code/tools/file/read_media.py +215 -0
- sahya_code-1.0.0/src/sahya_code/tools/file/replace.md +7 -0
- sahya_code-1.0.0/src/sahya_code/tools/file/replace.py +193 -0
- sahya_code-1.0.0/src/sahya_code/tools/file/utils.py +257 -0
- sahya_code-1.0.0/src/sahya_code/tools/file/write.md +5 -0
- sahya_code-1.0.0/src/sahya_code/tools/file/write.py +175 -0
- sahya_code-1.0.0/src/sahya_code/tools/plan/__init__.py +325 -0
- sahya_code-1.0.0/src/sahya_code/tools/plan/description.md +25 -0
- sahya_code-1.0.0/src/sahya_code/tools/plan/enter.py +183 -0
- sahya_code-1.0.0/src/sahya_code/tools/plan/enter_description.md +30 -0
- sahya_code-1.0.0/src/sahya_code/tools/plan/heroes.py +277 -0
- sahya_code-1.0.0/src/sahya_code/tools/shell/__init__.py +235 -0
- sahya_code-1.0.0/src/sahya_code/tools/shell/bash.md +35 -0
- sahya_code-1.0.0/src/sahya_code/tools/shell/powershell.md +30 -0
- sahya_code-1.0.0/src/sahya_code/tools/test.py +55 -0
- sahya_code-1.0.0/src/sahya_code/tools/think/__init__.py +21 -0
- sahya_code-1.0.0/src/sahya_code/tools/think/think.md +1 -0
- sahya_code-1.0.0/src/sahya_code/tools/todo/__init__.py +33 -0
- sahya_code-1.0.0/src/sahya_code/tools/todo/set_todo_list.md +15 -0
- sahya_code-1.0.0/src/sahya_code/tools/utils.py +199 -0
- sahya_code-1.0.0/src/sahya_code/tools/web/__init__.py +4 -0
- sahya_code-1.0.0/src/sahya_code/tools/web/fetch.md +1 -0
- sahya_code-1.0.0/src/sahya_code/tools/web/fetch.py +173 -0
- sahya_code-1.0.0/src/sahya_code/tools/web/search.md +1 -0
- sahya_code-1.0.0/src/sahya_code/tools/web/search.py +146 -0
- sahya_code-1.0.0/src/sahya_code/ui/__init__.py +0 -0
- sahya_code-1.0.0/src/sahya_code/ui/acp/__init__.py +99 -0
- sahya_code-1.0.0/src/sahya_code/ui/print/__init__.py +167 -0
- sahya_code-1.0.0/src/sahya_code/ui/print/visualize.py +185 -0
- sahya_code-1.0.0/src/sahya_code/ui/shell/__init__.py +991 -0
- sahya_code-1.0.0/src/sahya_code/ui/shell/approval_panel.py +481 -0
- sahya_code-1.0.0/src/sahya_code/ui/shell/console.py +105 -0
- sahya_code-1.0.0/src/sahya_code/ui/shell/debug.py +190 -0
- sahya_code-1.0.0/src/sahya_code/ui/shell/echo.py +17 -0
- sahya_code-1.0.0/src/sahya_code/ui/shell/export_import.py +111 -0
- sahya_code-1.0.0/src/sahya_code/ui/shell/keyboard.py +300 -0
- sahya_code-1.0.0/src/sahya_code/ui/shell/mcp_status.py +111 -0
- sahya_code-1.0.0/src/sahya_code/ui/shell/oauth.py +143 -0
- sahya_code-1.0.0/src/sahya_code/ui/shell/placeholders.py +530 -0
- sahya_code-1.0.0/src/sahya_code/ui/shell/prompt.py +2124 -0
- sahya_code-1.0.0/src/sahya_code/ui/shell/question_panel.py +586 -0
- sahya_code-1.0.0/src/sahya_code/ui/shell/replay.py +210 -0
- sahya_code-1.0.0/src/sahya_code/ui/shell/setup.py +212 -0
- sahya_code-1.0.0/src/sahya_code/ui/shell/slash.py +716 -0
- sahya_code-1.0.0/src/sahya_code/ui/shell/startup.py +32 -0
- sahya_code-1.0.0/src/sahya_code/ui/shell/task_browser.py +486 -0
- sahya_code-1.0.0/src/sahya_code/ui/shell/update.py +217 -0
- sahya_code-1.0.0/src/sahya_code/ui/shell/usage.py +281 -0
- sahya_code-1.0.0/src/sahya_code/ui/shell/visualize.py +1497 -0
- sahya_code-1.0.0/src/sahya_code/ui/theme.py +238 -0
- sahya_code-1.0.0/src/sahya_code/utils/__init__.py +0 -0
- sahya_code-1.0.0/src/sahya_code/utils/aiohttp.py +24 -0
- sahya_code-1.0.0/src/sahya_code/utils/aioqueue.py +72 -0
- sahya_code-1.0.0/src/sahya_code/utils/broadcast.py +37 -0
- sahya_code-1.0.0/src/sahya_code/utils/changelog.py +108 -0
- sahya_code-1.0.0/src/sahya_code/utils/clipboard.py +169 -0
- sahya_code-1.0.0/src/sahya_code/utils/datetime.py +37 -0
- sahya_code-1.0.0/src/sahya_code/utils/diff.py +135 -0
- sahya_code-1.0.0/src/sahya_code/utils/editor.py +91 -0
- sahya_code-1.0.0/src/sahya_code/utils/environment.py +58 -0
- sahya_code-1.0.0/src/sahya_code/utils/envvar.py +12 -0
- sahya_code-1.0.0/src/sahya_code/utils/export.py +696 -0
- sahya_code-1.0.0/src/sahya_code/utils/frontmatter.py +50 -0
- sahya_code-1.0.0/src/sahya_code/utils/io.py +27 -0
- sahya_code-1.0.0/src/sahya_code/utils/logging.py +124 -0
- sahya_code-1.0.0/src/sahya_code/utils/media_tags.py +29 -0
- sahya_code-1.0.0/src/sahya_code/utils/message.py +24 -0
- sahya_code-1.0.0/src/sahya_code/utils/path.py +140 -0
- sahya_code-1.0.0/src/sahya_code/utils/proctitle.py +33 -0
- sahya_code-1.0.0/src/sahya_code/utils/pyinstaller.py +32 -0
- sahya_code-1.0.0/src/sahya_code/utils/rich/__init__.py +33 -0
- sahya_code-1.0.0/src/sahya_code/utils/rich/columns.py +99 -0
- sahya_code-1.0.0/src/sahya_code/utils/rich/diff_render.py +436 -0
- sahya_code-1.0.0/src/sahya_code/utils/rich/markdown.py +900 -0
- sahya_code-1.0.0/src/sahya_code/utils/rich/markdown_sample.md +108 -0
- sahya_code-1.0.0/src/sahya_code/utils/rich/markdown_sample_short.md +2 -0
- sahya_code-1.0.0/src/sahya_code/utils/rich/syntax.py +114 -0
- sahya_code-1.0.0/src/sahya_code/utils/server.py +121 -0
- sahya_code-1.0.0/src/sahya_code/utils/signals.py +43 -0
- sahya_code-1.0.0/src/sahya_code/utils/slashcmd.py +124 -0
- sahya_code-1.0.0/src/sahya_code/utils/string.py +22 -0
- sahya_code-1.0.0/src/sahya_code/utils/subprocess_env.py +73 -0
- sahya_code-1.0.0/src/sahya_code/utils/term.py +168 -0
- sahya_code-1.0.0/src/sahya_code/utils/typing.py +20 -0
- sahya_code-1.0.0/src/sahya_code/vis/__init__.py +0 -0
- sahya_code-1.0.0/src/sahya_code/vis/api/__init__.py +5 -0
- sahya_code-1.0.0/src/sahya_code/vis/api/sessions.py +692 -0
- sahya_code-1.0.0/src/sahya_code/vis/api/statistics.py +209 -0
- sahya_code-1.0.0/src/sahya_code/vis/api/system.py +19 -0
- sahya_code-1.0.0/src/sahya_code/vis/app.py +175 -0
- sahya_code-1.0.0/src/sahya_code/web/__init__.py +5 -0
- sahya_code-1.0.0/src/sahya_code/web/api/__init__.py +15 -0
- sahya_code-1.0.0/src/sahya_code/web/api/config.py +208 -0
- sahya_code-1.0.0/src/sahya_code/web/api/open_in.py +197 -0
- sahya_code-1.0.0/src/sahya_code/web/api/sessions.py +1392 -0
- sahya_code-1.0.0/src/sahya_code/web/app.py +412 -0
- sahya_code-1.0.0/src/sahya_code/web/auth.py +191 -0
- sahya_code-1.0.0/src/sahya_code/web/models.py +98 -0
- sahya_code-1.0.0/src/sahya_code/web/runner/__init__.py +5 -0
- sahya_code-1.0.0/src/sahya_code/web/runner/messages.py +57 -0
- sahya_code-1.0.0/src/sahya_code/web/runner/process.py +745 -0
- sahya_code-1.0.0/src/sahya_code/web/runner/worker.py +87 -0
- sahya_code-1.0.0/src/sahya_code/web/store/__init__.py +1 -0
- sahya_code-1.0.0/src/sahya_code/web/store/sessions.py +517 -0
- sahya_code-1.0.0/src/sahya_code/wire/__init__.py +148 -0
- sahya_code-1.0.0/src/sahya_code/wire/file.py +151 -0
- sahya_code-1.0.0/src/sahya_code/wire/jsonrpc.py +263 -0
- sahya_code-1.0.0/src/sahya_code/wire/protocol.py +2 -0
- sahya_code-1.0.0/src/sahya_code/wire/root_hub.py +27 -0
- sahya_code-1.0.0/src/sahya_code/wire/serde.py +26 -0
- sahya_code-1.0.0/src/sahya_code/wire/server.py +1029 -0
- 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))
|