@thierryteisseire/leadgenius-skill 1.1.1 → 1.1.2

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.
package/SKILL.md CHANGED
@@ -65,6 +65,9 @@ python3 scripts/lgp.py auth --email your@email.com
65
65
  # List leads
66
66
  python3 scripts/lgp.py leads list
67
67
 
68
+ # Find specific leads
69
+ python3 scripts/lgp.py leads find --full-name "Hugo Sanchez"
70
+
68
71
  # Enrich specific leads
69
72
  python3 scripts/lgp.py leads enrich --ids lead_1 lead_2
70
73
  ```
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@thierryteisseire/leadgenius-skill",
3
- "version": "1.1.1",
3
+ "version": "1.1.2",
4
4
  "description": "LeadGenius Pro Agent API Skill for AI agents",
5
5
  "main": "SKILL.md",
6
6
  "repository": {
@@ -3,7 +3,7 @@
3
3
  This document provides a detailed breakdown of all available endpoints in the LeadGenius Pro Agent API.
4
4
 
5
5
  ## Base URL
6
- `https://last.leadgenius.app/api/agent`
6
+ `https://your-domain.com/api/agent`
7
7
 
8
8
  ## Authentication
9
9
  All requests require an API key passed in headers:
@@ -41,7 +41,7 @@ Lifecycle management for marketing and sales leads.
41
41
 
42
42
  ### `GET /leads`
43
43
  List leads with advanced filtering.
44
- - **Filters**: `status`, `campaignId`, `email`, `companyName`.
44
+ - **Filters**: `status`, `campaignId`, `email`, `companyName`, `firstName`, `lastName`, `fullName`.
45
45
  - **Pagination**: `page`, `pageSize` (Default 20, Max 100).
46
46
 
47
47
  ### `POST /leads`
@@ -120,50 +120,3 @@ Manage connections to CRMs (Salesforce, HubSpot) and Mail Platforms.
120
120
 
121
121
  ### `GET /webhooks`
122
122
  Configure event-based real-time notifications.
123
-
124
- ---
125
-
126
- ## 🛠️ Maintenance & System Health
127
- Endpoints for reporting issues and providing feedback.
128
-
129
- ### `GET /maintenance/bugs`
130
- List reported bugs.
131
-
132
- ### `POST /maintenance/bugs`
133
- Report a discovered issue.
134
- - **Body**: `{ description, userEmail }`
135
-
136
- ### `GET /maintenance/enhancements`
137
- List requested enhancements.
138
-
139
- ### `POST /maintenance/enhancements`
140
- Request a new feature.
141
- - **Body**: `{ description, userEmail }`
142
-
143
- ---
144
-
145
- ## 👑 Global Administration (Admin Only)
146
- High-level system management. Requires Master Admin status.
147
- Root Path: `/api/admin`
148
-
149
- ### `GET /companies`
150
- List all organizations currently using the platform.
151
-
152
- ### `GET /users`
153
- Get the global directory of all platform users and their roles.
154
-
155
- ---
156
-
157
- ## 🔑 Authentication & API Keys
158
- ### `POST /epsimo-auth`
159
- Exchange email/password for a JWT token.
160
- - **Root Path**: `/api/epsimo-auth`
161
- - **Body**: `{ email, password }`
162
-
163
- ### `POST /agent-api-keys`
164
- Generate a new persistent API Key.
165
- - **Auth**: Requires JWT (Bearer)
166
- - **Body**: `{ name, description }`
167
-
168
- ### `GET /agent-api-keys`
169
- List active API keys for the current user.
@@ -10,7 +10,7 @@ def main():
10
10
  parser.add_argument("method", choices=["GET", "POST", "PUT", "DELETE"], help="HTTP method")
11
11
  parser.add_argument("endpoint", help="API endpoint (e.g., /leads)")
12
12
  parser.add_argument("--data", help="JSON data for POST/PUT requests")
13
- parser.add_argument("--base-url", default="https://last.leadgenius.app/api/agent", help="Base URL")
13
+ parser.add_argument("--base-url", default="http://localhost:3000/api/agent", help="Base URL")
14
14
  parser.add_argument("--key", help="API Key (defaults to LGP_API_KEY env var)")
15
15
 
16
16
  args = parser.parse_args()
@@ -37,26 +37,8 @@ def main():
37
37
  print("Error: API Key is required. Run 'python3 scripts/auth.py' first, use --key, or set LGP_API_KEY.")
38
38
  sys.exit(1)
39
39
 
40
- # Detect base path
41
- root_base = args.base_url.rstrip('/').replace('/api/agent', '')
42
-
43
- if args.endpoint.startswith('/admin') or args.endpoint.startswith('admin/'):
44
- # Admin routes
45
- base_url = f"{root_base}/api/admin"
46
- clean_endpoint = args.endpoint.replace('/admin/', '').replace('admin/', '').lstrip('/')
47
- elif 'epsimo-auth' in args.endpoint or 'agent-api-keys' in args.endpoint:
48
- # Root API routes
49
- base_url = f"{root_base}/api"
50
- clean_endpoint = args.endpoint.lstrip('/')
51
- else:
52
- # Default Agent routes
53
- base_url = f"{root_base}/api/agent"
54
- clean_endpoint = args.endpoint.lstrip('/')
55
-
56
- url = f"{base_url}/{clean_endpoint}"
57
-
40
+ url = f"{args.base_url.rstrip('/')}/{args.endpoint.lstrip('/')}"
58
41
  headers = {
59
- "Authorization": f"Bearer {api_key}",
60
42
  "X-API-Key": api_key,
61
43
  "Content-Type": "application/json"
62
44
  }
@@ -66,7 +48,6 @@ def main():
66
48
  if args.data:
67
49
  data = json.loads(args.data)
68
50
 
69
- print(f"Calling: {args.method} {url}")
70
51
  response = requests.request(args.method, url, headers=headers, json=data)
71
52
 
72
53
  print(f"Status: {response.status_code}")
package/scripts/auth.py CHANGED
@@ -6,7 +6,7 @@ import requests
6
6
  import sys
7
7
  from getpass import getpass
8
8
 
9
- DEFAULT_BASE_URL = "https://last.leadgenius.app"
9
+ DEFAULT_BASE_URL = "http://localhost:3000"
10
10
  AUTH_FILE = os.path.expanduser("~/.leadgenius_auth.json")
11
11
 
12
12
  def main():
package/scripts/lgp.py CHANGED
@@ -5,9 +5,9 @@ import os
5
5
  import requests
6
6
  import sys
7
7
  from getpass import getpass
8
- from datetime import datetime, timedelta
8
+ from datetime import datetime
9
9
 
10
- DEFAULT_BASE_URL = "https://last.leadgenius.app"
10
+ DEFAULT_BASE_URL = "http://localhost:3000"
11
11
  AUTH_FILE = os.path.expanduser("~/.leadgenius_auth.json")
12
12
 
13
13
  class LeadGeniusCLI:
@@ -32,16 +32,13 @@ class LeadGeniusCLI:
32
32
  pass
33
33
  return None
34
34
 
35
- def _request(self, method, endpoint, data=None, params=None, is_admin=False):
35
+ def _request(self, method, endpoint, data=None, params=None):
36
36
  if not self.token:
37
37
  print("Error: Not authenticated. Set LGP_API_KEY or run 'lgp auth'.")
38
38
  sys.exit(1)
39
39
 
40
- base_path = "/api/admin" if is_admin else "/api/agent"
41
- url = f"{self.base_url}/{base_path.strip('/')}/{endpoint.lstrip('/')}"
42
-
40
+ url = f"{self.base_url}/api/agent/{endpoint.lstrip('/')}"
43
41
  headers = {
44
- "Authorization": f"Bearer {self.token}",
45
42
  "X-API-Key": self.token,
46
43
  "Content-Type": "application/json"
47
44
  }
@@ -63,11 +60,7 @@ class LeadGeniusCLI:
63
60
  print("Make sure LGP_API_KEY is set to a valid API Key.")
64
61
  return None
65
62
  if response.status_code >= 400:
66
- # Silently return so the caller can decide what to print or just print error
67
- if response.status_code == 403:
68
- print(f"Error (403): Master Admin access required for {url}")
69
- else:
70
- print(f"Error ({response.status_code}): {response.text}")
63
+ print(f"Error ({response.status_code}): {response.text}")
71
64
  return None
72
65
  return response.json()
73
66
  except Exception as e:
@@ -161,6 +154,54 @@ class LeadGeniusCLI:
161
154
  if data:
162
155
  print(json.dumps(data, indent=2))
163
156
 
157
+ def find_lead(self, first_name=None, last_name=None, full_name=None, email=None, company=None):
158
+ params = {"pageSize": 100}
159
+ if first_name:
160
+ params["firstName"] = first_name
161
+ if last_name:
162
+ params["lastName"] = last_name
163
+ if full_name:
164
+ params["fullName"] = full_name
165
+ if email:
166
+ params["email"] = email
167
+ if company:
168
+ params["companyName"] = company
169
+ data = self._request("GET", "leads", params=params)
170
+ if data:
171
+ leads = data.get("data", [])
172
+ if not leads:
173
+ print("No leads found matching criteria.")
174
+ return
175
+
176
+ # Client-side filtering (polyfill for server limitation)
177
+ filtered_leads = []
178
+ for lead in leads:
179
+ match = True
180
+ if first_name and first_name.lower() not in (lead.get('firstName') or '').lower(): match = False
181
+ if last_name and last_name.lower() not in (lead.get('lastName') or '').lower(): match = False
182
+ if full_name and full_name.lower() not in (lead.get('fullName') or '').lower(): match = False
183
+ if email and email.lower() not in (lead.get('email') or '').lower(): match = False
184
+ if company and company.lower() not in (lead.get('companyName') or '').lower(): match = False
185
+
186
+ if match:
187
+ filtered_leads.append(lead)
188
+
189
+ if not filtered_leads:
190
+ print("No leads found matching criteria (checked 100 most recent).")
191
+ return
192
+
193
+ print(f"Found {len(filtered_leads)} lead(s):\n")
194
+ for lead in filtered_leads:
195
+ print(f" ID: {lead.get('id')}")
196
+ print(f" Name: {lead.get('fullName') or lead.get('contactName', 'N/A')}")
197
+ print(f" Title: {lead.get('title', 'N/A')}")
198
+ print(f" Company: {lead.get('companyName', 'N/A')}")
199
+ print(f" Email: {lead.get('email', 'N/A')}")
200
+ print(f" LinkedIn: {lead.get('linkedinUrl', 'N/A')}")
201
+ print(f" Location: {lead.get('city', 'N/A')}, {lead.get('country', 'N/A')}")
202
+ print(f" Status: {lead.get('status', 'N/A')}")
203
+ print()
204
+
164
205
  def enrich_leads(self, lead_ids, type="technographic"):
165
206
  payload = {"leadIds": lead_ids, "enrichmentType": type}
166
207
  data = self._request("POST", "enrichment/trigger", data=payload)
@@ -171,12 +212,7 @@ class LeadGeniusCLI:
171
212
  def list_campaigns(self):
172
213
  data = self._request("GET", "campaigns")
173
214
  if data:
174
- # Production uses "data" field for lists
175
- campaigns = data.get("data")
176
- if campaigns is None: # Fallback for local/legacy if applicable
177
- campaigns = data.get("campaigns", [])
178
-
179
- for c in campaigns:
215
+ for c in data.get("campaigns", []):
180
216
  print(f"[{c.get('id')}] {c.get('name')} ({c.get('status')})")
181
217
 
182
218
  def create_campaign(self, name, type="abm"):
@@ -186,7 +222,7 @@ class LeadGeniusCLI:
186
222
  print(f"Campaign created: {data.get('id')}")
187
223
 
188
224
  # Analytics
189
- def show_pipeline(self, start_date, end_date):
225
+ def show_pipeline(self, start_date=None, end_date=None):
190
226
  params = {"startDate": start_date, "endDate": end_date}
191
227
  data = self._request("GET", "analytics/pipeline", params=params)
192
228
  if data:
@@ -220,17 +256,36 @@ class LeadGeniusCLI:
220
256
  enh = data.get('enhancement', {})
221
257
  print(f"Enhancement requested: ID {enh.get('id')}")
222
258
 
223
- # Admin (Master Admin Only)
259
+ # Admin
224
260
  def list_all_companies(self):
225
- data = self._request("GET", "companies", is_admin=True)
226
- if data:
227
- print(json.dumps(data, indent=2))
261
+ # Admin endpoint call attempt
262
+ print("Warning: Admin endpoints require session cookies. This might fail with API Key.")
263
+ url = f"{self.base_url}/api/admin/companies"
264
+ headers = {
265
+ "Content-Type": "application/json",
266
+ # Try passing API Key anyway, maybe backend changes later
267
+ "X-API-Key": self.token
268
+ }
269
+ try:
270
+ response = requests.get(url, headers=headers)
271
+ print(f"Status: {response.status_code}")
272
+ print(response.text)
273
+ except Exception as e:
274
+ print(f"Error: {e}")
228
275
 
229
276
  def list_all_users(self):
230
- data = self._request("GET", "users", is_admin=True)
231
- if data:
232
- print(json.dumps(data, indent=2))
233
-
277
+ print("Warning: Admin endpoints require session cookies. This might fail with API Key.")
278
+ url = f"{self.base_url}/api/admin/users"
279
+ headers = {
280
+ "Content-Type": "application/json",
281
+ "X-API-Key": self.token
282
+ }
283
+ try:
284
+ response = requests.get(url, headers=headers)
285
+ print(f"Status: {response.status_code}")
286
+ print(response.text)
287
+ except Exception as e:
288
+ print(f"Error: {e}")
234
289
 
235
290
  def main():
236
291
  parser = argparse.ArgumentParser(description="LeadGenius Pro Agent CLI")
@@ -248,8 +303,13 @@ def main():
248
303
 
249
304
  # Leads
250
305
  leads_parser = subparsers.add_parser("leads", help="Manage leads")
251
- leads_parser.add_argument("action", choices=["list", "enrich"])
306
+ leads_parser.add_argument("action", choices=["list", "find", "enrich"])
252
307
  leads_parser.add_argument("--ids", nargs="+", help="Lead IDs for enrichment")
308
+ leads_parser.add_argument("--first-name", help="First name filter (for find)")
309
+ leads_parser.add_argument("--last-name", help="Last name filter (for find)")
310
+ leads_parser.add_argument("--full-name", help="Full name search (for find)")
311
+ leads_parser.add_argument("--email", help="Email filter (for find)")
312
+ leads_parser.add_argument("--company", help="Company name filter (for find)")
253
313
 
254
314
  # Campaigns
255
315
  camp_parser = subparsers.add_parser("campaigns", help="Manage campaigns")
@@ -291,6 +351,17 @@ def main():
291
351
  elif args.command == "leads":
292
352
  if args.action == "list":
293
353
  cli.list_leads()
354
+ elif args.action == "find":
355
+ if not any([args.first_name, args.last_name, args.full_name, args.email, args.company]):
356
+ print("Error: provide at least one filter: --first-name, --last-name, --full-name, --email, or --company")
357
+ return
358
+ cli.find_lead(
359
+ first_name=args.first_name,
360
+ last_name=args.last_name,
361
+ full_name=args.full_name,
362
+ email=args.email,
363
+ company=args.company,
364
+ )
294
365
  elif args.action == "enrich":
295
366
  if not args.ids:
296
367
  print("Error: --ids required for enrichment")