cometapi-cli 0.2.0__tar.gz → 0.2.1__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 (74) hide show
  1. {cometapi_cli-0.2.0 → cometapi_cli-0.2.1}/AGENTS.md +2 -2
  2. {cometapi_cli-0.2.0 → cometapi_cli-0.2.1}/CHANGELOG.md +8 -0
  3. {cometapi_cli-0.2.0 → cometapi_cli-0.2.1}/PKG-INFO +6 -10
  4. {cometapi_cli-0.2.0 → cometapi_cli-0.2.1}/README.md +5 -9
  5. {cometapi_cli-0.2.0 → cometapi_cli-0.2.1}/docs/commands/models.md +1 -2
  6. {cometapi_cli-0.2.0 → cometapi_cli-0.2.1}/pyproject.toml +1 -1
  7. {cometapi_cli-0.2.0 → cometapi_cli-0.2.1}/src/cometapi_cli/__init__.py +1 -1
  8. cometapi_cli-0.2.1/src/cometapi_cli/commands/models.py +95 -0
  9. {cometapi_cli-0.2.0 → cometapi_cli-0.2.1}/tests/test_models.py +15 -4
  10. {cometapi_cli-0.2.0 → cometapi_cli-0.2.1}/uv.lock +1 -1
  11. cometapi_cli-0.2.0/src/cometapi_cli/commands/models.py +0 -44
  12. {cometapi_cli-0.2.0 → cometapi_cli-0.2.1}/.github/ISSUE_TEMPLATE/bug_report.yml +0 -0
  13. {cometapi_cli-0.2.0 → cometapi_cli-0.2.1}/.github/ISSUE_TEMPLATE/feature_request.yml +0 -0
  14. {cometapi_cli-0.2.0 → cometapi_cli-0.2.1}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
  15. {cometapi_cli-0.2.0 → cometapi_cli-0.2.1}/.github/workflows/ci.yml +0 -0
  16. {cometapi_cli-0.2.0 → cometapi_cli-0.2.1}/.github/workflows/publish.yml +0 -0
  17. {cometapi_cli-0.2.0 → cometapi_cli-0.2.1}/.gitignore +0 -0
  18. {cometapi_cli-0.2.0 → cometapi_cli-0.2.1}/CODE_OF_CONDUCT.md +0 -0
  19. {cometapi_cli-0.2.0 → cometapi_cli-0.2.1}/CONTRIBUTING.md +0 -0
  20. {cometapi_cli-0.2.0 → cometapi_cli-0.2.1}/LICENSE +0 -0
  21. {cometapi_cli-0.2.0 → cometapi_cli-0.2.1}/SECURITY.md +0 -0
  22. {cometapi_cli-0.2.0 → cometapi_cli-0.2.1}/SKILL.md +0 -0
  23. {cometapi_cli-0.2.0 → cometapi_cli-0.2.1}/docs/README.md +0 -0
  24. {cometapi_cli-0.2.0 → cometapi_cli-0.2.1}/docs/authentication.md +0 -0
  25. {cometapi_cli-0.2.0 → cometapi_cli-0.2.1}/docs/commands/account.md +0 -0
  26. {cometapi_cli-0.2.0 → cometapi_cli-0.2.1}/docs/commands/balance.md +0 -0
  27. {cometapi_cli-0.2.0 → cometapi_cli-0.2.1}/docs/commands/chat.md +0 -0
  28. {cometapi_cli-0.2.0 → cometapi_cli-0.2.1}/docs/commands/config.md +0 -0
  29. {cometapi_cli-0.2.0 → cometapi_cli-0.2.1}/docs/commands/doctor.md +0 -0
  30. {cometapi_cli-0.2.0 → cometapi_cli-0.2.1}/docs/commands/init.md +0 -0
  31. {cometapi_cli-0.2.0 → cometapi_cli-0.2.1}/docs/commands/logs.md +0 -0
  32. {cometapi_cli-0.2.0 → cometapi_cli-0.2.1}/docs/commands/repl.md +0 -0
  33. {cometapi_cli-0.2.0 → cometapi_cli-0.2.1}/docs/commands/stats.md +0 -0
  34. {cometapi_cli-0.2.0 → cometapi_cli-0.2.1}/docs/commands/tasks.md +0 -0
  35. {cometapi_cli-0.2.0 → cometapi_cli-0.2.1}/docs/commands/tokens.md +0 -0
  36. {cometapi_cli-0.2.0 → cometapi_cli-0.2.1}/docs/configuration.md +0 -0
  37. {cometapi_cli-0.2.0 → cometapi_cli-0.2.1}/docs/errors.md +0 -0
  38. {cometapi_cli-0.2.0 → cometapi_cli-0.2.1}/docs/installation.md +0 -0
  39. {cometapi_cli-0.2.0 → cometapi_cli-0.2.1}/docs/output-formats.md +0 -0
  40. {cometapi_cli-0.2.0 → cometapi_cli-0.2.1}/skills/live-test/SKILL.md +0 -0
  41. {cometapi_cli-0.2.0 → cometapi_cli-0.2.1}/src/cometapi_cli/app.py +0 -0
  42. {cometapi_cli-0.2.0 → cometapi_cli-0.2.1}/src/cometapi_cli/client.py +0 -0
  43. {cometapi_cli-0.2.0 → cometapi_cli-0.2.1}/src/cometapi_cli/commands/__init__.py +0 -0
  44. {cometapi_cli-0.2.0 → cometapi_cli-0.2.1}/src/cometapi_cli/commands/account.py +0 -0
  45. {cometapi_cli-0.2.0 → cometapi_cli-0.2.1}/src/cometapi_cli/commands/balance.py +0 -0
  46. {cometapi_cli-0.2.0 → cometapi_cli-0.2.1}/src/cometapi_cli/commands/chat.py +0 -0
  47. {cometapi_cli-0.2.0 → cometapi_cli-0.2.1}/src/cometapi_cli/commands/chat_repl.py +0 -0
  48. {cometapi_cli-0.2.0 → cometapi_cli-0.2.1}/src/cometapi_cli/commands/config_cmd.py +0 -0
  49. {cometapi_cli-0.2.0 → cometapi_cli-0.2.1}/src/cometapi_cli/commands/doctor.py +0 -0
  50. {cometapi_cli-0.2.0 → cometapi_cli-0.2.1}/src/cometapi_cli/commands/logs.py +0 -0
  51. {cometapi_cli-0.2.0 → cometapi_cli-0.2.1}/src/cometapi_cli/commands/repl.py +0 -0
  52. {cometapi_cli-0.2.0 → cometapi_cli-0.2.1}/src/cometapi_cli/commands/stats.py +0 -0
  53. {cometapi_cli-0.2.0 → cometapi_cli-0.2.1}/src/cometapi_cli/commands/tasks.py +0 -0
  54. {cometapi_cli-0.2.0 → cometapi_cli-0.2.1}/src/cometapi_cli/commands/tokens.py +0 -0
  55. {cometapi_cli-0.2.0 → cometapi_cli-0.2.1}/src/cometapi_cli/config.py +0 -0
  56. {cometapi_cli-0.2.0 → cometapi_cli-0.2.1}/src/cometapi_cli/console.py +0 -0
  57. {cometapi_cli-0.2.0 → cometapi_cli-0.2.1}/src/cometapi_cli/constants.py +0 -0
  58. {cometapi_cli-0.2.0 → cometapi_cli-0.2.1}/src/cometapi_cli/errors.py +0 -0
  59. {cometapi_cli-0.2.0 → cometapi_cli-0.2.1}/src/cometapi_cli/formatters.py +0 -0
  60. {cometapi_cli-0.2.0 → cometapi_cli-0.2.1}/src/cometapi_cli/main.py +0 -0
  61. {cometapi_cli-0.2.0 → cometapi_cli-0.2.1}/tests/__init__.py +0 -0
  62. {cometapi_cli-0.2.0 → cometapi_cli-0.2.1}/tests/conftest.py +0 -0
  63. {cometapi_cli-0.2.0 → cometapi_cli-0.2.1}/tests/test_account.py +0 -0
  64. {cometapi_cli-0.2.0 → cometapi_cli-0.2.1}/tests/test_balance.py +0 -0
  65. {cometapi_cli-0.2.0 → cometapi_cli-0.2.1}/tests/test_chat.py +0 -0
  66. {cometapi_cli-0.2.0 → cometapi_cli-0.2.1}/tests/test_config.py +0 -0
  67. {cometapi_cli-0.2.0 → cometapi_cli-0.2.1}/tests/test_doctor.py +0 -0
  68. {cometapi_cli-0.2.0 → cometapi_cli-0.2.1}/tests/test_errors.py +0 -0
  69. {cometapi_cli-0.2.0 → cometapi_cli-0.2.1}/tests/test_formatters.py +0 -0
  70. {cometapi_cli-0.2.0 → cometapi_cli-0.2.1}/tests/test_help.py +0 -0
  71. {cometapi_cli-0.2.0 → cometapi_cli-0.2.1}/tests/test_logs.py +0 -0
  72. {cometapi_cli-0.2.0 → cometapi_cli-0.2.1}/tests/test_stats.py +0 -0
  73. {cometapi_cli-0.2.0 → cometapi_cli-0.2.1}/tests/test_tasks.py +0 -0
  74. {cometapi_cli-0.2.0 → cometapi_cli-0.2.1}/tests/test_tokens.py +0 -0
@@ -189,9 +189,9 @@ These options apply to **every** command via the root Typer callback.
189
189
  | `--format` | `-f` | `OutputFormat` | inherits global | Per-command output format override |
190
190
  | `--json` | — | flag | `false` | Output as JSON |
191
191
 
192
- **Behavior:** Fetches all models via `client.models.list()`, sorts alphabetically by `id`, applies `--search` filter, then `--limit` truncation.
192
+ **Behavior:** Fetches all models via `client.models.list()`, applies `--search`, sorts model IDs in descending natural/version-aware order so newer variants surface first, then applies `--limit`.
193
193
 
194
- **Table columns:** `id` (cyan), `owned_by` (green).
194
+ **Table columns:** `id` (cyan).
195
195
 
196
196
  ---
197
197
 
@@ -5,6 +5,14 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [0.2.1] — 2026-04-14
9
+
10
+ ### Changed
11
+
12
+ - `models` now sorts model IDs in descending natural/version-aware order so newer GPT variants appear first in filtered output.
13
+ - `models` output now only includes the model `id`; the unrelated `owned_by` field is no longer shown in table, JSON, YAML, CSV, or Markdown output.
14
+ - README links were cleaned up for the next PyPI publish: duplicate License heading removed, homepage link kept on `www`, and tracked credential links use UTM parameters.
15
+
8
16
  ## [0.2.0] — 2026-04-13
9
17
 
10
18
  ### Added
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: cometapi-cli
3
- Version: 0.2.0
3
+ Version: 0.2.1
4
4
  Summary: CometAPI CLI — official command-line interface for the CometAPI AI gateway
5
5
  Project-URL: Homepage, https://github.com/cometapi-dev/cometapi-cli
6
6
  Project-URL: Repository, https://github.com/cometapi-dev/cometapi-cli
@@ -42,7 +42,7 @@ Description-Content-Type: text/markdown
42
42
  [![Python](https://img.shields.io/pypi/pyversions/cometapi-cli)](https://pypi.org/project/cometapi-cli/)
43
43
  [![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)
44
44
 
45
- > **Official command-line interface for [CometAPI](https://cometapi.com)** — 500+ AI Model API, All In One API.
45
+ > **Official command-line interface for [CometAPI](https://www.cometapi.com/?utm_source=cometapi-cli&utm_medium=readme&utm_campaign=oss&utm_content=homepage)** — 500+ AI Model API, All In One API.
46
46
 
47
47
  Access 500+ AI models at low cost, directly from the terminal. Chat, search models, check usage, and manage your account — all through a single API key.
48
48
 
@@ -59,7 +59,7 @@ pipx install cometapi-cli # isolated environment
59
59
  uv tool install cometapi-cli # uv
60
60
  ```
61
61
 
62
- **Prerequisites**: Python 3.10+ · [Get your API key](https://www.cometapi.com/console/token)
62
+ **Prerequisites**: Python 3.10+ · [CometAPI Key](https://www.cometapi.com/console/token?utm_source=cometapi-cli&utm_medium=readme&utm_campaign=oss&utm_content=prerequisites)
63
63
 
64
64
  ## Quick Start
65
65
 
@@ -77,8 +77,8 @@ cometapi models --search gpt --limit 10
77
77
  Or configure manually:
78
78
 
79
79
  ```bash
80
- export COMETAPI_KEY="your-api-key" # https://www.cometapi.com/console/token
81
- export COMETAPI_ACCESS_TOKEN="your-access-token" # https://www.cometapi.com/console/personal (optional)
80
+ export COMETAPI_KEY="your-api-key" # https://www.cometapi.com/console/token?utm_source=cometapi-cli&utm_medium=readme&utm_campaign=oss&utm_content=env-api-key
81
+ export COMETAPI_ACCESS_TOKEN="your-access-token" # https://www.cometapi.com/console/personal?utm_source=cometapi-cli&utm_medium=readme&utm_campaign=oss&utm_content=env-access-token (optional)
82
82
  ```
83
83
 
84
84
  ## Commands
@@ -226,7 +226,7 @@ pytest -v
226
226
  - API keys and access tokens are **never** logged or displayed in full — only the last 4 characters are shown
227
227
  - Config files are stored with restrictive permissions (`0600`)
228
228
  - Credentials should **never** be committed to version control
229
- - Create credentials at: [API Key](https://www.cometapi.com/console/token) · [Access Token](https://www.cometapi.com/console/personal)
229
+ - Create credentials at: [API Key](https://www.cometapi.com/console/token?utm_source=cometapi-cli&utm_medium=readme&utm_campaign=oss&utm_content=security-api-key) · [Access Token](https://www.cometapi.com/console/personal?utm_source=cometapi-cli&utm_medium=readme&utm_campaign=oss&utm_content=security-access-token)
230
230
  - **Disclaimer**: You are responsible for all usage and charges incurred with your API keys
231
231
 
232
232
  ## Troubleshooting
@@ -244,7 +244,3 @@ Contributions are welcome! See [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines
244
244
  ## License
245
245
 
246
246
  This project is licensed under the [MIT License](LICENSE).
247
-
248
- ## License
249
-
250
- MIT
@@ -4,7 +4,7 @@
4
4
  [![Python](https://img.shields.io/pypi/pyversions/cometapi-cli)](https://pypi.org/project/cometapi-cli/)
5
5
  [![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)
6
6
 
7
- > **Official command-line interface for [CometAPI](https://cometapi.com)** — 500+ AI Model API, All In One API.
7
+ > **Official command-line interface for [CometAPI](https://www.cometapi.com/?utm_source=cometapi-cli&utm_medium=readme&utm_campaign=oss&utm_content=homepage)** — 500+ AI Model API, All In One API.
8
8
 
9
9
  Access 500+ AI models at low cost, directly from the terminal. Chat, search models, check usage, and manage your account — all through a single API key.
10
10
 
@@ -21,7 +21,7 @@ pipx install cometapi-cli # isolated environment
21
21
  uv tool install cometapi-cli # uv
22
22
  ```
23
23
 
24
- **Prerequisites**: Python 3.10+ · [Get your API key](https://www.cometapi.com/console/token)
24
+ **Prerequisites**: Python 3.10+ · [CometAPI Key](https://www.cometapi.com/console/token?utm_source=cometapi-cli&utm_medium=readme&utm_campaign=oss&utm_content=prerequisites)
25
25
 
26
26
  ## Quick Start
27
27
 
@@ -39,8 +39,8 @@ cometapi models --search gpt --limit 10
39
39
  Or configure manually:
40
40
 
41
41
  ```bash
42
- export COMETAPI_KEY="your-api-key" # https://www.cometapi.com/console/token
43
- export COMETAPI_ACCESS_TOKEN="your-access-token" # https://www.cometapi.com/console/personal (optional)
42
+ export COMETAPI_KEY="your-api-key" # https://www.cometapi.com/console/token?utm_source=cometapi-cli&utm_medium=readme&utm_campaign=oss&utm_content=env-api-key
43
+ export COMETAPI_ACCESS_TOKEN="your-access-token" # https://www.cometapi.com/console/personal?utm_source=cometapi-cli&utm_medium=readme&utm_campaign=oss&utm_content=env-access-token (optional)
44
44
  ```
45
45
 
46
46
  ## Commands
@@ -188,7 +188,7 @@ pytest -v
188
188
  - API keys and access tokens are **never** logged or displayed in full — only the last 4 characters are shown
189
189
  - Config files are stored with restrictive permissions (`0600`)
190
190
  - Credentials should **never** be committed to version control
191
- - Create credentials at: [API Key](https://www.cometapi.com/console/token) · [Access Token](https://www.cometapi.com/console/personal)
191
+ - Create credentials at: [API Key](https://www.cometapi.com/console/token?utm_source=cometapi-cli&utm_medium=readme&utm_campaign=oss&utm_content=security-api-key) · [Access Token](https://www.cometapi.com/console/personal?utm_source=cometapi-cli&utm_medium=readme&utm_campaign=oss&utm_content=security-access-token)
192
192
  - **Disclaimer**: You are responsible for all usage and charges incurred with your API keys
193
193
 
194
194
  ## Troubleshooting
@@ -206,7 +206,3 @@ Contributions are welcome! See [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines
206
206
  ## License
207
207
 
208
208
  This project is licensed under the [MIT License](LICENSE).
209
-
210
- ## License
211
-
212
- MIT
@@ -22,7 +22,7 @@ Requires `COMETAPI_KEY`. Access token is not needed.
22
22
 
23
23
  ## Behavior
24
24
 
25
- - Results are sorted alphabetically by model ID.
25
+ - Results are sorted in descending natural/version-aware order so newer model IDs surface first.
26
26
  - `--search` performs a case-insensitive substring match on the model `id` field.
27
27
  - `--limit` is applied after filtering and sorting.
28
28
 
@@ -31,7 +31,6 @@ Requires `COMETAPI_KEY`. Access token is not needed.
31
31
  | Column | Description |
32
32
  |--------|-------------|
33
33
  | `id` | Model identifier (e.g., `gpt-5.4`, `claude-sonnet-4-6`) |
34
- | `owned_by` | Model provider (e.g., `openai`, `anthropic`) |
35
34
 
36
35
  ## Examples
37
36
 
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "cometapi-cli"
3
- version = "0.2.0"
3
+ version = "0.2.1"
4
4
  description = "CometAPI CLI — official command-line interface for the CometAPI AI gateway"
5
5
  readme = "README.md"
6
6
  license = { text = "MIT" }
@@ -1,3 +1,3 @@
1
1
  """CometAPI CLI — professional terminal interface for CometAPI."""
2
2
 
3
- __version__ = "0.2.0"
3
+ __version__ = "0.2.1"
@@ -0,0 +1,95 @@
1
+ """Models command."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import re
6
+ from functools import cmp_to_key
7
+ from typing import Annotated
8
+
9
+ import typer
10
+
11
+ from ..config import get_client
12
+ from ..errors import handle_errors
13
+ from ..formatters import OutputFormat, output, resolve_format
14
+
15
+ _MODEL_TOKEN_RE = re.compile(r"[a-z]+|\d+")
16
+
17
+
18
+ def _tokenize_model_id(model_id: str) -> list[str | int]:
19
+ tokens: list[str | int] = []
20
+ for segment in re.split(r"[-.]+", model_id.lower()):
21
+ if not segment:
22
+ continue
23
+ for part in _MODEL_TOKEN_RE.findall(segment):
24
+ tokens.append(int(part) if part.isdigit() else part)
25
+ return tokens
26
+
27
+
28
+ def _compare_model_ids(left: str, right: str) -> int:
29
+ left_tokens = _tokenize_model_id(left)
30
+ right_tokens = _tokenize_model_id(right)
31
+
32
+ for left_token, right_token in zip(left_tokens, right_tokens):
33
+ if left_token == right_token:
34
+ continue
35
+
36
+ if isinstance(left_token, int) and isinstance(right_token, int):
37
+ return -1 if left_token > right_token else 1
38
+
39
+ if isinstance(left_token, int):
40
+ return -1
41
+ if isinstance(right_token, int):
42
+ return 1
43
+
44
+ return -1 if left_token > right_token else 1
45
+
46
+ if len(left_tokens) == len(right_tokens):
47
+ if left.lower() == right.lower():
48
+ return 0
49
+ return -1 if left.lower() > right.lower() else 1
50
+
51
+ if len(left_tokens) < len(right_tokens):
52
+ next_token = right_tokens[len(left_tokens)]
53
+ return 1 if isinstance(next_token, int) else -1
54
+
55
+ next_token = left_tokens[len(right_tokens)]
56
+ return -1 if isinstance(next_token, int) else 1
57
+
58
+
59
+ def _compare_model_rows(left: dict[str, str], right: dict[str, str]) -> int:
60
+ return _compare_model_ids(left["id"], right["id"])
61
+
62
+
63
+ @handle_errors
64
+ def models(
65
+ ctx: typer.Context,
66
+ search: Annotated[str | None, typer.Option("--search", "-s", help="Filter models by name.")] = None,
67
+ limit: Annotated[int | None, typer.Option("--limit", "-l", help="Max number of models to show.")] = None,
68
+ output_format: Annotated[
69
+ OutputFormat | None,
70
+ typer.Option("--format", "-f", help="Output format (table, json, yaml, csv, markdown)."),
71
+ ] = None,
72
+ json_output: Annotated[bool, typer.Option("--json", help="Output as JSON.")] = False,
73
+ ) -> None:
74
+ """List available models."""
75
+ fmt = resolve_format(ctx, json_output, output_format)
76
+ client = get_client()
77
+ result = client.models.list()
78
+
79
+ rows = [{"id": m.id} for m in result]
80
+
81
+ if search:
82
+ term = search.lower()
83
+ rows = [r for r in rows if term in r["id"].lower()]
84
+
85
+ rows = sorted(rows, key=cmp_to_key(_compare_model_rows))
86
+
87
+ if limit and limit > 0:
88
+ rows = rows[:limit]
89
+
90
+ output(
91
+ rows,
92
+ fmt,
93
+ title=f"Available Models ({len(rows)})",
94
+ columns={"id": "cyan"},
95
+ )
@@ -4,20 +4,21 @@ from __future__ import annotations
4
4
 
5
5
  import json
6
6
 
7
+ from tests.conftest import _make_models_response
8
+
7
9
 
8
10
  def test_models_json(cli_runner, patched_client):
9
11
  result = cli_runner("models", "--json")
10
12
  assert result.exit_code == 0
11
13
  data = json.loads(result.output)
12
- assert isinstance(data, list)
13
- assert len(data) == 3
14
- assert data[0]["id"] == "claude-sonnet-4-6" # sorted alphabetically
14
+ assert data == [{"id": "gpt-5.4"}, {"id": "gpt-5.4-mini"}, {"id": "claude-sonnet-4-6"}]
15
15
 
16
16
 
17
17
  def test_models_table(cli_runner, patched_client):
18
18
  result = cli_runner("models")
19
19
  assert result.exit_code == 0
20
20
  assert "gpt-5.4" in result.output
21
+ assert "Owned By" not in result.output
21
22
 
22
23
 
23
24
  def test_models_search(cli_runner, patched_client):
@@ -27,6 +28,16 @@ def test_models_search(cli_runner, patched_client):
27
28
  assert all("gpt" in m["id"] for m in data)
28
29
 
29
30
 
31
+ def test_models_search_prioritizes_newest_versions(cli_runner, patched_client):
32
+ patched_client.models.list.return_value = _make_models_response(
33
+ ["gpt-3.5-turbo", "gpt-5-mini", "gpt-5", "gpt-5.4-mini", "gpt-4.1", "gpt-5.4"]
34
+ )
35
+ result = cli_runner("models", "--search", "gpt", "--limit", "5", "--json")
36
+ assert result.exit_code == 0
37
+ data = json.loads(result.output)
38
+ assert [model["id"] for model in data] == ["gpt-5.4", "gpt-5.4-mini", "gpt-5", "gpt-5-mini", "gpt-4.1"]
39
+
40
+
30
41
  def test_models_limit(cli_runner, patched_client):
31
42
  result = cli_runner("models", "--limit", "1", "--json")
32
43
  assert result.exit_code == 0
@@ -43,4 +54,4 @@ def test_models_yaml(cli_runner, patched_client):
43
54
  def test_models_csv(cli_runner, patched_client):
44
55
  result = cli_runner("--format", "csv", "models")
45
56
  assert result.exit_code == 0
46
- assert "id,owned_by" in result.output
57
+ assert result.output.splitlines()[0] == "id"
@@ -66,7 +66,7 @@ wheels = [
66
66
 
67
67
  [[package]]
68
68
  name = "cometapi-cli"
69
- version = "0.1.0"
69
+ version = "0.2.1"
70
70
  source = { editable = "." }
71
71
  dependencies = [
72
72
  { name = "openai" },
@@ -1,44 +0,0 @@
1
- """Models command."""
2
-
3
- from __future__ import annotations
4
-
5
- from typing import Annotated
6
-
7
- import typer
8
-
9
- from ..config import get_client
10
- from ..errors import handle_errors
11
- from ..formatters import OutputFormat, output, resolve_format
12
-
13
-
14
- @handle_errors
15
- def models(
16
- ctx: typer.Context,
17
- search: Annotated[str | None, typer.Option("--search", "-s", help="Filter models by name.")] = None,
18
- limit: Annotated[int | None, typer.Option("--limit", "-l", help="Max number of models to show.")] = None,
19
- output_format: Annotated[OutputFormat | None, typer.Option("--format", "-f", help="Output format (table, json, yaml, csv, markdown).")] = None,
20
- json_output: Annotated[bool, typer.Option("--json", help="Output as JSON.")] = False,
21
- ) -> None:
22
- """List available models."""
23
- fmt = resolve_format(ctx, json_output, output_format)
24
- client = get_client()
25
- result = client.models.list()
26
-
27
- rows = sorted(
28
- [{"id": m.id, "owned_by": m.owned_by} for m in result],
29
- key=lambda r: r["id"],
30
- )
31
-
32
- if search:
33
- term = search.lower()
34
- rows = [r for r in rows if term in r["id"].lower()]
35
-
36
- if limit and limit > 0:
37
- rows = rows[:limit]
38
-
39
- output(
40
- rows,
41
- fmt,
42
- title=f"Available Models ({len(rows)})",
43
- columns={"id": "cyan", "owned_by": "green"},
44
- )
File without changes
File without changes
File without changes
File without changes