cometapi-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.
Files changed (67) hide show
  1. cometapi_cli-0.1.0/.github/workflows/ci.yml +32 -0
  2. cometapi_cli-0.1.0/.github/workflows/publish.yml +30 -0
  3. cometapi_cli-0.1.0/.gitignore +20 -0
  4. cometapi_cli-0.1.0/AGENTS.md +486 -0
  5. cometapi_cli-0.1.0/CHANGELOG.md +46 -0
  6. cometapi_cli-0.1.0/LICENSE +21 -0
  7. cometapi_cli-0.1.0/PKG-INFO +228 -0
  8. cometapi_cli-0.1.0/README.md +190 -0
  9. cometapi_cli-0.1.0/SKILL.md +325 -0
  10. cometapi_cli-0.1.0/docs/README.md +42 -0
  11. cometapi_cli-0.1.0/docs/authentication.md +88 -0
  12. cometapi_cli-0.1.0/docs/commands/account.md +52 -0
  13. cometapi_cli-0.1.0/docs/commands/balance.md +70 -0
  14. cometapi_cli-0.1.0/docs/commands/chat.md +129 -0
  15. cometapi_cli-0.1.0/docs/commands/config.md +167 -0
  16. cometapi_cli-0.1.0/docs/commands/doctor.md +131 -0
  17. cometapi_cli-0.1.0/docs/commands/init.md +70 -0
  18. cometapi_cli-0.1.0/docs/commands/logs.md +457 -0
  19. cometapi_cli-0.1.0/docs/commands/models.md +60 -0
  20. cometapi_cli-0.1.0/docs/commands/repl.md +91 -0
  21. cometapi_cli-0.1.0/docs/commands/stats.md +61 -0
  22. cometapi_cli-0.1.0/docs/commands/tasks.md +277 -0
  23. cometapi_cli-0.1.0/docs/commands/tokens.md +78 -0
  24. cometapi_cli-0.1.0/docs/configuration.md +77 -0
  25. cometapi_cli-0.1.0/docs/errors.md +92 -0
  26. cometapi_cli-0.1.0/docs/installation.md +59 -0
  27. cometapi_cli-0.1.0/docs/output-formats.md +86 -0
  28. cometapi_cli-0.1.0/pyproject.toml +67 -0
  29. cometapi_cli-0.1.0/skills/live-test/SKILL.md +340 -0
  30. cometapi_cli-0.1.0/src/cometapi_cli/__init__.py +3 -0
  31. cometapi_cli-0.1.0/src/cometapi_cli/app.py +85 -0
  32. cometapi_cli-0.1.0/src/cometapi_cli/client.py +270 -0
  33. cometapi_cli-0.1.0/src/cometapi_cli/commands/__init__.py +1 -0
  34. cometapi_cli-0.1.0/src/cometapi_cli/commands/account.py +39 -0
  35. cometapi_cli-0.1.0/src/cometapi_cli/commands/balance.py +56 -0
  36. cometapi_cli-0.1.0/src/cometapi_cli/commands/chat.py +104 -0
  37. cometapi_cli-0.1.0/src/cometapi_cli/commands/chat_repl.py +229 -0
  38. cometapi_cli-0.1.0/src/cometapi_cli/commands/config_cmd.py +174 -0
  39. cometapi_cli-0.1.0/src/cometapi_cli/commands/doctor.py +144 -0
  40. cometapi_cli-0.1.0/src/cometapi_cli/commands/logs.py +326 -0
  41. cometapi_cli-0.1.0/src/cometapi_cli/commands/models.py +44 -0
  42. cometapi_cli-0.1.0/src/cometapi_cli/commands/repl.py +134 -0
  43. cometapi_cli-0.1.0/src/cometapi_cli/commands/stats.py +39 -0
  44. cometapi_cli-0.1.0/src/cometapi_cli/commands/tasks.py +130 -0
  45. cometapi_cli-0.1.0/src/cometapi_cli/commands/tokens.py +87 -0
  46. cometapi_cli-0.1.0/src/cometapi_cli/config.py +102 -0
  47. cometapi_cli-0.1.0/src/cometapi_cli/console.py +8 -0
  48. cometapi_cli-0.1.0/src/cometapi_cli/constants.py +55 -0
  49. cometapi_cli-0.1.0/src/cometapi_cli/errors.py +113 -0
  50. cometapi_cli-0.1.0/src/cometapi_cli/formatters.py +156 -0
  51. cometapi_cli-0.1.0/src/cometapi_cli/main.py +8 -0
  52. cometapi_cli-0.1.0/tests/__init__.py +1 -0
  53. cometapi_cli-0.1.0/tests/conftest.py +267 -0
  54. cometapi_cli-0.1.0/tests/test_account.py +19 -0
  55. cometapi_cli-0.1.0/tests/test_balance.py +53 -0
  56. cometapi_cli-0.1.0/tests/test_chat.py +49 -0
  57. cometapi_cli-0.1.0/tests/test_config.py +123 -0
  58. cometapi_cli-0.1.0/tests/test_doctor.py +40 -0
  59. cometapi_cli-0.1.0/tests/test_errors.py +28 -0
  60. cometapi_cli-0.1.0/tests/test_formatters.py +46 -0
  61. cometapi_cli-0.1.0/tests/test_help.py +65 -0
  62. cometapi_cli-0.1.0/tests/test_logs.py +237 -0
  63. cometapi_cli-0.1.0/tests/test_models.py +46 -0
  64. cometapi_cli-0.1.0/tests/test_stats.py +19 -0
  65. cometapi_cli-0.1.0/tests/test_tasks.py +120 -0
  66. cometapi_cli-0.1.0/tests/test_tokens.py +64 -0
  67. cometapi_cli-0.1.0/uv.lock +742 -0
@@ -0,0 +1,32 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+ branches: [main]
8
+
9
+ jobs:
10
+ test:
11
+ runs-on: ubuntu-latest
12
+ strategy:
13
+ matrix:
14
+ python-version: ["3.10", "3.11", "3.12", "3.13"]
15
+
16
+ steps:
17
+ - uses: actions/checkout@v4
18
+
19
+ - name: Install uv
20
+ uses: astral-sh/setup-uv@v4
21
+
22
+ - name: Set up Python ${{ matrix.python-version }}
23
+ run: uv python install ${{ matrix.python-version }}
24
+
25
+ - name: Install dependencies
26
+ run: uv sync --extra dev
27
+
28
+ - name: Lint
29
+ run: uv run ruff check src/ tests/
30
+
31
+ - name: Test
32
+ run: uv run pytest -v --tb=short
@@ -0,0 +1,30 @@
1
+ name: Publish to PyPI
2
+
3
+ on:
4
+ push:
5
+ tags:
6
+ - "v*"
7
+
8
+ permissions:
9
+ contents: read
10
+ id-token: write
11
+
12
+ jobs:
13
+ publish:
14
+ runs-on: ubuntu-latest
15
+ environment: pypi
16
+
17
+ steps:
18
+ - uses: actions/checkout@v4
19
+
20
+ - name: Install uv
21
+ uses: astral-sh/setup-uv@v4
22
+
23
+ - name: Set up Python
24
+ run: uv python install 3.13
25
+
26
+ - name: Build package
27
+ run: uv build
28
+
29
+ - name: Publish to PyPI
30
+ uses: pypa/gh-action-pypi-publish@release/v1
@@ -0,0 +1,20 @@
1
+ # Python
2
+ __pycache__/
3
+ *.pyc
4
+ *.pyo
5
+ .mypy_cache/
6
+ .ruff_cache/
7
+
8
+ # Virtual environment
9
+ .venv/
10
+
11
+ # Build artifacts
12
+ dist/
13
+ *.egg-info/
14
+
15
+ # Environment
16
+ .env
17
+ .envrc
18
+
19
+ # macOS
20
+ .DS_Store
@@ -0,0 +1,486 @@
1
+ # CometAPI CLI — Agent Instructions
2
+
3
+ > This file covers CLI-specific details. For cross-cutting architecture, see the root [AGENTS.md](../AGENTS.md).
4
+
5
+ ## Overview
6
+
7
+ The CLI is a Typer + Rich command-line tool that proxies all business logic through `cometapi-python`. It must **never** make direct HTTP requests — all network calls go through `CometClient` from the Python SDK.
8
+
9
+ ## Project Layout
10
+
11
+ ```
12
+ cometapi-cli/
13
+ ├── pyproject.toml # Hatch build, deps, entry point
14
+ ├── uv.lock # Lock file (committed)
15
+ ├── SKILL.md # Agent capability description
16
+ ├── skills/
17
+ │ └── live-test/
18
+ │ └── SKILL.md # Live testing SOP for Coding Agents
19
+ ├── src/cometapi_cli/
20
+ │ ├── __init__.py # __version__
21
+ │ ├── app.py # Typer app, global options, command registration
22
+ │ ├── main.py # Backward compat shim → app.py
23
+ │ ├── config.py # Config file (~/.config/cometapi/config.toml), get_client()
24
+ │ ├── constants.py # Shared constants (QUOTA_PER_UNIT, helpers)
25
+ │ ├── console.py # Shared Rich Console instances
26
+ │ ├── errors.py # CometCLIError hierarchy, exit codes, handle_errors decorator
27
+ │ ├── formatters.py # Multi-format output (table/json/yaml/csv/markdown)
28
+ │ └── commands/
29
+ │ ├── __init__.py
30
+ │ ├── chat.py # chat send (streaming + JSON), REPL entry
31
+ │ ├── chat_repl.py # Multi-turn chat REPL with prompt_toolkit
32
+ │ ├── models.py # models list with search/limit
33
+ │ ├── balance.py # account balance
34
+ │ ├── account.py # user profile (access_token)
35
+ │ ├── stats.py # usage statistics (access_token)
36
+ │ ├── tokens.py # API key listing and search (access_token)
37
+ │ ├── logs.py # Usage logs browsing and filtering (access_token)
38
+ │ ├── tasks.py # Async task logs — Suno, MJ, Luma, Kling (access_token)
39
+ │ ├── config_cmd.py # init wizard + config show/set/unset/path
40
+ │ ├── doctor.py # connectivity & config diagnostics
41
+ │ └── repl.py # Full command REPL (interactive shell)
42
+ └── tests/
43
+ ├── __init__.py
44
+ ├── conftest.py # Shared fixtures, mock client factory
45
+ ├── test_help.py # Version, help, command listing tests
46
+ ├── test_chat.py # Chat command tests
47
+ ├── test_config.py # Config read/write/CLI tests
48
+ ├── test_doctor.py # Doctor diagnostics tests
49
+ ├── test_errors.py # Error types and exit codes
50
+ ├── test_formatters.py # Multi-format output tests
51
+ ├── test_models.py # Models command tests
52
+ ├── test_balance.py # Balance command tests (incl. --source)
53
+ ├── test_account.py # Account command tests
54
+ ├── test_stats.py # Stats command tests
55
+ ├── test_tokens.py # Tokens command tests
56
+ ├── test_logs.py # Logs command tests
57
+ └── test_tasks.py # Tasks command tests
58
+ ```
59
+
60
+ ## Key Design Decisions
61
+
62
+ - **Self-contained client.** `cometapi_cli/client.py` contains `CometClient` (inherits `openai.OpenAI`). The CLI has **no dependency** on the `cometapi` Python SDK package.
63
+ - **No direct HTTP for OpenAI-compatible endpoints.** Always use inherited methods via `CometClient`. Only CometAPI-specific endpoints use `self._client.request()` directly.
64
+
65
+ ## Model ID Policy
66
+
67
+ The default model constant lives in `config.py:get_default_model()`. All examples, defaults, and test fixtures MUST use current model IDs — see the root [AGENTS.md](../AGENTS.md) for the authoritative list.
68
+
69
+ ## Security & Credential Policy
70
+
71
+ All user-facing messages involving missing or invalid credentials MUST include the relevant creation URL:
72
+ - API Key: https://www.cometapi.com/console/token
73
+ - Access Token: https://www.cometapi.com/console/personal
74
+
75
+ See the root [AGENTS.md](../AGENTS.md) for the full security policy.
76
+ - **Entry point:** `cometapi = "cometapi_cli.app:app"` — the command name is `cometapi`.
77
+
78
+ ## Publishing to PyPI
79
+
80
+ Package name: `cometapi-cli`. Triggered automatically by pushing a `v*` tag to GitHub.
81
+
82
+ ### Release SOP
83
+
84
+ ```bash
85
+ # 1. Bump version in TWO places (must match):
86
+ # - pyproject.toml: version = "X.Y.Z"
87
+ # - src/cometapi_cli/__init__.py: __version__ = "X.Y.Z"
88
+
89
+ # 2. Commit and push
90
+ git add -A
91
+ git commit -m "release: vX.Y.Z"
92
+ git push origin main
93
+
94
+ # 3. Tag and push — triggers publish.yml automatically
95
+ git tag vX.Y.Z
96
+ git push origin vX.Y.Z
97
+ ```
98
+
99
+ ### Verify
100
+
101
+ ```bash
102
+ open https://pypi.org/project/cometapi-cli/
103
+ pip install cometapi-cli==X.Y.Z
104
+ cometapi --version
105
+ ```
106
+
107
+ ### Version sync rule
108
+
109
+ `pyproject.toml` `version` and `src/cometapi_cli/__init__.py` `__version__` **must always match**.
110
+
111
+ ## Configuration
112
+ - **Output formats:** Every data command supports `--json` (per-command) and global `--format/-f` (table/json/yaml/csv/markdown). Persistent default can be set via `output_format` in config.toml.
113
+ - **Error handling:** All commands wrapped with `@handle_errors` decorator that catches SDK/network errors and maps to user-friendly messages + Unix exit codes.
114
+ - **Exit codes:** sysexits.h compatible: 0=success, 1=error, 2=usage, 64=config missing, 69=service unavailable, 77=auth error, 78=config error.
115
+
116
+ ## Commands — Complete Reference
117
+
118
+ > **Maintenance rule:** Any CLI interface change (new command, renamed flag, new option) **must** update this section. This is the single source of truth for what the CLI exposes.
119
+
120
+ ### Global Options
121
+
122
+ These options apply to **every** command via the root Typer callback.
123
+
124
+ | Option | Alias | Type | Default | Description |
125
+ |--------|-------|------|---------|-------------|
126
+ | `--version` | `-V` | flag | — | Print version (`cli`, `sdk`, `python`) and exit |
127
+ | `--format` | `-f` | `table\|json\|yaml\|csv\|markdown` | `table` | Global output format (overridden by per-command `--format` or `--json`) |
128
+ | `--json` | — | flag | `false` | Shortcut for `--format json` |
129
+ | `--help` | `-h` | flag | — | Show help for any command |
130
+ | `--install-completion` | — | flag | — | Install shell completion (bash/zsh/fish/powershell) |
131
+ | `--show-completion` | — | flag | — | Print the completion script |
132
+
133
+ **Output format resolution priority:** per-command `--json` > per-command `--format` > global `--format` > `table`.
134
+
135
+ ---
136
+
137
+ ### `chat` — Send a chat message or start interactive REPL
138
+
139
+ **Auth:** `COMETAPI_KEY`
140
+
141
+ | Parameter | Alias | Type | Default | Description |
142
+ |-----------|-------|------|---------|-------------|
143
+ | `MESSAGE` | — | argument (positional, optional) | `None` | Message to send. Omit to enter interactive multi-turn REPL. |
144
+ | `--model` | `-m` | `str` | config `default_model` or `gpt-5.4` | Model to use |
145
+ | `--system` | `-s` | `str` | `None` | System prompt prepended to conversation |
146
+ | `--temperature` | `-t` | `float` | API default | Sampling temperature (0.0–2.0) |
147
+ | `--max-tokens` | — | `int` | API default | Maximum tokens in the response |
148
+ | `--stream/--no-stream` | — | flag | `--stream` | Enable/disable streaming output |
149
+ | `--format` | `-f` | `OutputFormat` | inherits global | Per-command output format override |
150
+ | `--json` | — | flag | `false` | Output structured JSON (disables streaming) |
151
+
152
+ **Behavior:**
153
+ - With `MESSAGE`: sends a single request, streams response to stdout. With `--json`, returns `{"model", "role", "content", "usage"}`.
154
+ - Without `MESSAGE`: enters interactive multi-turn Chat REPL (see [Chat REPL Slash Commands](#chat-repl-slash-commands) below).
155
+ - Model resolved via: `--model` flag > config `default_model` > `gpt-5.4`.
156
+
157
+ **JSON output schema:**
158
+ ```json
159
+ {
160
+ "model": "gpt-5.4",
161
+ "role": "assistant",
162
+ "content": "...",
163
+ "usage": { "prompt_tokens": 9, "completion_tokens": 10, "total_tokens": 19 }
164
+ }
165
+ ```
166
+
167
+ ---
168
+
169
+ ### `models` — List available models
170
+
171
+ **Auth:** `COMETAPI_KEY`
172
+
173
+ | Parameter | Alias | Type | Default | Description |
174
+ |-----------|-------|------|---------|-------------|
175
+ | `--search` | `-s` | `str` | `None` | Filter models by name (case-insensitive substring match) |
176
+ | `--limit` | `-l` | `int` | `None` (show all) | Maximum number of models to display |
177
+ | `--format` | `-f` | `OutputFormat` | inherits global | Per-command output format override |
178
+ | `--json` | — | flag | `false` | Output as JSON |
179
+
180
+ **Behavior:** Fetches all models via `client.models.list()`, sorts alphabetically by `id`, applies `--search` filter, then `--limit` truncation.
181
+
182
+ **Table columns:** `id` (cyan), `owned_by` (green).
183
+
184
+ ---
185
+
186
+ ### `balance` — Show account balance
187
+
188
+ **Auth:** `COMETAPI_KEY` (always), `COMETAPI_ACCESS_TOKEN` (for account-level view)
189
+
190
+ | Parameter | Alias | Type | Default | Description |
191
+ |-----------|-------|------|---------|-------------|
192
+ | `--source` | `-s` | `str` (`account` or `token`) | `None` (auto-detect) | Force data source: `account` = full account balance via `/api/user/self`; `token` = per-API-key billing via `/v1/dashboard/billing/*` |
193
+ | `--format` | `-f` | `OutputFormat` | inherits global | Per-command output format override |
194
+ | `--json` | — | flag | `false` | Output raw balance dict as JSON |
195
+
196
+ **Auto-detection logic** (when `--source` is omitted):
197
+ 1. If `COMETAPI_ACCESS_TOKEN` is available → uses `account` source.
198
+ 2. Otherwise → falls back to `token` (per-key billing) source.
199
+
200
+ **Display — `account` source:**
201
+ | Field | Description |
202
+ |-------|-------------|
203
+ | Available Balance | Current remaining balance (USD) |
204
+ | Used | Total amount consumed (USD) |
205
+ | Total Topped Up | Lifetime top-up amount (USD) |
206
+
207
+ **Display — `token` (billing) source:**
208
+ | Field | Description |
209
+ |-------|-------------|
210
+ | Limit | Spending cap (`Unlimited` if no cap set) |
211
+ | Used | Amount consumed through this API key (USD) |
212
+
213
+ ---
214
+
215
+ ### `account` — Show account profile
216
+
217
+ **Auth:** `COMETAPI_ACCESS_TOKEN` (required)
218
+
219
+ | Parameter | Alias | Type | Default | Description |
220
+ |-----------|-------|------|---------|-------------|
221
+ | `--format` | `-f` | `OutputFormat` | inherits global | Per-command output format override |
222
+ | `--json` | — | flag | `false` | Output full profile as JSON |
223
+
224
+ **Display fields:** `id`, `username`, `display_name`, `email`, `role`, `status`.
225
+
226
+ ---
227
+
228
+ ### `stats` — Show usage statistics
229
+
230
+ **Auth:** `COMETAPI_ACCESS_TOKEN` (required)
231
+
232
+ | Parameter | Alias | Type | Default | Description |
233
+ |-----------|-------|------|---------|-------------|
234
+ | `--format` | `-f` | `OutputFormat` | inherits global | Per-command output format override |
235
+ | `--json` | — | flag | `false` | Output raw stats as JSON |
236
+
237
+ **Display fields:** `requests`, `request_rate_change`, `usage` (USD), `usage_rate_change`, `success_rate`, `predicted_days_left`.
238
+
239
+ ---
240
+
241
+ ### `tokens` — List and search API keys
242
+
243
+ **Auth:** `COMETAPI_ACCESS_TOKEN` (required)
244
+
245
+ | Parameter | Alias | Type | Default | Description |
246
+ |-----------|-------|------|---------|-------------|
247
+ | `--search` | `-s` | `str` | `None` | Search tokens by name or key substring (uses `/api/token/search`) |
248
+ | `--page` | `-p` | `int` | `1` | Page number for paginated results |
249
+ | `--limit` | `-l` | `int` | `20` | Results per page |
250
+ | `--format` | `-f` | `OutputFormat` | inherits global | Per-command output format override |
251
+ | `--json` | — | flag | `false` | Output raw token list as JSON |
252
+
253
+ **Behavior:**
254
+ - Without `--search`: calls `client.list_tokens(page=, page_size=)` — paginated, returns `data.items`.
255
+ - With `--search`: calls `client.search_tokens(keyword=)` — flat `data` list, ignores `--page`/`--limit`.
256
+
257
+ **Table columns:** `id` (cyan), `name` (green), `key` (yellow, masked), `status` (green — active/disabled/expired/exhausted), `balance` (green, USD or "Unlimited"), `used` (red, USD), `created` (dim), `accessed` (dim), `expires` (dim, "Never" if -1).
258
+
259
+ **Key masking:** Only the last 4 characters are shown, e.g., `****abcd`.
260
+
261
+ ---
262
+
263
+ ### `logs` — Show usage logs
264
+
265
+ **Auth:** `COMETAPI_ACCESS_TOKEN` (required)
266
+
267
+ | Parameter | Alias | Type | Default | Description |
268
+ |-----------|-------|------|---------|-------------|
269
+ | `--model` | `-m` | `str` | `None` | Filter by model name |
270
+ | `--token-name` | `-t` | `str` | `None` | Filter by token name |
271
+ | `--type` | — | `str` | `None` | Filter by log type (see values below) |
272
+ | `--search` | `-s` | `str` | `None` | Search logs by keyword (uses `/api/log/self/search`) |
273
+ | `--start` | — | `str` | `None` | Start date (`YYYY-MM-DD`, ISO 8601, or Unix timestamp) |
274
+ | `--end` | — | `str` | `None` | End date (`YYYY-MM-DD`, ISO 8601, or Unix timestamp) |
275
+ | `--group` | `-g` | `str` | `None` | Filter by API key group |
276
+ | `--page` | `-p` | `int` | `1` | Page number |
277
+ | `--limit` | `-l` | `int` | `20` | Results per page |
278
+ | `--export` | — | flag | `false` | Export logs as server-side CSV to stdout |
279
+ | `--format` | `-f` | `OutputFormat` | inherits global | Per-command output format override |
280
+ | `--json` | — | flag | `false` | Output raw log list as JSON |
281
+
282
+ **Valid `--type` values:**
283
+
284
+ | Value | Backend code | Description |
285
+ |-------|-------------|-------------|
286
+ | `unknown` | 0 | Unknown log type |
287
+ | `topup` | 1 | Balance top-up |
288
+ | `consume` | 2 | API consumption |
289
+ | `manage` | 3 | Management action |
290
+ | `system` | 4 | System event |
291
+ | `error` | 5 | Error log |
292
+ | `refund` | 6 | Refund |
293
+
294
+ Invalid `--type` values produce an error message with valid options and exit code 2.
295
+
296
+ **Behavior:**
297
+ - Without `--search` or `--export`: calls `client.list_logs(page=, page_size=, log_type=, model_name=, token_name=, start_timestamp=, end_timestamp=, group=)` — paginated, `data.items`.
298
+ - With `--search`: calls `client.search_logs(keyword=)` — flat `data` list, ignores other filter flags.
299
+ - With `--export`: calls `client.export_logs(...)` — writes server-side CSV bytes to stdout. Honors `--model`, `--token-name`, `--type`, `--start`, `--end`, `--group`. Pipe-friendly (no Rich formatting).
300
+
301
+ **Date parsing:** `--start` and `--end` accept `YYYY-MM-DD`, `YYYY-MM-DDTHH:MM:SS` (ISO 8601), or raw Unix timestamps. Dates are interpreted as UTC.
302
+
303
+ **Table columns:** `time` (dim), `type` (cyan), `model` (green), `token` (yellow), `prompt` (tokens count), `completion` (tokens count), `cost` (red, USD), `duration_ms`, `stream` (Yes/No).
304
+
305
+ ---
306
+
307
+ ### `tasks` — Show async task logs
308
+
309
+ **Auth:** `COMETAPI_ACCESS_TOKEN` (required)
310
+
311
+ | Parameter | Alias | Type | Default | Description |
312
+ |-----------|-------|------|---------|-------------|
313
+ | `--platform` | `-p` | `str` | `None` | Filter by platform (see values below) |
314
+ | `--task-id` | — | `str` | `None` | Filter by task ID |
315
+ | `--status` | `-s` | `str` | `None` | Filter by status (see values below) |
316
+ | `--action` | `-a` | `str` | `None` | Filter by action type (e.g., `MUSIC`, `generate`) |
317
+ | `--start` | — | `str` | `None` | Start date (`YYYY-MM-DD`, ISO 8601, or Unix timestamp) |
318
+ | `--end` | — | `str` | `None` | End date (`YYYY-MM-DD`, ISO 8601, or Unix timestamp) |
319
+ | `--page` | — | `int` | `1` | Page number |
320
+ | `--limit` | `-l` | `int` | `20` | Results per page |
321
+ | `--format` | `-f` | `OutputFormat` | inherits global | Per-command output format override |
322
+ | `--json` | — | flag | `false` | Output raw task list as JSON |
323
+
324
+ **Valid `--platform` values:** `suno`, `mj`, `luma`, `replicate`, `kling`, `runwayml`, `runway`, `jimeng`, `volcengine`, `sora`, `bria`, `flux`
325
+
326
+ **Valid `--status` values:** `SUBMITTED`, `QUEUED`, `IN_PROGRESS`, `FAILURE`, `SUCCESS`, `UNKNOWN` (case-insensitive input, sent as uppercase)
327
+
328
+ Invalid `--platform` or `--status` values produce an error message with valid options and exit code 2.
329
+
330
+ **Behavior:** Calls `client.list_tasks(page=, page_size=, platform=, task_id=, status=, action=, start_timestamp=, end_timestamp=)` — paginated response via `GET /api/task/self`.
331
+
332
+ **Table columns:** `time` (dim), `platform` (magenta), `task_id` (cyan), `action` (yellow), `status` (green), `model` (green), `progress` (dim), `cost` (red, USD), `duration` (dim, submit-to-finish).
333
+
334
+ ---
335
+
336
+ ### `init` — Interactive setup wizard
337
+
338
+ **Auth:** None (creates auth config)
339
+
340
+ No options. Launches an interactive Rich prompt that:
341
+ 1. Collects `api_key` (with connectivity test).
342
+ 2. Optionally collects `access_token`.
343
+ 3. Sets `default_model`.
344
+ 4. Saves to `~/.config/cometapi/config.toml` with 0600 permissions.
345
+ 5. Displays security disclaimer and credential creation URLs.
346
+
347
+ ---
348
+
349
+ ### `doctor` — Run diagnostics and health checks
350
+
351
+ **Auth:** None (inspects current config)
352
+
353
+ | Parameter | Alias | Type | Default | Description |
354
+ |-----------|-------|------|---------|-------------|
355
+ | `--format` | `-f` | `OutputFormat` | inherits global | Per-command output format override |
356
+ | `--json` | — | flag | `false` | Output diagnostics as JSON |
357
+
358
+ **Checks performed:**
359
+ 1. Config file existence (`~/.config/cometapi/config.toml`)
360
+ 2. API key presence and source (environment / config / none)
361
+ 3. API connectivity (calls `client.models.list()`)
362
+ 4. Access token presence
363
+ 5. SDK installation
364
+ 6. Version info (Python, SDK, CLI)
365
+
366
+ Exits with code 64 if any critical check fails.
367
+
368
+ ---
369
+
370
+ ### `repl` — Interactive command shell
371
+
372
+ **Auth:** None (individual commands within REPL check auth as needed)
373
+
374
+ No options. Starts a `prompt_toolkit` session with:
375
+ - Tab completion for all commands and common flags (`--json`, `--format`, `--model`, `--system`, `--search`, `--limit`, `--page`, `--type`, `--token-name`, `--help`).
376
+ - Persistent history in `~/.config/cometapi/repl_history`.
377
+ - Dispatches typed commands through the Typer app (no `cometapi` prefix needed).
378
+ - Built-in `help` and `exit`/`quit` commands.
379
+ - Prevents recursive `repl` invocation.
380
+
381
+ ---
382
+
383
+ ### `config` — Manage CLI configuration
384
+
385
+ A subcommand group with four subcommands:
386
+
387
+ #### `config show` — Display current configuration
388
+
389
+ | Parameter | Alias | Type | Default | Description |
390
+ |-----------|-------|------|---------|-------------|
391
+ | `--format` | `-f` | `OutputFormat` | inherits global | Per-command output format override |
392
+ | `--json` | — | flag | `false` | Output as JSON |
393
+
394
+ Secrets (`api_key`, `access_token`) are always masked in output.
395
+
396
+ #### `config set` — Set a configuration value
397
+
398
+ | Parameter | Type | Description |
399
+ |-----------|------|-------------|
400
+ | `KEY` | argument (required) | Configuration key (see valid keys below) |
401
+ | `VALUE` | argument (required) | Value to set |
402
+
403
+ #### `config unset` — Remove a configuration value
404
+
405
+ | Parameter | Type | Description |
406
+ |-----------|------|-------------|
407
+ | `KEY` | argument (required) | Configuration key to remove |
408
+
409
+ #### `config path` — Show the configuration file path
410
+
411
+ No options. Prints the absolute path to `config.toml`.
412
+
413
+ **Valid config keys:** `api_key`, `access_token`, `base_url`, `default_model`, `output_format`.
414
+
415
+ ---
416
+
417
+ ### Chat REPL Slash Commands
418
+
419
+ When `cometapi chat` is started without a message, these slash commands are available inside the REPL:
420
+
421
+ | Command | Description |
422
+ |---------|-------------|
423
+ | `/model <name>` | Switch model mid-conversation. Without arg: show current model. |
424
+ | `/system <prompt>` | Set system prompt. Without arg: show current system prompt. |
425
+ | `/clear` | Clear conversation history (preserves system prompt). |
426
+ | `/history` | Display all messages in the conversation. |
427
+ | `/save <file.json\|file.md>` | Export conversation to JSON or Markdown file. |
428
+ | `/tokens` | Show approximate token count and message count. |
429
+ | `/help` | List all slash commands. |
430
+ | `/exit` | Exit the chat REPL (also Ctrl+D, `/quit`, `/q`). |
431
+
432
+ ---
433
+
434
+ ### Exit Codes
435
+
436
+ | Code | Constant | Meaning |
437
+ |------|----------|---------|
438
+ | `0` | `SUCCESS` | Command completed successfully |
439
+ | `1` | `ERROR` | General runtime error |
440
+ | `2` | `USAGE` | Invalid usage (bad arguments, unknown `--type` value, etc.) |
441
+ | `64` | `CONFIG_MISSING` | Required configuration (API key) not set |
442
+ | `69` | `SERVICE_UNAVAILABLE` | API endpoint unreachable |
443
+ | `77` | `AUTH_ERROR` | Authentication failed (invalid key or token) |
444
+ | `78` | `CONFIG_ERROR` | Configuration file corrupt or unreadable |
445
+
446
+ ---
447
+
448
+ ## Build & Test
449
+
450
+ ```bash
451
+ uv sync # Install deps (links local cometapi-python)
452
+ uv run cometapi --version # Verify CLI version
453
+ uv run cometapi -h # List all commands
454
+ uv run cometapi doctor # Check configuration health
455
+ uv run pytest -v # Run tests (98 tests)
456
+ uv run ruff check src/ tests/ # Lint
457
+ ```
458
+
459
+ ## Architecture Conventions
460
+
461
+ - Framework: **Typer** with `rich_markup_mode="rich"` and `no_args_is_help=True`.
462
+ - UI: **Rich** for tables, panels, markdown rendering, and console formatting.
463
+ - Module name: `cometapi_cli` (underscore). Package name: `cometapi-cli` (hyphen).
464
+ - All commands use `typer.Option()` with `Annotated` type hints.
465
+ - Error messages via `err_console.print()` (stderr) with `[red bold]Error:[/]` markup.
466
+ - Config file: TOML format at `~/.config/cometapi/config.toml`, 0600 permissions.
467
+ - Valid config keys: `api_key`, `access_token`, `base_url`, `default_model`, `output_format`.
468
+ - Client creation via `config.get_client()` — resolves auth from env vars + config file.
469
+
470
+ ## Environment Variables
471
+
472
+ | Variable | Required | Purpose |
473
+ |----------|----------|---------|
474
+ | `COMETAPI_KEY` | Yes (for chat/balance/models) | API key for AI relay |
475
+ | `COMETAPI_ACCESS_TOKEN` | Yes (for account/stats/tokens/logs) | Access token for account mgmt |
476
+ | `COMETAPI_BASE_URL` | No | Override default base URL |
477
+
478
+ ## Dependencies
479
+
480
+ - `cometapi` — CometAPI Python SDK (local editable in dev)
481
+ - `typer>=0.12` — CLI framework
482
+ - `rich>=13.0` — Terminal UI
483
+ - `tomli>=2.0` — TOML reading (Python 3.10 only; 3.11+ uses stdlib `tomllib`)
484
+ - `tomli-w>=1.0` — TOML writing
485
+ - `pyyaml>=6.0` — YAML output format
486
+ - `prompt-toolkit>=3.0` — REPL line editing, history, completion
@@ -0,0 +1,46 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ## [0.2.0] — 2026-04-09
9
+
10
+ ### Added
11
+
12
+ - **12 commands**: `chat`, `models`, `balance`, `account`, `stats`, `tokens`, `logs`, `tasks`, `init`, `doctor`, `repl`, `config`
13
+ - **Chat REPL**: multi-turn interactive chat with slash commands (`/model`, `/system`, `/clear`, `/history`, `/save`, `/tokens`)
14
+ - **Command REPL**: interactive shell with tab completion and persistent history
15
+ - **Multi-format output**: table, JSON, YAML, CSV, Markdown via `--format` / `--json`
16
+ - **Logs**: date range filtering (`--start`, `--end`), group filtering (`--group`), CSV export (`--export`), request detail (`--request-id --detail`)
17
+ - **Tasks**: async task logs for Suno, Midjourney, Luma, Kling, and other platforms
18
+ - **Config management**: `config show/set/unset/path` subcommands, TOML config at `~/.config/cometapi/config.toml`
19
+ - **Persistent output_format**: set default output format in `config.toml`
20
+ - **Doctor diagnostics**: connectivity, auth, SDK, and config health checks
21
+ - **Setup wizard**: `cometapi init` with API key validation
22
+ - **Shell completion**: bash, zsh, fish, powershell
23
+ - **Error handling**: structured exit codes (sysexits.h compatible), user-friendly messages
24
+ - **Security**: credential masking, 0600 file permissions, creation URL guidance
25
+ - **CI/CD**: GitHub Actions for testing (Python 3.10–3.13) and PyPI publishing
26
+
27
+ ### Changed
28
+
29
+ - **Config priority**: `CLI flags > config.toml > env vars > defaults` (config file takes precedence over environment variables)
30
+ - Shared constants module — extracted `QUOTA_PER_UNIT`, `quota_to_usd`, `format_ts`, `parse_date`, `extract_items` from duplicated command code
31
+
32
+ ### Fixed
33
+
34
+ - `chat` command now supports `--format` option (was only `--json`)
35
+ - `tokens --search` now applies `--limit` for client-side truncation
36
+ - `logs --search` warns when other filters are silently ignored
37
+ - Corrupt config files now raise `ConfigError` (exit code 78) instead of silently returning empty config
38
+ - `get_default_model()` now respects `COMETAPI_DEFAULT_MODEL` environment variable
39
+
40
+ ## [0.1.0] — 2026-04-07
41
+
42
+ ### Added
43
+
44
+ - Initial release
45
+ - Core commands: `chat`, `models`, `balance`, `init`, `doctor`
46
+ - Basic config file support
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 CometAPI
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.