kash-shell 0.3.23__tar.gz → 0.3.25__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 (319) hide show
  1. {kash_shell-0.3.23 → kash_shell-0.3.25}/PKG-INFO +6 -4
  2. {kash_shell-0.3.23 → kash_shell-0.3.25}/README.md +2 -2
  3. {kash_shell-0.3.23 → kash_shell-0.3.25}/pyproject.toml +4 -1
  4. kash_shell-0.3.25/src/kash/actions/core/combine_docs.py +52 -0
  5. kash_shell-0.3.25/src/kash/actions/core/concat_docs.py +47 -0
  6. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/commands/workspace/workspace_commands.py +2 -2
  7. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/config/logger.py +3 -2
  8. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/config/settings.py +8 -0
  9. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/docs/markdown/topics/a2_installation.md +2 -2
  10. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/embeddings/embeddings.py +4 -6
  11. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/embeddings/text_similarity.py +2 -5
  12. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/exec/action_exec.py +1 -1
  13. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/exec/fetch_url_items.py +36 -8
  14. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/help/help_embeddings.py +3 -0
  15. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/llm_utils/llm_completion.py +1 -1
  16. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/llm_utils/llm_features.py +1 -1
  17. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/llm_utils/llms.py +5 -7
  18. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/mcp/mcp_cli.py +2 -2
  19. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/model/params_model.py +1 -1
  20. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/utils/api_utils/api_retries.py +84 -76
  21. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/utils/api_utils/gather_limited.py +227 -89
  22. kash_shell-0.3.25/src/kash/utils/api_utils/http_utils.py +46 -0
  23. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/utils/api_utils/progress_protocol.py +49 -56
  24. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/utils/rich_custom/multitask_status.py +70 -21
  25. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/utils/text_handling/doc_normalization.py +2 -0
  26. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/utils/text_handling/markdown_utils.py +14 -3
  27. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/web_content/web_extract.py +12 -8
  28. kash_shell-0.3.25/src/kash/web_content/web_fetch.py +373 -0
  29. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/web_content/web_page_model.py +5 -0
  30. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/web_gen/templates/base_styles.css.jinja +8 -1
  31. {kash_shell-0.3.23 → kash_shell-0.3.25}/tests/kash/utils/api_utils/test_gather_limited.py +69 -13
  32. {kash_shell-0.3.23 → kash_shell-0.3.25}/tests/kash/utils/rich_custom/test_multitask_status.py +14 -11
  33. {kash_shell-0.3.23 → kash_shell-0.3.25}/uv.lock +388 -204
  34. kash_shell-0.3.23/src/kash/web_content/web_fetch.py +0 -144
  35. {kash_shell-0.3.23 → kash_shell-0.3.25}/.copier-answers.yml +0 -0
  36. {kash_shell-0.3.23 → kash_shell-0.3.25}/.cursor/rules/general.mdc +0 -0
  37. {kash_shell-0.3.23 → kash_shell-0.3.25}/.cursor/rules/python.mdc +0 -0
  38. {kash_shell-0.3.23 → kash_shell-0.3.25}/.env.template +0 -0
  39. {kash_shell-0.3.23 → kash_shell-0.3.25}/.github/workflows/ci.yml +0 -0
  40. {kash_shell-0.3.23 → kash_shell-0.3.25}/.github/workflows/publish.yml +0 -0
  41. {kash_shell-0.3.23 → kash_shell-0.3.25}/.gitignore +0 -0
  42. {kash_shell-0.3.23 → kash_shell-0.3.25}/LICENSE +0 -0
  43. {kash_shell-0.3.23 → kash_shell-0.3.25}/Makefile +0 -0
  44. {kash_shell-0.3.23 → kash_shell-0.3.25}/development.md +0 -0
  45. {kash_shell-0.3.23 → kash_shell-0.3.25}/devtools/generate_readme.xsh +0 -0
  46. {kash_shell-0.3.23 → kash_shell-0.3.25}/devtools/lint.py +0 -0
  47. {kash_shell-0.3.23 → kash_shell-0.3.25}/devtools/profile_main.py +0 -0
  48. {kash_shell-0.3.23 → kash_shell-0.3.25}/installation.md +0 -0
  49. {kash_shell-0.3.23 → kash_shell-0.3.25}/publishing.md +0 -0
  50. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/__init__.py +0 -0
  51. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/__main__.py +0 -0
  52. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/actions/__init__.py +0 -0
  53. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/actions/core/assistant_chat.py +0 -0
  54. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/actions/core/chat.py +0 -0
  55. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/actions/core/format_markdown_template.py +0 -0
  56. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/actions/core/markdownify_html.py +0 -0
  57. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/actions/core/minify_html.py +0 -0
  58. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/actions/core/readability.py +0 -0
  59. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/actions/core/render_as_html.py +0 -0
  60. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/actions/core/show_webpage.py +0 -0
  61. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/actions/core/strip_html.py +0 -0
  62. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/actions/core/summarize_as_bullets.py +0 -0
  63. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/actions/core/tabbed_webpage_config.py +0 -0
  64. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/actions/core/tabbed_webpage_generate.py +0 -0
  65. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/actions/meta/write_instructions.py +0 -0
  66. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/actions/meta/write_new_action.py +0 -0
  67. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/commands/__init__.py +0 -0
  68. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/commands/base/basic_file_commands.py +0 -0
  69. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/commands/base/browser_commands.py +0 -0
  70. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/commands/base/debug_commands.py +0 -0
  71. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/commands/base/diff_commands.py +0 -0
  72. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/commands/base/files_command.py +0 -0
  73. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/commands/base/general_commands.py +0 -0
  74. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/commands/base/logs_commands.py +0 -0
  75. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/commands/base/model_commands.py +0 -0
  76. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/commands/base/reformat_command.py +0 -0
  77. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/commands/base/search_command.py +0 -0
  78. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/commands/base/show_command.py +0 -0
  79. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/commands/extras/parse_uv_lock.py +0 -0
  80. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/commands/extras/utils_commands.py +0 -0
  81. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/commands/help/assistant_commands.py +0 -0
  82. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/commands/help/doc_commands.py +0 -0
  83. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/commands/help/help_commands.py +0 -0
  84. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/commands/help/logo.py +0 -0
  85. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/commands/help/welcome.py +0 -0
  86. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/commands/workspace/selection_commands.py +0 -0
  87. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/config/__init__.py +0 -0
  88. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/config/capture_output.py +0 -0
  89. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/config/colors.py +0 -0
  90. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/config/env_settings.py +0 -0
  91. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/config/init.py +0 -0
  92. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/config/lazy_imports.py +0 -0
  93. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/config/logger_basic.py +0 -0
  94. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/config/logo.txt +0 -0
  95. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/config/server_config.py +0 -0
  96. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/config/setup.py +0 -0
  97. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/config/suppress_warnings.py +0 -0
  98. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/config/text_styles.py +0 -0
  99. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/docs/__init__.py +0 -0
  100. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/docs/all_docs.py +0 -0
  101. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/docs/load_actions_info.py +0 -0
  102. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/docs/load_api_docs.py +0 -0
  103. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/docs/load_help_topics.py +0 -0
  104. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/docs/load_source_code.py +0 -0
  105. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/docs/markdown/api_docs_template.md +0 -0
  106. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/docs/markdown/assistant_instructions_template.md +0 -0
  107. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/docs/markdown/readme_template.md +0 -0
  108. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/docs/markdown/topics/a1_what_is_kash.md +0 -0
  109. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/docs/markdown/topics/a3_getting_started.md +0 -0
  110. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/docs/markdown/topics/a4_elements.md +0 -0
  111. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/docs/markdown/topics/a5_tips_for_use_with_other_tools.md +0 -0
  112. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/docs/markdown/topics/b0_philosophy_of_kash.md +0 -0
  113. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/docs/markdown/topics/b1_kash_overview.md +0 -0
  114. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/docs/markdown/topics/b2_workspace_and_file_formats.md +0 -0
  115. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/docs/markdown/topics/b3_modern_shell_tool_recommendations.md +0 -0
  116. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/docs/markdown/topics/b4_faq.md +0 -0
  117. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/docs/markdown/warning.md +0 -0
  118. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/docs/markdown/welcome.md +0 -0
  119. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/docs_base/docs_base.py +0 -0
  120. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/docs_base/load_custom_command_info.py +0 -0
  121. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/docs_base/load_faqs.py +0 -0
  122. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/docs_base/load_recipe_snippets.py +0 -0
  123. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/docs_base/recipes/general_system_commands.sh +0 -0
  124. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/docs_base/recipes/python_dev_commands.sh +0 -0
  125. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/docs_base/recipes/tldr_standard_commands.sh +0 -0
  126. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/embeddings/cosine.py +0 -0
  127. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/exec/__init__.py +0 -0
  128. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/exec/action_decorators.py +0 -0
  129. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/exec/action_registry.py +0 -0
  130. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/exec/combiners.py +0 -0
  131. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/exec/command_exec.py +0 -0
  132. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/exec/command_registry.py +0 -0
  133. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/exec/history.py +0 -0
  134. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/exec/importing.py +0 -0
  135. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/exec/llm_transforms.py +0 -0
  136. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/exec/precondition_checks.py +0 -0
  137. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/exec/precondition_registry.py +0 -0
  138. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/exec/preconditions.py +0 -0
  139. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/exec/resolve_args.py +0 -0
  140. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/exec/runtime_settings.py +0 -0
  141. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/exec/shell_callable_action.py +0 -0
  142. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/exec_model/__init__.py +0 -0
  143. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/exec_model/args_model.py +0 -0
  144. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/exec_model/commands_model.py +0 -0
  145. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/exec_model/script_model.py +0 -0
  146. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/exec_model/shell_model.py +0 -0
  147. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/file_storage/__init__.py +0 -0
  148. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/file_storage/file_store.py +0 -0
  149. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/file_storage/item_file_format.py +0 -0
  150. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/file_storage/metadata_dirs.py +0 -0
  151. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/file_storage/persisted_yaml.py +0 -0
  152. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/file_storage/store_cache_warmer.py +0 -0
  153. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/file_storage/store_filenames.py +0 -0
  154. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/help/__init__.py +0 -0
  155. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/help/assistant.py +0 -0
  156. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/help/assistant_instructions.py +0 -0
  157. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/help/assistant_output.py +0 -0
  158. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/help/function_param_info.py +0 -0
  159. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/help/help_lookups.py +0 -0
  160. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/help/help_pages.py +0 -0
  161. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/help/help_printing.py +0 -0
  162. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/help/help_types.py +0 -0
  163. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/help/recommended_commands.py +0 -0
  164. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/help/tldr_help.py +0 -0
  165. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/llm_utils/__init__.py +0 -0
  166. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/llm_utils/clean_headings.py +0 -0
  167. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/llm_utils/custom_sliding_transforms.py +0 -0
  168. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/llm_utils/fuzzy_parsing.py +0 -0
  169. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/llm_utils/init_litellm.py +0 -0
  170. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/llm_utils/llm_api_keys.py +0 -0
  171. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/llm_utils/llm_messages.py +0 -0
  172. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/llm_utils/llm_names.py +0 -0
  173. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/local_server/__init__.py +0 -0
  174. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/local_server/local_server.py +0 -0
  175. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/local_server/local_server_commands.py +0 -0
  176. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/local_server/local_server_routes.py +0 -0
  177. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/local_server/local_url_formatters.py +0 -0
  178. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/local_server/port_tools.py +0 -0
  179. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/local_server/rich_html_template.py +0 -0
  180. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/mcp/__init__.py +0 -0
  181. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/mcp/mcp_main.py +0 -0
  182. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/mcp/mcp_server_commands.py +0 -0
  183. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/mcp/mcp_server_routes.py +0 -0
  184. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/mcp/mcp_server_sse.py +0 -0
  185. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/mcp/mcp_server_stdio.py +0 -0
  186. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/media_base/__init__.py +0 -0
  187. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/media_base/audio_processing.py +0 -0
  188. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/media_base/media_cache.py +0 -0
  189. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/media_base/media_services.py +0 -0
  190. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/media_base/media_tools.py +0 -0
  191. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/media_base/services/local_file_media.py +0 -0
  192. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/media_base/timestamp_citations.py +0 -0
  193. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/media_base/transcription_deepgram.py +0 -0
  194. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/media_base/transcription_format.py +0 -0
  195. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/media_base/transcription_whisper.py +0 -0
  196. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/model/__init__.py +0 -0
  197. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/model/actions_model.py +0 -0
  198. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/model/assistant_response_model.py +0 -0
  199. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/model/compound_actions_model.py +0 -0
  200. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/model/concept_model.py +0 -0
  201. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/model/exec_model.py +0 -0
  202. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/model/graph_model.py +0 -0
  203. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/model/items_model.py +0 -0
  204. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/model/language_list.py +0 -0
  205. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/model/llm_actions_model.py +0 -0
  206. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/model/media_model.py +0 -0
  207. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/model/operations_model.py +0 -0
  208. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/model/paths_model.py +0 -0
  209. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/model/preconditions_model.py +0 -0
  210. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/shell/__init__.py +0 -0
  211. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/shell/completions/completion_scoring.py +0 -0
  212. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/shell/completions/completion_types.py +0 -0
  213. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/shell/completions/shell_completions.py +0 -0
  214. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/shell/file_icons/color_for_format.py +0 -0
  215. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/shell/file_icons/nerd_icons.py +0 -0
  216. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/shell/input/__init__.py +0 -0
  217. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/shell/input/input_prompts.py +0 -0
  218. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/shell/input/inquirer_settings.py +0 -0
  219. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/shell/input/param_inputs.py +0 -0
  220. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/shell/input/shell_confirm.py +0 -0
  221. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/shell/output/__init__.py +0 -0
  222. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/shell/output/kerm_code_utils.py +0 -0
  223. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/shell/output/kerm_codes.py +0 -0
  224. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/shell/output/kmarkdown.py +0 -0
  225. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/shell/output/shell_formatting.py +0 -0
  226. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/shell/output/shell_output.py +0 -0
  227. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/shell/shell_main.py +0 -0
  228. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/shell/ui/__init__.py +0 -0
  229. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/shell/ui/shell_results.py +0 -0
  230. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/shell/ui/shell_syntax.py +0 -0
  231. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/shell/utils/exception_printing.py +0 -0
  232. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/shell/utils/native_utils.py +0 -0
  233. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/shell/utils/shell_function_wrapper.py +0 -0
  234. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/shell/version.py +0 -0
  235. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/utils/__init__.py +0 -0
  236. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/utils/api_utils/cache_requests_limited.py +0 -0
  237. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/utils/common/__init__.py +0 -0
  238. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/utils/common/format_utils.py +0 -0
  239. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/utils/common/function_inspect.py +0 -0
  240. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/utils/common/import_utils.py +0 -0
  241. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/utils/common/lazyobject.py +0 -0
  242. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/utils/common/obj_replace.py +0 -0
  243. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/utils/common/parse_docstring.py +0 -0
  244. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/utils/common/parse_key_vals.py +0 -0
  245. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/utils/common/parse_shell_args.py +0 -0
  246. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/utils/common/stack_traces.py +0 -0
  247. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/utils/common/task_stack.py +0 -0
  248. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/utils/common/testing.py +0 -0
  249. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/utils/common/type_utils.py +0 -0
  250. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/utils/common/uniquifier.py +0 -0
  251. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/utils/common/url.py +0 -0
  252. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/utils/common/url_slice.py +0 -0
  253. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/utils/errors.py +0 -0
  254. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/utils/file_formats/chat_format.py +0 -0
  255. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/utils/file_utils/__init__.py +0 -0
  256. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/utils/file_utils/dir_info.py +0 -0
  257. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/utils/file_utils/file_ext.py +0 -0
  258. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/utils/file_utils/file_formats.py +0 -0
  259. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/utils/file_utils/file_formats_model.py +0 -0
  260. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/utils/file_utils/file_sort_filter.py +0 -0
  261. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/utils/file_utils/file_walk.py +0 -0
  262. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/utils/file_utils/filename_parsing.py +0 -0
  263. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/utils/file_utils/ignore_files.py +0 -0
  264. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/utils/file_utils/mtime_cache.py +0 -0
  265. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/utils/file_utils/path_utils.py +0 -0
  266. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/utils/lang_utils/__init__.py +0 -0
  267. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/utils/lang_utils/capitalization.py +0 -0
  268. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/utils/rich_custom/__init__.py +0 -0
  269. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/utils/rich_custom/ansi_cell_len.py +0 -0
  270. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/utils/rich_custom/rich_char_transform.py +0 -0
  271. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/utils/rich_custom/rich_indent.py +0 -0
  272. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/utils/rich_custom/rich_markdown_fork.py +0 -0
  273. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/utils/text_handling/escape_html_tags.py +0 -0
  274. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/utils/text_handling/markdown_render.py +0 -0
  275. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/utils/text_handling/markdownify_utils.py +0 -0
  276. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/utils/text_handling/unified_diffs.py +0 -0
  277. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/web_content/canon_url.py +0 -0
  278. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/web_content/dir_store.py +0 -0
  279. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/web_content/file_cache_utils.py +0 -0
  280. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/web_content/file_processing.py +0 -0
  281. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/web_content/local_file_cache.py +0 -0
  282. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/web_content/web_extract_justext.py +0 -0
  283. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/web_content/web_extract_readabilipy.py +0 -0
  284. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/web_gen/__init__.py +0 -0
  285. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/web_gen/simple_webpage.py +0 -0
  286. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/web_gen/tabbed_webpage.py +0 -0
  287. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/web_gen/template_render.py +0 -0
  288. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/web_gen/templates/base_webpage.html.jinja +0 -0
  289. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/web_gen/templates/components/toc_scripts.js.jinja +0 -0
  290. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/web_gen/templates/components/toc_styles.css.jinja +0 -0
  291. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/web_gen/templates/components/tooltip_scripts.js.jinja +0 -0
  292. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/web_gen/templates/components/tooltip_styles.css.jinja +0 -0
  293. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/web_gen/templates/content_styles.css.jinja +0 -0
  294. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/web_gen/templates/explain_view.html.jinja +0 -0
  295. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/web_gen/templates/item_view.html.jinja +0 -0
  296. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/web_gen/templates/simple_webpage.html.jinja +0 -0
  297. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/web_gen/templates/tabbed_webpage.html.jinja +0 -0
  298. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/workspaces/__init__.py +0 -0
  299. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/workspaces/param_state.py +0 -0
  300. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/workspaces/selections.py +0 -0
  301. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/workspaces/source_items.py +0 -0
  302. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/workspaces/workspace_dirs.py +0 -0
  303. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/workspaces/workspace_output.py +0 -0
  304. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/workspaces/workspace_registry.py +0 -0
  305. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/workspaces/workspaces.py +0 -0
  306. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/xonsh_custom/command_nl_utils.py +0 -0
  307. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/xonsh_custom/custom_shell.py +0 -0
  308. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/xonsh_custom/customize_prompt.py +0 -0
  309. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/xonsh_custom/load_into_xonsh.py +0 -0
  310. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/xonsh_custom/shell_load_commands.py +0 -0
  311. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/xonsh_custom/shell_which.py +0 -0
  312. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/xonsh_custom/xonsh_completers.py +0 -0
  313. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/xonsh_custom/xonsh_env.py +0 -0
  314. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/xonsh_custom/xonsh_keybindings.py +0 -0
  315. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/xonsh_custom/xonsh_modern_tools.py +0 -0
  316. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/xonsh_custom/xonsh_ranking_completer.py +0 -0
  317. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/xontrib/fnm.py +0 -0
  318. {kash_shell-0.3.23 → kash_shell-0.3.25}/src/kash/xontrib/kash_extension.py +0 -0
  319. {kash_shell-0.3.23 → kash_shell-0.3.25}/tests/test_shell.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: kash-shell
3
- Version: 0.3.23
3
+ Version: 0.3.25
4
4
  Summary: The knowledge agent shell (core)
5
5
  Project-URL: Repository, https://github.com/jlevy/kash-shell
6
6
  Author-email: Joshua Levy <joshua@cal.berkeley.edu>
@@ -24,12 +24,14 @@ Requires-Dist: chopdiff>=0.2.3
24
24
  Requires-Dist: clideps>=0.1.4
25
25
  Requires-Dist: colour>=0.1.5
26
26
  Requires-Dist: cssselect>=1.2.0
27
+ Requires-Dist: curl-cffi>=0.11.4
27
28
  Requires-Dist: deepgram-sdk>=3.10.1
28
29
  Requires-Dist: dunamai>=1.23.0
29
30
  Requires-Dist: fastapi>=0.115.11
30
- Requires-Dist: flowmark>=0.4.6
31
+ Requires-Dist: flowmark>=0.4.8
31
32
  Requires-Dist: frontmatter-format>=0.2.1
32
33
  Requires-Dist: funlog>=0.2.0
34
+ Requires-Dist: httpx[brotli]>=0.28.1
33
35
  Requires-Dist: humanfriendly>=10.0
34
36
  Requires-Dist: inquirerpy>=0.3.4
35
37
  Requires-Dist: jinja2>=3.1.6
@@ -329,7 +331,7 @@ These are for `kash-media` but you can use a `kash-shell` for a more basic setup
329
331
 
330
332
  You can use kash from your MCP client (such as Anthropic Desktop or Cursor).
331
333
 
332
- You do this by running the the `kash_mcp` binary to make kash actions available as MCP
334
+ You do this by running the the `kash-mcp` binary to make kash actions available as MCP
333
335
  tools.
334
336
 
335
337
  For Claude Desktop, my config looks like this:
@@ -338,7 +340,7 @@ For Claude Desktop, my config looks like this:
338
340
  {
339
341
  "mcpServers": {
340
342
  "kash": {
341
- "command": "/Users/levy/.local/bin/kash_mcp",
343
+ "command": "/Users/levy/.local/bin/kash-mcp",
342
344
  "args": ["--proxy"]
343
345
  }
344
346
  }
@@ -255,7 +255,7 @@ These are for `kash-media` but you can use a `kash-shell` for a more basic setup
255
255
 
256
256
  You can use kash from your MCP client (such as Anthropic Desktop or Cursor).
257
257
 
258
- You do this by running the the `kash_mcp` binary to make kash actions available as MCP
258
+ You do this by running the the `kash-mcp` binary to make kash actions available as MCP
259
259
  tools.
260
260
 
261
261
  For Claude Desktop, my config looks like this:
@@ -264,7 +264,7 @@ For Claude Desktop, my config looks like this:
264
264
  {
265
265
  "mcpServers": {
266
266
  "kash": {
267
- "command": "/Users/levy/.local/bin/kash_mcp",
267
+ "command": "/Users/levy/.local/bin/kash-mcp",
268
268
  "args": ["--proxy"]
269
269
  }
270
270
  }
@@ -45,7 +45,7 @@ dependencies = [
45
45
  "strif>=3.0.1",
46
46
  "funlog>=0.2.0",
47
47
  "prettyfmt>=0.3.1",
48
- "flowmark>=0.4.6",
48
+ "flowmark>=0.4.8",
49
49
  "frontmatter-format>=0.2.1",
50
50
  "chopdiff>=0.2.3",
51
51
  "clideps>=0.1.4",
@@ -77,6 +77,9 @@ dependencies = [
77
77
  "pathspec>=0.12.1",
78
78
  "patch-ng>=1.18.1",
79
79
  "inquirerpy>=0.3.4",
80
+ # HTTP clients:
81
+ "httpx[brotli]>=0.28.1", # Include brotli for better compression and browser fingerprint.
82
+ "curl-cffi>=0.11.4",
80
83
  # LLM and API essentials:
81
84
  "tiktoken>=0.9.0",
82
85
  "openai>=1.66.3",
@@ -0,0 +1,52 @@
1
+ from chopdiff.html.html_in_md import div_wrapper
2
+
3
+ from kash.config.logger import get_logger
4
+ from kash.exec import kash_action
5
+ from kash.model import ONE_OR_MORE_ARGS, ActionInput, ActionResult, Param
6
+ from kash.utils.errors import InvalidInput
7
+
8
+ log = get_logger(__name__)
9
+
10
+
11
+ @kash_action(
12
+ expected_args=ONE_OR_MORE_ARGS,
13
+ params=(
14
+ Param(
15
+ "class_name",
16
+ "CSS class name to use for wrapping each document in a div.",
17
+ type=str,
18
+ default_value="doc",
19
+ ),
20
+ ),
21
+ )
22
+ def combine_docs(input: ActionInput, class_name: str = "page") -> ActionResult:
23
+ """
24
+ Combine multiple text items into a single document, wrapping each piece
25
+ in a div with the specified CSS class.
26
+ """
27
+ items = input.items
28
+
29
+ if not items:
30
+ raise InvalidInput("No items provided for combination")
31
+
32
+ # Create wrapper function
33
+ wrapper = div_wrapper(class_name=class_name)
34
+
35
+ # Collect and wrap all bodies
36
+ wrapped_bodies = []
37
+ for item in items:
38
+ if not item.body:
39
+ raise InvalidInput(f"Item has no body: {item.store_path}")
40
+ wrapped_bodies.append(wrapper(item.body))
41
+
42
+ # Concatenate with double newlines
43
+ combined_body = "\n\n".join(wrapped_bodies)
44
+
45
+ # Create title
46
+ count = len(items)
47
+ title = f"Combined ({count} doc{'s' if count != 1 else ''})"
48
+
49
+ # Create result item based on first item
50
+ result_item = items[0].derived_copy(body=combined_body, title=title, original_filename=None)
51
+
52
+ return ActionResult([result_item])
@@ -0,0 +1,47 @@
1
+ from kash.config.logger import get_logger
2
+ from kash.exec import kash_action
3
+ from kash.model import ONE_OR_MORE_ARGS, ActionInput, ActionResult, Param
4
+ from kash.utils.errors import InvalidInput
5
+
6
+ log = get_logger(__name__)
7
+
8
+
9
+ @kash_action(
10
+ expected_args=ONE_OR_MORE_ARGS,
11
+ params=(
12
+ Param(
13
+ "separator",
14
+ "String to use between concatenated items.",
15
+ type=str,
16
+ default_value="\n\n",
17
+ ),
18
+ ),
19
+ )
20
+ def concat_docs(input: ActionInput, separator: str = "\n\n") -> ActionResult:
21
+ """
22
+ Concatenate multiple text items into a single document with the specified
23
+ separator between each piece.
24
+ """
25
+ items = input.items
26
+
27
+ if not items:
28
+ raise InvalidInput("No items provided for concatenation")
29
+
30
+ # Collect all bodies
31
+ bodies = []
32
+ for item in items:
33
+ if not item.body:
34
+ raise InvalidInput(f"Item has no body: {item.store_path}")
35
+ bodies.append(item.body)
36
+
37
+ # Concatenate with the specified separator
38
+ concat_body = separator.join(bodies)
39
+
40
+ # Create title
41
+ count = len(items)
42
+ title = f"Concat ({count} doc{'s' if count != 1 else ''})"
43
+
44
+ # Create result item based on first item
45
+ result_item = items[0].derived_copy(body=concat_body, title=title, original_filename=None)
46
+
47
+ return ActionResult([result_item])
@@ -474,8 +474,8 @@ def fetch_url(*files_or_urls: str, refetch: bool = False) -> ShellResult:
474
474
  store_paths = []
475
475
  for locator in locators:
476
476
  try:
477
- fetched_item = fetch_url_item(locator, refetch=refetch)
478
- store_paths.append(fetched_item.store_path)
477
+ fetch_result = fetch_url_item(locator, refetch=refetch)
478
+ store_paths.append(fetch_result.item.store_path)
479
479
  except InvalidInput as e:
480
480
  log.warning(
481
481
  "Not a URL or URL resource, will not fetch metadata: %s: %s", fmt_loc(locator), e
@@ -254,9 +254,10 @@ def _do_logging_setup(log_settings: LogSettings):
254
254
  _console_handler = basic_stderr_handler(log_settings.log_console_level)
255
255
 
256
256
  # Manually adjust logging for a few packages, removing previous verbose default handlers.
257
-
257
+ # Set root logger to most permissive level so handlers can do the filtering
258
+ root_level = min(log_settings.log_console_level.value, log_settings.log_file_level.value)
258
259
  log_levels = {
259
- None: INFO,
260
+ None: root_level,
260
261
  "LiteLLM": INFO,
261
262
  "LiteLLM Router": INFO,
262
263
  "LiteLLM Proxy": INFO,
@@ -210,6 +210,12 @@ class Settings:
210
210
  use_nerd_icons: bool
211
211
  """If true, use Nerd Icons in file listings. Requires a compatible font."""
212
212
 
213
+ limit_rps: float
214
+ """Default rate limit for API calls."""
215
+
216
+ limit_concurrency: int
217
+ """Default concurrency limit for API calls."""
218
+
213
219
 
214
220
  ws_root_dir = Path("~/Kash").expanduser()
215
221
 
@@ -276,6 +282,8 @@ def _read_settings():
276
282
  mcp_server_port=DEFAULT_MCP_SERVER_PORT,
277
283
  use_kerm_codes=False,
278
284
  use_nerd_icons=True,
285
+ limit_rps=5.0,
286
+ limit_concurrency=10,
279
287
  )
280
288
 
281
289
 
@@ -124,7 +124,7 @@ These are for `kash-media` but you can use a `kash-shell` for a more basic setup
124
124
 
125
125
  You can use kash from your MCP client (such as Anthropic Desktop or Cursor).
126
126
 
127
- You do this by running the the `kash_mcp` binary to make kash actions available as MCP
127
+ You do this by running the the `kash-mcp` binary to make kash actions available as MCP
128
128
  tools.
129
129
 
130
130
  For Claude Desktop, my config looks like this:
@@ -133,7 +133,7 @@ For Claude Desktop, my config looks like this:
133
133
  {
134
134
  "mcpServers": {
135
135
  "kash": {
136
- "command": "/Users/levy/.local/bin/kash_mcp",
136
+ "command": "/Users/levy/.local/bin/kash-mcp",
137
137
  "args": ["--proxy"]
138
138
  }
139
139
  }
@@ -3,7 +3,7 @@ from __future__ import annotations
3
3
  import ast
4
4
  from collections.abc import Iterable
5
5
  from pathlib import Path
6
- from typing import TYPE_CHECKING, TypeAlias, cast
6
+ from typing import TYPE_CHECKING, TypeAlias
7
7
 
8
8
  from pydantic.dataclasses import dataclass
9
9
  from strif import abbrev_list
@@ -65,12 +65,11 @@ class Embeddings:
65
65
  @classmethod
66
66
  def embed(cls, keyvals: list[KeyVal], model=DEFAULT_EMBEDDING_MODEL) -> Embeddings:
67
67
  from litellm import embedding
68
- from litellm.types.utils import EmbeddingResponse
69
68
 
70
69
  init_litellm()
71
70
 
72
71
  data = {}
73
- log.message(
72
+ log.info(
74
73
  "Embedding %d texts (model %s, batch size %s)…",
75
74
  len(keyvals),
76
75
  model.litellm_name,
@@ -82,9 +81,8 @@ class Embeddings:
82
81
  keys = [kv[0] for kv in batch]
83
82
  texts = [kv[1] for kv in batch]
84
83
 
85
- response: EmbeddingResponse = cast(
86
- EmbeddingResponse, embedding(model=model.litellm_name, input=texts)
87
- )
84
+ response = embedding(model=model.litellm_name, input=texts)
85
+
88
86
  if not response.data:
89
87
  raise ValueError("No embedding response data")
90
88
 
@@ -1,6 +1,6 @@
1
1
  from __future__ import annotations
2
2
 
3
- from typing import TYPE_CHECKING, cast
3
+ from typing import TYPE_CHECKING
4
4
 
5
5
  from funlog import log_calls
6
6
 
@@ -24,12 +24,9 @@ def cosine_relatedness(x: ArrayLike, y: ArrayLike) -> float:
24
24
  def embed_query(model: EmbeddingModel, query: str) -> EmbeddingResponse:
25
25
  import litellm
26
26
  from litellm import embedding
27
- from litellm.types.utils import EmbeddingResponse
28
27
 
29
28
  try:
30
- response: EmbeddingResponse = cast(
31
- EmbeddingResponse, embedding(model=model.litellm_name, input=[query])
32
- )
29
+ response = embedding(model=model.litellm_name, input=[query])
33
30
  except litellm.exceptions.APIError as e:
34
31
  log.info("API error embedding query: %s", e)
35
32
  raise ApiResultError(str(e))
@@ -55,7 +55,7 @@ def prepare_action_input(*input_args: CommandArg, refetch: bool = False) -> Acti
55
55
  if input_items:
56
56
  log.message("Assembling metadata for input items:\n%s", fmt_lines(input_items))
57
57
  input_items = [
58
- fetch_url_item_content(item, refetch=refetch) if is_url_resource(item) else item
58
+ fetch_url_item_content(item, refetch=refetch).item if is_url_resource(item) else item
59
59
  for item in input_items
60
60
  ]
61
61
 
@@ -1,23 +1,42 @@
1
+ from dataclasses import dataclass
2
+
1
3
  from kash.config.logger import get_logger
2
4
  from kash.exec.preconditions import is_url_resource
3
- from kash.media_base.media_services import get_media_metadata
4
5
  from kash.model.items_model import Item, ItemType
5
6
  from kash.model.paths_model import StorePath
6
7
  from kash.utils.common.format_utils import fmt_loc
7
8
  from kash.utils.common.url import Url, is_url
8
9
  from kash.utils.common.url_slice import add_slice_to_url, parse_url_slice
9
10
  from kash.utils.errors import InvalidInput
11
+ from kash.web_content.web_page_model import WebPageData
10
12
 
11
13
  log = get_logger(__name__)
12
14
 
13
15
 
16
+ @dataclass(frozen=True)
17
+ class FetchItemResult:
18
+ """
19
+ Result of fetching a URL item.
20
+ """
21
+
22
+ item: Item
23
+
24
+ was_cached: bool
25
+ """Whether this item was already present in cache (or if we skipped the fetch
26
+ because we already had the data)."""
27
+
28
+ page_data: WebPageData | None = None
29
+ """If the item was fetched from a URL via the web content cache,
30
+ this will hold additional metadata whether it was cached."""
31
+
32
+
14
33
  def fetch_url_item(
15
34
  locator: Url | StorePath,
16
35
  *,
17
36
  save_content: bool = True,
18
37
  refetch: bool = False,
19
38
  cache: bool = True,
20
- ) -> Item:
39
+ ) -> FetchItemResult:
21
40
  from kash.workspaces import current_ws
22
41
 
23
42
  ws = current_ws()
@@ -37,7 +56,7 @@ def fetch_url_item(
37
56
 
38
57
  def fetch_url_item_content(
39
58
  item: Item, *, save_content: bool = True, refetch: bool = False, cache: bool = True
40
- ) -> Item:
59
+ ) -> FetchItemResult:
41
60
  """
42
61
  Fetch content and metadata for a URL using a media service if we
43
62
  recognize the URL as a known media service. Otherwise, fetch and extract the
@@ -51,6 +70,7 @@ def fetch_url_item_content(
51
70
  The content item is returned if content was saved. Otherwise, the updated
52
71
  URL item is returned.
53
72
  """
73
+ from kash.media_base.media_services import get_media_metadata
54
74
  from kash.web_content.canon_url import canonicalize_url
55
75
  from kash.web_content.web_extract import fetch_page_content
56
76
  from kash.workspaces import current_ws
@@ -61,7 +81,7 @@ def fetch_url_item_content(
61
81
  "Already have title, description, and body, will not fetch: %s",
62
82
  item.fmt_loc(),
63
83
  )
64
- return item
84
+ return FetchItemResult(item, was_cached=True)
65
85
 
66
86
  if not item.url:
67
87
  raise InvalidInput(f"No URL for item: {item.fmt_loc()}")
@@ -74,6 +94,8 @@ def fetch_url_item_content(
74
94
  media_metadata = get_media_metadata(url)
75
95
  url_item: Item | None = None
76
96
  content_item: Item | None = None
97
+ page_data: WebPageData | None = None
98
+
77
99
  if media_metadata:
78
100
  url_item = Item.from_media_metadata(media_metadata)
79
101
  # Preserve and canonicalize any slice suffix on the URL.
@@ -101,7 +123,6 @@ def fetch_url_item_content(
101
123
  original_filename=item.get_filename(),
102
124
  format=page_data.format_info.format,
103
125
  )
104
- ws.save(content_item)
105
126
 
106
127
  if not url_item.title:
107
128
  log.warning("Failed to fetch page data: title is missing: %s", item.url)
@@ -112,8 +133,15 @@ def fetch_url_item_content(
112
133
  if content_item:
113
134
  ws.save(content_item)
114
135
  assert content_item.store_path
115
- log.info("Saved content item: %s", content_item.fmt_loc())
136
+ log.info(
137
+ "Saved both URL and content item: %s, %s",
138
+ url_item.fmt_loc(),
139
+ content_item.fmt_loc(),
140
+ )
116
141
  else:
117
- log.info("Saved URL item: %s", url_item.fmt_loc())
142
+ log.info("Saved URL item (no content): %s", url_item.fmt_loc())
118
143
 
119
- return content_item or url_item
144
+ was_cached = bool(
145
+ not page_data or (page_data.cache_result and page_data.cache_result.was_cached)
146
+ )
147
+ return FetchItemResult(content_item or url_item, was_cached=was_cached, page_data=page_data)
@@ -3,6 +3,8 @@ from __future__ import annotations
3
3
  from dataclasses import dataclass, field
4
4
  from pathlib import Path
5
5
 
6
+ from typing_extensions import override
7
+
6
8
  from kash.config.logger import get_logger
7
9
  from kash.embeddings.embeddings import Embeddings
8
10
  from kash.embeddings.text_similarity import rank_by_relatedness
@@ -19,6 +21,7 @@ class DocKey:
19
21
  doc_type: HelpDocType
20
22
  index: int
21
23
 
24
+ @override
22
25
  def __str__(self) -> str:
23
26
  return f"{self.doc_type.value}:{self.index}"
24
27
 
@@ -107,7 +107,7 @@ def llm_completion(
107
107
 
108
108
  total_input_len = sum(len(m["content"]) for m in messages)
109
109
  speed = len(content) / elapsed
110
- log.message(
110
+ log.info(
111
111
  f"{EMOJI_TIMING} LLM completion from {model.litellm_name} in {format_duration(elapsed)}: "
112
112
  f"input {total_input_len} chars in {len(messages)} messages, output {len(content)} chars "
113
113
  f"({speed:.0f} char/s)"
@@ -68,5 +68,5 @@ preferred_llms: list[LLMName] = [
68
68
  LLM.claude_4_opus,
69
69
  LLM.claude_3_7_sonnet,
70
70
  LLM.claude_3_5_haiku,
71
- LLM.gemini_2_5_pro_preview_05_06,
71
+ LLM.gemini_2_5_pro,
72
72
  ]
@@ -15,6 +15,7 @@ class LLM(LLMName, Enum):
15
15
  # https://platform.openai.com/docs/models
16
16
  o4_mini = LLMName("o4-mini")
17
17
  o3 = LLMName("o3")
18
+ o3_pro = LLMName("o3-pro")
18
19
  o3_mini = LLMName("o3-mini")
19
20
  o1 = LLMName("o1")
20
21
  o1_mini = LLMName("o1-mini")
@@ -35,13 +36,9 @@ class LLM(LLMName, Enum):
35
36
  claude_3_5_haiku = LLMName("claude-3-5-haiku-latest")
36
37
 
37
38
  # https://ai.google.dev/gemini-api/docs/models
38
- gemini_2_5_pro_preview_06_05 = LLMName("gemini/gemini-2.5-pro-preview-06-05")
39
- gemini_2_5_pro_preview_05_06 = LLMName("gemini/gemini-2.5-pro-preview-05-06")
40
- gemini_2_5_pro_preview_03_25 = LLMName("gemini/gemini-2.5-pro-preview-03-25")
41
- gemini_2_5_flash_preview = LLMName("gemini-2.5-flash-preview-05-20")
42
- gemini_2_0_flash = LLMName("gemini/gemini-2_0-flash")
43
- gemini_2_0_flash_lite = LLMName("gemini/gemini-2.0-flash-lite")
44
- gemini_2_0_pro_exp_02_05 = LLMName("gemini/gemini-2.0-pro-exp-02-05")
39
+ gemini_2_5_pro = LLMName("gemini/gemini-2.5-pro")
40
+ gemini_2_5_flash = LLMName("gemini/gemini-2.5-flash")
41
+ gemini_2_5_flash_lite = LLMName("gemini-2.5-flash-lite-preview-06-17")
45
42
 
46
43
  # https://docs.x.ai/docs/models
47
44
  xai_grok_3 = LLMName("xai/grok-3")
@@ -56,6 +53,7 @@ class LLM(LLMName, Enum):
56
53
  deepseek_reasoner = LLMName("deepseek/deepseek-reasoner")
57
54
 
58
55
  # https://console.groq.com/docs/models
56
+ groq_gemma2_9b_it = LLMName("groq/gemma2-9b-it")
59
57
  groq_llama_3_1_8b_instant = LLMName("groq/llama-3.1-8b-instant")
60
58
  groq_llama_3_3_70b_versatile = LLMName("groq/llama-3.3-70b-versatile")
61
59
  groq_deepseek_r1_distill_llama_70b = LLMName("groq/deepseek-r1-distill-llama-70b")
@@ -114,10 +114,10 @@ def main():
114
114
  args = build_parser().parse_args()
115
115
 
116
116
  if args.list_tools or args.tool_help:
117
- kash_setup(rich_logging=True, level=LogLevel.warning)
117
+ kash_setup(rich_logging=True, log_level=LogLevel.warning)
118
118
  show_tool_info(args.tool_help)
119
119
  else:
120
- kash_setup(rich_logging=False, level=LogLevel.info)
120
+ kash_setup(rich_logging=False, log_level=LogLevel.info)
121
121
  run_server(args)
122
122
 
123
123
 
@@ -209,7 +209,7 @@ A list of parameter declarations, possibly with default values.
209
209
  DEFAULT_CAREFUL_LLM = LLM.o3
210
210
  DEFAULT_STRUCTURED_LLM = LLM.gpt_4o
211
211
  DEFAULT_STANDARD_LLM = LLM.claude_4_sonnet
212
- DEFAULT_FAST_LLM = LLM.o1_mini
212
+ DEFAULT_FAST_LLM = LLM.gpt_4o
213
213
 
214
214
 
215
215
  # Parameters set globally such as in the workspace.