k-cli-for-devs 1.0.0__tar.gz → 1.0.1__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 (137) hide show
  1. {k_cli_for_devs-1.0.0/k_cli_for_devs.egg-info → k_cli_for_devs-1.0.1}/PKG-INFO +22 -3
  2. {k_cli_for_devs-1.0.0 → k_cli_for_devs-1.0.1}/README.md +21 -2
  3. k_cli_for_devs-1.0.1/k_cli/agents/autonomous_agent.py +539 -0
  4. {k_cli_for_devs-1.0.0 → k_cli_for_devs-1.0.1}/k_cli/ui/simple_repl.py +10 -13
  5. {k_cli_for_devs-1.0.0 → k_cli_for_devs-1.0.1}/k_cli/web/server.py +23 -82
  6. {k_cli_for_devs-1.0.0 → k_cli_for_devs-1.0.1/k_cli_for_devs.egg-info}/PKG-INFO +22 -3
  7. {k_cli_for_devs-1.0.0 → k_cli_for_devs-1.0.1}/k_cli_for_devs.egg-info/SOURCES.txt +2 -0
  8. {k_cli_for_devs-1.0.0 → k_cli_for_devs-1.0.1}/pyproject.toml +1 -1
  9. k_cli_for_devs-1.0.1/tests/test_autonomous_agent.py +60 -0
  10. {k_cli_for_devs-1.0.0 → k_cli_for_devs-1.0.1}/LICENSE +0 -0
  11. {k_cli_for_devs-1.0.0 → k_cli_for_devs-1.0.1}/MANIFEST.in +0 -0
  12. {k_cli_for_devs-1.0.0 → k_cli_for_devs-1.0.1}/k_cli/__init__.py +0 -0
  13. {k_cli_for_devs-1.0.0 → k_cli_for_devs-1.0.1}/k_cli/agents/__init__.py +0 -0
  14. {k_cli_for_devs-1.0.0 → k_cli_for_devs-1.0.1}/k_cli/agents/adversarial_swarm.py +0 -0
  15. {k_cli_for_devs-1.0.0 → k_cli_for_devs-1.0.1}/k_cli/agents/agent_core.py +0 -0
  16. {k_cli_for_devs-1.0.0 → k_cli_for_devs-1.0.1}/k_cli/agents/background_daemon.py +0 -0
  17. {k_cli_for_devs-1.0.0 → k_cli_for_devs-1.0.1}/k_cli/agents/orchestrator.py +0 -0
  18. {k_cli_for_devs-1.0.0 → k_cli_for_devs-1.0.1}/k_cli/agents/persona.py +0 -0
  19. {k_cli_for_devs-1.0.0 → k_cli_for_devs-1.0.1}/k_cli/agents/scaffold_engine.py +0 -0
  20. {k_cli_for_devs-1.0.0 → k_cli_for_devs-1.0.1}/k_cli/agents/strands_agent.py +0 -0
  21. {k_cli_for_devs-1.0.0 → k_cli_for_devs-1.0.1}/k_cli/agents/subagents.py +0 -0
  22. {k_cli_for_devs-1.0.0 → k_cli_for_devs-1.0.1}/k_cli/cli.py +0 -0
  23. {k_cli_for_devs-1.0.0 → k_cli_for_devs-1.0.1}/k_cli/core/__init__.py +0 -0
  24. {k_cli_for_devs-1.0.0 → k_cli_for_devs-1.0.1}/k_cli/core/airgap.py +0 -0
  25. {k_cli_for_devs-1.0.0 → k_cli_for_devs-1.0.1}/k_cli/core/credentials.py +0 -0
  26. {k_cli_for_devs-1.0.0 → k_cli_for_devs-1.0.1}/k_cli/core/intent_sensor.py +0 -0
  27. {k_cli_for_devs-1.0.0 → k_cli_for_devs-1.0.1}/k_cli/core/llm_driver.py +0 -0
  28. {k_cli_for_devs-1.0.0 → k_cli_for_devs-1.0.1}/k_cli/core/model_manager.py +0 -0
  29. {k_cli_for_devs-1.0.0 → k_cli_for_devs-1.0.1}/k_cli/core/models_hub.py +0 -0
  30. {k_cli_for_devs-1.0.0 → k_cli_for_devs-1.0.1}/k_cli/core/prompting.py +0 -0
  31. {k_cli_for_devs-1.0.0 → k_cli_for_devs-1.0.1}/k_cli/core/sdk.py +0 -0
  32. {k_cli_for_devs-1.0.0 → k_cli_for_devs-1.0.1}/k_cli/core/session.py +0 -0
  33. {k_cli_for_devs-1.0.0 → k_cli_for_devs-1.0.1}/k_cli/core/smart_router.py +0 -0
  34. {k_cli_for_devs-1.0.0 → k_cli_for_devs-1.0.1}/k_cli/core/storage_manager.py +0 -0
  35. {k_cli_for_devs-1.0.0 → k_cli_for_devs-1.0.1}/k_cli/core/viewport_engine.py +0 -0
  36. {k_cli_for_devs-1.0.0 → k_cli_for_devs-1.0.1}/k_cli/demo/demo_runner.py +0 -0
  37. {k_cli_for_devs-1.0.0 → k_cli_for_devs-1.0.1}/k_cli/git/__init__.py +0 -0
  38. {k_cli_for_devs-1.0.0 → k_cli_for_devs-1.0.1}/k_cli/git/ai_bisect.py +0 -0
  39. {k_cli_for_devs-1.0.0 → k_cli_for_devs-1.0.1}/k_cli/git/conflict_resolver.py +0 -0
  40. {k_cli_for_devs-1.0.0 → k_cli_for_devs-1.0.1}/k_cli/git/git_guard.py +0 -0
  41. {k_cli_for_devs-1.0.0 → k_cli_for_devs-1.0.1}/k_cli/git/patcher.py +0 -0
  42. {k_cli_for_devs-1.0.0 → k_cli_for_devs-1.0.1}/k_cli/git/repo_map.py +0 -0
  43. {k_cli_for_devs-1.0.0 → k_cli_for_devs-1.0.1}/k_cli/git/smart_git.py +0 -0
  44. {k_cli_for_devs-1.0.0 → k_cli_for_devs-1.0.1}/k_cli/git/verifier.py +0 -0
  45. {k_cli_for_devs-1.0.0 → k_cli_for_devs-1.0.1}/k_cli/github/__init__.py +0 -0
  46. {k_cli_for_devs-1.0.0 → k_cli_for_devs-1.0.1}/k_cli/github/dedup_engine.py +0 -0
  47. {k_cli_for_devs-1.0.0 → k_cli_for_devs-1.0.1}/k_cli/github/github_client.py +0 -0
  48. {k_cli_for_devs-1.0.0 → k_cli_for_devs-1.0.1}/k_cli/github/github_engine.py +0 -0
  49. {k_cli_for_devs-1.0.0 → k_cli_for_devs-1.0.1}/k_cli/github/local_hub.py +0 -0
  50. {k_cli_for_devs-1.0.0 → k_cli_for_devs-1.0.1}/k_cli/github/pr_watcher.py +0 -0
  51. {k_cli_for_devs-1.0.0 → k_cli_for_devs-1.0.1}/k_cli/github/trending.py +0 -0
  52. {k_cli_for_devs-1.0.0 → k_cli_for_devs-1.0.1}/k_cli/tools/__init__.py +0 -0
  53. {k_cli_for_devs-1.0.0 → k_cli_for_devs-1.0.1}/k_cli/tools/audit.py +0 -0
  54. {k_cli_for_devs-1.0.0 → k_cli_for_devs-1.0.1}/k_cli/tools/chaos_immunity.py +0 -0
  55. {k_cli_for_devs-1.0.0 → k_cli_for_devs-1.0.1}/k_cli/tools/codebase_qa.py +0 -0
  56. {k_cli_for_devs-1.0.0 → k_cli_for_devs-1.0.1}/k_cli/tools/command_runner.py +0 -0
  57. {k_cli_for_devs-1.0.0 → k_cli_for_devs-1.0.1}/k_cli/tools/diagram_generator.py +0 -0
  58. {k_cli_for_devs-1.0.0 → k_cli_for_devs-1.0.1}/k_cli/tools/doc_retriever.py +0 -0
  59. {k_cli_for_devs-1.0.0 → k_cli_for_devs-1.0.1}/k_cli/tools/feature.py +0 -0
  60. {k_cli_for_devs-1.0.0 → k_cli_for_devs-1.0.1}/k_cli/tools/ghost_daemon.py +0 -0
  61. {k_cli_for_devs-1.0.0 → k_cli_for_devs-1.0.1}/k_cli/tools/incident_triage.py +0 -0
  62. {k_cli_for_devs-1.0.0 → k_cli_for_devs-1.0.1}/k_cli/tools/mcp_client.py +0 -0
  63. {k_cli_for_devs-1.0.0 → k_cli_for_devs-1.0.1}/k_cli/tools/repo_gardener.py +0 -0
  64. {k_cli_for_devs-1.0.0 → k_cli_for_devs-1.0.1}/k_cli/tools/rules.py +0 -0
  65. {k_cli_for_devs-1.0.0 → k_cli_for_devs-1.0.1}/k_cli/tools/security.py +0 -0
  66. {k_cli_for_devs-1.0.0 → k_cli_for_devs-1.0.1}/k_cli/tools/security_healer.py +0 -0
  67. {k_cli_for_devs-1.0.0 → k_cli_for_devs-1.0.1}/k_cli/tools/synapse_graph.py +0 -0
  68. {k_cli_for_devs-1.0.0 → k_cli_for_devs-1.0.1}/k_cli/tui/__init__.py +0 -0
  69. {k_cli_for_devs-1.0.0 → k_cli_for_devs-1.0.1}/k_cli/tui/diff_viewer.py +0 -0
  70. {k_cli_for_devs-1.0.0 → k_cli_for_devs-1.0.1}/k_cli/tui/tui.py +0 -0
  71. {k_cli_for_devs-1.0.0 → k_cli_for_devs-1.0.1}/k_cli/tui/tui_animations.py +0 -0
  72. {k_cli_for_devs-1.0.0 → k_cli_for_devs-1.0.1}/k_cli/tui/tui_app.py +0 -0
  73. {k_cli_for_devs-1.0.0 → k_cli_for_devs-1.0.1}/k_cli/ui/__init__.py +0 -0
  74. {k_cli_for_devs-1.0.0 → k_cli_for_devs-1.0.1}/k_cli/web/__init__.py +0 -0
  75. {k_cli_for_devs-1.0.0 → k_cli_for_devs-1.0.1}/k_cli/web/static/app.js +0 -0
  76. {k_cli_for_devs-1.0.0 → k_cli_for_devs-1.0.1}/k_cli/web/static/index.html +0 -0
  77. {k_cli_for_devs-1.0.0 → k_cli_for_devs-1.0.1}/k_cli/web/static/monitor.html +0 -0
  78. {k_cli_for_devs-1.0.0 → k_cli_for_devs-1.0.1}/k_cli/web/static/style.css +0 -0
  79. {k_cli_for_devs-1.0.0 → k_cli_for_devs-1.0.1}/k_cli_for_devs.egg-info/dependency_links.txt +0 -0
  80. {k_cli_for_devs-1.0.0 → k_cli_for_devs-1.0.1}/k_cli_for_devs.egg-info/entry_points.txt +0 -0
  81. {k_cli_for_devs-1.0.0 → k_cli_for_devs-1.0.1}/k_cli_for_devs.egg-info/requires.txt +0 -0
  82. {k_cli_for_devs-1.0.0 → k_cli_for_devs-1.0.1}/k_cli_for_devs.egg-info/top_level.txt +0 -0
  83. {k_cli_for_devs-1.0.0 → k_cli_for_devs-1.0.1}/setup.cfg +0 -0
  84. {k_cli_for_devs-1.0.0 → k_cli_for_devs-1.0.1}/tests/test_adaptive_smart_router.py +0 -0
  85. {k_cli_for_devs-1.0.0 → k_cli_for_devs-1.0.1}/tests/test_adversarial_knowledge.py +0 -0
  86. {k_cli_for_devs-1.0.0 → k_cli_for_devs-1.0.1}/tests/test_adversarial_m6_patcher_git_session.py +0 -0
  87. {k_cli_for_devs-1.0.0 → k_cli_for_devs-1.0.1}/tests/test_challenger_m1_driver_and_mock.py +0 -0
  88. {k_cli_for_devs-1.0.0 → k_cli_for_devs-1.0.1}/tests/test_challenger_m1_streaming.py +0 -0
  89. {k_cli_for_devs-1.0.0 → k_cli_for_devs-1.0.1}/tests/test_chaos_immunity.py +0 -0
  90. {k_cli_for_devs-1.0.0 → k_cli_for_devs-1.0.1}/tests/test_cli.py +0 -0
  91. {k_cli_for_devs-1.0.0 → k_cli_for_devs-1.0.1}/tests/test_cli_fuzzer_traversal.py +0 -0
  92. {k_cli_for_devs-1.0.0 → k_cli_for_devs-1.0.1}/tests/test_cli_github_conflict_mcp.py +0 -0
  93. {k_cli_for_devs-1.0.0 → k_cli_for_devs-1.0.1}/tests/test_codex_hub.py +0 -0
  94. {k_cli_for_devs-1.0.0 → k_cli_for_devs-1.0.1}/tests/test_command_runner.py +0 -0
  95. {k_cli_for_devs-1.0.0 → k_cli_for_devs-1.0.1}/tests/test_conflict_resolver.py +0 -0
  96. {k_cli_for_devs-1.0.0 → k_cli_for_devs-1.0.1}/tests/test_credentials.py +0 -0
  97. {k_cli_for_devs-1.0.0 → k_cli_for_devs-1.0.1}/tests/test_dedup_engine.py +0 -0
  98. {k_cli_for_devs-1.0.0 → k_cli_for_devs-1.0.1}/tests/test_devdocs_expansion.py +0 -0
  99. {k_cli_for_devs-1.0.0 → k_cli_for_devs-1.0.1}/tests/test_diagram_generator.py +0 -0
  100. {k_cli_for_devs-1.0.0 → k_cli_for_devs-1.0.1}/tests/test_doc_retriever.py +0 -0
  101. {k_cli_for_devs-1.0.0 → k_cli_for_devs-1.0.1}/tests/test_dynamic_discovery_and_audit.py +0 -0
  102. {k_cli_for_devs-1.0.0 → k_cli_for_devs-1.0.1}/tests/test_e2e_suite.py +0 -0
  103. {k_cli_for_devs-1.0.0 → k_cli_for_devs-1.0.1}/tests/test_git_guard.py +0 -0
  104. {k_cli_for_devs-1.0.0 → k_cli_for_devs-1.0.1}/tests/test_github_client.py +0 -0
  105. {k_cli_for_devs-1.0.0 → k_cli_for_devs-1.0.1}/tests/test_github_engine.py +0 -0
  106. {k_cli_for_devs-1.0.0 → k_cli_for_devs-1.0.1}/tests/test_hackathon_bedrock_and_daemon.py +0 -0
  107. {k_cli_for_devs-1.0.0 → k_cli_for_devs-1.0.1}/tests/test_incident_triage.py +0 -0
  108. {k_cli_for_devs-1.0.0 → k_cli_for_devs-1.0.1}/tests/test_intent_sensor.py +0 -0
  109. {k_cli_for_devs-1.0.0 → k_cli_for_devs-1.0.1}/tests/test_k_cli_full_e2e.py +0 -0
  110. {k_cli_for_devs-1.0.0 → k_cli_for_devs-1.0.1}/tests/test_killer_features.py +0 -0
  111. {k_cli_for_devs-1.0.0 → k_cli_for_devs-1.0.1}/tests/test_llm_driver.py +0 -0
  112. {k_cli_for_devs-1.0.0 → k_cli_for_devs-1.0.1}/tests/test_local_hub.py +0 -0
  113. {k_cli_for_devs-1.0.0 → k_cli_for_devs-1.0.1}/tests/test_mcp_client.py +0 -0
  114. {k_cli_for_devs-1.0.0 → k_cli_for_devs-1.0.1}/tests/test_model_manager.py +0 -0
  115. {k_cli_for_devs-1.0.0 → k_cli_for_devs-1.0.1}/tests/test_models_hub.py +0 -0
  116. {k_cli_for_devs-1.0.0 → k_cli_for_devs-1.0.1}/tests/test_multi_provider_llm_driver.py +0 -0
  117. {k_cli_for_devs-1.0.0 → k_cli_for_devs-1.0.1}/tests/test_orchestrator.py +0 -0
  118. {k_cli_for_devs-1.0.0 → k_cli_for_devs-1.0.1}/tests/test_patcher.py +0 -0
  119. {k_cli_for_devs-1.0.0 → k_cli_for_devs-1.0.1}/tests/test_persona_system.py +0 -0
  120. {k_cli_for_devs-1.0.0 → k_cli_for_devs-1.0.1}/tests/test_repo_map.py +0 -0
  121. {k_cli_for_devs-1.0.0 → k_cli_for_devs-1.0.1}/tests/test_rules.py +0 -0
  122. {k_cli_for_devs-1.0.0 → k_cli_for_devs-1.0.1}/tests/test_sdk.py +0 -0
  123. {k_cli_for_devs-1.0.0 → k_cli_for_devs-1.0.1}/tests/test_security_healer.py +0 -0
  124. {k_cli_for_devs-1.0.0 → k_cli_for_devs-1.0.1}/tests/test_session.py +0 -0
  125. {k_cli_for_devs-1.0.0 → k_cli_for_devs-1.0.1}/tests/test_simple_ui_and_rules.py +0 -0
  126. {k_cli_for_devs-1.0.0 → k_cli_for_devs-1.0.1}/tests/test_smart_git.py +0 -0
  127. {k_cli_for_devs-1.0.0 → k_cli_for_devs-1.0.1}/tests/test_storage_manager.py +0 -0
  128. {k_cli_for_devs-1.0.0 → k_cli_for_devs-1.0.1}/tests/test_strands_agent.py +0 -0
  129. {k_cli_for_devs-1.0.0 → k_cli_for_devs-1.0.1}/tests/test_subagents.py +0 -0
  130. {k_cli_for_devs-1.0.0 → k_cli_for_devs-1.0.1}/tests/test_tui.py +0 -0
  131. {k_cli_for_devs-1.0.0 → k_cli_for_devs-1.0.1}/tests/test_tui_animations.py +0 -0
  132. {k_cli_for_devs-1.0.0 → k_cli_for_devs-1.0.1}/tests/test_tui_app.py +0 -0
  133. {k_cli_for_devs-1.0.0 → k_cli_for_devs-1.0.1}/tests/test_tui_app_screens.py +0 -0
  134. {k_cli_for_devs-1.0.0 → k_cli_for_devs-1.0.1}/tests/test_tui_pilot.py +0 -0
  135. {k_cli_for_devs-1.0.0 → k_cli_for_devs-1.0.1}/tests/test_verifier.py +0 -0
  136. {k_cli_for_devs-1.0.0 → k_cli_for_devs-1.0.1}/tests/test_viewport_engine.py +0 -0
  137. {k_cli_for_devs-1.0.0 → k_cli_for_devs-1.0.1}/tests/test_web_ui.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: k-cli-for-devs
3
- Version: 1.0.0
3
+ Version: 1.0.1
4
4
  Summary: K-CLI for Devs: Autonomous Self-Healing DevOps & Engineering Agent built with AWS Strands Agents SDK
5
5
  License: MIT License
6
6
 
@@ -61,6 +61,8 @@ Dynamic: license-file
61
61
 
62
62
  ---
63
63
 
64
+ [![PyPI Version](https://img.shields.io/pypi/v/k-cli-for-devs?color=blue&style=flat-square)](https://pypi.org/project/k-cli-for-devs/)
65
+ [![PyPI Install](https://img.shields.io/badge/pip-install%20k--cli--for--devs-blue?style=flat-square&logo=pypi&logoColor=white)](https://pypi.org/project/k-cli-for-devs/)
64
66
  [![MIT License](https://img.shields.io/badge/License-MIT-blue.svg?style=flat-square)](LICENSE)
65
67
  [![Python 3.11+](https://img.shields.io/badge/Python-3.11%20%7C%203.12-brightgreen.svg?style=flat-square)](https://python.org)
66
68
  [![AWS Strands Agents](https://img.shields.io/badge/AWS-Strands%20Agents%20SDK-orange.svg?style=flat-square)](https://strandsagents.com)
@@ -69,6 +71,10 @@ Dynamic: license-file
69
71
  [![Architecture](https://img.shields.io/badge/Architecture-Verification--First%20AST-blueviolet.svg?style=flat-square)](#-zero-trust-ast-compiler-verification-guardrails)
70
72
  [![Offline Ready](https://img.shields.io/badge/Air--Gapped-100%25%20Offline%20Ready-teal.svg?style=flat-square)](#-sovereign-air-gapped-offline-engine)
71
73
 
74
+ ```bash
75
+ pip install k-cli-for-devs
76
+ ```
77
+
72
78
  > **K-CLI is the next-generation autonomous developer workstation that unites 3 unified UI tiers, zero-latency intent sensing, compiler-grounded AST verification, Google Antigravity-grade local shell execution, and AWS Bedrock AgentCore into a sovereign, production-grade CLI.**
73
79
 
74
80
  ---
@@ -262,6 +268,13 @@ K-CLI provides 3 purpose-built interfaces tailored to developer workflows:
262
268
 
263
269
  ## 🏛️ System Architecture Diagram
264
270
 
271
+ ![K-CLI System Architecture Diagram](docs/assets/architecture_diagram.png)
272
+
273
+ > 📄 **Official PDF Specification**: Download the vector [`docs/assets/architecture_diagram.pdf`](docs/assets/architecture_diagram.pdf) submitted to the AWS Hackathon.
274
+
275
+ <details>
276
+ <summary><b>Click to expand raw Mermaid flowchart specification</b></summary>
277
+
265
278
  ```mermaid
266
279
  flowchart TD
267
280
  subgraph Ingestion ["📥 Incident & Multi-Interface Ingestion Layer"]
@@ -313,16 +326,22 @@ flowchart TD
313
326
  Gate -- "Passed" --> Delivery
314
327
  ```
315
328
 
329
+ </details>
330
+
316
331
  ---
317
332
 
318
333
  ## 📦 Installation & Quickstart
319
334
 
320
- ### 1. Prerequisites
335
+ ### 1. Fast Install via PyPI (Recommended)
336
+ ```bash
337
+ pip install k-cli-for-devs
338
+ ```
339
+
340
+ ### 2. Prerequisites & Build from Source
321
341
  * **Python 3.11** or **Python 3.12**
322
342
  * **Git** installed on host machine
323
343
  * (Optional) **AWS Credentials** configured for Amazon Bedrock / Strands Agents
324
344
 
325
- ### 2. Clone and Install
326
345
  ```bash
327
346
  # Clone repository
328
347
  git clone https://github.com/krishivjoshi219-collab/K-Cli-for-Devs.git
@@ -5,6 +5,8 @@
5
5
 
6
6
  ---
7
7
 
8
+ [![PyPI Version](https://img.shields.io/pypi/v/k-cli-for-devs?color=blue&style=flat-square)](https://pypi.org/project/k-cli-for-devs/)
9
+ [![PyPI Install](https://img.shields.io/badge/pip-install%20k--cli--for--devs-blue?style=flat-square&logo=pypi&logoColor=white)](https://pypi.org/project/k-cli-for-devs/)
8
10
  [![MIT License](https://img.shields.io/badge/License-MIT-blue.svg?style=flat-square)](LICENSE)
9
11
  [![Python 3.11+](https://img.shields.io/badge/Python-3.11%20%7C%203.12-brightgreen.svg?style=flat-square)](https://python.org)
10
12
  [![AWS Strands Agents](https://img.shields.io/badge/AWS-Strands%20Agents%20SDK-orange.svg?style=flat-square)](https://strandsagents.com)
@@ -13,6 +15,10 @@
13
15
  [![Architecture](https://img.shields.io/badge/Architecture-Verification--First%20AST-blueviolet.svg?style=flat-square)](#-zero-trust-ast-compiler-verification-guardrails)
14
16
  [![Offline Ready](https://img.shields.io/badge/Air--Gapped-100%25%20Offline%20Ready-teal.svg?style=flat-square)](#-sovereign-air-gapped-offline-engine)
15
17
 
18
+ ```bash
19
+ pip install k-cli-for-devs
20
+ ```
21
+
16
22
  > **K-CLI is the next-generation autonomous developer workstation that unites 3 unified UI tiers, zero-latency intent sensing, compiler-grounded AST verification, Google Antigravity-grade local shell execution, and AWS Bedrock AgentCore into a sovereign, production-grade CLI.**
17
23
 
18
24
  ---
@@ -206,6 +212,13 @@ K-CLI provides 3 purpose-built interfaces tailored to developer workflows:
206
212
 
207
213
  ## 🏛️ System Architecture Diagram
208
214
 
215
+ ![K-CLI System Architecture Diagram](docs/assets/architecture_diagram.png)
216
+
217
+ > 📄 **Official PDF Specification**: Download the vector [`docs/assets/architecture_diagram.pdf`](docs/assets/architecture_diagram.pdf) submitted to the AWS Hackathon.
218
+
219
+ <details>
220
+ <summary><b>Click to expand raw Mermaid flowchart specification</b></summary>
221
+
209
222
  ```mermaid
210
223
  flowchart TD
211
224
  subgraph Ingestion ["📥 Incident & Multi-Interface Ingestion Layer"]
@@ -257,16 +270,22 @@ flowchart TD
257
270
  Gate -- "Passed" --> Delivery
258
271
  ```
259
272
 
273
+ </details>
274
+
260
275
  ---
261
276
 
262
277
  ## 📦 Installation & Quickstart
263
278
 
264
- ### 1. Prerequisites
279
+ ### 1. Fast Install via PyPI (Recommended)
280
+ ```bash
281
+ pip install k-cli-for-devs
282
+ ```
283
+
284
+ ### 2. Prerequisites & Build from Source
265
285
  * **Python 3.11** or **Python 3.12**
266
286
  * **Git** installed on host machine
267
287
  * (Optional) **AWS Credentials** configured for Amazon Bedrock / Strands Agents
268
288
 
269
- ### 2. Clone and Install
270
289
  ```bash
271
290
  # Clone repository
272
291
  git clone https://github.com/krishivjoshi219-collab/K-Cli-for-Devs.git
@@ -0,0 +1,539 @@
1
+ """
2
+ autonomous_agent.py - True Agentic Autonomous Execution Engine for K-CLI
3
+ Project Bankai v1.0.0
4
+
5
+ Enables K-CLI to act as a full autonomous developer workstation (like Google Antigravity, Aider, and Claude Code):
6
+ 1. Proactive local machine & workspace awareness (inspect files, explore directories).
7
+ 2. Autonomous ReAct tool execution loop (read, write, edit, execute shell commands, verify with compilers).
8
+ 3. Multi-file project synthesis on the user's computer with AST verification and test execution.
9
+ 4. Real-time streaming of thoughts, tool invocations, and tool results.
10
+ """
11
+
12
+ from __future__ import annotations
13
+
14
+ import ast
15
+ import json
16
+ import logging
17
+ import os
18
+ import re
19
+ import subprocess
20
+ import time
21
+ from dataclasses import dataclass, field
22
+ from pathlib import Path
23
+ from typing import Any, Callable, Dict, List, Optional, Tuple, Union
24
+
25
+ from k_cli.core.llm_driver import LLMDriver
26
+ from k_cli.tools.command_runner import global_command_executor
27
+
28
+ logger = logging.getLogger("k_cli.agents.autonomous_agent")
29
+
30
+
31
+ # ==============================================================================
32
+ # LOCAL WORKSPACE TOOLS
33
+ # ==============================================================================
34
+
35
+ def tool_list_dir(directory: str = ".", max_depth: int = 2) -> str:
36
+ """Lists files and directories in the workspace with hierarchy and file sizes."""
37
+ try:
38
+ target = Path(directory).resolve()
39
+ if not target.exists():
40
+ return f"Error: Directory '{directory}' does not exist (resolved to {target})."
41
+
42
+ lines = [f"📁 Directory listing for: {target}"]
43
+ ignored_names = {".git", ".venv", "venv", "k_cli_env", "__pycache__", "node_modules", ".pytest_cache", ".ruff_cache", ".mypy_cache"}
44
+
45
+ count = 0
46
+ for root, dirs, files in os.walk(target):
47
+ dirs[:] = [d for d in dirs if d not in ignored_names and not d.startswith(".")]
48
+ rel = os.path.relpath(root, target)
49
+ depth = 0 if rel == "." else rel.count(os.sep) + 1
50
+ if depth > max_depth:
51
+ dirs.clear()
52
+ continue
53
+
54
+ indent = " " * depth
55
+ if rel != ".":
56
+ lines.append(f"{indent}📂 {os.path.basename(root)}/")
57
+
58
+ for f in sorted(files):
59
+ if f.startswith(".") or f.endswith((".pyc", ".pyo", ".egg-info")):
60
+ continue
61
+ fpath = Path(root) / f
62
+ sz = fpath.stat().st_size if fpath.exists() else 0
63
+ lines.append(f"{indent} 📄 {f} ({sz} bytes)")
64
+ count += 1
65
+ if count > 120:
66
+ lines.append(f"{indent} ... [truncated, showing top 120 items]")
67
+ return "\n".join(lines)
68
+
69
+ return "\n".join(lines)
70
+ except Exception as e:
71
+ return f"Error in list_dir: {e}"
72
+
73
+
74
+ def tool_read_workspace_file(file_path: str, start_line: int = 1, max_lines: int = 200) -> str:
75
+ """Reads lines from a local file with line numbering."""
76
+ try:
77
+ p = Path(file_path).resolve()
78
+ if not p.exists():
79
+ return f"Error: File '{file_path}' does not exist."
80
+ if not p.is_file():
81
+ return f"Error: '{file_path}' is a directory, not a file."
82
+
83
+ text = p.read_text(encoding="utf-8", errors="replace")
84
+ lines = text.splitlines()
85
+ total_lines = len(lines)
86
+
87
+ start_idx = max(0, start_line - 1)
88
+ end_idx = min(total_lines, start_idx + max_lines)
89
+ selected = lines[start_idx:end_idx]
90
+
91
+ output = [f"--- File: {p} (Lines {start_line}-{end_idx} of {total_lines}) ---"]
92
+ for i, line in enumerate(selected):
93
+ output.append(f"{start_line + i:4d} | {line}")
94
+
95
+ if end_idx < total_lines:
96
+ output.append(f"... [{total_lines - end_idx} more lines remaining]")
97
+
98
+ return "\n".join(output)
99
+ except Exception as e:
100
+ return f"Error reading file '{file_path}': {e}"
101
+
102
+
103
+ def tool_write_workspace_file(file_path: str, content: str) -> str:
104
+ """Creates or overwrites a file on the user's computer, with AST syntax validation for Python."""
105
+ try:
106
+ p = Path(file_path).resolve()
107
+ p.parent.mkdir(parents=True, exist_ok=True)
108
+ p.write_text(content, encoding="utf-8")
109
+
110
+ status_msg = f"Successfully wrote {len(content.encode('utf-8'))} bytes to '{p}'"
111
+
112
+ # If Python file, run py_compile
113
+ if p.suffix.lower() == ".py":
114
+ import py_compile
115
+ try:
116
+ py_compile.compile(str(p), doraise=True)
117
+ status_msg += " (AST py_compile verified: VALID SYNTAX)"
118
+ except py_compile.PyCompileError as pe:
119
+ status_msg += f" (WARNING: Syntax error detected: {pe})"
120
+
121
+ return status_msg
122
+ except Exception as e:
123
+ return f"Error writing file '{file_path}': {e}"
124
+
125
+
126
+ def tool_edit_workspace_file(file_path: str, target_content: str, replacement_content: str) -> str:
127
+ """Surgically replaces an exact text block in an existing file."""
128
+ try:
129
+ p = Path(file_path).resolve()
130
+ if not p.exists():
131
+ return f"Error: File '{file_path}' does not exist."
132
+
133
+ text = p.read_text(encoding="utf-8", errors="replace")
134
+ if target_content not in text:
135
+ return f"Error: target_content not found in '{file_path}'."
136
+
137
+ new_text = text.replace(target_content, replacement_content, 1)
138
+ p.write_text(new_text, encoding="utf-8")
139
+
140
+ if p.suffix.lower() == ".py":
141
+ import py_compile
142
+ try:
143
+ py_compile.compile(str(p), doraise=True)
144
+ return f"Successfully updated '{file_path}' (AST py_compile: VALID)"
145
+ except py_compile.PyCompileError as pe:
146
+ return f"Updated '{file_path}' but syntax error detected: {pe}"
147
+
148
+ return f"Successfully updated '{file_path}'"
149
+ except Exception as e:
150
+ return f"Error editing file '{file_path}': {e}"
151
+
152
+
153
+ def tool_execute_command(command: str, cwd: str = ".", timeout_seconds: int = 60) -> str:
154
+ """Executes any terminal/shell command on the local machine (Google Antigravity engine)."""
155
+ try:
156
+ res = global_command_executor.execute(command, cwd=cwd, timeout=timeout_seconds)
157
+ output_parts = [
158
+ f"$ {res.command} (exit code: {res.exit_code}, duration: {res.duration_sec:.2f}s)"
159
+ ]
160
+ if res.stdout.strip():
161
+ output_parts.append("[stdout]\n" + res.stdout.strip())
162
+ if res.stderr.strip():
163
+ output_parts.append("[stderr]\n" + res.stderr.strip())
164
+ if not res.stdout.strip() and not res.stderr.strip():
165
+ output_parts.append("[command completed with no output]")
166
+ return "\n".join(output_parts)
167
+ except Exception as e:
168
+ return f"Error executing command '{command}': {e}"
169
+
170
+
171
+ def tool_inspect_repo_structure(directory: str = ".") -> str:
172
+ """Generates an AST symbol map of functions, classes, and imports across the codebase."""
173
+ try:
174
+ from k_cli.git.repo_map import RepoMap
175
+ rm = RepoMap(root_dir=directory)
176
+ return rm.render_summary(max_tokens=600)
177
+ except Exception as e:
178
+ return tool_list_dir(directory=directory, max_depth=2)
179
+
180
+
181
+ def tool_verify_code_file(file_path: str) -> str:
182
+ """Runs compiler syntax checks and test suites for a workspace file."""
183
+ try:
184
+ from k_cli.git.verifier import Verifier
185
+ v = Verifier()
186
+ p = Path(file_path).resolve()
187
+ if not p.exists():
188
+ return f"Error: File '{file_path}' does not exist."
189
+ content = p.read_text(encoding="utf-8", errors="replace")
190
+ res = v.verify(content, language="python")
191
+ return f"Verification Result for '{file_path}': Success={res.success}, Type={res.verification_type} (Errors: {res.error_trace or 'None'})"
192
+ except Exception as e:
193
+ return f"Error in verify_code_file: {e}"
194
+
195
+
196
+ def tool_search_codebase(query: str, directory: str = ".") -> str:
197
+ """Searches for text, functions, or patterns across workspace source files."""
198
+ try:
199
+ root = Path(directory).resolve()
200
+ matches = []
201
+ ignored = {".git", ".venv", "venv", "k_cli_env", "__pycache__", "node_modules"}
202
+
203
+ for p in root.rglob("*"):
204
+ if any(part in ignored for part in p.parts):
205
+ continue
206
+ if not p.is_file() or p.suffix.lower() not in {".py", ".js", ".ts", ".html", ".css", ".md", ".json", ".toml", ".yaml", ".sh"}:
207
+ continue
208
+ try:
209
+ lines = p.read_text(encoding="utf-8", errors="replace").splitlines()
210
+ for idx, line in enumerate(lines):
211
+ if query.lower() in line.lower():
212
+ rel = os.path.relpath(p, root)
213
+ matches.append(f"{rel}:{idx + 1}: {line.strip()}")
214
+ if len(matches) >= 40:
215
+ matches.append("... [truncated, 40+ matches found]")
216
+ return "\n".join(matches)
217
+ except Exception:
218
+ continue
219
+
220
+ if not matches:
221
+ return f"No matches found for '{query}' in {root}"
222
+ return "\n".join(matches)
223
+ except Exception as e:
224
+ return f"Error searching codebase: {e}"
225
+
226
+
227
+ def tool_triage_and_heal_incident(error_traceback: str) -> str:
228
+ """Triages multi-language crash tracebacks and attempts automated patch healing."""
229
+ try:
230
+ from k_cli.agents.strands_agent import triage_and_heal_incident
231
+ return triage_and_heal_incident(error_traceback)
232
+ except Exception as e:
233
+ return f"Error in incident triage: {e}"
234
+
235
+
236
+ # Tool registry map
237
+ AVAILABLE_TOOLS: Dict[str, Callable[..., str]] = {
238
+ "list_dir": tool_list_dir,
239
+ "read_workspace_file": tool_read_workspace_file,
240
+ "write_workspace_file": tool_write_workspace_file,
241
+ "edit_workspace_file": tool_edit_workspace_file,
242
+ "execute_command": tool_execute_command,
243
+ "inspect_repo_structure": tool_inspect_repo_structure,
244
+ "verify_code_file": tool_verify_code_file,
245
+ "search_codebase": tool_search_codebase,
246
+ "triage_and_heal_incident": tool_triage_and_heal_incident,
247
+ }
248
+
249
+
250
+ # ==============================================================================
251
+ # AUTONOMOUS AGENT SYSTEM PROMPT
252
+ # ==============================================================================
253
+
254
+ def build_agentic_system_prompt(cwd: Optional[str] = None) -> str:
255
+ """Generates the mission-critical system prompt establishing local machine authority."""
256
+ cwd_path = Path(cwd or ".").resolve()
257
+
258
+ top_items = []
259
+ try:
260
+ for item in sorted(cwd_path.iterdir()):
261
+ if not item.name.startswith((".", "__")) and item.name not in ("k_cli_env", "venv", "node_modules"):
262
+ top_items.append(f"{item.name}{'/' if item.is_dir() else ''}")
263
+ except Exception:
264
+ pass
265
+
266
+ top_manifest = ", ".join(top_items[:20]) or "standard project tree"
267
+
268
+ return f"""You are K-CLI, a fully autonomous AI DevOps and software engineering workstation running directly on the developer's Linux machine (comparable to Google Antigravity, Aider, and Claude Code).
269
+
270
+ LOCAL MACHINE ENVIRONMENT:
271
+ - Working Directory: {cwd_path}
272
+ - Workspace Root Items: {top_manifest}
273
+ - Execution Privilege: Full local machine terminal execution & file system read/write via tools.
274
+
275
+ CRITICAL OPERATIONAL RULES:
276
+ 1. YOU ARE NOT A CHATBOT. You are an autonomous software engineering agent with REAL tools on this local machine.
277
+ 2. NEVER say "I do not have access to local file systems" or "I cannot check folders on your computer". YOU DO HAVE ACCESS through your tools!
278
+ 3. When the user asks you to:
279
+ - "check", "inspect", or "explore" a folder or project:
280
+ Use `list_dir` or `read_workspace_file` or `inspect_repo_structure` to inspect the real files and evaluate them.
281
+ - "create", "write", "build", or "implement" a project, app, game, or script:
282
+ Autonomously write the files to disk using `write_workspace_file`, verify them with `execute_command` or `verify_code_file`, and confirm they are saved.
283
+ - "run", "test", or "fix" something:
284
+ Use `execute_command` to run the real terminal commands (pytest, python, git, etc.) and inspect the outputs.
285
+
286
+ TOOL CALLING PROTOCOL:
287
+ When you need to execute an action on the local machine, output a tool call block:
288
+ ```tool_call
289
+ {{"name": "tool_name", "arguments": {{"arg1": "value1"}}}}
290
+ ```
291
+ Stop immediately after the tool call block and wait for the real result. DO NOT simulate or make up the tool result.
292
+
293
+ Available Tools:
294
+ - `list_dir(directory=".", max_depth=2)`: List files and subfolders.
295
+ - `read_workspace_file(file_path="...", start_line=1, max_lines=200)`: Read file contents with line numbers.
296
+ - `write_workspace_file(file_path="...", content="...")`: Write or create a file on disk (auto-verifies Python syntax).
297
+ - `edit_workspace_file(file_path="...", target_content="...", replacement_content="...")`: Surgical search/replace edit.
298
+ - `execute_command(command="...", cwd=".")`: Execute ANY shell command locally on host (pytest, git, python, etc.).
299
+ - `inspect_repo_structure(directory=".")`: AST map of classes and functions.
300
+ - `verify_code_file(file_path="...")`: Ground-truth compiler and test verification.
301
+ - `search_codebase(query="...", directory=".")`: Search for symbols or text across files.
302
+ - `triage_and_heal_incident(error_traceback="...")`: Automated crash traceback triage and repair.
303
+
304
+ Always take real action. Inspect real files, write real code to disk, and verify before giving your final answer."""
305
+
306
+
307
+ # ==============================================================================
308
+ # AUTONOMOUS AGENT RUNNER
309
+ # ==============================================================================
310
+
311
+ @dataclass
312
+ class AgentStep:
313
+ step_num: int
314
+ thought: str
315
+ tool_name: Optional[str] = None
316
+ tool_args: Optional[Dict[str, Any]] = None
317
+ tool_output: Optional[str] = None
318
+
319
+
320
+ @dataclass
321
+ class AutonomousAgentResult:
322
+ success: bool
323
+ final_response: str
324
+ steps: List[AgentStep] = field(default_factory=list)
325
+ tools_executed: List[str] = field(default_factory=list)
326
+ total_tokens: int = 0
327
+ duration_sec: float = 0.0
328
+
329
+
330
+ class AutonomousAgent:
331
+ """
332
+ Autonomous Agentic Execution Engine.
333
+ Executes a multi-turn ReAct loop with local machine tools, streaming progress in real time.
334
+ """
335
+
336
+ def __init__(
337
+ self,
338
+ driver: Optional[LLMDriver] = None,
339
+ model_name: str = "auto",
340
+ cwd: Optional[str] = None,
341
+ max_steps: int = 8,
342
+ ):
343
+ self.driver = driver or LLMDriver(model_name=model_name)
344
+ self.cwd = cwd or os.getcwd()
345
+ self.max_steps = max_steps
346
+
347
+ def _extract_tool_call(self, text: str) -> Optional[Tuple[str, Dict[str, Any]]]:
348
+ """Extracts tool name and arguments from JSON or Python-style model output."""
349
+ # 1. Check for JSON tool call
350
+ for match in re.finditer(r"```(?:tool_call|json)?\s*(\{.*?\})\s*```|<tool_call>\s*(\{.*?\})\s*</tool_call>", text, re.DOTALL):
351
+ raw = match.group(1) or match.group(2)
352
+ try:
353
+ d = json.loads(raw.strip())
354
+ if "name" in d and d["name"] in AVAILABLE_TOOLS:
355
+ return d["name"], d.get("arguments", {})
356
+ except Exception:
357
+ continue
358
+
359
+ # 2. Check for Python-style tool call (e.g. write_workspace_file(...) or execute_command(...))
360
+ for block in re.findall(r"```(?:tool_code|tool_call|python)?\s*([a-zA-Z_]\w*\s*\(.*?\))\s*```|<tool_code>\s*([a-zA-Z_]\w*\s*\(.*?\))\s*</tool_code>", text, re.DOTALL):
361
+ raw_code = (block[0] or block[1]).strip()
362
+ try:
363
+ tree = ast.parse(raw_code)
364
+ for node in ast.walk(tree):
365
+ if isinstance(node, ast.Call) and isinstance(node.func, ast.Name):
366
+ fn_name = node.func.id
367
+ if fn_name in AVAILABLE_TOOLS:
368
+ kwargs = {}
369
+ for kw in node.keywords:
370
+ try:
371
+ kwargs[kw.arg] = ast.literal_eval(kw.value)
372
+ except Exception:
373
+ kwargs[kw.arg] = ast.unparse(kw.value) if hasattr(ast, "unparse") else str(kw.value)
374
+ # Handle positional args if any
375
+ if node.args and fn_name == "list_dir":
376
+ kwargs["directory"] = ast.literal_eval(node.args[0])
377
+ elif node.args and fn_name == "execute_command":
378
+ kwargs["command"] = ast.literal_eval(node.args[0])
379
+ elif node.args and fn_name == "read_workspace_file":
380
+ kwargs["file_path"] = ast.literal_eval(node.args[0])
381
+ return fn_name, kwargs
382
+ except Exception:
383
+ continue
384
+
385
+ # 3. Inline function call scan (e.g. `write_workspace_file(...)`)
386
+ for fn_name in AVAILABLE_TOOLS:
387
+ pattern = re.compile(rf"\b{fn_name}\s*\((.*?)\)", re.DOTALL)
388
+ m = pattern.search(text)
389
+ if m:
390
+ raw_call = m.group(0)
391
+ try:
392
+ tree = ast.parse(raw_call.strip())
393
+ for node in ast.walk(tree):
394
+ if isinstance(node, ast.Call) and isinstance(node.func, ast.Name) and node.func.id == fn_name:
395
+ kwargs = {}
396
+ for kw in node.keywords:
397
+ try:
398
+ kwargs[kw.arg] = ast.literal_eval(kw.value)
399
+ except Exception:
400
+ kwargs[kw.arg] = str(kw.value)
401
+ return fn_name, kwargs
402
+ except Exception:
403
+ continue
404
+
405
+ return None
406
+
407
+ def execute_tool(self, name: str, args: Dict[str, Any]) -> str:
408
+ """Executes a registered local tool with arguments."""
409
+ if name not in AVAILABLE_TOOLS:
410
+ return f"Error: Tool '{name}' is not recognized. Available tools: {list(AVAILABLE_TOOLS.keys())}"
411
+
412
+ tool_fn = AVAILABLE_TOOLS[name]
413
+ try:
414
+ logger.info(f"Executing tool: {name} with args {args}")
415
+ return tool_fn(**args)
416
+ except TypeError as te:
417
+ try:
418
+ if len(args) == 1:
419
+ val = next(iter(args.values()))
420
+ return tool_fn(val)
421
+ except Exception:
422
+ pass
423
+ return f"Error calling {name}: invalid arguments {args} ({te})"
424
+ except Exception as e:
425
+ return f"Error executing tool '{name}': {e}"
426
+
427
+ def run(
428
+ self,
429
+ prompt: str,
430
+ token_callback: Optional[Callable[[str, str], None]] = None,
431
+ ) -> AutonomousAgentResult:
432
+ """
433
+ Executes the autonomous agent ReAct loop.
434
+ token_callback(persona_label, token_or_chunk) is called for real-time streaming.
435
+ """
436
+ start_time = time.time()
437
+ system_prompt = build_agentic_system_prompt(self.cwd)
438
+ steps: List[AgentStep] = []
439
+ tools_executed: List[str] = []
440
+
441
+ # 1. Proactive Reconnaissance:
442
+ lower_prompt = prompt.lower()
443
+ extra_context = ""
444
+ if any(w in lower_prompt for w in ("check", "inspect", "explore", "what is inside", "list folder", "folder", "directory", "structure", "impressive", "review")):
445
+ target_dir = "."
446
+ words = prompt.split()
447
+ for i, w in enumerate(words):
448
+ clean_w = w.strip("`'\",:;")
449
+ if clean_w in ("folder", "directory", "repo", "project") and i > 0:
450
+ prev = words[i - 1].strip("`'\",:;")
451
+ if prev not in ("the", "this", "my", "a", "our"):
452
+ target_dir = prev
453
+ elif Path(clean_w).is_dir():
454
+ target_dir = clean_w
455
+ break
456
+
457
+ recon_listing = tool_list_dir(target_dir, max_depth=2)
458
+ extra_context = f"\n\n[LOCAL WORKSPACE RECONNAISSANCE - Items in '{target_dir}']:\n{recon_listing}\n"
459
+ if token_callback:
460
+ token_callback("RECON", f"⚡ [Inspecting local directory: {target_dir}]\n")
461
+
462
+ conversation_history = [
463
+ f"User Task: {prompt}{extra_context}"
464
+ ]
465
+
466
+ final_response = ""
467
+ current_persona = "RESEARCHER"
468
+
469
+ for step_idx in range(1, self.max_steps + 1):
470
+ full_prompt = "\n\n".join(conversation_history)
471
+ current_turn_tokens: List[str] = []
472
+
473
+ def turn_stream_cb(token: str):
474
+ current_turn_tokens.append(token)
475
+ if token_callback:
476
+ token_callback(current_persona, token)
477
+
478
+ model_out = self.driver.generate(
479
+ prompt=full_prompt,
480
+ system_prompt=system_prompt,
481
+ stream_callback=turn_stream_cb,
482
+ temperature=0.2,
483
+ )
484
+
485
+ if not model_out and current_turn_tokens:
486
+ model_out = "".join(current_turn_tokens)
487
+
488
+ tool_call_info = self._extract_tool_call(model_out)
489
+
490
+ if not tool_call_info:
491
+ final_response = model_out
492
+ steps.append(AgentStep(step_num=step_idx, thought=model_out))
493
+ break
494
+
495
+ tool_name, tool_args = tool_call_info
496
+ tools_executed.append(tool_name)
497
+ current_persona = "TOOL EXEC"
498
+
499
+ # Execute tool locally on developer's machine
500
+ args_summary = ", ".join(f"{k}={repr(v)[:50]}" for k, v in tool_args.items())
501
+ if token_callback:
502
+ token_callback("TOOL EXEC", f"\n\n⚡ [Executing Tool: {tool_name}({args_summary})]\n")
503
+
504
+ tool_result = self.execute_tool(tool_name, tool_args)
505
+
506
+ if token_callback:
507
+ res_lines = tool_result.strip().splitlines()
508
+ summary_preview = res_lines[0] if res_lines else "Completed"
509
+ token_callback("TOOL RESULT", f"✔ [{tool_name} Result]: {summary_preview} ({len(tool_result)} bytes)\n\n")
510
+
511
+ steps.append(
512
+ AgentStep(
513
+ step_num=step_idx,
514
+ thought=model_out,
515
+ tool_name=tool_name,
516
+ tool_args=tool_args,
517
+ tool_output=tool_result,
518
+ )
519
+ )
520
+
521
+ # Feed tool execution back to conversation history
522
+ conversation_history.append(
523
+ f"Assistant Action:\n{model_out}\n\n"
524
+ f"<tool_result tool=\"{tool_name}\">\n{tool_result}\n</tool_result>\n"
525
+ f"The tool execution succeeded. Now continue your response, invoke any additional tools if needed, or conclude your answer."
526
+ )
527
+ current_persona = "CODER" if "write" in tool_name else "VERIFIER"
528
+
529
+ if not final_response:
530
+ final_response = model_out or "Task completed by K-CLI Autonomous Agent."
531
+
532
+ duration = time.time() - start_time
533
+ return AutonomousAgentResult(
534
+ success=True,
535
+ final_response=final_response,
536
+ steps=steps,
537
+ tools_executed=tools_executed,
538
+ duration_sec=duration,
539
+ )