agentic-cli 0.5.1__tar.gz → 0.5.2__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (217) hide show
  1. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/CHANGELOG.md +12 -0
  2. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/PKG-INFO +11 -5
  3. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/README.md +10 -4
  4. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/examples/research_demo/agents.py +1 -1
  5. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/pyproject.toml +1 -1
  6. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/src/agentic_cli/__init__.py +1 -1
  7. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/src/agentic_cli/knowledge_base/concepts.py +43 -1
  8. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/src/agentic_cli/tools/__init__.py +13 -3
  9. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/src/agentic_cli/tools/executor.py +35 -8
  10. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/src/agentic_cli/tools/factories.py +60 -12
  11. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/src/agentic_cli/tools/knowledge_tools.py +271 -110
  12. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/src/agentic_cli/tools/shell/sandbox.py +33 -1
  13. agentic_cli-0.5.2/src/agentic_cli/tools/webfetch/fetcher.py +236 -0
  14. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/src/agentic_cli/workflow/base_manager.py +3 -1
  15. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/src/agentic_cli/workflow/tool_summaries.py +3 -1
  16. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/tests/integration/test_kb_research_flow.py +2 -2
  17. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/tests/test_concept_store.py +37 -0
  18. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/tests/test_kb_sidecar.py +4 -4
  19. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/tests/test_kb_tool_renames.py +25 -5
  20. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/tests/test_knowledge_tools.py +77 -24
  21. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/tests/test_tool_summaries.py +5 -2
  22. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/tests/test_tools.py +6 -3
  23. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/tests/test_webfetch.py +102 -14
  24. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/tests/tools/test_factories.py +6 -4
  25. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/tests/tools/test_os_sandbox.py +54 -18
  26. agentic_cli-0.5.1/src/agentic_cli/tools/webfetch/fetcher.py +0 -203
  27. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/.gitignore +0 -0
  28. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/CLAUDE.md +0 -0
  29. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/LICENSE +0 -0
  30. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/environment.yml +0 -0
  31. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/examples/arxiv_demo.py +0 -0
  32. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/examples/fileops_demo.py +0 -0
  33. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/examples/hello_agent.py +0 -0
  34. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/examples/hello_langgraph.py +0 -0
  35. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/examples/memory_demo.py +0 -0
  36. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/examples/research_demo/__init__.py +0 -0
  37. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/examples/research_demo/__main__.py +0 -0
  38. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/examples/research_demo/app.py +0 -0
  39. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/examples/research_demo/commands.py +0 -0
  40. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/examples/research_demo/settings.py +0 -0
  41. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/examples/shell_demo.py +0 -0
  42. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/examples/webfetch_demo.py +0 -0
  43. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/examples/websearch_demo.py +0 -0
  44. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/requirements-dev.txt +0 -0
  45. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/requirements.txt +0 -0
  46. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/src/agentic_cli/cli/__init__.py +0 -0
  47. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/src/agentic_cli/cli/app.py +0 -0
  48. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/src/agentic_cli/cli/builtin_commands.py +0 -0
  49. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/src/agentic_cli/cli/commands.py +0 -0
  50. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/src/agentic_cli/cli/message_processor.py +0 -0
  51. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/src/agentic_cli/cli/settings_command.py +0 -0
  52. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/src/agentic_cli/cli/settings_introspection.py +0 -0
  53. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/src/agentic_cli/cli/usage_tracker.py +0 -0
  54. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/src/agentic_cli/cli/workflow_controller.py +0 -0
  55. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/src/agentic_cli/config.py +0 -0
  56. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/src/agentic_cli/constants.py +0 -0
  57. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/src/agentic_cli/file_utils.py +0 -0
  58. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/src/agentic_cli/knowledge_base/__init__.py +0 -0
  59. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/src/agentic_cli/knowledge_base/_bm25_backends.py +0 -0
  60. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/src/agentic_cli/knowledge_base/_mock_bm25.py +0 -0
  61. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/src/agentic_cli/knowledge_base/_mocks.py +0 -0
  62. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/src/agentic_cli/knowledge_base/bm25_index.py +0 -0
  63. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/src/agentic_cli/knowledge_base/embeddings.py +0 -0
  64. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/src/agentic_cli/knowledge_base/manager.py +0 -0
  65. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/src/agentic_cli/knowledge_base/models.py +0 -0
  66. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/src/agentic_cli/knowledge_base/sidecar.py +0 -0
  67. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/src/agentic_cli/knowledge_base/sources.py +0 -0
  68. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/src/agentic_cli/knowledge_base/vector_store.py +0 -0
  69. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/src/agentic_cli/logging.py +0 -0
  70. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/src/agentic_cli/persistence/__init__.py +0 -0
  71. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/src/agentic_cli/persistence/session.py +0 -0
  72. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/src/agentic_cli/settings_mixins.py +0 -0
  73. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/src/agentic_cli/settings_persistence.py +0 -0
  74. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/src/agentic_cli/tools/_core/__init__.py +0 -0
  75. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/src/agentic_cli/tools/_core/planning.py +0 -0
  76. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/src/agentic_cli/tools/_core/tasks.py +0 -0
  77. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/src/agentic_cli/tools/adk/__init__.py +0 -0
  78. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/src/agentic_cli/tools/adk/state_tools.py +0 -0
  79. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/src/agentic_cli/tools/arxiv_source.py +0 -0
  80. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/src/agentic_cli/tools/arxiv_tools.py +0 -0
  81. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/src/agentic_cli/tools/execution_tools.py +0 -0
  82. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/src/agentic_cli/tools/file_read.py +0 -0
  83. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/src/agentic_cli/tools/file_write.py +0 -0
  84. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/src/agentic_cli/tools/glob_tool.py +0 -0
  85. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/src/agentic_cli/tools/grep_tool.py +0 -0
  86. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/src/agentic_cli/tools/interaction_tools.py +0 -0
  87. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/src/agentic_cli/tools/langgraph/__init__.py +0 -0
  88. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/src/agentic_cli/tools/langgraph/state_tools.py +0 -0
  89. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/src/agentic_cli/tools/memory_tools.py +0 -0
  90. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/src/agentic_cli/tools/pdf_utils.py +0 -0
  91. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/src/agentic_cli/tools/reflection_tools.py +0 -0
  92. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/src/agentic_cli/tools/registry.py +0 -0
  93. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/src/agentic_cli/tools/sandbox/__init__.py +0 -0
  94. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/src/agentic_cli/tools/sandbox/backends/__init__.py +0 -0
  95. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/src/agentic_cli/tools/sandbox/backends/base.py +0 -0
  96. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/src/agentic_cli/tools/sandbox/backends/jupyter_local.py +0 -0
  97. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/src/agentic_cli/tools/sandbox/manager.py +0 -0
  98. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/src/agentic_cli/tools/sandbox/models.py +0 -0
  99. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/src/agentic_cli/tools/search.py +0 -0
  100. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/src/agentic_cli/tools/shell/__init__.py +0 -0
  101. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/src/agentic_cli/tools/shell/audit.py +0 -0
  102. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/src/agentic_cli/tools/shell/classifier.py +0 -0
  103. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/src/agentic_cli/tools/shell/config.py +0 -0
  104. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/src/agentic_cli/tools/shell/executor.py +0 -0
  105. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/src/agentic_cli/tools/shell/models.py +0 -0
  106. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/src/agentic_cli/tools/shell/os_sandbox/__init__.py +0 -0
  107. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/src/agentic_cli/tools/shell/os_sandbox/base.py +0 -0
  108. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/src/agentic_cli/tools/shell/os_sandbox/bubblewrap.py +0 -0
  109. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/src/agentic_cli/tools/shell/os_sandbox/detect.py +0 -0
  110. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/src/agentic_cli/tools/shell/os_sandbox/policy.py +0 -0
  111. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/src/agentic_cli/tools/shell/os_sandbox/seatbelt.py +0 -0
  112. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/src/agentic_cli/tools/shell/os_sandbox/seatbelt_profile.py +0 -0
  113. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/src/agentic_cli/tools/shell/path_analyzer.py +0 -0
  114. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/src/agentic_cli/tools/shell/preprocessor.py +0 -0
  115. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/src/agentic_cli/tools/shell/risk_assessor.py +0 -0
  116. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/src/agentic_cli/tools/shell/tokenizer.py +0 -0
  117. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/src/agentic_cli/tools/webfetch/__init__.py +0 -0
  118. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/src/agentic_cli/tools/webfetch/converter.py +0 -0
  119. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/src/agentic_cli/tools/webfetch/robots.py +0 -0
  120. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/src/agentic_cli/tools/webfetch/summarizer.py +0 -0
  121. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/src/agentic_cli/tools/webfetch/validator.py +0 -0
  122. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/src/agentic_cli/tools/webfetch_tool.py +0 -0
  123. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/src/agentic_cli/workflow/__init__.py +0 -0
  124. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/src/agentic_cli/workflow/adk/__init__.py +0 -0
  125. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/src/agentic_cli/workflow/adk/event_processor.py +0 -0
  126. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/src/agentic_cli/workflow/adk/manager.py +0 -0
  127. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/src/agentic_cli/workflow/adk/permission_plugin.py +0 -0
  128. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/src/agentic_cli/workflow/adk/plugins.py +0 -0
  129. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/src/agentic_cli/workflow/adk/task_progress_plugin.py +0 -0
  130. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/src/agentic_cli/workflow/config.py +0 -0
  131. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/src/agentic_cli/workflow/events.py +0 -0
  132. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/src/agentic_cli/workflow/factory.py +0 -0
  133. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/src/agentic_cli/workflow/langgraph/__init__.py +0 -0
  134. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/src/agentic_cli/workflow/langgraph/graph_builder.py +0 -0
  135. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/src/agentic_cli/workflow/langgraph/manager.py +0 -0
  136. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/src/agentic_cli/workflow/langgraph/permission_wrap.py +0 -0
  137. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/src/agentic_cli/workflow/langgraph/persistence/__init__.py +0 -0
  138. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/src/agentic_cli/workflow/langgraph/persistence/checkpointers.py +0 -0
  139. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/src/agentic_cli/workflow/langgraph/persistence/stores.py +0 -0
  140. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/src/agentic_cli/workflow/langgraph/state.py +0 -0
  141. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/src/agentic_cli/workflow/models.py +0 -0
  142. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/src/agentic_cli/workflow/permissions/__init__.py +0 -0
  143. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/src/agentic_cli/workflow/permissions/capabilities.py +0 -0
  144. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/src/agentic_cli/workflow/permissions/engine.py +0 -0
  145. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/src/agentic_cli/workflow/permissions/matchers.py +0 -0
  146. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/src/agentic_cli/workflow/permissions/prompt.py +0 -0
  147. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/src/agentic_cli/workflow/permissions/rules.py +0 -0
  148. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/src/agentic_cli/workflow/permissions/store.py +0 -0
  149. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/src/agentic_cli/workflow/retry.py +0 -0
  150. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/src/agentic_cli/workflow/service_registry.py +0 -0
  151. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/src/agentic_cli/workflow/settings.py +0 -0
  152. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/tests/__init__.py +0 -0
  153. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/tests/conftest.py +0 -0
  154. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/tests/integration/__init__.py +0 -0
  155. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/tests/integration/conftest.py +0 -0
  156. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/tests/integration/helpers.py +0 -0
  157. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/tests/integration/test_adk_integration.py +0 -0
  158. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/tests/integration/test_langgraph_integration.py +0 -0
  159. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/tests/integration/test_live.py +0 -0
  160. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/tests/integration/test_permission_adk.py +0 -0
  161. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/tests/integration/test_permission_langgraph.py +0 -0
  162. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/tests/permissions/__init__.py +0 -0
  163. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/tests/permissions/test_capabilities.py +0 -0
  164. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/tests/permissions/test_engine.py +0 -0
  165. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/tests/permissions/test_matchers.py +0 -0
  166. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/tests/permissions/test_prompt.py +0 -0
  167. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/tests/permissions/test_rules.py +0 -0
  168. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/tests/permissions/test_store.py +0 -0
  169. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/tests/test_adk_event_processor.py +0 -0
  170. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/tests/test_adk_plugins.py +0 -0
  171. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/tests/test_arxiv_tools.py +0 -0
  172. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/tests/test_bm25_index.py +0 -0
  173. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/tests/test_commands.py +0 -0
  174. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/tests/test_concurrent_stores.py +0 -0
  175. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/tests/test_config.py +0 -0
  176. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/tests/test_context_trimming.py +0 -0
  177. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/tests/test_context_window.py +0 -0
  178. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/tests/test_dual_thinking_boxes.py +0 -0
  179. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/tests/test_embeddings.py +0 -0
  180. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/tests/test_grep_tool_cache.py +0 -0
  181. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/tests/test_input_callback.py +0 -0
  182. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/tests/test_kb_concepts.py +0 -0
  183. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/tests/test_kb_helpers.py +0 -0
  184. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/tests/test_kb_index_md.py +0 -0
  185. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/tests/test_kb_ingest_log.py +0 -0
  186. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/tests/test_knowledge_base.py +0 -0
  187. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/tests/test_langgraph.py +0 -0
  188. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/tests/test_memory.py +0 -0
  189. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/tests/test_model_registry.py +0 -0
  190. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/tests/test_persistence.py +0 -0
  191. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/tests/test_planning.py +0 -0
  192. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/tests/test_reflection.py +0 -0
  193. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/tests/test_session_save_resume.py +0 -0
  194. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/tests/test_settings_persistence.py +0 -0
  195. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/tests/test_task_tools.py +0 -0
  196. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/tests/test_token_caching.py +0 -0
  197. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/tests/test_update_setting.py +0 -0
  198. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/tests/test_usage_tracker.py +0 -0
  199. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/tests/test_vector_store.py +0 -0
  200. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/tests/test_workflow.py +0 -0
  201. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/tests/test_workflow_controller.py +0 -0
  202. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/tests/tools/__init__.py +0 -0
  203. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/tests/tools/test_adk_state_tools.py +0 -0
  204. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/tests/tools/test_bubblewrap.py +0 -0
  205. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/tests/tools/test_core_planning.py +0 -0
  206. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/tests/tools/test_core_tasks.py +0 -0
  207. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/tests/tools/test_langgraph_state_tools.py +0 -0
  208. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/tests/tools/test_registry.py +0 -0
  209. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/tests/tools/test_sandbox.py +0 -0
  210. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/tests/tools/test_seatbelt_profile.py +0 -0
  211. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/tests/tools/test_shell_security.py +0 -0
  212. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/tests/workflow/__init__.py +0 -0
  213. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/tests/workflow/test_backend_isolation.py +0 -0
  214. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/tests/workflow/test_base_manager_permissions.py +0 -0
  215. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/tests/workflow/test_settings_permissions.py +0 -0
  216. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/tests/workflow/test_task_progress_plugin.py +0 -0
  217. {agentic_cli-0.5.1 → agentic_cli-0.5.2}/tests/workflow/test_tool_assembly.py +0 -0
@@ -5,6 +5,18 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [0.5.2] - 2026-05-01
9
+
10
+ ### Security
11
+ - **`kb_ingest` split into `kb_ingest_text` / `kb_ingest_file` / `kb_ingest_url`**: the previous unified tool declared only `kb.write` (auto-allowed by the builtin `kb.*` rule) while internally reading arbitrary local paths and fetching arbitrary URLs. The split lets the permission engine gate `filesystem.read` and `http.read` at the right entry point, and the URL path now flows through the hardened `ContentFetcher` (URLValidator + manual redirect revalidation + DNS-rebinding mitigation).
12
+ - **Concept-page slug traversal blocked** (`ConceptStore`): explicit slugs are validated against a strict `[a-z0-9-]+` allowlist, and `_concept_path` asserts the resolved path stays under `base_dir`. A slug like `../../etc/passwd` is now rejected before any filesystem write.
13
+ - **Webfetch redirect handling rewritten**: `ContentFetcher.fetch` no longer follows redirects via httpx. Each `Location` is revalidated through `URLValidator` *before* the next GET, cross-host redirects are reported without contacting the new origin, same-host redirects re-check `robots.txt`, and the redirect chain is capped at 5.
14
+ - **`os_sandbox_enabled=True` now fails closed**: when shell or Python execution is requested with sandboxing on, both executors refuse to run if the resolved sandbox is `NoOpSandbox` or wrap fails — instead of silently dropping back to plain subprocess/ulimit.
15
+
16
+ ### Changed
17
+ - **`kb_ingest` tool removed** in favor of the three split entry points; `KB_WRITER_TOOLS` and `make_kb_tools` updated. Internal helper renamed: `_ingest_document_with_kb` → `_ingest_text_with_kb` / `_ingest_file_with_kb` / `_ingest_url_with_kb`.
18
+ - **research_demo agent guide** updated to direct ingestion at `ingest_arxiv_paper` for arXiv papers and at the typed `kb_ingest_*` tools for everything else.
19
+
8
20
  ## [0.5.1] - 2026-04-18
9
21
 
10
22
  ### Added
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: agentic-cli
3
- Version: 0.5.1
3
+ Version: 0.5.2
4
4
  Summary: A framework for building domain-specific agentic CLI applications
5
5
  Project-URL: Homepage, https://github.com/shoom1/agentic-cli
6
6
  Project-URL: Repository, https://github.com/shoom1/agentic-cli
@@ -460,7 +460,7 @@ results = search_arxiv("transformer attention", max_results=10, categories=["cs.
460
460
  paper = fetch_arxiv_paper("1706.03762") # "Attention Is All You Need"
461
461
  ```
462
462
 
463
- The `ArxivSearchSource` (in `knowledge_base/sources.py`) is cached via the service registry and reused across tools, including `kb_ingest` for arXiv URLs.
463
+ The `ArxivSearchSource` (in `knowledge_base/sources.py`) is cached via the service registry and reused across tools. To pull a paper into the KB, use `ingest_arxiv_paper(arxiv_id)` — it composes the arxiv source with `kb_manager`.
464
464
 
465
465
  #### File Operations
466
466
 
@@ -513,7 +513,8 @@ Renamed tools and a new concept-pages subsystem:
513
513
 
514
514
  ```python
515
515
  from agentic_cli.tools import (
516
- kb_search, kb_ingest, kb_read, kb_list,
516
+ kb_search, kb_ingest_text, kb_ingest_file, kb_ingest_url,
517
+ kb_read, kb_list,
517
518
  kb_write_concept, kb_search_concepts,
518
519
  KB_READER_TOOLS, KB_WRITER_TOOLS,
519
520
  )
@@ -522,12 +523,16 @@ from agentic_cli.tools import (
522
523
  | Tool | Purpose |
523
524
  |------|---------|
524
525
  | `kb_search` | Hybrid BM25 + vector search with RRF fusion, filters by source/date |
525
- | `kb_ingest` | Ingest content or URL (arXiv URLs auto-fetch metadata + PDF) |
526
+ | `kb_ingest_text` | Ingest in-memory text content (no FS or network access) |
527
+ | `kb_ingest_file` | Ingest a local file; declares `filesystem.read(path)` for the permission engine |
528
+ | `kb_ingest_url` | Ingest content from an http(s) URL; routed through the hardened `ContentFetcher` and declares `http.read(url)` |
526
529
  | `kb_read` | Return the per-document markdown sidecar (lazy-generated on first read) |
527
530
  | `kb_list` | List documents, optionally filtered |
528
531
  | `kb_write_concept` | Agent-authored concept/summary page (slugged, merged on overwrite) |
529
532
  | `kb_search_concepts` | Search concept pages (title-weighted, case-insensitive) |
530
533
 
534
+ The single `kb_ingest` tool was split in 0.5.2 so each entry point declares the right capability — text-only stays under `kb.write`, while file and URL ingestion correctly trip `filesystem.read` / `http.read` checks. For arXiv papers, prefer `ingest_arxiv_paper(arxiv_id)`.
535
+
531
536
  Bundle convenience:
532
537
 
533
538
  ```python
@@ -784,7 +789,8 @@ agentic-cli/
784
789
  │ │ ├── arxiv_source.py # ArxivSearchSource (service-registered)
785
790
  │ │ ├── execution_tools.py # execute_python
786
791
  │ │ ├── interaction_tools.py # ask_clarification
787
- │ │ ├── knowledge_tools.py # kb_search / kb_ingest / kb_read / kb_list /
792
+ │ │ ├── knowledge_tools.py # kb_search / kb_ingest_text / kb_ingest_file /
793
+ │ │ │ # kb_ingest_url / kb_read / kb_list /
788
794
  │ │ │ # kb_write_concept / kb_search_concepts
789
795
  │ │ ├── file_read.py # read_file, diff_compare
790
796
  │ │ ├── file_write.py # write_file, edit_file (atomic)
@@ -412,7 +412,7 @@ results = search_arxiv("transformer attention", max_results=10, categories=["cs.
412
412
  paper = fetch_arxiv_paper("1706.03762") # "Attention Is All You Need"
413
413
  ```
414
414
 
415
- The `ArxivSearchSource` (in `knowledge_base/sources.py`) is cached via the service registry and reused across tools, including `kb_ingest` for arXiv URLs.
415
+ The `ArxivSearchSource` (in `knowledge_base/sources.py`) is cached via the service registry and reused across tools. To pull a paper into the KB, use `ingest_arxiv_paper(arxiv_id)` — it composes the arxiv source with `kb_manager`.
416
416
 
417
417
  #### File Operations
418
418
 
@@ -465,7 +465,8 @@ Renamed tools and a new concept-pages subsystem:
465
465
 
466
466
  ```python
467
467
  from agentic_cli.tools import (
468
- kb_search, kb_ingest, kb_read, kb_list,
468
+ kb_search, kb_ingest_text, kb_ingest_file, kb_ingest_url,
469
+ kb_read, kb_list,
469
470
  kb_write_concept, kb_search_concepts,
470
471
  KB_READER_TOOLS, KB_WRITER_TOOLS,
471
472
  )
@@ -474,12 +475,16 @@ from agentic_cli.tools import (
474
475
  | Tool | Purpose |
475
476
  |------|---------|
476
477
  | `kb_search` | Hybrid BM25 + vector search with RRF fusion, filters by source/date |
477
- | `kb_ingest` | Ingest content or URL (arXiv URLs auto-fetch metadata + PDF) |
478
+ | `kb_ingest_text` | Ingest in-memory text content (no FS or network access) |
479
+ | `kb_ingest_file` | Ingest a local file; declares `filesystem.read(path)` for the permission engine |
480
+ | `kb_ingest_url` | Ingest content from an http(s) URL; routed through the hardened `ContentFetcher` and declares `http.read(url)` |
478
481
  | `kb_read` | Return the per-document markdown sidecar (lazy-generated on first read) |
479
482
  | `kb_list` | List documents, optionally filtered |
480
483
  | `kb_write_concept` | Agent-authored concept/summary page (slugged, merged on overwrite) |
481
484
  | `kb_search_concepts` | Search concept pages (title-weighted, case-insensitive) |
482
485
 
486
+ The single `kb_ingest` tool was split in 0.5.2 so each entry point declares the right capability — text-only stays under `kb.write`, while file and URL ingestion correctly trip `filesystem.read` / `http.read` checks. For arXiv papers, prefer `ingest_arxiv_paper(arxiv_id)`.
487
+
483
488
  Bundle convenience:
484
489
 
485
490
  ```python
@@ -736,7 +741,8 @@ agentic-cli/
736
741
  │ │ ├── arxiv_source.py # ArxivSearchSource (service-registered)
737
742
  │ │ ├── execution_tools.py # execute_python
738
743
  │ │ ├── interaction_tools.py # ask_clarification
739
- │ │ ├── knowledge_tools.py # kb_search / kb_ingest / kb_read / kb_list /
744
+ │ │ ├── knowledge_tools.py # kb_search / kb_ingest_text / kb_ingest_file /
745
+ │ │ │ # kb_ingest_url / kb_read / kb_list /
740
746
  │ │ │ # kb_write_concept / kb_search_concepts
741
747
  │ │ ├── file_read.py # read_file, diff_compare
742
748
  │ │ ├── file_write.py # write_file, edit_file (atomic)
@@ -50,7 +50,7 @@ When asked to research papers on a topic:
50
50
  1. Check if a relevant concept page already exists with `kb_search_concepts(topic)`. If one is relevant, read it first — it already synthesizes prior work and lists the source `doc_ids` you can follow.
51
51
  2. Search arXiv for relevant papers. If a search returns `success: false`, report the error instead of retrying with simpler queries.
52
52
  3. Fetch metadata for papers of interest.
53
- 4. Ingest papers into the knowledge base by passing an arXiv PDF URL to `kb_ingest` — this auto-fetches metadata, downloads the PDF, extracts text, embeds chunks, and generates the sidecar in one call. The response includes the LLM-generated `summary` and the `document_id`.
53
+ 4. Ingest papers into the knowledge base. For arXiv papers, call `ingest_arxiv_paper(arxiv_id)` — it handles metadata, PDF download, and rate limiting. For other web sources use `kb_ingest_url(url)`; for a local PDF use `kb_ingest_file(path)`; for raw text you already hold use `kb_ingest_text(content)`. Each returns a `document_id` and the LLM-generated `summary`.
54
54
  5. Read each paper's sidecar with `kb_read(doc_id)` to plan the per-paper analysis.
55
55
  6. Pull full text with `kb_read(doc_id, full=True)` for any sections where the sidecar is insufficient (specific numbers, quotes, methodology details).
56
56
  7. Save detailed per-paper analyses via `write_file`.
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "agentic-cli"
7
- version = "0.5.1"
7
+ version = "0.5.2"
8
8
  description = "A framework for building domain-specific agentic CLI applications"
9
9
  readme = "README.md"
10
10
  license = "MIT"
@@ -92,4 +92,4 @@ __all__ = [
92
92
  "CLISettingsMixin",
93
93
  ]
94
94
 
95
- __version__ = "0.5.1"
95
+ __version__ = "0.5.2"
@@ -21,9 +21,28 @@ _SLUG_WHITESPACE = re.compile(r"[\s_]+")
21
21
  _SLUG_DASH_RUN = re.compile(r"-+")
22
22
  _FRONTMATTER_RE = re.compile(r"^---\n(.*?)\n---\n?(.*)", re.DOTALL)
23
23
 
24
+ # Strict allowlist for explicit slugs. Auto-generated slugs from
25
+ # slug_from_title() already conform; explicit slugs from callers must be
26
+ # checked against this pattern to prevent path traversal (``../escape``)
27
+ # and unsafe filenames.
28
+ _SAFE_SLUG_RE = re.compile(r"^[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$")
29
+
24
30
  MAX_SLUG_LENGTH = 80
25
31
 
26
32
 
33
+ def _is_safe_explicit_slug(slug: str) -> bool:
34
+ """Return True iff ``slug`` is safe to use as a concept filename.
35
+
36
+ Rejects empty strings, anything containing path separators, ``..``,
37
+ leading/trailing dashes, uppercase letters, or characters outside the
38
+ ``[a-z0-9-]`` set. This protects ``ConceptStore`` from writes outside
39
+ its base directory regardless of where ``slug`` originated.
40
+ """
41
+ if not slug or len(slug) > MAX_SLUG_LENGTH:
42
+ return False
43
+ return bool(_SAFE_SLUG_RE.match(slug))
44
+
45
+
27
46
  def slug_from_title(title: str) -> str:
28
47
  """Convert a title into a kebab-case ASCII slug.
29
48
 
@@ -119,7 +138,17 @@ class ConceptStore:
119
138
  self.base_dir = Path(base_dir)
120
139
 
121
140
  def _concept_path(self, slug: str) -> Path:
122
- return self.base_dir / f"{slug}.md"
141
+ # Defense in depth: even if a caller bypasses the explicit-slug
142
+ # validation, refuse to compose a path that escapes base_dir.
143
+ candidate = (self.base_dir / f"{slug}.md").resolve()
144
+ base_resolved = self.base_dir.resolve()
145
+ try:
146
+ candidate.relative_to(base_resolved)
147
+ except ValueError as exc:
148
+ raise ValueError(
149
+ f"Refusing to compose concept path outside base_dir: {slug!r}"
150
+ ) from exc
151
+ return candidate
123
152
 
124
153
  def write(
125
154
  self,
@@ -150,6 +179,19 @@ class ConceptStore:
150
179
  Dict with keys ``success``, ``slug``, ``path``, ``action``
151
180
  (``"created"`` or ``"updated"``), and ``invalid_sources``.
152
181
  """
182
+ if slug and not _is_safe_explicit_slug(slug):
183
+ return {
184
+ "success": False,
185
+ "slug": "",
186
+ "path": "",
187
+ "action": "failed",
188
+ "error": (
189
+ f"invalid slug {slug!r}: must match [a-z0-9-]+, no path "
190
+ f"separators, max {MAX_SLUG_LENGTH} chars"
191
+ ),
192
+ "invalid_sources": [],
193
+ }
194
+
153
195
  valid_sources, invalid = _partition_sources(sources, valid_ids_check)
154
196
 
155
197
  if not valid_sources:
@@ -28,7 +28,9 @@ from agentic_cli.tools.file_write import write_file, edit_file
28
28
 
29
29
  from agentic_cli.tools.knowledge_tools import (
30
30
  kb_search,
31
- kb_ingest,
31
+ kb_ingest_text,
32
+ kb_ingest_file,
33
+ kb_ingest_url,
32
34
  kb_read,
33
35
  kb_list,
34
36
  kb_write_concept,
@@ -36,7 +38,13 @@ from agentic_cli.tools.knowledge_tools import (
36
38
  )
37
39
 
38
40
  KB_READER_TOOLS = [kb_search, kb_read, kb_list, kb_search_concepts]
39
- KB_WRITER_TOOLS = [*KB_READER_TOOLS, kb_ingest, kb_write_concept]
41
+ KB_WRITER_TOOLS = [
42
+ *KB_READER_TOOLS,
43
+ kb_ingest_text,
44
+ kb_ingest_file,
45
+ kb_ingest_url,
46
+ kb_write_concept,
47
+ ]
40
48
  from agentic_cli.tools.arxiv_tools import (
41
49
  search_arxiv,
42
50
  fetch_arxiv_paper,
@@ -87,7 +95,9 @@ __all__ = [
87
95
  "google_search_tool",
88
96
  # Standard tool functions (ready to use with agents)
89
97
  "kb_search",
90
- "kb_ingest",
98
+ "kb_ingest_text",
99
+ "kb_ingest_file",
100
+ "kb_ingest_url",
91
101
  "kb_read",
92
102
  "kb_list",
93
103
  "kb_write_concept",
@@ -247,6 +247,28 @@ class SafePythonExecutor:
247
247
  from agentic_cli.tools.shell.os_sandbox import get_os_sandbox
248
248
 
249
249
  sandbox = get_os_sandbox()
250
+ # Fail closed when sandboxing was requested but no real
251
+ # isolation is available — silently dropping back to a plain
252
+ # subprocess would defeat the user's opt-in.
253
+ if sandbox.sandbox_type == "none":
254
+ logger.error(
255
+ "python_executor.os_sandbox_required_but_unavailable",
256
+ sandbox_type=sandbox.sandbox_type,
257
+ )
258
+ elapsed = (time.time() - start_time) * 1000
259
+ return {
260
+ "success": False,
261
+ "output": "",
262
+ "result": None,
263
+ "error": (
264
+ "OS sandbox is required (os_sandbox_enabled=True) "
265
+ "but no supported sandbox tool is available on "
266
+ "this system (install sandbox-exec on macOS or "
267
+ "bwrap on Linux). Refusing to execute without "
268
+ "isolation."
269
+ ),
270
+ "execution_time_ms": round(elapsed, 2),
271
+ }
250
272
  wrap_result = sandbox.wrap_python_command(
251
273
  [sys.executable, "-c", script],
252
274
  Path.cwd(),
@@ -266,17 +288,22 @@ class SafePythonExecutor:
266
288
  timeout=timeout,
267
289
  )
268
290
  else:
269
- logger.warning(
291
+ logger.error(
270
292
  "python_executor.os_sandbox_wrap_failed",
271
293
  error=wrap_result.error,
272
294
  )
273
- proc = subprocess.run(
274
- [sys.executable, "-c", script],
275
- input=code,
276
- capture_output=True,
277
- text=True,
278
- timeout=timeout,
279
- )
295
+ elapsed = (time.time() - start_time) * 1000
296
+ return {
297
+ "success": False,
298
+ "output": "",
299
+ "result": None,
300
+ "error": (
301
+ f"OS sandbox wrap failed "
302
+ f"({wrap_result.sandbox_type}): {wrap_result.error}. "
303
+ f"Refusing to execute without isolation."
304
+ ),
305
+ "execution_time_ms": round(elapsed, 2),
306
+ }
280
307
  else:
281
308
  proc = subprocess.run(
282
309
  [sys.executable, "-c", script],
@@ -107,18 +107,22 @@ def make_kb_tools(kb_manager, user_kb_manager=None) -> list[Callable]:
107
107
  user_kb_manager: Optional user-scoped KnowledgeBaseManager.
108
108
 
109
109
  Returns:
110
- [kb_search, kb_ingest, kb_read, kb_list, kb_write_concept, kb_search_concepts]
111
- (six tools — the concept pages pair was added in Phase 2.)
110
+ [kb_search, kb_ingest_text, kb_ingest_file, kb_ingest_url,
111
+ kb_read, kb_list, kb_write_concept, kb_search_concepts]
112
112
  """
113
113
  from agentic_cli.tools.knowledge_tools import (
114
114
  READ_DOCUMENT_MAX_CHARS,
115
- _ingest_document_with_kb,
115
+ _ingest_file_with_kb,
116
+ _ingest_text_with_kb,
117
+ _ingest_url_with_kb,
116
118
  _list_documents_in_kbs,
117
119
  _read_document_from_kbs,
118
120
  _search_concepts_with_kb,
119
121
  _search_kbs,
120
122
  _write_concept_with_kb,
121
- kb_ingest as _orig_ingest,
123
+ kb_ingest_file as _orig_ingest_file,
124
+ kb_ingest_text as _orig_ingest_text,
125
+ kb_ingest_url as _orig_ingest_url,
122
126
  kb_list as _orig_list,
123
127
  kb_read as _orig_read,
124
128
  kb_search as _orig_search,
@@ -133,9 +137,8 @@ def make_kb_tools(kb_manager, user_kb_manager=None) -> list[Callable]:
133
137
  ) -> dict[str, Any]:
134
138
  return _search_kbs(kb_manager, user_kb_manager, query, filters, top_k)
135
139
 
136
- async def kb_ingest(
137
- content: str = "",
138
- url_or_path: str = "",
140
+ async def kb_ingest_text(
141
+ content: str,
139
142
  title: str = "",
140
143
  source_type: str = "user",
141
144
  source_url: str | None = None,
@@ -143,10 +146,49 @@ def make_kb_tools(kb_manager, user_kb_manager=None) -> list[Callable]:
143
146
  abstract: str = "",
144
147
  tags: list[str] | None = None,
145
148
  ) -> dict[str, Any]:
146
- return await _ingest_document_with_kb(
149
+ return await _ingest_text_with_kb(
147
150
  kb_manager,
148
151
  content=content,
149
- url_or_path=url_or_path,
152
+ title=title,
153
+ source_type=source_type,
154
+ source_url=source_url,
155
+ authors=authors,
156
+ abstract=abstract,
157
+ tags=tags,
158
+ )
159
+
160
+ async def kb_ingest_file(
161
+ path: str,
162
+ title: str = "",
163
+ source_type: str = "local",
164
+ source_url: str | None = None,
165
+ authors: list[str] | None = None,
166
+ abstract: str = "",
167
+ tags: list[str] | None = None,
168
+ ) -> dict[str, Any]:
169
+ return await _ingest_file_with_kb(
170
+ kb_manager,
171
+ path=path,
172
+ title=title,
173
+ source_type=source_type,
174
+ source_url=source_url,
175
+ authors=authors,
176
+ abstract=abstract,
177
+ tags=tags,
178
+ )
179
+
180
+ async def kb_ingest_url(
181
+ url: str,
182
+ title: str = "",
183
+ source_type: str = "web",
184
+ source_url: str | None = None,
185
+ authors: list[str] | None = None,
186
+ abstract: str = "",
187
+ tags: list[str] | None = None,
188
+ ) -> dict[str, Any]:
189
+ return await _ingest_url_with_kb(
190
+ kb_manager,
191
+ url=url,
150
192
  title=title,
151
193
  source_type=source_type,
152
194
  source_url=source_url,
@@ -194,8 +236,12 @@ def make_kb_tools(kb_manager, user_kb_manager=None) -> list[Callable]:
194
236
 
195
237
  kb_search.__name__ = "kb_search"
196
238
  kb_search.__doc__ = _orig_search.__doc__
197
- kb_ingest.__name__ = "kb_ingest"
198
- kb_ingest.__doc__ = _orig_ingest.__doc__
239
+ kb_ingest_text.__name__ = "kb_ingest_text"
240
+ kb_ingest_text.__doc__ = _orig_ingest_text.__doc__
241
+ kb_ingest_file.__name__ = "kb_ingest_file"
242
+ kb_ingest_file.__doc__ = _orig_ingest_file.__doc__
243
+ kb_ingest_url.__name__ = "kb_ingest_url"
244
+ kb_ingest_url.__doc__ = _orig_ingest_url.__doc__
199
245
  kb_read.__name__ = "kb_read"
200
246
  kb_read.__doc__ = _orig_read.__doc__
201
247
  kb_list.__name__ = "kb_list"
@@ -207,7 +253,9 @@ def make_kb_tools(kb_manager, user_kb_manager=None) -> list[Callable]:
207
253
 
208
254
  return [
209
255
  kb_search,
210
- kb_ingest,
256
+ kb_ingest_text,
257
+ kb_ingest_file,
258
+ kb_ingest_url,
211
259
  kb_read,
212
260
  kb_list,
213
261
  kb_write_concept,