devin-cli 1.1.9__tar.gz → 1.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 (53) hide show
  1. {devin_cli-1.1.9 → devin_cli-1.2.1}/CHANGELOG.md +9 -0
  2. {devin_cli-1.1.9 → devin_cli-1.2.1}/PKG-INFO +1 -1
  3. {devin_cli-1.1.9 → devin_cli-1.2.1}/pyproject.toml +1 -1
  4. {devin_cli-1.1.9 → devin_cli-1.2.1}/src/devin_cli/api/v1/sessions.py +13 -8
  5. {devin_cli-1.1.9 → devin_cli-1.2.1}/src/devin_cli/api/v3/sessions.py +3 -0
  6. {devin_cli-1.1.9 → devin_cli-1.2.1}/src/devin_cli/cli.py +44 -8
  7. {devin_cli-1.1.9 → devin_cli-1.2.1}/.github/workflows/pypi-publish.yml +0 -0
  8. {devin_cli-1.1.9 → devin_cli-1.2.1}/.gitignore +0 -0
  9. {devin_cli-1.1.9 → devin_cli-1.2.1}/LICENSE +0 -0
  10. {devin_cli-1.1.9 → devin_cli-1.2.1}/README.md +0 -0
  11. {devin_cli-1.1.9 → devin_cli-1.2.1}/assets/logo.png +0 -0
  12. {devin_cli-1.1.9 → devin_cli-1.2.1}/generate_facades.py +0 -0
  13. {devin_cli-1.1.9 → devin_cli-1.2.1}/setup.py +0 -0
  14. {devin_cli-1.1.9 → devin_cli-1.2.1}/src/devin_cli/__init__.py +0 -0
  15. {devin_cli-1.1.9 → devin_cli-1.2.1}/src/devin_cli/api/__init__.py +0 -0
  16. {devin_cli-1.1.9 → devin_cli-1.2.1}/src/devin_cli/api/attachments.py +0 -0
  17. {devin_cli-1.1.9 → devin_cli-1.2.1}/src/devin_cli/api/client.py +0 -0
  18. {devin_cli-1.1.9 → devin_cli-1.2.1}/src/devin_cli/api/consumption.py +0 -0
  19. {devin_cli-1.1.9 → devin_cli-1.2.1}/src/devin_cli/api/knowledge.py +0 -0
  20. {devin_cli-1.1.9 → devin_cli-1.2.1}/src/devin_cli/api/members.py +0 -0
  21. {devin_cli-1.1.9 → devin_cli-1.2.1}/src/devin_cli/api/organizations.py +0 -0
  22. {devin_cli-1.1.9 → devin_cli-1.2.1}/src/devin_cli/api/playbooks.py +0 -0
  23. {devin_cli-1.1.9 → devin_cli-1.2.1}/src/devin_cli/api/repositories.py +0 -0
  24. {devin_cli-1.1.9 → devin_cli-1.2.1}/src/devin_cli/api/schedules.py +0 -0
  25. {devin_cli-1.1.9 → devin_cli-1.2.1}/src/devin_cli/api/secrets.py +0 -0
  26. {devin_cli-1.1.9 → devin_cli-1.2.1}/src/devin_cli/api/sessions.py +0 -0
  27. {devin_cli-1.1.9 → devin_cli-1.2.1}/src/devin_cli/api/v1/__init__.py +0 -0
  28. {devin_cli-1.1.9 → devin_cli-1.2.1}/src/devin_cli/api/v1/attachments.py +0 -0
  29. {devin_cli-1.1.9 → devin_cli-1.2.1}/src/devin_cli/api/v1/knowledge.py +0 -0
  30. {devin_cli-1.1.9 → devin_cli-1.2.1}/src/devin_cli/api/v1/playbooks.py +0 -0
  31. {devin_cli-1.1.9 → devin_cli-1.2.1}/src/devin_cli/api/v1/secrets.py +0 -0
  32. {devin_cli-1.1.9 → devin_cli-1.2.1}/src/devin_cli/api/v3/__init__.py +0 -0
  33. {devin_cli-1.1.9 → devin_cli-1.2.1}/src/devin_cli/api/v3/attachments.py +0 -0
  34. {devin_cli-1.1.9 → devin_cli-1.2.1}/src/devin_cli/api/v3/consumption.py +0 -0
  35. {devin_cli-1.1.9 → devin_cli-1.2.1}/src/devin_cli/api/v3/knowledge.py +0 -0
  36. {devin_cli-1.1.9 → devin_cli-1.2.1}/src/devin_cli/api/v3/members.py +0 -0
  37. {devin_cli-1.1.9 → devin_cli-1.2.1}/src/devin_cli/api/v3/organizations.py +0 -0
  38. {devin_cli-1.1.9 → devin_cli-1.2.1}/src/devin_cli/api/v3/playbooks.py +0 -0
  39. {devin_cli-1.1.9 → devin_cli-1.2.1}/src/devin_cli/api/v3/repositories.py +0 -0
  40. {devin_cli-1.1.9 → devin_cli-1.2.1}/src/devin_cli/api/v3/schedules.py +0 -0
  41. {devin_cli-1.1.9 → devin_cli-1.2.1}/src/devin_cli/api/v3/secrets.py +0 -0
  42. {devin_cli-1.1.9 → devin_cli-1.2.1}/src/devin_cli/config.py +0 -0
  43. {devin_cli-1.1.9 → devin_cli-1.2.1}/tests/__init__.py +0 -0
  44. {devin_cli-1.1.9 → devin_cli-1.2.1}/tests/conftest.py +0 -0
  45. {devin_cli-1.1.9 → devin_cli-1.2.1}/tests/test_api/test_attachments.py +0 -0
  46. {devin_cli-1.1.9 → devin_cli-1.2.1}/tests/test_api/test_knowledge.py +0 -0
  47. {devin_cli-1.1.9 → devin_cli-1.2.1}/tests/test_api/test_playbooks.py +0 -0
  48. {devin_cli-1.1.9 → devin_cli-1.2.1}/tests/test_api/test_repositories.py +0 -0
  49. {devin_cli-1.1.9 → devin_cli-1.2.1}/tests/test_api/test_schedules.py +0 -0
  50. {devin_cli-1.1.9 → devin_cli-1.2.1}/tests/test_api/test_secrets.py +0 -0
  51. {devin_cli-1.1.9 → devin_cli-1.2.1}/tests/test_api/test_sessions.py +0 -0
  52. {devin_cli-1.1.9 → devin_cli-1.2.1}/tests/test_cli.py +0 -0
  53. {devin_cli-1.1.9 → devin_cli-1.2.1}/tests/test_config.py +0 -0
@@ -5,6 +5,15 @@ 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.2.0] - 2026-03-11
9
+ ### Added
10
+ - `sessions create` / `create-session` now exposes all 8 previously missing v3 API parameters: `--playbook-id`, `--tag`, `--repo`, `--knowledge-id`, `--secret-id`, `--session-link`, `--attachment-url`, `--create-as-user-id`.
11
+ - Profile feedback on session create: prints which profile and API version is being used.
12
+ - Explicit warning when v3-only flags (`--advanced-mode`, `--playbook-id`, `--repo`, `--secret-id`, `--session-link`, `--attachment-url`, `--create-as-user-id`) are passed on a v1 profile — instead of silently ignored.
13
+ ### Fixed
14
+ - Removed `**kwargs` anti-pattern from `v1/sessions.create_session`. Typos in keyword args now raise `TypeError` instead of silently vanishing.
15
+ - v3-only params added as explicit no-ops in v1 `create_session` so the shared CLI call site works without `TypeError`.
16
+
8
17
  ## [1.1.9] - 2026-03-11
9
18
  ### Fixed
10
19
  - `devin watch` terminal status message was printed inside a `Live` context, causing output corruption. Now printed after the `Live` block exits.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: devin-cli
3
- Version: 1.1.9
3
+ Version: 1.2.1
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.9"
3
+ version = "1.2.1"
4
4
  description = "Unofficial CLI for Devin AI - The first AI Software Engineer"
5
5
  readme = "README.md"
6
6
  authors = [
@@ -1,7 +1,7 @@
1
1
  from typing import List, Optional
2
2
  from devin_cli.api.client import client
3
3
 
4
- def list_sessions(limit: int = 100, offset: int = 0, tags: List[str] = None):
4
+ def list_sessions(limit: int = 100, offset: int = 0, tags: Optional[List[str]] = None):
5
5
  params = {"limit": limit, "offset": offset}
6
6
  if tags:
7
7
  params["tags"] = tags
@@ -10,21 +10,26 @@ def list_sessions(limit: int = 100, offset: int = 0, tags: List[str] = None):
10
10
  def create_session(
11
11
  prompt: str,
12
12
  idempotent: bool = False,
13
- snapshot_id: str = None,
14
- playbook_id: str = None,
13
+ snapshot_id: Optional[str] = None,
14
+ playbook_id: Optional[str] = None,
15
15
  unlisted: bool = False,
16
- tags: List[str] = None,
17
- session_secrets: List[dict] = None,
16
+ tags: Optional[List[str]] = None,
17
+ session_secrets: Optional[List[dict]] = None,
18
18
  title: Optional[str] = None,
19
19
  knowledge_ids: Optional[List[str]] = None,
20
20
  secret_ids: Optional[List[str]] = None,
21
21
  max_acu_limit: Optional[int] = None,
22
- **kwargs
22
+ advanced_mode: Optional[str] = None,
23
+ repos: Optional[List[str]] = None,
24
+ session_links: Optional[List[str]] = None,
25
+ attachment_urls: Optional[List[str]] = None,
26
+ create_as_user_id: Optional[str] = None,
27
+ child_playbook_id: Optional[str] = None,
23
28
  ):
24
29
  data = {
25
30
  "prompt": prompt,
26
31
  "idempotent": idempotent,
27
- "unlisted": unlisted
32
+ "unlisted": unlisted,
28
33
  }
29
34
  if snapshot_id:
30
35
  data["snapshot_id"] = snapshot_id
@@ -42,7 +47,7 @@ def create_session(
42
47
  data["secret_ids"] = secret_ids
43
48
  if max_acu_limit:
44
49
  data["max_acu_limit"] = max_acu_limit
45
-
50
+
46
51
  return client.post("sessions", json=data)
47
52
 
48
53
  def get_session(session_id: str):
@@ -15,6 +15,7 @@ def create_session(
15
15
  knowledge_ids: Optional[List[str]] = None,
16
16
  max_acu_limit: Optional[int] = None,
17
17
  playbook_id: Optional[str] = None,
18
+ child_playbook_id: Optional[str] = None,
18
19
  repos: Optional[List[str]] = None,
19
20
  secret_ids: Optional[List[str]] = None,
20
21
  session_links: Optional[List[str]] = None,
@@ -37,6 +38,8 @@ def create_session(
37
38
  data["max_acu_limit"] = max_acu_limit
38
39
  if playbook_id:
39
40
  data["playbook_id"] = playbook_id
41
+ if child_playbook_id:
42
+ data["child_playbook_id"] = child_playbook_id
40
43
  if repos:
41
44
  data["repos"] = repos
42
45
  if secret_ids:
@@ -155,13 +155,39 @@ def create_session_cmd(
155
155
  title: Optional[str] = typer.Option(None, "--title", "-t", help="Custom session title"),
156
156
  org: Optional[str] = typer.Option(None, "--org", help="Override organization ID"),
157
157
  max_acu: Optional[int] = typer.Option(None, "--max-acu", help="Maximum ACU limit"),
158
- advanced_mode: Optional[str] = typer.Option(None, "--advanced-mode", help="Enable advanced mode (e.g. CLI, browser) for the session"),
158
+ advanced_mode: Optional[str] = typer.Option(None, "--advanced-mode", help="Advanced mode type: analyze | create_playbook | improve_playbook | batch | manage_knowledge"),
159
+ playbook_id: Optional[str] = typer.Option(None, "--playbook-id", help="Playbook ID to apply (v3 only)"),
160
+ child_playbook_id: Optional[str] = typer.Option(None, "--child-playbook-id", help="Playbook ID applied to each sub-session in batch mode (v3 only)"),
161
+ tags: Optional[List[str]] = typer.Option(None, "--tag", help="Session tags (repeatable)"),
162
+ repos: Optional[List[str]] = typer.Option(None, "--repo", help="Repository URLs to attach (v3 only, repeatable)"),
163
+ knowledge_ids: Optional[List[str]] = typer.Option(None, "--knowledge-id", help="Knowledge IDs to attach (repeatable)"),
164
+ secret_ids: Optional[List[str]] = typer.Option(None, "--secret-id", help="Secret IDs to inject (v3 only, repeatable)"),
165
+ session_links: Optional[List[str]] = typer.Option(None, "--session-link", help="Session URLs to link as context (v3 only, repeatable)"),
166
+ attachment_urls: Optional[List[str]] = typer.Option(None, "--attachment-url", help="Attachment URLs to attach (v3 only, repeatable)"),
167
+ create_as_user_id: Optional[str] = typer.Option(None, "--create-as-user-id", help="Enterprise: create session on behalf of this user ID (v3 only)"),
159
168
  force: bool = typer.Option(False, "--force", help="Force creation even if duplicate prompt is detected"),
160
169
  wait: bool = typer.Option(False, "--wait", "-w", help="Block until the session reaches a terminal status"),
161
170
  interval: int = typer.Option(5, "--interval", help="Polling interval in seconds when --wait is used"),
162
171
  ):
163
172
  """Create a new Devin session."""
164
173
  if org: config.temporary_org_id = org
174
+
175
+ api_ver = config.api_version
176
+ console.print(f"[dim]Using profile: {config.active_profile or 'default'} ({api_ver})[/dim]")
177
+
178
+ v3_only_used = [x for x, v in [
179
+ ("--advanced-mode", advanced_mode),
180
+ ("--playbook-id", playbook_id),
181
+ ("--repos", repos),
182
+ ("--secret-ids", secret_ids),
183
+ ("--session-links", session_links),
184
+ ("--attachment-urls", attachment_urls),
185
+ ("--create-as-user-id", create_as_user_id),
186
+ ] if v]
187
+ if api_ver == "v1" and v3_only_used:
188
+ console.print(f"[bold yellow]Warning:[/bold yellow] The following flags are v3-only and will be ignored on a v1 profile: {', '.join(v3_only_used)}")
189
+ console.print(" Run [bold cyan]devin configure[/bold cyan] to switch to a v3 profile.")
190
+
165
191
  if file:
166
192
  prompt_text = file.read_text()
167
193
  elif prompt:
@@ -169,10 +195,10 @@ def create_session_cmd(
169
195
  else:
170
196
  console.print("[bold red]Error:[/bold red] Must provide prompt or --file")
171
197
  raise typer.Exit(1)
172
-
198
+
173
199
  prompt_hash = hashlib.sha256(prompt_text.encode('utf-8')).hexdigest()
174
200
  existing_sid = config.get_session_by_prompt_hash(prompt_hash)
175
-
201
+
176
202
  if existing_sid and not force:
177
203
  console.print(f"[bold yellow]Duplicate Detected:[/bold yellow] You recently created a session with this exact prompt.")
178
204
  console.print(f"Existing Session ID: [bold cyan]{existing_sid}[/bold cyan]")
@@ -182,13 +208,22 @@ def create_session_cmd(
182
208
 
183
209
  with console.status("[bold green]Creating session...[/bold green]"):
184
210
  resp = sessions.create_session(
185
- prompt=prompt_text,
186
- title=title,
211
+ prompt=prompt_text,
212
+ title=title,
187
213
  max_acu_limit=max_acu,
188
- advanced_mode=advanced_mode
214
+ advanced_mode=advanced_mode,
215
+ playbook_id=playbook_id,
216
+ child_playbook_id=child_playbook_id,
217
+ tags=tags or None,
218
+ repos=repos or None,
219
+ knowledge_ids=knowledge_ids or None,
220
+ secret_ids=secret_ids or None,
221
+ session_links=session_links or None,
222
+ attachment_urls=attachment_urls or None,
223
+ create_as_user_id=create_as_user_id,
189
224
  )
190
225
  sid = resp.get("session_id")
191
-
226
+
192
227
  if "advanced_mode_url" in resp:
193
228
  adv_url = resp["advanced_mode_url"]
194
229
  console.print(f"[bold yellow]Advanced Mode Authorization Required![/bold yellow]")
@@ -197,7 +232,7 @@ def create_session_cmd(
197
232
  if typer.confirm("Open browser now?"):
198
233
  import webbrowser
199
234
  webbrowser.open(adv_url)
200
-
235
+
201
236
  if sid:
202
237
  config.current_session_id = sid
203
238
  config.save_prompt_hash(prompt_hash, sid)
@@ -219,6 +254,7 @@ def create_session_cmd(
219
254
  else:
220
255
  console.print("[yellow]Session created, but no ID returned immediately (awaiting advanced mode setup).[/yellow]")
221
256
 
257
+
222
258
  @session_app.command("list")
223
259
  @handle_api_error
224
260
  def list_sessions_cmd(
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