devin-cli 1.1.1__tar.gz → 1.1.3__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.
- {devin_cli-1.1.1 → devin_cli-1.1.3}/CHANGELOG.md +12 -0
- {devin_cli-1.1.1 → devin_cli-1.1.3}/PKG-INFO +1 -1
- {devin_cli-1.1.1 → devin_cli-1.1.3}/pyproject.toml +1 -1
- {devin_cli-1.1.1 → devin_cli-1.1.3}/src/devin_cli/cli.py +39 -11
- devin_cli-1.1.3/test_profile.py +3 -0
- {devin_cli-1.1.1 → devin_cli-1.1.3}/tests/test_cli.py +1 -1
- {devin_cli-1.1.1 → devin_cli-1.1.3}/.github/workflows/pypi-publish.yml +0 -0
- {devin_cli-1.1.1 → devin_cli-1.1.3}/.gitignore +0 -0
- {devin_cli-1.1.1 → devin_cli-1.1.3}/LICENSE +0 -0
- {devin_cli-1.1.1 → devin_cli-1.1.3}/README.md +0 -0
- {devin_cli-1.1.1 → devin_cli-1.1.3}/assets/logo.png +0 -0
- {devin_cli-1.1.1 → devin_cli-1.1.3}/generate_facades.py +0 -0
- {devin_cli-1.1.1 → devin_cli-1.1.3}/setup.py +0 -0
- {devin_cli-1.1.1 → devin_cli-1.1.3}/src/devin_cli/__init__.py +0 -0
- {devin_cli-1.1.1 → devin_cli-1.1.3}/src/devin_cli/api/__init__.py +0 -0
- {devin_cli-1.1.1 → devin_cli-1.1.3}/src/devin_cli/api/attachments.py +0 -0
- {devin_cli-1.1.1 → devin_cli-1.1.3}/src/devin_cli/api/client.py +0 -0
- {devin_cli-1.1.1 → devin_cli-1.1.3}/src/devin_cli/api/consumption.py +0 -0
- {devin_cli-1.1.1 → devin_cli-1.1.3}/src/devin_cli/api/knowledge.py +0 -0
- {devin_cli-1.1.1 → devin_cli-1.1.3}/src/devin_cli/api/members.py +0 -0
- {devin_cli-1.1.1 → devin_cli-1.1.3}/src/devin_cli/api/organizations.py +0 -0
- {devin_cli-1.1.1 → devin_cli-1.1.3}/src/devin_cli/api/playbooks.py +0 -0
- {devin_cli-1.1.1 → devin_cli-1.1.3}/src/devin_cli/api/repositories.py +0 -0
- {devin_cli-1.1.1 → devin_cli-1.1.3}/src/devin_cli/api/schedules.py +0 -0
- {devin_cli-1.1.1 → devin_cli-1.1.3}/src/devin_cli/api/secrets.py +0 -0
- {devin_cli-1.1.1 → devin_cli-1.1.3}/src/devin_cli/api/sessions.py +0 -0
- {devin_cli-1.1.1 → devin_cli-1.1.3}/src/devin_cli/api/v1/__init__.py +0 -0
- {devin_cli-1.1.1 → devin_cli-1.1.3}/src/devin_cli/api/v1/attachments.py +0 -0
- {devin_cli-1.1.1 → devin_cli-1.1.3}/src/devin_cli/api/v1/knowledge.py +0 -0
- {devin_cli-1.1.1 → devin_cli-1.1.3}/src/devin_cli/api/v1/playbooks.py +0 -0
- {devin_cli-1.1.1 → devin_cli-1.1.3}/src/devin_cli/api/v1/secrets.py +0 -0
- {devin_cli-1.1.1 → devin_cli-1.1.3}/src/devin_cli/api/v1/sessions.py +0 -0
- {devin_cli-1.1.1 → devin_cli-1.1.3}/src/devin_cli/api/v3/__init__.py +0 -0
- {devin_cli-1.1.1 → devin_cli-1.1.3}/src/devin_cli/api/v3/attachments.py +0 -0
- {devin_cli-1.1.1 → devin_cli-1.1.3}/src/devin_cli/api/v3/consumption.py +0 -0
- {devin_cli-1.1.1 → devin_cli-1.1.3}/src/devin_cli/api/v3/knowledge.py +0 -0
- {devin_cli-1.1.1 → devin_cli-1.1.3}/src/devin_cli/api/v3/members.py +0 -0
- {devin_cli-1.1.1 → devin_cli-1.1.3}/src/devin_cli/api/v3/organizations.py +0 -0
- {devin_cli-1.1.1 → devin_cli-1.1.3}/src/devin_cli/api/v3/playbooks.py +0 -0
- {devin_cli-1.1.1 → devin_cli-1.1.3}/src/devin_cli/api/v3/repositories.py +0 -0
- {devin_cli-1.1.1 → devin_cli-1.1.3}/src/devin_cli/api/v3/schedules.py +0 -0
- {devin_cli-1.1.1 → devin_cli-1.1.3}/src/devin_cli/api/v3/secrets.py +0 -0
- {devin_cli-1.1.1 → devin_cli-1.1.3}/src/devin_cli/api/v3/sessions.py +0 -0
- {devin_cli-1.1.1 → devin_cli-1.1.3}/src/devin_cli/config.py +0 -0
- {devin_cli-1.1.1 → devin_cli-1.1.3}/test_duplicate.py +0 -0
- {devin_cli-1.1.1 → devin_cli-1.1.3}/tests/__init__.py +0 -0
- {devin_cli-1.1.1 → devin_cli-1.1.3}/tests/conftest.py +0 -0
- {devin_cli-1.1.1 → devin_cli-1.1.3}/tests/test_api/test_attachments.py +0 -0
- {devin_cli-1.1.1 → devin_cli-1.1.3}/tests/test_api/test_knowledge.py +0 -0
- {devin_cli-1.1.1 → devin_cli-1.1.3}/tests/test_api/test_playbooks.py +0 -0
- {devin_cli-1.1.1 → devin_cli-1.1.3}/tests/test_api/test_repositories.py +0 -0
- {devin_cli-1.1.1 → devin_cli-1.1.3}/tests/test_api/test_schedules.py +0 -0
- {devin_cli-1.1.1 → devin_cli-1.1.3}/tests/test_api/test_secrets.py +0 -0
- {devin_cli-1.1.1 → devin_cli-1.1.3}/tests/test_api/test_sessions.py +0 -0
- {devin_cli-1.1.1 → devin_cli-1.1.3}/tests/test_config.py +0 -0
|
@@ -5,6 +5,18 @@ 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.0.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [1.1.3] - 2026-03-11
|
|
9
|
+
### Fixed
|
|
10
|
+
- `repos list` now resolves blank Path column by trying `repository_path`, `path`, and `name` keys from the API response.
|
|
11
|
+
- `secrets list` no longer crashes when the API returns a raw list instead of a dict with a key.
|
|
12
|
+
- `sessions cost <id>` now pulls cost data from the org-scoped `get_session` endpoint instead of the enterprise-only consumption path.
|
|
13
|
+
- `sessions insights` on v1 now displays a readable error with a hint to switch to v3 instead of a confusing JSON blob.
|
|
14
|
+
- `--json` flag added to `repos list` and `secrets list` for raw programmatic output.
|
|
15
|
+
|
|
16
|
+
## [1.1.2] - 2026-03-11
|
|
17
|
+
### Fixed
|
|
18
|
+
- **Critical Profile Bug**: Stopped `cli.py` from statically overriding the active user profile back to `"default"` on every boot unless the `--profile` flag is explicitly passed over the terminal.
|
|
19
|
+
|
|
8
20
|
## [1.1.1] - 2026-03-11
|
|
9
21
|
### Fixed
|
|
10
22
|
- Fixed v1 API HTTP redirects stripping authorization headers on org-scoped endpoints (403 errors).
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: devin-cli
|
|
3
|
-
Version: 1.1.
|
|
3
|
+
Version: 1.1.3
|
|
4
4
|
Summary: Unofficial CLI for Devin AI - The first AI Software Engineer
|
|
5
5
|
Project-URL: Homepage, https://github.com/revanthpobala/devin-cli
|
|
6
6
|
Project-URL: Repository, https://github.com/revanthpobala/devin-cli.git
|
|
@@ -78,7 +78,7 @@ ASCII_LOGO = r"""
|
|
|
78
78
|
@app.callback(invoke_without_command=True)
|
|
79
79
|
def main(
|
|
80
80
|
ctx: typer.Context,
|
|
81
|
-
profile: str = typer.Option(
|
|
81
|
+
profile: Optional[str] = typer.Option(None, "--profile", "-p", help="Configuration profile to use (e.g., service, personal)"),
|
|
82
82
|
version: Optional[bool] = typer.Option(None, "--version", "-v", help="Show the application's version and exit."),
|
|
83
83
|
):
|
|
84
84
|
"""
|
|
@@ -88,7 +88,8 @@ def main(
|
|
|
88
88
|
console.print(f"devin CLI version: {__version__}")
|
|
89
89
|
raise typer.Exit()
|
|
90
90
|
|
|
91
|
-
|
|
91
|
+
if profile:
|
|
92
|
+
config.active_profile = profile
|
|
92
93
|
if ctx.invoked_subcommand is None:
|
|
93
94
|
console.print(ASCII_LOGO)
|
|
94
95
|
|
|
@@ -254,7 +255,11 @@ def session_insights_cmd(
|
|
|
254
255
|
if org: config.temporary_org_id = org
|
|
255
256
|
sid = session_id or get_current_session_id()
|
|
256
257
|
resp = sessions.get_session_insights(sid)
|
|
257
|
-
|
|
258
|
+
if isinstance(resp, dict) and "error" in resp:
|
|
259
|
+
console.print(f"[bold yellow]Note:[/bold yellow] {resp['error']}")
|
|
260
|
+
console.print("Tip: Switch to v3 with [bold cyan]devin configure[/bold cyan] or use [bold cyan]--profile [v3-profile][/bold cyan]")
|
|
261
|
+
else:
|
|
262
|
+
console.print(Panel(json.dumps(resp, indent=2), title=f"Insights for {sid}"))
|
|
258
263
|
|
|
259
264
|
@session_app.command("cost")
|
|
260
265
|
@handle_api_error
|
|
@@ -265,10 +270,12 @@ def session_cost_cmd(
|
|
|
265
270
|
"""View ACU consumption."""
|
|
266
271
|
if org: config.temporary_org_id = org
|
|
267
272
|
if session_id:
|
|
268
|
-
resp =
|
|
273
|
+
resp = sessions.get_session(session_id)
|
|
274
|
+
cost_data = {"session_id": resp.get("session_id"), "status": resp.get("status_enum"), "acu_used": resp.get("acu_used")}
|
|
275
|
+
console.print(Panel(json.dumps(cost_data, indent=2), title=f"Session Cost: {session_id}"))
|
|
269
276
|
else:
|
|
270
277
|
resp = consumption.get_daily_consumption_breakdown()
|
|
271
|
-
|
|
278
|
+
console.print(Panel(json.dumps(resp, indent=2), title="Daily Consumption"))
|
|
272
279
|
|
|
273
280
|
@session_app.command("message")
|
|
274
281
|
@handle_api_error
|
|
@@ -424,15 +431,29 @@ def delete_playbook_cmd(
|
|
|
424
431
|
# --- Secrets ---
|
|
425
432
|
@secret_app.command("list")
|
|
426
433
|
@handle_api_error
|
|
427
|
-
def list_secrets_cmd(
|
|
434
|
+
def list_secrets_cmd(
|
|
435
|
+
org: Optional[str] = typer.Option(None, "--org"),
|
|
436
|
+
json_output: bool = typer.Option(False, "--json"),
|
|
437
|
+
):
|
|
428
438
|
"""List organization secrets."""
|
|
429
439
|
if org: config.temporary_org_id = org
|
|
430
440
|
resp = secrets.list_secrets()
|
|
441
|
+
if isinstance(resp, dict):
|
|
442
|
+
items = resp.get("secrets", resp.get("items", []))
|
|
443
|
+
elif isinstance(resp, list):
|
|
444
|
+
items = resp
|
|
445
|
+
else:
|
|
446
|
+
console.print(f"[yellow]Unexpected response format: {type(resp).__name__}[/yellow]")
|
|
447
|
+
items = []
|
|
448
|
+
if json_output:
|
|
449
|
+
console.print(json.dumps(items, indent=2))
|
|
450
|
+
return
|
|
431
451
|
table = Table(title="Secrets")
|
|
432
452
|
table.add_column("ID", style="cyan")
|
|
433
453
|
table.add_column("Name")
|
|
434
|
-
for item in
|
|
435
|
-
|
|
454
|
+
for item in items:
|
|
455
|
+
if isinstance(item, dict):
|
|
456
|
+
table.add_row(item.get("id"), item.get("name"))
|
|
436
457
|
console.print(table)
|
|
437
458
|
|
|
438
459
|
@secret_app.command("delete")
|
|
@@ -491,16 +512,23 @@ def create_schedule_cmd(
|
|
|
491
512
|
# --- Repositories ---
|
|
492
513
|
@repo_app.command("list")
|
|
493
514
|
@handle_api_error
|
|
494
|
-
def list_repos_cmd(
|
|
515
|
+
def list_repos_cmd(
|
|
516
|
+
org: Optional[str] = typer.Option(None, "--org"),
|
|
517
|
+
json_output: bool = typer.Option(False, "--json"),
|
|
518
|
+
):
|
|
495
519
|
"""List repositories indexed for Devin."""
|
|
496
520
|
if org: config.temporary_org_id = org
|
|
497
521
|
resp = repositories.list_repositories()
|
|
498
|
-
items = resp.get("items", [])
|
|
522
|
+
items = resp.get("repositories", resp.get("items", []))
|
|
523
|
+
if json_output:
|
|
524
|
+
console.print(json.dumps(items, indent=2))
|
|
525
|
+
return
|
|
499
526
|
table = Table(title="Repositories")
|
|
500
527
|
table.add_column("Path", style="cyan")
|
|
501
528
|
table.add_column("Indexed", style="green")
|
|
502
529
|
for item in items:
|
|
503
|
-
|
|
530
|
+
path = item.get("repository_path") or item.get("path") or item.get("name", "")
|
|
531
|
+
table.add_row(path, "Yes" if item.get("is_indexed") else "No")
|
|
504
532
|
console.print(table)
|
|
505
533
|
|
|
506
534
|
@repo_app.command("index")
|
|
@@ -7,7 +7,7 @@ runner = CliRunner()
|
|
|
7
7
|
def test_app_help():
|
|
8
8
|
result = runner.invoke(app, ["--help"])
|
|
9
9
|
assert result.exit_code == 0
|
|
10
|
-
assert "Unofficial CLI for Devin AI
|
|
10
|
+
assert "Unofficial CLI for Devin AI" in result.stdout
|
|
11
11
|
|
|
12
12
|
def test_app_configure_help():
|
|
13
13
|
result = runner.invoke(app, ["configure", "--help"])
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|