dacp 0.1.0__py3-none-any.whl
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.
- dacp/__init__.py +31 -0
- dacp/exceptions.py +0 -0
- dacp/llm.py +19 -0
- dacp/protocol.py +35 -0
- dacp/tools.py +30 -0
- dacp/types.py +0 -0
- dacp-0.1.0.dist-info/METADATA +114 -0
- dacp-0.1.0.dist-info/RECORD +11 -0
- dacp-0.1.0.dist-info/WHEEL +5 -0
- dacp-0.1.0.dist-info/licenses/LICENSE +21 -0
- dacp-0.1.0.dist-info/top_level.txt +1 -0
dacp/__init__.py
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
"""
|
2
|
+
DACP - Declarative Agent Communication Protocol
|
3
|
+
|
4
|
+
A Python library for managing LLM/agent communications and tool function calls
|
5
|
+
following the OAS Open Agent Specification.
|
6
|
+
"""
|
7
|
+
|
8
|
+
from .tools import register_tool, run_tool, TOOL_REGISTRY
|
9
|
+
from .llm import call_llm
|
10
|
+
from .protocol import (
|
11
|
+
parse_agent_response,
|
12
|
+
is_tool_request,
|
13
|
+
get_tool_request,
|
14
|
+
wrap_tool_result,
|
15
|
+
is_final_response,
|
16
|
+
get_final_response,
|
17
|
+
)
|
18
|
+
|
19
|
+
__version__ = "0.1.0"
|
20
|
+
__all__ = [
|
21
|
+
"register_tool",
|
22
|
+
"run_tool",
|
23
|
+
"TOOL_REGISTRY",
|
24
|
+
"call_llm",
|
25
|
+
"parse_agent_response",
|
26
|
+
"is_tool_request",
|
27
|
+
"get_tool_request",
|
28
|
+
"wrap_tool_result",
|
29
|
+
"is_final_response",
|
30
|
+
"get_final_response",
|
31
|
+
]
|
dacp/exceptions.py
ADDED
File without changes
|
dacp/llm.py
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
import os
|
2
|
+
import openai
|
3
|
+
|
4
|
+
|
5
|
+
def call_llm(prompt: str, model: str = "gpt-4") -> str:
|
6
|
+
# Default: OpenAI, can later extend for other LLMs
|
7
|
+
client = openai.OpenAI(
|
8
|
+
api_key=os.getenv("OPENAI_API_KEY"), base_url="https://api.openai.com/v1"
|
9
|
+
)
|
10
|
+
response = client.chat.completions.create(
|
11
|
+
model=model,
|
12
|
+
messages=[{"role": "user", "content": prompt}],
|
13
|
+
temperature=0.7,
|
14
|
+
max_tokens=150,
|
15
|
+
)
|
16
|
+
content = response.choices[0].message.content
|
17
|
+
if content is None:
|
18
|
+
raise ValueError("LLM returned empty response")
|
19
|
+
return content
|
dacp/protocol.py
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
import json
|
2
|
+
from typing import Dict, Any, Union, Tuple, cast
|
3
|
+
|
4
|
+
|
5
|
+
def parse_agent_response(response: Union[str, Dict[str, Any]]) -> Dict[str, Any]:
|
6
|
+
"""
|
7
|
+
Parse the agent/LLM response (as string or dict) and return a dict.
|
8
|
+
"""
|
9
|
+
if isinstance(response, dict):
|
10
|
+
return response
|
11
|
+
try:
|
12
|
+
return cast(Dict[str, Any], json.loads(response))
|
13
|
+
except Exception as e:
|
14
|
+
raise ValueError(f"Malformed agent response: {e}")
|
15
|
+
|
16
|
+
|
17
|
+
def is_tool_request(msg: Dict[str, Any]) -> bool:
|
18
|
+
return "tool_request" in msg
|
19
|
+
|
20
|
+
|
21
|
+
def get_tool_request(msg: Dict[str, Any]) -> Tuple[str, Dict[str, Any]]:
|
22
|
+
req = msg["tool_request"]
|
23
|
+
return req["name"], req.get("args", {})
|
24
|
+
|
25
|
+
|
26
|
+
def wrap_tool_result(name: str, result: Dict[str, Any]) -> Dict[str, Any]:
|
27
|
+
return {"tool_result": {"name": name, "result": result}}
|
28
|
+
|
29
|
+
|
30
|
+
def is_final_response(msg: Dict[str, Any]) -> bool:
|
31
|
+
return "final_response" in msg
|
32
|
+
|
33
|
+
|
34
|
+
def get_final_response(msg: Dict[str, Any]) -> Dict[str, Any]:
|
35
|
+
return cast(Dict[str, Any], msg["final_response"])
|
dacp/tools.py
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
from typing import Dict, Any, Callable
|
2
|
+
|
3
|
+
TOOL_REGISTRY: Dict[str, Callable[..., Dict[str, Any]]] = {}
|
4
|
+
|
5
|
+
|
6
|
+
def register_tool(tool_id: str, func: Callable[..., Dict[str, Any]]) -> None:
|
7
|
+
"""Register a tool function."""
|
8
|
+
TOOL_REGISTRY[tool_id] = func
|
9
|
+
|
10
|
+
|
11
|
+
def run_tool(tool_id: str, args: Dict[str, Any]) -> Dict[str, Any]:
|
12
|
+
"""Run a registered tool with the given arguments."""
|
13
|
+
if tool_id not in TOOL_REGISTRY:
|
14
|
+
raise ValueError(f"Unknown tool: {tool_id}")
|
15
|
+
tool_func = TOOL_REGISTRY[tool_id]
|
16
|
+
return tool_func(**args)
|
17
|
+
|
18
|
+
|
19
|
+
# --- Example tool ---
|
20
|
+
def file_writer(path: str, content: str) -> dict:
|
21
|
+
# Only allow paths in /tmp or ./output for now!
|
22
|
+
allowed_prefixes = ["./output/", "/tmp/"]
|
23
|
+
if not any(path.startswith(prefix) for prefix in allowed_prefixes):
|
24
|
+
raise ValueError("Path not allowed")
|
25
|
+
with open(path, "w") as f:
|
26
|
+
f.write(content)
|
27
|
+
return {"result": f"Written to {path}"}
|
28
|
+
|
29
|
+
|
30
|
+
register_tool("file_writer", file_writer)
|
dacp/types.py
ADDED
File without changes
|
@@ -0,0 +1,114 @@
|
|
1
|
+
Metadata-Version: 2.4
|
2
|
+
Name: dacp
|
3
|
+
Version: 0.1.0
|
4
|
+
Summary: DACP - Declarative Agent Communication Protocol for LLM/agent communications and tool function calls
|
5
|
+
Author-email: Your Name <your.email@example.com>
|
6
|
+
License: MIT
|
7
|
+
Project-URL: Homepage, https://github.com/yourusername/dacp
|
8
|
+
Project-URL: Repository, https://github.com/yourusername/dacp
|
9
|
+
Project-URL: Issues, https://github.com/yourusername/dacp/issues
|
10
|
+
Keywords: llm,agent,tools,openai,communication
|
11
|
+
Classifier: Development Status :: 3 - Alpha
|
12
|
+
Classifier: Intended Audience :: Developers
|
13
|
+
Classifier: License :: OSI Approved :: MIT License
|
14
|
+
Classifier: Programming Language :: Python :: 3
|
15
|
+
Classifier: Programming Language :: Python :: 3.8
|
16
|
+
Classifier: Programming Language :: Python :: 3.9
|
17
|
+
Classifier: Programming Language :: Python :: 3.10
|
18
|
+
Classifier: Programming Language :: Python :: 3.11
|
19
|
+
Classifier: Programming Language :: Python :: 3.12
|
20
|
+
Requires-Python: >=3.8
|
21
|
+
Description-Content-Type: text/markdown
|
22
|
+
License-File: LICENSE
|
23
|
+
Requires-Dist: openai>=1.0.0
|
24
|
+
Provides-Extra: dev
|
25
|
+
Requires-Dist: pytest>=7.0.0; extra == "dev"
|
26
|
+
Requires-Dist: pytest-cov>=4.0.0; extra == "dev"
|
27
|
+
Requires-Dist: black>=22.0.0; extra == "dev"
|
28
|
+
Requires-Dist: flake8>=5.0.0; extra == "dev"
|
29
|
+
Requires-Dist: mypy>=1.0.0; extra == "dev"
|
30
|
+
Requires-Dist: types-requests>=2.28.0; extra == "dev"
|
31
|
+
Dynamic: license-file
|
32
|
+
|
33
|
+
# DACP - Delcarative Agent Communication Protocol
|
34
|
+
|
35
|
+
A Python library for managing LLM/agent communications and tool function calls following the OAS Open Agent Specification.
|
36
|
+
|
37
|
+
## Installation
|
38
|
+
|
39
|
+
```bash
|
40
|
+
pip install -e .
|
41
|
+
```
|
42
|
+
|
43
|
+
## Quick Start
|
44
|
+
|
45
|
+
```python
|
46
|
+
import dacp
|
47
|
+
|
48
|
+
# Register a custom tool
|
49
|
+
def my_custom_tool(param1: str, param2: int) -> dict:
|
50
|
+
return {"result": f"Processed {param1} with {param2}"}
|
51
|
+
|
52
|
+
dacp.register_tool("my_custom_tool", my_custom_tool)
|
53
|
+
|
54
|
+
# Call an LLM
|
55
|
+
response = dacp.call_llm("What is the weather like today?")
|
56
|
+
|
57
|
+
# Parse agent response
|
58
|
+
parsed = dacp.parse_agent_response(response)
|
59
|
+
|
60
|
+
# Check if it's a tool request
|
61
|
+
if dacp.is_tool_request(parsed):
|
62
|
+
tool_name, args = dacp.get_tool_request(parsed)
|
63
|
+
result = dacp.run_tool(tool_name, args)
|
64
|
+
tool_response = dacp.wrap_tool_result(tool_name, result)
|
65
|
+
```
|
66
|
+
|
67
|
+
## Features
|
68
|
+
|
69
|
+
- **Tool Registry**: Register and manage custom tools for LLM agents
|
70
|
+
- **LLM Integration**: Built-in support for OpenAI models (extensible)
|
71
|
+
- **Protocol Parsing**: Parse and validate agent responses
|
72
|
+
- **Tool Execution**: Safe execution of registered tools
|
73
|
+
- **OAS Compliance**: Follows Open Agent Specification standards
|
74
|
+
|
75
|
+
## API Reference
|
76
|
+
|
77
|
+
### Tools
|
78
|
+
|
79
|
+
- `register_tool(tool_id: str, func)`: Register a new tool
|
80
|
+
- `run_tool(tool_id: str, args: Dict) -> dict`: Execute a registered tool
|
81
|
+
- `TOOL_REGISTRY`: Access the current tool registry
|
82
|
+
|
83
|
+
### LLM
|
84
|
+
|
85
|
+
- `call_llm(prompt: str, model: str = "gpt-4") -> str`: Call an LLM with a prompt
|
86
|
+
|
87
|
+
### Protocol
|
88
|
+
|
89
|
+
- `parse_agent_response(response: str | dict) -> dict`: Parse agent response
|
90
|
+
- `is_tool_request(msg: dict) -> bool`: Check if message is a tool request
|
91
|
+
- `get_tool_request(msg: dict) -> tuple[str, dict]`: Extract tool request details
|
92
|
+
- `wrap_tool_result(name: str, result: dict) -> dict`: Wrap tool result for agent
|
93
|
+
- `is_final_response(msg: dict) -> bool`: Check if message is a final response
|
94
|
+
- `get_final_response(msg: dict) -> dict`: Extract final response
|
95
|
+
|
96
|
+
## Development
|
97
|
+
|
98
|
+
```bash
|
99
|
+
# Install development dependencies
|
100
|
+
pip install -e .[dev]
|
101
|
+
|
102
|
+
# Run tests
|
103
|
+
pytest
|
104
|
+
|
105
|
+
# Format code
|
106
|
+
black .
|
107
|
+
|
108
|
+
# Lint code
|
109
|
+
flake8
|
110
|
+
```
|
111
|
+
|
112
|
+
## License
|
113
|
+
|
114
|
+
MIT License
|
@@ -0,0 +1,11 @@
|
|
1
|
+
dacp/__init__.py,sha256=SY-MnntwhtBTXfVVSSEtK6rLBrlOMkWyXhfPvpeJSDo,690
|
2
|
+
dacp/exceptions.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
3
|
+
dacp/llm.py,sha256=doz7mHby2pLf0khX-AVcNo9DE1yZCGLwAzaEUEfTeo0,581
|
4
|
+
dacp/protocol.py,sha256=DVhLTdyDVlAu8ETSEX8trPeycKfMeirHwcWQ8-BY7eA,1026
|
5
|
+
dacp/tools.py,sha256=fkRAnVPgbsOxfphYgevDmrxfIkSF3lliVWAMLThpY68,971
|
6
|
+
dacp/types.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
7
|
+
dacp-0.1.0.dist-info/licenses/LICENSE,sha256=tb5kgUYRypHqAy8wlrJUBSYI5l1SBmawSYHmCC-MVW0,1074
|
8
|
+
dacp-0.1.0.dist-info/METADATA,sha256=Dwm_o_IWbwSdr3QeRFTccyGzwAwNRRQ20eG8g0BX12I,3447
|
9
|
+
dacp-0.1.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
10
|
+
dacp-0.1.0.dist-info/top_level.txt,sha256=Qxy0cy5jl7ttTQoGFlY9LXB6CbSvsekJ2y0P8I7L1zA,5
|
11
|
+
dacp-0.1.0.dist-info/RECORD,,
|
@@ -0,0 +1,21 @@
|
|
1
|
+
MIT License
|
2
|
+
|
3
|
+
Copyright (c) 2024 DACP Contributors
|
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 @@
|
|
1
|
+
dacp
|