Compare commits

...

2 Commits

Author SHA1 Message Date
Otto
9d96807737 fix(chat): resolve both graph_id and library_agent_id in edit_agent
Fixes SECRT-1863

The edit_agent tool's schema claims it accepts either a graph ID or library
agent ID, but CoPilot often passes library_agent_id (which it naturally
grabs from context after creating/saving an agent), causing the lookup to
fail.

This adds explicit fallback logic in edit_agent to:
1. First try get_agent_as_json with the ID as-is (treats as graph_id)
2. If not found, try to resolve it as a library_agent_id
3. If found, use the library agent's graph_id to fetch the agent

This makes the schema truthful and improves robustness for CoPilot.
2026-02-02 15:17:33 +00:00
Guofang.Tang
1081590384 feat(backend): cover webhook ingress URL route (#11747)
### Changes 🏗️

- Add a unit test to verify webhook ingress URL generation matches the
FastAPI route.

  ### Checklist 📋

  #### For code changes:

  - [x] I have clearly listed my changes in the PR description
  - [x] I have made a test plan
  - [x] I have tested my changes according to the test plan:
- [x] poetry run pytest backend/integrations/webhooks/utils_test.py
--confcutdir=backend/integrations/webhooks

  #### For configuration changes:

  - [x] .env.default is updated or already compatible with my changes
- [x] docker-compose.yml is updated or already compatible with my
changes
- [x] I have included a list of my configuration changes in the PR
description (under Changes)



<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **Tests**
* Added a unit test that validates webhook ingress URL generation
matches the application's resolved route (scheme, host, and path) for
provider-specific webhook endpoints, improving confidence in routing
behavior and helping prevent regressions.

<sub>✏️ Tip: You can customize this high-level summary in your review
settings.</sub>
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Reinier van der Leer <pwuts@agpt.co>
2026-02-01 20:29:15 +00:00
2 changed files with 52 additions and 0 deletions

View File

@@ -4,6 +4,7 @@ import logging
from typing import Any
from backend.api.features.chat.model import ChatSession
from backend.api.features.library import db as library_db
from .agent_generator import (
AgentGeneratorNotConfiguredError,
@@ -120,6 +121,18 @@ class EditAgentTool(BaseTool):
current_agent = await get_agent_as_json(agent_id, user_id)
# If not found by graph_id, try resolving as library_agent_id
if current_agent is None and user_id:
try:
library_agent = await library_db.get_library_agent(agent_id, user_id)
logger.debug(
f"Resolved library_agent_id '{agent_id}' to graph_id "
f"'{library_agent.graph_id}'"
)
current_agent = await get_agent_as_json(library_agent.graph_id, user_id)
except Exception as e:
logger.debug(f"Could not resolve '{agent_id}' as library_agent_id: {e}")
if current_agent is None:
return ErrorResponse(
message=f"Could not find agent with ID '{agent_id}' in your library.",

View File

@@ -0,0 +1,39 @@
from urllib.parse import urlparse
import fastapi
from fastapi.routing import APIRoute
from backend.api.features.integrations.router import router as integrations_router
from backend.integrations.providers import ProviderName
from backend.integrations.webhooks import utils as webhooks_utils
def test_webhook_ingress_url_matches_route(monkeypatch) -> None:
app = fastapi.FastAPI()
app.include_router(integrations_router, prefix="/api/integrations")
provider = ProviderName.GITHUB
webhook_id = "webhook_123"
base_url = "https://example.com"
monkeypatch.setattr(webhooks_utils.app_config, "platform_base_url", base_url)
route = next(
route
for route in integrations_router.routes
if isinstance(route, APIRoute)
and route.path == "/{provider}/webhooks/{webhook_id}/ingress"
and "POST" in route.methods
)
expected_path = f"/api/integrations{route.path}".format(
provider=provider.value,
webhook_id=webhook_id,
)
actual_url = urlparse(webhooks_utils.webhook_ingress_url(provider, webhook_id))
expected_base = urlparse(base_url)
assert (actual_url.scheme, actual_url.netloc) == (
expected_base.scheme,
expected_base.netloc,
)
assert actual_url.path == expected_path