cueapi 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.
- cueapi-0.1.0/LICENSE +21 -0
- cueapi-0.1.0/PKG-INFO +74 -0
- cueapi-0.1.0/README.md +53 -0
- cueapi-0.1.0/cueapi/__init__.py +3 -0
- cueapi-0.1.0/cueapi/auth.py +185 -0
- cueapi-0.1.0/cueapi/cli.py +468 -0
- cueapi-0.1.0/cueapi/client.py +77 -0
- cueapi-0.1.0/cueapi/credentials.py +139 -0
- cueapi-0.1.0/cueapi/formatting.py +82 -0
- cueapi-0.1.0/cueapi/quickstart.py +113 -0
- cueapi-0.1.0/cueapi.egg-info/PKG-INFO +74 -0
- cueapi-0.1.0/cueapi.egg-info/SOURCES.txt +17 -0
- cueapi-0.1.0/cueapi.egg-info/dependency_links.txt +1 -0
- cueapi-0.1.0/cueapi.egg-info/entry_points.txt +2 -0
- cueapi-0.1.0/cueapi.egg-info/requires.txt +2 -0
- cueapi-0.1.0/cueapi.egg-info/top_level.txt +1 -0
- cueapi-0.1.0/pyproject.toml +34 -0
- cueapi-0.1.0/setup.cfg +4 -0
- cueapi-0.1.0/setup.py +16 -0
cueapi-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Vector Apps Inc.
|
|
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.
|
cueapi-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: cueapi
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: CLI for CueAPI — Your Agents' Cue to Act. The scheduling API for AI agents.
|
|
5
|
+
Author-email: "Vector Apps Inc." <hello@cueapi.ai>
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: Homepage, https://cueapi.ai
|
|
8
|
+
Project-URL: Repository, https://github.com/govindkavaturi-art/cueapi-cli
|
|
9
|
+
Keywords: cueapi,ai-agents,scheduling,webhook,cron,cli
|
|
10
|
+
Classifier: Development Status :: 4 - Beta
|
|
11
|
+
Classifier: Intended Audience :: Developers
|
|
12
|
+
Classifier: Programming Language :: Python :: 3
|
|
13
|
+
Classifier: Topic :: Software Development :: Libraries
|
|
14
|
+
Classifier: Topic :: Utilities
|
|
15
|
+
Requires-Python: >=3.9
|
|
16
|
+
Description-Content-Type: text/markdown
|
|
17
|
+
License-File: LICENSE
|
|
18
|
+
Requires-Dist: click>=8.0
|
|
19
|
+
Requires-Dist: httpx>=0.27
|
|
20
|
+
Dynamic: license-file
|
|
21
|
+
|
|
22
|
+
# CueAPI CLI
|
|
23
|
+
|
|
24
|
+
The official command-line interface for [CueAPI](https://cueapi.ai) — Your Agents' Cue to Act.
|
|
25
|
+
|
|
26
|
+
CueAPI is a scheduling API for AI agents. Agents register cues (scheduled tasks), CueAPI fires webhooks at the right time. No cron jobs. No infrastructure.
|
|
27
|
+
|
|
28
|
+
## Install
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
pip install cueapi
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
## Quick Start
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
cueapi login
|
|
38
|
+
cueapi quickstart
|
|
39
|
+
cueapi create --name "morning-check" --cron "0 9 * * *" --url https://my-agent.com/webhook
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
## Commands
|
|
43
|
+
|
|
44
|
+
| Command | Description |
|
|
45
|
+
|---|---|
|
|
46
|
+
| `cueapi login` | Authenticate and store API key |
|
|
47
|
+
| `cueapi whoami` | Show current user and plan |
|
|
48
|
+
| `cueapi logout` | Remove local credentials |
|
|
49
|
+
| `cueapi quickstart` | Guided first-cue setup |
|
|
50
|
+
| `cueapi create` | Create a new cue |
|
|
51
|
+
| `cueapi list` | List all cues |
|
|
52
|
+
| `cueapi get <id>` | Get cue details |
|
|
53
|
+
| `cueapi pause <id>` | Pause a cue |
|
|
54
|
+
| `cueapi resume <id>` | Resume a cue |
|
|
55
|
+
| `cueapi delete <id>` | Delete a cue |
|
|
56
|
+
| `cueapi upgrade` | Open billing |
|
|
57
|
+
| `cueapi usage` | Show current usage |
|
|
58
|
+
| `cueapi key regenerate` | Regenerate API key |
|
|
59
|
+
|
|
60
|
+
## Auth
|
|
61
|
+
|
|
62
|
+
Credentials stored in `~/.config/cueapi/credentials.json`.
|
|
63
|
+
|
|
64
|
+
Override: `export CUEAPI_API_KEY=cue_sk_your_key` or `--api-key` flag.
|
|
65
|
+
|
|
66
|
+
## Links
|
|
67
|
+
|
|
68
|
+
- [Website](https://cueapi.ai)
|
|
69
|
+
- [API Reference](https://cueapi.ai/api)
|
|
70
|
+
- [Pricing](https://cueapi.ai/pricing)
|
|
71
|
+
|
|
72
|
+
## License
|
|
73
|
+
|
|
74
|
+
MIT — Built by [Vector Apps Inc.](https://vectorapps.com)
|
cueapi-0.1.0/README.md
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
# CueAPI CLI
|
|
2
|
+
|
|
3
|
+
The official command-line interface for [CueAPI](https://cueapi.ai) — Your Agents' Cue to Act.
|
|
4
|
+
|
|
5
|
+
CueAPI is a scheduling API for AI agents. Agents register cues (scheduled tasks), CueAPI fires webhooks at the right time. No cron jobs. No infrastructure.
|
|
6
|
+
|
|
7
|
+
## Install
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
pip install cueapi
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Quick Start
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
cueapi login
|
|
17
|
+
cueapi quickstart
|
|
18
|
+
cueapi create --name "morning-check" --cron "0 9 * * *" --url https://my-agent.com/webhook
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## Commands
|
|
22
|
+
|
|
23
|
+
| Command | Description |
|
|
24
|
+
|---|---|
|
|
25
|
+
| `cueapi login` | Authenticate and store API key |
|
|
26
|
+
| `cueapi whoami` | Show current user and plan |
|
|
27
|
+
| `cueapi logout` | Remove local credentials |
|
|
28
|
+
| `cueapi quickstart` | Guided first-cue setup |
|
|
29
|
+
| `cueapi create` | Create a new cue |
|
|
30
|
+
| `cueapi list` | List all cues |
|
|
31
|
+
| `cueapi get <id>` | Get cue details |
|
|
32
|
+
| `cueapi pause <id>` | Pause a cue |
|
|
33
|
+
| `cueapi resume <id>` | Resume a cue |
|
|
34
|
+
| `cueapi delete <id>` | Delete a cue |
|
|
35
|
+
| `cueapi upgrade` | Open billing |
|
|
36
|
+
| `cueapi usage` | Show current usage |
|
|
37
|
+
| `cueapi key regenerate` | Regenerate API key |
|
|
38
|
+
|
|
39
|
+
## Auth
|
|
40
|
+
|
|
41
|
+
Credentials stored in `~/.config/cueapi/credentials.json`.
|
|
42
|
+
|
|
43
|
+
Override: `export CUEAPI_API_KEY=cue_sk_your_key` or `--api-key` flag.
|
|
44
|
+
|
|
45
|
+
## Links
|
|
46
|
+
|
|
47
|
+
- [Website](https://cueapi.ai)
|
|
48
|
+
- [API Reference](https://cueapi.ai/api)
|
|
49
|
+
- [Pricing](https://cueapi.ai/pricing)
|
|
50
|
+
|
|
51
|
+
## License
|
|
52
|
+
|
|
53
|
+
MIT — Built by [Vector Apps Inc.](https://vectorapps.com)
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
"""Auth commands: login, logout, whoami, key regenerate."""
|
|
2
|
+
from __future__ import annotations
|
|
3
|
+
|
|
4
|
+
import secrets
|
|
5
|
+
import string
|
|
6
|
+
import time
|
|
7
|
+
import webbrowser
|
|
8
|
+
from typing import Optional
|
|
9
|
+
|
|
10
|
+
import click
|
|
11
|
+
|
|
12
|
+
from cueapi.client import CueAPIClient, UnauthClient
|
|
13
|
+
from cueapi.credentials import (
|
|
14
|
+
get_profile_info,
|
|
15
|
+
remove_all_credentials,
|
|
16
|
+
remove_credentials,
|
|
17
|
+
resolve_api_base,
|
|
18
|
+
save_credentials,
|
|
19
|
+
)
|
|
20
|
+
from cueapi.formatting import echo_error, echo_info, echo_success
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def _generate_device_code() -> str:
|
|
24
|
+
"""Generate a random device code like ABCD-EFGH."""
|
|
25
|
+
chars = string.ascii_uppercase + string.digits
|
|
26
|
+
part1 = "".join(secrets.choice(chars) for _ in range(4))
|
|
27
|
+
part2 = "".join(secrets.choice(chars) for _ in range(4))
|
|
28
|
+
return f"{part1}-{part2}"
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def do_login(api_base: Optional[str] = None, profile: str = "default") -> None:
|
|
32
|
+
"""Run the device code login flow."""
|
|
33
|
+
base = api_base or resolve_api_base(profile=profile)
|
|
34
|
+
device_code = _generate_device_code()
|
|
35
|
+
|
|
36
|
+
with UnauthClient(api_base=base) as client:
|
|
37
|
+
# Step 1: Create device code
|
|
38
|
+
resp = client.post("/auth/device-code", json={"device_code": device_code})
|
|
39
|
+
if resp.status_code != 201:
|
|
40
|
+
error = resp.json().get("detail", {}).get("error", {})
|
|
41
|
+
echo_error(error.get("message", f"Failed to create device code (HTTP {resp.status_code})"))
|
|
42
|
+
return
|
|
43
|
+
|
|
44
|
+
data = resp.json()
|
|
45
|
+
verification_url = data["verification_url"]
|
|
46
|
+
expires_in = data["expires_in"]
|
|
47
|
+
|
|
48
|
+
# Step 2: Open browser
|
|
49
|
+
click.echo("\nOpening browser to authenticate...")
|
|
50
|
+
try:
|
|
51
|
+
webbrowser.open(verification_url)
|
|
52
|
+
except Exception:
|
|
53
|
+
pass
|
|
54
|
+
click.echo(f"If browser doesn't open, visit: {verification_url}\n")
|
|
55
|
+
|
|
56
|
+
# Step 3: Poll
|
|
57
|
+
click.echo("Waiting for authentication...", nl=False)
|
|
58
|
+
deadline = time.time() + expires_in
|
|
59
|
+
while time.time() < deadline:
|
|
60
|
+
time.sleep(2)
|
|
61
|
+
click.echo(".", nl=False)
|
|
62
|
+
|
|
63
|
+
resp = client.post("/auth/device-code/poll", json={"device_code": device_code})
|
|
64
|
+
if resp.status_code != 200:
|
|
65
|
+
continue
|
|
66
|
+
|
|
67
|
+
poll_data = resp.json()
|
|
68
|
+
status = poll_data.get("status")
|
|
69
|
+
|
|
70
|
+
if status == "approved":
|
|
71
|
+
api_key = poll_data["api_key"]
|
|
72
|
+
email = poll_data["email"]
|
|
73
|
+
|
|
74
|
+
# Save credentials
|
|
75
|
+
save_credentials(
|
|
76
|
+
profile=profile,
|
|
77
|
+
data={
|
|
78
|
+
"api_key": api_key,
|
|
79
|
+
"email": email,
|
|
80
|
+
"api_base": base,
|
|
81
|
+
},
|
|
82
|
+
)
|
|
83
|
+
|
|
84
|
+
click.echo()
|
|
85
|
+
echo_success(f"Authenticated as {email}")
|
|
86
|
+
click.echo(f"API key stored in credentials file.\n")
|
|
87
|
+
click.echo(f"Your API key: {api_key}")
|
|
88
|
+
click.echo("(This is the only time your full key will be shown. Save it if you need it elsewhere.)\n")
|
|
89
|
+
click.echo('Run `cueapi quickstart` to create your first cue.')
|
|
90
|
+
return
|
|
91
|
+
|
|
92
|
+
if status == "expired":
|
|
93
|
+
click.echo()
|
|
94
|
+
echo_error("Device code expired. Run `cueapi login` to try again.")
|
|
95
|
+
return
|
|
96
|
+
|
|
97
|
+
click.echo()
|
|
98
|
+
echo_error("Login timed out. Run `cueapi login` to try again.")
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
def do_whoami(
|
|
102
|
+
api_key: Optional[str] = None,
|
|
103
|
+
profile: Optional[str] = None,
|
|
104
|
+
) -> None:
|
|
105
|
+
"""Show current user info."""
|
|
106
|
+
profile_name = profile or "default"
|
|
107
|
+
try:
|
|
108
|
+
with CueAPIClient(api_key=api_key, profile=profile) as client:
|
|
109
|
+
resp = client.get("/auth/me")
|
|
110
|
+
if resp.status_code != 200:
|
|
111
|
+
echo_error(f"Failed to get user info (HTTP {resp.status_code})")
|
|
112
|
+
return
|
|
113
|
+
|
|
114
|
+
data = resp.json()
|
|
115
|
+
|
|
116
|
+
# Get local key prefix
|
|
117
|
+
prof_info = get_profile_info(profile=profile)
|
|
118
|
+
key_display = "***"
|
|
119
|
+
if prof_info and "api_key" in prof_info:
|
|
120
|
+
key_display = prof_info["api_key"][:7] + "..." + prof_info["api_key"][-4:]
|
|
121
|
+
|
|
122
|
+
click.echo()
|
|
123
|
+
echo_info("Email:", data["email"])
|
|
124
|
+
echo_info("Plan:", data["plan"].capitalize())
|
|
125
|
+
echo_info("Active cues:", f"{data['active_cues']} / {data['active_cue_limit']}")
|
|
126
|
+
echo_info("Executions:", f"{data['executions_this_month']} / {data['monthly_execution_limit']} this month")
|
|
127
|
+
echo_info("API key:", key_display)
|
|
128
|
+
echo_info("Profile:", profile_name)
|
|
129
|
+
echo_info("API base:", client.api_base)
|
|
130
|
+
click.echo()
|
|
131
|
+
except click.ClickException:
|
|
132
|
+
click.echo("Not logged in. Run `cueapi login` to authenticate.")
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
def do_logout(profile: str = "default", logout_all: bool = False) -> None:
|
|
136
|
+
"""Remove credentials."""
|
|
137
|
+
if logout_all:
|
|
138
|
+
remove_all_credentials()
|
|
139
|
+
click.echo("Removed all credentials.")
|
|
140
|
+
return
|
|
141
|
+
|
|
142
|
+
email = remove_credentials(profile=profile)
|
|
143
|
+
if email:
|
|
144
|
+
click.echo(f"Removed credentials for {email} ({profile} profile).")
|
|
145
|
+
else:
|
|
146
|
+
click.echo(f"No credentials found for profile '{profile}'.")
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
def do_key_regenerate(
|
|
150
|
+
api_key: Optional[str] = None,
|
|
151
|
+
profile: Optional[str] = None,
|
|
152
|
+
skip_confirm: bool = False,
|
|
153
|
+
) -> None:
|
|
154
|
+
"""Regenerate API key."""
|
|
155
|
+
if not skip_confirm:
|
|
156
|
+
click.echo()
|
|
157
|
+
click.echo(click.style("Warning: ", fg="yellow") + "This will instantly revoke your current API key.")
|
|
158
|
+
click.echo(" All agents using the old key will stop working.\n")
|
|
159
|
+
if not click.confirm("Proceed?"):
|
|
160
|
+
click.echo("Cancelled.")
|
|
161
|
+
return
|
|
162
|
+
|
|
163
|
+
try:
|
|
164
|
+
with CueAPIClient(api_key=api_key, profile=profile) as client:
|
|
165
|
+
resp = client.post("/auth/key/regenerate")
|
|
166
|
+
if resp.status_code != 200:
|
|
167
|
+
echo_error(f"Failed to regenerate key (HTTP {resp.status_code})")
|
|
168
|
+
return
|
|
169
|
+
|
|
170
|
+
data = resp.json()
|
|
171
|
+
new_key = data["api_key"]
|
|
172
|
+
|
|
173
|
+
# Update local credentials
|
|
174
|
+
profile_name = profile or "default"
|
|
175
|
+
prof_info = get_profile_info(profile=profile)
|
|
176
|
+
if prof_info:
|
|
177
|
+
prof_info["api_key"] = new_key
|
|
178
|
+
save_credentials(profile=profile_name, data=prof_info)
|
|
179
|
+
|
|
180
|
+
click.echo()
|
|
181
|
+
click.echo(f"New API key: {new_key}")
|
|
182
|
+
click.echo("(This is the only time this key will be shown.)\n")
|
|
183
|
+
click.echo("Local credentials updated.")
|
|
184
|
+
except click.ClickException as e:
|
|
185
|
+
click.echo(str(e))
|