code-puppy-core-plugins 0.0.26__tar.gz → 0.0.27__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (344) hide show
  1. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/PKG-INFO +1 -1
  2. code_puppy_core_plugins-0.0.27/code_puppy_core_plugins/openrouter_oauth/__init__.py +6 -0
  3. code_puppy_core_plugins-0.0.27/code_puppy_core_plugins/openrouter_oauth/config.py +21 -0
  4. code_puppy_core_plugins-0.0.27/code_puppy_core_plugins/openrouter_oauth/oauth_flow.py +242 -0
  5. code_puppy_core_plugins-0.0.27/code_puppy_core_plugins/openrouter_oauth/register_callbacks.py +93 -0
  6. code_puppy_core_plugins-0.0.27/code_puppy_core_plugins/openrouter_oauth/test_plugin.py +263 -0
  7. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/pyproject.toml +2 -1
  8. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/.gitignore +0 -0
  9. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/LICENSE +0 -0
  10. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/README.md +0 -0
  11. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/__init__.py +0 -0
  12. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/acp/README.md +0 -0
  13. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/acp/__init__.py +0 -0
  14. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/acp/agent.py +0 -0
  15. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/acp/bridge.py +0 -0
  16. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/acp/capabilities.py +0 -0
  17. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/acp/commands.py +0 -0
  18. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/acp/content.py +0 -0
  19. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/acp/io_delegation.py +0 -0
  20. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/acp/mcp_config.py +0 -0
  21. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/acp/permissions.py +0 -0
  22. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/acp/persistence.py +0 -0
  23. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/acp/register_callbacks.py +0 -0
  24. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/acp/replay.py +0 -0
  25. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/acp/session.py +0 -0
  26. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/acp/session_config.py +0 -0
  27. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/acp/state.py +0 -0
  28. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/agent_creator_skill/SKILL.md +0 -0
  29. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/agent_creator_skill/__init__.py +0 -0
  30. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/agent_creator_skill/register_callbacks.py +0 -0
  31. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/agent_skills/__init__.py +0 -0
  32. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/agent_skills/config.py +0 -0
  33. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/agent_skills/discovery.py +0 -0
  34. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/agent_skills/downloader.py +0 -0
  35. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/agent_skills/enabled_skills.py +0 -0
  36. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/agent_skills/installer.py +0 -0
  37. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/agent_skills/metadata.py +0 -0
  38. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/agent_skills/prompt_builder.py +0 -0
  39. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/agent_skills/provider.py +0 -0
  40. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/agent_skills/register_callbacks.py +0 -0
  41. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/agent_skills/remote_catalog.py +0 -0
  42. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/agent_skills/skill_catalog.py +0 -0
  43. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/agent_skills/skill_commands.py +0 -0
  44. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/agent_skills/skills_install_menu.py +0 -0
  45. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/agent_skills/skills_menu.py +0 -0
  46. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/aws_bedrock/__init__.py +0 -0
  47. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/aws_bedrock/config.py +0 -0
  48. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/aws_bedrock/register_callbacks.py +0 -0
  49. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/aws_bedrock/utils.py +0 -0
  50. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/azure_foundry/README.md +0 -0
  51. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/azure_foundry/__init__.py +0 -0
  52. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/azure_foundry/config.py +0 -0
  53. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/azure_foundry/discovery.py +0 -0
  54. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/azure_foundry/register_callbacks.py +0 -0
  55. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/azure_foundry/token.py +0 -0
  56. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/azure_foundry/utils.py +0 -0
  57. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/btw/__init__.py +0 -0
  58. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/btw/inline_view.py +0 -0
  59. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/btw/register_callbacks.py +0 -0
  60. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/btw/side_query.py +0 -0
  61. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/chatgpt_oauth/IMAGEGEN_SKILL.md +0 -0
  62. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/chatgpt_oauth/__init__.py +0 -0
  63. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/chatgpt_oauth/config.py +0 -0
  64. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/chatgpt_oauth/image_generation.py +0 -0
  65. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/chatgpt_oauth/image_tool.py +0 -0
  66. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/chatgpt_oauth/model_catalog.py +0 -0
  67. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/chatgpt_oauth/oauth_flow.py +0 -0
  68. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/chatgpt_oauth/register_callbacks.py +0 -0
  69. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/chatgpt_oauth/test_plugin.py +0 -0
  70. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/chatgpt_oauth/usage.py +0 -0
  71. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/chatgpt_oauth/utils.py +0 -0
  72. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/claude_code_hooks/__init__.py +0 -0
  73. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/claude_code_hooks/config.py +0 -0
  74. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/claude_code_hooks/register_callbacks.py +0 -0
  75. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/claude_code_hooks/trust.py +0 -0
  76. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/claude_code_oauth/README.md +0 -0
  77. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/claude_code_oauth/SETUP.md +0 -0
  78. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/claude_code_oauth/__init__.py +0 -0
  79. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/claude_code_oauth/config.py +0 -0
  80. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/claude_code_oauth/fast_mode.py +0 -0
  81. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/claude_code_oauth/prompt_handler.py +0 -0
  82. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/claude_code_oauth/register_callbacks.py +0 -0
  83. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/claude_code_oauth/test_plugin.py +0 -0
  84. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/claude_code_oauth/token_refresh_heartbeat.py +0 -0
  85. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/claude_code_oauth/utils.py +0 -0
  86. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/code_puppy_agent/AGENTS_AND_TOOLS.md +0 -0
  87. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/code_puppy_agent/MODELS_AND_MCP.md +0 -0
  88. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/code_puppy_agent/PLUGINS_AND_CALLBACKS.md +0 -0
  89. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/code_puppy_agent/SESSIONS_AND_HISTORY.md +0 -0
  90. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/code_puppy_agent/SKILL.md +0 -0
  91. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/code_puppy_agent/SKILLS_SYSTEM.md +0 -0
  92. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/code_puppy_agent/SYSTEM_PROMPT_CONFIG_AND_I18N.md +0 -0
  93. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/code_puppy_agent/__init__.py +0 -0
  94. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/code_puppy_agent/register_callbacks.py +0 -0
  95. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/computer_use/NativeCapture.swift +0 -0
  96. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/computer_use/README.md +0 -0
  97. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/computer_use/__init__.py +0 -0
  98. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/computer_use/accessibility.py +0 -0
  99. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/computer_use/activation.py +0 -0
  100. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/computer_use/backend.py +0 -0
  101. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/computer_use/backend_types.py +0 -0
  102. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/computer_use/capture.py +0 -0
  103. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/computer_use/commands.py +0 -0
  104. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/computer_use/geometry.py +0 -0
  105. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/computer_use/inline_image.py +0 -0
  106. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/computer_use/keycodes.py +0 -0
  107. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/computer_use/policy.py +0 -0
  108. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/computer_use/register_callbacks.py +0 -0
  109. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/computer_use/safety.py +0 -0
  110. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/computer_use/settle.py +0 -0
  111. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/computer_use/state.py +0 -0
  112. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/computer_use/tools.py +0 -0
  113. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/context_indicator/__init__.py +0 -0
  114. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/context_indicator/register_callbacks.py +0 -0
  115. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/context_indicator/usage.py +0 -0
  116. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/copilot_auth/__init__.py +0 -0
  117. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/copilot_auth/config.py +0 -0
  118. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/copilot_auth/reasoning_client.py +0 -0
  119. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/copilot_auth/register_callbacks.py +0 -0
  120. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/copilot_auth/utils.py +0 -0
  121. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/customizable_commands/__init__.py +0 -0
  122. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/customizable_commands/register_callbacks.py +0 -0
  123. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/dbos_durable_exec/__init__.py +0 -0
  124. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/dbos_durable_exec/cancel.py +0 -0
  125. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/dbos_durable_exec/commands.py +0 -0
  126. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/dbos_durable_exec/config.py +0 -0
  127. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/dbos_durable_exec/lifecycle.py +0 -0
  128. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/dbos_durable_exec/register_callbacks.py +0 -0
  129. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/dbos_durable_exec/runtime.py +0 -0
  130. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/dbos_durable_exec/startup_lock.py +0 -0
  131. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/dbos_durable_exec/workflow_ids.py +0 -0
  132. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/dbos_durable_exec/wrapper.py +0 -0
  133. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/destructive_command_guard/AGENTS.md +0 -0
  134. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/destructive_command_guard/__init__.py +0 -0
  135. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/destructive_command_guard/detector.py +0 -0
  136. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/destructive_command_guard/register_callbacks.py +0 -0
  137. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/emoji_filter/__init__.py +0 -0
  138. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/emoji_filter/config.py +0 -0
  139. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/emoji_filter/register_callbacks.py +0 -0
  140. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/emoji_filter/stripper.py +0 -0
  141. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/empty_html_comment_filter/register_callbacks.py +0 -0
  142. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/example_custom_command/README.md +0 -0
  143. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/example_custom_command/register_callbacks.py +0 -0
  144. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/file_permission_handler/__init__.py +0 -0
  145. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/file_permission_handler/register_callbacks.py +0 -0
  146. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/flux_bootstrap/__init__.py +0 -0
  147. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/flux_bootstrap/bundled/commands/flux/_docs/README.md +0 -0
  148. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/flux_bootstrap/bundled/commands/flux/_docs/cheatsheet.md +0 -0
  149. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/flux_bootstrap/bundled/commands/flux/_docs/pipeline.md +0 -0
  150. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/flux_bootstrap/bundled/commands/flux/_docs/synopsis.md +0 -0
  151. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/flux_bootstrap/bundled/commands/flux/about.md +0 -0
  152. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/flux_bootstrap/bundled/commands/flux/address-feedback.md +0 -0
  153. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/flux_bootstrap/bundled/commands/flux/ask.md +0 -0
  154. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/flux_bootstrap/bundled/commands/flux/aug.md +0 -0
  155. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/flux_bootstrap/bundled/commands/flux/auto-pilot.md +0 -0
  156. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/flux_bootstrap/bundled/commands/flux/cheatsheet.md +0 -0
  157. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/flux_bootstrap/bundled/commands/flux/commit.md +0 -0
  158. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/flux_bootstrap/bundled/commands/flux/config.md +0 -0
  159. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/flux_bootstrap/bundled/commands/flux/create-pr.md +0 -0
  160. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/flux_bootstrap/bundled/commands/flux/exec.md +0 -0
  161. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/flux_bootstrap/bundled/commands/flux/new.md +0 -0
  162. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/flux_bootstrap/bundled/commands/flux/qa.md +0 -0
  163. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/flux_bootstrap/bundled/commands/flux/rebase.md +0 -0
  164. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/flux_bootstrap/bundled/commands/flux/review.md +0 -0
  165. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/flux_bootstrap/bundled/commands/flux/split.md +0 -0
  166. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/flux_bootstrap/bundled/commands/flux/squash-commits.md +0 -0
  167. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/flux_bootstrap/bundled/commands/flux/status.md +0 -0
  168. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/flux_bootstrap/bundled/commands/flux/tests.md +0 -0
  169. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/flux_bootstrap/bundled/scripts/flux_about.py +0 -0
  170. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/flux_bootstrap/bundled/scripts/flux_cheatsheet.py +0 -0
  171. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/flux_bootstrap/bundled/scripts/flux_status.py +0 -0
  172. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/flux_bootstrap/installer.py +0 -0
  173. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/flux_bootstrap/register_callbacks.py +0 -0
  174. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/force_push_guard/__init__.py +0 -0
  175. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/force_push_guard/detector.py +0 -0
  176. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/force_push_guard/register_callbacks.py +0 -0
  177. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/fork/__init__.py +0 -0
  178. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/fork/register_callbacks.py +0 -0
  179. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/frontend_emitter/__init__.py +0 -0
  180. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/frontend_emitter/emitter.py +0 -0
  181. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/frontend_emitter/register_callbacks.py +0 -0
  182. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/frontend_emitter/session_context.py +0 -0
  183. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/grok_oauth/__init__.py +0 -0
  184. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/grok_oauth/config.py +0 -0
  185. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/grok_oauth/oauth_flow.py +0 -0
  186. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/grok_oauth/register_callbacks.py +0 -0
  187. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/grok_oauth/utils.py +0 -0
  188. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/herdr/README.md +0 -0
  189. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/herdr/__init__.py +0 -0
  190. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/herdr/client.py +0 -0
  191. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/herdr/register_callbacks.py +0 -0
  192. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/herdr/reporter.py +0 -0
  193. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/herdr/smoke.py +0 -0
  194. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/herdr/sources.py +0 -0
  195. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/hook_creator/__init__.py +0 -0
  196. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/hook_creator/register_callbacks.py +0 -0
  197. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/hook_manager/__init__.py +0 -0
  198. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/hook_manager/config.py +0 -0
  199. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/hook_manager/hooks_menu.py +0 -0
  200. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/hook_manager/register_callbacks.py +0 -0
  201. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/hook_manager/trust_handler.py +0 -0
  202. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/logfire_oauth/__init__.py +0 -0
  203. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/logfire_oauth/oauth.py +0 -0
  204. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/logfire_oauth/query_tool.py +0 -0
  205. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/logfire_oauth/register_callbacks.py +0 -0
  206. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/logfire_sessions/__init__.py +0 -0
  207. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/logfire_sessions/mirror.py +0 -0
  208. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/logfire_sessions/query.py +0 -0
  209. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/logfire_sessions/register_callbacks.py +0 -0
  210. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/logfire_sessions/sync.py +0 -0
  211. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/meta_oauth/__init__.py +0 -0
  212. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/meta_oauth/config.py +0 -0
  213. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/meta_oauth/oauth_flow.py +0 -0
  214. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/meta_oauth/register_callbacks.py +0 -0
  215. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/meta_oauth/utils.py +0 -0
  216. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/namespace_skill_search/README.md +0 -0
  217. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/namespace_skill_search/__init__.py +0 -0
  218. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/namespace_skill_search/namespaces.py +0 -0
  219. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/namespace_skill_search/register_callbacks.py +0 -0
  220. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/namespace_skill_search/search_tool.py +0 -0
  221. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/no_tools/__init__.py +0 -0
  222. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/no_tools/register_callbacks.py +0 -0
  223. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/oauth_pasteback.py +0 -0
  224. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/oauth_puppy_html.py +0 -0
  225. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/obsidian_agent/README.md +0 -0
  226. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/obsidian_agent/__init__.py +0 -0
  227. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/obsidian_agent/agent_obsidian.py +0 -0
  228. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/obsidian_agent/register_callbacks.py +0 -0
  229. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/ollama/__init__.py +0 -0
  230. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/ollama/register_callbacks.py +0 -0
  231. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/ollama_setup/__init__.py +0 -0
  232. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/ollama_setup/completer.py +0 -0
  233. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/ollama_setup/register_callbacks.py +0 -0
  234. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/plugin_list/__init__.py +0 -0
  235. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/plugin_list/plugin_contributions.py +0 -0
  236. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/plugin_list/plugin_meta.py +0 -0
  237. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/plugin_list/plugin_text_utils.py +0 -0
  238. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/plugin_list/plugins_menu.py +0 -0
  239. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/plugin_list/plugins_menu_render.py +0 -0
  240. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/plugin_list/project_trust_flow.py +0 -0
  241. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/plugin_list/register_callbacks.py +0 -0
  242. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/pop_command/__init__.py +0 -0
  243. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/pop_command/register_callbacks.py +0 -0
  244. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/prompt_newline/__init__.py +0 -0
  245. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/prompt_newline/config.py +0 -0
  246. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/prompt_newline/register_callbacks.py +0 -0
  247. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/prune/__init__.py +0 -0
  248. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/prune/prune_menu.py +0 -0
  249. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/prune/prune_model.py +0 -0
  250. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/prune/prune_render.py +0 -0
  251. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/prune/register_callbacks.py +0 -0
  252. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/puppy_kennel/README.md +0 -0
  253. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/puppy_kennel/__init__.py +0 -0
  254. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/puppy_kennel/commands.py +0 -0
  255. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/puppy_kennel/config.py +0 -0
  256. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/puppy_kennel/kennel.py +0 -0
  257. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/puppy_kennel/packer.py +0 -0
  258. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/puppy_kennel/recorder.py +0 -0
  259. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/puppy_kennel/register_callbacks.py +0 -0
  260. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/puppy_kennel/retriever.py +0 -0
  261. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/puppy_kennel/schema.py +0 -0
  262. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/puppy_kennel/state.py +0 -0
  263. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/puppy_kennel/tools.py +0 -0
  264. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/puppy_kennel/wings.py +0 -0
  265. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/puppy_spinner/README.md +0 -0
  266. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/puppy_spinner/__init__.py +0 -0
  267. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/puppy_spinner/builtin_frames.py +0 -0
  268. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/puppy_spinner/commands.py +0 -0
  269. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/puppy_spinner/picker.py +0 -0
  270. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/puppy_spinner/register_callbacks.py +0 -0
  271. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/puppy_spinner/spinners.py +0 -0
  272. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/qa_kitten_skill/SKILL.md +0 -0
  273. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/qa_kitten_skill/__init__.py +0 -0
  274. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/qa_kitten_skill/register_callbacks.py +0 -0
  275. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/quick_resume/__init__.py +0 -0
  276. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/quick_resume/register_callbacks.py +0 -0
  277. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/review_pr/__init__.py +0 -0
  278. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/review_pr/register_callbacks.py +0 -0
  279. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/session_namer/__init__.py +0 -0
  280. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/session_namer/namer.py +0 -0
  281. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/session_namer/register_callbacks.py +0 -0
  282. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/shell_safety/__init__.py +0 -0
  283. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/shell_safety/agent_shell_safety.py +0 -0
  284. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/shell_safety/command_cache.py +0 -0
  285. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/shell_safety/register_callbacks.py +0 -0
  286. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/spill/LICENSE.deepseek +0 -0
  287. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/spill/__init__.py +0 -0
  288. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/spill/register_callbacks.py +0 -0
  289. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/spill/store.py +0 -0
  290. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/stack_dump/__init__.py +0 -0
  291. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/stack_dump/register_callbacks.py +0 -0
  292. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/statusline/__init__.py +0 -0
  293. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/statusline/config.py +0 -0
  294. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/statusline/payload.py +0 -0
  295. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/statusline/prompt_patch.py +0 -0
  296. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/statusline/register_callbacks.py +0 -0
  297. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/statusline/runner.py +0 -0
  298. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/statusline/statusline_command.py +0 -0
  299. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/steer_queue/__init__.py +0 -0
  300. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/steer_queue/queue_menu.py +0 -0
  301. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/steer_queue/register_callbacks.py +0 -0
  302. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/subagent_panel/README.md +0 -0
  303. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/subagent_panel/__init__.py +0 -0
  304. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/subagent_panel/coalesce_patch.py +0 -0
  305. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/subagent_panel/panel_render.py +0 -0
  306. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/subagent_panel/register_callbacks.py +0 -0
  307. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/subagent_panel/resume_repaint.py +0 -0
  308. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/subagent_panel/state.py +0 -0
  309. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/switch_agent_resume/__init__.py +0 -0
  310. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/switch_agent_resume/register_callbacks.py +0 -0
  311. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/termflow_tui.py +0 -0
  312. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/theme/README.md +0 -0
  313. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/theme/__init__.py +0 -0
  314. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/theme/bundled_palettes.py +0 -0
  315. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/theme/content_styles.py +0 -0
  316. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/theme/osc_palette.py +0 -0
  317. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/theme/picker.py +0 -0
  318. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/theme/prompt_toolkit_theme.py +0 -0
  319. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/theme/register_callbacks.py +0 -0
  320. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/theme/rich_themes.py +0 -0
  321. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/theme/themes.py +0 -0
  322. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/timestamp_heartbeat/__init__.py +0 -0
  323. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/timestamp_heartbeat/register_callbacks.py +0 -0
  324. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/token_ratio_learner/__init__.py +0 -0
  325. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/token_ratio_learner/ratios.py +0 -0
  326. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/token_ratio_learner/register_callbacks.py +0 -0
  327. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/universal_constructor/__init__.py +0 -0
  328. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/universal_constructor/models.py +0 -0
  329. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/universal_constructor/provider.py +0 -0
  330. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/universal_constructor/register_callbacks.py +0 -0
  331. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/universal_constructor/registry.py +0 -0
  332. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/universal_constructor/sandbox.py +0 -0
  333. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/web_retriever_skill/SKILL.md +0 -0
  334. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/web_retriever_skill/__init__.py +0 -0
  335. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/web_retriever_skill/register_callbacks.py +0 -0
  336. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/wiggum/__init__.py +0 -0
  337. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/wiggum/goal_runs.py +0 -0
  338. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/wiggum/judge.py +0 -0
  339. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/wiggum/judge_config.py +0 -0
  340. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/wiggum/judges_menu.py +0 -0
  341. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/wiggum/register_callbacks.py +0 -0
  342. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/wiggum/state.py +0 -0
  343. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/yolo_cli/__init__.py +0 -0
  344. {code_puppy_core_plugins-0.0.26 → code_puppy_core_plugins-0.0.27}/code_puppy_core_plugins/yolo_cli/register_callbacks.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: code-puppy-core-plugins
3
- Version: 0.0.26
3
+ Version: 0.0.27
4
4
  Summary: Official plugin bundle for Code Puppy
5
5
  Project-URL: Repository, https://github.com/mpfaffenberger/code_puppy_core_plugins
6
6
  Project-URL: Homepage, https://github.com/mpfaffenberger/code_puppy_core_plugins
@@ -0,0 +1,6 @@
1
+ """OpenRouter OAuth PKCE plugin.
2
+
3
+ One-click browser sign-in that exchanges an authorization code for a
4
+ user-controlled OpenRouter API key, wired into the ``/add_model`` flow via
5
+ the ``provider_credential_flow`` hook.
6
+ """
@@ -0,0 +1,21 @@
1
+ """Configuration for the OpenRouter OAuth PKCE flow.
2
+
3
+ OpenRouter's flow is deliberately simple: no client id, no scopes, no
4
+ refresh tokens. The authorization code is exchanged at ``keys_url`` for a
5
+ user-controlled API key. Localhost callbacks are supported on any port, so
6
+ we bind an ephemeral one. See https://openrouter.ai/docs/use-cases/oauth-pkce
7
+ """
8
+
9
+ from __future__ import annotations
10
+
11
+ OPENROUTER_OAUTH_CONFIG = {
12
+ "auth_url": "https://openrouter.ai/auth",
13
+ "keys_url": "https://openrouter.ai/api/v1/auth/keys",
14
+ "env_var": "OPENROUTER_API_KEY",
15
+ "provider_id": "openrouter",
16
+ "redirect_host": "localhost",
17
+ "redirect_path": "/callback",
18
+ # OpenRouter authorization codes are single-use and expire after 10
19
+ # minutes; give the user most of that window.
20
+ "callback_timeout": 540,
21
+ }
@@ -0,0 +1,242 @@
1
+ """OpenRouter OAuth PKCE flow.
2
+
3
+ Follows https://openrouter.ai/docs/use-cases/oauth-pkce: send the user to
4
+ ``/auth`` with an S256 code challenge, receive the authorization code on a
5
+ localhost callback (any port is allowed), then exchange code + verifier at
6
+ ``/api/v1/auth/keys`` for a user-controlled API key. There is no state
7
+ parameter in OpenRouter's flow -- PKCE is the integrity mechanism, and the
8
+ code is single-use with a 10 minute expiry.
9
+
10
+ The key is persisted via :func:`code_puppy.provider_credentials.save_credential`
11
+ so it is immediately usable by the model factory (puppy.cfg + os.environ).
12
+ """
13
+
14
+ from __future__ import annotations
15
+
16
+ import base64
17
+ import hashlib
18
+ import secrets
19
+ import threading
20
+ import time
21
+ import urllib.parse
22
+ from http.server import BaseHTTPRequestHandler, HTTPServer
23
+ from typing import Any, Tuple
24
+
25
+ import requests
26
+
27
+ from code_puppy.messaging import emit_error, emit_info, emit_success, emit_warning
28
+ from code_puppy.provider_credentials import save_credential
29
+
30
+ from ..oauth_pasteback import parse_oauth_callback_input, read_available_stdin_line
31
+ from ..oauth_puppy_html import oauth_failure_html, oauth_success_html
32
+ from .config import OPENROUTER_OAUTH_CONFIG
33
+
34
+
35
+ def generate_pkce_pair() -> Tuple[str, str]:
36
+ """Return an S256 ``(code_verifier, code_challenge)`` pair."""
37
+ verifier = secrets.token_urlsafe(64)
38
+ digest = hashlib.sha256(verifier.encode("ascii")).digest()
39
+ challenge = base64.urlsafe_b64encode(digest).rstrip(b"=").decode("ascii")
40
+ return verifier, challenge
41
+
42
+
43
+ def exchange_code_for_key(code: str, code_verifier: str) -> str:
44
+ """Exchange an authorization code for a user-controlled API key.
45
+
46
+ Raises on HTTP errors or a malformed response so callers can surface
47
+ the failure; returns the API key on success.
48
+ """
49
+ response = requests.post(
50
+ OPENROUTER_OAUTH_CONFIG["keys_url"],
51
+ json={
52
+ "code": code,
53
+ "code_verifier": code_verifier,
54
+ "code_challenge_method": "S256",
55
+ },
56
+ timeout=30,
57
+ )
58
+ response.raise_for_status()
59
+ key = response.json().get("key")
60
+ if not key:
61
+ raise RuntimeError("OpenRouter response did not include an API key")
62
+ return key
63
+
64
+
65
+ def _save_key(key: str) -> None:
66
+ save_credential(OPENROUTER_OAUTH_CONFIG["env_var"], key)
67
+
68
+
69
+ class _OAuthServer(HTTPServer):
70
+ """Localhost callback server holding the state for one OAuth attempt."""
71
+
72
+ def __init__(self) -> None:
73
+ host = OPENROUTER_OAUTH_CONFIG["redirect_host"]
74
+ # OpenRouter explicitly supports localhost callbacks on any port.
75
+ super().__init__((host, 0), _CallbackHandler)
76
+
77
+ self.exit_code = 1
78
+ self.code_verifier, self.code_challenge = generate_pkce_pair()
79
+ port = self.server_address[1]
80
+ path = OPENROUTER_OAUTH_CONFIG["redirect_path"]
81
+ self.callback_url = f"http://{host}:{port}{path}"
82
+
83
+ def auth_url(self) -> str:
84
+ params = {
85
+ "callback_url": self.callback_url,
86
+ "code_challenge": self.code_challenge,
87
+ "code_challenge_method": "S256",
88
+ }
89
+ return f"{OPENROUTER_OAUTH_CONFIG['auth_url']}?{urllib.parse.urlencode(params)}"
90
+
91
+ def exchange_code(self, code: str) -> None:
92
+ _save_key(exchange_code_for_key(code, self.code_verifier))
93
+
94
+
95
+ class _CallbackHandler(BaseHTTPRequestHandler):
96
+ server: "_OAuthServer"
97
+
98
+ def do_GET(self) -> None: # noqa: N802
99
+ parsed = urllib.parse.urlparse(self.path)
100
+ if parsed.path != OPENROUTER_OAUTH_CONFIG["redirect_path"]:
101
+ self._send_failure(404, "Callback endpoint not found for the puppy parade.")
102
+ return
103
+
104
+ params = urllib.parse.parse_qs(parsed.query)
105
+ error = params.get("error", [None])[0]
106
+ if error:
107
+ description = params.get("error_description", [error])[0]
108
+ self._send_failure(400, f"OpenRouter authorization failed: {description}")
109
+ self._shutdown_after_delay()
110
+ return
111
+
112
+ code = params.get("code", [None])[0]
113
+ if not code:
114
+ self._send_failure(400, "Missing auth code — the token treat rolled away.")
115
+ self._shutdown_after_delay()
116
+ return
117
+
118
+ try:
119
+ self.server.exchange_code(code)
120
+ except Exception as exc: # noqa: BLE001
121
+ self._send_failure(500, f"Key exchange failed: {exc}")
122
+ self._shutdown_after_delay()
123
+ return
124
+
125
+ self.server.exit_code = 0
126
+ self._send_html(
127
+ oauth_success_html(
128
+ "OpenRouter",
129
+ "You can now close this window and return to Code Puppy.",
130
+ )
131
+ )
132
+ self._shutdown_after_delay()
133
+
134
+ def log_message(self, fmt: str, *args: Any) -> None: # noqa: A003
135
+ pass
136
+
137
+ def _send_html(self, body: str, status: int = 200) -> None:
138
+ encoded = body.encode("utf-8")
139
+ self.send_response(status)
140
+ self.send_header("Content-Type", "text/html; charset=utf-8")
141
+ self.send_header("Content-Length", str(len(encoded)))
142
+ self.end_headers()
143
+ self.wfile.write(encoded)
144
+
145
+ def _send_failure(self, status: int, reason: str) -> None:
146
+ self._send_html(oauth_failure_html("OpenRouter", reason), status)
147
+
148
+ def _shutdown_after_delay(self, seconds: float = 2.0) -> None:
149
+ def _later() -> None:
150
+ time.sleep(seconds)
151
+ self.server.shutdown()
152
+
153
+ threading.Thread(target=_later, daemon=True).start()
154
+
155
+
156
+ def _complete_pasted_input(raw_input: str, code_verifier: str) -> bool:
157
+ """Exchange a pasted callback URL / bare code for an API key."""
158
+ try:
159
+ parsed = parse_oauth_callback_input(raw_input)
160
+ except ValueError as exc:
161
+ emit_error(f"Could not parse pasted OAuth input: {exc}")
162
+ return False
163
+
164
+ if parsed.error:
165
+ emit_error(f"OpenRouter returned an error: {parsed.error_message}")
166
+ return False
167
+ if not parsed.code:
168
+ emit_error("Pasted OAuth input did not contain an authorization code.")
169
+ return False
170
+
171
+ try:
172
+ _save_key(exchange_code_for_key(parsed.code, code_verifier))
173
+ except Exception as exc: # noqa: BLE001
174
+ emit_error(f"Key exchange failed: {exc}")
175
+ return False
176
+ return True
177
+
178
+
179
+ def _wait_for_completion(server: _OAuthServer) -> bool:
180
+ """Poll for the localhost callback, accepting pasted input meanwhile."""
181
+ emit_info(
182
+ "Waiting for the OpenRouter callback. If localhost cannot be reached "
183
+ "(SSH, container), paste the full callback URL or authorization code "
184
+ "here and press Enter."
185
+ )
186
+
187
+ elapsed = 0.0
188
+ timeout = OPENROUTER_OAUTH_CONFIG["callback_timeout"]
189
+ interval = 0.25
190
+ while elapsed < timeout:
191
+ if server.exit_code == 0:
192
+ return True
193
+
194
+ pasted = read_available_stdin_line()
195
+ if pasted is not None and pasted.strip():
196
+ if _complete_pasted_input(pasted, server.code_verifier):
197
+ return True
198
+
199
+ time.sleep(interval)
200
+ elapsed += interval
201
+ return False
202
+
203
+
204
+ def run_oauth_flow() -> bool:
205
+ """Run the browser PKCE flow. Returns True when a key was saved."""
206
+ try:
207
+ server = _OAuthServer()
208
+ except Exception as exc: # noqa: BLE001
209
+ emit_error(f"Could not start OpenRouter OAuth flow: {exc}")
210
+ return False
211
+
212
+ auth_url = server.auth_url()
213
+ emit_info(f"Open this URL in your browser: {auth_url}")
214
+
215
+ server_thread = threading.Thread(target=server.serve_forever, daemon=True)
216
+ server_thread.start()
217
+
218
+ from code_puppy.tools.common import should_suppress_browser
219
+
220
+ if should_suppress_browser():
221
+ emit_info(f"[HEADLESS MODE] Would normally open: {auth_url}")
222
+ else:
223
+ try:
224
+ import webbrowser
225
+
226
+ if not webbrowser.open(auth_url):
227
+ emit_warning("Please open the URL manually — the browser stayed home.")
228
+ except Exception as exc: # noqa: BLE001
229
+ emit_warning(f"Could not open browser automatically: {exc}")
230
+
231
+ completed = _wait_for_completion(server)
232
+
233
+ server.shutdown()
234
+ server_thread.join(timeout=5)
235
+
236
+ if not completed:
237
+ emit_error("OpenRouter authentication failed or timed out.")
238
+ return False
239
+
240
+ env_var = OPENROUTER_OAUTH_CONFIG["env_var"]
241
+ emit_success(f"OpenRouter OAuth complete — API key saved as {env_var}.")
242
+ return True
@@ -0,0 +1,93 @@
1
+ """OpenRouter OAuth plugin callbacks.
2
+
3
+ Hooks into the ``/add_model`` credential step: when the user adds an
4
+ OpenRouter model and ``OPENROUTER_API_KEY`` is not set, offer the one-click
5
+ browser PKCE sign-in before falling back to manual key entry.
6
+ """
7
+
8
+ from __future__ import annotations
9
+
10
+ import logging
11
+ from typing import Optional
12
+
13
+ from code_puppy.callbacks import register_callback
14
+
15
+ from .config import OPENROUTER_OAUTH_CONFIG
16
+
17
+ logger = logging.getLogger(__name__)
18
+
19
+ _OAUTH = "oauth"
20
+ _MANUAL = "manual"
21
+
22
+
23
+ def _themed(builder):
24
+ """Apply the app menu theme when the host exposes it."""
25
+ try:
26
+ from code_puppy.command_line.tui_style import themed
27
+ except Exception: # noqa: BLE001 - older cores; unthemed menus still work
28
+ return builder
29
+ return themed(builder)
30
+
31
+
32
+ def build_choice_menu(**overrides):
33
+ """Menu offering browser sign-in vs manual key entry."""
34
+ from termflow.tui import MenuBuilder, MenuItem
35
+
36
+ env_var = OPENROUTER_OAUTH_CONFIG["env_var"]
37
+ builder = _themed(
38
+ MenuBuilder(f"OpenRouter needs {env_var}")
39
+ .items(
40
+ [
41
+ MenuItem(
42
+ "Sign in with OpenRouter (browser)",
43
+ value=_OAUTH,
44
+ description="OAuth PKCE — mints a key for you",
45
+ ),
46
+ MenuItem(
47
+ "Paste an API key manually",
48
+ value=_MANUAL,
49
+ description="Get one at https://openrouter.ai/keys",
50
+ ),
51
+ ]
52
+ )
53
+ .alt_screen(False)
54
+ .footer_hint("Enter select - Esc enter key manually")
55
+ )
56
+ for name, value in overrides.items():
57
+ getattr(builder, name)(value)
58
+ return builder.build()
59
+
60
+
61
+ def choose_flow(**overrides) -> str:
62
+ """Ask how to acquire the key. Esc/cancel defers to manual entry."""
63
+ result = build_choice_menu(**overrides).run()
64
+ if result.cancelled or result.item is None:
65
+ return _MANUAL
66
+ return result.item.value
67
+
68
+
69
+ def _credential_flow(*, provider_id: str, env_var: str) -> Optional[bool]:
70
+ """``provider_credential_flow`` hook: OpenRouter browser sign-in.
71
+
72
+ Returns True when a key was obtained and saved; None to defer to the
73
+ core manual-entry prompt (wrong provider, user preference, or a failed
74
+ OAuth attempt).
75
+ """
76
+ if (
77
+ provider_id != OPENROUTER_OAUTH_CONFIG["provider_id"]
78
+ or env_var != OPENROUTER_OAUTH_CONFIG["env_var"]
79
+ ):
80
+ return None
81
+ if choose_flow() != _OAUTH:
82
+ return None
83
+
84
+ from .oauth_flow import run_oauth_flow
85
+
86
+ return True if run_oauth_flow() else None
87
+
88
+
89
+ try:
90
+ register_callback("provider_credential_flow", _credential_flow)
91
+ except ValueError:
92
+ # Older core without the hook: stay quiet, /add_model still works manually.
93
+ logger.debug("Core lacks provider_credential_flow; openrouter_oauth inactive")
@@ -0,0 +1,263 @@
1
+ """Tests for the OpenRouter OAuth PKCE plugin."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import base64
6
+ import hashlib
7
+ import threading
8
+ import urllib.error
9
+ import urllib.parse
10
+ import urllib.request
11
+ from io import StringIO
12
+ from unittest.mock import MagicMock, patch
13
+
14
+ import pytest
15
+
16
+ from code_puppy_core_plugins.openrouter_oauth import oauth_flow, register_callbacks
17
+ from code_puppy_core_plugins.openrouter_oauth.config import OPENROUTER_OAUTH_CONFIG
18
+
19
+
20
+ # -- PKCE --------------------------------------------------------------------
21
+
22
+
23
+ class TestPkce:
24
+ def test_challenge_is_s256_of_verifier(self):
25
+ verifier, challenge = oauth_flow.generate_pkce_pair()
26
+ expected = (
27
+ base64.urlsafe_b64encode(hashlib.sha256(verifier.encode()).digest())
28
+ .rstrip(b"=")
29
+ .decode()
30
+ )
31
+ assert challenge == expected
32
+ assert "=" not in challenge
33
+
34
+ def test_pairs_are_unique(self):
35
+ assert oauth_flow.generate_pkce_pair() != oauth_flow.generate_pkce_pair()
36
+
37
+
38
+ # -- code -> key exchange ----------------------------------------------------
39
+
40
+
41
+ class TestExchange:
42
+ def _response(self, payload, status=200):
43
+ response = MagicMock()
44
+ response.json.return_value = payload
45
+ if status >= 400:
46
+ response.raise_for_status.side_effect = Exception(f"HTTP {status}")
47
+ return response
48
+
49
+ def test_success_returns_key(self):
50
+ with patch.object(oauth_flow.requests, "post") as mock_post:
51
+ mock_post.return_value = self._response({"key": "sk-or-v1-abc"})
52
+ key = oauth_flow.exchange_code_for_key("code123", "verifier456")
53
+ assert key == "sk-or-v1-abc"
54
+ _, kwargs = mock_post.call_args
55
+ assert kwargs["json"] == {
56
+ "code": "code123",
57
+ "code_verifier": "verifier456",
58
+ "code_challenge_method": "S256",
59
+ }
60
+ assert mock_post.call_args[0][0] == OPENROUTER_OAUTH_CONFIG["keys_url"]
61
+
62
+ def test_missing_key_raises(self):
63
+ with patch.object(oauth_flow.requests, "post") as mock_post:
64
+ mock_post.return_value = self._response({"nope": True})
65
+ with pytest.raises(RuntimeError, match="did not include an API key"):
66
+ oauth_flow.exchange_code_for_key("code", "verifier")
67
+
68
+ def test_http_error_propagates(self):
69
+ with patch.object(oauth_flow.requests, "post") as mock_post:
70
+ mock_post.return_value = self._response({}, status=403)
71
+ with pytest.raises(Exception, match="HTTP 403"):
72
+ oauth_flow.exchange_code_for_key("code", "verifier")
73
+
74
+
75
+ # -- localhost callback server -----------------------------------------------
76
+
77
+
78
+ class TestCallbackServer:
79
+ def _serve(self):
80
+ server = oauth_flow._OAuthServer()
81
+ thread = threading.Thread(target=server.serve_forever, daemon=True)
82
+ thread.start()
83
+ return server, thread
84
+
85
+ def _get(self, url):
86
+ try:
87
+ with urllib.request.urlopen(url, timeout=5) as response:
88
+ return response.status
89
+ except urllib.error.HTTPError as exc:
90
+ return exc.code
91
+
92
+ def test_auth_url_contains_callback_and_challenge(self):
93
+ server = oauth_flow._OAuthServer()
94
+ try:
95
+ url = server.auth_url()
96
+ assert url.startswith(OPENROUTER_OAUTH_CONFIG["auth_url"])
97
+ assert urllib.parse.quote(server.callback_url, safe="") in url
98
+ assert "code_challenge_method=S256" in url
99
+ finally:
100
+ server.server_close()
101
+
102
+ def test_callback_with_code_saves_key(self):
103
+ server, thread = self._serve()
104
+ try:
105
+ with (
106
+ patch.object(oauth_flow, "exchange_code_for_key") as mock_exchange,
107
+ patch.object(oauth_flow, "save_credential") as mock_save,
108
+ ):
109
+ mock_exchange.return_value = "sk-or-v1-abc"
110
+ status = self._get(f"{server.callback_url}?code=authcode")
111
+ assert status == 200
112
+ assert server.exit_code == 0
113
+ mock_exchange.assert_called_once_with("authcode", server.code_verifier)
114
+ mock_save.assert_called_once_with(
115
+ OPENROUTER_OAUTH_CONFIG["env_var"], "sk-or-v1-abc"
116
+ )
117
+ finally:
118
+ server.shutdown()
119
+ thread.join(timeout=5)
120
+
121
+ def test_callback_missing_code_fails(self):
122
+ server, thread = self._serve()
123
+ try:
124
+ assert self._get(server.callback_url) == 400
125
+ assert server.exit_code == 1
126
+ finally:
127
+ server.shutdown()
128
+ thread.join(timeout=5)
129
+
130
+ def test_callback_wrong_path_404s(self):
131
+ server, thread = self._serve()
132
+ try:
133
+ host, port = server.server_address[:2]
134
+ assert self._get(f"http://{host}:{port}/nope?code=x") == 404
135
+ finally:
136
+ server.shutdown()
137
+ thread.join(timeout=5)
138
+
139
+ def test_callback_provider_error_fails(self):
140
+ server, thread = self._serve()
141
+ try:
142
+ status = self._get(
143
+ f"{server.callback_url}?error=access_denied"
144
+ "&error_description=user+said+no"
145
+ )
146
+ assert status == 400
147
+ assert server.exit_code == 1
148
+ finally:
149
+ server.shutdown()
150
+ thread.join(timeout=5)
151
+
152
+
153
+ # -- pasted input ------------------------------------------------------------
154
+
155
+
156
+ class TestPastedInput:
157
+ def test_full_url_paste_exchanges_code(self):
158
+ with (
159
+ patch.object(oauth_flow, "exchange_code_for_key") as mock_exchange,
160
+ patch.object(oauth_flow, "save_credential") as mock_save,
161
+ ):
162
+ mock_exchange.return_value = "sk-or-v1-abc"
163
+ ok = oauth_flow._complete_pasted_input(
164
+ "http://localhost:5555/callback?code=pasted", "verifier"
165
+ )
166
+ assert ok is True
167
+ mock_exchange.assert_called_once_with("pasted", "verifier")
168
+ mock_save.assert_called_once()
169
+
170
+ def test_error_paste_fails(self):
171
+ ok = oauth_flow._complete_pasted_input(
172
+ "?error=access_denied&error_description=nope", "verifier"
173
+ )
174
+ assert ok is False
175
+
176
+ def test_exchange_failure_reported(self):
177
+ with patch.object(oauth_flow, "exchange_code_for_key") as mock_exchange:
178
+ mock_exchange.side_effect = RuntimeError("boom")
179
+ assert oauth_flow._complete_pasted_input("barecode", "verifier") is False
180
+
181
+
182
+ # -- credential-flow hook ----------------------------------------------------
183
+
184
+
185
+ class TestCredentialFlowHook:
186
+ def test_ignores_other_providers(self):
187
+ with patch.object(register_callbacks, "choose_flow") as mock_choose:
188
+ assert (
189
+ register_callbacks._credential_flow(
190
+ provider_id="acme", env_var="ACME_API_KEY"
191
+ )
192
+ is None
193
+ )
194
+ mock_choose.assert_not_called()
195
+
196
+ def test_ignores_other_env_vars(self):
197
+ with patch.object(register_callbacks, "choose_flow") as mock_choose:
198
+ assert (
199
+ register_callbacks._credential_flow(
200
+ provider_id="openrouter", env_var="SOMETHING_ELSE"
201
+ )
202
+ is None
203
+ )
204
+ mock_choose.assert_not_called()
205
+
206
+ def test_manual_choice_defers(self):
207
+ with (
208
+ patch.object(register_callbacks, "choose_flow", return_value="manual"),
209
+ patch.object(oauth_flow, "run_oauth_flow") as mock_run,
210
+ ):
211
+ assert (
212
+ register_callbacks._credential_flow(
213
+ provider_id="openrouter", env_var="OPENROUTER_API_KEY"
214
+ )
215
+ is None
216
+ )
217
+ mock_run.assert_not_called()
218
+
219
+ def test_oauth_success_returns_true(self):
220
+ with (
221
+ patch.object(register_callbacks, "choose_flow", return_value="oauth"),
222
+ patch.object(oauth_flow, "run_oauth_flow", return_value=True),
223
+ ):
224
+ assert (
225
+ register_callbacks._credential_flow(
226
+ provider_id="openrouter", env_var="OPENROUTER_API_KEY"
227
+ )
228
+ is True
229
+ )
230
+
231
+ def test_oauth_failure_defers_to_manual(self):
232
+ with (
233
+ patch.object(register_callbacks, "choose_flow", return_value="oauth"),
234
+ patch.object(oauth_flow, "run_oauth_flow", return_value=False),
235
+ ):
236
+ assert (
237
+ register_callbacks._credential_flow(
238
+ provider_id="openrouter", env_var="OPENROUTER_API_KEY"
239
+ )
240
+ is None
241
+ )
242
+
243
+
244
+ # -- choice menu (headless) --------------------------------------------------
245
+
246
+
247
+ class TestChoiceMenu:
248
+ def _keys(self, *keys):
249
+ script = iter(keys)
250
+ return {
251
+ "key_source": lambda: next(script),
252
+ "output": StringIO(),
253
+ "size": lambda: (90, 20),
254
+ }
255
+
256
+ def test_enter_selects_oauth(self):
257
+ assert register_callbacks.choose_flow(**self._keys("enter")) == "oauth"
258
+
259
+ def test_down_enter_selects_manual(self):
260
+ assert register_callbacks.choose_flow(**self._keys("down", "enter")) == "manual"
261
+
262
+ def test_escape_defers_to_manual(self):
263
+ assert register_callbacks.choose_flow(**self._keys("escape")) == "manual"
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "code-puppy-core-plugins"
7
- version = "0.0.26"
7
+ version = "0.0.27"
8
8
  description = "Official plugin bundle for Code Puppy"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.11,<3.15"
@@ -64,6 +64,7 @@ no_tools = "code_puppy_core_plugins.no_tools.register_callbacks"
64
64
  obsidian_agent = "code_puppy_core_plugins.obsidian_agent.register_callbacks"
65
65
  ollama = "code_puppy_core_plugins.ollama.register_callbacks"
66
66
  ollama_setup = "code_puppy_core_plugins.ollama_setup.register_callbacks"
67
+ openrouter_oauth = "code_puppy_core_plugins.openrouter_oauth.register_callbacks"
67
68
  plugin_list = "code_puppy_core_plugins.plugin_list.register_callbacks"
68
69
  pop_command = "code_puppy_core_plugins.pop_command.register_callbacks"
69
70
  prompt_newline = "code_puppy_core_plugins.prompt_newline.register_callbacks"