kash-shell 0.3.12__tar.gz → 0.3.13__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.12 → kash_shell-0.3.13}/.copier-answers.yml +1 -1
- {kash_shell-0.3.12 → kash_shell-0.3.13}/.github/workflows/ci.yml +1 -1
- {kash_shell-0.3.12 → kash_shell-0.3.13}/.github/workflows/publish.yml +1 -1
- {kash_shell-0.3.12 → kash_shell-0.3.13}/PKG-INFO +1 -1
- {kash_shell-0.3.12 → kash_shell-0.3.13}/devtools/lint.py +7 -3
- {kash_shell-0.3.12 → kash_shell-0.3.13}/pyproject.toml +5 -2
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/actions/core/markdownify.py +5 -4
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/actions/core/readability.py +4 -4
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/actions/core/render_as_html.py +6 -4
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/commands/base/basic_file_commands.py +3 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/commands/base/diff_commands.py +38 -3
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/commands/base/reformat_command.py +1 -1
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/commands/base/show_command.py +1 -1
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/commands/workspace/selection_commands.py +1 -1
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/commands/workspace/workspace_commands.py +62 -16
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/docs/load_source_code.py +1 -1
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/exec/action_exec.py +4 -5
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/exec/fetch_url_metadata.py +8 -5
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/exec/importing.py +4 -4
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/exec/llm_transforms.py +1 -1
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/exec/preconditions.py +7 -7
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/file_storage/file_store.py +73 -32
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/file_storage/item_file_format.py +1 -1
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/file_storage/store_filenames.py +2 -1
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/help/help_embeddings.py +2 -2
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/llm_utils/clean_headings.py +1 -1
- {kash_shell-0.3.12/src/kash/text_handling → kash_shell-0.3.13/src/kash/llm_utils}/custom_sliding_transforms.py +0 -3
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/llm_utils/llm_completion.py +1 -1
- kash_shell-0.3.13/src/kash/local_server/__init__.py +5 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/local_server/local_server_commands.py +2 -1
- kash_shell-0.3.13/src/kash/mcp/__init__.py +5 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/mcp/mcp_server_commands.py +8 -2
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/media_base/media_cache.py +10 -3
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/model/actions_model.py +3 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/model/items_model.py +71 -42
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/shell/ui/shell_results.py +2 -1
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/utils/common/format_utils.py +0 -8
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/utils/common/import_utils.py +46 -18
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/utils/file_utils/file_formats_model.py +46 -26
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/utils/file_utils/filename_parsing.py +41 -16
- {kash_shell-0.3.12/src/kash → kash_shell-0.3.13/src/kash/utils}/text_handling/doc_normalization.py +10 -8
- kash_shell-0.3.13/src/kash/utils/text_handling/escape_html_tags.py +156 -0
- {kash_shell-0.3.12/src/kash → kash_shell-0.3.13/src/kash/utils}/text_handling/markdown_utils.py +0 -3
- kash_shell-0.3.13/src/kash/utils/text_handling/markdownify_utils.py +87 -0
- {kash_shell-0.3.12/src/kash → kash_shell-0.3.13/src/kash/utils}/text_handling/unified_diffs.py +1 -44
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/web_content/file_cache_utils.py +42 -34
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/web_content/local_file_cache.py +29 -12
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/web_content/web_extract.py +1 -1
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/web_content/web_extract_readabilipy.py +4 -2
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/web_content/web_fetch.py +42 -7
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/web_content/web_page_model.py +2 -1
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/web_gen/simple_webpage.py +1 -1
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/web_gen/templates/base_styles.css.jinja +134 -16
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/web_gen/templates/simple_webpage.html.jinja +1 -1
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/workspaces/selections.py +2 -2
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/workspaces/workspace_importing.py +1 -1
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/workspaces/workspace_output.py +2 -2
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/xonsh_custom/load_into_xonsh.py +4 -2
- {kash_shell-0.3.12 → kash_shell-0.3.13}/uv.lock +111 -110
- kash_shell-0.3.12/src/kash/local_server/__init__.py +0 -5
- kash_shell-0.3.12/src/kash/mcp/__init__.py +0 -5
- kash_shell-0.3.12/src/kash/utils/common/inflection.py +0 -22
- {kash_shell-0.3.12 → kash_shell-0.3.13}/.env.template +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/.gitignore +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/LICENSE +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/Makefile +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/README.md +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/development.md +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/devtools/generate_readme.xsh +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/devtools/profile_main.py +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/installation.md +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/publishing.md +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/__init__.py +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/__main__.py +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/actions/__init__.py +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/actions/core/assistant_chat.py +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/actions/core/chat.py +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/actions/core/format_markdown_template.py +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/actions/core/show_webpage.py +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/actions/core/strip_html.py +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/actions/core/summarize_as_bullets.py +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/actions/core/tabbed_webpage_config.py +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/actions/core/tabbed_webpage_generate.py +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/actions/meta/write_instructions.py +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/actions/meta/write_new_action.py +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/commands/__init__.py +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/commands/base/browser_commands.py +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/commands/base/debug_commands.py +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/commands/base/files_command.py +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/commands/base/general_commands.py +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/commands/base/logs_commands.py +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/commands/base/model_commands.py +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/commands/base/search_command.py +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/commands/extras/parse_uv_lock.py +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/commands/extras/utils_commands.py +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/commands/help/assistant_commands.py +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/commands/help/doc_commands.py +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/commands/help/help_commands.py +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/commands/help/logo.py +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/commands/help/welcome.py +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/config/__init__.py +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/config/capture_output.py +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/config/colors.py +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/config/env_settings.py +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/config/init.py +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/config/lazy_imports.py +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/config/logger.py +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/config/logger_basic.py +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/config/logo.txt +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/config/server_config.py +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/config/settings.py +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/config/setup.py +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/config/suppress_warnings.py +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/config/text_styles.py +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/docs/__init__.py +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/docs/all_docs.py +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/docs/load_actions_info.py +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/docs/load_api_docs.py +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/docs/load_help_topics.py +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/docs/markdown/api_docs_template.md +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/docs/markdown/assistant_instructions_template.md +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/docs/markdown/readme_template.md +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/docs/markdown/topics/a1_what_is_kash.md +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/docs/markdown/topics/a2_installation.md +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/docs/markdown/topics/a3_getting_started.md +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/docs/markdown/topics/a4_elements.md +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/docs/markdown/topics/a5_tips_for_use_with_other_tools.md +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/docs/markdown/topics/b0_philosophy_of_kash.md +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/docs/markdown/topics/b1_kash_overview.md +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/docs/markdown/topics/b2_workspace_and_file_formats.md +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/docs/markdown/topics/b3_modern_shell_tool_recommendations.md +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/docs/markdown/topics/b4_faq.md +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/docs/markdown/warning.md +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/docs/markdown/welcome.md +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/docs_base/docs_base.py +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/docs_base/load_custom_command_info.py +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/docs_base/load_faqs.py +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/docs_base/load_recipe_snippets.py +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/docs_base/recipes/general_system_commands.sh +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/docs_base/recipes/python_dev_commands.sh +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/docs_base/recipes/tldr_standard_commands.sh +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/embeddings/cosine.py +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/embeddings/embeddings.py +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/embeddings/text_similarity.py +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/exec/__init__.py +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/exec/action_decorators.py +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/exec/action_registry.py +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/exec/combiners.py +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/exec/command_exec.py +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/exec/command_registry.py +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/exec/history.py +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/exec/precondition_checks.py +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/exec/precondition_registry.py +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/exec/resolve_args.py +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/exec/runtime_settings.py +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/exec/shell_callable_action.py +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/exec_model/__init__.py +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/exec_model/args_model.py +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/exec_model/commands_model.py +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/exec_model/script_model.py +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/exec_model/shell_model.py +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/file_storage/__init__.py +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/file_storage/metadata_dirs.py +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/file_storage/persisted_yaml.py +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/file_storage/store_cache_warmer.py +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/help/__init__.py +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/help/assistant.py +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/help/assistant_instructions.py +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/help/assistant_output.py +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/help/docstring_utils.py +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/help/function_param_info.py +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/help/help_lookups.py +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/help/help_pages.py +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/help/help_printing.py +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/help/help_types.py +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/help/recommended_commands.py +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/help/tldr_help.py +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/llm_utils/__init__.py +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/llm_utils/fuzzy_parsing.py +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/llm_utils/init_litellm.py +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/llm_utils/llm_api_keys.py +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/llm_utils/llm_features.py +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/llm_utils/llm_messages.py +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/llm_utils/llm_names.py +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/llm_utils/llms.py +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/local_server/local_server.py +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/local_server/local_server_routes.py +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/local_server/local_url_formatters.py +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/local_server/port_tools.py +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/local_server/rich_html_template.py +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/mcp/mcp_cli.py +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/mcp/mcp_main.py +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/mcp/mcp_server_routes.py +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/mcp/mcp_server_sse.py +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/mcp/mcp_server_stdio.py +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/media_base/__init__.py +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/media_base/audio_processing.py +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/media_base/media_services.py +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/media_base/media_tools.py +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/media_base/services/local_file_media.py +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/media_base/timestamp_citations.py +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/media_base/transcription_deepgram.py +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/media_base/transcription_format.py +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/media_base/transcription_whisper.py +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/model/__init__.py +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/model/assistant_response_model.py +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/model/compound_actions_model.py +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/model/concept_model.py +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/model/exec_model.py +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/model/graph_model.py +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/model/language_list.py +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/model/llm_actions_model.py +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/model/media_model.py +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/model/operations_model.py +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/model/params_model.py +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/model/paths_model.py +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/model/preconditions_model.py +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/shell/__init__.py +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/shell/completions/completion_scoring.py +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/shell/completions/completion_types.py +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/shell/completions/shell_completions.py +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/shell/file_icons/color_for_format.py +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/shell/file_icons/nerd_icons.py +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/shell/input/__init__.py +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/shell/input/input_prompts.py +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/shell/input/inquirer_settings.py +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/shell/input/param_inputs.py +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/shell/input/shell_confirm.py +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/shell/output/__init__.py +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/shell/output/kerm_code_utils.py +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/shell/output/kerm_codes.py +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/shell/output/kmarkdown.py +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/shell/output/shell_formatting.py +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/shell/output/shell_output.py +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/shell/shell_main.py +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/shell/ui/__init__.py +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/shell/ui/shell_syntax.py +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/shell/utils/exception_printing.py +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/shell/utils/native_utils.py +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/shell/utils/shell_function_wrapper.py +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/shell/version.py +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/utils/__init__.py +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/utils/common/__init__.py +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/utils/common/function_inspect.py +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/utils/common/lazyobject.py +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/utils/common/obj_replace.py +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/utils/common/parse_key_vals.py +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/utils/common/parse_shell_args.py +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/utils/common/stack_traces.py +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/utils/common/task_stack.py +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/utils/common/type_utils.py +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/utils/common/uniquifier.py +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/utils/common/url.py +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/utils/errors.py +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/utils/file_formats/chat_format.py +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/utils/file_utils/__init__.py +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/utils/file_utils/dir_info.py +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/utils/file_utils/file_ext.py +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/utils/file_utils/file_formats.py +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/utils/file_utils/file_sort_filter.py +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/utils/file_utils/file_walk.py +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/utils/file_utils/ignore_files.py +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/utils/file_utils/mtime_cache.py +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/utils/file_utils/path_utils.py +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/utils/lang_utils/__init__.py +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/utils/lang_utils/capitalization.py +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/utils/rich_custom/__init__.py +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/utils/rich_custom/ansi_cell_len.py +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/utils/rich_custom/rich_char_transform.py +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/utils/rich_custom/rich_indent.py +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/utils/rich_custom/rich_markdown_fork.py +0 -0
- {kash_shell-0.3.12/src/kash → kash_shell-0.3.13/src/kash/utils}/text_handling/markdown_render.py +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/web_content/canon_url.py +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/web_content/dir_store.py +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/web_content/file_processing.py +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/web_content/web_extract_justext.py +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/web_gen/__init__.py +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/web_gen/tabbed_webpage.py +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/web_gen/template_render.py +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/web_gen/templates/base_webpage.html.jinja +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/web_gen/templates/content_styles.css.jinja +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/web_gen/templates/explain_view.html.jinja +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/web_gen/templates/item_view.html.jinja +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/web_gen/templates/tabbed_webpage.html.jinja +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/workspaces/__init__.py +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/workspaces/param_state.py +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/workspaces/source_items.py +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/workspaces/workspace_dirs.py +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/workspaces/workspace_registry.py +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/workspaces/workspaces.py +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/xonsh_custom/command_nl_utils.py +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/xonsh_custom/custom_shell.py +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/xonsh_custom/customize_prompt.py +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/xonsh_custom/shell_load_commands.py +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/xonsh_custom/shell_which.py +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/xonsh_custom/xonsh_completers.py +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/xonsh_custom/xonsh_env.py +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/xonsh_custom/xonsh_keybindings.py +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/xonsh_custom/xonsh_modern_tools.py +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/xonsh_custom/xonsh_ranking_completer.py +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/xontrib/fnm.py +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/src/kash/xontrib/kash_extension.py +0 -0
- {kash_shell-0.3.12 → kash_shell-0.3.13}/tests/test_shell.py +0 -0
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import subprocess
|
|
2
2
|
|
|
3
3
|
from funlog import log_calls
|
|
4
|
+
from rich import get_console, reconfigure
|
|
4
5
|
from rich import print as rprint
|
|
5
6
|
|
|
6
7
|
# Update as needed.
|
|
@@ -8,6 +9,9 @@ SRC_PATHS = ["src", "tests", "devtools"]
|
|
|
8
9
|
DOC_PATHS = ["README.md"]
|
|
9
10
|
|
|
10
11
|
|
|
12
|
+
reconfigure(emoji=not get_console().options.legacy_windows) # No emojis on legacy windows.
|
|
13
|
+
|
|
14
|
+
|
|
11
15
|
def main():
|
|
12
16
|
rprint()
|
|
13
17
|
|
|
@@ -21,9 +25,9 @@ def main():
|
|
|
21
25
|
rprint()
|
|
22
26
|
|
|
23
27
|
if errcount != 0:
|
|
24
|
-
rprint(f"[bold red]
|
|
28
|
+
rprint(f"[bold red]:x: Lint failed with {errcount} errors.[/bold red]")
|
|
25
29
|
else:
|
|
26
|
-
rprint("[bold green]
|
|
30
|
+
rprint("[bold green]:white_check_mark: Lint passed![/bold green]")
|
|
27
31
|
rprint()
|
|
28
32
|
|
|
29
33
|
return errcount
|
|
@@ -32,7 +36,7 @@ def main():
|
|
|
32
36
|
@log_calls(level="warning", show_timing_only=True)
|
|
33
37
|
def run(cmd: list[str]) -> int:
|
|
34
38
|
rprint()
|
|
35
|
-
rprint(f"[bold green]
|
|
39
|
+
rprint(f"[bold green]:arrow_forward: {' '.join(cmd)}[/bold green]")
|
|
36
40
|
errcount = 0
|
|
37
41
|
try:
|
|
38
42
|
subprocess.run(cmd, text=True, check=True)
|
|
@@ -38,7 +38,7 @@ classifiers = [
|
|
|
38
38
|
# ---- Main dependencies ----
|
|
39
39
|
|
|
40
40
|
dependencies = [
|
|
41
|
-
|
|
41
|
+
"dunamai>=1.23.0",
|
|
42
42
|
"pydantic>=2.10.6",
|
|
43
43
|
"typing-extensions>=4.12.2",
|
|
44
44
|
# My tools:
|
|
@@ -102,6 +102,8 @@ dependencies = [
|
|
|
102
102
|
"mcp-proxy>=0.5.0",
|
|
103
103
|
]
|
|
104
104
|
|
|
105
|
+
# ---- Dev dependencies ----
|
|
106
|
+
|
|
105
107
|
[dependency-groups]
|
|
106
108
|
dev = [
|
|
107
109
|
"pytest>=8.3.5",
|
|
@@ -155,8 +157,8 @@ packages = ["src/kash"]
|
|
|
155
157
|
line-length = 100
|
|
156
158
|
|
|
157
159
|
[tool.ruff.lint]
|
|
158
|
-
# See: https://docs.astral.sh/ruff/rules/
|
|
159
160
|
select = [
|
|
161
|
+
# See: https://docs.astral.sh/ruff/rules/
|
|
160
162
|
# Basic list from: https://docs.astral.sh/ruff/linter/#rule-selection
|
|
161
163
|
"E", # https://docs.astral.sh/ruff/rules/#error-e
|
|
162
164
|
"F", # https://docs.astral.sh/ruff/rules/#pyflakes-f
|
|
@@ -171,6 +173,7 @@ select = [
|
|
|
171
173
|
|
|
172
174
|
]
|
|
173
175
|
ignore = [
|
|
176
|
+
# Disable some rules that are overly pedantic. Add/remove as desired:
|
|
174
177
|
"E501", # https://docs.astral.sh/ruff/rules/line-too-long/
|
|
175
178
|
"E402", # https://docs.astral.sh/ruff/rules/module-import-not-at-top-of-file/
|
|
176
179
|
"E731", # https://docs.astral.sh/ruff/rules/lambda-assignment/
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
from kash.config.logger import get_logger
|
|
2
2
|
from kash.exec import kash_action
|
|
3
|
-
from kash.exec.preconditions import has_html_body,
|
|
3
|
+
from kash.exec.preconditions import has_html_body, is_url_resource
|
|
4
4
|
from kash.model import Format, Item
|
|
5
5
|
from kash.model.params_model import common_params
|
|
6
|
+
from kash.utils.text_handling.markdownify_utils import markdownify_custom
|
|
6
7
|
from kash.web_content.file_cache_utils import get_url_html
|
|
7
8
|
from kash.web_content.web_extract_readabilipy import extract_text_readabilipy
|
|
8
9
|
|
|
@@ -10,7 +11,7 @@ log = get_logger(__name__)
|
|
|
10
11
|
|
|
11
12
|
|
|
12
13
|
@kash_action(
|
|
13
|
-
precondition=
|
|
14
|
+
precondition=is_url_resource | has_html_body,
|
|
14
15
|
params=common_params("refetch"),
|
|
15
16
|
mcp_tool=True,
|
|
16
17
|
)
|
|
@@ -19,12 +20,12 @@ def markdownify(item: Item, refetch: bool = False) -> Item:
|
|
|
19
20
|
Converts a URL or raw HTML item to Markdown, fetching with the content
|
|
20
21
|
cache if needed. Also uses readability to clean up the HTML.
|
|
21
22
|
"""
|
|
22
|
-
from markdownify import markdownify as markdownify_convert
|
|
23
23
|
|
|
24
24
|
expiration_sec = 0 if refetch else None
|
|
25
25
|
url, html_content = get_url_html(item, expiration_sec=expiration_sec)
|
|
26
26
|
page_data = extract_text_readabilipy(url, html_content)
|
|
27
|
-
|
|
27
|
+
assert page_data.clean_html
|
|
28
|
+
markdown_content = markdownify_custom(page_data.clean_html)
|
|
28
29
|
|
|
29
30
|
output_item = item.derived_copy(format=Format.markdown, body=markdown_content)
|
|
30
31
|
return output_item
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
from kash.config.logger import get_logger
|
|
2
2
|
from kash.exec import kash_action
|
|
3
|
-
from kash.exec.preconditions import has_html_body,
|
|
3
|
+
from kash.exec.preconditions import has_html_body, is_url_resource
|
|
4
4
|
from kash.model import Format, Item
|
|
5
5
|
from kash.model.params_model import common_params
|
|
6
6
|
from kash.web_content.file_cache_utils import get_url_html
|
|
@@ -10,7 +10,7 @@ log = get_logger(__name__)
|
|
|
10
10
|
|
|
11
11
|
|
|
12
12
|
@kash_action(
|
|
13
|
-
precondition=
|
|
13
|
+
precondition=is_url_resource | has_html_body,
|
|
14
14
|
params=common_params("refetch"),
|
|
15
15
|
mcp_tool=True,
|
|
16
16
|
)
|
|
@@ -20,8 +20,8 @@ def readability(item: Item, refetch: bool = False) -> Item:
|
|
|
20
20
|
See `markdownify` to also convert to Markdown.
|
|
21
21
|
"""
|
|
22
22
|
expiration_sec = 0 if refetch else None
|
|
23
|
-
|
|
24
|
-
page_data = extract_text_readabilipy(
|
|
23
|
+
locator, html_content = get_url_html(item, expiration_sec=expiration_sec)
|
|
24
|
+
page_data = extract_text_readabilipy(locator, html_content)
|
|
25
25
|
|
|
26
26
|
output_item = item.derived_copy(format=Format.html, body=page_data.clean_html)
|
|
27
27
|
|
|
@@ -12,9 +12,9 @@ from kash.web_gen.simple_webpage import simple_webpage_render
|
|
|
12
12
|
@kash_action(
|
|
13
13
|
expected_args=ONE_OR_MORE_ARGS,
|
|
14
14
|
precondition=(has_html_body | has_simple_text_body) & ~has_full_html_page_body,
|
|
15
|
-
params=(Param("
|
|
15
|
+
params=(Param("no_title", "Don't add a title to the page body.", type=bool),),
|
|
16
16
|
)
|
|
17
|
-
def render_as_html(input: ActionInput,
|
|
17
|
+
def render_as_html(input: ActionInput, no_title: bool = False) -> ActionResult:
|
|
18
18
|
"""
|
|
19
19
|
Convert text, Markdown, or HTML to pretty, formatted HTML using a clean
|
|
20
20
|
and simple page template. Supports GFM-flavored Markdown tables and footnotes.
|
|
@@ -27,11 +27,13 @@ def render_as_html(input: ActionInput, add_title: bool = False) -> ActionResult:
|
|
|
27
27
|
"""
|
|
28
28
|
if len(input.items) == 1:
|
|
29
29
|
input_item = input.items[0]
|
|
30
|
-
html_body = simple_webpage_render(input_item, add_title_h1=
|
|
30
|
+
html_body = simple_webpage_render(input_item, add_title_h1=not no_title)
|
|
31
31
|
result_item = input_item.derived_copy(
|
|
32
32
|
type=ItemType.export, format=Format.html, body=html_body
|
|
33
33
|
)
|
|
34
34
|
return ActionResult([result_item])
|
|
35
35
|
else:
|
|
36
36
|
config_result = tabbed_webpage_config(input)
|
|
37
|
-
return tabbed_webpage_generate(
|
|
37
|
+
return tabbed_webpage_generate(
|
|
38
|
+
ActionInput(items=config_result.items), add_title=not no_title
|
|
39
|
+
)
|
|
@@ -81,6 +81,9 @@ def clipboard_paste(path: str = "untitled_paste.txt") -> None:
|
|
|
81
81
|
import pyperclip
|
|
82
82
|
|
|
83
83
|
contents = pyperclip.paste()
|
|
84
|
+
if not contents.strip():
|
|
85
|
+
raise InvalidInput("Clipboard is empty")
|
|
86
|
+
|
|
84
87
|
with atomic_output_file(path, backup_suffix=".{timestamp}.bak") as f:
|
|
85
88
|
f.write_text(contents)
|
|
86
89
|
|
|
@@ -5,16 +5,51 @@ from kash.commands.workspace.selection_commands import select
|
|
|
5
5
|
from kash.config.logger import get_logger
|
|
6
6
|
from kash.exec import import_locator_args, kash_command
|
|
7
7
|
from kash.exec_model.shell_model import ShellResult
|
|
8
|
-
from kash.model.items_model import Item, ItemType
|
|
8
|
+
from kash.model.items_model import Item, ItemRelations, ItemType
|
|
9
|
+
from kash.model.paths_model import StorePath
|
|
9
10
|
from kash.shell.output.shell_output import Wrap, cprint
|
|
10
|
-
from kash.
|
|
11
|
-
from kash.utils.errors import InvalidInput, InvalidOperation
|
|
11
|
+
from kash.utils.errors import ContentError, InvalidInput, InvalidOperation
|
|
12
12
|
from kash.utils.file_utils.file_formats_model import Format
|
|
13
|
+
from kash.utils.text_handling.unified_diffs import unified_diff, unified_diff_files
|
|
13
14
|
from kash.workspaces import current_ws
|
|
14
15
|
|
|
15
16
|
log = get_logger(__name__)
|
|
16
17
|
|
|
17
18
|
|
|
19
|
+
def unified_diff_items(from_item: Item, to_item: Item, strict: bool = True) -> Item:
|
|
20
|
+
"""
|
|
21
|
+
Generate a unified diff between two items. If `strict` is true, will raise
|
|
22
|
+
an error if the items are of different formats.
|
|
23
|
+
"""
|
|
24
|
+
if not from_item.body and not to_item.body:
|
|
25
|
+
raise ContentError(f"No body to diff for {from_item} and {to_item}")
|
|
26
|
+
if not from_item.store_path or not to_item.store_path:
|
|
27
|
+
raise ContentError("No store path on items; save before diffing")
|
|
28
|
+
diff_items = [item for item in [from_item, to_item] if item.format == Format.diff]
|
|
29
|
+
if len(diff_items) == 1:
|
|
30
|
+
raise ContentError(
|
|
31
|
+
f"Cannot compare diffs to non-diffs: {from_item.format}, {to_item.format}"
|
|
32
|
+
)
|
|
33
|
+
if len(diff_items) > 0 or from_item.format != to_item.format:
|
|
34
|
+
msg = f"Diffing items of incompatible format: {from_item.format}, {to_item.format}"
|
|
35
|
+
if strict:
|
|
36
|
+
raise ContentError(msg)
|
|
37
|
+
else:
|
|
38
|
+
log.warning("%s", msg)
|
|
39
|
+
|
|
40
|
+
from_path, to_path = StorePath(from_item.store_path), StorePath(to_item.store_path)
|
|
41
|
+
|
|
42
|
+
diff = unified_diff(from_item.body, to_item.body, str(from_path), str(to_path))
|
|
43
|
+
|
|
44
|
+
return Item(
|
|
45
|
+
type=ItemType.doc,
|
|
46
|
+
title=f"Diff of {from_path} and {to_path}",
|
|
47
|
+
format=Format.diff,
|
|
48
|
+
relations=ItemRelations(diff_of=[from_path, to_path]),
|
|
49
|
+
body=diff.patch_text,
|
|
50
|
+
)
|
|
51
|
+
|
|
52
|
+
|
|
18
53
|
@kash_command
|
|
19
54
|
def diff_items(*paths: str, force: bool = False) -> ShellResult:
|
|
20
55
|
"""
|
|
@@ -8,9 +8,9 @@ from kash.config.logger import get_logger
|
|
|
8
8
|
from kash.exec import assemble_path_args, kash_command, resolvable_paths
|
|
9
9
|
from kash.exec_model.shell_model import ShellResult
|
|
10
10
|
from kash.shell.output.shell_output import print_status
|
|
11
|
-
from kash.text_handling.doc_normalization import normalize_text_file
|
|
12
11
|
from kash.utils.common.format_utils import fmt_loc
|
|
13
12
|
from kash.utils.file_utils.filename_parsing import join_filename, split_filename
|
|
13
|
+
from kash.utils.text_handling.doc_normalization import normalize_text_file
|
|
14
14
|
|
|
15
15
|
log = get_logger(__name__)
|
|
16
16
|
|
|
@@ -54,7 +54,7 @@ def show(
|
|
|
54
54
|
item = ws.load(input_path)
|
|
55
55
|
if thumbnail and item.thumbnail_url:
|
|
56
56
|
try:
|
|
57
|
-
local_path
|
|
57
|
+
local_path = cache_file(item.thumbnail_url).content.path
|
|
58
58
|
terminal_show_image(local_path)
|
|
59
59
|
except Exception as e:
|
|
60
60
|
log.info("Had trouble showing thumbnail image (will skip): %s", e)
|
|
@@ -2,6 +2,7 @@ from os.path import basename
|
|
|
2
2
|
from pathlib import Path
|
|
3
3
|
|
|
4
4
|
from frontmatter_format import fmf_strip_frontmatter
|
|
5
|
+
from prettyfmt import plural
|
|
5
6
|
from strif import copyfile_atomic
|
|
6
7
|
|
|
7
8
|
from kash.config.logger import get_logger
|
|
@@ -10,7 +11,6 @@ from kash.exec_model.shell_model import ShellResult
|
|
|
10
11
|
from kash.model.paths_model import StorePath
|
|
11
12
|
from kash.shell.ui.shell_results import shell_print_selection_history
|
|
12
13
|
from kash.utils.common.format_utils import fmt_loc
|
|
13
|
-
from kash.utils.common.inflection import plural
|
|
14
14
|
from kash.utils.errors import InvalidInput
|
|
15
15
|
from kash.workspaces import Selection, current_ws
|
|
16
16
|
|
|
@@ -2,7 +2,7 @@ import os
|
|
|
2
2
|
from pathlib import Path
|
|
3
3
|
|
|
4
4
|
from frontmatter_format import to_yaml_string
|
|
5
|
-
from prettyfmt import fmt_lines
|
|
5
|
+
from prettyfmt import fmt_lines, plural
|
|
6
6
|
from rich.text import Text
|
|
7
7
|
|
|
8
8
|
from kash.commands.base.basic_file_commands import trash
|
|
@@ -26,7 +26,7 @@ from kash.exec.action_registry import get_all_actions_defaults
|
|
|
26
26
|
from kash.exec.fetch_url_metadata import fetch_url_metadata
|
|
27
27
|
from kash.exec.precondition_checks import actions_matching_paths
|
|
28
28
|
from kash.exec.precondition_registry import get_all_preconditions
|
|
29
|
-
from kash.exec.preconditions import
|
|
29
|
+
from kash.exec.preconditions import is_url_resource
|
|
30
30
|
from kash.exec_model.shell_model import ShellResult
|
|
31
31
|
from kash.local_server.local_url_formatters import local_url_formatter
|
|
32
32
|
from kash.media_base import media_tools
|
|
@@ -51,14 +51,14 @@ from kash.shell.output.shell_output import (
|
|
|
51
51
|
)
|
|
52
52
|
from kash.shell.utils.native_utils import tail_file
|
|
53
53
|
from kash.utils.common.format_utils import fmt_loc
|
|
54
|
-
from kash.utils.common.inflection import plural
|
|
55
54
|
from kash.utils.common.obj_replace import remove_values
|
|
56
55
|
from kash.utils.common.parse_key_vals import parse_key_value
|
|
57
56
|
from kash.utils.common.type_utils import not_none
|
|
58
|
-
from kash.utils.common.url import Url, is_url
|
|
57
|
+
from kash.utils.common.url import Url, is_url, parse_http_url
|
|
59
58
|
from kash.utils.errors import InvalidInput
|
|
60
59
|
from kash.utils.file_formats.chat_format import tail_chat_history
|
|
61
60
|
from kash.utils.file_utils.dir_info import is_nonempty_dir
|
|
61
|
+
from kash.utils.file_utils.file_formats_model import Format
|
|
62
62
|
from kash.web_content.file_cache_utils import cache_file
|
|
63
63
|
from kash.workspaces import (
|
|
64
64
|
current_ws,
|
|
@@ -181,15 +181,15 @@ def cache_content(*urls_or_paths: str, refetch: bool = False) -> None:
|
|
|
181
181
|
PrintHooks.spacer()
|
|
182
182
|
for url_or_path in urls_or_paths:
|
|
183
183
|
locator = resolve_locator_arg(url_or_path)
|
|
184
|
-
|
|
185
|
-
cache_str = " (already cached)" if was_cached else ""
|
|
184
|
+
cache_result = cache_file(locator, expiration_sec=expiration_sec)
|
|
185
|
+
cache_str = " (already cached)" if cache_result.was_cached else ""
|
|
186
186
|
cprint(f"{fmt_loc(url_or_path)}{cache_str}:", style=STYLE_EMPH, text_wrap=Wrap.NONE)
|
|
187
|
-
cprint(f"{
|
|
187
|
+
cprint(f"{cache_result.content.path}", text_wrap=Wrap.INDENT_ONLY)
|
|
188
188
|
PrintHooks.spacer()
|
|
189
189
|
|
|
190
190
|
|
|
191
191
|
@kash_command
|
|
192
|
-
def download(*urls_or_paths: str, refetch: bool = False) ->
|
|
192
|
+
def download(*urls_or_paths: str, refetch: bool = False) -> ShellResult:
|
|
193
193
|
"""
|
|
194
194
|
Download a URL or resource. Uses cached content if available, unless `refetch` is true.
|
|
195
195
|
Inputs can be URLs or paths to URL resources.
|
|
@@ -198,31 +198,49 @@ def download(*urls_or_paths: str, refetch: bool = False) -> None:
|
|
|
198
198
|
|
|
199
199
|
# TODO: Add option to include frontmatter metadata for text files.
|
|
200
200
|
ws = current_ws()
|
|
201
|
+
saved_paths = []
|
|
201
202
|
for url_or_path in urls_or_paths:
|
|
202
203
|
locator = resolve_locator_arg(url_or_path)
|
|
203
|
-
url = None
|
|
204
|
+
url: Url | None = None
|
|
204
205
|
if not isinstance(locator, Path) and is_url(locator):
|
|
205
206
|
url = Url(locator)
|
|
206
207
|
if isinstance(locator, StorePath):
|
|
207
208
|
url_item = ws.load(locator)
|
|
208
|
-
if
|
|
209
|
+
if is_url_resource(url_item):
|
|
209
210
|
url = url_item.url
|
|
210
211
|
if not url:
|
|
211
212
|
raise InvalidInput(f"Not a URL or URL resource: {fmt_loc(locator)}")
|
|
212
213
|
|
|
213
214
|
if is_media_url(url):
|
|
214
|
-
store_path = ws.import_item(locator, as_type=ItemType.resource)
|
|
215
215
|
log.message(
|
|
216
|
-
"URL is a media URL, so
|
|
216
|
+
"URL is a media URL, so adding as a resource and will cache media: %s", fmt_loc(url)
|
|
217
217
|
)
|
|
218
|
+
store_path = ws.import_item(locator, as_type=ItemType.resource)
|
|
218
219
|
media_tools.cache_media(url)
|
|
219
220
|
else:
|
|
220
221
|
log.message("Will cache file and save to workspace: %s", fmt_loc(url))
|
|
221
|
-
|
|
222
|
-
|
|
222
|
+
original_filename = Path(parse_http_url(url).path).name
|
|
223
|
+
cache_result = cache_file(url, expiration_sec=expiration_sec)
|
|
224
|
+
# If available, use the mime type to help set item file extension.
|
|
225
|
+
mime_type = cache_result.content.headers and cache_result.content.headers.mime_type
|
|
226
|
+
item = Item.from_external_path(
|
|
227
|
+
cache_result.content.path,
|
|
228
|
+
ItemType.resource,
|
|
229
|
+
mime_type=mime_type,
|
|
230
|
+
original_filename=original_filename,
|
|
231
|
+
)
|
|
223
232
|
store_path = ws.save(item)
|
|
233
|
+
saved_paths.append(store_path)
|
|
234
|
+
|
|
235
|
+
print_status(
|
|
236
|
+
"Downloaded %s %s:\n%s",
|
|
237
|
+
len(urls_or_paths),
|
|
238
|
+
plural("item", len(urls_or_paths)),
|
|
239
|
+
fmt_lines(saved_paths),
|
|
240
|
+
)
|
|
241
|
+
select(*saved_paths)
|
|
224
242
|
|
|
225
|
-
|
|
243
|
+
return ShellResult(show_selection=True)
|
|
226
244
|
|
|
227
245
|
|
|
228
246
|
@kash_command
|
|
@@ -437,7 +455,7 @@ def import_item(
|
|
|
437
455
|
*files_or_urls: str, type: ItemType | None = None, inplace: bool = False
|
|
438
456
|
) -> ShellResult:
|
|
439
457
|
"""
|
|
440
|
-
Add a file or URL resource to the workspace as an item
|
|
458
|
+
Add a file or URL resource to the workspace as an item.
|
|
441
459
|
|
|
442
460
|
:param inplace: If set and the item is already in the store, reimport the item,
|
|
443
461
|
adding or rewriting metadata frontmatter.
|
|
@@ -464,6 +482,34 @@ def import_item(
|
|
|
464
482
|
return ShellResult(show_selection=True)
|
|
465
483
|
|
|
466
484
|
|
|
485
|
+
@kash_command
|
|
486
|
+
def import_clipboard(
|
|
487
|
+
title: str | None = "pasted_text",
|
|
488
|
+
type: ItemType = ItemType.resource,
|
|
489
|
+
format: Format = Format.plaintext,
|
|
490
|
+
) -> ShellResult:
|
|
491
|
+
"""
|
|
492
|
+
Import the contents of the OS-native clipboard as a new item in the workspace.
|
|
493
|
+
|
|
494
|
+
:param title: The title of the new item (default: "pasted_text").
|
|
495
|
+
:param type: The type of the new item (default: resource).
|
|
496
|
+
:param format: The format of the new item (default: plaintext).
|
|
497
|
+
"""
|
|
498
|
+
import pyperclip
|
|
499
|
+
|
|
500
|
+
contents = pyperclip.paste()
|
|
501
|
+
if not contents.strip():
|
|
502
|
+
raise InvalidInput("Clipboard is empty")
|
|
503
|
+
|
|
504
|
+
ws = current_ws()
|
|
505
|
+
store_path = ws.save(Item(type=type, format=format, title=title, body=contents))
|
|
506
|
+
|
|
507
|
+
print_status("Imported clipboard contents to:\n%s", fmt_lines([fmt_loc(store_path)]))
|
|
508
|
+
select(store_path)
|
|
509
|
+
|
|
510
|
+
return ShellResult(show_selection=True)
|
|
511
|
+
|
|
512
|
+
|
|
467
513
|
@kash_command
|
|
468
514
|
def fetch_metadata(*files_or_urls: str, refetch: bool = False) -> ShellResult:
|
|
469
515
|
"""
|
|
@@ -104,7 +104,7 @@ def load_source_code() -> SourceCode:
|
|
|
104
104
|
kash_base_path / "model" / "assistant_response_model.py",
|
|
105
105
|
),
|
|
106
106
|
text_tool_src=read_source_code(
|
|
107
|
-
kash_base_path / "text_handling",
|
|
107
|
+
kash_base_path / "utils" / "text_handling",
|
|
108
108
|
kash_base_path / "utils" / "lang_utils",
|
|
109
109
|
# TODO: Include additional dep libs like chopdiff TextDoc too?
|
|
110
110
|
),
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import time
|
|
2
2
|
from dataclasses import replace
|
|
3
3
|
|
|
4
|
-
from prettyfmt import fmt_lines
|
|
4
|
+
from prettyfmt import fmt_lines, plural
|
|
5
5
|
|
|
6
6
|
from kash.config.logger import get_logger
|
|
7
7
|
from kash.config.text_styles import (
|
|
@@ -10,7 +10,7 @@ from kash.config.text_styles import (
|
|
|
10
10
|
EMOJI_SUCCESS,
|
|
11
11
|
EMOJI_TIMING,
|
|
12
12
|
)
|
|
13
|
-
from kash.exec.preconditions import
|
|
13
|
+
from kash.exec.preconditions import is_url_resource
|
|
14
14
|
from kash.exec.resolve_args import assemble_action_args
|
|
15
15
|
from kash.exec_model.args_model import CommandArg
|
|
16
16
|
from kash.file_storage.file_store import FileStore
|
|
@@ -28,7 +28,6 @@ from kash.model.operations_model import Input, Operation, Source
|
|
|
28
28
|
from kash.model.params_model import ALL_COMMON_PARAMS, GLOBAL_PARAMS, RawParamValues
|
|
29
29
|
from kash.model.paths_model import StorePath
|
|
30
30
|
from kash.shell.output.shell_output import PrintHooks
|
|
31
|
-
from kash.utils.common.inflection import plural
|
|
32
31
|
from kash.utils.common.task_stack import task_stack
|
|
33
32
|
from kash.utils.common.type_utils import not_none
|
|
34
33
|
from kash.utils.errors import ContentError, InvalidOutput, get_nonfatal_exceptions
|
|
@@ -56,7 +55,7 @@ def prepare_action_input(*input_args: CommandArg, refetch: bool = False) -> Acti
|
|
|
56
55
|
if input_items:
|
|
57
56
|
log.message("Assembling metadata for input items:\n%s", fmt_lines(input_items))
|
|
58
57
|
input_items = [
|
|
59
|
-
fetch_url_item_metadata(item, refetch=refetch) if
|
|
58
|
+
fetch_url_item_metadata(item, refetch=refetch) if is_url_resource(item) else item
|
|
60
59
|
for item in input_items
|
|
61
60
|
]
|
|
62
61
|
|
|
@@ -299,7 +298,7 @@ def save_action_result(
|
|
|
299
298
|
skipped_paths.append(store_path)
|
|
300
299
|
continue
|
|
301
300
|
|
|
302
|
-
ws.save(item, as_tmp=as_tmp, no_format=no_format)
|
|
301
|
+
ws.save(item, overwrite=result.overwrite, as_tmp=as_tmp, no_format=no_format)
|
|
303
302
|
|
|
304
303
|
if skipped_paths:
|
|
305
304
|
log.message(
|
|
@@ -1,19 +1,18 @@
|
|
|
1
1
|
from kash.config.logger import get_logger
|
|
2
|
-
from kash.exec.preconditions import
|
|
2
|
+
from kash.exec.preconditions import is_url_resource
|
|
3
3
|
from kash.media_base.media_services import get_media_metadata
|
|
4
4
|
from kash.model.items_model import Item, ItemType
|
|
5
5
|
from kash.model.paths_model import StorePath
|
|
6
6
|
from kash.utils.common.format_utils import fmt_loc
|
|
7
7
|
from kash.utils.common.url import Url, is_url
|
|
8
8
|
from kash.utils.errors import InvalidInput
|
|
9
|
-
from kash.web_content.canon_url import canonicalize_url
|
|
10
|
-
from kash.web_content.web_extract import fetch_extract
|
|
11
|
-
from kash.workspaces import current_ws
|
|
12
9
|
|
|
13
10
|
log = get_logger(__name__)
|
|
14
11
|
|
|
15
12
|
|
|
16
13
|
def fetch_url_metadata(locator: Url | StorePath, refetch: bool = False) -> Item:
|
|
14
|
+
from kash.workspaces import current_ws
|
|
15
|
+
|
|
17
16
|
ws = current_ws()
|
|
18
17
|
if is_url(locator):
|
|
19
18
|
# Import or find URL as a resource in the current workspace.
|
|
@@ -21,7 +20,7 @@ def fetch_url_metadata(locator: Url | StorePath, refetch: bool = False) -> Item:
|
|
|
21
20
|
item = ws.load(store_path)
|
|
22
21
|
elif isinstance(locator, StorePath):
|
|
23
22
|
item = ws.load(locator)
|
|
24
|
-
if not
|
|
23
|
+
if not is_url_resource(item):
|
|
25
24
|
raise InvalidInput(f"Not a URL resource: {fmt_loc(locator)}")
|
|
26
25
|
else:
|
|
27
26
|
raise InvalidInput(f"Not a URL or URL resource: {fmt_loc(locator)}")
|
|
@@ -34,6 +33,10 @@ def fetch_url_item_metadata(item: Item, refetch: bool = False) -> Item:
|
|
|
34
33
|
Fetch metadata for a URL using a media service if we recognize the URL,
|
|
35
34
|
and otherwise fetching and extracting it from the web page HTML.
|
|
36
35
|
"""
|
|
36
|
+
from kash.web_content.canon_url import canonicalize_url
|
|
37
|
+
from kash.web_content.web_extract import fetch_extract
|
|
38
|
+
from kash.workspaces import current_ws
|
|
39
|
+
|
|
37
40
|
ws = current_ws()
|
|
38
41
|
if not refetch and item.title and item.description:
|
|
39
42
|
log.message(
|
|
@@ -5,7 +5,7 @@ from prettyfmt import fmt_lines, fmt_path
|
|
|
5
5
|
from kash.config.logger import get_logger
|
|
6
6
|
from kash.exec.action_registry import action_classes, refresh_action_classes
|
|
7
7
|
from kash.exec.command_registry import get_all_commands
|
|
8
|
-
from kash.utils.common.import_utils import Tallies,
|
|
8
|
+
from kash.utils.common.import_utils import Tallies, import_recursive
|
|
9
9
|
|
|
10
10
|
log = get_logger(__name__)
|
|
11
11
|
|
|
@@ -13,12 +13,12 @@ log = get_logger(__name__)
|
|
|
13
13
|
def import_and_register(
|
|
14
14
|
package_name: str | None,
|
|
15
15
|
parent_dir: Path,
|
|
16
|
-
|
|
16
|
+
resource_names: list[str] | None = None,
|
|
17
17
|
tallies: Tallies | None = None,
|
|
18
18
|
):
|
|
19
19
|
"""
|
|
20
20
|
This hook can be used for auto-registering commands and actions from any
|
|
21
|
-
subdirectory of a given package.
|
|
21
|
+
module or subdirectory of a given package.
|
|
22
22
|
|
|
23
23
|
Useful to call from `__init__.py` files to import a directory of code,
|
|
24
24
|
auto-registering annotated commands and actions and also handles refreshing the
|
|
@@ -38,7 +38,7 @@ def import_and_register(
|
|
|
38
38
|
prev_command_count = len(get_all_commands())
|
|
39
39
|
prev_action_count = len(ac)
|
|
40
40
|
|
|
41
|
-
|
|
41
|
+
import_recursive(package_name, parent_dir, resource_names, tallies)
|
|
42
42
|
|
|
43
43
|
new_command_count = len(get_all_commands()) - prev_command_count
|
|
44
44
|
new_action_count = len(ac) - prev_action_count
|
|
@@ -13,9 +13,9 @@ from kash.llm_utils.llm_completion import llm_template_completion
|
|
|
13
13
|
from kash.llm_utils.llm_messages import Message, MessageTemplate
|
|
14
14
|
from kash.model.actions_model import LLMOptions
|
|
15
15
|
from kash.model.items_model import Item
|
|
16
|
-
from kash.text_handling.doc_normalization import normalize_formatting
|
|
17
16
|
from kash.utils.errors import InvalidInput
|
|
18
17
|
from kash.utils.file_utils.file_formats_model import Format
|
|
18
|
+
from kash.utils.text_handling.doc_normalization import normalize_formatting
|
|
19
19
|
|
|
20
20
|
log = get_logger(__name__)
|
|
21
21
|
|
|
@@ -7,9 +7,9 @@ from chopdiff.html import has_timestamp
|
|
|
7
7
|
|
|
8
8
|
from kash.exec.precondition_registry import kash_precondition
|
|
9
9
|
from kash.model.items_model import Item, ItemType
|
|
10
|
-
from kash.text_handling.markdown_utils import extract_bullet_points
|
|
11
10
|
from kash.utils.file_utils.file_formats import is_full_html_page
|
|
12
11
|
from kash.utils.file_utils.file_formats_model import Format
|
|
12
|
+
from kash.utils.text_handling.markdown_utils import extract_bullet_points
|
|
13
13
|
|
|
14
14
|
|
|
15
15
|
@kash_precondition
|
|
@@ -32,6 +32,11 @@ def is_docx_resource(item: Item) -> bool:
|
|
|
32
32
|
return bool(is_resource(item) and item.format and item.format == Format.docx)
|
|
33
33
|
|
|
34
34
|
|
|
35
|
+
@kash_precondition
|
|
36
|
+
def is_pdf_resource(item: Item) -> bool:
|
|
37
|
+
return bool(is_resource(item) and item.format and item.format == Format.pdf)
|
|
38
|
+
|
|
39
|
+
|
|
35
40
|
@kash_precondition
|
|
36
41
|
def is_concept(item: Item) -> bool:
|
|
37
42
|
return item.type == ItemType.concept
|
|
@@ -53,7 +58,7 @@ def is_instructions(item: Item) -> bool:
|
|
|
53
58
|
|
|
54
59
|
|
|
55
60
|
@kash_precondition
|
|
56
|
-
def
|
|
61
|
+
def is_url_resource(item: Item) -> bool:
|
|
57
62
|
return bool(item.type == ItemType.resource and item.url)
|
|
58
63
|
|
|
59
64
|
|
|
@@ -114,11 +119,6 @@ def is_markdown_template(item: Item) -> bool:
|
|
|
114
119
|
return is_markdown(item) and contains_curly_vars(item)
|
|
115
120
|
|
|
116
121
|
|
|
117
|
-
@kash_precondition
|
|
118
|
-
def is_html(item: Item) -> bool:
|
|
119
|
-
return has_body(item) and item.format == Format.html
|
|
120
|
-
|
|
121
|
-
|
|
122
122
|
@kash_precondition
|
|
123
123
|
def is_markdown_list(item: Item) -> bool:
|
|
124
124
|
try:
|