kash-shell 0.3.35__tar.gz → 0.3.36__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.
- {kash_shell-0.3.35 → kash_shell-0.3.36}/.copier-answers.yml +1 -1
- {kash_shell-0.3.35 → kash_shell-0.3.36}/.cursor/rules/general.mdc +11 -11
- {kash_shell-0.3.35 → kash_shell-0.3.36}/.cursor/rules/python.mdc +23 -8
- {kash_shell-0.3.35 → kash_shell-0.3.36}/.github/workflows/ci.yml +1 -1
- {kash_shell-0.3.35 → kash_shell-0.3.36}/.github/workflows/publish.yml +1 -1
- {kash_shell-0.3.35 → kash_shell-0.3.36}/PKG-INFO +1 -1
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/exec/llm_transforms.py +4 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/file_storage/file_store.py +4 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/llm_utils/llm_completion.py +115 -19
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/llm_utils/llms.py +8 -7
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/model/actions_model.py +7 -3
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/model/items_model.py +8 -1
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/model/params_model.py +4 -4
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/web_gen/templates/youtube_webpage.html.jinja +3 -2
- kash_shell-0.3.36/uv.lock +3575 -0
- kash_shell-0.3.35/uv.lock +0 -3120
- {kash_shell-0.3.35 → kash_shell-0.3.36}/.env.template +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/.gitignore +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/LICENSE +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/Makefile +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/README.md +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/development.md +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/devtools/generate_readme.xsh +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/devtools/lint.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/devtools/profile_main.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/installation.md +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/publishing.md +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/pyproject.toml +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/__init__.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/__main__.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/actions/__init__.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/actions/core/assistant_chat.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/actions/core/chat.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/actions/core/combine_docs.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/actions/core/concat_docs.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/actions/core/format_markdown_template.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/actions/core/markdownify_html.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/actions/core/minify_html.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/actions/core/readability.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/actions/core/render_as_html.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/actions/core/save_sidematter_meta.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/actions/core/show_webpage.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/actions/core/strip_html.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/actions/core/summarize_as_bullets.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/actions/core/tabbed_webpage_config.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/actions/core/tabbed_webpage_generate.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/actions/core/zip_sidematter.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/actions/meta/write_instructions.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/actions/meta/write_new_action.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/commands/__init__.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/commands/base/basic_file_commands.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/commands/base/browser_commands.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/commands/base/debug_commands.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/commands/base/diff_commands.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/commands/base/files_command.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/commands/base/general_commands.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/commands/base/logs_commands.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/commands/base/model_commands.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/commands/base/reformat_command.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/commands/base/search_command.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/commands/base/show_command.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/commands/extras/parse_uv_lock.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/commands/extras/utils_commands.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/commands/help/assistant_commands.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/commands/help/doc_commands.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/commands/help/help_commands.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/commands/help/logo.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/commands/help/welcome.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/commands/workspace/selection_commands.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/commands/workspace/workspace_commands.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/config/__init__.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/config/capture_output.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/config/colors.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/config/env_settings.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/config/init.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/config/lazy_imports.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/config/logger.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/config/logger_basic.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/config/logo.txt +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/config/server_config.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/config/settings.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/config/setup.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/config/suppress_warnings.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/config/text_styles.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/config/unified_live.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/config/warm_slow_imports.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/docs/__init__.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/docs/all_docs.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/docs/load_actions_info.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/docs/load_api_docs.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/docs/load_help_topics.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/docs/load_source_code.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/docs/markdown/api_docs_template.md +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/docs/markdown/assistant_instructions_template.md +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/docs/markdown/readme_template.md +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/docs/markdown/topics/a1_what_is_kash.md +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/docs/markdown/topics/a2_installation.md +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/docs/markdown/topics/a3_getting_started.md +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/docs/markdown/topics/a4_elements.md +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/docs/markdown/topics/a5_tips_for_use_with_other_tools.md +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/docs/markdown/topics/b0_philosophy_of_kash.md +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/docs/markdown/topics/b1_kash_overview.md +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/docs/markdown/topics/b2_workspace_and_file_formats.md +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/docs/markdown/topics/b3_modern_shell_tool_recommendations.md +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/docs/markdown/topics/b4_faq.md +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/docs/markdown/warning.md +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/docs/markdown/welcome.md +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/docs_base/docs_base.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/docs_base/load_custom_command_info.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/docs_base/load_faqs.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/docs_base/load_recipe_snippets.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/docs_base/recipes/general_system_commands.sh +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/docs_base/recipes/python_dev_commands.sh +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/docs_base/recipes/tldr_standard_commands.sh +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/embeddings/cosine.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/embeddings/embeddings.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/embeddings/text_similarity.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/exec/__init__.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/exec/action_decorators.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/exec/action_exec.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/exec/action_registry.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/exec/combiners.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/exec/command_exec.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/exec/command_registry.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/exec/fetch_url_items.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/exec/history.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/exec/importing.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/exec/precondition_checks.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/exec/precondition_registry.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/exec/preconditions.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/exec/resolve_args.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/exec/runtime_settings.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/exec/shell_callable_action.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/exec_model/__init__.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/exec_model/args_model.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/exec_model/commands_model.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/exec_model/script_model.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/exec_model/shell_model.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/file_storage/__init__.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/file_storage/item_file_format.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/file_storage/item_id_index.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/file_storage/metadata_dirs.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/file_storage/persisted_yaml.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/file_storage/store_cache_warmer.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/file_storage/store_filenames.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/help/__init__.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/help/assistant.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/help/assistant_instructions.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/help/assistant_output.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/help/function_param_info.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/help/help_embeddings.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/help/help_lookups.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/help/help_pages.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/help/help_printing.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/help/help_types.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/help/recommended_commands.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/help/tldr_help.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/llm_utils/__init__.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/llm_utils/clean_headings.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/llm_utils/custom_sliding_transforms.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/llm_utils/fuzzy_parsing.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/llm_utils/init_litellm.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/llm_utils/llm_api_keys.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/llm_utils/llm_messages.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/llm_utils/llm_names.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/local_server/__init__.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/local_server/local_server.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/local_server/local_server_commands.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/local_server/local_server_routes.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/local_server/local_url_formatters.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/local_server/port_tools.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/local_server/rich_html_template.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/mcp/__init__.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/mcp/mcp_cli.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/mcp/mcp_main.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/mcp/mcp_server_commands.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/mcp/mcp_server_routes.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/mcp/mcp_server_sse.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/mcp/mcp_server_stdio.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/media_base/__init__.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/media_base/audio_processing.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/media_base/media_cache.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/media_base/media_services.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/media_base/media_tools.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/media_base/services/local_file_media.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/media_base/timestamp_citations.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/media_base/transcription_deepgram.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/media_base/transcription_format.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/media_base/transcription_whisper.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/model/__init__.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/model/assistant_response_model.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/model/compound_actions_model.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/model/concept_model.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/model/exec_model.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/model/graph_model.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/model/language_list.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/model/llm_actions_model.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/model/media_model.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/model/operations_model.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/model/paths_model.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/model/preconditions_model.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/shell/__init__.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/shell/completions/completion_scoring.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/shell/completions/completion_types.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/shell/completions/shell_completions.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/shell/file_icons/color_for_format.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/shell/file_icons/nerd_icons.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/shell/input/__init__.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/shell/input/input_prompts.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/shell/input/inquirer_settings.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/shell/input/param_inputs.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/shell/input/shell_confirm.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/shell/output/__init__.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/shell/output/kerm_code_utils.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/shell/output/kerm_codes.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/shell/output/kmarkdown.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/shell/output/shell_formatting.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/shell/output/shell_output.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/shell/shell_main.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/shell/ui/__init__.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/shell/ui/shell_results.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/shell/ui/shell_syntax.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/shell/utils/exception_printing.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/shell/utils/native_utils.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/shell/utils/shell_function_wrapper.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/shell/version.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/utils/__init__.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/utils/api_utils/api_retries.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/utils/api_utils/cache_requests_limited.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/utils/api_utils/gather_limited.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/utils/api_utils/http_utils.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/utils/api_utils/multitask_gather.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/utils/api_utils/progress_protocol.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/utils/common/__init__.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/utils/common/format_utils.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/utils/common/function_inspect.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/utils/common/import_utils.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/utils/common/lazyobject.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/utils/common/obj_replace.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/utils/common/parse_docstring.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/utils/common/parse_key_vals.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/utils/common/parse_shell_args.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/utils/common/s3_utils.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/utils/common/stack_traces.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/utils/common/task_stack.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/utils/common/testing.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/utils/common/type_utils.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/utils/common/uniquifier.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/utils/common/url.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/utils/common/url_slice.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/utils/errors.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/utils/file_formats/chat_format.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/utils/file_utils/__init__.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/utils/file_utils/csv_utils.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/utils/file_utils/dir_info.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/utils/file_utils/file_ext.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/utils/file_utils/file_formats.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/utils/file_utils/file_formats_model.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/utils/file_utils/file_sort_filter.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/utils/file_utils/file_walk.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/utils/file_utils/filename_parsing.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/utils/file_utils/ignore_files.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/utils/file_utils/mtime_cache.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/utils/file_utils/path_utils.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/utils/lang_utils/__init__.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/utils/lang_utils/capitalization.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/utils/rich_custom/__init__.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/utils/rich_custom/ansi_cell_len.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/utils/rich_custom/multitask_status.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/utils/rich_custom/rich_char_transform.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/utils/rich_custom/rich_indent.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/utils/rich_custom/rich_markdown_fork.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/utils/text_handling/doc_normalization.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/utils/text_handling/escape_html_tags.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/utils/text_handling/markdown_footnotes.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/utils/text_handling/markdown_render.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/utils/text_handling/markdown_utils.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/utils/text_handling/markdownify_utils.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/utils/text_handling/unified_diffs.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/web_content/canon_url.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/web_content/dir_store.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/web_content/file_cache_utils.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/web_content/file_processing.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/web_content/local_file_cache.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/web_content/web_extract.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/web_content/web_extract_justext.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/web_content/web_extract_readabilipy.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/web_content/web_fetch.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/web_content/web_page_model.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/web_gen/__init__.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/web_gen/tabbed_webpage.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/web_gen/template_render.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/web_gen/templates/base_styles.css.jinja +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/web_gen/templates/base_webpage.html.jinja +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/web_gen/templates/components/toc_scripts.js.jinja +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/web_gen/templates/components/toc_styles.css.jinja +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/web_gen/templates/components/tooltip_scripts.js.jinja +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/web_gen/templates/components/tooltip_styles.css.jinja +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/web_gen/templates/components/youtube_popover_scripts.js.jinja +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/web_gen/templates/components/youtube_popover_styles.css.jinja +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/web_gen/templates/content_styles.css.jinja +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/web_gen/templates/explain_view.html.jinja +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/web_gen/templates/item_view.html.jinja +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/web_gen/templates/simple_webpage.html.jinja +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/web_gen/templates/tabbed_webpage.html.jinja +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/web_gen/webpage_render.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/workspaces/__init__.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/workspaces/param_state.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/workspaces/selections.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/workspaces/source_items.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/workspaces/workspace_dirs.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/workspaces/workspace_output.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/workspaces/workspace_registry.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/workspaces/workspaces.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/xonsh_custom/command_nl_utils.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/xonsh_custom/custom_shell.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/xonsh_custom/customize_prompt.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/xonsh_custom/load_into_xonsh.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/xonsh_custom/shell_load_commands.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/xonsh_custom/shell_which.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/xonsh_custom/xonsh_completers.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/xonsh_custom/xonsh_env.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/xonsh_custom/xonsh_keybindings.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/xonsh_custom/xonsh_modern_tools.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/xonsh_custom/xonsh_ranking_completer.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/xontrib/fnm.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/xontrib/kash_extension.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/tests/file_storage/test_file_store.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/tests/kash/utils/api_utils/test_gather_limited.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/tests/kash/utils/file_utils/test_csv_utils.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/tests/kash/utils/rich_custom/test_multitask_status.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/tests/model/test_item_serialization.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/tests/shell/input/interactive_input_test.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/tests/test_shell.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/tests/utils/text_handling/test_markdown_footnotes.py +0 -0
- {kash_shell-0.3.35 → kash_shell-0.3.36}/tests/web_gen/test_social_metadata.py +0 -0
|
@@ -7,7 +7,7 @@ alwaysApply: true
|
|
|
7
7
|
|
|
8
8
|
**Your fundamental responsibility:** Remember you are a senior engineer and have a
|
|
9
9
|
serious responsibility to be clear, factual, think step by step and be systematic,
|
|
10
|
-
express expert opinion, and make use of the user
|
|
10
|
+
express expert opinion, and make use of the user’s attention wisely.
|
|
11
11
|
|
|
12
12
|
**Rules must be followed:** It is your responsibility to carefully read these rules as
|
|
13
13
|
well as Python or other language-specific rules included here.
|
|
@@ -22,19 +22,19 @@ Therefore:
|
|
|
22
22
|
confirmation.
|
|
23
23
|
|
|
24
24
|
- If you can think of a much better approach that the user requests, be sure to mention
|
|
25
|
-
it. It
|
|
25
|
+
it. It’s your responsibility to suggest approaches that lead to better, simpler
|
|
26
26
|
solutions.
|
|
27
27
|
|
|
28
|
-
- Give thoughtful opinions on better/worse approaches, but NEVER say
|
|
29
|
-
or
|
|
28
|
+
- Give thoughtful opinions on better/worse approaches, but NEVER say “great idea!”
|
|
29
|
+
or “good job” or other compliments, encouragement, or non-essential banter.
|
|
30
30
|
Your job is to give expert opinions and to solve problems, not to motivate the user.
|
|
31
31
|
|
|
32
32
|
- Avoid gratuitous enthusiasm or generalizations.
|
|
33
|
-
Use thoughtful comparisons like saying which code is
|
|
33
|
+
Use thoughtful comparisons like saying which code is “cleaner” but don’t congratulate
|
|
34
34
|
yourself. Avoid subjective descriptions.
|
|
35
|
-
For example, don
|
|
35
|
+
For example, don’t say “I’ve meticulously improved the code and it is in great shape!”
|
|
36
36
|
That is useless generalization.
|
|
37
|
-
Instead, specifically say what you
|
|
37
|
+
Instead, specifically say what you’ve done, e.g., "I’ve added types, including
|
|
38
38
|
generics, to all the methods in `Foo` and fixed all linter errors."
|
|
39
39
|
|
|
40
40
|
# General Coding Guidelines
|
|
@@ -49,17 +49,17 @@ Therefore:
|
|
|
49
49
|
- DO NOT repeat in comments what is obvious from the names of functions or variables or
|
|
50
50
|
types.
|
|
51
51
|
|
|
52
|
-
- DO NOT include comments that reflect what you did, such as
|
|
52
|
+
- DO NOT include comments that reflect what you did, such as “Added this function” as
|
|
53
53
|
this is meaningless to anyone reading the code later.
|
|
54
54
|
(Instead, describe in your message to the user any other contextual information.)
|
|
55
55
|
|
|
56
|
-
- DO NOT use fancy or needlessly decorated headings like
|
|
56
|
+
- DO NOT use fancy or needlessly decorated headings like “===== MIGRATION TOOLS =====”
|
|
57
57
|
in comments
|
|
58
58
|
|
|
59
59
|
- DO NOT number steps in comments.
|
|
60
60
|
These are hard to maintain if the code changes.
|
|
61
|
-
NEVER DO THIS:
|
|
62
|
-
This is fine:
|
|
61
|
+
NEVER DO THIS: “// Step 3: Fetch the data from the cache”\
|
|
62
|
+
This is fine: “// Now fetch the data from the cache”
|
|
63
63
|
|
|
64
64
|
- DO NOT use emojis or special unicode characters like ① or • or – or — in comments.
|
|
65
65
|
|
|
@@ -87,7 +87,7 @@ Always use full type annotations, generics, and other modern practices.
|
|
|
87
87
|
- Use pathlib `Path` instead of strings.
|
|
88
88
|
Use `Path(filename).read_text()` instead of two-line `with open(...)` blocks.
|
|
89
89
|
|
|
90
|
-
- Use strif
|
|
90
|
+
- Use strif’s `atomic_output_file` context manager when writing files to ensure output
|
|
91
91
|
files are written atomically.
|
|
92
92
|
|
|
93
93
|
## Use Modern Python Practices
|
|
@@ -112,7 +112,7 @@ Always use full type annotations, generics, and other modern practices.
|
|
|
112
112
|
|
|
113
113
|
- You can run such individual tests with `uv run pytest -s src/.../path/to/test`
|
|
114
114
|
|
|
115
|
-
- Don
|
|
115
|
+
- Don’t add docs to assertions unless it’s not obvious what they’re checking - the
|
|
116
116
|
assertion appears in the stack trace.
|
|
117
117
|
Do NOT write `assert x == 5, "x should be 5"`. Do NOT write `assert x == 5 # Check if
|
|
118
118
|
x is 5`. That is redundant.
|
|
@@ -122,7 +122,7 @@ Always use full type annotations, generics, and other modern practices.
|
|
|
122
122
|
assertions that confirm the value of a constant setting.
|
|
123
123
|
|
|
124
124
|
- NEVER write `assert False`. If a test reaches an unexpected branch and must fail
|
|
125
|
-
explicitly, `raise AssertionError("
|
|
125
|
+
explicitly, `raise AssertionError("Some explanation")` instead.
|
|
126
126
|
This is best typical best practice in Python since assertions can be removed with
|
|
127
127
|
optimization.
|
|
128
128
|
|
|
@@ -132,6 +132,21 @@ Always use full type annotations, generics, and other modern practices.
|
|
|
132
132
|
This is also preferable because then simple tests have no explicit pytest dependencies
|
|
133
133
|
and can be placed in code anywhere.
|
|
134
134
|
|
|
135
|
+
- DO NOT write trivial tests that test something we know already works, like
|
|
136
|
+
instantiating a Pydantic object.
|
|
137
|
+
|
|
138
|
+
```python
|
|
139
|
+
class Link(BaseModel):
|
|
140
|
+
url: str
|
|
141
|
+
title: str = None
|
|
142
|
+
|
|
143
|
+
# DO NOT write tests like this. They are trivial and only create clutter!
|
|
144
|
+
def test_link_model():
|
|
145
|
+
link = Link(url="https://example.com", title="Example")
|
|
146
|
+
assert link.url == "https://example.com"
|
|
147
|
+
assert link.title == "Example"
|
|
148
|
+
```
|
|
149
|
+
|
|
135
150
|
## Types and Type Annotations
|
|
136
151
|
|
|
137
152
|
- Use modern union syntax: `str | None` instead of `Optional[str]`, `dict[str]` instead
|
|
@@ -142,7 +157,7 @@ Always use full type annotations, generics, and other modern practices.
|
|
|
142
157
|
- Use modern enums like `StrEnum` if appropriate.
|
|
143
158
|
|
|
144
159
|
- One exception to common practice on enums: If an enum has many values that are
|
|
145
|
-
strings, and they have a literal value as a string (like in a JSON protocol), it
|
|
160
|
+
strings, and they have a literal value as a string (like in a JSON protocol), it’s
|
|
146
161
|
fine to use lower_snake_case for enum values to match the actual value.
|
|
147
162
|
This is more readable than LONG_ALL_CAPS_VALUES, and you can simply set the value to
|
|
148
163
|
be the same as the name for each.
|
|
@@ -228,7 +243,7 @@ Always use full type annotations, generics, and other modern practices.
|
|
|
228
243
|
- For classes with many methods, use a concise docstring on the class that explains all
|
|
229
244
|
the common information, and avoid repeating the same information on every method.
|
|
230
245
|
|
|
231
|
-
- Docstrings should provide context or as concisely as possible explain
|
|
246
|
+
- Docstrings should provide context or as concisely as possible explain “why”, not
|
|
232
247
|
obvious details evident from the class names, function names, parameter names, and
|
|
233
248
|
type annotations.
|
|
234
249
|
|
|
@@ -240,10 +255,10 @@ Always use full type annotations, generics, and other modern practices.
|
|
|
240
255
|
name, variable name, or types.
|
|
241
256
|
That is silly and obvious and makes the code longer for no reason.
|
|
242
257
|
|
|
243
|
-
- Do NOT list args and return values if they
|
|
258
|
+
- Do NOT list args and return values if they’re obvious.
|
|
244
259
|
In the above examples, you do not need and `Arguments:` or `Returns:` section, since
|
|
245
|
-
|
|
246
|
-
do list these if there are many arguments and their meaning isn
|
|
260
|
+
sections as it is obvious from context.
|
|
261
|
+
do list these if there are many arguments and their meaning isn’t clear.
|
|
247
262
|
If it returns a less obvious type like a tuple, do explain in the pydoc.
|
|
248
263
|
|
|
249
264
|
- Exported/public variables, functions, or methods SHOULD have concise docstrings.
|
|
@@ -29,6 +29,7 @@ def windowed_llm_transform(
|
|
|
29
29
|
windowing: WindowSettings | None,
|
|
30
30
|
diff_filter: DiffFilter | None = None,
|
|
31
31
|
check_no_results: bool = True,
|
|
32
|
+
enable_web_search: bool = False,
|
|
32
33
|
) -> TextDoc:
|
|
33
34
|
def doc_transform(input_doc: TextDoc) -> TextDoc:
|
|
34
35
|
return TextDoc.from_text(
|
|
@@ -41,6 +42,7 @@ def windowed_llm_transform(
|
|
|
41
42
|
input=input_doc.reassemble(),
|
|
42
43
|
body_template=template,
|
|
43
44
|
check_no_results=check_no_results,
|
|
45
|
+
enable_web_search=enable_web_search,
|
|
44
46
|
).content
|
|
45
47
|
)
|
|
46
48
|
)
|
|
@@ -67,6 +69,7 @@ def llm_transform_str(options: LLMOptions, input_str: str, check_no_results: boo
|
|
|
67
69
|
input_str,
|
|
68
70
|
options.windowing,
|
|
69
71
|
diff_filter=options.diff_filter,
|
|
72
|
+
enable_web_search=options.enable_web_search,
|
|
70
73
|
).reassemble()
|
|
71
74
|
else:
|
|
72
75
|
log.info(
|
|
@@ -81,6 +84,7 @@ def llm_transform_str(options: LLMOptions, input_str: str, check_no_results: boo
|
|
|
81
84
|
body_template=options.body_template,
|
|
82
85
|
input=input_str,
|
|
83
86
|
check_no_results=check_no_results,
|
|
87
|
+
enable_web_search=options.enable_web_search,
|
|
84
88
|
).content
|
|
85
89
|
|
|
86
90
|
return result_str
|
|
@@ -485,6 +485,9 @@ class FileStore(Workspace):
|
|
|
485
485
|
If `with_sidematter` is true, will copy any sidematter files (metadata/assets) to
|
|
486
486
|
the destination.
|
|
487
487
|
"""
|
|
488
|
+
# TODO: Make sure importing a text item that already has
|
|
489
|
+
# frontmatter doesn't accidentally duplicate the frontmatter
|
|
490
|
+
|
|
488
491
|
from kash.file_storage.item_file_format import read_item
|
|
489
492
|
from kash.web_content.canon_url import canonicalize_url
|
|
490
493
|
|
|
@@ -531,6 +534,7 @@ class FileStore(Workspace):
|
|
|
531
534
|
# This will read the file with or without frontmatter.
|
|
532
535
|
# We are importing so we want to drop the external path so we save the body.
|
|
533
536
|
item = read_item(path, self.base_dir)
|
|
537
|
+
log.info("Imported text item: %s", item)
|
|
534
538
|
item.external_path = None
|
|
535
539
|
|
|
536
540
|
if item.type and as_type and item.type != as_type:
|
|
@@ -2,7 +2,7 @@ from __future__ import annotations
|
|
|
2
2
|
|
|
3
3
|
import time
|
|
4
4
|
from dataclasses import dataclass
|
|
5
|
-
from typing import TYPE_CHECKING, cast
|
|
5
|
+
from typing import TYPE_CHECKING, Any, cast
|
|
6
6
|
|
|
7
7
|
from flowmark import Wrap, fill_text
|
|
8
8
|
from funlog import format_duration, log_calls
|
|
@@ -51,6 +51,7 @@ class LLMCompletionResult:
|
|
|
51
51
|
message: LiteLLMMessage
|
|
52
52
|
content: str
|
|
53
53
|
citations: CitationList | None
|
|
54
|
+
tool_calls: list[dict[str, Any]] | None = None
|
|
54
55
|
|
|
55
56
|
@property
|
|
56
57
|
def content_with_citations(self) -> str:
|
|
@@ -59,40 +60,111 @@ class LLMCompletionResult:
|
|
|
59
60
|
content = content + "\n\n" + self.citations.as_markdown_footnotes()
|
|
60
61
|
return content
|
|
61
62
|
|
|
63
|
+
@property
|
|
64
|
+
def has_tool_calls(self) -> bool:
|
|
65
|
+
"""Check if the response contains tool calls."""
|
|
66
|
+
return bool(self.tool_calls)
|
|
67
|
+
|
|
68
|
+
@property
|
|
69
|
+
def tool_call_names(self) -> list[str]:
|
|
70
|
+
"""Get list of tool names that were called."""
|
|
71
|
+
if not self.tool_calls:
|
|
72
|
+
return []
|
|
73
|
+
names = []
|
|
74
|
+
for call in self.tool_calls:
|
|
75
|
+
# Handle both LiteLLM objects and dict representations
|
|
76
|
+
if hasattr(call, "function") and hasattr(getattr(call, "function", None), "name"):
|
|
77
|
+
# LiteLLM object format
|
|
78
|
+
names.append(f"{call.function.name}()") # pyright: ignore[reportAttributeAccessIssue]
|
|
79
|
+
elif isinstance(call, dict) and call.get("function", {}).get("name"):
|
|
80
|
+
# Dict format
|
|
81
|
+
names.append(f"{call['function']['name']}()")
|
|
82
|
+
else:
|
|
83
|
+
names.append(str(call))
|
|
84
|
+
return names
|
|
85
|
+
|
|
62
86
|
|
|
63
87
|
@log_calls(level="info")
|
|
64
88
|
def llm_completion(
|
|
65
89
|
model: LLMName,
|
|
66
90
|
messages: list[dict[str, str]],
|
|
67
91
|
save_objects: bool = True,
|
|
68
|
-
response_format: dict | type[BaseModel] | None = None,
|
|
92
|
+
response_format: dict[str, Any] | type[BaseModel] | None = None,
|
|
93
|
+
tools: list[dict[str, Any]] | None = None,
|
|
94
|
+
enable_web_search: bool = False,
|
|
69
95
|
**kwargs,
|
|
70
96
|
) -> LLMCompletionResult:
|
|
71
97
|
"""
|
|
72
98
|
Perform an LLM completion with LiteLLM.
|
|
99
|
+
|
|
100
|
+
Args:
|
|
101
|
+
model: The LLM model to use
|
|
102
|
+
messages: Chat messages
|
|
103
|
+
save_objects: Whether to save chat history
|
|
104
|
+
response_format: Response format specification
|
|
105
|
+
tools: List of tools available for function calling (e.g., web_search)
|
|
106
|
+
enable_web_search: If True, automatically add web search tools for the model
|
|
107
|
+
**kwargs: Additional LiteLLM parameters
|
|
73
108
|
"""
|
|
74
|
-
import litellm
|
|
75
109
|
from litellm.types.utils import Choices, ModelResponse
|
|
76
110
|
|
|
77
111
|
init_litellm()
|
|
78
112
|
|
|
113
|
+
# Prepare completion parameters
|
|
114
|
+
completion_params = {
|
|
115
|
+
"model": model.litellm_name,
|
|
116
|
+
"messages": messages,
|
|
117
|
+
**kwargs,
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
# Auto-enable web search if requested
|
|
121
|
+
if enable_web_search:
|
|
122
|
+
import litellm
|
|
123
|
+
|
|
124
|
+
if litellm.supports_web_search(model=model.litellm_name):
|
|
125
|
+
log.message("Enabling web search for model %s", model.litellm_name)
|
|
126
|
+
completion_params["web_search_options"] = {"search_context_size": "medium"}
|
|
127
|
+
else:
|
|
128
|
+
log.warning("Web search requested but not supported by model %s", model.litellm_name)
|
|
129
|
+
|
|
79
130
|
chat_history = ChatHistory.from_dicts(messages)
|
|
131
|
+
|
|
132
|
+
# Enhanced logging to detect tool use
|
|
133
|
+
tools_info = f", {len(tools)} tools" if tools else ", no tools"
|
|
80
134
|
log.info(
|
|
81
|
-
"Calling LLM completion from %s on %s, response_format=%s",
|
|
135
|
+
"Calling LLM completion from %s on %s, response_format=%s%s",
|
|
82
136
|
model.litellm_name,
|
|
83
137
|
chat_history.size_summary(),
|
|
84
138
|
response_format,
|
|
139
|
+
tools_info,
|
|
85
140
|
)
|
|
86
141
|
|
|
142
|
+
if tools:
|
|
143
|
+
tool_names = []
|
|
144
|
+
for tool in tools:
|
|
145
|
+
if tool.get("type") == "function":
|
|
146
|
+
tool_names.append(tool.get("function", {}).get("name", "unknown"))
|
|
147
|
+
elif tool.get("type") == "native_web_search":
|
|
148
|
+
tool_names.append("native_web_search")
|
|
149
|
+
else:
|
|
150
|
+
tool_names.append(tool.get("type", "unknown"))
|
|
151
|
+
|
|
152
|
+
log.message("Tools enabled: %s", tool_names)
|
|
153
|
+
|
|
87
154
|
start_time = time.time()
|
|
155
|
+
|
|
156
|
+
if response_format:
|
|
157
|
+
completion_params["response_format"] = response_format
|
|
158
|
+
|
|
159
|
+
if tools:
|
|
160
|
+
completion_params["tools"] = tools
|
|
161
|
+
log.info("Enabling function calling with %d tools", len(tools))
|
|
162
|
+
|
|
163
|
+
import litellm
|
|
164
|
+
|
|
88
165
|
llm_output = cast(
|
|
89
166
|
ModelResponse,
|
|
90
|
-
litellm.completion(
|
|
91
|
-
model.litellm_name,
|
|
92
|
-
messages=messages,
|
|
93
|
-
response_format=response_format,
|
|
94
|
-
**kwargs,
|
|
95
|
-
), # pyright: ignore
|
|
167
|
+
litellm.completion(**completion_params), # pyright: ignore
|
|
96
168
|
)
|
|
97
169
|
elapsed = time.time() - start_time
|
|
98
170
|
|
|
@@ -100,23 +172,47 @@ def llm_completion(
|
|
|
100
172
|
|
|
101
173
|
message = choices.message
|
|
102
174
|
|
|
175
|
+
# Extract tool calls from the response
|
|
176
|
+
tool_calls = getattr(message, "tool_calls", None)
|
|
177
|
+
tool_calls_list = list(tool_calls) if tool_calls else None
|
|
178
|
+
|
|
103
179
|
# Just sanity checking and logging.
|
|
104
180
|
content = choices.message.content
|
|
105
181
|
if not content or not isinstance(content, str):
|
|
106
182
|
raise ApiResultError(f"LLM completion failed: {model.litellm_name}: {llm_output}")
|
|
107
183
|
|
|
184
|
+
# Create the result object with tool calls
|
|
185
|
+
citations = llm_output.get("citations", None)
|
|
186
|
+
result = LLMCompletionResult(
|
|
187
|
+
message=message,
|
|
188
|
+
content=content,
|
|
189
|
+
citations=CitationList(citations=citations) if citations else None,
|
|
190
|
+
tool_calls=tool_calls_list,
|
|
191
|
+
)
|
|
192
|
+
|
|
193
|
+
# Log tool calls if present
|
|
194
|
+
if result.has_tool_calls:
|
|
195
|
+
tool_count = len(result.tool_calls or [])
|
|
196
|
+
log.message("LLM executed %d function calls: %s", tool_count, result.tool_call_names)
|
|
197
|
+
log.message(
|
|
198
|
+
"⚠️ Function calls require implementation - LLM requested tools but no handlers are implemented"
|
|
199
|
+
)
|
|
200
|
+
|
|
201
|
+
# Performance logging
|
|
108
202
|
total_input_len = sum(len(m["content"]) for m in messages)
|
|
109
203
|
speed = len(content) / elapsed
|
|
204
|
+
tool_count = len(result.tool_calls or []) if result.has_tool_calls else 0
|
|
205
|
+
tool_info = f", {tool_count} tool calls" if result.has_tool_calls else ""
|
|
110
206
|
log.info(
|
|
111
207
|
f"{EMOJI_TIMING} LLM completion from {model.litellm_name} in {format_duration(elapsed)}: "
|
|
112
208
|
f"input {total_input_len} chars in {len(messages)} messages, output {len(content)} chars "
|
|
113
|
-
f"({speed:.0f} char/s)"
|
|
209
|
+
f"({speed:.0f} char/s){tool_info}"
|
|
114
210
|
)
|
|
115
211
|
|
|
116
|
-
citations = llm_output.get("citations", None)
|
|
117
|
-
|
|
118
212
|
if save_objects:
|
|
119
213
|
metadata = {"citations": citations} if citations else {}
|
|
214
|
+
if result.has_tool_calls:
|
|
215
|
+
metadata["tool_calls"] = len(result.tool_calls or [])
|
|
120
216
|
chat_history.messages.append(
|
|
121
217
|
ChatMessage(role=ChatRole.assistant, content=content, metadata=metadata)
|
|
122
218
|
)
|
|
@@ -128,11 +224,7 @@ def llm_completion(
|
|
|
128
224
|
file_ext="yml",
|
|
129
225
|
)
|
|
130
226
|
|
|
131
|
-
return
|
|
132
|
-
message=message,
|
|
133
|
-
content=content,
|
|
134
|
-
citations=CitationList(citations=citations) if citations else None,
|
|
135
|
-
)
|
|
227
|
+
return result
|
|
136
228
|
|
|
137
229
|
|
|
138
230
|
def llm_template_completion(
|
|
@@ -143,7 +235,9 @@ def llm_template_completion(
|
|
|
143
235
|
previous_messages: list[dict[str, str]] | None = None,
|
|
144
236
|
save_objects: bool = True,
|
|
145
237
|
check_no_results: bool = True,
|
|
146
|
-
response_format: dict | type[BaseModel] | None = None,
|
|
238
|
+
response_format: dict[str, Any] | type[BaseModel] | None = None,
|
|
239
|
+
tools: list[dict[str, Any]] | None = None,
|
|
240
|
+
enable_web_search: bool = False,
|
|
147
241
|
**kwargs,
|
|
148
242
|
) -> LLMCompletionResult:
|
|
149
243
|
"""
|
|
@@ -169,6 +263,8 @@ def llm_template_completion(
|
|
|
169
263
|
],
|
|
170
264
|
save_objects=save_objects,
|
|
171
265
|
response_format=response_format,
|
|
266
|
+
tools=tools,
|
|
267
|
+
enable_web_search=enable_web_search,
|
|
172
268
|
**kwargs,
|
|
173
269
|
)
|
|
174
270
|
|
|
@@ -28,22 +28,23 @@ class LLM(LLMName, Enum):
|
|
|
28
28
|
gpt_4_1 = LLMName("gpt-4.1")
|
|
29
29
|
gpt_4o = LLMName("gpt-4o")
|
|
30
30
|
gpt_4o_mini = LLMName("gpt-4o-mini")
|
|
31
|
+
gpt_4o_search_preview = LLMName("gpt-4o-search-preview")
|
|
31
32
|
gpt_4 = LLMName("gpt-4")
|
|
32
33
|
gpt_4_1_mini = LLMName("gpt-4.1-mini")
|
|
33
34
|
gpt_4_1_nano = LLMName("gpt-4.1-nano")
|
|
34
35
|
|
|
35
|
-
# https://docs.
|
|
36
|
+
# https://docs.claude.com/en/docs/about-claude/models
|
|
36
37
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
38
|
+
claude_sonnet_4_5 = LLMName("claude-sonnet-4-5-20250929")
|
|
39
|
+
claude_haiku_4_5 = LLMName("claude-haiku-4-5-20251001")
|
|
40
|
+
claude_opus_4_1 = LLMName("claude-opus-4-1-20250805")
|
|
41
|
+
claude_sonnet_4 = LLMName("claude-sonnet-4-20250514")
|
|
42
|
+
claude_opus_4 = LLMName("claude-opus-4-20250514")
|
|
42
43
|
|
|
43
44
|
# https://ai.google.dev/gemini-api/docs/models
|
|
44
45
|
gemini_2_5_pro = LLMName("gemini/gemini-2.5-pro")
|
|
45
46
|
gemini_2_5_flash = LLMName("gemini/gemini-2.5-flash")
|
|
46
|
-
gemini_2_5_flash_lite = LLMName("gemini-2.5-flash-lite
|
|
47
|
+
gemini_2_5_flash_lite = LLMName("gemini/gemini-2.5-flash-lite")
|
|
47
48
|
|
|
48
49
|
# https://docs.x.ai/docs/models
|
|
49
50
|
xai_grok_3 = LLMName("xai/grok-3")
|
|
@@ -171,6 +171,7 @@ class LLMOptions:
|
|
|
171
171
|
body_template: MessageTemplate = MessageTemplate("{body}")
|
|
172
172
|
windowing: WindowSettings = WINDOW_NONE
|
|
173
173
|
diff_filter: DiffFilter | None = None
|
|
174
|
+
enable_web_search: bool = False
|
|
174
175
|
|
|
175
176
|
def updated_with(self, param_name: str, value: Any) -> LLMOptions:
|
|
176
177
|
"""Update option from an action parameter."""
|
|
@@ -543,8 +544,8 @@ class Action(ABC):
|
|
|
543
544
|
def preassemble_result(self, context: ActionContext) -> ActionResult | None:
|
|
544
545
|
"""
|
|
545
546
|
Actions can have a separate preliminary step to pre-assemble outputs. This allows
|
|
546
|
-
us to determine
|
|
547
|
-
|
|
547
|
+
us to determine thew expected shape of the expected output and check if it already
|
|
548
|
+
exists.
|
|
548
549
|
|
|
549
550
|
For now, this only applies to actions with a single output, when `self.cacheable`
|
|
550
551
|
is True.
|
|
@@ -568,7 +569,10 @@ class Action(ABC):
|
|
|
568
569
|
self.name,
|
|
569
570
|
)
|
|
570
571
|
output_type = ItemType.doc
|
|
571
|
-
|
|
572
|
+
output_format = context.action.output_format or primary_input.format
|
|
573
|
+
primary_output = primary_input.derived_copy(
|
|
574
|
+
context, 0, type=output_type, format=output_format
|
|
575
|
+
)
|
|
572
576
|
log.info("Preassembled output: source %s, %s", primary_output.source, primary_output)
|
|
573
577
|
return ActionResult([primary_output])
|
|
574
578
|
else:
|
|
@@ -193,9 +193,16 @@ class ItemId:
|
|
|
193
193
|
from kash.web_content.canon_url import canonicalize_url
|
|
194
194
|
|
|
195
195
|
item_id = None
|
|
196
|
-
if
|
|
196
|
+
if (
|
|
197
|
+
item.type == ItemType.resource
|
|
198
|
+
and item.format == Format.url
|
|
199
|
+
and item.url
|
|
200
|
+
and not item.source
|
|
201
|
+
):
|
|
202
|
+
# This is a plain URL resource, so its identity is its URL.
|
|
197
203
|
item_id = ItemId(item.type, IdType.url, canonicalize_url(item.url))
|
|
198
204
|
elif item.type == ItemType.concept and item.title:
|
|
205
|
+
# This is a concept, so its identity is its title.
|
|
199
206
|
item_id = ItemId(item.type, IdType.concept, canonicalize_concept(item.title))
|
|
200
207
|
elif item.source and item.source.cacheable and item.source.operation.has_known_inputs:
|
|
201
208
|
# We know the source of this and if the action was cacheable, we can create
|
|
@@ -206,10 +206,10 @@ A list of parameter declarations, possibly with default values.
|
|
|
206
206
|
|
|
207
207
|
# These are the default models for typical use cases.
|
|
208
208
|
# The user may override them with parameters.
|
|
209
|
-
DEFAULT_CAREFUL_LLM = LLM.
|
|
210
|
-
DEFAULT_STRUCTURED_LLM = LLM.
|
|
211
|
-
DEFAULT_STANDARD_LLM = LLM.
|
|
212
|
-
DEFAULT_FAST_LLM = LLM.
|
|
209
|
+
DEFAULT_CAREFUL_LLM = LLM.claude_sonnet_4_5
|
|
210
|
+
DEFAULT_STRUCTURED_LLM = LLM.claude_sonnet_4_5
|
|
211
|
+
DEFAULT_STANDARD_LLM = LLM.claude_sonnet_4_5
|
|
212
|
+
DEFAULT_FAST_LLM = LLM.claude_haiku_4_5
|
|
213
213
|
|
|
214
214
|
|
|
215
215
|
# Parameters set globally such as in the workspace.
|
{kash_shell-0.3.35 → kash_shell-0.3.36}/src/kash/web_gen/templates/youtube_webpage.html.jinja
RENAMED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
{% extends "simple_webpage.html.jinja" %}
|
|
2
2
|
|
|
3
3
|
{#
|
|
4
|
-
Extends the simple page with
|
|
5
|
-
|
|
4
|
+
Extends the simple page with YouTube popover player.
|
|
5
|
+
Safe to use instead of simple_webpage.html.jinja since it only adds
|
|
6
|
+
functionality for YouTube if applicable.
|
|
6
7
|
#}
|
|
7
8
|
|
|
8
9
|
{% block custom_styles %}
|