code-puppy 0.0.577__tar.gz → 0.0.579__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.
- {code_puppy-0.0.577 → code_puppy-0.0.579}/PKG-INFO +1 -1
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/cli_runner.py +170 -126
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/command_line/autosave_menu.py +49 -6
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/command_line/session_commands.py +79 -47
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/config.py +172 -27
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/plugins/agent_skills/config.py +9 -5
- code_puppy-0.0.579/code_puppy/plugins/plugin_list/plugin_contributions.py +355 -0
- code_puppy-0.0.579/code_puppy/plugins/plugin_list/plugin_meta.py +67 -0
- code_puppy-0.0.579/code_puppy/plugins/plugin_list/plugin_text_utils.py +177 -0
- code_puppy-0.0.579/code_puppy/plugins/plugin_list/plugins_menu.py +419 -0
- code_puppy-0.0.579/code_puppy/plugins/plugin_list/plugins_menu_render.py +297 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/plugins/plugin_list/register_callbacks.py +69 -60
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/plugins/switch_agent_resume/register_callbacks.py +4 -4
- code_puppy-0.0.579/code_puppy/session_lifecycle.py +317 -0
- code_puppy-0.0.579/code_puppy/session_migration.py +222 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/session_storage.py +2 -2
- {code_puppy-0.0.577 → code_puppy-0.0.579}/pyproject.toml +1 -1
- code_puppy-0.0.577/code_puppy/plugins/plugin_list/plugins_menu.py +0 -328
- {code_puppy-0.0.577 → code_puppy-0.0.579}/.gitignore +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/LICENSE +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/README.md +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/__init__.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/__main__.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/agents/__init__.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/agents/_builder.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/agents/_compaction.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/agents/_diagnostics.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/agents/_history.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/agents/_key_listeners.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/agents/_non_streaming_render.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/agents/_run_signals.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/agents/_runtime.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/agents/_steer_processor.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/agents/agent_code_puppy.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/agents/agent_creator_agent.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/agents/agent_helios.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/agents/agent_manager.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/agents/agent_planning.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/agents/agent_qa_kitten.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/agents/base_agent.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/agents/event_stream_handler.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/agents/json_agent.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/agents/run_stats.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/agents/smooth_stream.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/agents/subagent_stream_handler.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/callbacks.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/chatgpt_codex_client.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/claude_cache_client.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/command_line/__init__.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/command_line/add_model_menu.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/command_line/agent_menu.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/command_line/attachments.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/command_line/autosave_search.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/command_line/clipboard.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/command_line/colors_menu.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/command_line/command_handler.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/command_line/command_registry.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/command_line/config_apply.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/command_line/config_commands.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/command_line/core_commands.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/command_line/diff_menu.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/command_line/file_index.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/command_line/file_path_completion.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/command_line/judges_menu.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/command_line/load_context_completion.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/command_line/mcp/__init__.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/command_line/mcp/base.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/command_line/mcp/catalog_server_installer.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/command_line/mcp/custom_server_form.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/command_line/mcp/custom_server_installer.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/command_line/mcp/edit_command.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/command_line/mcp/handler.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/command_line/mcp/help_command.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/command_line/mcp/install_command.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/command_line/mcp/install_menu.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/command_line/mcp/list_command.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/command_line/mcp/logs_command.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/command_line/mcp/remove_command.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/command_line/mcp/restart_command.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/command_line/mcp/search_command.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/command_line/mcp/silence_warning_command.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/command_line/mcp/start_all_command.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/command_line/mcp/start_command.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/command_line/mcp/status_command.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/command_line/mcp/stop_all_command.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/command_line/mcp/stop_command.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/command_line/mcp/utils.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/command_line/mcp/wizard_utils.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/command_line/mcp_binding_menu.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/command_line/mcp_completion.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/command_line/model_picker_completion.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/command_line/model_settings_menu.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/command_line/onboarding_slides.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/command_line/onboarding_wizard.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/command_line/pagination.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/command_line/pin_command_completion.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/command_line/prompt_toolkit_completion.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/command_line/set_menu.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/command_line/set_menu_catalog.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/command_line/set_menu_render.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/command_line/set_menu_schema.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/command_line/set_menu_settings.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/command_line/set_menu_shims.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/command_line/set_menu_values.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/command_line/shell_passthrough.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/command_line/skills_completion.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/command_line/uc_menu.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/command_line/utils.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/command_line/wiggum_state.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/error_logging.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/gemini_code_assist.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/gemini_model.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/hook_engine/README.md +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/hook_engine/__init__.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/hook_engine/aliases.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/hook_engine/engine.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/hook_engine/executor.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/hook_engine/matcher.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/hook_engine/models.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/hook_engine/registry.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/hook_engine/validator.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/http_utils.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/keymap.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/list_filtering.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/main.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/mcp_/__init__.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/mcp_/agent_bindings.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/mcp_/async_lifecycle.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/mcp_/blocking_startup.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/mcp_/captured_stdio_server.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/mcp_/circuit_breaker.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/mcp_/config_wizard.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/mcp_/dashboard.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/mcp_/error_isolation.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/mcp_/examples/retry_example.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/mcp_/health_monitor.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/mcp_/managed_server.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/mcp_/manager.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/mcp_/mcp_logs.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/mcp_/registry.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/mcp_/retry_manager.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/mcp_/server_registry_catalog.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/mcp_/status_tracker.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/mcp_/system_tools.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/mcp_prompts/__init__.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/mcp_prompts/hook_creator.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/messaging/__init__.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/messaging/bus.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/messaging/commands.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/messaging/markdown_patches.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/messaging/message_queue.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/messaging/messages.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/messaging/pause_controller.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/messaging/queue_console.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/messaging/renderers.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/messaging/rich_renderer.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/messaging/spinner/__init__.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/messaging/spinner/console_spinner.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/messaging/spinner/spinner_base.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/messaging/subagent_console.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/model_descriptions.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/model_factory.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/model_switching.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/model_utils.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/models.json +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/models_dev_api.json +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/models_dev_parser.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/plugins/__init__.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/plugins/agent_skills/__init__.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/plugins/agent_skills/discovery.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/plugins/agent_skills/downloader.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/plugins/agent_skills/enabled_skills.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/plugins/agent_skills/installer.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/plugins/agent_skills/metadata.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/plugins/agent_skills/prompt_builder.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/plugins/agent_skills/register_callbacks.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/plugins/agent_skills/remote_catalog.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/plugins/agent_skills/skill_catalog.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/plugins/agent_skills/skill_commands.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/plugins/agent_skills/skills_install_menu.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/plugins/agent_skills/skills_menu.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/plugins/agent_steering/README.md +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/plugins/agent_steering/__init__.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/plugins/agent_steering/line_editor.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/plugins/agent_steering/register_callbacks.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/plugins/agent_steering/steering_prompt.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/plugins/aws_bedrock/__init__.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/plugins/aws_bedrock/config.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/plugins/aws_bedrock/register_callbacks.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/plugins/aws_bedrock/utils.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/plugins/azure_foundry/README.md +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/plugins/azure_foundry/__init__.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/plugins/azure_foundry/config.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/plugins/azure_foundry/discovery.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/plugins/azure_foundry/register_callbacks.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/plugins/azure_foundry/token.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/plugins/azure_foundry/utils.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/plugins/chatgpt_oauth/__init__.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/plugins/chatgpt_oauth/config.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/plugins/chatgpt_oauth/oauth_flow.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/plugins/chatgpt_oauth/register_callbacks.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/plugins/chatgpt_oauth/test_plugin.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/plugins/chatgpt_oauth/utils.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/plugins/claude_code_hooks/__init__.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/plugins/claude_code_hooks/config.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/plugins/claude_code_hooks/register_callbacks.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/plugins/claude_code_oauth/README.md +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/plugins/claude_code_oauth/SETUP.md +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/plugins/claude_code_oauth/__init__.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/plugins/claude_code_oauth/config.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/plugins/claude_code_oauth/fast_mode.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/plugins/claude_code_oauth/prompt_handler.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/plugins/claude_code_oauth/register_callbacks.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/plugins/claude_code_oauth/test_fast_mode.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/plugins/claude_code_oauth/test_plugin.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/plugins/claude_code_oauth/token_refresh_heartbeat.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/plugins/claude_code_oauth/utils.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/plugins/code_puppy_agent/SKILL.md +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/plugins/code_puppy_agent/__init__.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/plugins/code_puppy_agent/register_callbacks.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/plugins/config.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/plugins/context_indicator/__init__.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/plugins/context_indicator/register_callbacks.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/plugins/context_indicator/usage.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/plugins/copilot_auth/__init__.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/plugins/copilot_auth/config.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/plugins/copilot_auth/reasoning_client.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/plugins/copilot_auth/register_callbacks.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/plugins/copilot_auth/utils.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/plugins/customizable_commands/__init__.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/plugins/customizable_commands/register_callbacks.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/plugins/dbos_durable_exec/__init__.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/plugins/dbos_durable_exec/cancel.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/plugins/dbos_durable_exec/commands.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/plugins/dbos_durable_exec/config.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/plugins/dbos_durable_exec/lifecycle.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/plugins/dbos_durable_exec/register_callbacks.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/plugins/dbos_durable_exec/runtime.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/plugins/dbos_durable_exec/startup_lock.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/plugins/dbos_durable_exec/workflow_ids.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/plugins/dbos_durable_exec/wrapper.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/plugins/destructive_command_guard/__init__.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/plugins/destructive_command_guard/detector.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/plugins/destructive_command_guard/register_callbacks.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/plugins/emoji_filter/__init__.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/plugins/emoji_filter/config.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/plugins/emoji_filter/register_callbacks.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/plugins/emoji_filter/stripper.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/plugins/example_custom_command/README.md +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/plugins/example_custom_command/register_callbacks.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/plugins/file_permission_handler/__init__.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/plugins/file_permission_handler/register_callbacks.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/plugins/force_push_guard/__init__.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/plugins/force_push_guard/detector.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/plugins/force_push_guard/register_callbacks.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/plugins/force_push_guard/test_detector.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/plugins/frontend_emitter/__init__.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/plugins/frontend_emitter/emitter.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/plugins/frontend_emitter/register_callbacks.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/plugins/frontend_emitter/session_context.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/plugins/hook_creator/__init__.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/plugins/hook_creator/register_callbacks.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/plugins/hook_manager/__init__.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/plugins/hook_manager/config.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/plugins/hook_manager/hooks_menu.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/plugins/hook_manager/register_callbacks.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/plugins/oauth_puppy_html.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/plugins/obsidian_agent/README.md +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/plugins/obsidian_agent/__init__.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/plugins/obsidian_agent/agent_obsidian.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/plugins/obsidian_agent/register_callbacks.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/plugins/ollama/__init__.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/plugins/ollama/register_callbacks.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/plugins/ollama_setup/__init__.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/plugins/ollama_setup/completer.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/plugins/ollama_setup/register_callbacks.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/plugins/plugin_list/__init__.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/plugins/pop_command/__init__.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/plugins/pop_command/register_callbacks.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/plugins/prompt_newline/__init__.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/plugins/prompt_newline/config.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/plugins/prompt_newline/register_callbacks.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/plugins/prune/__init__.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/plugins/prune/prune_menu.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/plugins/prune/prune_model.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/plugins/prune/prune_render.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/plugins/prune/register_callbacks.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/plugins/puppy_kennel/README.md +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/plugins/puppy_kennel/__init__.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/plugins/puppy_kennel/commands.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/plugins/puppy_kennel/config.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/plugins/puppy_kennel/kennel.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/plugins/puppy_kennel/packer.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/plugins/puppy_kennel/recorder.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/plugins/puppy_kennel/register_callbacks.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/plugins/puppy_kennel/retriever.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/plugins/puppy_kennel/schema.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/plugins/puppy_kennel/state.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/plugins/puppy_kennel/tools.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/plugins/puppy_kennel/wings.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/plugins/quick_resume/__init__.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/plugins/quick_resume/register_callbacks.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/plugins/review_pr/__init__.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/plugins/review_pr/register_callbacks.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/plugins/shell_safety/__init__.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/plugins/shell_safety/agent_shell_safety.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/plugins/shell_safety/command_cache.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/plugins/shell_safety/register_callbacks.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/plugins/statusline/__init__.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/plugins/statusline/config.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/plugins/statusline/payload.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/plugins/statusline/prompt_patch.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/plugins/statusline/register_callbacks.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/plugins/statusline/runner.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/plugins/statusline/statusline_command.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/plugins/subagent_panel/README.md +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/plugins/subagent_panel/__init__.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/plugins/subagent_panel/coalesce_patch.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/plugins/subagent_panel/register_callbacks.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/plugins/subagent_panel/resume_repaint.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/plugins/subagent_panel/state.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/plugins/switch_agent_resume/__init__.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/plugins/synthetic_status/__init__.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/plugins/synthetic_status/register_callbacks.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/plugins/synthetic_status/status_api.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/plugins/theme/README.md +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/plugins/theme/__init__.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/plugins/theme/bundled_palettes.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/plugins/theme/content_styles.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/plugins/theme/osc_palette.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/plugins/theme/picker.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/plugins/theme/register_callbacks.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/plugins/theme/rich_themes.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/plugins/theme/themes.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/plugins/token_ratio_learner/__init__.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/plugins/token_ratio_learner/ratios.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/plugins/token_ratio_learner/register_callbacks.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/plugins/universal_constructor/__init__.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/plugins/universal_constructor/models.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/plugins/universal_constructor/register_callbacks.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/plugins/universal_constructor/registry.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/plugins/universal_constructor/sandbox.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/plugins/wide_completion_menu/__init__.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/plugins/wide_completion_menu/register_callbacks.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/plugins/wiggum/__init__.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/plugins/wiggum/judge.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/plugins/wiggum/judge_config.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/plugins/wiggum/register_callbacks.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/plugins/wiggum/state.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/provider_credentials.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/provider_identity.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/pydantic_patches.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/reopenable_async_client.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/round_robin_model.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/status_display.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/summarization_agent.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/terminal_utils.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/tools/__init__.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/tools/agent_tools.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/tools/ask_user_question/__init__.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/tools/ask_user_question/constants.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/tools/ask_user_question/demo_tui.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/tools/ask_user_question/handler.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/tools/ask_user_question/models.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/tools/ask_user_question/registration.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/tools/ask_user_question/renderers.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/tools/ask_user_question/terminal_ui.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/tools/ask_user_question/theme.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/tools/ask_user_question/tui_loop.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/tools/browser/__init__.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/tools/browser/browser_control.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/tools/browser/browser_interactions.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/tools/browser/browser_locators.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/tools/browser/browser_manager.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/tools/browser/browser_navigation.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/tools/browser/browser_screenshot.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/tools/browser/browser_scripts.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/tools/browser/browser_workflows.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/tools/command_runner.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/tools/common.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/tools/display.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/tools/file_modifications.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/tools/file_operations.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/tools/image_tools.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/tools/model_tools.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/tools/skills_tools.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/tools/subagent_context.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/tools/subagent_invocation.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/tools/tools_content.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/tools/universal_constructor.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/undo_manager.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/uvx_detection.py +0 -0
- {code_puppy-0.0.577 → code_puppy-0.0.579}/code_puppy/version_checker.py +0 -0
|
@@ -27,7 +27,7 @@ from code_puppy.config import (
|
|
|
27
27
|
COMMAND_HISTORY_FILE,
|
|
28
28
|
ensure_config_exists,
|
|
29
29
|
finalize_autosave_session,
|
|
30
|
-
|
|
30
|
+
get_current_session_name,
|
|
31
31
|
initialize_command_history_file,
|
|
32
32
|
record_terminal_session,
|
|
33
33
|
save_command_to_history,
|
|
@@ -82,57 +82,6 @@ def _render_turn_exception(exc: Exception) -> None:
|
|
|
82
82
|
get_queue_console().print_exception()
|
|
83
83
|
|
|
84
84
|
|
|
85
|
-
def _resume_session_from_path(raw_path: str) -> None:
|
|
86
|
-
"""Restore agent message history from a saved .pkl session file.
|
|
87
|
-
|
|
88
|
-
Accepts any path (autosaves, contexts, somewhere weird on disk). We don't
|
|
89
|
-
care where it lives — we just decompose into (parent_dir, stem) and reuse
|
|
90
|
-
``session_storage.load_session`` so we stay DRY.
|
|
91
|
-
"""
|
|
92
|
-
from code_puppy.agents.agent_manager import get_current_agent
|
|
93
|
-
from code_puppy.messaging import emit_error, emit_success
|
|
94
|
-
from code_puppy.session_storage import load_session
|
|
95
|
-
|
|
96
|
-
session_path = Path(raw_path).expanduser().resolve()
|
|
97
|
-
|
|
98
|
-
if not session_path.exists():
|
|
99
|
-
emit_error(f"--resume: session file not found: {session_path}")
|
|
100
|
-
sys.exit(1)
|
|
101
|
-
|
|
102
|
-
if session_path.suffix != ".pkl":
|
|
103
|
-
emit_error(
|
|
104
|
-
f"--resume: expected a .pkl session file, got '{session_path.suffix}': {session_path}"
|
|
105
|
-
)
|
|
106
|
-
sys.exit(1)
|
|
107
|
-
|
|
108
|
-
try:
|
|
109
|
-
history = load_session(session_path.stem, session_path.parent)
|
|
110
|
-
except Exception as exc:
|
|
111
|
-
emit_error(f"--resume: failed to load session: {exc}")
|
|
112
|
-
sys.exit(1)
|
|
113
|
-
|
|
114
|
-
try:
|
|
115
|
-
agent = get_current_agent()
|
|
116
|
-
agent.set_message_history(history)
|
|
117
|
-
except Exception as exc:
|
|
118
|
-
emit_error(f"--resume: failed to attach history to agent: {exc}")
|
|
119
|
-
sys.exit(1)
|
|
120
|
-
|
|
121
|
-
# Rotate autosave id so we don't clobber the original file we just resumed.
|
|
122
|
-
try:
|
|
123
|
-
from code_puppy.config import rotate_autosave_id
|
|
124
|
-
|
|
125
|
-
rotate_autosave_id()
|
|
126
|
-
except Exception:
|
|
127
|
-
pass # autosave rotation is best-effort
|
|
128
|
-
|
|
129
|
-
total_tokens = sum(agent.estimate_tokens_for_message(m) for m in history)
|
|
130
|
-
emit_success(
|
|
131
|
-
f"✅ Resumed session: {len(history)} messages ({total_tokens} tokens)\n"
|
|
132
|
-
f"📁 From: {session_path}"
|
|
133
|
-
)
|
|
134
|
-
|
|
135
|
-
|
|
136
85
|
def apply_quick_resume(args) -> bool:
|
|
137
86
|
"""Resolve ``--quick-resume [PATH]`` into ``args.resume`` so the existing
|
|
138
87
|
resume machinery loads it.
|
|
@@ -447,14 +396,98 @@ async def main():
|
|
|
447
396
|
else:
|
|
448
397
|
default_version_mismatch_behavior(current_version)
|
|
449
398
|
|
|
399
|
+
# One-shot sweep of legacy ~/.code_puppy/contexts/ into the unified
|
|
400
|
+
# autosaves/ store. Idempotent via a sentinel; safe to call every
|
|
401
|
+
# startup. MUST run before any plugin startup callback can read
|
|
402
|
+
# AUTOSAVE_DIR (otherwise a plugin could miss freshly-swept files)
|
|
403
|
+
# and before the resume block below resolves -r NAME.
|
|
404
|
+
try:
|
|
405
|
+
from code_puppy.session_migration import sweep_contexts_to_autosaves
|
|
406
|
+
|
|
407
|
+
sweep_contexts_to_autosaves()
|
|
408
|
+
except Exception:
|
|
409
|
+
# Sweep failure must never block startup -- it logs internally.
|
|
410
|
+
pass
|
|
411
|
+
|
|
450
412
|
await callbacks.on_startup()
|
|
451
413
|
|
|
452
414
|
# Resolve --quick-resume [PATH] into --resume so the resume machinery below
|
|
453
415
|
# loads the most recent session for that canonical (git-root + branch) scope.
|
|
454
416
|
apply_quick_resume(args)
|
|
455
417
|
|
|
418
|
+
# Holds the resolved (normalised) session name when -r/--resume is in
|
|
419
|
+
# effect, so save-back paths can persist into the same file the resolver
|
|
420
|
+
# opened — not the raw user input (which might be ``foo.pkl`` or an
|
|
421
|
+
# absolute path that the resolver normalised to a bare slug).
|
|
422
|
+
resolved_resume_session: str | None = None
|
|
423
|
+
|
|
456
424
|
if args.resume:
|
|
457
|
-
|
|
425
|
+
from code_puppy.agents.agent_manager import get_current_agent
|
|
426
|
+
from code_puppy.config import AUTOSAVE_DIR, pin_current_session_name
|
|
427
|
+
from code_puppy.messaging import emit_error, emit_info, emit_success
|
|
428
|
+
from code_puppy.session_lifecycle import (
|
|
429
|
+
ResumeTargetError,
|
|
430
|
+
resolve_or_create_resume_target,
|
|
431
|
+
)
|
|
432
|
+
from code_puppy.session_storage import list_sessions, load_session
|
|
433
|
+
|
|
434
|
+
resume_target = args.resume
|
|
435
|
+
sessions_dir = Path(AUTOSAVE_DIR)
|
|
436
|
+
|
|
437
|
+
# Lazy-create is symmetric across modes: both headless and
|
|
438
|
+
# interactive accept ``-r missing-name`` and materialise an
|
|
439
|
+
# empty session. The typo-guard concern is preserved by the
|
|
440
|
+
# visible ``Created new session: NAME`` info line plus the
|
|
441
|
+
# empty ``message_count: 0`` initial state.
|
|
442
|
+
try:
|
|
443
|
+
session_name, session_dir, lazy_created = resolve_or_create_resume_target(
|
|
444
|
+
resume_target,
|
|
445
|
+
sessions_dir=sessions_dir,
|
|
446
|
+
allow_lazy_create=True,
|
|
447
|
+
)
|
|
448
|
+
except ResumeTargetError as resolve_exc:
|
|
449
|
+
emit_error(resolve_exc.message)
|
|
450
|
+
if resolve_exc.hint:
|
|
451
|
+
emit_info(resolve_exc.hint)
|
|
452
|
+
available = list_sessions(sessions_dir)
|
|
453
|
+
if available:
|
|
454
|
+
emit_info(f"Available sessions: {', '.join(available[:10])}")
|
|
455
|
+
sys.exit(1)
|
|
456
|
+
|
|
457
|
+
# When lazy-create fired, announce it so scripts and users can
|
|
458
|
+
# distinguish first-run creation from a normal resume.
|
|
459
|
+
if lazy_created:
|
|
460
|
+
emit_info(f"Created new session: {session_name}")
|
|
461
|
+
|
|
462
|
+
try:
|
|
463
|
+
history = load_session(session_name, session_dir)
|
|
464
|
+
agent = get_current_agent()
|
|
465
|
+
agent.set_message_history(history)
|
|
466
|
+
total_tokens = sum(agent.estimate_tokens_for_message(m) for m in history)
|
|
467
|
+
|
|
468
|
+
# Pin the singleton so periodic autosave AND headless save-back
|
|
469
|
+
# both update this named file in place. Replaces the old
|
|
470
|
+
# rotate_autosave_id() call, which under unification would
|
|
471
|
+
# actively undo the named-session wiring we want.
|
|
472
|
+
#
|
|
473
|
+
# Note: even when the user resumed via an absolute path
|
|
474
|
+
# (resolver branches 1 or 3), we pin the *stem* and let
|
|
475
|
+
# subsequent writes land in AUTOSAVE_DIR. That keeps cross-mode
|
|
476
|
+
# resume by name consistent; users who passed a one-off path
|
|
477
|
+
# can copy the resulting AUTOSAVE_DIR file back if they care.
|
|
478
|
+
pin_current_session_name(session_name)
|
|
479
|
+
|
|
480
|
+
# Record the resolved name for the headless save-back path below.
|
|
481
|
+
resolved_resume_session = session_name
|
|
482
|
+
|
|
483
|
+
if not lazy_created:
|
|
484
|
+
emit_success(
|
|
485
|
+
f"Resumed: {len(history)} messages "
|
|
486
|
+
f"({total_tokens} tokens) from {session_name}"
|
|
487
|
+
)
|
|
488
|
+
except Exception as e:
|
|
489
|
+
emit_error(f"Failed to resume from {resume_target}: {e}")
|
|
490
|
+
sys.exit(1)
|
|
458
491
|
|
|
459
492
|
global shutdown_flag
|
|
460
493
|
shutdown_flag = False
|
|
@@ -470,7 +503,11 @@ async def main():
|
|
|
470
503
|
prompt_only_mode = False
|
|
471
504
|
|
|
472
505
|
if prompt_only_mode:
|
|
473
|
-
await execute_single_prompt(
|
|
506
|
+
await execute_single_prompt(
|
|
507
|
+
initial_command,
|
|
508
|
+
message_renderer,
|
|
509
|
+
session_name=resolved_resume_session,
|
|
510
|
+
)
|
|
474
511
|
else:
|
|
475
512
|
# Default to interactive mode (no args = same as -i)
|
|
476
513
|
await interactive_mode(message_renderer, initial_command=initial_command)
|
|
@@ -652,55 +689,7 @@ async def interactive_mode(message_renderer, initial_command: str = None) -> Non
|
|
|
652
689
|
|
|
653
690
|
# Autosave loading is now manual - use /autosave_load command
|
|
654
691
|
|
|
655
|
-
|
|
656
|
-
record_terminal_session(get_current_autosave_session_name(), overwrite=False)
|
|
657
|
-
|
|
658
|
-
# Auto-run tutorial on first startup
|
|
659
|
-
try:
|
|
660
|
-
from code_puppy.command_line.onboarding_wizard import should_show_onboarding
|
|
661
|
-
|
|
662
|
-
if should_show_onboarding():
|
|
663
|
-
import concurrent.futures
|
|
664
|
-
|
|
665
|
-
from code_puppy.command_line.onboarding_wizard import run_onboarding_wizard
|
|
666
|
-
from code_puppy.config import set_model_name
|
|
667
|
-
from code_puppy.messaging import emit_info
|
|
668
|
-
|
|
669
|
-
from code_puppy.command_line.onboarding_wizard import (
|
|
670
|
-
require_model_setup_if_needed,
|
|
671
|
-
)
|
|
672
|
-
|
|
673
|
-
with concurrent.futures.ThreadPoolExecutor() as executor:
|
|
674
|
-
future = executor.submit(lambda: asyncio.run(run_onboarding_wizard()))
|
|
675
|
-
result = future.result(timeout=300)
|
|
676
|
-
|
|
677
|
-
if result == "chatgpt":
|
|
678
|
-
emit_info("🔐 Starting ChatGPT OAuth flow...")
|
|
679
|
-
from code_puppy.plugins.chatgpt_oauth.oauth_flow import run_oauth_flow
|
|
680
|
-
|
|
681
|
-
run_oauth_flow()
|
|
682
|
-
set_model_name("chatgpt-gpt-5.4")
|
|
683
|
-
elif result == "claude":
|
|
684
|
-
emit_info("🔐 Starting Claude Code OAuth flow...")
|
|
685
|
-
from code_puppy.plugins.claude_code_oauth.register_callbacks import (
|
|
686
|
-
_perform_authentication,
|
|
687
|
-
)
|
|
688
|
-
|
|
689
|
-
_perform_authentication()
|
|
690
|
-
set_model_name("claude-code-claude-opus-4-7")
|
|
691
|
-
elif result == "completed":
|
|
692
|
-
emit_info("🎉 Tutorial complete! Happy coding!")
|
|
693
|
-
elif result == "skipped":
|
|
694
|
-
emit_info("⏭️ Tutorial skipped. Run /tutorial anytime!")
|
|
695
|
-
|
|
696
|
-
# No bundled default model anymore: if the user skipped OAuth they
|
|
697
|
-
# must add a model explicitly.
|
|
698
|
-
require_model_setup_if_needed(result)
|
|
699
|
-
except Exception as e:
|
|
700
|
-
from code_puppy.messaging import emit_warning
|
|
701
|
-
|
|
702
|
-
emit_warning(f"Tutorial auto-start failed: {e}")
|
|
703
|
-
|
|
692
|
+
record_terminal_session(get_current_session_name(), overwrite=False)
|
|
704
693
|
# Track the current agent task for cancellation on quit
|
|
705
694
|
current_agent_task = None
|
|
706
695
|
|
|
@@ -856,7 +845,7 @@ async def interactive_mode(message_renderer, initial_command: str = None) -> Non
|
|
|
856
845
|
interactive_autosave_picker,
|
|
857
846
|
)
|
|
858
847
|
from code_puppy.config import (
|
|
859
|
-
|
|
848
|
+
pin_current_session_name,
|
|
860
849
|
)
|
|
861
850
|
from code_puppy.messaging import (
|
|
862
851
|
emit_error,
|
|
@@ -882,7 +871,7 @@ async def interactive_mode(message_renderer, initial_command: str = None) -> Non
|
|
|
882
871
|
agent.set_message_history(history)
|
|
883
872
|
|
|
884
873
|
# Set current autosave session
|
|
885
|
-
|
|
874
|
+
pin_current_session_name(chosen_session)
|
|
886
875
|
|
|
887
876
|
total_tokens = sum(
|
|
888
877
|
agent.estimate_tokens_for_message(msg)
|
|
@@ -1196,8 +1185,28 @@ async def run_prompt_with_attachments(
|
|
|
1196
1185
|
return None, agent_task
|
|
1197
1186
|
|
|
1198
1187
|
|
|
1199
|
-
async def execute_single_prompt(
|
|
1200
|
-
|
|
1188
|
+
async def execute_single_prompt(
|
|
1189
|
+
prompt: str,
|
|
1190
|
+
message_renderer,
|
|
1191
|
+
*,
|
|
1192
|
+
session_name: str | None = None,
|
|
1193
|
+
) -> None:
|
|
1194
|
+
"""Execute a single prompt and exit (for -p flag).
|
|
1195
|
+
|
|
1196
|
+
When ``session_name`` is supplied (i.e. the user passed ``-r NAME``),
|
|
1197
|
+
history is persisted back to that named session in a ``finally`` block
|
|
1198
|
+
so partial state still lands on cancel / error paths. The runtime
|
|
1199
|
+
prunes interrupted tool calls before returning so the saved history is
|
|
1200
|
+
coherent (see ``agents/_runtime.py`` -- the two ``_message_history``
|
|
1201
|
+
commit/prune sites around lines 446 and 498).
|
|
1202
|
+
|
|
1203
|
+
Edge case worth knowing: when the agent returns ``(None, None)`` for an
|
|
1204
|
+
empty-prompt scenario, the response emit is skipped but the ``finally``
|
|
1205
|
+
still fires, producing a no-op idempotent rewrite of an existing
|
|
1206
|
+
session (and a phantom ``post_autosave`` event for plugin authors who
|
|
1207
|
+
count saves). Acceptable trade-off versus the complexity of a
|
|
1208
|
+
'something-actually-ran' tracking flag.
|
|
1209
|
+
"""
|
|
1201
1210
|
# Shell pass-through: !<cmd> bypasses the agent even in -p mode
|
|
1202
1211
|
from code_puppy.command_line.shell_passthrough import (
|
|
1203
1212
|
execute_shell_passthrough,
|
|
@@ -1206,9 +1215,26 @@ async def execute_single_prompt(prompt: str, message_renderer) -> None:
|
|
|
1206
1215
|
|
|
1207
1216
|
if is_shell_passthrough(prompt):
|
|
1208
1217
|
execute_shell_passthrough(prompt)
|
|
1218
|
+
# Agent never ran — do NOT touch the named session, otherwise
|
|
1219
|
+
# `-r mywork -p '!ls'` would clobber existing history with an empty
|
|
1220
|
+
# save-back. Return before the try/finally so the save path is
|
|
1221
|
+
# genuinely unreachable, not just guarded.
|
|
1209
1222
|
return
|
|
1210
1223
|
|
|
1211
|
-
from code_puppy.messaging import
|
|
1224
|
+
from code_puppy.messaging import (
|
|
1225
|
+
emit_error,
|
|
1226
|
+
emit_info,
|
|
1227
|
+
emit_warning,
|
|
1228
|
+
get_message_bus,
|
|
1229
|
+
)
|
|
1230
|
+
from code_puppy.messaging.messages import AgentResponseMessage
|
|
1231
|
+
|
|
1232
|
+
# Hoist save-back imports here rather than into the ``finally`` block --
|
|
1233
|
+
# if the user passed ``-r`` we will exercise these on every code path,
|
|
1234
|
+
# and lazy-importing inside ``finally`` just hides the dependency without
|
|
1235
|
+
# buying any actual startup savings (the module is already loaded).
|
|
1236
|
+
from code_puppy.config import AUTOSAVE_DIR
|
|
1237
|
+
from code_puppy.session_lifecycle import persist_named_session
|
|
1212
1238
|
|
|
1213
1239
|
emit_info(f"Executing prompt: {prompt}")
|
|
1214
1240
|
|
|
@@ -1220,29 +1246,47 @@ async def execute_single_prompt(prompt: str, message_renderer) -> None:
|
|
|
1220
1246
|
prompt,
|
|
1221
1247
|
spinner_console=message_renderer.console,
|
|
1222
1248
|
)
|
|
1223
|
-
if result is None:
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1249
|
+
if result is not None:
|
|
1250
|
+
response_msg = AgentResponseMessage(
|
|
1251
|
+
content=result.output,
|
|
1252
|
+
is_markdown=True,
|
|
1253
|
+
)
|
|
1254
|
+
get_message_bus().emit(response_msg)
|
|
1255
|
+
|
|
1256
|
+
# Commit the completed turn (user prompt + assistant response)
|
|
1257
|
+
# into the agent's history BEFORE the finally-block save-back.
|
|
1258
|
+
# Without this, headless -r save-back persists only user prompts
|
|
1259
|
+
# (the normal _do_run path never writes result.all_messages()
|
|
1260
|
+
# back to agent._message_history), so resumed sessions feed the
|
|
1261
|
+
# model a pile of unanswered prompts and it re-answers them all.
|
|
1262
|
+
# Mirrors interactive_mode's post-run set_message_history call.
|
|
1263
|
+
if hasattr(result, "all_messages"):
|
|
1264
|
+
agent.set_message_history(list(result.all_messages()))
|
|
1237
1265
|
|
|
1238
1266
|
except asyncio.CancelledError:
|
|
1239
|
-
from code_puppy.messaging import emit_warning
|
|
1240
|
-
|
|
1241
1267
|
emit_warning("Execution cancelled by user")
|
|
1242
1268
|
except Exception as e:
|
|
1243
|
-
from code_puppy.messaging import emit_error
|
|
1244
|
-
|
|
1245
1269
|
emit_error(f"Error executing prompt: {str(e)}")
|
|
1270
|
+
finally:
|
|
1271
|
+
if session_name:
|
|
1272
|
+
try:
|
|
1273
|
+
persist_named_session(
|
|
1274
|
+
get_current_agent(),
|
|
1275
|
+
session_name,
|
|
1276
|
+
base_dir=Path(AUTOSAVE_DIR),
|
|
1277
|
+
# Headless -r save-back is automated (user passed a
|
|
1278
|
+
# flag and walked away) rather than an explicit
|
|
1279
|
+
# /dump_context-style intent, so it carries the same
|
|
1280
|
+
# auto_saved=True bit as autosave proper. Plugins
|
|
1281
|
+
# that filter on `metadata.auto_saved` get the right
|
|
1282
|
+
# signal.
|
|
1283
|
+
auto_saved=True,
|
|
1284
|
+
)
|
|
1285
|
+
except Exception as save_exc:
|
|
1286
|
+
# The user's primary deliverable (the agent response) has
|
|
1287
|
+
# already been emitted. Report the save failure but do not
|
|
1288
|
+
# re-raise -- a save bug shouldn't mask a successful turn.
|
|
1289
|
+
emit_error(f"Failed to save session {session_name}: {save_exc}")
|
|
1246
1290
|
|
|
1247
1291
|
|
|
1248
1292
|
def _force_utf8_stdio():
|
|
@@ -48,8 +48,26 @@ def _get_session_metadata(base_dir: Path, session_name: str) -> dict:
|
|
|
48
48
|
return {}
|
|
49
49
|
|
|
50
50
|
|
|
51
|
+
def _is_auto_flavored(session_name: str) -> bool:
|
|
52
|
+
"""Return True for system-generated session names.
|
|
53
|
+
|
|
54
|
+
Matches the ``auto_session_`` prefix reserved by
|
|
55
|
+
``code_puppy.session_lifecycle.is_valid_session_name``. Pre-unification,
|
|
56
|
+
all autosaves carried this prefix; the unified-autosave migration introduces user-named
|
|
57
|
+
entries (from ``-r NAME``, ``/dump_context``, ``/load_context``) into
|
|
58
|
+
the same store, hence the need to distinguish.
|
|
59
|
+
"""
|
|
60
|
+
return session_name.startswith("auto_session_")
|
|
61
|
+
|
|
62
|
+
|
|
51
63
|
def _get_session_entries(base_dir: Path) -> List[Tuple[str, dict]]:
|
|
52
|
-
"""Get all sessions with their metadata
|
|
64
|
+
"""Get all sessions with their metadata.
|
|
65
|
+
|
|
66
|
+
Returns entries grouped "named first, auto-flavored second", each group
|
|
67
|
+
sorted mtime-descending. Section headers (if any) are inserted at
|
|
68
|
+
render time -- see ``_render_menu_panel`` -- to keep this function's
|
|
69
|
+
return shape stable and pagination math straightforward.
|
|
70
|
+
"""
|
|
53
71
|
try:
|
|
54
72
|
sessions = list_sessions(base_dir)
|
|
55
73
|
except (FileNotFoundError, PermissionError):
|
|
@@ -75,8 +93,11 @@ def _get_session_entries(base_dir: Path) -> List[Tuple[str, dict]]:
|
|
|
75
93
|
return datetime.min
|
|
76
94
|
return datetime.min
|
|
77
95
|
|
|
78
|
-
entries
|
|
79
|
-
|
|
96
|
+
named = [e for e in entries if not _is_auto_flavored(e[0])]
|
|
97
|
+
auto = [e for e in entries if _is_auto_flavored(e[0])]
|
|
98
|
+
named.sort(key=sort_key, reverse=True)
|
|
99
|
+
auto.sort(key=sort_key, reverse=True)
|
|
100
|
+
return named + auto
|
|
80
101
|
|
|
81
102
|
|
|
82
103
|
def _extract_last_user_message(history: list) -> str:
|
|
@@ -216,10 +237,24 @@ def _render_menu_panel(
|
|
|
216
237
|
lines.append(("", "Cancel"))
|
|
217
238
|
return lines
|
|
218
239
|
|
|
219
|
-
# Show sessions for current page
|
|
240
|
+
# Show sessions for current page. We inject visual section headers
|
|
241
|
+
# at named->auto boundaries within the visible page (and at the very
|
|
242
|
+
# top if the page starts in either section). Section headers do NOT
|
|
243
|
+
# consume entry indices -- they're cosmetic only -- so selection and
|
|
244
|
+
# pagination math stay untouched.
|
|
245
|
+
prev_section = None
|
|
220
246
|
for i in range(start_idx, end_idx):
|
|
221
247
|
session_name, metadata = entries[i]
|
|
222
248
|
is_selected = i == selected_idx
|
|
249
|
+
section = "auto" if _is_auto_flavored(session_name) else "named"
|
|
250
|
+
|
|
251
|
+
if section != prev_section:
|
|
252
|
+
header = "Named sessions" if section == "named" else "Auto-saved sessions"
|
|
253
|
+
# Blank line between sections (skip for the very first one).
|
|
254
|
+
if prev_section is not None:
|
|
255
|
+
lines.append(("", "\n"))
|
|
256
|
+
lines.append(("fg:ansibrightcyan bold", f" {header}\n"))
|
|
257
|
+
prev_section = section
|
|
223
258
|
|
|
224
259
|
# Format timestamp
|
|
225
260
|
timestamp = metadata.get("timestamp", "unknown")
|
|
@@ -232,11 +267,19 @@ def _render_menu_panel(
|
|
|
232
267
|
# Format message count
|
|
233
268
|
msg_count = metadata.get("message_count", "?")
|
|
234
269
|
|
|
270
|
+
# For named sessions, include the name so users can tell them
|
|
271
|
+
# apart at a glance. Auto-flavored sessions keep the existing
|
|
272
|
+
# timestamp+count summary -- the auto_session_* names are noise.
|
|
273
|
+
if section == "named":
|
|
274
|
+
label = f"{time_str} \u2022 {msg_count} msgs ({session_name})"
|
|
275
|
+
else:
|
|
276
|
+
label = f"{time_str} \u2022 {msg_count} msgs"
|
|
277
|
+
|
|
235
278
|
# Highlight selected item
|
|
236
279
|
if is_selected:
|
|
237
|
-
lines.append(("fg:ansibrightblack", f" > {
|
|
280
|
+
lines.append(("fg:ansibrightblack", f" > {label}"))
|
|
238
281
|
else:
|
|
239
|
-
lines.append(("fg:ansibrightblack", f" {
|
|
282
|
+
lines.append(("fg:ansibrightblack", f" {label}"))
|
|
240
283
|
|
|
241
284
|
lines.append(("", "\n"))
|
|
242
285
|
|
|
@@ -4,13 +4,12 @@ This module contains @register_command decorated handlers that are automatically
|
|
|
4
4
|
discovered by the command registry system.
|
|
5
5
|
"""
|
|
6
6
|
|
|
7
|
-
from datetime import datetime
|
|
8
7
|
import logging
|
|
9
8
|
from pathlib import Path
|
|
10
9
|
|
|
11
10
|
from code_puppy.command_line.command_registry import register_command
|
|
12
|
-
from code_puppy.config import
|
|
13
|
-
from code_puppy.session_storage import list_sessions, load_session
|
|
11
|
+
from code_puppy.config import AUTOSAVE_DIR
|
|
12
|
+
from code_puppy.session_storage import list_sessions, load_session
|
|
14
13
|
|
|
15
14
|
logger = logging.getLogger(__name__)
|
|
16
15
|
|
|
@@ -64,25 +63,23 @@ def get_commands_help():
|
|
|
64
63
|
def handle_session_command(command: str) -> bool:
|
|
65
64
|
"""Handle /session command."""
|
|
66
65
|
from code_puppy.config import (
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
get_current_autosave_session_name,
|
|
70
|
-
rotate_autosave_id,
|
|
66
|
+
get_current_session_name,
|
|
67
|
+
rotate_session_name,
|
|
71
68
|
)
|
|
72
69
|
from code_puppy.messaging import emit_info, emit_success, emit_warning
|
|
73
70
|
|
|
74
71
|
tokens = command.split()
|
|
75
72
|
|
|
76
73
|
if len(tokens) == 1 or tokens[1] == "id":
|
|
77
|
-
|
|
74
|
+
session_name = get_current_session_name()
|
|
78
75
|
emit_info(
|
|
79
|
-
f"[bold magenta]Autosave Session[/bold magenta]: {
|
|
80
|
-
f"Files prefix: {Path(AUTOSAVE_DIR) /
|
|
76
|
+
f"[bold magenta]Autosave Session[/bold magenta]: {session_name}\n"
|
|
77
|
+
f"Files prefix: {Path(AUTOSAVE_DIR) / session_name}"
|
|
81
78
|
)
|
|
82
79
|
return True
|
|
83
80
|
if tokens[1] == "new":
|
|
84
|
-
|
|
85
|
-
emit_success(f"New autosave session
|
|
81
|
+
new_name = rotate_session_name()
|
|
82
|
+
emit_success(f"New autosave session: {new_name}")
|
|
86
83
|
return True
|
|
87
84
|
emit_warning("Usage: /session [id|new]")
|
|
88
85
|
return True
|
|
@@ -350,7 +347,11 @@ def handle_quick_resume_command(command: str) -> bool:
|
|
|
350
347
|
def handle_dump_context_command(command: str) -> bool:
|
|
351
348
|
"""Dump message history to a file."""
|
|
352
349
|
from code_puppy.agents.agent_manager import get_current_agent
|
|
353
|
-
from code_puppy.messaging import emit_error,
|
|
350
|
+
from code_puppy.messaging import emit_error, emit_warning
|
|
351
|
+
from code_puppy.session_lifecycle import (
|
|
352
|
+
is_valid_session_name,
|
|
353
|
+
persist_named_session,
|
|
354
|
+
)
|
|
354
355
|
|
|
355
356
|
tokens = command.split()
|
|
356
357
|
if len(tokens) != 2:
|
|
@@ -358,24 +359,38 @@ def handle_dump_context_command(command: str) -> bool:
|
|
|
358
359
|
return True
|
|
359
360
|
|
|
360
361
|
session_name = tokens[1]
|
|
361
|
-
|
|
362
|
-
|
|
362
|
+
# Enforce reserved-prefix + slug rules at every user-input write site
|
|
363
|
+
# (the resolver enforces them for ``-r NAME``; this is the parallel
|
|
364
|
+
# gate for ``/dump_context``). Without it, /dump_context bypasses
|
|
365
|
+
# the validator that ``-r`` runs and lets a user squat the
|
|
366
|
+
# ``auto_session_`` namespace or smuggle in a path-traversal name.
|
|
367
|
+
if not is_valid_session_name(session_name, allow_reserved_prefix=False):
|
|
368
|
+
emit_error(
|
|
369
|
+
f"Invalid session name: {session_name!r}. "
|
|
370
|
+
"Session names must be 1-128 chars of [A-Za-z0-9._-] "
|
|
371
|
+
"and may not start with 'auto_session_' (reserved)."
|
|
372
|
+
)
|
|
373
|
+
return True
|
|
363
374
|
|
|
364
|
-
|
|
375
|
+
agent = get_current_agent()
|
|
376
|
+
if not agent.get_message_history():
|
|
365
377
|
emit_warning("No message history to dump!")
|
|
366
378
|
return True
|
|
367
379
|
|
|
368
380
|
try:
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
381
|
+
# The user-facing success line is preserved verbatim via
|
|
382
|
+
# ``success_message_template`` so /dump_context UX doesn't
|
|
383
|
+
# regress. The silent save-back paths (``-r``, periodic
|
|
384
|
+
# autosave) omit the template and stay quiet.
|
|
385
|
+
persist_named_session(
|
|
386
|
+
agent,
|
|
387
|
+
session_name,
|
|
388
|
+
base_dir=Path(AUTOSAVE_DIR),
|
|
389
|
+
success_message_template=(
|
|
390
|
+
"\u2705 Context saved: {message_count} messages "
|
|
391
|
+
"({total_tokens} tokens)\n"
|
|
392
|
+
"\U0001f4c1 Files: {pickle_path}, {metadata_path}"
|
|
393
|
+
),
|
|
379
394
|
)
|
|
380
395
|
return True
|
|
381
396
|
|
|
@@ -392,10 +407,8 @@ def handle_dump_context_command(command: str) -> bool:
|
|
|
392
407
|
)
|
|
393
408
|
def handle_load_context_command(command: str) -> bool:
|
|
394
409
|
"""Load message history from a file."""
|
|
395
|
-
from rich.text import Text
|
|
396
|
-
|
|
397
410
|
from code_puppy.agents.agent_manager import get_current_agent
|
|
398
|
-
from code_puppy.config import
|
|
411
|
+
from code_puppy.config import rotate_session_name
|
|
399
412
|
from code_puppy.messaging import emit_error, emit_info, emit_success, emit_warning
|
|
400
413
|
|
|
401
414
|
tokens = command.split()
|
|
@@ -404,14 +417,14 @@ def handle_load_context_command(command: str) -> bool:
|
|
|
404
417
|
return True
|
|
405
418
|
|
|
406
419
|
session_name = tokens[1]
|
|
407
|
-
|
|
408
|
-
session_path =
|
|
420
|
+
sessions_dir = Path(AUTOSAVE_DIR)
|
|
421
|
+
session_path = sessions_dir / f"{session_name}.pkl"
|
|
409
422
|
|
|
410
423
|
try:
|
|
411
|
-
history = load_session(session_name,
|
|
424
|
+
history = load_session(session_name, sessions_dir)
|
|
412
425
|
except FileNotFoundError:
|
|
413
426
|
emit_error(f"Context file not found: {session_path}")
|
|
414
|
-
available = list_sessions(
|
|
427
|
+
available = list_sessions(sessions_dir)
|
|
415
428
|
if available:
|
|
416
429
|
emit_info(f"Available contexts: {', '.join(available)}")
|
|
417
430
|
return True
|
|
@@ -423,22 +436,41 @@ def handle_load_context_command(command: str) -> bool:
|
|
|
423
436
|
agent.set_message_history(history)
|
|
424
437
|
total_tokens = sum(agent.estimate_tokens_for_message(m) for m in history)
|
|
425
438
|
|
|
426
|
-
# Rotate
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
439
|
+
# Rotate the singleton to a fresh ``auto_session_<TS>`` so subsequent
|
|
440
|
+
# autosaves do NOT overwrite the loaded snapshot. This asymmetry with
|
|
441
|
+
# ``-r NAME`` (which pins and saves back in place) is INTENTIONAL --
|
|
442
|
+
# the two verbs encode two different intents:
|
|
443
|
+
#
|
|
444
|
+
# * ``/dump_context NAME`` + ``/load_context NAME`` are a snapshot
|
|
445
|
+
# pair (think ``pg_dump`` / ``pg_restore``, save games, git
|
|
446
|
+
# stash). The named file is a stable reference point; loading
|
|
447
|
+
# it lets you inspect / branch from it without dirtying the
|
|
448
|
+
# original.
|
|
449
|
+
# * ``-r NAME`` / ``--resume NAME`` is a continuation verb (pick
|
|
450
|
+
# up where you left off). That path pins and saves back.
|
|
451
|
+
#
|
|
452
|
+
# Origin: commit ``cc04629b`` (Mike Pfaffenberger, 2025-10-11)
|
|
453
|
+
# introduced this rotate-on-load behavior as a deliberate design
|
|
454
|
+
# choice; the commit message explicitly says "Automatically rotate
|
|
455
|
+
# session ID when loading saved context to prevent overwrites." The
|
|
456
|
+
# ``-r`` flag was added 4 months later (commit ``92bb0f90``) and
|
|
457
|
+
# the asymmetry was preserved -- on purpose. Do NOT "unify" these
|
|
458
|
+
# two paths in the name of symmetry; you'd be deleting the encoded
|
|
459
|
+
# distinction between snapshot-load and continuation-resume.
|
|
460
|
+
#
|
|
461
|
+
# If a user wants to continue working on the loaded snapshot in
|
|
462
|
+
# place, the explicit move is ``/load_context NAME`` followed by
|
|
463
|
+
# ``/dump_context NAME`` later -- or relaunch via ``-r NAME``.
|
|
464
|
+
new_autosave_id = rotate_session_name()
|
|
434
465
|
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
f"
|
|
438
|
-
f"
|
|
466
|
+
emit_success(
|
|
467
|
+
f"\u2705 Context loaded: {len(history)} messages "
|
|
468
|
+
f"({total_tokens} tokens)\n"
|
|
469
|
+
f"\U0001f4c1 From: {session_path}\n"
|
|
470
|
+
f"\U0001f504 Autosave rotated to: {new_autosave_id} "
|
|
471
|
+
f"(snapshot at {session_path.name} is preserved; further "
|
|
472
|
+
f"autosaves land in the new session)"
|
|
439
473
|
)
|
|
440
|
-
success_msg.append_text(autosave_info)
|
|
441
|
-
emit_success(success_msg)
|
|
442
474
|
|
|
443
475
|
# Display recent message history for context
|
|
444
476
|
from code_puppy.command_line.autosave_menu import display_resumed_history
|