Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion RELEASE_NOTES.md
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
Added support for org-wide network egress allow list configuration
## Other Changes
- General stability and compatibility improvements across CLI commands, routing, and template generation components.
2 changes: 1 addition & 1 deletion dispatch_cli/commands/agent.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
import pathspec
import requests
import typer
from dispatch_agents.models import AgentContainerStatus
from dispatch_agents._models import AgentContainerStatus
from rich.console import Console
from rich.progress import (
BarColumn,
Expand Down
2 changes: 1 addition & 1 deletion dispatch_cli/commands/router.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@

import requests
import typer
from dispatch_agents.models import TopicMessage
from dispatch_agents._models import TopicMessage

from dispatch_cli.logger import get_logger
from dispatch_cli.utils import LOCAL_ROUTER_PORT, LOCAL_ROUTER_URL
Expand Down
2 changes: 1 addition & 1 deletion dispatch_cli/mcp/agent/tools.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
import sys
from typing import Any

from dispatch_agents.invocation import InvocationStatus
from dispatch_agents._invocation import InvocationStatus

from mcp.server.lowlevel import Server
from mcp.types import TASK_REQUIRED, CallToolResult, TextContent, Tool
Expand Down
6 changes: 4 additions & 2 deletions dispatch_cli/mcp/operator/tools.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,10 @@
import signal
import subprocess
from pathlib import Path
from typing import Any
from typing import Any, Literal, TypeAlias

import aiohttp
import httpx
from dispatch_agents import FeedbackSentiment, FeedbackType
from pydantic import BaseModel, Field

from dispatch_cli.utils import (
Expand All @@ -20,6 +19,9 @@
from mcp.server.fastmcp import Context, FastMCP
from mcp.server.session import ServerSession

FeedbackType: TypeAlias = Literal["bug", "feature_request", "general"]
FeedbackSentiment: TypeAlias = Literal["positive", "negative"]

from ..client import OperatorBackendClient
from ..config import MCPConfig
from ..models import (
Expand Down
2 changes: 1 addition & 1 deletion dispatch_cli/registry.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
from datetime import UTC, datetime
from pathlib import Path

from dispatch_agents.models import Agent, AgentContainerStatus
from dispatch_agents._models import Agent, AgentContainerStatus

REGISTRY_PATH = Path.home() / ".dispatch_agents" / "default" / "registry.db"
REGISTRY_PATH.parent.mkdir(parents=True, exist_ok=True)
Expand Down
38 changes: 2 additions & 36 deletions dispatch_cli/router/service.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
service_pb2_grpc,
)
from dispatch_agents import LLMToolCall
from dispatch_agents.models import (
from dispatch_agents._models import (
EventRequest,
FunctionMessage,
InvokeFunctionRequest,
Expand Down Expand Up @@ -307,7 +307,7 @@ class InvocationStatus:
ERROR = "error"


# InvokeFunctionRequest is imported from dispatch_agents.models (SDK)
# InvokeFunctionRequest is imported from dispatch_agents._models (SDK)
# to ensure API consistency between SDK, backend, and local router


Expand Down Expand Up @@ -651,40 +651,6 @@ async def subscribe(body: SubscriptionBody, request: Request):
)


@api_router.post("/events/unsubscribe", response_model=SubscriptionResponse)
async def unsubscribe(body: SubscriptionBody):
"""Backend-compatible unsubscribe endpoint."""
if not body.topics or not body.agent_name:
raise HTTPException(
status_code=400, detail="Both topics and agent_name are required"
)

topics = [t for t in set(body.topics) if isinstance(t, str) and t.strip()]
remaining_counts: dict[str, int] = {}

async with _subscriptions_lock:
for topic in topics:
if (
topic in _subscriptions_by_topic
and body.agent_name in _subscriptions_by_topic[topic]
):
_subscriptions_by_topic[topic].discard(body.agent_name)
if not _subscriptions_by_topic[topic]:
_subscriptions_by_topic.pop(topic)
remaining_counts[topic] = 0
else:
remaining_counts[topic] = len(_subscriptions_by_topic[topic])
else:
remaining_counts[topic] = len(_subscriptions_by_topic.get(topic, set()))

return SubscriptionResponse(
message="Unsubscribed",
topics=topics,
agent_name=body.agent_name,
subscribers=remaining_counts,
)


async def route_message_to_agents_with_invocations(
topic: str, message: Message
) -> list[str]:
Expand Down
23 changes: 1 addition & 22 deletions dispatch_cli/router/static/components.js

Large diffs are not rendered by default.

6 changes: 4 additions & 2 deletions dispatch_cli/templates/extract_schemas.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,9 @@
print(f"[extract_schemas] Set {key.strip()}")

# Import SDK functions
from dispatch_agents import BasePayload, Message, get_handler_schemas
from dispatch_agents import BasePayload
from dispatch_agents._models import Message
from dispatch_agents.events import _get_handler_schemas


def extract_schemas_and_compliance():
Expand All @@ -65,7 +67,7 @@ def extract_schemas_and_compliance():
__import__(module_name)

# Get all handler schemas (both @on and @fn handlers)
handler_schemas = get_handler_schemas()
handler_schemas = _get_handler_schemas()

schemas = {}
compliance_issues = []
Expand Down
12 changes: 6 additions & 6 deletions dispatch_cli/templates/grpc_listener.py
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ def _start_llm_proxy(agent_config: dict) -> None:

# Start proxy in a daemon thread (avoids macOS multiprocessing spawn issues)
def _run_proxy():
from dispatch_agents.proxy.server import run_server
from dispatch_agents._proxy.server import run_server

run_server(port=proxy_port)

Expand Down Expand Up @@ -199,7 +199,7 @@ def _run_proxy():
os.environ.setdefault("DISPATCH_AGENT_NAME", AGENT_NAME)

# Enable auto-instrumentation (patches httpx/requests for trace headers)
from dispatch_agents.instrument import auto_instrument
from dispatch_agents._instrument import auto_instrument

auto_instrument()

Expand Down Expand Up @@ -227,10 +227,10 @@ def _run_proxy():
print(f"Successfully imported entrypoint: {entrypoint_file}", flush=True)

# Import from dispatch_agents to verify registration
from dispatch_agents.events import REGISTERED_HANDLERS, TOPIC_HANDLERS
from dispatch_agents.events import _REGISTERED_HANDLERS, _TOPIC_HANDLERS

print(f"Registered handlers: {list(REGISTERED_HANDLERS.keys())}", flush=True)
print(f"Topic triggers: {list(TOPIC_HANDLERS.keys())}", flush=True)
print(f"Registered handlers: {list(_REGISTERED_HANDLERS.keys())}", flush=True)
print(f"Topic triggers: {list(_TOPIC_HANDLERS.keys())}", flush=True)
else:
print(f"Warning: Entrypoint file not found: {entrypoint_path}", flush=True)
raise FileNotFoundError(f"Entrypoint file not found: {entrypoint_path}")
Expand All @@ -242,7 +242,7 @@ def _run_proxy():

async def main(port=50051):
"""Start the gRPC server for the agent."""
from dispatch_agents.grpc_server import serve
from dispatch_agents._grpc_server import serve

logger.info(f"Starting gRPC server for agent '{AGENT_NAME}'...")

Expand Down
5 changes: 3 additions & 2 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
[project]
name = "dispatch-cli"
version = "0.9.6"
version = "0.10.0"
description = ""
authors = [
{name = "Diamond Bishop", email = "diamond.bishop@datadoghq.com"},
{name = "Matt Pillari", email = "matthew.pillari@datadoghq.com"},
{name = "Jacob LeGrone", email = "jacob.legrone@datadoghq.com"}
{name = "Jacob LeGrone", email = "jacob.legrone@datadoghq.com"},
{name = "Jack Burns", email = "jack.burns@datadoghq.com"}
]
readme = "README.md"
requires-python = ">=3.11"
Expand Down
Loading
Loading