spruce-grove 1.0.1__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.
- spruce_grove-1.0.1/.gitignore +70 -0
- spruce_grove-1.0.1/LICENSE +21 -0
- spruce_grove-1.0.1/PKG-INFO +194 -0
- spruce_grove-1.0.1/README.md +139 -0
- spruce_grove-1.0.1/pyproject.toml +121 -0
- spruce_grove-1.0.1/spruce_grove/__init__.py +42 -0
- spruce_grove-1.0.1/spruce_grove/__main__.py +10 -0
- spruce_grove-1.0.1/spruce_grove/_code_puppy_compat.py +103 -0
- spruce_grove-1.0.1/spruce_grove/_pydantic_tool_helpers.py +103 -0
- spruce_grove-1.0.1/spruce_grove/agent_execution_context.py +40 -0
- spruce_grove-1.0.1/spruce_grove/agents/__init__.py +34 -0
- spruce_grove-1.0.1/spruce_grove/agents/_builder.py +796 -0
- spruce_grove-1.0.1/spruce_grove/agents/_compaction.py +403 -0
- spruce_grove-1.0.1/spruce_grove/agents/_diagnostics.py +173 -0
- spruce_grove-1.0.1/spruce_grove/agents/_history.py +650 -0
- spruce_grove-1.0.1/spruce_grove/agents/_key_listeners.py +1013 -0
- spruce_grove-1.0.1/spruce_grove/agents/_model_message_transform.py +28 -0
- spruce_grove-1.0.1/spruce_grove/agents/_non_streaming_render.py +149 -0
- spruce_grove-1.0.1/spruce_grove/agents/_output_limits.py +78 -0
- spruce_grove-1.0.1/spruce_grove/agents/_run_signals.py +310 -0
- spruce_grove-1.0.1/spruce_grove/agents/_runtime.py +1224 -0
- spruce_grove-1.0.1/spruce_grove/agents/_steer_processor.py +94 -0
- spruce_grove-1.0.1/spruce_grove/agents/_subagent_recursion.py +114 -0
- spruce_grove-1.0.1/spruce_grove/agents/agent_code_puppy.py +14 -0
- spruce_grove-1.0.1/spruce_grove/agents/agent_creator_agent.py +711 -0
- spruce_grove-1.0.1/spruce_grove/agents/agent_helios.py +123 -0
- spruce_grove-1.0.1/spruce_grove/agents/agent_manager.py +847 -0
- spruce_grove-1.0.1/spruce_grove/agents/agent_model_judge.py +197 -0
- spruce_grove-1.0.1/spruce_grove/agents/agent_planning.py +163 -0
- spruce_grove-1.0.1/spruce_grove/agents/agent_qa_kitten.py +248 -0
- spruce_grove-1.0.1/spruce_grove/agents/agent_spruce_grove.py +163 -0
- spruce_grove-1.0.1/spruce_grove/agents/agent_web_retriever.py +258 -0
- spruce_grove-1.0.1/spruce_grove/agents/base_agent.py +371 -0
- spruce_grove-1.0.1/spruce_grove/agents/event_stream_handler.py +572 -0
- spruce_grove-1.0.1/spruce_grove/agents/json_agent.py +398 -0
- spruce_grove-1.0.1/spruce_grove/agents/retry_checkpoint.py +62 -0
- spruce_grove-1.0.1/spruce_grove/agents/retry_profiles.py +281 -0
- spruce_grove-1.0.1/spruce_grove/agents/run_stats.py +684 -0
- spruce_grove-1.0.1/spruce_grove/agents/smooth_stream.py +130 -0
- spruce_grove-1.0.1/spruce_grove/agents/subagent_stream_handler.py +277 -0
- spruce_grove-1.0.1/spruce_grove/asyncio_cleanup.py +71 -0
- spruce_grove-1.0.1/spruce_grove/atomic_io.py +269 -0
- spruce_grove-1.0.1/spruce_grove/atomic_json.py +129 -0
- spruce_grove-1.0.1/spruce_grove/callbacks.py +1740 -0
- spruce_grove-1.0.1/spruce_grove/chatgpt_codex_client.py +437 -0
- spruce_grove-1.0.1/spruce_grove/claude_cache_client.py +498 -0
- spruce_grove-1.0.1/spruce_grove/claude_oauth_transport.py +285 -0
- spruce_grove-1.0.1/spruce_grove/cli_runner.py +1627 -0
- spruce_grove-1.0.1/spruce_grove/command_line/__init__.py +1 -0
- spruce_grove-1.0.1/spruce_grove/command_line/add_model_details.py +144 -0
- spruce_grove-1.0.1/spruce_grove/command_line/add_model_menu.py +602 -0
- spruce_grove-1.0.1/spruce_grove/command_line/agent_menu.py +471 -0
- spruce_grove-1.0.1/spruce_grove/command_line/attachments.py +491 -0
- spruce_grove-1.0.1/spruce_grove/command_line/autosave_menu.py +112 -0
- spruce_grove-1.0.1/spruce_grove/command_line/autosave_search.py +178 -0
- spruce_grove-1.0.1/spruce_grove/command_line/clipboard.py +472 -0
- spruce_grove-1.0.1/spruce_grove/command_line/colors_menu.py +102 -0
- spruce_grove-1.0.1/spruce_grove/command_line/command_handler.py +304 -0
- spruce_grove-1.0.1/spruce_grove/command_line/command_registry.py +186 -0
- spruce_grove-1.0.1/spruce_grove/command_line/completers.py +436 -0
- spruce_grove-1.0.1/spruce_grove/command_line/completion_cache.py +37 -0
- spruce_grove-1.0.1/spruce_grove/command_line/config_apply.py +154 -0
- spruce_grove-1.0.1/spruce_grove/command_line/config_commands.py +477 -0
- spruce_grove-1.0.1/spruce_grove/command_line/core_commands.py +745 -0
- spruce_grove-1.0.1/spruce_grove/command_line/file_index.py +157 -0
- spruce_grove-1.0.1/spruce_grove/command_line/file_path_completion.py +184 -0
- spruce_grove-1.0.1/spruce_grove/command_line/help_catalog.py +266 -0
- spruce_grove-1.0.1/spruce_grove/command_line/help_overlay.py +100 -0
- spruce_grove-1.0.1/spruce_grove/command_line/image_utils.py +198 -0
- spruce_grove-1.0.1/spruce_grove/command_line/load_context_completion.py +52 -0
- spruce_grove-1.0.1/spruce_grove/command_line/mcp/__init__.py +10 -0
- spruce_grove-1.0.1/spruce_grove/command_line/mcp/base.py +32 -0
- spruce_grove-1.0.1/spruce_grove/command_line/mcp/catalog_server_installer.py +175 -0
- spruce_grove-1.0.1/spruce_grove/command_line/mcp/custom_server_form.py +544 -0
- spruce_grove-1.0.1/spruce_grove/command_line/mcp/custom_server_installer.py +192 -0
- spruce_grove-1.0.1/spruce_grove/command_line/mcp/edit_command.py +148 -0
- spruce_grove-1.0.1/spruce_grove/command_line/mcp/handler.py +141 -0
- spruce_grove-1.0.1/spruce_grove/command_line/mcp/help_command.py +153 -0
- spruce_grove-1.0.1/spruce_grove/command_line/mcp/install_command.py +214 -0
- spruce_grove-1.0.1/spruce_grove/command_line/mcp/install_menu.py +320 -0
- spruce_grove-1.0.1/spruce_grove/command_line/mcp/list_command.py +94 -0
- spruce_grove-1.0.1/spruce_grove/command_line/mcp/logs_command.py +235 -0
- spruce_grove-1.0.1/spruce_grove/command_line/mcp/mcp_servers_store.py +74 -0
- spruce_grove-1.0.1/spruce_grove/command_line/mcp/remove_command.py +86 -0
- spruce_grove-1.0.1/spruce_grove/command_line/mcp/restart_command.py +100 -0
- spruce_grove-1.0.1/spruce_grove/command_line/mcp/search_command.py +123 -0
- spruce_grove-1.0.1/spruce_grove/command_line/mcp/silence_warning_command.py +91 -0
- spruce_grove-1.0.1/spruce_grove/command_line/mcp/start_all_command.py +135 -0
- spruce_grove-1.0.1/spruce_grove/command_line/mcp/start_command.py +151 -0
- spruce_grove-1.0.1/spruce_grove/command_line/mcp/status_command.py +184 -0
- spruce_grove-1.0.1/spruce_grove/command_line/mcp/stop_all_command.py +112 -0
- spruce_grove-1.0.1/spruce_grove/command_line/mcp/stop_command.py +80 -0
- spruce_grove-1.0.1/spruce_grove/command_line/mcp/trust_command.py +216 -0
- spruce_grove-1.0.1/spruce_grove/command_line/mcp/utils.py +129 -0
- spruce_grove-1.0.1/spruce_grove/command_line/mcp/wizard_utils.py +328 -0
- spruce_grove-1.0.1/spruce_grove/command_line/mcp_binding_menu.py +249 -0
- spruce_grove-1.0.1/spruce_grove/command_line/mcp_completion.py +173 -0
- spruce_grove-1.0.1/spruce_grove/command_line/menu_session.py +72 -0
- spruce_grove-1.0.1/spruce_grove/command_line/model_picker_completion.py +411 -0
- spruce_grove-1.0.1/spruce_grove/command_line/model_settings_defs.py +420 -0
- spruce_grove-1.0.1/spruce_grove/command_line/model_settings_menu.py +497 -0
- spruce_grove-1.0.1/spruce_grove/command_line/onboarding_slides.py +192 -0
- spruce_grove-1.0.1/spruce_grove/command_line/onboarding_wizard.py +413 -0
- spruce_grove-1.0.1/spruce_grove/command_line/pagination.py +43 -0
- spruce_grove-1.0.1/spruce_grove/command_line/pin_command_completion.py +361 -0
- spruce_grove-1.0.1/spruce_grove/command_line/refresh_models.py +140 -0
- spruce_grove-1.0.1/spruce_grove/command_line/session_browser.py +604 -0
- spruce_grove-1.0.1/spruce_grove/command_line/session_browser_data.py +418 -0
- spruce_grove-1.0.1/spruce_grove/command_line/session_commands.py +513 -0
- spruce_grove-1.0.1/spruce_grove/command_line/set_menu.py +440 -0
- spruce_grove-1.0.1/spruce_grove/command_line/set_menu_catalog.py +662 -0
- spruce_grove-1.0.1/spruce_grove/command_line/set_menu_schema.py +33 -0
- spruce_grove-1.0.1/spruce_grove/command_line/set_menu_settings.py +26 -0
- spruce_grove-1.0.1/spruce_grove/command_line/set_menu_shims.py +46 -0
- spruce_grove-1.0.1/spruce_grove/command_line/set_menu_values.py +126 -0
- spruce_grove-1.0.1/spruce_grove/command_line/shell_passthrough.py +150 -0
- spruce_grove-1.0.1/spruce_grove/command_line/skills_completion.py +160 -0
- spruce_grove-1.0.1/spruce_grove/command_line/tui_style.py +44 -0
- spruce_grove-1.0.1/spruce_grove/command_line/uc_menu.py +376 -0
- spruce_grove-1.0.1/spruce_grove/command_line/utils.py +104 -0
- spruce_grove-1.0.1/spruce_grove/config.py +3251 -0
- spruce_grove-1.0.1/spruce_grove/config_file.py +158 -0
- spruce_grove-1.0.1/spruce_grove/diagnostics.py +124 -0
- spruce_grove-1.0.1/spruce_grove/error_logging.py +134 -0
- spruce_grove-1.0.1/spruce_grove/file_completion_io.py +59 -0
- spruce_grove-1.0.1/spruce_grove/file_completion_tokens.py +42 -0
- spruce_grove-1.0.1/spruce_grove/gemini_code_assist.py +396 -0
- spruce_grove-1.0.1/spruce_grove/gemini_model.py +968 -0
- spruce_grove-1.0.1/spruce_grove/hook_engine/README.md +105 -0
- spruce_grove-1.0.1/spruce_grove/hook_engine/__init__.py +21 -0
- spruce_grove-1.0.1/spruce_grove/hook_engine/aliases.py +156 -0
- spruce_grove-1.0.1/spruce_grove/hook_engine/engine.py +221 -0
- spruce_grove-1.0.1/spruce_grove/hook_engine/executor.py +544 -0
- spruce_grove-1.0.1/spruce_grove/hook_engine/matcher.py +156 -0
- spruce_grove-1.0.1/spruce_grove/hook_engine/models.py +240 -0
- spruce_grove-1.0.1/spruce_grove/hook_engine/registry.py +106 -0
- spruce_grove-1.0.1/spruce_grove/hook_engine/validator.py +144 -0
- spruce_grove-1.0.1/spruce_grove/http_retry.py +138 -0
- spruce_grove-1.0.1/spruce_grove/http_utils.py +277 -0
- spruce_grove-1.0.1/spruce_grove/httpx2_utils.py +67 -0
- spruce_grove-1.0.1/spruce_grove/i18n/__init__.py +79 -0
- spruce_grove-1.0.1/spruce_grove/i18n/audit.py +336 -0
- spruce_grove-1.0.1/spruce_grove/i18n/catalog.py +213 -0
- spruce_grove-1.0.1/spruce_grove/i18n/formats.py +90 -0
- spruce_grove-1.0.1/spruce_grove/i18n/locale.py +147 -0
- spruce_grove-1.0.1/spruce_grove/i18n/locales/en-US.json +390 -0
- spruce_grove-1.0.1/spruce_grove/i18n/locales/es.json +257 -0
- spruce_grove-1.0.1/spruce_grove/i18n/locales/fr-CA.json +257 -0
- spruce_grove-1.0.1/spruce_grove/i18n/plurals.py +71 -0
- spruce_grove-1.0.1/spruce_grove/i18n/pseudo.py +108 -0
- spruce_grove-1.0.1/spruce_grove/i18n/translate.py +199 -0
- spruce_grove-1.0.1/spruce_grove/kennel_provider.py +39 -0
- spruce_grove-1.0.1/spruce_grove/keymap.py +154 -0
- spruce_grove-1.0.1/spruce_grove/list_filtering.py +26 -0
- spruce_grove-1.0.1/spruce_grove/main.py +23 -0
- spruce_grove-1.0.1/spruce_grove/mcp_/__init__.py +66 -0
- spruce_grove-1.0.1/spruce_grove/mcp_/agent_bindings.py +289 -0
- spruce_grove-1.0.1/spruce_grove/mcp_/async_lifecycle.py +306 -0
- spruce_grove-1.0.1/spruce_grove/mcp_/blocking_startup.py +381 -0
- spruce_grove-1.0.1/spruce_grove/mcp_/circuit_breaker.py +287 -0
- spruce_grove-1.0.1/spruce_grove/mcp_/config_wizard.py +536 -0
- spruce_grove-1.0.1/spruce_grove/mcp_/dashboard.py +308 -0
- spruce_grove-1.0.1/spruce_grove/mcp_/error_isolation.py +407 -0
- spruce_grove-1.0.1/spruce_grove/mcp_/examples/retry_example.py +226 -0
- spruce_grove-1.0.1/spruce_grove/mcp_/health_monitor.py +582 -0
- spruce_grove-1.0.1/spruce_grove/mcp_/managed_server.py +541 -0
- spruce_grove-1.0.1/spruce_grove/mcp_/manager.py +976 -0
- spruce_grove-1.0.1/spruce_grove/mcp_/mcp_logs.py +224 -0
- spruce_grove-1.0.1/spruce_grove/mcp_/project_config.py +288 -0
- spruce_grove-1.0.1/spruce_grove/mcp_/registry.py +451 -0
- spruce_grove-1.0.1/spruce_grove/mcp_/retry_manager.py +337 -0
- spruce_grove-1.0.1/spruce_grove/mcp_/server_registry_catalog.py +1122 -0
- spruce_grove-1.0.1/spruce_grove/mcp_/status_tracker.py +355 -0
- spruce_grove-1.0.1/spruce_grove/mcp_/system_tools.py +209 -0
- spruce_grove-1.0.1/spruce_grove/mcp_/tool_arg_coercion.py +180 -0
- spruce_grove-1.0.1/spruce_grove/mcp_/toolset_utils.py +77 -0
- spruce_grove-1.0.1/spruce_grove/mcp_prompts/__init__.py +1 -0
- spruce_grove-1.0.1/spruce_grove/mcp_prompts/hook_creator.py +103 -0
- spruce_grove-1.0.1/spruce_grove/messaging/__init__.py +299 -0
- spruce_grove-1.0.1/spruce_grove/messaging/bar_painters.py +352 -0
- spruce_grove-1.0.1/spruce_grove/messaging/bar_rendering.py +326 -0
- spruce_grove-1.0.1/spruce_grove/messaging/bottom_bar.py +803 -0
- spruce_grove-1.0.1/spruce_grove/messaging/bus.py +655 -0
- spruce_grove-1.0.1/spruce_grove/messaging/chords.py +151 -0
- spruce_grove-1.0.1/spruce_grove/messaging/commands.py +216 -0
- spruce_grove-1.0.1/spruce_grove/messaging/editor_actions.py +100 -0
- spruce_grove-1.0.1/spruce_grove/messaging/editor_completion.py +313 -0
- spruce_grove-1.0.1/spruce_grove/messaging/editor_display.py +132 -0
- spruce_grove-1.0.1/spruce_grove/messaging/editor_history.py +279 -0
- spruce_grove-1.0.1/spruce_grove/messaging/editor_keys.py +171 -0
- spruce_grove-1.0.1/spruce_grove/messaging/editor_paste.py +175 -0
- spruce_grove-1.0.1/spruce_grove/messaging/external_editor.py +137 -0
- spruce_grove-1.0.1/spruce_grove/messaging/inline_bar.py +386 -0
- spruce_grove-1.0.1/spruce_grove/messaging/line_editor.py +706 -0
- spruce_grove-1.0.1/spruce_grove/messaging/markdown_patches.py +88 -0
- spruce_grove-1.0.1/spruce_grove/messaging/message_queue.py +416 -0
- spruce_grove-1.0.1/spruce_grove/messaging/messages.py +581 -0
- spruce_grove-1.0.1/spruce_grove/messaging/pause_controller.py +494 -0
- spruce_grove-1.0.1/spruce_grove/messaging/prompt_prefix_style.py +103 -0
- spruce_grove-1.0.1/spruce_grove/messaging/queue_console.py +285 -0
- spruce_grove-1.0.1/spruce_grove/messaging/renderers.py +554 -0
- spruce_grove-1.0.1/spruce_grove/messaging/rich_renderer.py +1361 -0
- spruce_grove-1.0.1/spruce_grove/messaging/run_ui.py +754 -0
- spruce_grove-1.0.1/spruce_grove/messaging/run_ui_wiring.py +131 -0
- spruce_grove-1.0.1/spruce_grove/messaging/spinner/__init__.py +162 -0
- spruce_grove-1.0.1/spruce_grove/messaging/subagent_console.py +468 -0
- spruce_grove-1.0.1/spruce_grove/messaging/transcript_guard.py +466 -0
- spruce_grove-1.0.1/spruce_grove/model_descriptions.py +62 -0
- spruce_grove-1.0.1/spruce_grove/model_factory.py +1194 -0
- spruce_grove-1.0.1/spruce_grove/model_switching.py +143 -0
- spruce_grove-1.0.1/spruce_grove/model_utils.py +535 -0
- spruce_grove-1.0.1/spruce_grove/models.json +2 -0
- spruce_grove-1.0.1/spruce_grove/models_dev_api.json +1 -0
- spruce_grove-1.0.1/spruce_grove/models_dev_parser.py +461 -0
- spruce_grove-1.0.1/spruce_grove/observability.py +112 -0
- spruce_grove-1.0.1/spruce_grove/platform_utils.py +42 -0
- spruce_grove-1.0.1/spruce_grove/plugins/__init__.py +831 -0
- spruce_grove-1.0.1/spruce_grove/plugins/config.py +114 -0
- spruce_grove-1.0.1/spruce_grove/plugins/oauth_grove_html.py +194 -0
- spruce_grove-1.0.1/spruce_grove/plugins/oauth_pasteback.py +110 -0
- spruce_grove-1.0.1/spruce_grove/plugins/trust.py +146 -0
- spruce_grove-1.0.1/spruce_grove/plugins/trust_notice.py +69 -0
- spruce_grove-1.0.1/spruce_grove/private_inference.py +114 -0
- spruce_grove-1.0.1/spruce_grove/provider_credentials.py +328 -0
- spruce_grove-1.0.1/spruce_grove/provider_identity.py +110 -0
- spruce_grove-1.0.1/spruce_grove/pydantic_patches.py +650 -0
- spruce_grove-1.0.1/spruce_grove/reopenable_async_client.py +232 -0
- spruce_grove-1.0.1/spruce_grove/round_robin_model.py +155 -0
- spruce_grove-1.0.1/spruce_grove/secret_store.py +796 -0
- spruce_grove-1.0.1/spruce_grove/secret_store_backends.py +193 -0
- spruce_grove-1.0.1/spruce_grove/session_format_migration.py +302 -0
- spruce_grove-1.0.1/spruce_grove/session_lifecycle.py +317 -0
- spruce_grove-1.0.1/spruce_grove/session_migration.py +220 -0
- spruce_grove-1.0.1/spruce_grove/session_storage.py +340 -0
- spruce_grove-1.0.1/spruce_grove/session_surrogate_unpickler.py +418 -0
- spruce_grove-1.0.1/spruce_grove/shared_credentials.py +118 -0
- spruce_grove-1.0.1/spruce_grove/skill_provider.py +45 -0
- spruce_grove-1.0.1/spruce_grove/splash.py +385 -0
- spruce_grove-1.0.1/spruce_grove/status_display.py +315 -0
- spruce_grove-1.0.1/spruce_grove/steer_metadata.py +33 -0
- spruce_grove-1.0.1/spruce_grove/terminal_utils.py +634 -0
- spruce_grove-1.0.1/spruce_grove/token_usage.py +415 -0
- spruce_grove-1.0.1/spruce_grove/tolerant_openai.py +73 -0
- spruce_grove-1.0.1/spruce_grove/tools/__init__.py +473 -0
- spruce_grove-1.0.1/spruce_grove/tools/_browser_registry.py +142 -0
- spruce_grove-1.0.1/spruce_grove/tools/_lazy.py +12 -0
- spruce_grove-1.0.1/spruce_grove/tools/agent_tools.py +340 -0
- spruce_grove-1.0.1/spruce_grove/tools/apply_patch.py +478 -0
- spruce_grove-1.0.1/spruce_grove/tools/ask_user_question/__init__.py +26 -0
- spruce_grove-1.0.1/spruce_grove/tools/ask_user_question/constants.py +75 -0
- spruce_grove-1.0.1/spruce_grove/tools/ask_user_question/demo_tui.py +55 -0
- spruce_grove-1.0.1/spruce_grove/tools/ask_user_question/handler.py +232 -0
- spruce_grove-1.0.1/spruce_grove/tools/ask_user_question/models.py +304 -0
- spruce_grove-1.0.1/spruce_grove/tools/ask_user_question/registration.py +153 -0
- spruce_grove-1.0.1/spruce_grove/tools/ask_user_question/renderers.py +394 -0
- spruce_grove-1.0.1/spruce_grove/tools/ask_user_question/terminal_ui.py +336 -0
- spruce_grove-1.0.1/spruce_grove/tools/ask_user_question/theme.py +155 -0
- spruce_grove-1.0.1/spruce_grove/tools/ask_user_question/tui_loop.py +262 -0
- spruce_grove-1.0.1/spruce_grove/tools/browser/__init__.py +37 -0
- spruce_grove-1.0.1/spruce_grove/tools/browser/browser_control.py +289 -0
- spruce_grove-1.0.1/spruce_grove/tools/browser/browser_interactions.py +545 -0
- spruce_grove-1.0.1/spruce_grove/tools/browser/browser_locator_resolver.py +70 -0
- spruce_grove-1.0.1/spruce_grove/tools/browser/browser_locators.py +640 -0
- spruce_grove-1.0.1/spruce_grove/tools/browser/browser_manager.py +519 -0
- spruce_grove-1.0.1/spruce_grove/tools/browser/browser_navigation.py +251 -0
- spruce_grove-1.0.1/spruce_grove/tools/browser/browser_page_snapshot.py +147 -0
- spruce_grove-1.0.1/spruce_grove/tools/browser/browser_screenshot.py +179 -0
- spruce_grove-1.0.1/spruce_grove/tools/browser/browser_scripts.py +462 -0
- spruce_grove-1.0.1/spruce_grove/tools/browser/browser_semantic_interactions.py +189 -0
- spruce_grove-1.0.1/spruce_grove/tools/browser/browser_workflows.py +220 -0
- spruce_grove-1.0.1/spruce_grove/tools/browser/tool_registry.py +5 -0
- spruce_grove-1.0.1/spruce_grove/tools/command_runner.py +1590 -0
- spruce_grove-1.0.1/spruce_grove/tools/common.py +1332 -0
- spruce_grove-1.0.1/spruce_grove/tools/display.py +103 -0
- spruce_grove-1.0.1/spruce_grove/tools/file_modifications.py +1471 -0
- spruce_grove-1.0.1/spruce_grove/tools/file_operations.py +1534 -0
- spruce_grove-1.0.1/spruce_grove/tools/file_permission_state.py +137 -0
- spruce_grove-1.0.1/spruce_grove/tools/fs_access.py +228 -0
- spruce_grove-1.0.1/spruce_grove/tools/image_tools.py +192 -0
- spruce_grove-1.0.1/spruce_grove/tools/io_backends.py +186 -0
- spruce_grove-1.0.1/spruce_grove/tools/model_tools.py +105 -0
- spruce_grove-1.0.1/spruce_grove/tools/shell_backgrounding.py +94 -0
- spruce_grove-1.0.1/spruce_grove/tools/skills_tools.py +205 -0
- spruce_grove-1.0.1/spruce_grove/tools/subagent_context.py +247 -0
- spruce_grove-1.0.1/spruce_grove/tools/subagent_invocation.py +840 -0
- spruce_grove-1.0.1/spruce_grove/tools/subagent_usage_metrics.py +221 -0
- spruce_grove-1.0.1/spruce_grove/tools/tools_content.py +52 -0
- spruce_grove-1.0.1/spruce_grove/tools/universal_constructor.py +923 -0
- spruce_grove-1.0.1/spruce_grove/undo_manager.py +67 -0
- spruce_grove-1.0.1/spruce_grove/universal_constructor_provider.py +97 -0
- spruce_grove-1.0.1/spruce_grove/version_checker.py +106 -0
- spruce_grove-1.0.1/spruce_grove/zai_model.py +16 -0
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
# Python-generated files
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[oc]
|
|
4
|
+
build/
|
|
5
|
+
dist/
|
|
6
|
+
wheels/
|
|
7
|
+
*.egg-info
|
|
8
|
+
|
|
9
|
+
# Virtual environments
|
|
10
|
+
.venv
|
|
11
|
+
|
|
12
|
+
.coverage
|
|
13
|
+
coverage.json
|
|
14
|
+
|
|
15
|
+
# Session memory
|
|
16
|
+
.puppy_session_memory.json
|
|
17
|
+
|
|
18
|
+
# Pytest cache
|
|
19
|
+
.pytest_cache/
|
|
20
|
+
|
|
21
|
+
dummy_path
|
|
22
|
+
|
|
23
|
+
.idea/
|
|
24
|
+
|
|
25
|
+
.DS_Store
|
|
26
|
+
.env
|
|
27
|
+
.serena/
|
|
28
|
+
.beads/
|
|
29
|
+
main.dist/
|
|
30
|
+
nuitka-crash-report.xml
|
|
31
|
+
*.backup
|
|
32
|
+
main.bin
|
|
33
|
+
|
|
34
|
+
# Session log dumps (auto-committed by updater; not source)
|
|
35
|
+
NEWLog*.txt
|
|
36
|
+
|
|
37
|
+
# Bundled skills removed — skills are now fetched from remote catalog
|
|
38
|
+
code_puppy/bundled_skills/
|
|
39
|
+
|
|
40
|
+
# Hook engine runtime artifacts (logs, compiled outputs)
|
|
41
|
+
.claude/activity.jsonl
|
|
42
|
+
.claude/hooks/audit.log
|
|
43
|
+
|
|
44
|
+
# Compiled hook binaries (built from .go sources in .claude/hooks/go-hooks/)
|
|
45
|
+
.claude/hooks/go-hooks/audit-bash
|
|
46
|
+
.claude/hooks/go-hooks/file-policy
|
|
47
|
+
|
|
48
|
+
# Compiled TypeScript hook output (built from .ts sources)
|
|
49
|
+
.claude/hooks/ts-hooks/dist/
|
|
50
|
+
|
|
51
|
+
.json
|
|
52
|
+
|
|
53
|
+
.state/
|
|
54
|
+
|
|
55
|
+
# Local git worktrees
|
|
56
|
+
.worktrees/
|
|
57
|
+
|
|
58
|
+
# Cancel-wedge repro harness output (scripts/repro_cancel_wedge.py)
|
|
59
|
+
wedge_artifacts/
|
|
60
|
+
wedge_soak.log
|
|
61
|
+
|
|
62
|
+
# Personal voice memo + local transcript (never publish — repo is public)
|
|
63
|
+
MASTER-MASTER-PROMPT.m4a
|
|
64
|
+
MASTER-MASTER-PROMPT.txt
|
|
65
|
+
MASTER-MASTER-PROMPT.srt
|
|
66
|
+
|
|
67
|
+
# Beads / Dolt files (added by bd init)
|
|
68
|
+
.dolt/
|
|
69
|
+
*.db
|
|
70
|
+
.beads-credential-key
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Mike Pfaffenberger
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: spruce-grove
|
|
3
|
+
Version: 1.0.1
|
|
4
|
+
Summary: Spruce Grove OS - an agentic coding CLI distribution inspired by Code Puppy. Together we are better. Always.
|
|
5
|
+
Project-URL: repository, https://github.com/t-granlund/SPRUCE-GROVE-OS
|
|
6
|
+
Project-URL: HomePage, https://tylergranlund.com
|
|
7
|
+
Author: Michael Pfaffenberger
|
|
8
|
+
Author-email: Tyler Granlund <hello@tylergranlund.com>
|
|
9
|
+
License: MIT
|
|
10
|
+
License-File: LICENSE
|
|
11
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
12
|
+
Classifier: Operating System :: OS Independent
|
|
13
|
+
Classifier: Programming Language :: Python :: 3
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
17
|
+
Classifier: Topic :: Software Development :: Code Generators
|
|
18
|
+
Requires-Python: <3.15,>=3.11
|
|
19
|
+
Requires-Dist: agent-client-protocol<0.12,>=0.11.0
|
|
20
|
+
Requires-Dist: anthropic<2,>=1.0.0
|
|
21
|
+
Requires-Dist: anyio>=4.7.0
|
|
22
|
+
Requires-Dist: azure-identity>=1.15.0
|
|
23
|
+
Requires-Dist: boto3>=1.43.9
|
|
24
|
+
Requires-Dist: code-puppy-core-plugins>=0.0.45
|
|
25
|
+
Requires-Dist: httpx2>=2.7
|
|
26
|
+
Requires-Dist: httpx[http2]>=0.24.1
|
|
27
|
+
Requires-Dist: json-repair>=0.46.2
|
|
28
|
+
Requires-Dist: keyring>=24.0.0
|
|
29
|
+
Requires-Dist: logfire>=4.0
|
|
30
|
+
Requires-Dist: mcp>=1.9.4
|
|
31
|
+
Requires-Dist: openai>=2.45.0
|
|
32
|
+
Requires-Dist: packaging>=24.0
|
|
33
|
+
Requires-Dist: pillow>=10.0.0
|
|
34
|
+
Requires-Dist: playwright>=1.40.0; sys_platform != 'android'
|
|
35
|
+
Requires-Dist: pydantic-ai-harness==0.23.0
|
|
36
|
+
Requires-Dist: pydantic-ai-slim[anthropic,mcp,openai]==2.35.0
|
|
37
|
+
Requires-Dist: pydantic>=2.4.0
|
|
38
|
+
Requires-Dist: pyfiglet>=0.8.post1
|
|
39
|
+
Requires-Dist: python-dotenv>=1.0.0
|
|
40
|
+
Requires-Dist: rapidfuzz>=3.13.0
|
|
41
|
+
Requires-Dist: requests>=2.28.0
|
|
42
|
+
Requires-Dist: rich>=13.4.2
|
|
43
|
+
Requires-Dist: ripgrep==14.1.0; sys_platform != 'android'
|
|
44
|
+
Requires-Dist: termflow-md>=0.9.1
|
|
45
|
+
Requires-Dist: typer>=0.12.0
|
|
46
|
+
Provides-Extra: bedrock
|
|
47
|
+
Requires-Dist: boto3>=1.35.0; extra == 'bedrock'
|
|
48
|
+
Provides-Extra: computer-use
|
|
49
|
+
Requires-Dist: pyobjc-framework-applicationservices>=10.3; (sys_platform == 'darwin') and extra == 'computer-use'
|
|
50
|
+
Requires-Dist: pyobjc-framework-cocoa>=10.3; (sys_platform == 'darwin') and extra == 'computer-use'
|
|
51
|
+
Requires-Dist: pyobjc-framework-quartz>=10.3; (sys_platform == 'darwin') and extra == 'computer-use'
|
|
52
|
+
Provides-Extra: durable
|
|
53
|
+
Requires-Dist: dbos>=2.11.0; extra == 'durable'
|
|
54
|
+
Description-Content-Type: text/markdown
|
|
55
|
+
|
|
56
|
+
# SPRUCE GROVE OS
|
|
57
|
+
|
|
58
|
+
<p align="center">
|
|
59
|
+
<img src="logos/spruce_grove_logo_withback.jpeg" alt="The Spruce Grove mark - three geometric spruces in brand greens on charcoal" width="260">
|
|
60
|
+
</p>
|
|
61
|
+
|
|
62
|
+
**gran · lund · sv. · spruce grove** — an agentic coding CLI grown in the grove.
|
|
63
|
+
|
|
64
|
+
> Together we are better. Always.
|
|
65
|
+
|
|
66
|
+

|
|
67
|
+

|
|
68
|
+

|
|
69
|
+

|
|
70
|
+
|
|
71
|
+
Spruce Grove OS is a full custom instance of an agentic coding assistant:
|
|
72
|
+
the same engine, frameworks, plugins, agents, tools, skills, MCP plumbing,
|
|
73
|
+
and TUI as the project it is inspired by — replanted around one grove's
|
|
74
|
+
vision, mission, and values.
|
|
75
|
+
|
|
76
|
+
## Inspired by Code Puppy
|
|
77
|
+
|
|
78
|
+
Every trail in this grove started as a Code Puppy trail. Spruce Grove OS is
|
|
79
|
+
built directly from — and stays import-compatible with — **Code Puppy** by
|
|
80
|
+
[Michael Pfaffenberger](https://github.com/mpfaffenberger/code_puppy)
|
|
81
|
+
(MIT licensed). Huge respect to the original project and its contributors;
|
|
82
|
+
this grove exists because the puppy shared everything. Exact lineage, sync
|
|
83
|
+
points, and the full rename/contract map: [PROVENANCE.md](PROVENANCE.md).
|
|
84
|
+
|
|
85
|
+
## The ethos of the grove
|
|
86
|
+
|
|
87
|
+
Three sources, one creed — [ETHOS.md](ETHOS.md):
|
|
88
|
+
|
|
89
|
+
1. **Ozark Bagels — how to carry yourself.** Be first to say hello. Be kinder
|
|
90
|
+
than necessary. Be tough minded, but tender hearted. Leave everything
|
|
91
|
+
better than you found it. Spread joy, love, and cream cheese.
|
|
92
|
+
2. **The Junto (1727) — how to think with others.** Love truth for truth's
|
|
93
|
+
sake. No invented facts — ever; cite or flag "NOT VERIFIED". Provisional
|
|
94
|
+
phrasing over contradiction combat. Pragmatism over metaphysics.
|
|
95
|
+
3. **gran·lund — who is doing the carrying.** Help people solve problems.
|
|
96
|
+
Remove technology obstacles. Meet people where they are, as humans.
|
|
97
|
+
|
|
98
|
+
## Meet Cedar
|
|
99
|
+
|
|
100
|
+
The default agent persona is **Cedar**, the grove guide — same competent
|
|
101
|
+
agent core, new disposition: candid about code, gentle with people, allergic
|
|
102
|
+
to invented facts. Rename it anytime in `grove.cfg`.
|
|
103
|
+
|
|
104
|
+
---
|
|
105
|
+
|
|
106
|
+
## Design system
|
|
107
|
+
|
|
108
|
+
Nordic forest, dark-first. Charcoal base, deep spruce, warm cedar accents,
|
|
109
|
+
mist typography. Tokens shared with
|
|
110
|
+
[tylergranlund.com](https://tylergranlund.com) — the same palette that colors
|
|
111
|
+
the terminal splash.
|
|
112
|
+
|
|
113
|
+
### Color tokens
|
|
114
|
+
|
|
115
|
+
| Token | OKLCH | Role | Chip |
|
|
116
|
+
|---|---|---|---|
|
|
117
|
+
| charcoal | `oklch(0.18 0.012 150)` | base background |  |
|
|
118
|
+
| spruce-deep | `oklch(0.22 0.03 158)` | deep brand layer |  |
|
|
119
|
+
| spruce | `oklch(0.32 0.045 158)` | primary brand |  |
|
|
120
|
+
| moss | `oklch(0.45 0.06 155)` | accent green |  |
|
|
121
|
+
| cedar | `oklch(0.78 0.12 55)` | warm accent, persona |  |
|
|
122
|
+
| bark | `oklch(0.32 0.025 60)` | earthy neutral |  |
|
|
123
|
+
| stone | `oklch(0.85 0.012 90)` | soft UI text |  |
|
|
124
|
+
| mist | `oklch(0.94 0.008 100)` | foreground/typography |  |
|
|
125
|
+
|
|
126
|
+
### Typography
|
|
127
|
+
|
|
128
|
+
- **Fraunces** (variable serif) — wordmarks and display
|
|
129
|
+
- **Inter** — body copy
|
|
130
|
+
- **JetBrains Mono** — code, CLI output
|
|
131
|
+
|
|
132
|
+
### Terminal theming
|
|
133
|
+
|
|
134
|
+
The boot splash renders a shimmering pyramid + figlet lockup
|
|
135
|
+
("SPRUCE GROVE", compact "GROVE" on narrow terminals) in a truecolor
|
|
136
|
+
canopy-to-cedar gradient: halo `#2D4F3A` → glow `#588F5E` → core `#D2A069`,
|
|
137
|
+
with a mist-white crest (`#F0E1C8`) where the sheen passes. ANSI fallbacks
|
|
138
|
+
step down through green → bright green → yellow.
|
|
139
|
+
|
|
140
|
+
### Voice
|
|
141
|
+
|
|
142
|
+
Plain-spoken, warm, a little playful. First to say hello. Candid, never
|
|
143
|
+
roasty. Zero invented facts — "NOT VERIFIED" beats a confident guess.
|
|
144
|
+
|
|
145
|
+
Full tokens and voice guide: [BRAND.md](BRAND.md).
|
|
146
|
+
|
|
147
|
+
---
|
|
148
|
+
|
|
149
|
+
## What's inside (same bones as Code Puppy)
|
|
150
|
+
|
|
151
|
+
```
|
|
152
|
+
┌──────────────────────────────────────────────────┐
|
|
153
|
+
│ TUI / CLI (command_line/) │
|
|
154
|
+
├──────────────────────────────────────────────────┤
|
|
155
|
+
│ Agent Layer (agents/) — Cedar default + JSON │
|
|
156
|
+
├──────────────────────────────────────────────────┤
|
|
157
|
+
│ Tool Layer (tools/) — TOOL_REGISTRY │
|
|
158
|
+
├──────────────────────────────────────────────────┤
|
|
159
|
+
│ Plugin Layer (plugins/, callbacks.py) │
|
|
160
|
+
├──────────────────────────────────────────────────┤
|
|
161
|
+
│ Model Layer (model_factory.py) │
|
|
162
|
+
├──────────────────────────────────────────────────┤
|
|
163
|
+
│ pydantic-ai + MCP (external) │
|
|
164
|
+
└──────────────────────────────────────────────────┘
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
Python 3.11–3.14 · pydantic-ai · pluggable models (OpenAI, Anthropic,
|
|
168
|
+
Gemini, Bedrock, Z.AI, custom endpoints) · MCP servers · skills with
|
|
169
|
+
namespaces · session history + compaction · i18n.
|
|
170
|
+
|
|
171
|
+
## Install & run
|
|
172
|
+
|
|
173
|
+
```bash
|
|
174
|
+
git clone https://github.com/t-granlund/SPRUCE-GROVE-OS
|
|
175
|
+
cd SPRUCE-GROVE-OS
|
|
176
|
+
uv sync
|
|
177
|
+
uv run spruce-grove # or: uv run grove
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
Config: `~/.spruce_grove/grove.cfg` · Env vars: `SPRUCE_GROVE_*`.
|
|
181
|
+
|
|
182
|
+
## Code Puppy compatibility
|
|
183
|
+
|
|
184
|
+
- `code_puppy.*` imports (e.g. from `code-puppy-core-plugins`) resolve to
|
|
185
|
+
`spruce_grove.*` via an import shim with true module identity.
|
|
186
|
+
- The plugin entry-point group `code_puppy.plugins` is intentionally retained.
|
|
187
|
+
- Legacy aliases kept: `agent_code_puppy`, `CodePuppyAgent`,
|
|
188
|
+
`get_puppy_name()`, persisted `puppy_name` fallback.
|
|
189
|
+
- Full contract ledger: [PROVENANCE.md](PROVENANCE.md).
|
|
190
|
+
|
|
191
|
+
## License
|
|
192
|
+
|
|
193
|
+
MIT — inherited from Code Puppy. See [LICENSE](LICENSE) and attribution in
|
|
194
|
+
[PROVENANCE.md](PROVENANCE.md).
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
# SPRUCE GROVE OS
|
|
2
|
+
|
|
3
|
+
<p align="center">
|
|
4
|
+
<img src="logos/spruce_grove_logo_withback.jpeg" alt="The Spruce Grove mark - three geometric spruces in brand greens on charcoal" width="260">
|
|
5
|
+
</p>
|
|
6
|
+
|
|
7
|
+
**gran · lund · sv. · spruce grove** — an agentic coding CLI grown in the grove.
|
|
8
|
+
|
|
9
|
+
> Together we are better. Always.
|
|
10
|
+
|
|
11
|
+

|
|
12
|
+

|
|
13
|
+

|
|
14
|
+

|
|
15
|
+
|
|
16
|
+
Spruce Grove OS is a full custom instance of an agentic coding assistant:
|
|
17
|
+
the same engine, frameworks, plugins, agents, tools, skills, MCP plumbing,
|
|
18
|
+
and TUI as the project it is inspired by — replanted around one grove's
|
|
19
|
+
vision, mission, and values.
|
|
20
|
+
|
|
21
|
+
## Inspired by Code Puppy
|
|
22
|
+
|
|
23
|
+
Every trail in this grove started as a Code Puppy trail. Spruce Grove OS is
|
|
24
|
+
built directly from — and stays import-compatible with — **Code Puppy** by
|
|
25
|
+
[Michael Pfaffenberger](https://github.com/mpfaffenberger/code_puppy)
|
|
26
|
+
(MIT licensed). Huge respect to the original project and its contributors;
|
|
27
|
+
this grove exists because the puppy shared everything. Exact lineage, sync
|
|
28
|
+
points, and the full rename/contract map: [PROVENANCE.md](PROVENANCE.md).
|
|
29
|
+
|
|
30
|
+
## The ethos of the grove
|
|
31
|
+
|
|
32
|
+
Three sources, one creed — [ETHOS.md](ETHOS.md):
|
|
33
|
+
|
|
34
|
+
1. **Ozark Bagels — how to carry yourself.** Be first to say hello. Be kinder
|
|
35
|
+
than necessary. Be tough minded, but tender hearted. Leave everything
|
|
36
|
+
better than you found it. Spread joy, love, and cream cheese.
|
|
37
|
+
2. **The Junto (1727) — how to think with others.** Love truth for truth's
|
|
38
|
+
sake. No invented facts — ever; cite or flag "NOT VERIFIED". Provisional
|
|
39
|
+
phrasing over contradiction combat. Pragmatism over metaphysics.
|
|
40
|
+
3. **gran·lund — who is doing the carrying.** Help people solve problems.
|
|
41
|
+
Remove technology obstacles. Meet people where they are, as humans.
|
|
42
|
+
|
|
43
|
+
## Meet Cedar
|
|
44
|
+
|
|
45
|
+
The default agent persona is **Cedar**, the grove guide — same competent
|
|
46
|
+
agent core, new disposition: candid about code, gentle with people, allergic
|
|
47
|
+
to invented facts. Rename it anytime in `grove.cfg`.
|
|
48
|
+
|
|
49
|
+
---
|
|
50
|
+
|
|
51
|
+
## Design system
|
|
52
|
+
|
|
53
|
+
Nordic forest, dark-first. Charcoal base, deep spruce, warm cedar accents,
|
|
54
|
+
mist typography. Tokens shared with
|
|
55
|
+
[tylergranlund.com](https://tylergranlund.com) — the same palette that colors
|
|
56
|
+
the terminal splash.
|
|
57
|
+
|
|
58
|
+
### Color tokens
|
|
59
|
+
|
|
60
|
+
| Token | OKLCH | Role | Chip |
|
|
61
|
+
|---|---|---|---|
|
|
62
|
+
| charcoal | `oklch(0.18 0.012 150)` | base background |  |
|
|
63
|
+
| spruce-deep | `oklch(0.22 0.03 158)` | deep brand layer |  |
|
|
64
|
+
| spruce | `oklch(0.32 0.045 158)` | primary brand |  |
|
|
65
|
+
| moss | `oklch(0.45 0.06 155)` | accent green |  |
|
|
66
|
+
| cedar | `oklch(0.78 0.12 55)` | warm accent, persona |  |
|
|
67
|
+
| bark | `oklch(0.32 0.025 60)` | earthy neutral |  |
|
|
68
|
+
| stone | `oklch(0.85 0.012 90)` | soft UI text |  |
|
|
69
|
+
| mist | `oklch(0.94 0.008 100)` | foreground/typography |  |
|
|
70
|
+
|
|
71
|
+
### Typography
|
|
72
|
+
|
|
73
|
+
- **Fraunces** (variable serif) — wordmarks and display
|
|
74
|
+
- **Inter** — body copy
|
|
75
|
+
- **JetBrains Mono** — code, CLI output
|
|
76
|
+
|
|
77
|
+
### Terminal theming
|
|
78
|
+
|
|
79
|
+
The boot splash renders a shimmering pyramid + figlet lockup
|
|
80
|
+
("SPRUCE GROVE", compact "GROVE" on narrow terminals) in a truecolor
|
|
81
|
+
canopy-to-cedar gradient: halo `#2D4F3A` → glow `#588F5E` → core `#D2A069`,
|
|
82
|
+
with a mist-white crest (`#F0E1C8`) where the sheen passes. ANSI fallbacks
|
|
83
|
+
step down through green → bright green → yellow.
|
|
84
|
+
|
|
85
|
+
### Voice
|
|
86
|
+
|
|
87
|
+
Plain-spoken, warm, a little playful. First to say hello. Candid, never
|
|
88
|
+
roasty. Zero invented facts — "NOT VERIFIED" beats a confident guess.
|
|
89
|
+
|
|
90
|
+
Full tokens and voice guide: [BRAND.md](BRAND.md).
|
|
91
|
+
|
|
92
|
+
---
|
|
93
|
+
|
|
94
|
+
## What's inside (same bones as Code Puppy)
|
|
95
|
+
|
|
96
|
+
```
|
|
97
|
+
┌──────────────────────────────────────────────────┐
|
|
98
|
+
│ TUI / CLI (command_line/) │
|
|
99
|
+
├──────────────────────────────────────────────────┤
|
|
100
|
+
│ Agent Layer (agents/) — Cedar default + JSON │
|
|
101
|
+
├──────────────────────────────────────────────────┤
|
|
102
|
+
│ Tool Layer (tools/) — TOOL_REGISTRY │
|
|
103
|
+
├──────────────────────────────────────────────────┤
|
|
104
|
+
│ Plugin Layer (plugins/, callbacks.py) │
|
|
105
|
+
├──────────────────────────────────────────────────┤
|
|
106
|
+
│ Model Layer (model_factory.py) │
|
|
107
|
+
├──────────────────────────────────────────────────┤
|
|
108
|
+
│ pydantic-ai + MCP (external) │
|
|
109
|
+
└──────────────────────────────────────────────────┘
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
Python 3.11–3.14 · pydantic-ai · pluggable models (OpenAI, Anthropic,
|
|
113
|
+
Gemini, Bedrock, Z.AI, custom endpoints) · MCP servers · skills with
|
|
114
|
+
namespaces · session history + compaction · i18n.
|
|
115
|
+
|
|
116
|
+
## Install & run
|
|
117
|
+
|
|
118
|
+
```bash
|
|
119
|
+
git clone https://github.com/t-granlund/SPRUCE-GROVE-OS
|
|
120
|
+
cd SPRUCE-GROVE-OS
|
|
121
|
+
uv sync
|
|
122
|
+
uv run spruce-grove # or: uv run grove
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
Config: `~/.spruce_grove/grove.cfg` · Env vars: `SPRUCE_GROVE_*`.
|
|
126
|
+
|
|
127
|
+
## Code Puppy compatibility
|
|
128
|
+
|
|
129
|
+
- `code_puppy.*` imports (e.g. from `code-puppy-core-plugins`) resolve to
|
|
130
|
+
`spruce_grove.*` via an import shim with true module identity.
|
|
131
|
+
- The plugin entry-point group `code_puppy.plugins` is intentionally retained.
|
|
132
|
+
- Legacy aliases kept: `agent_code_puppy`, `CodePuppyAgent`,
|
|
133
|
+
`get_puppy_name()`, persisted `puppy_name` fallback.
|
|
134
|
+
- Full contract ledger: [PROVENANCE.md](PROVENANCE.md).
|
|
135
|
+
|
|
136
|
+
## License
|
|
137
|
+
|
|
138
|
+
MIT — inherited from Code Puppy. See [LICENSE](LICENSE) and attribution in
|
|
139
|
+
[PROVENANCE.md](PROVENANCE.md).
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["hatchling"]
|
|
3
|
+
build-backend = "hatchling.build"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "spruce-grove"
|
|
7
|
+
version = "1.0.1"
|
|
8
|
+
description = "Spruce Grove OS - an agentic coding CLI distribution inspired by Code Puppy. Together we are better. Always."
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.11,<3.15"
|
|
11
|
+
dependencies = [
|
|
12
|
+
"code-puppy-core-plugins>=0.0.45",
|
|
13
|
+
"logfire>=4.0",
|
|
14
|
+
"pydantic-ai-slim[openai,anthropic,mcp]==2.35.0",
|
|
15
|
+
"pydantic-ai-harness==0.23.0",
|
|
16
|
+
"anyio>=4.7.0",
|
|
17
|
+
"typer>=0.12.0",
|
|
18
|
+
"mcp>=1.9.4",
|
|
19
|
+
"httpx[http2]>=0.24.1",
|
|
20
|
+
"httpx2>=2.7",
|
|
21
|
+
"requests>=2.28.0",
|
|
22
|
+
"packaging>=24.0",
|
|
23
|
+
"rich>=13.4.2",
|
|
24
|
+
"pydantic>=2.4.0",
|
|
25
|
+
"python-dotenv>=1.0.0",
|
|
26
|
+
"json-repair>=0.46.2",
|
|
27
|
+
"pyfiglet>=0.8.post1",
|
|
28
|
+
"rapidfuzz>=3.13.0",
|
|
29
|
+
"openai>=2.45.0",
|
|
30
|
+
"ripgrep==14.1.0; sys_platform != 'android'",
|
|
31
|
+
"playwright>=1.40.0; sys_platform != 'android'",
|
|
32
|
+
"termflow-md>=0.9.1",
|
|
33
|
+
"Pillow>=10.0.0",
|
|
34
|
+
"azure-identity>=1.15.0",
|
|
35
|
+
"anthropic>=1.0.0,<2",
|
|
36
|
+
"boto3>=1.43.9",
|
|
37
|
+
"keyring>=24.0.0",
|
|
38
|
+
"agent-client-protocol>=0.11.0,<0.12",
|
|
39
|
+
]
|
|
40
|
+
dev-dependencies = [
|
|
41
|
+
"pytest>=8.3.4",
|
|
42
|
+
"pytest-cov>=6.1.1",
|
|
43
|
+
"pytest-asyncio>=0.23.1",
|
|
44
|
+
"ruff>=0.15,<0.16",
|
|
45
|
+
"pexpect>=4.9.0",
|
|
46
|
+
]
|
|
47
|
+
authors = [
|
|
48
|
+
{name = "Tyler Granlund", email = "hello@tylergranlund.com"},
|
|
49
|
+
{name = "Michael Pfaffenberger"} # original author of Code Puppy, the project this is inspired by and built from
|
|
50
|
+
]
|
|
51
|
+
license = {text = "MIT"}
|
|
52
|
+
classifiers = [
|
|
53
|
+
"Programming Language :: Python :: 3",
|
|
54
|
+
"Programming Language :: Python :: 3.11",
|
|
55
|
+
"Programming Language :: Python :: 3.12",
|
|
56
|
+
"Programming Language :: Python :: 3.13",
|
|
57
|
+
"License :: OSI Approved :: MIT License",
|
|
58
|
+
"Operating System :: OS Independent",
|
|
59
|
+
"Topic :: Software Development :: Code Generators",
|
|
60
|
+
]
|
|
61
|
+
|
|
62
|
+
[project.optional-dependencies]
|
|
63
|
+
bedrock = ["boto3>=1.35.0"]
|
|
64
|
+
durable = ["dbos>=2.11.0"]
|
|
65
|
+
computer-use = [
|
|
66
|
+
"pyobjc-framework-ApplicationServices>=10.3; sys_platform == 'darwin'",
|
|
67
|
+
"pyobjc-framework-Cocoa>=10.3; sys_platform == 'darwin'",
|
|
68
|
+
"pyobjc-framework-Quartz>=10.3; sys_platform == 'darwin'",
|
|
69
|
+
]
|
|
70
|
+
|
|
71
|
+
[project.urls]
|
|
72
|
+
repository = "https://github.com/t-granlund/SPRUCE-GROVE-OS"
|
|
73
|
+
HomePage = "https://tylergranlund.com"
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
[project.scripts]
|
|
77
|
+
spruce-grove = "spruce_grove.main:main_entry"
|
|
78
|
+
grove = "spruce_grove.main:main_entry"
|
|
79
|
+
|
|
80
|
+
[tool.logfire]
|
|
81
|
+
ignore_no_config = true
|
|
82
|
+
|
|
83
|
+
[tool.hatch.build]
|
|
84
|
+
packages = ["spruce_grove"]
|
|
85
|
+
|
|
86
|
+
[tool.hatch.build.targets.wheel.shared-data]
|
|
87
|
+
"spruce_grove/models.json" = "spruce_grove/models.json"
|
|
88
|
+
"spruce_grove/models_dev_api.json" = "spruce_grove/models_dev_api.json"
|
|
89
|
+
|
|
90
|
+
[[tool.hatch.build.targets.sdist.include]]
|
|
91
|
+
path = "spruce_grove/models.json"
|
|
92
|
+
|
|
93
|
+
[[tool.hatch.build.targets.sdist.include]]
|
|
94
|
+
path = "spruce_grove/models_dev_api.json"
|
|
95
|
+
|
|
96
|
+
[tool.ruff.lint.per-file-ignores]
|
|
97
|
+
"spruce_grove/__init__.py" = ["E402"]
|
|
98
|
+
"spruce_grove/main.py" = ["E402"]
|
|
99
|
+
"spruce_grove/cli_runner.py" = ["E402"]
|
|
100
|
+
"spruce_grove/messaging/__init__.py" = ["E402"]
|
|
101
|
+
|
|
102
|
+
[tool.pytest.ini_options]
|
|
103
|
+
addopts = "--cov=spruce_grove --cov-report=term-missing"
|
|
104
|
+
testpaths = ["tests"]
|
|
105
|
+
asyncio_mode = "auto"
|
|
106
|
+
|
|
107
|
+
[tool.coverage.run]
|
|
108
|
+
omit = ["spruce_grove/main.py"]
|
|
109
|
+
|
|
110
|
+
[tool.uv]
|
|
111
|
+
python-preference = "only-managed"
|
|
112
|
+
|
|
113
|
+
[dependency-groups]
|
|
114
|
+
dev = [
|
|
115
|
+
"pytest>=8.3.4",
|
|
116
|
+
"pytest-cov>=6.1.1",
|
|
117
|
+
"pytest-asyncio>=0.23.1",
|
|
118
|
+
"ruff>=0.15,<0.16",
|
|
119
|
+
"pexpect>=4.9.0",
|
|
120
|
+
"pyte>=0.8.2",
|
|
121
|
+
]
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
"""Installed distribution metadata for Spruce Grove."""
|
|
2
|
+
|
|
3
|
+
import importlib.metadata
|
|
4
|
+
|
|
5
|
+
from packaging.version import Version
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def _get_distribution_version(
|
|
9
|
+
distribution_name: str, fallback: str | None = None
|
|
10
|
+
) -> str | None:
|
|
11
|
+
"""Return an installed distribution version or a stable fallback."""
|
|
12
|
+
try:
|
|
13
|
+
detected_version = importlib.metadata.version(distribution_name)
|
|
14
|
+
return detected_version if detected_version else fallback
|
|
15
|
+
except Exception:
|
|
16
|
+
return fallback
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def get_core_plugins_version() -> str | None:
|
|
20
|
+
"""Return the valid installed official core-plugin bundle version."""
|
|
21
|
+
detected_version = _get_distribution_version("code-puppy-core-plugins")
|
|
22
|
+
if not isinstance(detected_version, str):
|
|
23
|
+
return None
|
|
24
|
+
|
|
25
|
+
try:
|
|
26
|
+
normalized_version = detected_version.strip()
|
|
27
|
+
if not normalized_version:
|
|
28
|
+
return None
|
|
29
|
+
Version(normalized_version)
|
|
30
|
+
except Exception:
|
|
31
|
+
return None
|
|
32
|
+
|
|
33
|
+
return normalized_version
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
# Planted in the grove. -Cedar
|
|
37
|
+
__version__ = _get_distribution_version("spruce-grove", "0.0.0-dev")
|
|
38
|
+
|
|
39
|
+
from spruce_grove._code_puppy_compat import install as _install_legacy_shim
|
|
40
|
+
|
|
41
|
+
_install_legacy_shim()
|
|
42
|
+
del _install_legacy_shim
|