acra-cli 0.1.2__tar.gz → 0.1.4__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 (186) hide show
  1. {acra_cli-0.1.2/acra_cli.egg-info → acra_cli-0.1.4}/PKG-INFO +1 -1
  2. {acra_cli-0.1.2 → acra_cli-0.1.4}/acra/__init__.py +1 -1
  3. {acra_cli-0.1.2 → acra_cli-0.1.4}/acra/cli.py +41 -5
  4. {acra_cli-0.1.2 → acra_cli-0.1.4}/acra/commands/__init__.py +2 -0
  5. acra_cli-0.1.4/acra/commands/ask.py +106 -0
  6. {acra_cli-0.1.2 → acra_cli-0.1.4}/acra/commands/research.py +16 -4
  7. {acra_cli-0.1.2 → acra_cli-0.1.4}/acra/commands/serve.py +10 -2
  8. acra_cli-0.1.4/acra/ui/__pycache__/animated_banner.cpython-312.pyc +0 -0
  9. acra_cli-0.1.4/acra/ui/__pycache__/banner.cpython-312.pyc +0 -0
  10. acra_cli-0.1.4/acra/ui/__pycache__/shell.cpython-312.pyc +0 -0
  11. acra_cli-0.1.4/acra/ui/animated_banner.py +287 -0
  12. {acra_cli-0.1.2 → acra_cli-0.1.4}/acra/ui/banner.py +3 -11
  13. {acra_cli-0.1.2 → acra_cli-0.1.4}/acra/ui/shell.py +4 -2
  14. {acra_cli-0.1.2 → acra_cli-0.1.4/acra_cli.egg-info}/PKG-INFO +1 -1
  15. {acra_cli-0.1.2 → acra_cli-0.1.4}/acra_cli.egg-info/SOURCES.txt +4 -1
  16. {acra_cli-0.1.2 → acra_cli-0.1.4}/pyproject.toml +1 -1
  17. acra_cli-0.1.4/tests/test_cli.py +91 -0
  18. acra_cli-0.1.4/tests/test_interactive_routing.py +53 -0
  19. acra_cli-0.1.2/acra/commands/ask.py +0 -49
  20. acra_cli-0.1.2/acra/ui/__pycache__/banner.cpython-312.pyc +0 -0
  21. acra_cli-0.1.2/acra/ui/__pycache__/shell.cpython-312.pyc +0 -0
  22. acra_cli-0.1.2/tests/test_cli.py +0 -36
  23. {acra_cli-0.1.2 → acra_cli-0.1.4}/LICENSE +0 -0
  24. {acra_cli-0.1.2 → acra_cli-0.1.4}/MANIFEST.in +0 -0
  25. {acra_cli-0.1.2 → acra_cli-0.1.4}/README.md +0 -0
  26. {acra_cli-0.1.2 → acra_cli-0.1.4}/acra/__main__.py +0 -0
  27. {acra_cli-0.1.2 → acra_cli-0.1.4}/acra/agents/__init__.py +0 -0
  28. {acra_cli-0.1.2 → acra_cli-0.1.4}/acra/agents/__pycache__/__init__.cpython-312.pyc +0 -0
  29. {acra_cli-0.1.2 → acra_cli-0.1.4}/acra/agents/__pycache__/llm.cpython-312.pyc +0 -0
  30. {acra_cli-0.1.2 → acra_cli-0.1.4}/acra/agents/__pycache__/llm_utils.cpython-312.pyc +0 -0
  31. {acra_cli-0.1.2 → acra_cli-0.1.4}/acra/agents/coder/__init__.py +0 -0
  32. {acra_cli-0.1.2 → acra_cli-0.1.4}/acra/agents/coder/__pycache__/__init__.cpython-312.pyc +0 -0
  33. {acra_cli-0.1.2 → acra_cli-0.1.4}/acra/agents/coder/__pycache__/coder_agent.cpython-312.pyc +0 -0
  34. {acra_cli-0.1.2 → acra_cli-0.1.4}/acra/agents/coder/__pycache__/coder_chain.cpython-312.pyc +0 -0
  35. {acra_cli-0.1.2 → acra_cli-0.1.4}/acra/agents/coder/coder_agent.py +0 -0
  36. {acra_cli-0.1.2 → acra_cli-0.1.4}/acra/agents/coder/coder_chain.py +0 -0
  37. {acra_cli-0.1.2 → acra_cli-0.1.4}/acra/agents/critic/__init__.py +0 -0
  38. {acra_cli-0.1.2 → acra_cli-0.1.4}/acra/agents/critic/__pycache__/__init__.cpython-312.pyc +0 -0
  39. {acra_cli-0.1.2 → acra_cli-0.1.4}/acra/agents/critic/__pycache__/critic_agent.cpython-312.pyc +0 -0
  40. {acra_cli-0.1.2 → acra_cli-0.1.4}/acra/agents/critic/__pycache__/critic_chain.cpython-312.pyc +0 -0
  41. {acra_cli-0.1.2 → acra_cli-0.1.4}/acra/agents/critic/critic_agent.py +0 -0
  42. {acra_cli-0.1.2 → acra_cli-0.1.4}/acra/agents/critic/critic_chain.py +0 -0
  43. {acra_cli-0.1.2 → acra_cli-0.1.4}/acra/agents/executor/__init__.py +0 -0
  44. {acra_cli-0.1.2 → acra_cli-0.1.4}/acra/agents/executor/__pycache__/__init__.cpython-312.pyc +0 -0
  45. {acra_cli-0.1.2 → acra_cli-0.1.4}/acra/agents/executor/__pycache__/docker_runner.cpython-312.pyc +0 -0
  46. {acra_cli-0.1.2 → acra_cli-0.1.4}/acra/agents/executor/__pycache__/executor_agent.cpython-312.pyc +0 -0
  47. {acra_cli-0.1.2 → acra_cli-0.1.4}/acra/agents/executor/__pycache__/sandbox_runner.cpython-312.pyc +0 -0
  48. {acra_cli-0.1.2 → acra_cli-0.1.4}/acra/agents/executor/docker_runner.py +0 -0
  49. {acra_cli-0.1.2 → acra_cli-0.1.4}/acra/agents/executor/executor_agent.py +0 -0
  50. {acra_cli-0.1.2 → acra_cli-0.1.4}/acra/agents/executor/sandbox_runner.py +0 -0
  51. {acra_cli-0.1.2 → acra_cli-0.1.4}/acra/agents/human/__init__.py +0 -0
  52. {acra_cli-0.1.2 → acra_cli-0.1.4}/acra/agents/human/__pycache__/__init__.cpython-312.pyc +0 -0
  53. {acra_cli-0.1.2 → acra_cli-0.1.4}/acra/agents/human/__pycache__/human_node.cpython-312.pyc +0 -0
  54. {acra_cli-0.1.2 → acra_cli-0.1.4}/acra/agents/human/human_node.py +0 -0
  55. {acra_cli-0.1.2 → acra_cli-0.1.4}/acra/agents/llm.py +0 -0
  56. {acra_cli-0.1.2 → acra_cli-0.1.4}/acra/agents/llm_utils.py +0 -0
  57. {acra_cli-0.1.2 → acra_cli-0.1.4}/acra/agents/memory/__init__.py +0 -0
  58. {acra_cli-0.1.2 → acra_cli-0.1.4}/acra/agents/memory/__pycache__/__init__.cpython-312.pyc +0 -0
  59. {acra_cli-0.1.2 → acra_cli-0.1.4}/acra/agents/memory/__pycache__/memory_agent.cpython-312.pyc +0 -0
  60. {acra_cli-0.1.2 → acra_cli-0.1.4}/acra/agents/memory/__pycache__/memory_manager.cpython-312.pyc +0 -0
  61. {acra_cli-0.1.2 → acra_cli-0.1.4}/acra/agents/memory/__pycache__/retrieval.cpython-312.pyc +0 -0
  62. {acra_cli-0.1.2 → acra_cli-0.1.4}/acra/agents/memory/memory_agent.py +0 -0
  63. {acra_cli-0.1.2 → acra_cli-0.1.4}/acra/agents/memory/memory_manager.py +0 -0
  64. {acra_cli-0.1.2 → acra_cli-0.1.4}/acra/agents/memory/retrieval.py +0 -0
  65. {acra_cli-0.1.2 → acra_cli-0.1.4}/acra/agents/planner/__init__.py +0 -0
  66. {acra_cli-0.1.2 → acra_cli-0.1.4}/acra/agents/planner/__pycache__/__init__.cpython-312.pyc +0 -0
  67. {acra_cli-0.1.2 → acra_cli-0.1.4}/acra/agents/planner/__pycache__/planner_agent.cpython-312.pyc +0 -0
  68. {acra_cli-0.1.2 → acra_cli-0.1.4}/acra/agents/planner/__pycache__/planner_chain.cpython-312.pyc +0 -0
  69. {acra_cli-0.1.2 → acra_cli-0.1.4}/acra/agents/planner/planner_agent.py +0 -0
  70. {acra_cli-0.1.2 → acra_cli-0.1.4}/acra/agents/planner/planner_chain.py +0 -0
  71. {acra_cli-0.1.2 → acra_cli-0.1.4}/acra/agents/researcher/__init__.py +0 -0
  72. {acra_cli-0.1.2 → acra_cli-0.1.4}/acra/agents/researcher/__pycache__/__init__.cpython-312.pyc +0 -0
  73. {acra_cli-0.1.2 → acra_cli-0.1.4}/acra/agents/researcher/__pycache__/researcher_agent.cpython-312.pyc +0 -0
  74. {acra_cli-0.1.2 → acra_cli-0.1.4}/acra/agents/researcher/__pycache__/researcher_chain.cpython-312.pyc +0 -0
  75. {acra_cli-0.1.2 → acra_cli-0.1.4}/acra/agents/researcher/researcher_agent.py +0 -0
  76. {acra_cli-0.1.2 → acra_cli-0.1.4}/acra/agents/researcher/researcher_chain.py +0 -0
  77. {acra_cli-0.1.2 → acra_cli-0.1.4}/acra/brain/__init__.py +0 -0
  78. {acra_cli-0.1.2 → acra_cli-0.1.4}/acra/brain/model_registry.py +0 -0
  79. {acra_cli-0.1.2 → acra_cli-0.1.4}/acra/brain/provider_manager.py +0 -0
  80. {acra_cli-0.1.2 → acra_cli-0.1.4}/acra/commands/brain.py +0 -0
  81. {acra_cli-0.1.2 → acra_cli-0.1.4}/acra/commands/config.py +0 -0
  82. {acra_cli-0.1.2 → acra_cli-0.1.4}/acra/commands/context.py +0 -0
  83. {acra_cli-0.1.2 → acra_cli-0.1.4}/acra/commands/graph.py +0 -0
  84. {acra_cli-0.1.2 → acra_cli-0.1.4}/acra/commands/keys.py +0 -0
  85. {acra_cli-0.1.2 → acra_cli-0.1.4}/acra/commands/logs.py +0 -0
  86. {acra_cli-0.1.2 → acra_cli-0.1.4}/acra/commands/memory.py +0 -0
  87. {acra_cli-0.1.2 → acra_cli-0.1.4}/acra/commands/plugin.py +0 -0
  88. {acra_cli-0.1.2 → acra_cli-0.1.4}/acra/commands/session.py +0 -0
  89. {acra_cli-0.1.2 → acra_cli-0.1.4}/acra/commands/utils.py +0 -0
  90. {acra_cli-0.1.2 → acra_cli-0.1.4}/acra/config/__init__.py +0 -0
  91. {acra_cli-0.1.2 → acra_cli-0.1.4}/acra/config/__pycache__/__init__.cpython-312.pyc +0 -0
  92. {acra_cli-0.1.2 → acra_cli-0.1.4}/acra/config/__pycache__/defaults.cpython-312.pyc +0 -0
  93. {acra_cli-0.1.2 → acra_cli-0.1.4}/acra/config/__pycache__/profile_manager.cpython-312.pyc +0 -0
  94. {acra_cli-0.1.2 → acra_cli-0.1.4}/acra/config/defaults.py +0 -0
  95. {acra_cli-0.1.2 → acra_cli-0.1.4}/acra/config/profile_manager.py +0 -0
  96. {acra_cli-0.1.2 → acra_cli-0.1.4}/acra/execution/__init__.py +0 -0
  97. {acra_cli-0.1.2 → acra_cli-0.1.4}/acra/execution/logs/__init__.py +0 -0
  98. {acra_cli-0.1.2 → acra_cli-0.1.4}/acra/execution/logs/error_logs/__init__.py +0 -0
  99. {acra_cli-0.1.2 → acra_cli-0.1.4}/acra/execution/logs/execution_logs/__init__.py +0 -0
  100. {acra_cli-0.1.2 → acra_cli-0.1.4}/acra/execution/sandbox/__init__.py +0 -0
  101. {acra_cli-0.1.2 → acra_cli-0.1.4}/acra/execution/sandbox/docker_executor.py +0 -0
  102. {acra_cli-0.1.2 → acra_cli-0.1.4}/acra/execution/sandbox/isolated_runner.py +0 -0
  103. {acra_cli-0.1.2 → acra_cli-0.1.4}/acra/execution/sandbox/sandbox_manager.py +0 -0
  104. {acra_cli-0.1.2 → acra_cli-0.1.4}/acra/graph/__init__.py +0 -0
  105. {acra_cli-0.1.2 → acra_cli-0.1.4}/acra/graph/checkpoint.py +0 -0
  106. {acra_cli-0.1.2 → acra_cli-0.1.4}/acra/graph/conditional_edges.py +0 -0
  107. {acra_cli-0.1.2 → acra_cli-0.1.4}/acra/graph/edges.py +0 -0
  108. {acra_cli-0.1.2 → acra_cli-0.1.4}/acra/graph/graph_visualizer.py +0 -0
  109. {acra_cli-0.1.2 → acra_cli-0.1.4}/acra/graph/nodes.py +0 -0
  110. {acra_cli-0.1.2 → acra_cli-0.1.4}/acra/graph/router.py +0 -0
  111. {acra_cli-0.1.2 → acra_cli-0.1.4}/acra/graph/state.py +0 -0
  112. {acra_cli-0.1.2 → acra_cli-0.1.4}/acra/graph/workflow.py +0 -0
  113. {acra_cli-0.1.2 → acra_cli-0.1.4}/acra/memory/__init__.py +0 -0
  114. {acra_cli-0.1.2 → acra_cli-0.1.4}/acra/memory/checkpoints/__init__.py +0 -0
  115. {acra_cli-0.1.2 → acra_cli-0.1.4}/acra/memory/checkpoints/data/__init__.py +0 -0
  116. {acra_cli-0.1.2 → acra_cli-0.1.4}/acra/memory/checkpoints/postgres_checkpoint.py +0 -0
  117. {acra_cli-0.1.2 → acra_cli-0.1.4}/acra/memory/checkpoints/sqlite_checkpoint.py +0 -0
  118. {acra_cli-0.1.2 → acra_cli-0.1.4}/acra/memory/chroma_db/__init__.py +0 -0
  119. {acra_cli-0.1.2 → acra_cli-0.1.4}/acra/memory/conversation_memory/__init__.py +0 -0
  120. {acra_cli-0.1.2 → acra_cli-0.1.4}/acra/memory/conversation_memory/long_term.py +0 -0
  121. {acra_cli-0.1.2 → acra_cli-0.1.4}/acra/memory/conversation_memory/short_term.py +0 -0
  122. {acra_cli-0.1.2 → acra_cli-0.1.4}/acra/memory/storage/__init__.py +0 -0
  123. {acra_cli-0.1.2 → acra_cli-0.1.4}/acra/memory/vector_store/__init__.py +0 -0
  124. {acra_cli-0.1.2 → acra_cli-0.1.4}/acra/memory/vector_store/chroma_store.py +0 -0
  125. {acra_cli-0.1.2 → acra_cli-0.1.4}/acra/memory/vector_store/embeddings.py +0 -0
  126. {acra_cli-0.1.2 → acra_cli-0.1.4}/acra/observability/__init__.py +0 -0
  127. {acra_cli-0.1.2 → acra_cli-0.1.4}/acra/observability/langsmith_tracing.py +0 -0
  128. {acra_cli-0.1.2 → acra_cli-0.1.4}/acra/observability/metrics.py +0 -0
  129. {acra_cli-0.1.2 → acra_cli-0.1.4}/acra/observability/monitoring.py +0 -0
  130. {acra_cli-0.1.2 → acra_cli-0.1.4}/acra/observability/token_tracking.py +0 -0
  131. {acra_cli-0.1.2 → acra_cli-0.1.4}/acra/prompts/__init__.py +0 -0
  132. {acra_cli-0.1.2 → acra_cli-0.1.4}/acra/schemas/__init__.py +0 -0
  133. {acra_cli-0.1.2 → acra_cli-0.1.4}/acra/schemas/__pycache__/__init__.cpython-312.pyc +0 -0
  134. {acra_cli-0.1.2 → acra_cli-0.1.4}/acra/schemas/__pycache__/coder_schema.cpython-312.pyc +0 -0
  135. {acra_cli-0.1.2 → acra_cli-0.1.4}/acra/schemas/__pycache__/critic_schema.cpython-312.pyc +0 -0
  136. {acra_cli-0.1.2 → acra_cli-0.1.4}/acra/schemas/__pycache__/execution_schema.cpython-312.pyc +0 -0
  137. {acra_cli-0.1.2 → acra_cli-0.1.4}/acra/schemas/__pycache__/planner_schema.cpython-312.pyc +0 -0
  138. {acra_cli-0.1.2 → acra_cli-0.1.4}/acra/schemas/__pycache__/researcher_schema.cpython-312.pyc +0 -0
  139. {acra_cli-0.1.2 → acra_cli-0.1.4}/acra/schemas/__pycache__/shared_schema.cpython-312.pyc +0 -0
  140. {acra_cli-0.1.2 → acra_cli-0.1.4}/acra/schemas/coder_schema.py +0 -0
  141. {acra_cli-0.1.2 → acra_cli-0.1.4}/acra/schemas/critic_schema.py +0 -0
  142. {acra_cli-0.1.2 → acra_cli-0.1.4}/acra/schemas/execution_schema.py +0 -0
  143. {acra_cli-0.1.2 → acra_cli-0.1.4}/acra/schemas/planner_schema.py +0 -0
  144. {acra_cli-0.1.2 → acra_cli-0.1.4}/acra/schemas/researcher_schema.py +0 -0
  145. {acra_cli-0.1.2 → acra_cli-0.1.4}/acra/schemas/shared_schema.py +0 -0
  146. {acra_cli-0.1.2 → acra_cli-0.1.4}/acra/tools/__init__.py +0 -0
  147. {acra_cli-0.1.2 → acra_cli-0.1.4}/acra/tools/code_tools/__init__.py +0 -0
  148. {acra_cli-0.1.2 → acra_cli-0.1.4}/acra/tools/code_tools/file_reader.py +0 -0
  149. {acra_cli-0.1.2 → acra_cli-0.1.4}/acra/tools/code_tools/file_writer.py +0 -0
  150. {acra_cli-0.1.2 → acra_cli-0.1.4}/acra/tools/code_tools/python_repl.py +0 -0
  151. {acra_cli-0.1.2 → acra_cli-0.1.4}/acra/tools/code_tools/terminal_runner.py +0 -0
  152. {acra_cli-0.1.2 → acra_cli-0.1.4}/acra/tools/github_tools/__init__.py +0 -0
  153. {acra_cli-0.1.2 → acra_cli-0.1.4}/acra/tools/github_tools/commit_generator.py +0 -0
  154. {acra_cli-0.1.2 → acra_cli-0.1.4}/acra/tools/github_tools/github_search.py +0 -0
  155. {acra_cli-0.1.2 → acra_cli-0.1.4}/acra/tools/github_tools/repo_analyzer.py +0 -0
  156. {acra_cli-0.1.2 → acra_cli-0.1.4}/acra/tools/integration_test_helper.py +0 -0
  157. {acra_cli-0.1.2 → acra_cli-0.1.4}/acra/tools/validation_tools/__init__.py +0 -0
  158. {acra_cli-0.1.2 → acra_cli-0.1.4}/acra/tools/validation_tools/dependency_checker.py +0 -0
  159. {acra_cli-0.1.2 → acra_cli-0.1.4}/acra/tools/validation_tools/environment_config_validator.py +0 -0
  160. {acra_cli-0.1.2 → acra_cli-0.1.4}/acra/tools/validation_tools/http_validator.py +0 -0
  161. {acra_cli-0.1.2 → acra_cli-0.1.4}/acra/tools/validation_tools/response_validator.py +0 -0
  162. {acra_cli-0.1.2 → acra_cli-0.1.4}/acra/tools/validation_tools/security_checker.py +0 -0
  163. {acra_cli-0.1.2 → acra_cli-0.1.4}/acra/tools/validation_tools/syntax_checker.py +0 -0
  164. {acra_cli-0.1.2 → acra_cli-0.1.4}/acra/tools/validation_tools/web_framework_validator.py +0 -0
  165. {acra_cli-0.1.2 → acra_cli-0.1.4}/acra/tools/web_tools/__init__.py +0 -0
  166. {acra_cli-0.1.2 → acra_cli-0.1.4}/acra/tools/web_tools/arxiv_search.py +0 -0
  167. {acra_cli-0.1.2 → acra_cli-0.1.4}/acra/tools/web_tools/serpapi_search.py +0 -0
  168. {acra_cli-0.1.2 → acra_cli-0.1.4}/acra/tools/web_tools/tavily_search.py +0 -0
  169. {acra_cli-0.1.2 → acra_cli-0.1.4}/acra/ui/__init__.py +0 -0
  170. {acra_cli-0.1.2 → acra_cli-0.1.4}/acra/ui/__pycache__/__init__.cpython-312.pyc +0 -0
  171. {acra_cli-0.1.2 → acra_cli-0.1.4}/acra/ui/__pycache__/components.cpython-312.pyc +0 -0
  172. {acra_cli-0.1.2 → acra_cli-0.1.4}/acra/ui/__pycache__/theme.cpython-312.pyc +0 -0
  173. {acra_cli-0.1.2 → acra_cli-0.1.4}/acra/ui/components.py +0 -0
  174. {acra_cli-0.1.2 → acra_cli-0.1.4}/acra/ui/theme.py +0 -0
  175. {acra_cli-0.1.2 → acra_cli-0.1.4}/acra/utils/__init__.py +0 -0
  176. {acra_cli-0.1.2 → acra_cli-0.1.4}/acra/utils/context_manager.py +0 -0
  177. {acra_cli-0.1.2 → acra_cli-0.1.4}/acra/utils/keyring_manager.py +0 -0
  178. {acra_cli-0.1.2 → acra_cli-0.1.4}/acra/utils/output_formatter.py +0 -0
  179. {acra_cli-0.1.2 → acra_cli-0.1.4}/acra/utils/session_manager.py +0 -0
  180. {acra_cli-0.1.2 → acra_cli-0.1.4}/acra_cli.egg-info/dependency_links.txt +0 -0
  181. {acra_cli-0.1.2 → acra_cli-0.1.4}/acra_cli.egg-info/entry_points.txt +0 -0
  182. {acra_cli-0.1.2 → acra_cli-0.1.4}/acra_cli.egg-info/requires.txt +0 -0
  183. {acra_cli-0.1.2 → acra_cli-0.1.4}/acra_cli.egg-info/top_level.txt +0 -0
  184. {acra_cli-0.1.2 → acra_cli-0.1.4}/requirements.txt +0 -0
  185. {acra_cli-0.1.2 → acra_cli-0.1.4}/setup.cfg +0 -0
  186. {acra_cli-0.1.2 → acra_cli-0.1.4}/setup.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: acra-cli
3
- Version: 0.1.2
3
+ Version: 0.1.4
4
4
  Summary: Agentic CLI for LLM task execution, research, and workflow automation.
5
5
  Author: Raj Tembe
6
6
  License: GNU Affero General Public License v3
@@ -1,6 +1,6 @@
1
1
  """acra package root."""
2
2
 
3
- __version__ = "0.1.2"
3
+ __version__ = "0.1.4"
4
4
 
5
5
  from .cli import main
6
6
 
@@ -2,11 +2,17 @@
2
2
 
3
3
  import typer
4
4
 
5
+ import acra
6
+ from acra.commands.ask import ask, build, explain, fix, review, run
7
+ from acra.commands.research import research
5
8
  from acra.commands import (
6
9
  serve_app,
7
10
  config_app,
8
11
  keys_app,
9
- research_app,
12
+ brain_app,
13
+ context_app,
14
+ logs_app,
15
+ plugin_app,
10
16
  memory_app,
11
17
  session_app,
12
18
  graph_app,
@@ -19,11 +25,28 @@ app = typer.Typer(add_completion=True)
19
25
  app.add_typer(serve_app, name="serve")
20
26
  app.add_typer(config_app, name="config")
21
27
  app.add_typer(keys_app, name="keys")
22
- app.add_typer(research_app, name="research")
23
28
  app.add_typer(memory_app, name="memory")
24
29
  app.add_typer(session_app, name="session")
25
30
  app.add_typer(graph_app, name="graph")
26
31
  app.add_typer(utils_app, name="workspace")
32
+ app.add_typer(brain_app, name="brain", help="Brain management commands for acra.")
33
+ app.add_typer(context_app, name="context", help="Context management commands for acra.")
34
+ app.add_typer(logs_app, name="logs", help="Logging commands for acra.")
35
+ app.add_typer(plugin_app, name="plugin", help="Plugin commands for acra.")
36
+
37
+ app.command("ask")(ask)
38
+ app.command("build")(build)
39
+ app.command("fix")(fix)
40
+ app.command("review")(review)
41
+ app.command("explain")(explain)
42
+ app.command("run")(run)
43
+ app.command("research")(research)
44
+
45
+
46
+ def _version_callback(value: bool):
47
+ if value:
48
+ typer.echo(acra.__version__)
49
+ raise typer.Exit()
27
50
 
28
51
 
29
52
  def app_main() -> None:
@@ -34,19 +57,32 @@ def app_main() -> None:
34
57
  @app.callback(invoke_without_command=True)
35
58
  def main(
36
59
  ctx: typer.Context,
60
+ version: bool = typer.Option(
61
+ False,
62
+ "--version",
63
+ callback=_version_callback,
64
+ is_eager=True,
65
+ help="Show the installed acra version and exit.",
66
+ ),
37
67
  profile: str = typer.Option(None, "--profile", help="Profile to use."),
38
68
  workspace: str = typer.Option(None, "--workspace", help="Override workspace path."),
39
- no_memory: bool = typer.Option(False, "--no-memory", help="Run without memory."),
69
+ use_memory: bool = typer.Option(True, "--memory/--no-memory", help="Use memory."),
40
70
  dry_run: bool = typer.Option(False, "--dry-run", help="Display planned actions without executing."),
41
71
  json_output: bool = typer.Option(False, "--json", help="Output JSON-formatted results."),
42
72
  verbose: bool = typer.Option(False, "--verbose", "-v", help="Enable verbose logging."),
43
73
  quiet: bool = typer.Option(False, "--quiet", "-q", help="Suppress output."),
44
74
  timeout: int = typer.Option(0, "--timeout", help="Override execution timeout in seconds."),
75
+ party: bool = typer.Option(
76
+ False,
77
+ "--party",
78
+ "--easter-egg",
79
+ help="Show the rainbow party-mode startup banner.",
80
+ ),
45
81
  ):
46
82
  """acra: Agentic CLI for LLM powered task execution and research workflows."""
47
83
  if ctx.invoked_subcommand is None:
48
- launch_shell(profile=profile, workspace=workspace)
84
+ launch_shell(profile=profile, workspace=workspace, party=party)
49
85
 
50
86
 
51
87
  if __name__ == "__main__":
52
- app_main()
88
+ app_main()
@@ -1,6 +1,7 @@
1
1
  """acra command modules."""
2
2
 
3
3
  from .serve import app as serve_app
4
+ from .ask import app as ask_app
4
5
  from .config import app as config_app
5
6
  from .brain import app as brain_app
6
7
  from .research import app as research_app
@@ -15,6 +16,7 @@ from .utils import app as utils_app
15
16
 
16
17
  __all__ = [
17
18
  "serve_app",
19
+ "ask_app",
18
20
  "config_app",
19
21
  "brain_app",
20
22
  "research_app",
@@ -0,0 +1,106 @@
1
+ """Agent task commands for acra."""
2
+
3
+ import uuid
4
+ from typing import Optional
5
+
6
+ import typer
7
+
8
+ from acra.graph.workflow import OmniAgentCallbacks, omniagent_graph
9
+ from acra.ui.components import render_panel
10
+
11
+ app = typer.Typer(help="Agent task commands for acra.")
12
+
13
+
14
+ def _run_task(
15
+ task: str,
16
+ task_label: str,
17
+ profile: Optional[str] = None,
18
+ use_memory: bool = True,
19
+ interactive: bool = False,
20
+ ):
21
+ state = {
22
+ "user_request": task,
23
+ "task_label": task_label,
24
+ "no_memory": not use_memory,
25
+ "profile": profile,
26
+ "interactive": interactive,
27
+ }
28
+ # The compiled graph always carries a checkpointer, which requires a
29
+ # thread_id on every invoke call regardless of whether the caller wants
30
+ # persistence. A fresh id is generated per invocation; when --no-memory
31
+ # is set, nothing is done with it beyond satisfying the checkpointer, so
32
+ # no state is meaningfully persisted or reused across runs.
33
+ thread_id = str(uuid.uuid4())
34
+ config = {
35
+ "callbacks": [OmniAgentCallbacks()],
36
+ "configurable": {"thread_id": thread_id},
37
+ }
38
+ result = omniagent_graph.invoke(state, config=config)
39
+ render_panel(result, title=task_label)
40
+ return result
41
+
42
+
43
+ @app.command()
44
+ def ask(
45
+ task: str = typer.Argument(..., help="Task or question for the agent."),
46
+ profile: Optional[str] = typer.Option(None, help="Profile to use."),
47
+ use_memory: bool = typer.Option(True, "--memory/--no-memory", help="Use memory for this task."),
48
+ interactive: bool = typer.Option(False, "--interactive", help="Route agent approval requests to the human node."),
49
+ ):
50
+ """Ask the assistant a question."""
51
+ return _run_task(task, "ask", profile, use_memory, interactive)
52
+
53
+
54
+ @app.command()
55
+ def build(
56
+ task: str = typer.Argument(..., help="Build task for the agent."),
57
+ profile: Optional[str] = typer.Option(None, help="Profile to use."),
58
+ use_memory: bool = typer.Option(True, "--memory/--no-memory", help="Use memory for this task."),
59
+ interactive: bool = typer.Option(False, "--interactive", help="Route agent approval requests to the human node."),
60
+ ):
61
+ """Run a build workflow for a project task."""
62
+ return _run_task(task, "build", profile, use_memory, interactive)
63
+
64
+
65
+ @app.command()
66
+ def fix(
67
+ task: str = typer.Argument(..., help="Code issue or bug for the agent to fix."),
68
+ profile: Optional[str] = typer.Option(None, help="Profile to use."),
69
+ use_memory: bool = typer.Option(True, "--memory/--no-memory", help="Use memory for this task."),
70
+ interactive: bool = typer.Option(False, "--interactive", help="Route agent approval requests to the human node."),
71
+ ):
72
+ """Run a fix workflow for a code issue."""
73
+ return _run_task(task, "fix", profile, use_memory, interactive)
74
+
75
+
76
+ @app.command()
77
+ def review(
78
+ task: str = typer.Argument(..., help="Code, design, or task to review."),
79
+ profile: Optional[str] = typer.Option(None, help="Profile to use."),
80
+ use_memory: bool = typer.Option(True, "--memory/--no-memory", help="Use memory for this task."),
81
+ interactive: bool = typer.Option(False, "--interactive", help="Route agent approval requests to the human node."),
82
+ ):
83
+ """Review code or design with the critic pipeline."""
84
+ return _run_task(task, "review", profile, use_memory, interactive)
85
+
86
+
87
+ @app.command()
88
+ def explain(
89
+ task: str = typer.Argument(..., help="Concept or code path to explain."),
90
+ profile: Optional[str] = typer.Option(None, help="Profile to use."),
91
+ use_memory: bool = typer.Option(True, "--memory/--no-memory", help="Use memory for this task."),
92
+ interactive: bool = typer.Option(False, "--interactive", help="Route agent approval requests to the human node."),
93
+ ):
94
+ """Explain a technical concept or code path."""
95
+ return _run_task(task, "explain", profile, use_memory, interactive)
96
+
97
+
98
+ @app.command()
99
+ def run(
100
+ task: str = typer.Argument(..., help="Task for the agent to execute."),
101
+ profile: Optional[str] = typer.Option(None, help="Profile to use."),
102
+ use_memory: bool = typer.Option(True, "--memory/--no-memory", help="Use memory for this task."),
103
+ interactive: bool = typer.Option(False, "--interactive", help="Route agent approval requests to the human node."),
104
+ ):
105
+ """Execute a task using the executor agent."""
106
+ return _run_task(task, "run", profile, use_memory, interactive)
@@ -1,6 +1,7 @@
1
1
  """Research command module for acra."""
2
2
 
3
3
  import json
4
+ import uuid
4
5
  import typer
5
6
  from typing import List, Optional
6
7
 
@@ -27,7 +28,11 @@ def research(
27
28
  output: Optional[str] = typer.Option(None, help="Write research output to a file."),
28
29
  save: bool = typer.Option(False, help="Persist research output into memory."),
29
30
  follow_up: bool = typer.Option(False, help="Keep the session open for follow-up questions."),
30
- no_memory: bool = typer.Option(False, help="Skip memory persistence for this research."),
31
+ use_memory: bool = typer.Option(
32
+ True,
33
+ "--memory/--no-memory",
34
+ help="Use memory persistence for this research.",
35
+ ),
31
36
  profile: Optional[str] = typer.Option(None, help="Profile to use."),
32
37
  json_output: bool = typer.Option(False, "--json", help="Output JSON instead of rich text."),
33
38
  verbose: bool = typer.Option(False, "--verbose", "-v", help="Show detailed debug output."),
@@ -45,11 +50,18 @@ def research(
45
50
  "research_depth": depth,
46
51
  "research_sources": source_list,
47
52
  "follow_up": follow_up,
48
- "save_to_memory": save and not no_memory,
53
+ "save_to_memory": save and use_memory,
49
54
  "profile": profile,
50
55
  }
51
56
 
52
- result = workflow.invoke(state, config={"callbacks": [OmniAgentCallbacks()]})
57
+ thread_id = str(uuid.uuid4())
58
+ result = workflow.invoke(
59
+ state,
60
+ config={
61
+ "callbacks": [OmniAgentCallbacks()],
62
+ "configurable": {"thread_id": thread_id},
63
+ },
64
+ )
53
65
 
54
66
  report = format_research_report(result, output_format=format)
55
67
 
@@ -62,4 +74,4 @@ def research(
62
74
 
63
75
  render_panel(report, title="Research Results")
64
76
  if json_output:
65
- typer.echo(json.dumps(report, indent=2))
77
+ typer.echo(json.dumps(report, indent=2))
@@ -7,7 +7,15 @@ app = typer.Typer(help="Interactive shell for acra.", invoke_without_command=Tru
7
7
 
8
8
 
9
9
  @app.callback()
10
- def serve(ctx: typer.Context):
10
+ def serve(
11
+ ctx: typer.Context,
12
+ party: bool = typer.Option(
13
+ False,
14
+ "--party",
15
+ "--easter-egg",
16
+ help="Show the rainbow party-mode startup banner.",
17
+ ),
18
+ ):
11
19
  """Launch the interactive acra shell."""
12
20
  if ctx.invoked_subcommand is None:
13
- launch_shell()
21
+ launch_shell(party=party)
@@ -0,0 +1,287 @@
1
+ """Animated startup banner and easter eggs for acra.
2
+
3
+ This module owns the ANSI-driven intro sequence shown when the interactive
4
+ shell starts (`acra` with no subcommand, or `acra serve`):
5
+
6
+ 1. The "ACRA" wordmark is revealed with a left-to-right glitch/scan
7
+ animation (or, in --party mode, a rainbow cycle with an emoji burst).
8
+ 2. A subtitle is typed out character by character.
9
+ 3. A tagline fades in (swapped for a holiday-specific line on a handful
10
+ of dates).
11
+ 4. The version number is shown with a short spinner that resolves to a
12
+ "ready" checkmark, similar to Copilot CLI's startup indicator.
13
+
14
+ Everything here is pure ANSI escape codes + stdlib (no extra dependencies).
15
+
16
+ Two independent accessibility/scripting gates, matching conventions used
17
+ across the CLI ecosystem (see https://no-color.org, https://force-color.org,
18
+ and GitHub's writeup on building the Copilot CLI banner: fast-changing
19
+ terminal output is a real screen-reader and low-vision concern, not just a
20
+ cosmetic one):
21
+
22
+ * Color (`_supports_color`) is disabled by NO_COLOR or TERM=dumb, and can
23
+ be forced back on with FORCE_COLOR even when piped.
24
+ * Timed motion (`_animations_enabled`) is disabled whenever stdout isn't a
25
+ real interactive terminal, in CI, or when ACRA_NO_ANIMATION is set -
26
+ falling back to an instant, fully-resolved static print so scripting,
27
+ piping, and tests stay fast and deterministic.
28
+
29
+ These are independent: a NO_COLOR user on a real terminal still gets the
30
+ scan/typing motion, just monochrome; a CI run gets neither, instantly.
31
+ """
32
+
33
+ from __future__ import annotations
34
+
35
+ import os
36
+ import random
37
+ import sys
38
+ import time
39
+ from datetime import date
40
+ from typing import Iterable, List, Optional
41
+
42
+ from acra import __version__
43
+ from acra.ui.banner import WELCOME_TEXT
44
+
45
+ RESET = "\033[0m"
46
+ BOLD = "\033[1m"
47
+ DIM = "\033[2m"
48
+
49
+ COLORS = {
50
+ "black": "\033[30m",
51
+ "red": "\033[31m",
52
+ "green": "\033[32m",
53
+ "yellow": "\033[33m",
54
+ "blue": "\033[34m",
55
+ "magenta": "\033[35m",
56
+ "cyan": "\033[36m",
57
+ "white": "\033[37m",
58
+ "bright_red": "\033[91m",
59
+ "bright_green": "\033[92m",
60
+ "bright_yellow": "\033[93m",
61
+ "bright_blue": "\033[94m",
62
+ "bright_magenta": "\033[95m",
63
+ "bright_cyan": "\033[96m",
64
+ "bright_white": "\033[97m",
65
+ }
66
+
67
+ # ANSI-Shadow-style block glyphs. Only the letters ACRA needs are defined;
68
+ # each glyph is a fixed 6-row x 8-column block so rows line up cleanly
69
+ # whichever letters are combined.
70
+ _GLYPHS = {
71
+ "A": [
72
+ " █████╗ ",
73
+ "██╔══██╗",
74
+ "███████║",
75
+ "██╔══██║",
76
+ "██║ ██║",
77
+ "╚═╝ ╚═╝",
78
+ ],
79
+ "C": [
80
+ " ██████╗",
81
+ "██╔════╝",
82
+ "██║ ",
83
+ "██║ ",
84
+ "╚██████╗",
85
+ " ╚═════╝",
86
+ ],
87
+ "R": [
88
+ "██████╗ ",
89
+ "██╔══██╗",
90
+ "██████╔╝",
91
+ "██╔══██╗",
92
+ "██║ ██║",
93
+ "╚═╝ ╚═╝",
94
+ ],
95
+ }
96
+
97
+ WORDMARK = "ACRA"
98
+ _GLYPH_HEIGHT = 6
99
+
100
+ # Vertical gradient applied to the wordmark, top row to bottom row.
101
+ _GRADIENT = ["bright_cyan", "bright_cyan", "cyan", "bright_magenta", "magenta", "bright_yellow"]
102
+
103
+ _RAINBOW_CYCLE = [
104
+ "bright_red",
105
+ "bright_yellow",
106
+ "bright_green",
107
+ "bright_cyan",
108
+ "bright_blue",
109
+ "bright_magenta",
110
+ ]
111
+
112
+ _GLITCH_CHARS = "@#$%&*+=-/\\|<>?░▒▓"
113
+ _PARTY_EMOJIS = ["🎉", "✨", "🎊", "🚀", "🔥", "🥳", "⭐", "💥"]
114
+
115
+ # Same frame set as the "dots" spinner in the widely-used cli-spinners
116
+ # package (npm), the de facto standard braille spinner recognized across
117
+ # npm/yarn/ora-based tools.
118
+ _SPINNER_FRAMES = "⠋⠙⠹⠸⠼⠴⠦⠧⠇⠏"
119
+
120
+ _HOLIDAY_TAGLINES = {
121
+ (1, 1): "New year, new agent runs. Let's build.",
122
+ (4, 1): "ACRA: (mostly) not lying to you today.",
123
+ (10, 31): "ACRA: coding like it's Halloween.",
124
+ (12, 25): "Shipping code, not presents, today.",
125
+ }
126
+
127
+
128
+ def _supports_color() -> bool:
129
+ """https://no-color.org / https://force-color.org, checked in that order."""
130
+ if os.environ.get("FORCE_COLOR", "") != "":
131
+ return True
132
+ if os.environ.get("NO_COLOR", "") != "":
133
+ return False
134
+ if os.environ.get("TERM") == "dumb":
135
+ return False
136
+ return True
137
+
138
+
139
+ def _animations_enabled() -> bool:
140
+ """Whether to run the timed ANSI animations, or fall back to a static print."""
141
+ if os.environ.get("ACRA_NO_ANIMATION"):
142
+ return False
143
+ if os.environ.get("CI"):
144
+ return False
145
+ return sys.stdout.isatty()
146
+
147
+
148
+ def _style(text: str, color: Optional[str] = None, bold: bool = False, dim: bool = False) -> str:
149
+ """Wrap text in ANSI codes, or return it unchanged when color is disabled."""
150
+ if not _supports_color():
151
+ return text
152
+ codes = ""
153
+ if bold:
154
+ codes += BOLD
155
+ if dim:
156
+ codes += DIM
157
+ if color:
158
+ codes += COLORS.get(color, "")
159
+ return f"{codes}{text}{RESET}" if codes else text
160
+
161
+
162
+ def _build_art(word: str = WORDMARK, spacing: str = " ") -> List[str]:
163
+ return [spacing.join(_GLYPHS[letter][row] for letter in word) for row in range(_GLYPH_HEIGHT)]
164
+
165
+
166
+ def _print_art_static(art_lines: Iterable[str], gradient: List[str]) -> None:
167
+ for row_idx, line in enumerate(art_lines):
168
+ print(_style(line, color=gradient[row_idx % len(gradient)], bold=True))
169
+
170
+
171
+ def _glitch_scan_reveal(art_lines: List[str], gradient: List[str], steps: int = 10, delay: float = 0.025) -> None:
172
+ """Reveal the wordmark left-to-right, resolving glitch characters into the real ones."""
173
+ if not _animations_enabled():
174
+ _print_art_static(art_lines, gradient)
175
+ return
176
+
177
+ width = max(len(line) for line in art_lines)
178
+ height = len(art_lines)
179
+
180
+ sys.stdout.write("\n" * height)
181
+ for step in range(1, steps + 1):
182
+ threshold = int(width * step / steps)
183
+ sys.stdout.write(f"\033[{height}A")
184
+ for row_idx, line in enumerate(art_lines):
185
+ rendered = [
186
+ " " if ch == " " else (ch if col < threshold else random.choice(_GLITCH_CHARS))
187
+ for col, ch in enumerate(line)
188
+ ]
189
+ styled = _style("".join(rendered), color=gradient[row_idx % len(gradient)], bold=True)
190
+ sys.stdout.write(f"\033[K{styled}\n")
191
+ sys.stdout.flush()
192
+ time.sleep(delay)
193
+
194
+
195
+ def _party_reveal(art_lines: List[str], frames: int = 10, delay: float = 0.09) -> None:
196
+ """Rainbow-cycling wordmark with a burst of flying emojis, for --party / --easter-egg."""
197
+ if not _animations_enabled():
198
+ print(_style("PARTY MODE \U0001f389", color="bright_magenta", bold=True))
199
+ _print_art_static(art_lines, _RAINBOW_CYCLE)
200
+ return
201
+
202
+ width = max(len(line) for line in art_lines)
203
+ height = len(art_lines)
204
+
205
+ sys.stdout.write("\n" * (height + 1))
206
+ for frame in range(frames):
207
+ sys.stdout.write(f"\033[{height + 1}A")
208
+ for row_idx, line in enumerate(art_lines):
209
+ color = _RAINBOW_CYCLE[(row_idx + frame) % len(_RAINBOW_CYCLE)]
210
+ sys.stdout.write(f"\033[K{_style(line, color=color, bold=True)}\n")
211
+ emoji_row = "".join(
212
+ random.choice(_PARTY_EMOJIS) if random.random() < 0.3 else " " for _ in range(width // 2)
213
+ )
214
+ sys.stdout.write(f"\033[K{emoji_row}\n")
215
+ sys.stdout.flush()
216
+ time.sleep(delay)
217
+
218
+ print(_style("\U0001f389 PARTY MODE ACTIVATED \U0001f389", color="bright_magenta", bold=True))
219
+
220
+
221
+ def _type_line(text: str, color: Optional[str] = None, delay: float = 0.012) -> None:
222
+ if not _animations_enabled():
223
+ print(_style(text, color=color))
224
+ return
225
+ for ch in text:
226
+ sys.stdout.write(_style(ch, color=color))
227
+ sys.stdout.flush()
228
+ time.sleep(delay)
229
+ sys.stdout.write("\n")
230
+
231
+
232
+ def _fade_in_lines(lines: Iterable[str], dim: bool = False, delay: float = 0.12) -> None:
233
+ for line in lines:
234
+ if _animations_enabled():
235
+ time.sleep(delay)
236
+ print(_style(line, dim=dim))
237
+
238
+
239
+ def _spinner_version_line(accent: str, frames: int = 14, delay: float = 0.035) -> None:
240
+ """Show 'acra vX.Y.Z' with a small spinner that resolves into a ready check."""
241
+ label = _style(f"acra v{__version__}", color=accent, bold=True)
242
+ ready = _style("\u2713 ready", color="bright_green")
243
+
244
+ if not _animations_enabled():
245
+ print(f"{label} {ready}")
246
+ return
247
+
248
+ for i in range(frames):
249
+ frame = _SPINNER_FRAMES[i % len(_SPINNER_FRAMES)]
250
+ status = _style(f"{frame} initializing\u2026", dim=True)
251
+ sys.stdout.write(f"\r{label} {status}\033[K")
252
+ sys.stdout.flush()
253
+ time.sleep(delay)
254
+ sys.stdout.write(f"\r{label} {ready}\033[K\n")
255
+ sys.stdout.flush()
256
+
257
+
258
+ def _holiday_tagline(today: Optional[date] = None) -> Optional[str]:
259
+ today = today or date.today()
260
+ return _HOLIDAY_TAGLINES.get((today.month, today.day))
261
+
262
+
263
+ def render_intro(theme: Optional[dict] = None, party: bool = False) -> None:
264
+ """Print the full animated acra startup banner.
265
+
266
+ `theme` is one of the dicts from acra.ui.theme (must contain "accent").
267
+ `party` triggers the rainbow/emoji easter egg instead of the normal
268
+ glitch-scan reveal; wired up to `acra --party` / `acra --easter-egg`.
269
+ """
270
+ theme = theme or {}
271
+ accent = theme.get("accent", "bright_cyan")
272
+ if accent not in COLORS:
273
+ accent = "bright_cyan"
274
+
275
+ art = _build_art()
276
+
277
+ if party:
278
+ _party_reveal(art)
279
+ else:
280
+ _glitch_scan_reveal(art, _GRADIENT)
281
+
282
+ _type_line("Autonomous Coding & Research Agent", color=accent)
283
+
284
+ tagline = _holiday_tagline() or WELCOME_TEXT
285
+ _fade_in_lines([tagline], dim=True)
286
+
287
+ _spinner_version_line(accent)
@@ -3,14 +3,7 @@
3
3
  from rich.panel import Panel
4
4
  from rich.console import Console
5
5
 
6
- MASCOT = r"""
7
- ____ ____ ____
8
- / __ \ / __ \/ __ \
9
- | | | | | | | | | |
10
- | | | | | | | | | |
11
- | |__| | |__| | |__| |
12
- \____/ \____/ \____/
13
- """
6
+ from acra import __version__
14
7
 
15
8
  WELCOME_TEXT = "acra: agentic CLI for LLM task workflows"
16
9
 
@@ -18,12 +11,11 @@ WELCOME_TEXT = "acra: agentic CLI for LLM task workflows"
18
11
  def render_banner(provider: str, model: str, profile: str, workspace: str, theme: dict) -> Panel:
19
12
  console = Console()
20
13
  lines = [
21
- f"[bold {theme['accent']}]acra v0.1.2[/bold {theme['accent']}]",
22
14
  f"Provider: {provider} · Model: {model}",
23
15
  f"Profile: {profile} · Workspace: {workspace}",
24
16
  ]
25
17
  content = "\n".join(lines)
26
- return Panel(content, title=WELCOME_TEXT, subtitle=MASCOT, style=theme["border"], border_style=theme["border"])
18
+ return Panel(content, title="Session", style=theme["border"], border_style=theme["border"])
27
19
 
28
20
 
29
21
  def render_tips(theme: dict) -> Panel:
@@ -37,4 +29,4 @@ def render_tips(theme: dict) -> Panel:
37
29
 
38
30
 
39
31
  # Compatibility alias for older imports and public package API.
40
- welcome_banner = render_banner
32
+ welcome_banner = render_banner
@@ -9,6 +9,7 @@ from prompt_toolkit import PromptSession
9
9
  from prompt_toolkit.completion import Completer, Completion
10
10
  from prompt_toolkit.shortcuts import CompleteStyle
11
11
  from acra.ui.banner import render_banner, render_tips
12
+ from acra.ui.animated_banner import render_intro
12
13
  from acra.ui.theme import get_theme
13
14
  from acra.config.profile_manager import ProfileManager
14
15
  from rich.console import Console
@@ -31,9 +32,10 @@ class SlashCompleter(Completer):
31
32
  yield completion
32
33
 
33
34
 
34
- def launch_shell(profile: str = None, workspace: str = None):
35
+ def launch_shell(profile: str = None, workspace: str = None, party: bool = False):
35
36
  config = ProfileManager().load_profile(profile)
36
37
  theme = get_theme(config.get("theme", "dark-orange"))
38
+ render_intro(theme, party=party)
37
39
  banner = render_banner(
38
40
  config.get("provider", "gemini"),
39
41
  config.get("model", "gemini-2.5-flash"),
@@ -88,4 +90,4 @@ def launch_shell(profile: str = None, workspace: str = None):
88
90
  except EOFError:
89
91
  break
90
92
 
91
- console.print(Panel("Goodbye", title="acra"))
93
+ console.print(Panel("Goodbye", title="acra"))
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: acra-cli
3
- Version: 0.1.2
3
+ Version: 0.1.4
4
4
  Summary: Agentic CLI for LLM task execution, research, and workflow automation.
5
5
  Author: Raj Tembe
6
6
  License: GNU Affero General Public License v3
@@ -154,11 +154,13 @@ acra/tools/web_tools/arxiv_search.py
154
154
  acra/tools/web_tools/serpapi_search.py
155
155
  acra/tools/web_tools/tavily_search.py
156
156
  acra/ui/__init__.py
157
+ acra/ui/animated_banner.py
157
158
  acra/ui/banner.py
158
159
  acra/ui/components.py
159
160
  acra/ui/shell.py
160
161
  acra/ui/theme.py
161
162
  acra/ui/__pycache__/__init__.cpython-312.pyc
163
+ acra/ui/__pycache__/animated_banner.cpython-312.pyc
162
164
  acra/ui/__pycache__/banner.cpython-312.pyc
163
165
  acra/ui/__pycache__/components.cpython-312.pyc
164
166
  acra/ui/__pycache__/shell.cpython-312.pyc
@@ -174,4 +176,5 @@ acra_cli.egg-info/dependency_links.txt
174
176
  acra_cli.egg-info/entry_points.txt
175
177
  acra_cli.egg-info/requires.txt
176
178
  acra_cli.egg-info/top_level.txt
177
- tests/test_cli.py
179
+ tests/test_cli.py
180
+ tests/test_interactive_routing.py