-
Notifications
You must be signed in to change notification settings - Fork 87
Feat/acp protocol #184
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Feat/acp protocol #184
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,22 @@ | ||
| """ACP Gateway Plugin. | ||
|
|
||
| Exposes Code Puppy as an ACP (Agent Client Protocol) agent using the | ||
| official ``agent-client-protocol`` Python SDK. | ||
|
|
||
| The SDK handles all transport concerns (stdio JSON-RPC, session | ||
| lifecycle, content blocks). This plugin provides the bridge between | ||
| ACP and Code Puppy's pydantic-ai agent system. | ||
|
|
||
| The plugin gracefully degrades — if ``agent-client-protocol`` is not | ||
| installed, Code Puppy starts normally with a warning log. | ||
| """ | ||
|
|
||
| __version__ = "0.2.0" | ||
| __description__ = "ACP Gateway plugin for Code Puppy" | ||
|
|
||
| from code_puppy.plugins.acp_gateway.agent import CodePuppyAgent, run_code_puppy_agent | ||
|
|
||
| __all__ = [ | ||
| "CodePuppyAgent", | ||
| "run_code_puppy_agent", | ||
| ] | ||
|
Comment on lines
+17
to
+22
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chain🏁 Script executed: # First, verify the structure and see if the files exist
git ls-files code_puppy/plugins/acp_gateway/
# Check agent.py for unconditional acp imports
rg -n "from acp import\|import acp" code_puppy/plugins/acp_gateway/agent.py
# Check the __init__.py content
cat -n code_puppy/plugins/acp_gateway/__init__.py
# Check if there's any graceful degradation pattern elsewhere in the plugin
rg -n "gracefully degrade\|optional\|ImportError" code_puppy/plugins/acp_gateway/Repository: mpfaffenberger/code_puppy Length of output: 1172 🏁 Script executed: # Read agent.py to check its imports
cat -n code_puppy/plugins/acp_gateway/agent.py | head -40
# Also check if there's any conditional import guard mechanism in place
rg -B5 -A5 "CodePuppyAgent\|run_code_puppy_agent" code_puppy/plugins/acp_gateway/agent.py | head -50Repository: mpfaffenberger/code_puppy Length of output: 1391 🏁 Script executed: # Check register_callbacks.py to see how this plugin is loaded/registered
cat -n code_puppy/plugins/acp_gateway/register_callbacks.py
# Also check if there's any error handling at the plugin loading level
rg -n "try:|except" code_puppy/plugins/acp_gateway/__init__.py code_puppy/plugins/acp_gateway/register_callbacks.pyRepository: mpfaffenberger/code_puppy Length of output: 4153 🏁 Script executed: # Check how the plugin is imported/loaded in the core system
rg -n "from code_puppy.plugins.acp_gateway import\|import code_puppy.plugins.acp_gateway" --type py
# Check the plugin loading mechanism
fd "plugin" code_puppy/ --type f -e py | head -20
rg -n "plugins\|register_callback" code_puppy/ -t py | grep -i "import\|load" | head -20Repository: mpfaffenberger/code_puppy Length of output: 220 🏁 Script executed: # Check how plugins are discovered and loaded
rg -n "plugins" code_puppy/ -t py --max-count 5 | head -30
# Look at the main entry point or plugin loader
fd -name "*.py" code_puppy/ -type f | xargs grep -l "register_callback\|plugins" | head -10
# Check if register_callbacks.py is auto-discovered
cat -n code_puppy/__init__.py code_puppy/core.py 2>/dev/null | head -50Repository: mpfaffenberger/code_puppy Length of output: 4133 🏁 Script executed: # Look for the plugin loading mechanism
fd "callbacks.py" code_puppy/ -type f
# Check the callbacks module
cat -n code_puppy/callbacks.py | head -80
# Look for where plugins are discovered/loaded
rg -n "discover\|load.*plugin\|import.*plugin" code_puppy/ -t py | grep -v "test" | head -20Repository: mpfaffenberger/code_puppy Length of output: 2860 🏁 Script executed: # Search for where plugins are imported/discovered at startup
rg -n "plugins" code_puppy/ --glob "*.py" | grep -i "import\|load\|discover" | head -30
# Check if there's a plugin discovery mechanism
fd "register_callbacks.py" code_puppy/plugins/
# Look at the main entry point
cat -n code_puppy/command_line/app.py | head -100Repository: mpfaffenberger/code_puppy Length of output: 4316 🏁 Script executed: # Find the main entry point
fd "main.py\|__main__.py\|app.py" code_puppy/ --type f
# Check for plugin auto-discovery
rg -n "pkgutil\|importlib\|namespace\|entry_points" code_puppy/ --glob "*.py" | head -20
# Look at a known plugin's register_callbacks.py to see the pattern
cat -n code_puppy/plugins/claude_code_oauth/register_callbacks.py | head -30Repository: mpfaffenberger/code_puppy Length of output: 1223 🏁 Script executed: # Search for where register_callbacks modules are imported at startup
rg -n "register_callbacks" code_puppy/ --glob "*.py" | grep -v "plugins/" | head -20
# Check if there's a pattern where __init__.py is imported from plugins
rg -n "from code_puppy.plugins\." code_puppy/command_line/ --glob "*.py" 2>/dev/null || echo "No command_line directory"
# Find the entry point
find code_puppy -maxdepth 2 -name "__main__.py" -o -name "main.py" -o -name "cli.py" | head -5
# Check the main CLI entry point
fd "__main__" code_puppy --type fRepository: mpfaffenberger/code_puppy Length of output: 2001 🏁 Script executed: # Check the main entry point
cat -n code_puppy/main.py | head -150
# Check __main__.py
cat -n code_puppy/__main__.pyRepository: mpfaffenberger/code_puppy Length of output: 684 🏁 Script executed: # Check cli_runner.py for plugin loading
cat -n code_puppy/cli_runner.py | head -200Repository: mpfaffenberger/code_puppy Length of output: 8057 🏁 Script executed: # Check code_puppy/plugins/__init__.py to see load_plugin_callbacks
cat -n code_puppy/plugins/__init__.pyRepository: mpfaffenberger/code_puppy Length of output: 8080 🏁 Script executed: # Check if __init__.py is ever imported directly in the codebase
rg -n "from code_puppy.plugins.acp_gateway import\|import code_puppy.plugins.acp_gateway" code_puppy/ --glob "*.py"
# Also check the specific cli_runner import path more closely
sed -n '105,125p' code_puppy/cli_runner.pyRepository: mpfaffenberger/code_puppy Length of output: 954 Wrap the import in The docstring states the plugin "gracefully degrades" when Wrap the import in a try/except so the module remains importable regardless. Per coding guidelines: "Wrap risky operations in try/except blocks in plugin code to ensure a broken plugin never crashes the entire application." Proposed fix+try:
+ from code_puppy.plugins.acp_gateway.agent import CodePuppyAgent, run_code_puppy_agent
+except ImportError:
+ import logging as _logging
+ _logging.getLogger(__name__).warning(
+ "acp-sdk is not installed — ACP Gateway plugin disabled. "
+ "Install with: pip install agent-client-protocol"
+ )
+ CodePuppyAgent = None # type: ignore[assignment,misc]
+ run_code_puppy_agent = None # type: ignore[assignment]
+
-from code_puppy.plugins.acp_gateway.agent import CodePuppyAgent, run_code_puppy_agent
__all__ = [
"CodePuppyAgent",
"run_code_puppy_agent",
]🤖 Prompt for AI Agents |
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,21 @@ | ||
| """Allow running the ACP agent as: python -m code_puppy.plugins.acp_gateway | ||
| All transport concerns (stdio JSON-RPC) are handled by the ACP SDK. | ||
| We just start the CodePuppyAgent and let ``run_agent()`` do the rest. | ||
| """ | ||
|
|
||
| import asyncio | ||
| import logging | ||
| import sys | ||
|
|
||
| from code_puppy.plugins.acp_gateway.agent import run_code_puppy_agent | ||
|
|
||
| # Redirect logging to stderr so stdout stays clean for JSON-RPC | ||
| logging.basicConfig( | ||
| stream=sys.stderr, | ||
| level=logging.INFO, | ||
| format="%(asctime)s [%(name)s] %(levelname)s: %(message)s", | ||
| ) | ||
|
|
||
| if __name__ == "__main__": | ||
| asyncio.run(run_code_puppy_agent()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🏁 Script executed:
Repository: mpfaffenberger/code_puppy
Length of output: 1677
🏁 Script executed:
Repository: mpfaffenberger/code_puppy
Length of output: 2104
Move ACP env var setup before
on_startup()callback.Lines 355-358 set
ACP_ENABLEDandACP_TRANSPORT, but this occurs afterawait callbacks.on_startup()at line 320. The startup callback triggers_on_startup()inregister_callbacks.py, which immediately callsACPConfig.from_env()(line 52) to read these env vars—before they are set. The env vars must be set before line 320 for the HTTP transport startup path to initialize correctly.🤖 Prompt for AI Agents