dailybot-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.
- dailybot_cli-0.1.0/LICENSE +21 -0
- dailybot_cli-0.1.0/PKG-INFO +146 -0
- dailybot_cli-0.1.0/README.md +119 -0
- dailybot_cli-0.1.0/dailybot_cli/__init__.py +3 -0
- dailybot_cli-0.1.0/dailybot_cli/api_client.py +303 -0
- dailybot_cli-0.1.0/dailybot_cli/commands/__init__.py +1 -0
- dailybot_cli-0.1.0/dailybot_cli/commands/agent.py +269 -0
- dailybot_cli-0.1.0/dailybot_cli/commands/auth.py +115 -0
- dailybot_cli-0.1.0/dailybot_cli/commands/config.py +61 -0
- dailybot_cli-0.1.0/dailybot_cli/commands/interactive.py +136 -0
- dailybot_cli-0.1.0/dailybot_cli/commands/status.py +31 -0
- dailybot_cli-0.1.0/dailybot_cli/commands/update.py +91 -0
- dailybot_cli-0.1.0/dailybot_cli/config.py +136 -0
- dailybot_cli-0.1.0/dailybot_cli/display.py +201 -0
- dailybot_cli-0.1.0/dailybot_cli/main.py +55 -0
- dailybot_cli-0.1.0/dailybot_cli.egg-info/PKG-INFO +146 -0
- dailybot_cli-0.1.0/dailybot_cli.egg-info/SOURCES.txt +21 -0
- dailybot_cli-0.1.0/dailybot_cli.egg-info/dependency_links.txt +1 -0
- dailybot_cli-0.1.0/dailybot_cli.egg-info/entry_points.txt +2 -0
- dailybot_cli-0.1.0/dailybot_cli.egg-info/requires.txt +4 -0
- dailybot_cli-0.1.0/dailybot_cli.egg-info/top_level.txt +1 -0
- dailybot_cli-0.1.0/pyproject.toml +42 -0
- dailybot_cli-0.1.0/setup.cfg +4 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 DailyBot
|
|
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,146 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: dailybot-cli
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: DailyBot CLI - Submit check-in updates from your terminal
|
|
5
|
+
Author-email: DailyBot <support@dailybot.com>
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://www.dailybot.com
|
|
8
|
+
Project-URL: Documentation, https://docs.dailybot.com
|
|
9
|
+
Classifier: Development Status :: 3 - Alpha
|
|
10
|
+
Classifier: Environment :: Console
|
|
11
|
+
Classifier: Intended Audience :: Developers
|
|
12
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
13
|
+
Classifier: Programming Language :: Python :: 3
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
18
|
+
Classifier: Topic :: Software Development :: Build Tools
|
|
19
|
+
Requires-Python: >=3.9
|
|
20
|
+
Description-Content-Type: text/markdown
|
|
21
|
+
License-File: LICENSE
|
|
22
|
+
Requires-Dist: click>=8.1.0
|
|
23
|
+
Requires-Dist: httpx>=0.25.0
|
|
24
|
+
Requires-Dist: questionary>=2.0.0
|
|
25
|
+
Requires-Dist: rich>=13.0.0
|
|
26
|
+
Dynamic: license-file
|
|
27
|
+
|
|
28
|
+
# DailyBot CLI
|
|
29
|
+
|
|
30
|
+
A command-line interface for [DailyBot](https://www.dailybot.com) that lets **people** and **software agents** share progress updates, blockers, and feedback — straight from the terminal.
|
|
31
|
+
|
|
32
|
+
Whether you're a developer who lives in the terminal or an AI agent running in a CI pipeline, the DailyBot CLI gives you a fast way to submit check-ins without leaving your workflow.
|
|
33
|
+
|
|
34
|
+
## Installation
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
pip install dailybot-cli
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
Or via the install script:
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
curl -sSL https://cli.dailybot.com/install.sh | bash
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
Requires Python 3.9+.
|
|
47
|
+
|
|
48
|
+
## For humans
|
|
49
|
+
|
|
50
|
+
Authenticate once with your DailyBot email, then submit updates and check pending check-ins right from your terminal.
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
# Log in (one-time setup, email OTP)
|
|
54
|
+
dailybot login
|
|
55
|
+
|
|
56
|
+
# See what check-ins are waiting for you
|
|
57
|
+
dailybot status
|
|
58
|
+
|
|
59
|
+
# Submit a free-text update
|
|
60
|
+
dailybot update "Finished the auth module, starting on tests."
|
|
61
|
+
|
|
62
|
+
# Or use structured fields
|
|
63
|
+
dailybot update --done "Auth module" --doing "Tests" --blocked "None"
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
Run `dailybot` with no arguments to enter **interactive mode** — if you're not logged in yet, it will walk you through authentication first, then let you submit updates step by step.
|
|
67
|
+
|
|
68
|
+
## For agents
|
|
69
|
+
|
|
70
|
+
Any software agent — AI coding assistants, CI jobs, deploy scripts, bots — can report activity through the CLI. This lets teams get visibility into what automated processes are doing, alongside human updates.
|
|
71
|
+
|
|
72
|
+
Authenticate with any of these methods (checked in this order):
|
|
73
|
+
|
|
74
|
+
```bash
|
|
75
|
+
# Option 1: Environment variable (CI pipelines, one-off scripts)
|
|
76
|
+
export DAILYBOT_API_KEY=your-key
|
|
77
|
+
|
|
78
|
+
# Option 2: Store the key on disk (recommended for dev machines)
|
|
79
|
+
dailybot config key=your-key
|
|
80
|
+
|
|
81
|
+
# Option 3: Use your login session (no API key needed)
|
|
82
|
+
dailybot login
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
Then run agent commands:
|
|
86
|
+
|
|
87
|
+
```bash
|
|
88
|
+
# Report a deployment
|
|
89
|
+
dailybot agent update "Deployed v2.1 to staging"
|
|
90
|
+
|
|
91
|
+
# Name the agent so the team knows who's reporting
|
|
92
|
+
dailybot agent update "Built feature X" --name "Claude Code"
|
|
93
|
+
|
|
94
|
+
# Include structured data
|
|
95
|
+
dailybot agent update "Tests passed" --name "CI Bot" --json-data '{"suite": "integration", "passed": 42}'
|
|
96
|
+
|
|
97
|
+
# Report agent health
|
|
98
|
+
dailybot agent health --ok --message "All systems go" --name "Claude Code"
|
|
99
|
+
dailybot agent health --fail --message "DB unreachable" --name "CI Bot"
|
|
100
|
+
|
|
101
|
+
# Check agent health status
|
|
102
|
+
dailybot agent health --status --name "Claude Code"
|
|
103
|
+
|
|
104
|
+
# Register a webhook to receive messages
|
|
105
|
+
dailybot agent webhook register --url https://my-server.com/hook --secret my-token --name "Claude Code"
|
|
106
|
+
|
|
107
|
+
# Unregister a webhook
|
|
108
|
+
dailybot agent webhook unregister --name "Claude Code"
|
|
109
|
+
|
|
110
|
+
# Send a message to an agent
|
|
111
|
+
dailybot agent message send --to "Claude Code" --content "Review PR #42"
|
|
112
|
+
dailybot agent message send --to "Claude Code" --content "Do X" --type command
|
|
113
|
+
|
|
114
|
+
# List messages for an agent
|
|
115
|
+
dailybot agent message list --name "Claude Code"
|
|
116
|
+
dailybot agent message list --name "Claude Code" --pending
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
## Commands
|
|
120
|
+
|
|
121
|
+
| Command | Description |
|
|
122
|
+
|---|---|
|
|
123
|
+
| `dailybot login` | Authenticate with email OTP |
|
|
124
|
+
| `dailybot logout` | Log out and revoke token |
|
|
125
|
+
| `dailybot status` | Show pending check-ins for today |
|
|
126
|
+
| `dailybot update` | Submit a check-in update (free-text or structured) |
|
|
127
|
+
| `dailybot config` | Get, set, or remove a stored setting (e.g. API key) |
|
|
128
|
+
| `dailybot agent update` | Submit an agent activity report (API key or login) |
|
|
129
|
+
| `dailybot agent health` | Report or query agent health status (API key or login) |
|
|
130
|
+
| `dailybot agent webhook register` | Register a webhook for the agent (API key or login) |
|
|
131
|
+
| `dailybot agent webhook unregister` | Unregister the agent's webhook (API key or login) |
|
|
132
|
+
| `dailybot agent message send` | Send a message to an agent (API key or login) |
|
|
133
|
+
| `dailybot agent message list` | List messages for an agent (API key or login) |
|
|
134
|
+
|
|
135
|
+
Run `dailybot --help` for full details on any command.
|
|
136
|
+
|
|
137
|
+
## Development
|
|
138
|
+
|
|
139
|
+
```bash
|
|
140
|
+
pip install -e ".[dev]"
|
|
141
|
+
pytest
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
## License
|
|
145
|
+
|
|
146
|
+
[MIT](LICENSE)
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
# DailyBot CLI
|
|
2
|
+
|
|
3
|
+
A command-line interface for [DailyBot](https://www.dailybot.com) that lets **people** and **software agents** share progress updates, blockers, and feedback — straight from the terminal.
|
|
4
|
+
|
|
5
|
+
Whether you're a developer who lives in the terminal or an AI agent running in a CI pipeline, the DailyBot CLI gives you a fast way to submit check-ins without leaving your workflow.
|
|
6
|
+
|
|
7
|
+
## Installation
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
pip install dailybot-cli
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
Or via the install script:
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
curl -sSL https://cli.dailybot.com/install.sh | bash
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
Requires Python 3.9+.
|
|
20
|
+
|
|
21
|
+
## For humans
|
|
22
|
+
|
|
23
|
+
Authenticate once with your DailyBot email, then submit updates and check pending check-ins right from your terminal.
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
# Log in (one-time setup, email OTP)
|
|
27
|
+
dailybot login
|
|
28
|
+
|
|
29
|
+
# See what check-ins are waiting for you
|
|
30
|
+
dailybot status
|
|
31
|
+
|
|
32
|
+
# Submit a free-text update
|
|
33
|
+
dailybot update "Finished the auth module, starting on tests."
|
|
34
|
+
|
|
35
|
+
# Or use structured fields
|
|
36
|
+
dailybot update --done "Auth module" --doing "Tests" --blocked "None"
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
Run `dailybot` with no arguments to enter **interactive mode** — if you're not logged in yet, it will walk you through authentication first, then let you submit updates step by step.
|
|
40
|
+
|
|
41
|
+
## For agents
|
|
42
|
+
|
|
43
|
+
Any software agent — AI coding assistants, CI jobs, deploy scripts, bots — can report activity through the CLI. This lets teams get visibility into what automated processes are doing, alongside human updates.
|
|
44
|
+
|
|
45
|
+
Authenticate with any of these methods (checked in this order):
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
# Option 1: Environment variable (CI pipelines, one-off scripts)
|
|
49
|
+
export DAILYBOT_API_KEY=your-key
|
|
50
|
+
|
|
51
|
+
# Option 2: Store the key on disk (recommended for dev machines)
|
|
52
|
+
dailybot config key=your-key
|
|
53
|
+
|
|
54
|
+
# Option 3: Use your login session (no API key needed)
|
|
55
|
+
dailybot login
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
Then run agent commands:
|
|
59
|
+
|
|
60
|
+
```bash
|
|
61
|
+
# Report a deployment
|
|
62
|
+
dailybot agent update "Deployed v2.1 to staging"
|
|
63
|
+
|
|
64
|
+
# Name the agent so the team knows who's reporting
|
|
65
|
+
dailybot agent update "Built feature X" --name "Claude Code"
|
|
66
|
+
|
|
67
|
+
# Include structured data
|
|
68
|
+
dailybot agent update "Tests passed" --name "CI Bot" --json-data '{"suite": "integration", "passed": 42}'
|
|
69
|
+
|
|
70
|
+
# Report agent health
|
|
71
|
+
dailybot agent health --ok --message "All systems go" --name "Claude Code"
|
|
72
|
+
dailybot agent health --fail --message "DB unreachable" --name "CI Bot"
|
|
73
|
+
|
|
74
|
+
# Check agent health status
|
|
75
|
+
dailybot agent health --status --name "Claude Code"
|
|
76
|
+
|
|
77
|
+
# Register a webhook to receive messages
|
|
78
|
+
dailybot agent webhook register --url https://my-server.com/hook --secret my-token --name "Claude Code"
|
|
79
|
+
|
|
80
|
+
# Unregister a webhook
|
|
81
|
+
dailybot agent webhook unregister --name "Claude Code"
|
|
82
|
+
|
|
83
|
+
# Send a message to an agent
|
|
84
|
+
dailybot agent message send --to "Claude Code" --content "Review PR #42"
|
|
85
|
+
dailybot agent message send --to "Claude Code" --content "Do X" --type command
|
|
86
|
+
|
|
87
|
+
# List messages for an agent
|
|
88
|
+
dailybot agent message list --name "Claude Code"
|
|
89
|
+
dailybot agent message list --name "Claude Code" --pending
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
## Commands
|
|
93
|
+
|
|
94
|
+
| Command | Description |
|
|
95
|
+
|---|---|
|
|
96
|
+
| `dailybot login` | Authenticate with email OTP |
|
|
97
|
+
| `dailybot logout` | Log out and revoke token |
|
|
98
|
+
| `dailybot status` | Show pending check-ins for today |
|
|
99
|
+
| `dailybot update` | Submit a check-in update (free-text or structured) |
|
|
100
|
+
| `dailybot config` | Get, set, or remove a stored setting (e.g. API key) |
|
|
101
|
+
| `dailybot agent update` | Submit an agent activity report (API key or login) |
|
|
102
|
+
| `dailybot agent health` | Report or query agent health status (API key or login) |
|
|
103
|
+
| `dailybot agent webhook register` | Register a webhook for the agent (API key or login) |
|
|
104
|
+
| `dailybot agent webhook unregister` | Unregister the agent's webhook (API key or login) |
|
|
105
|
+
| `dailybot agent message send` | Send a message to an agent (API key or login) |
|
|
106
|
+
| `dailybot agent message list` | List messages for an agent (API key or login) |
|
|
107
|
+
|
|
108
|
+
Run `dailybot --help` for full details on any command.
|
|
109
|
+
|
|
110
|
+
## Development
|
|
111
|
+
|
|
112
|
+
```bash
|
|
113
|
+
pip install -e ".[dev]"
|
|
114
|
+
pytest
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
## License
|
|
118
|
+
|
|
119
|
+
[MIT](LICENSE)
|
|
@@ -0,0 +1,303 @@
|
|
|
1
|
+
"""HTTP client for DailyBot CLI API endpoints."""
|
|
2
|
+
|
|
3
|
+
from typing import Any, Optional
|
|
4
|
+
|
|
5
|
+
import httpx
|
|
6
|
+
|
|
7
|
+
from dailybot_cli.config import get_api_key, get_api_url, get_token
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class APIError(Exception):
|
|
11
|
+
"""Raised when the API returns a non-success response."""
|
|
12
|
+
|
|
13
|
+
def __init__(self, status_code: int, detail: str) -> None:
|
|
14
|
+
self.status_code: int = status_code
|
|
15
|
+
self.detail: str = detail
|
|
16
|
+
super().__init__(f"API error {status_code}: {detail}")
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class DailyBotClient:
|
|
20
|
+
"""HTTP client for the DailyBot /v1/cli/* API endpoints."""
|
|
21
|
+
|
|
22
|
+
def __init__(
|
|
23
|
+
self,
|
|
24
|
+
api_url: Optional[str] = None,
|
|
25
|
+
token: Optional[str] = None,
|
|
26
|
+
api_key: Optional[str] = None,
|
|
27
|
+
timeout: float = 30.0,
|
|
28
|
+
) -> None:
|
|
29
|
+
self.api_url: str = (api_url or get_api_url()).rstrip("/")
|
|
30
|
+
self.token: Optional[str] = token or get_token()
|
|
31
|
+
self.api_key: Optional[str] = api_key or get_api_key()
|
|
32
|
+
self.timeout: float = timeout
|
|
33
|
+
self._agent_auth_mode: Optional[str] = None
|
|
34
|
+
|
|
35
|
+
def _headers(self, authenticated: bool = True) -> dict[str, str]:
|
|
36
|
+
"""Build request headers."""
|
|
37
|
+
headers: dict[str, str] = {
|
|
38
|
+
"Content-Type": "application/json",
|
|
39
|
+
"Accept": "application/json",
|
|
40
|
+
}
|
|
41
|
+
if authenticated and self.token:
|
|
42
|
+
headers["Authorization"] = f"Bearer {self.token}"
|
|
43
|
+
return headers
|
|
44
|
+
|
|
45
|
+
def _agent_headers(self) -> dict[str, str]:
|
|
46
|
+
"""Build headers for agent authentication (API key preferred, then Bearer)."""
|
|
47
|
+
headers: dict[str, str] = {
|
|
48
|
+
"Content-Type": "application/json",
|
|
49
|
+
"Accept": "application/json",
|
|
50
|
+
}
|
|
51
|
+
if self.api_key:
|
|
52
|
+
headers["X-API-KEY"] = self.api_key
|
|
53
|
+
self._agent_auth_mode = "api_key"
|
|
54
|
+
elif self.token:
|
|
55
|
+
headers["Authorization"] = f"Bearer {self.token}"
|
|
56
|
+
self._agent_auth_mode = "bearer"
|
|
57
|
+
else:
|
|
58
|
+
self._agent_auth_mode = None
|
|
59
|
+
return headers
|
|
60
|
+
|
|
61
|
+
def _handle_response(self, response: httpx.Response) -> dict[str, Any]:
|
|
62
|
+
"""Parse API response and raise on errors."""
|
|
63
|
+
if response.status_code >= 400:
|
|
64
|
+
try:
|
|
65
|
+
body: dict[str, Any] = response.json()
|
|
66
|
+
detail: str = body.get("detail", body.get("error", str(body)))
|
|
67
|
+
except Exception:
|
|
68
|
+
detail = response.text or f"HTTP {response.status_code}"
|
|
69
|
+
if response.status_code in (401, 403) and self._agent_auth_mode == "bearer":
|
|
70
|
+
detail = "Session expired. Run 'dailybot login' to re-authenticate."
|
|
71
|
+
raise APIError(status_code=response.status_code, detail=detail)
|
|
72
|
+
if response.status_code == 204:
|
|
73
|
+
return {}
|
|
74
|
+
return response.json() # type: ignore[no-any-return]
|
|
75
|
+
|
|
76
|
+
# --- Auth endpoints ---
|
|
77
|
+
|
|
78
|
+
def request_code(self, email: str) -> dict[str, Any]:
|
|
79
|
+
"""POST /v1/cli/auth/request-code/"""
|
|
80
|
+
response: httpx.Response = httpx.post(
|
|
81
|
+
f"{self.api_url}/v1/cli/auth/request-code/",
|
|
82
|
+
json={"email": email},
|
|
83
|
+
headers=self._headers(authenticated=False),
|
|
84
|
+
timeout=self.timeout,
|
|
85
|
+
)
|
|
86
|
+
return self._handle_response(response)
|
|
87
|
+
|
|
88
|
+
def verify_code(
|
|
89
|
+
self,
|
|
90
|
+
email: str,
|
|
91
|
+
code: str,
|
|
92
|
+
organization_id: Optional[int] = None,
|
|
93
|
+
) -> dict[str, Any]:
|
|
94
|
+
"""POST /v1/cli/auth/verify-code/"""
|
|
95
|
+
payload: dict[str, Any] = {"email": email, "code": code}
|
|
96
|
+
if organization_id is not None:
|
|
97
|
+
payload["organization_id"] = organization_id
|
|
98
|
+
response: httpx.Response = httpx.post(
|
|
99
|
+
f"{self.api_url}/v1/cli/auth/verify-code/",
|
|
100
|
+
json=payload,
|
|
101
|
+
headers=self._headers(authenticated=False),
|
|
102
|
+
timeout=self.timeout,
|
|
103
|
+
)
|
|
104
|
+
return self._handle_response(response)
|
|
105
|
+
|
|
106
|
+
def auth_status(self) -> dict[str, Any]:
|
|
107
|
+
"""GET /v1/cli/auth/status/"""
|
|
108
|
+
response: httpx.Response = httpx.get(
|
|
109
|
+
f"{self.api_url}/v1/cli/auth/status/",
|
|
110
|
+
headers=self._headers(),
|
|
111
|
+
timeout=self.timeout,
|
|
112
|
+
)
|
|
113
|
+
return self._handle_response(response)
|
|
114
|
+
|
|
115
|
+
def logout(self) -> dict[str, Any]:
|
|
116
|
+
"""POST /v1/cli/auth/logout/"""
|
|
117
|
+
response: httpx.Response = httpx.post(
|
|
118
|
+
f"{self.api_url}/v1/cli/auth/logout/",
|
|
119
|
+
headers=self._headers(),
|
|
120
|
+
timeout=self.timeout,
|
|
121
|
+
)
|
|
122
|
+
return self._handle_response(response)
|
|
123
|
+
|
|
124
|
+
# --- Update/Status endpoints ---
|
|
125
|
+
|
|
126
|
+
def submit_update(
|
|
127
|
+
self,
|
|
128
|
+
message: Optional[str] = None,
|
|
129
|
+
done: Optional[str] = None,
|
|
130
|
+
doing: Optional[str] = None,
|
|
131
|
+
blocked: Optional[str] = None,
|
|
132
|
+
) -> dict[str, Any]:
|
|
133
|
+
"""POST /v1/cli/updates/"""
|
|
134
|
+
payload: dict[str, str] = {}
|
|
135
|
+
if message:
|
|
136
|
+
payload["message"] = message
|
|
137
|
+
if done:
|
|
138
|
+
payload["done"] = done
|
|
139
|
+
if doing:
|
|
140
|
+
payload["doing"] = doing
|
|
141
|
+
if blocked:
|
|
142
|
+
payload["blocked"] = blocked
|
|
143
|
+
response: httpx.Response = httpx.post(
|
|
144
|
+
f"{self.api_url}/v1/cli/updates/",
|
|
145
|
+
json=payload,
|
|
146
|
+
headers=self._headers(),
|
|
147
|
+
timeout=120.0,
|
|
148
|
+
)
|
|
149
|
+
return self._handle_response(response)
|
|
150
|
+
|
|
151
|
+
def get_status(self) -> dict[str, Any]:
|
|
152
|
+
"""GET /v1/cli/status/"""
|
|
153
|
+
response: httpx.Response = httpx.get(
|
|
154
|
+
f"{self.api_url}/v1/cli/status/",
|
|
155
|
+
headers=self._headers(),
|
|
156
|
+
timeout=self.timeout,
|
|
157
|
+
)
|
|
158
|
+
return self._handle_response(response)
|
|
159
|
+
|
|
160
|
+
# --- Agent endpoints ---
|
|
161
|
+
|
|
162
|
+
def submit_agent_report(
|
|
163
|
+
self,
|
|
164
|
+
agent_name: str,
|
|
165
|
+
content: str,
|
|
166
|
+
structured: Optional[dict[str, Any]] = None,
|
|
167
|
+
metadata: Optional[dict[str, Any]] = None,
|
|
168
|
+
) -> dict[str, Any]:
|
|
169
|
+
"""POST /v1/agent-reports/"""
|
|
170
|
+
payload: dict[str, Any] = {
|
|
171
|
+
"agent_name": agent_name,
|
|
172
|
+
"content": content,
|
|
173
|
+
}
|
|
174
|
+
if structured:
|
|
175
|
+
payload["structured"] = structured
|
|
176
|
+
if metadata:
|
|
177
|
+
payload["metadata"] = metadata
|
|
178
|
+
response: httpx.Response = httpx.post(
|
|
179
|
+
f"{self.api_url}/v1/agent-reports/",
|
|
180
|
+
json=payload,
|
|
181
|
+
headers=self._agent_headers(),
|
|
182
|
+
timeout=self.timeout,
|
|
183
|
+
)
|
|
184
|
+
return self._handle_response(response)
|
|
185
|
+
|
|
186
|
+
def submit_agent_health(
|
|
187
|
+
self,
|
|
188
|
+
agent_name: str,
|
|
189
|
+
ok: bool,
|
|
190
|
+
message: Optional[str] = None,
|
|
191
|
+
) -> dict[str, Any]:
|
|
192
|
+
"""POST /v1/agent-health/"""
|
|
193
|
+
payload: dict[str, Any] = {
|
|
194
|
+
"agent_name": agent_name,
|
|
195
|
+
"ok": ok,
|
|
196
|
+
}
|
|
197
|
+
if message:
|
|
198
|
+
payload["message"] = message
|
|
199
|
+
response: httpx.Response = httpx.post(
|
|
200
|
+
f"{self.api_url}/v1/agent-health/",
|
|
201
|
+
json=payload,
|
|
202
|
+
headers=self._agent_headers(),
|
|
203
|
+
timeout=self.timeout,
|
|
204
|
+
)
|
|
205
|
+
return self._handle_response(response)
|
|
206
|
+
|
|
207
|
+
def get_agent_health(self, agent_name: str) -> dict[str, Any]:
|
|
208
|
+
"""GET /v1/agent-health/?agent_name=..."""
|
|
209
|
+
response: httpx.Response = httpx.get(
|
|
210
|
+
f"{self.api_url}/v1/agent-health/",
|
|
211
|
+
params={"agent_name": agent_name},
|
|
212
|
+
headers=self._agent_headers(),
|
|
213
|
+
timeout=self.timeout,
|
|
214
|
+
)
|
|
215
|
+
return self._handle_response(response)
|
|
216
|
+
|
|
217
|
+
# --- Agent webhook endpoints ---
|
|
218
|
+
|
|
219
|
+
def register_agent_webhook(
|
|
220
|
+
self,
|
|
221
|
+
agent_name: str,
|
|
222
|
+
webhook_url: str,
|
|
223
|
+
webhook_secret: Optional[str] = None,
|
|
224
|
+
) -> dict[str, Any]:
|
|
225
|
+
"""POST /v1/agent-webhook/"""
|
|
226
|
+
payload: dict[str, Any] = {
|
|
227
|
+
"agent_name": agent_name,
|
|
228
|
+
"webhook_url": webhook_url,
|
|
229
|
+
}
|
|
230
|
+
if webhook_secret:
|
|
231
|
+
payload["webhook_secret"] = webhook_secret
|
|
232
|
+
response: httpx.Response = httpx.post(
|
|
233
|
+
f"{self.api_url}/v1/agent-webhook/",
|
|
234
|
+
json=payload,
|
|
235
|
+
headers=self._agent_headers(),
|
|
236
|
+
timeout=self.timeout,
|
|
237
|
+
)
|
|
238
|
+
return self._handle_response(response)
|
|
239
|
+
|
|
240
|
+
def unregister_agent_webhook(self, agent_name: str) -> dict[str, Any]:
|
|
241
|
+
"""DELETE /v1/agent-webhook/"""
|
|
242
|
+
response: httpx.Response = httpx.request(
|
|
243
|
+
"DELETE",
|
|
244
|
+
f"{self.api_url}/v1/agent-webhook/",
|
|
245
|
+
json={"agent_name": agent_name},
|
|
246
|
+
headers=self._agent_headers(),
|
|
247
|
+
timeout=self.timeout,
|
|
248
|
+
)
|
|
249
|
+
return self._handle_response(response)
|
|
250
|
+
|
|
251
|
+
# --- Agent message endpoints ---
|
|
252
|
+
|
|
253
|
+
def send_agent_message(
|
|
254
|
+
self,
|
|
255
|
+
agent_name: str,
|
|
256
|
+
content: str,
|
|
257
|
+
message_type: Optional[str] = None,
|
|
258
|
+
metadata: Optional[dict[str, Any]] = None,
|
|
259
|
+
expires_at: Optional[str] = None,
|
|
260
|
+
sender_type: Optional[str] = None,
|
|
261
|
+
sender_name: Optional[str] = None,
|
|
262
|
+
) -> dict[str, Any]:
|
|
263
|
+
"""POST /v1/agent-messages/"""
|
|
264
|
+
payload: dict[str, Any] = {
|
|
265
|
+
"agent_name": agent_name,
|
|
266
|
+
"content": content,
|
|
267
|
+
}
|
|
268
|
+
if message_type:
|
|
269
|
+
payload["message_type"] = message_type
|
|
270
|
+
if metadata:
|
|
271
|
+
payload["metadata"] = metadata
|
|
272
|
+
if expires_at:
|
|
273
|
+
payload["expires_at"] = expires_at
|
|
274
|
+
if sender_type:
|
|
275
|
+
payload["sender_type"] = sender_type
|
|
276
|
+
if sender_name:
|
|
277
|
+
payload["sender_name"] = sender_name
|
|
278
|
+
response: httpx.Response = httpx.post(
|
|
279
|
+
f"{self.api_url}/v1/agent-messages/",
|
|
280
|
+
json=payload,
|
|
281
|
+
headers=self._agent_headers(),
|
|
282
|
+
timeout=self.timeout,
|
|
283
|
+
)
|
|
284
|
+
return self._handle_response(response)
|
|
285
|
+
|
|
286
|
+
def get_agent_messages(
|
|
287
|
+
self,
|
|
288
|
+
agent_name: str,
|
|
289
|
+
delivered: Optional[bool] = None,
|
|
290
|
+
) -> list[dict[str, Any]]:
|
|
291
|
+
"""GET /v1/agent-messages/?agent_name=..."""
|
|
292
|
+
params: dict[str, str] = {"agent_name": agent_name}
|
|
293
|
+
if delivered is not None:
|
|
294
|
+
params["delivered"] = "true" if delivered else "false"
|
|
295
|
+
response: httpx.Response = httpx.get(
|
|
296
|
+
f"{self.api_url}/v1/agent-messages/",
|
|
297
|
+
params=params,
|
|
298
|
+
headers=self._agent_headers(),
|
|
299
|
+
timeout=self.timeout,
|
|
300
|
+
)
|
|
301
|
+
if response.status_code >= 400:
|
|
302
|
+
self._handle_response(response)
|
|
303
|
+
return response.json() # type: ignore[no-any-return]
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""DailyBot CLI commands."""
|