devin-cli 1.1.8__tar.gz → 1.1.9__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 (53) hide show
  1. {devin_cli-1.1.8 → devin_cli-1.1.9}/CHANGELOG.md +6 -0
  2. {devin_cli-1.1.8 → devin_cli-1.1.9}/PKG-INFO +1 -1
  3. {devin_cli-1.1.8 → devin_cli-1.1.9}/pyproject.toml +1 -1
  4. {devin_cli-1.1.8 → devin_cli-1.1.9}/src/devin_cli/cli.py +44 -7
  5. {devin_cli-1.1.8 → devin_cli-1.1.9}/.github/workflows/pypi-publish.yml +0 -0
  6. {devin_cli-1.1.8 → devin_cli-1.1.9}/.gitignore +0 -0
  7. {devin_cli-1.1.8 → devin_cli-1.1.9}/LICENSE +0 -0
  8. {devin_cli-1.1.8 → devin_cli-1.1.9}/README.md +0 -0
  9. {devin_cli-1.1.8 → devin_cli-1.1.9}/assets/logo.png +0 -0
  10. {devin_cli-1.1.8 → devin_cli-1.1.9}/generate_facades.py +0 -0
  11. {devin_cli-1.1.8 → devin_cli-1.1.9}/setup.py +0 -0
  12. {devin_cli-1.1.8 → devin_cli-1.1.9}/src/devin_cli/__init__.py +0 -0
  13. {devin_cli-1.1.8 → devin_cli-1.1.9}/src/devin_cli/api/__init__.py +0 -0
  14. {devin_cli-1.1.8 → devin_cli-1.1.9}/src/devin_cli/api/attachments.py +0 -0
  15. {devin_cli-1.1.8 → devin_cli-1.1.9}/src/devin_cli/api/client.py +0 -0
  16. {devin_cli-1.1.8 → devin_cli-1.1.9}/src/devin_cli/api/consumption.py +0 -0
  17. {devin_cli-1.1.8 → devin_cli-1.1.9}/src/devin_cli/api/knowledge.py +0 -0
  18. {devin_cli-1.1.8 → devin_cli-1.1.9}/src/devin_cli/api/members.py +0 -0
  19. {devin_cli-1.1.8 → devin_cli-1.1.9}/src/devin_cli/api/organizations.py +0 -0
  20. {devin_cli-1.1.8 → devin_cli-1.1.9}/src/devin_cli/api/playbooks.py +0 -0
  21. {devin_cli-1.1.8 → devin_cli-1.1.9}/src/devin_cli/api/repositories.py +0 -0
  22. {devin_cli-1.1.8 → devin_cli-1.1.9}/src/devin_cli/api/schedules.py +0 -0
  23. {devin_cli-1.1.8 → devin_cli-1.1.9}/src/devin_cli/api/secrets.py +0 -0
  24. {devin_cli-1.1.8 → devin_cli-1.1.9}/src/devin_cli/api/sessions.py +0 -0
  25. {devin_cli-1.1.8 → devin_cli-1.1.9}/src/devin_cli/api/v1/__init__.py +0 -0
  26. {devin_cli-1.1.8 → devin_cli-1.1.9}/src/devin_cli/api/v1/attachments.py +0 -0
  27. {devin_cli-1.1.8 → devin_cli-1.1.9}/src/devin_cli/api/v1/knowledge.py +0 -0
  28. {devin_cli-1.1.8 → devin_cli-1.1.9}/src/devin_cli/api/v1/playbooks.py +0 -0
  29. {devin_cli-1.1.8 → devin_cli-1.1.9}/src/devin_cli/api/v1/secrets.py +0 -0
  30. {devin_cli-1.1.8 → devin_cli-1.1.9}/src/devin_cli/api/v1/sessions.py +0 -0
  31. {devin_cli-1.1.8 → devin_cli-1.1.9}/src/devin_cli/api/v3/__init__.py +0 -0
  32. {devin_cli-1.1.8 → devin_cli-1.1.9}/src/devin_cli/api/v3/attachments.py +0 -0
  33. {devin_cli-1.1.8 → devin_cli-1.1.9}/src/devin_cli/api/v3/consumption.py +0 -0
  34. {devin_cli-1.1.8 → devin_cli-1.1.9}/src/devin_cli/api/v3/knowledge.py +0 -0
  35. {devin_cli-1.1.8 → devin_cli-1.1.9}/src/devin_cli/api/v3/members.py +0 -0
  36. {devin_cli-1.1.8 → devin_cli-1.1.9}/src/devin_cli/api/v3/organizations.py +0 -0
  37. {devin_cli-1.1.8 → devin_cli-1.1.9}/src/devin_cli/api/v3/playbooks.py +0 -0
  38. {devin_cli-1.1.8 → devin_cli-1.1.9}/src/devin_cli/api/v3/repositories.py +0 -0
  39. {devin_cli-1.1.8 → devin_cli-1.1.9}/src/devin_cli/api/v3/schedules.py +0 -0
  40. {devin_cli-1.1.8 → devin_cli-1.1.9}/src/devin_cli/api/v3/secrets.py +0 -0
  41. {devin_cli-1.1.8 → devin_cli-1.1.9}/src/devin_cli/api/v3/sessions.py +0 -0
  42. {devin_cli-1.1.8 → devin_cli-1.1.9}/src/devin_cli/config.py +0 -0
  43. {devin_cli-1.1.8 → devin_cli-1.1.9}/tests/__init__.py +0 -0
  44. {devin_cli-1.1.8 → devin_cli-1.1.9}/tests/conftest.py +0 -0
  45. {devin_cli-1.1.8 → devin_cli-1.1.9}/tests/test_api/test_attachments.py +0 -0
  46. {devin_cli-1.1.8 → devin_cli-1.1.9}/tests/test_api/test_knowledge.py +0 -0
  47. {devin_cli-1.1.8 → devin_cli-1.1.9}/tests/test_api/test_playbooks.py +0 -0
  48. {devin_cli-1.1.8 → devin_cli-1.1.9}/tests/test_api/test_repositories.py +0 -0
  49. {devin_cli-1.1.8 → devin_cli-1.1.9}/tests/test_api/test_schedules.py +0 -0
  50. {devin_cli-1.1.8 → devin_cli-1.1.9}/tests/test_api/test_secrets.py +0 -0
  51. {devin_cli-1.1.8 → devin_cli-1.1.9}/tests/test_api/test_sessions.py +0 -0
  52. {devin_cli-1.1.8 → devin_cli-1.1.9}/tests/test_cli.py +0 -0
  53. {devin_cli-1.1.8 → devin_cli-1.1.9}/tests/test_config.py +0 -0
@@ -5,6 +5,12 @@ 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.9] - 2026-03-11
9
+ ### Fixed
10
+ - `devin watch` terminal status message was printed inside a `Live` context, causing output corruption. Now printed after the `Live` block exits.
11
+ - `update-playbook` was sending an empty string title when `--title` was not passed, overwriting the existing playbook title. Now only sends fields that are explicitly provided.
12
+ - `chain` used bare `resp["session_id"]` key access which would raise `KeyError` on unexpected API responses. Now uses `.get()` with an explicit error guard.
13
+
8
14
  ## [1.1.8] - 2026-03-11
9
15
  ### Added
10
16
  - Restored all 0.1.x flat commands: `watch`, `status`, `open`, `message`, `terminate`, `list-sessions`, `create-session`, `upload`, `list-knowledge`, `attach`, `update-tags`, `history`, `messages`, `get-session`, `update-knowledge`, `update-playbook`, `delete-playbook`, `list-secrets`, `delete-secret`, `chain`.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: devin-cli
3
- Version: 1.1.8
3
+ Version: 1.1.9
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
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "devin-cli"
3
- version = "1.1.8"
3
+ version = "1.1.9"
4
4
  description = "Unofficial CLI for Devin AI - The first AI Software Engineer"
5
5
  readme = "README.md"
6
6
  authors = [
@@ -299,14 +299,25 @@ def session_cost_cmd(
299
299
  @session_app.command("message")
300
300
  @handle_api_error
301
301
  def send_message_cmd(
302
- text: str = typer.Argument(...),
302
+ text: Optional[str] = typer.Argument(None, help="Message text"),
303
+ file: Optional[Path] = typer.Option(None, "--file", "-f", help="Read message from file"),
303
304
  session_id: Optional[str] = typer.Option(None, "--id"),
304
305
  org: Optional[str] = typer.Option(None, "--org"),
305
306
  ):
306
307
  """Send a message to a session."""
307
308
  if org: config.temporary_org_id = org
308
309
  sid = session_id or get_current_session_id()
309
- sessions.send_message(sid, text)
310
+ if file:
311
+ if not file.exists():
312
+ console.print(f"[bold red]Error:[/bold red] File not found: {file}")
313
+ raise typer.Exit(1)
314
+ msg_text = file.read_text()
315
+ elif text:
316
+ msg_text = text
317
+ else:
318
+ console.print("[bold red]Error:[/bold red] Provide message text or --file")
319
+ raise typer.Exit(1)
320
+ sessions.send_message(sid, msg_text)
310
321
  console.print(f"[green]Message sent to {sid}[/green]")
311
322
 
312
323
  @session_app.command("messages")
@@ -708,13 +719,15 @@ def watch_session_cmd(
708
719
 
709
720
  if resp.get("status_enum", "").lower() in terminal_statuses:
710
721
  live.update(build_status_panel(resp))
711
- console.print(f"[bold green]Session {resp.get('status_enum')}![/bold green]")
712
722
  break
713
723
 
714
724
  time.sleep(min(backoff, 30))
715
725
  backoff = min(backoff * 1.5, 30)
716
726
  except KeyboardInterrupt:
717
727
  console.print("\n[dim]Watch stopped.[/dim]")
728
+ return
729
+
730
+ console.print(f"[bold green]Session {resp.get('status_enum')}![/bold green]")
718
731
 
719
732
  # --- Flat top-level aliases (backward compat with 0.1.x command structure) ---
720
733
 
@@ -730,12 +743,23 @@ def watch_cmd(
730
743
  @app.command("message")
731
744
  @handle_api_error
732
745
  def message_cmd(
733
- text: str = typer.Argument(..., help="Message to send"),
746
+ text: Optional[str] = typer.Argument(None, help="Message to send"),
747
+ file: Optional[Path] = typer.Option(None, "--file", "-f", help="Read message from file"),
734
748
  session_id: Optional[str] = typer.Option(None, "--id"),
735
749
  ):
736
750
  """Send a message to the active session."""
737
751
  sid = session_id or get_current_session_id()
738
- sessions.send_message(sid, text)
752
+ if file:
753
+ if not file.exists():
754
+ console.print(f"[bold red]Error:[/bold red] File not found: {file}")
755
+ raise typer.Exit(1)
756
+ msg_text = file.read_text()
757
+ elif text:
758
+ msg_text = text
759
+ else:
760
+ console.print("[bold red]Error:[/bold red] Provide message text or --file")
761
+ raise typer.Exit(1)
762
+ sessions.send_message(sid, msg_text)
739
763
  console.print(f"[green]Message sent to {sid}[/green]")
740
764
 
741
765
  @app.command("terminate")
@@ -895,6 +919,16 @@ def update_playbook_top_cmd(
895
919
  macro: Optional[str] = typer.Option(None, "--macro"),
896
920
  ):
897
921
  """Update an existing playbook."""
922
+ data: dict = {}
923
+ if title is not None:
924
+ data["title"] = title
925
+ if body is not None:
926
+ data["body"] = body
927
+ if macro is not None:
928
+ data["macro"] = macro
929
+ if not data:
930
+ console.print("[yellow]Nothing to update. Pass --title, --body, or --macro.[/yellow]")
931
+ return
898
932
  playbooks.update_playbook(playbook_id, title=title or "", body=body, macro=macro)
899
933
  console.print(f"[green]Playbook {playbook_id} updated.[/green]")
900
934
 
@@ -971,9 +1005,12 @@ def chain_cmd(
971
1005
  console.print(f"[bold cyan]Step {i+1}/{len(steps)}:[/bold cyan] Playbook={step_pb}")
972
1006
 
973
1007
  if i == 0:
974
- with console.status(f"Starting session..."):
1008
+ with console.status("Starting session..."):
975
1009
  resp = sessions.create_session(prompt=step_prompt, playbook_id=step_pb)
976
- current_sid = resp["session_id"]
1010
+ current_sid = resp.get("session_id")
1011
+ if not current_sid:
1012
+ console.print("[bold red]Error:[/bold red] No session ID returned from API.")
1013
+ raise typer.Exit(1)
977
1014
  config.current_session_id = current_sid
978
1015
  console.print(f"[green]Session started:[/green] {current_sid}")
979
1016
  else:
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