semanticapi-cli 0.1.0__tar.gz
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.
- semanticapi_cli-0.1.0/LICENSE +21 -0
- semanticapi_cli-0.1.0/PKG-INFO +115 -0
- semanticapi_cli-0.1.0/README.md +88 -0
- semanticapi_cli-0.1.0/pyproject.toml +42 -0
- semanticapi_cli-0.1.0/semanticapi_cli/__init__.py +12 -0
- semanticapi_cli-0.1.0/semanticapi_cli/__main__.py +9 -0
- semanticapi_cli-0.1.0/semanticapi_cli/api.py +129 -0
- semanticapi_cli-0.1.0/semanticapi_cli/cli.py +476 -0
- semanticapi_cli-0.1.0/semanticapi_cli/config.py +101 -0
- semanticapi_cli-0.1.0/semanticapi_cli/output.py +355 -0
- semanticapi_cli-0.1.0/semanticapi_cli.egg-info/PKG-INFO +115 -0
- semanticapi_cli-0.1.0/semanticapi_cli.egg-info/SOURCES.txt +14 -0
- semanticapi_cli-0.1.0/semanticapi_cli.egg-info/dependency_links.txt +1 -0
- semanticapi_cli-0.1.0/semanticapi_cli.egg-info/entry_points.txt +2 -0
- semanticapi_cli-0.1.0/semanticapi_cli.egg-info/top_level.txt +1 -0
- semanticapi_cli-0.1.0/setup.cfg +4 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Peter Thompson / Cove AI
|
|
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,115 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: semanticapi-cli
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: CLI for Semantic API — discover and query 700+ APIs with natural language
|
|
5
|
+
Author-email: Peter Thompson <peter@coveai.dev>
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://semanticapi.dev
|
|
8
|
+
Project-URL: Documentation, https://semanticapi.dev/docs
|
|
9
|
+
Project-URL: Repository, https://github.com/peter-j-thompson/semanticapi-cli
|
|
10
|
+
Project-URL: Issues, https://github.com/peter-j-thompson/semanticapi-cli/issues
|
|
11
|
+
Keywords: api,cli,semantic,discovery,mcp,ai-agents
|
|
12
|
+
Classifier: Development Status :: 4 - Beta
|
|
13
|
+
Classifier: Environment :: Console
|
|
14
|
+
Classifier: Intended Audience :: Developers
|
|
15
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
16
|
+
Classifier: Programming Language :: Python :: 3
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
21
|
+
Classifier: Topic :: Software Development :: Libraries
|
|
22
|
+
Classifier: Topic :: Internet :: WWW/HTTP
|
|
23
|
+
Requires-Python: >=3.9
|
|
24
|
+
Description-Content-Type: text/markdown
|
|
25
|
+
License-File: LICENSE
|
|
26
|
+
Dynamic: license-file
|
|
27
|
+
|
|
28
|
+
# Semantic API CLI
|
|
29
|
+
|
|
30
|
+
Query 700+ APIs with natural language from your terminal. Zero dependencies.
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
pip install semanticapi
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
## Quick Start
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
# Save your API key
|
|
40
|
+
semanticapi config set-key sapi_your_key
|
|
41
|
+
|
|
42
|
+
# Query any API
|
|
43
|
+
semanticapi query "send an SMS via Twilio"
|
|
44
|
+
|
|
45
|
+
# Pre-check what you'll need (free, no LLM cost)
|
|
46
|
+
semanticapi preflight "send an email"
|
|
47
|
+
|
|
48
|
+
# Discover a provider
|
|
49
|
+
semanticapi discover stripe
|
|
50
|
+
|
|
51
|
+
# Batch queries
|
|
52
|
+
semanticapi batch "send email" "upload file" "translate text"
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
## Commands
|
|
56
|
+
|
|
57
|
+
| Command | Description |
|
|
58
|
+
|---------|-------------|
|
|
59
|
+
| `query` | Natural language API query |
|
|
60
|
+
| `batch` | Multiple queries in one call |
|
|
61
|
+
| `preflight` | Pre-check (free, identifies needed auth) |
|
|
62
|
+
| `discover` | Look up a provider by name |
|
|
63
|
+
| `discover-url` | Discover provider from docs URL |
|
|
64
|
+
| `status` | Show config and API health |
|
|
65
|
+
| `config` | Manage API key and settings |
|
|
66
|
+
|
|
67
|
+
## Authentication
|
|
68
|
+
|
|
69
|
+
API key priority (first found wins):
|
|
70
|
+
|
|
71
|
+
1. `--key sapi_xxx` flag
|
|
72
|
+
2. `SEMANTICAPI_KEY` environment variable
|
|
73
|
+
3. `~/.semanticapi/config.json` (saved via `config set-key`)
|
|
74
|
+
|
|
75
|
+
Get your key at [semanticapi.dev](https://semanticapi.dev).
|
|
76
|
+
|
|
77
|
+
## Output Modes
|
|
78
|
+
|
|
79
|
+
```bash
|
|
80
|
+
# Pretty-printed (default)
|
|
81
|
+
semanticapi query "get weather"
|
|
82
|
+
|
|
83
|
+
# Raw JSON (for piping)
|
|
84
|
+
semanticapi --raw query "get weather"
|
|
85
|
+
|
|
86
|
+
# Minimal output
|
|
87
|
+
semanticapi --quiet query "get weather"
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
## Exit Codes
|
|
91
|
+
|
|
92
|
+
| Code | Meaning |
|
|
93
|
+
|------|---------|
|
|
94
|
+
| 0 | Success |
|
|
95
|
+
| 1 | Error |
|
|
96
|
+
| 2 | Auth required |
|
|
97
|
+
|
|
98
|
+
## What You Get Back
|
|
99
|
+
|
|
100
|
+
Every query returns:
|
|
101
|
+
- **Provider** and endpoint details
|
|
102
|
+
- **Code snippets** (curl + Python) ready to copy-paste
|
|
103
|
+
- **Auth requirements** and setup instructions
|
|
104
|
+
- **Alternative providers** ranked by relevance
|
|
105
|
+
|
|
106
|
+
## Related
|
|
107
|
+
|
|
108
|
+
- [Semantic API](https://semanticapi.dev) — The API
|
|
109
|
+
- [MCP Server](https://pypi.org/project/semanticapi-mcp/) — For Claude Desktop / ChatGPT
|
|
110
|
+
- [Agent Skill](https://pypi.org/project/semantic-api-skill/) — For autonomous agents
|
|
111
|
+
- [Open Source Engine](https://github.com/peter-j-thompson/semanticapi-engine) — AGPL-3.0
|
|
112
|
+
|
|
113
|
+
## License
|
|
114
|
+
|
|
115
|
+
MIT
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
# Semantic API CLI
|
|
2
|
+
|
|
3
|
+
Query 700+ APIs with natural language from your terminal. Zero dependencies.
|
|
4
|
+
|
|
5
|
+
```bash
|
|
6
|
+
pip install semanticapi
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
## Quick Start
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
# Save your API key
|
|
13
|
+
semanticapi config set-key sapi_your_key
|
|
14
|
+
|
|
15
|
+
# Query any API
|
|
16
|
+
semanticapi query "send an SMS via Twilio"
|
|
17
|
+
|
|
18
|
+
# Pre-check what you'll need (free, no LLM cost)
|
|
19
|
+
semanticapi preflight "send an email"
|
|
20
|
+
|
|
21
|
+
# Discover a provider
|
|
22
|
+
semanticapi discover stripe
|
|
23
|
+
|
|
24
|
+
# Batch queries
|
|
25
|
+
semanticapi batch "send email" "upload file" "translate text"
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## Commands
|
|
29
|
+
|
|
30
|
+
| Command | Description |
|
|
31
|
+
|---------|-------------|
|
|
32
|
+
| `query` | Natural language API query |
|
|
33
|
+
| `batch` | Multiple queries in one call |
|
|
34
|
+
| `preflight` | Pre-check (free, identifies needed auth) |
|
|
35
|
+
| `discover` | Look up a provider by name |
|
|
36
|
+
| `discover-url` | Discover provider from docs URL |
|
|
37
|
+
| `status` | Show config and API health |
|
|
38
|
+
| `config` | Manage API key and settings |
|
|
39
|
+
|
|
40
|
+
## Authentication
|
|
41
|
+
|
|
42
|
+
API key priority (first found wins):
|
|
43
|
+
|
|
44
|
+
1. `--key sapi_xxx` flag
|
|
45
|
+
2. `SEMANTICAPI_KEY` environment variable
|
|
46
|
+
3. `~/.semanticapi/config.json` (saved via `config set-key`)
|
|
47
|
+
|
|
48
|
+
Get your key at [semanticapi.dev](https://semanticapi.dev).
|
|
49
|
+
|
|
50
|
+
## Output Modes
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
# Pretty-printed (default)
|
|
54
|
+
semanticapi query "get weather"
|
|
55
|
+
|
|
56
|
+
# Raw JSON (for piping)
|
|
57
|
+
semanticapi --raw query "get weather"
|
|
58
|
+
|
|
59
|
+
# Minimal output
|
|
60
|
+
semanticapi --quiet query "get weather"
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
## Exit Codes
|
|
64
|
+
|
|
65
|
+
| Code | Meaning |
|
|
66
|
+
|------|---------|
|
|
67
|
+
| 0 | Success |
|
|
68
|
+
| 1 | Error |
|
|
69
|
+
| 2 | Auth required |
|
|
70
|
+
|
|
71
|
+
## What You Get Back
|
|
72
|
+
|
|
73
|
+
Every query returns:
|
|
74
|
+
- **Provider** and endpoint details
|
|
75
|
+
- **Code snippets** (curl + Python) ready to copy-paste
|
|
76
|
+
- **Auth requirements** and setup instructions
|
|
77
|
+
- **Alternative providers** ranked by relevance
|
|
78
|
+
|
|
79
|
+
## Related
|
|
80
|
+
|
|
81
|
+
- [Semantic API](https://semanticapi.dev) — The API
|
|
82
|
+
- [MCP Server](https://pypi.org/project/semanticapi-mcp/) — For Claude Desktop / ChatGPT
|
|
83
|
+
- [Agent Skill](https://pypi.org/project/semantic-api-skill/) — For autonomous agents
|
|
84
|
+
- [Open Source Engine](https://github.com/peter-j-thompson/semanticapi-engine) — AGPL-3.0
|
|
85
|
+
|
|
86
|
+
## License
|
|
87
|
+
|
|
88
|
+
MIT
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=61.0"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "semanticapi-cli"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
description = "CLI for Semantic API — discover and query 700+ APIs with natural language"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
license = {text = "MIT"}
|
|
11
|
+
requires-python = ">=3.9"
|
|
12
|
+
authors = [
|
|
13
|
+
{name = "Peter Thompson", email = "peter@coveai.dev"},
|
|
14
|
+
]
|
|
15
|
+
keywords = ["api", "cli", "semantic", "discovery", "mcp", "ai-agents"]
|
|
16
|
+
classifiers = [
|
|
17
|
+
"Development Status :: 4 - Beta",
|
|
18
|
+
"Environment :: Console",
|
|
19
|
+
"Intended Audience :: Developers",
|
|
20
|
+
"License :: OSI Approved :: MIT License",
|
|
21
|
+
"Programming Language :: Python :: 3",
|
|
22
|
+
"Programming Language :: Python :: 3.9",
|
|
23
|
+
"Programming Language :: Python :: 3.10",
|
|
24
|
+
"Programming Language :: Python :: 3.11",
|
|
25
|
+
"Programming Language :: Python :: 3.12",
|
|
26
|
+
"Topic :: Software Development :: Libraries",
|
|
27
|
+
"Topic :: Internet :: WWW/HTTP",
|
|
28
|
+
]
|
|
29
|
+
|
|
30
|
+
dependencies = []
|
|
31
|
+
|
|
32
|
+
[project.scripts]
|
|
33
|
+
semanticapi = "semanticapi_cli.cli:main"
|
|
34
|
+
|
|
35
|
+
[project.urls]
|
|
36
|
+
Homepage = "https://semanticapi.dev"
|
|
37
|
+
Documentation = "https://semanticapi.dev/docs"
|
|
38
|
+
Repository = "https://github.com/peter-j-thompson/semanticapi-cli"
|
|
39
|
+
Issues = "https://github.com/peter-j-thompson/semanticapi-cli/issues"
|
|
40
|
+
|
|
41
|
+
[tool.setuptools.packages.find]
|
|
42
|
+
include = ["semanticapi_cli*"]
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Semantic API CLI
|
|
3
|
+
================
|
|
4
|
+
|
|
5
|
+
A command-line interface for Semantic API - discover and query APIs with natural language.
|
|
6
|
+
|
|
7
|
+
Usage:
|
|
8
|
+
python -m semanticapi_cli query "send an SMS"
|
|
9
|
+
semanticapi query "send an SMS" --key sapi_your_key
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
__version__ = "0.1.0"
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
"""
|
|
2
|
+
API client for Semantic API CLI.
|
|
3
|
+
|
|
4
|
+
Uses stdlib urllib only - no external dependencies.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import json
|
|
8
|
+
import urllib.request
|
|
9
|
+
import urllib.error
|
|
10
|
+
import urllib.parse
|
|
11
|
+
from typing import Optional, Dict, Any, Tuple
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class APIError(Exception):
|
|
15
|
+
"""Error from Semantic API."""
|
|
16
|
+
def __init__(self, message: str, status_code: int = 0, details: Optional[Dict] = None):
|
|
17
|
+
super().__init__(message)
|
|
18
|
+
self.status_code = status_code
|
|
19
|
+
self.details = details or {}
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class APIClient:
|
|
23
|
+
"""HTTP client for Semantic API."""
|
|
24
|
+
|
|
25
|
+
def __init__(self, base_url: str, api_key: Optional[str] = None):
|
|
26
|
+
self.base_url = base_url.rstrip("/")
|
|
27
|
+
self.api_key = api_key
|
|
28
|
+
|
|
29
|
+
def _request(
|
|
30
|
+
self,
|
|
31
|
+
method: str,
|
|
32
|
+
path: str,
|
|
33
|
+
data: Optional[Dict] = None,
|
|
34
|
+
timeout: int = 60,
|
|
35
|
+
) -> Tuple[int, Dict[str, Any]]:
|
|
36
|
+
"""
|
|
37
|
+
Make HTTP request to API.
|
|
38
|
+
|
|
39
|
+
Returns (status_code, response_json).
|
|
40
|
+
Raises APIError on failure.
|
|
41
|
+
"""
|
|
42
|
+
url = f"{self.base_url}{path}"
|
|
43
|
+
|
|
44
|
+
headers = {
|
|
45
|
+
"Content-Type": "application/json",
|
|
46
|
+
"Accept": "application/json",
|
|
47
|
+
"User-Agent": "semanticapi-cli/0.1.0",
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
if self.api_key:
|
|
51
|
+
headers["Authorization"] = f"Bearer {self.api_key}"
|
|
52
|
+
|
|
53
|
+
body = json.dumps(data).encode("utf-8") if data else None
|
|
54
|
+
|
|
55
|
+
req = urllib.request.Request(url, data=body, headers=headers, method=method)
|
|
56
|
+
|
|
57
|
+
try:
|
|
58
|
+
with urllib.request.urlopen(req, timeout=timeout) as response:
|
|
59
|
+
response_body = response.read().decode("utf-8")
|
|
60
|
+
try:
|
|
61
|
+
return response.status, json.loads(response_body)
|
|
62
|
+
except json.JSONDecodeError:
|
|
63
|
+
return response.status, {"raw": response_body}
|
|
64
|
+
|
|
65
|
+
except urllib.error.HTTPError as e:
|
|
66
|
+
body = e.read().decode("utf-8") if e.fp else ""
|
|
67
|
+
try:
|
|
68
|
+
error_data = json.loads(body)
|
|
69
|
+
detail = error_data.get("detail", str(e))
|
|
70
|
+
except json.JSONDecodeError:
|
|
71
|
+
detail = body or str(e)
|
|
72
|
+
|
|
73
|
+
raise APIError(detail, status_code=e.code, details={"body": body})
|
|
74
|
+
|
|
75
|
+
except urllib.error.URLError as e:
|
|
76
|
+
raise APIError(f"Connection failed: {e.reason}")
|
|
77
|
+
except TimeoutError:
|
|
78
|
+
raise APIError("Request timed out")
|
|
79
|
+
|
|
80
|
+
def query(self, query: str, auto_discover: bool = True) -> Dict[str, Any]:
|
|
81
|
+
"""Execute a natural language query."""
|
|
82
|
+
status, data = self._request("POST", "/api/query", {
|
|
83
|
+
"query": query,
|
|
84
|
+
"auto_discover": auto_discover,
|
|
85
|
+
})
|
|
86
|
+
return data
|
|
87
|
+
|
|
88
|
+
def query_batch(self, queries: list) -> Dict[str, Any]:
|
|
89
|
+
"""Execute multiple queries in one call."""
|
|
90
|
+
status, data = self._request("POST", "/api/query/batch", {
|
|
91
|
+
"queries": queries,
|
|
92
|
+
})
|
|
93
|
+
return data
|
|
94
|
+
|
|
95
|
+
def preflight(self, query: str) -> Dict[str, Any]:
|
|
96
|
+
"""Pre-analyze a query to identify needed providers."""
|
|
97
|
+
status, data = self._request("POST", "/api/query/preflight", {
|
|
98
|
+
"query": query,
|
|
99
|
+
})
|
|
100
|
+
return data
|
|
101
|
+
|
|
102
|
+
def agentic(self, query: str, execution_id: Optional[str] = None) -> Dict[str, Any]:
|
|
103
|
+
"""Execute a query with agentic (execution) mode."""
|
|
104
|
+
payload = {"query": query}
|
|
105
|
+
if execution_id:
|
|
106
|
+
payload["execution_id"] = execution_id
|
|
107
|
+
status, data = self._request("POST", "/api/query/agentic", payload, timeout=120)
|
|
108
|
+
return data
|
|
109
|
+
|
|
110
|
+
def discover(self, provider_name: str, user_intent: Optional[str] = None) -> Dict[str, Any]:
|
|
111
|
+
"""Discover a provider by name."""
|
|
112
|
+
payload = {"provider_name": provider_name}
|
|
113
|
+
if user_intent:
|
|
114
|
+
payload["user_intent"] = user_intent
|
|
115
|
+
status, data = self._request("POST", "/api/discover/search", payload, timeout=60)
|
|
116
|
+
return data
|
|
117
|
+
|
|
118
|
+
def discover_url(self, url: str, user_intent: Optional[str] = None) -> Dict[str, Any]:
|
|
119
|
+
"""Discover a provider from documentation URL."""
|
|
120
|
+
payload = {"url": url}
|
|
121
|
+
if user_intent:
|
|
122
|
+
payload["user_intent"] = user_intent
|
|
123
|
+
status, data = self._request("POST", "/api/discover/from-url", payload, timeout=60)
|
|
124
|
+
return data
|
|
125
|
+
|
|
126
|
+
def health(self) -> Dict[str, Any]:
|
|
127
|
+
"""Get API health status."""
|
|
128
|
+
status, data = self._request("GET", "/api/health")
|
|
129
|
+
return data
|