yugapurush commited on
Commit
bbb25bf
·
1 Parent(s): 0fbe5c9

Closer to dday

Browse files
Files changed (3) hide show
  1. README.md +2 -0
  2. app.py +5 -212
  3. requirements.txt +5 -2
README.md CHANGED
@@ -8,6 +8,8 @@ sdk_version: 5.33.0
8
  app_file: app.py
9
  pinned: false
10
  short_description: 'MCP-based AI agent for Dolibarr ERP '
 
 
11
  ---
12
 
13
  Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
8
  app_file: app.py
9
  pinned: false
10
  short_description: 'MCP-based AI agent for Dolibarr ERP '
11
+ - agent-demo-track
12
+ - mcp-server-track
13
  ---
14
 
15
  Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
app.py CHANGED
@@ -1,215 +1,8 @@
1
  import gradio as gr
2
- import requests
3
- import json
4
- import asyncio
5
- import logging
6
- from typing import Dict, List, Any, Optional
7
 
8
- # Set up logging to help debug issues
9
- logging.basicConfig(level=logging.INFO)
10
- logger = logging.getLogger(__name__)
11
 
12
- class DolibarrAPI:
13
- base_url = "http://localhost/dolibarr/api/index.php"
14
-
15
- def __init__(self, api_key: str):
16
- """
17
- Just a constructor, sets up the api key and some other stuff
18
-
19
- Args:
20
- api_key (str): Dolibarr user api key
21
- """
22
- self.api_key = "OKgV53jdbT1p1tKuZrB05eK9z0p9I2YX"
23
- self.headers = {
24
- 'DOLAPIKEY': api_key,
25
- 'Content-Type': 'application/json',
26
- 'Accept': 'application/json'
27
- }
28
-
29
- def _request(self, method: str, endpoint: str, data: Optional[dict] = None, params: Optional[dict] = None) -> Any:
30
- """
31
- basic method used for making http request to Dolibarr api
32
-
33
- Args:
34
- method (str): The type of HTTP - GET, POST, PUT, DELETE,etc
35
- endpoint (str): api endpoint based on the request type - "/invoice" , "/thirdparties",etc
36
- data (Optional[dict]) : data to be sent in request body, dictionary
37
- params (Optional[dict]) : dictionary of params to be sent with this request (for GET)
38
- """
39
-
40
- base_url = "http://localhost/dolibarr/api/index.php"
41
- url = f"{base_url}{endpoint}"
42
-
43
- try:
44
- response = requests.request(method, url, headers=self.headers, json=data, params=params)
45
- response.raise_for_status()
46
- return response.json()
47
- except requests.exceptions.RequestException as e:
48
- logger.error(f"API request failed: {e}")
49
- return {"error": f"API request failed: {str(e)}"}
50
- except json.JSONDecodeError as e:
51
- logger.error(f"JSON decode error: {e}")
52
- return {"error": f"Invalid JSON response: {str(e)}"}
53
-
54
- # --- GET REQUESTS ------
55
- def get_req(self, endpoint: str, params: Optional[dict] = None):
56
- return self._request('GET', endpoint, params=params)
57
-
58
- # --- POST requests -----
59
- def post_req(self, endpoint: str, params: dict):
60
- return self._request("POST", endpoint, data=params)
61
-
62
- # --- PUT requests ----
63
- def put_req(self, endpoint: str, params: dict):
64
- return self._request("PUT", endpoint, data=params)
65
-
66
- # --- DELETE requests ----
67
- def del_req(self, endpoint: str, params: Optional[dict] = None):
68
- return self._request("DELETE", endpoint, params=params)
69
-
70
- def dolibarr_interface(method: str, endpoint: str, api_key="OKgV53jdbT1p1tKuZrB05eK9z0p9I2YX", payload_str: str = "") -> str:
71
- """
72
- To orchestrate the API call from start to finish based on simple string and dictionary inputs
73
-
74
- Args:
75
- method (str): http method type ( GET, POST, PUT, DELETE,etc)
76
- endpoint (str): api endpoint, basically which api to call (/invoices, /thirdparties,/products,etc)
77
- api_key : dolibarr api key
78
- payload_str (str): payload as JSON string to send as request body
79
- """
80
-
81
- try:
82
- api = DolibarrAPI(api_key)
83
- method = method.upper()
84
-
85
- # Parse payload if provided
86
- payload = None
87
- if payload_str and payload_str.strip():
88
- try:
89
- payload = json.loads(payload_str)
90
- except json.JSONDecodeError as e:
91
- return json.dumps({"error": f"Invalid JSON payload: {str(e)}"}, indent=2)
92
-
93
- if method == 'GET':
94
- result = api.get_req(endpoint, payload)
95
- elif method == 'POST':
96
- if not payload:
97
- return json.dumps({"error": "POST requests require a payload"}, indent=2)
98
- result = api.post_req(endpoint, payload)
99
- elif method == 'PUT':
100
- if not payload:
101
- return json.dumps({"error": "PUT requests require a payload"}, indent=2)
102
- result = api.put_req(endpoint, payload)
103
- elif method == 'DELETE':
104
- result = api.del_req(endpoint, payload)
105
- else:
106
- return json.dumps({"error": f"Invalid HTTP method '{method}' selected."}, indent=2)
107
-
108
- cleaned = clean_json_response(result)
109
- return json.dumps(cleaned, indent=2)
110
-
111
- except Exception as e:
112
- logger.error(f"Unexpected error in dolibarr_interface: {e}")
113
- return json.dumps({"error": f"Unexpected error: {str(e)}"}, indent=2)
114
-
115
- def clean_json_response(data: Any) -> Any:
116
- """
117
- Recursively clean JSON response by removing null values, empty strings, and empty collections.
118
-
119
- Args:
120
- data: The data to clean (can be dict, list, or primitive type)
121
-
122
- Returns:
123
- Cleaned data with null values and empty collections removed
124
- """
125
- if isinstance(data, dict):
126
- return {
127
- k: clean_json_response(v)
128
- for k, v in data.items()
129
- if v is not None and v != "" and clean_json_response(v) is not None
130
- }
131
- elif isinstance(data, list):
132
- cleaned = [clean_json_response(item) for item in data]
133
- return [item for item in cleaned if item is not None and item != ""]
134
- else:
135
- return data
136
-
137
- # Create the Gradio interface with better error handling
138
- def create_interface():
139
- """Create and return the Gradio interface"""
140
-
141
- demo = gr.Interface(
142
- fn=dolibarr_interface,
143
- inputs=[
144
- gr.Dropdown(
145
- choices=["GET", "POST", "PUT", "DELETE"],
146
- label="HTTP Method",
147
- value="GET"
148
- ),
149
- gr.Dropdown(
150
- choices=["/thirdparties", "/invoices", "/products", "/contacts", "/users"],
151
- label="API Endpoint",
152
- value="/thirdparties",
153
- allow_custom_value=True
154
- ),
155
- gr.Textbox(
156
- label="API Key",
157
- value="OKgV53jdbT1p1tKuZrB05eK9z0p9I2YX"
158
- ),
159
- gr.Textbox(
160
- label="Payload (JSON format)",
161
- placeholder='{"ref": "PROD-001", "label": "Product Name", "price": "99.99"}'
162
- )
163
- ],
164
- outputs=gr.Textbox(
165
- label="API Response",
166
- #lines=10
167
- ),
168
- title="Dolibarr AI Agent/Personal ERP Assistant",
169
- description="Interact with your Dolibarr ERP system through API calls. Select method, endpoint, and provide JSON payload for POST/PUT requests.",
170
- examples=[
171
- ["GET", "/thirdparties", "OKgV53jdbT1p1tKuZrB05eK9z0p9I2YX", ""],
172
- ["POST", "/products", "OKgV53jdbT1p1tKuZrB05eK9z0p9I2YX", '{"ref": "PROD-007", "label": "New AI-Powered Gadget", "price": "199.99", "tva_tx": "20.0"}']
173
- ]
174
- )
175
-
176
- return demo
177
-
178
- # Main execution with better MCP server handling
179
- if __name__ == '__main__':
180
- try:
181
- demo = create_interface()
182
-
183
- logger.info("starting gradio app...")
184
- demo.launch()
185
-
186
- except Exception as e:
187
- logger.error(f"Failed to start application: {e}")
188
- print(f"Error starting application: {e}")
189
-
190
-
191
-
192
-
193
-
194
-
195
- #----- Example usage ----
196
- # Uncomment these lines to test the API functionality directly
197
-
198
- # # Test basic API calling
199
- # print("Testing API connection...")
200
- # list_result = dolibarr_interface(method='GET', endpoint='/thirdparties')
201
- # print("Thirdparties list:", list_result)
202
-
203
- # # Test creating a product
204
- # new_product_data = {
205
- # "ref": "PROD-007",
206
- # "label": "New AI-Powered Gadget",
207
- # "price": "199.99",
208
- # "tva_tx": "20.0"
209
- # }
210
- # create_result = dolibarr_interface(
211
- # method='POST',
212
- # endpoint='/products',
213
- # payload_str=json.dumps(new_product_data)
214
- # )
215
- # print("Product creation result:", create_result)
 
1
  import gradio as gr
2
+ from doli4 import create_openai_agent_interface
 
 
 
 
3
 
4
+ # Create and launch the interface
5
+ demo = create_openai_agent_interface()
 
6
 
7
+ # For Hugging Face Spaces
8
+ demo.launch()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
requirements.txt CHANGED
@@ -1,2 +1,5 @@
1
- gradio==5.31.0
2
-
 
 
 
 
1
+ gradio
2
+ openai
3
+ python-dotenv
4
+ requests
5
+ anthropic