devin-cli 1.1.8__tar.gz → 1.2.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.
- {devin_cli-1.1.8 → devin_cli-1.2.0}/CHANGELOG.md +15 -0
- {devin_cli-1.1.8 → devin_cli-1.2.0}/PKG-INFO +1 -1
- {devin_cli-1.1.8 → devin_cli-1.2.0}/pyproject.toml +1 -1
- {devin_cli-1.1.8 → devin_cli-1.2.0}/src/devin_cli/api/v1/sessions.py +12 -8
- {devin_cli-1.1.8 → devin_cli-1.2.0}/src/devin_cli/cli.py +86 -15
- {devin_cli-1.1.8 → devin_cli-1.2.0}/.github/workflows/pypi-publish.yml +0 -0
- {devin_cli-1.1.8 → devin_cli-1.2.0}/.gitignore +0 -0
- {devin_cli-1.1.8 → devin_cli-1.2.0}/LICENSE +0 -0
- {devin_cli-1.1.8 → devin_cli-1.2.0}/README.md +0 -0
- {devin_cli-1.1.8 → devin_cli-1.2.0}/assets/logo.png +0 -0
- {devin_cli-1.1.8 → devin_cli-1.2.0}/generate_facades.py +0 -0
- {devin_cli-1.1.8 → devin_cli-1.2.0}/setup.py +0 -0
- {devin_cli-1.1.8 → devin_cli-1.2.0}/src/devin_cli/__init__.py +0 -0
- {devin_cli-1.1.8 → devin_cli-1.2.0}/src/devin_cli/api/__init__.py +0 -0
- {devin_cli-1.1.8 → devin_cli-1.2.0}/src/devin_cli/api/attachments.py +0 -0
- {devin_cli-1.1.8 → devin_cli-1.2.0}/src/devin_cli/api/client.py +0 -0
- {devin_cli-1.1.8 → devin_cli-1.2.0}/src/devin_cli/api/consumption.py +0 -0
- {devin_cli-1.1.8 → devin_cli-1.2.0}/src/devin_cli/api/knowledge.py +0 -0
- {devin_cli-1.1.8 → devin_cli-1.2.0}/src/devin_cli/api/members.py +0 -0
- {devin_cli-1.1.8 → devin_cli-1.2.0}/src/devin_cli/api/organizations.py +0 -0
- {devin_cli-1.1.8 → devin_cli-1.2.0}/src/devin_cli/api/playbooks.py +0 -0
- {devin_cli-1.1.8 → devin_cli-1.2.0}/src/devin_cli/api/repositories.py +0 -0
- {devin_cli-1.1.8 → devin_cli-1.2.0}/src/devin_cli/api/schedules.py +0 -0
- {devin_cli-1.1.8 → devin_cli-1.2.0}/src/devin_cli/api/secrets.py +0 -0
- {devin_cli-1.1.8 → devin_cli-1.2.0}/src/devin_cli/api/sessions.py +0 -0
- {devin_cli-1.1.8 → devin_cli-1.2.0}/src/devin_cli/api/v1/__init__.py +0 -0
- {devin_cli-1.1.8 → devin_cli-1.2.0}/src/devin_cli/api/v1/attachments.py +0 -0
- {devin_cli-1.1.8 → devin_cli-1.2.0}/src/devin_cli/api/v1/knowledge.py +0 -0
- {devin_cli-1.1.8 → devin_cli-1.2.0}/src/devin_cli/api/v1/playbooks.py +0 -0
- {devin_cli-1.1.8 → devin_cli-1.2.0}/src/devin_cli/api/v1/secrets.py +0 -0
- {devin_cli-1.1.8 → devin_cli-1.2.0}/src/devin_cli/api/v3/__init__.py +0 -0
- {devin_cli-1.1.8 → devin_cli-1.2.0}/src/devin_cli/api/v3/attachments.py +0 -0
- {devin_cli-1.1.8 → devin_cli-1.2.0}/src/devin_cli/api/v3/consumption.py +0 -0
- {devin_cli-1.1.8 → devin_cli-1.2.0}/src/devin_cli/api/v3/knowledge.py +0 -0
- {devin_cli-1.1.8 → devin_cli-1.2.0}/src/devin_cli/api/v3/members.py +0 -0
- {devin_cli-1.1.8 → devin_cli-1.2.0}/src/devin_cli/api/v3/organizations.py +0 -0
- {devin_cli-1.1.8 → devin_cli-1.2.0}/src/devin_cli/api/v3/playbooks.py +0 -0
- {devin_cli-1.1.8 → devin_cli-1.2.0}/src/devin_cli/api/v3/repositories.py +0 -0
- {devin_cli-1.1.8 → devin_cli-1.2.0}/src/devin_cli/api/v3/schedules.py +0 -0
- {devin_cli-1.1.8 → devin_cli-1.2.0}/src/devin_cli/api/v3/secrets.py +0 -0
- {devin_cli-1.1.8 → devin_cli-1.2.0}/src/devin_cli/api/v3/sessions.py +0 -0
- {devin_cli-1.1.8 → devin_cli-1.2.0}/src/devin_cli/config.py +0 -0
- {devin_cli-1.1.8 → devin_cli-1.2.0}/tests/__init__.py +0 -0
- {devin_cli-1.1.8 → devin_cli-1.2.0}/tests/conftest.py +0 -0
- {devin_cli-1.1.8 → devin_cli-1.2.0}/tests/test_api/test_attachments.py +0 -0
- {devin_cli-1.1.8 → devin_cli-1.2.0}/tests/test_api/test_knowledge.py +0 -0
- {devin_cli-1.1.8 → devin_cli-1.2.0}/tests/test_api/test_playbooks.py +0 -0
- {devin_cli-1.1.8 → devin_cli-1.2.0}/tests/test_api/test_repositories.py +0 -0
- {devin_cli-1.1.8 → devin_cli-1.2.0}/tests/test_api/test_schedules.py +0 -0
- {devin_cli-1.1.8 → devin_cli-1.2.0}/tests/test_api/test_secrets.py +0 -0
- {devin_cli-1.1.8 → devin_cli-1.2.0}/tests/test_api/test_sessions.py +0 -0
- {devin_cli-1.1.8 → devin_cli-1.2.0}/tests/test_cli.py +0 -0
- {devin_cli-1.1.8 → devin_cli-1.2.0}/tests/test_config.py +0 -0
|
@@ -5,6 +5,21 @@ 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
|
+
|
|
17
|
+
## [1.1.9] - 2026-03-11
|
|
18
|
+
### Fixed
|
|
19
|
+
- `devin watch` terminal status message was printed inside a `Live` context, causing output corruption. Now printed after the `Live` block exits.
|
|
20
|
+
- `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.
|
|
21
|
+
- `chain` used bare `resp["session_id"]` key access which would raise `KeyError` on unexpected API responses. Now uses `.get()` with an explicit error guard.
|
|
22
|
+
|
|
8
23
|
## [1.1.8] - 2026-03-11
|
|
9
24
|
### Added
|
|
10
25
|
- 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.
|
|
3
|
+
Version: 1.2.0
|
|
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,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,25 @@ 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
|
-
|
|
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,
|
|
23
27
|
):
|
|
24
28
|
data = {
|
|
25
29
|
"prompt": prompt,
|
|
26
30
|
"idempotent": idempotent,
|
|
27
|
-
"unlisted": unlisted
|
|
31
|
+
"unlisted": unlisted,
|
|
28
32
|
}
|
|
29
33
|
if snapshot_id:
|
|
30
34
|
data["snapshot_id"] = snapshot_id
|
|
@@ -42,7 +46,7 @@ def create_session(
|
|
|
42
46
|
data["secret_ids"] = secret_ids
|
|
43
47
|
if max_acu_limit:
|
|
44
48
|
data["max_acu_limit"] = max_acu_limit
|
|
45
|
-
|
|
49
|
+
|
|
46
50
|
return client.post("sessions", json=data)
|
|
47
51
|
|
|
48
52
|
def get_session(session_id: str):
|
|
@@ -155,13 +155,38 @@ 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="
|
|
158
|
+
advanced_mode: Optional[str] = typer.Option(None, "--advanced-mode", help="Advanced mode type: 'cli' or 'browser' (v3 only)"),
|
|
159
|
+
playbook_id: Optional[str] = typer.Option(None, "--playbook-id", help="Playbook ID to apply (v3 only)"),
|
|
160
|
+
tags: Optional[List[str]] = typer.Option(None, "--tag", help="Session tags (repeatable)"),
|
|
161
|
+
repos: Optional[List[str]] = typer.Option(None, "--repo", help="Repository URLs to attach (v3 only, repeatable)"),
|
|
162
|
+
knowledge_ids: Optional[List[str]] = typer.Option(None, "--knowledge-id", help="Knowledge IDs to attach (repeatable)"),
|
|
163
|
+
secret_ids: Optional[List[str]] = typer.Option(None, "--secret-id", help="Secret IDs to inject (v3 only, repeatable)"),
|
|
164
|
+
session_links: Optional[List[str]] = typer.Option(None, "--session-link", help="Session URLs to link as context (v3 only, repeatable)"),
|
|
165
|
+
attachment_urls: Optional[List[str]] = typer.Option(None, "--attachment-url", help="Attachment URLs to attach (v3 only, repeatable)"),
|
|
166
|
+
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
167
|
force: bool = typer.Option(False, "--force", help="Force creation even if duplicate prompt is detected"),
|
|
160
168
|
wait: bool = typer.Option(False, "--wait", "-w", help="Block until the session reaches a terminal status"),
|
|
161
169
|
interval: int = typer.Option(5, "--interval", help="Polling interval in seconds when --wait is used"),
|
|
162
170
|
):
|
|
163
171
|
"""Create a new Devin session."""
|
|
164
172
|
if org: config.temporary_org_id = org
|
|
173
|
+
|
|
174
|
+
api_ver = config.api_version
|
|
175
|
+
console.print(f"[dim]Using profile: {config.active_profile or 'default'} ({api_ver})[/dim]")
|
|
176
|
+
|
|
177
|
+
v3_only_used = [x for x, v in [
|
|
178
|
+
("--advanced-mode", advanced_mode),
|
|
179
|
+
("--playbook-id", playbook_id),
|
|
180
|
+
("--repos", repos),
|
|
181
|
+
("--secret-ids", secret_ids),
|
|
182
|
+
("--session-links", session_links),
|
|
183
|
+
("--attachment-urls", attachment_urls),
|
|
184
|
+
("--create-as-user-id", create_as_user_id),
|
|
185
|
+
] if v]
|
|
186
|
+
if api_ver == "v1" and v3_only_used:
|
|
187
|
+
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)}")
|
|
188
|
+
console.print(" Run [bold cyan]devin configure[/bold cyan] to switch to a v3 profile.")
|
|
189
|
+
|
|
165
190
|
if file:
|
|
166
191
|
prompt_text = file.read_text()
|
|
167
192
|
elif prompt:
|
|
@@ -169,10 +194,10 @@ def create_session_cmd(
|
|
|
169
194
|
else:
|
|
170
195
|
console.print("[bold red]Error:[/bold red] Must provide prompt or --file")
|
|
171
196
|
raise typer.Exit(1)
|
|
172
|
-
|
|
197
|
+
|
|
173
198
|
prompt_hash = hashlib.sha256(prompt_text.encode('utf-8')).hexdigest()
|
|
174
199
|
existing_sid = config.get_session_by_prompt_hash(prompt_hash)
|
|
175
|
-
|
|
200
|
+
|
|
176
201
|
if existing_sid and not force:
|
|
177
202
|
console.print(f"[bold yellow]Duplicate Detected:[/bold yellow] You recently created a session with this exact prompt.")
|
|
178
203
|
console.print(f"Existing Session ID: [bold cyan]{existing_sid}[/bold cyan]")
|
|
@@ -182,13 +207,21 @@ def create_session_cmd(
|
|
|
182
207
|
|
|
183
208
|
with console.status("[bold green]Creating session...[/bold green]"):
|
|
184
209
|
resp = sessions.create_session(
|
|
185
|
-
prompt=prompt_text,
|
|
186
|
-
title=title,
|
|
210
|
+
prompt=prompt_text,
|
|
211
|
+
title=title,
|
|
187
212
|
max_acu_limit=max_acu,
|
|
188
|
-
advanced_mode=advanced_mode
|
|
213
|
+
advanced_mode=advanced_mode,
|
|
214
|
+
playbook_id=playbook_id,
|
|
215
|
+
tags=tags or None,
|
|
216
|
+
repos=repos or None,
|
|
217
|
+
knowledge_ids=knowledge_ids or None,
|
|
218
|
+
secret_ids=secret_ids or None,
|
|
219
|
+
session_links=session_links or None,
|
|
220
|
+
attachment_urls=attachment_urls or None,
|
|
221
|
+
create_as_user_id=create_as_user_id,
|
|
189
222
|
)
|
|
190
223
|
sid = resp.get("session_id")
|
|
191
|
-
|
|
224
|
+
|
|
192
225
|
if "advanced_mode_url" in resp:
|
|
193
226
|
adv_url = resp["advanced_mode_url"]
|
|
194
227
|
console.print(f"[bold yellow]Advanced Mode Authorization Required![/bold yellow]")
|
|
@@ -197,7 +230,7 @@ def create_session_cmd(
|
|
|
197
230
|
if typer.confirm("Open browser now?"):
|
|
198
231
|
import webbrowser
|
|
199
232
|
webbrowser.open(adv_url)
|
|
200
|
-
|
|
233
|
+
|
|
201
234
|
if sid:
|
|
202
235
|
config.current_session_id = sid
|
|
203
236
|
config.save_prompt_hash(prompt_hash, sid)
|
|
@@ -219,6 +252,7 @@ def create_session_cmd(
|
|
|
219
252
|
else:
|
|
220
253
|
console.print("[yellow]Session created, but no ID returned immediately (awaiting advanced mode setup).[/yellow]")
|
|
221
254
|
|
|
255
|
+
|
|
222
256
|
@session_app.command("list")
|
|
223
257
|
@handle_api_error
|
|
224
258
|
def list_sessions_cmd(
|
|
@@ -299,14 +333,25 @@ def session_cost_cmd(
|
|
|
299
333
|
@session_app.command("message")
|
|
300
334
|
@handle_api_error
|
|
301
335
|
def send_message_cmd(
|
|
302
|
-
text: str = typer.Argument(
|
|
336
|
+
text: Optional[str] = typer.Argument(None, help="Message text"),
|
|
337
|
+
file: Optional[Path] = typer.Option(None, "--file", "-f", help="Read message from file"),
|
|
303
338
|
session_id: Optional[str] = typer.Option(None, "--id"),
|
|
304
339
|
org: Optional[str] = typer.Option(None, "--org"),
|
|
305
340
|
):
|
|
306
341
|
"""Send a message to a session."""
|
|
307
342
|
if org: config.temporary_org_id = org
|
|
308
343
|
sid = session_id or get_current_session_id()
|
|
309
|
-
|
|
344
|
+
if file:
|
|
345
|
+
if not file.exists():
|
|
346
|
+
console.print(f"[bold red]Error:[/bold red] File not found: {file}")
|
|
347
|
+
raise typer.Exit(1)
|
|
348
|
+
msg_text = file.read_text()
|
|
349
|
+
elif text:
|
|
350
|
+
msg_text = text
|
|
351
|
+
else:
|
|
352
|
+
console.print("[bold red]Error:[/bold red] Provide message text or --file")
|
|
353
|
+
raise typer.Exit(1)
|
|
354
|
+
sessions.send_message(sid, msg_text)
|
|
310
355
|
console.print(f"[green]Message sent to {sid}[/green]")
|
|
311
356
|
|
|
312
357
|
@session_app.command("messages")
|
|
@@ -708,13 +753,15 @@ def watch_session_cmd(
|
|
|
708
753
|
|
|
709
754
|
if resp.get("status_enum", "").lower() in terminal_statuses:
|
|
710
755
|
live.update(build_status_panel(resp))
|
|
711
|
-
console.print(f"[bold green]Session {resp.get('status_enum')}![/bold green]")
|
|
712
756
|
break
|
|
713
757
|
|
|
714
758
|
time.sleep(min(backoff, 30))
|
|
715
759
|
backoff = min(backoff * 1.5, 30)
|
|
716
760
|
except KeyboardInterrupt:
|
|
717
761
|
console.print("\n[dim]Watch stopped.[/dim]")
|
|
762
|
+
return
|
|
763
|
+
|
|
764
|
+
console.print(f"[bold green]Session {resp.get('status_enum')}![/bold green]")
|
|
718
765
|
|
|
719
766
|
# --- Flat top-level aliases (backward compat with 0.1.x command structure) ---
|
|
720
767
|
|
|
@@ -730,12 +777,23 @@ def watch_cmd(
|
|
|
730
777
|
@app.command("message")
|
|
731
778
|
@handle_api_error
|
|
732
779
|
def message_cmd(
|
|
733
|
-
text: str = typer.Argument(
|
|
780
|
+
text: Optional[str] = typer.Argument(None, help="Message to send"),
|
|
781
|
+
file: Optional[Path] = typer.Option(None, "--file", "-f", help="Read message from file"),
|
|
734
782
|
session_id: Optional[str] = typer.Option(None, "--id"),
|
|
735
783
|
):
|
|
736
784
|
"""Send a message to the active session."""
|
|
737
785
|
sid = session_id or get_current_session_id()
|
|
738
|
-
|
|
786
|
+
if file:
|
|
787
|
+
if not file.exists():
|
|
788
|
+
console.print(f"[bold red]Error:[/bold red] File not found: {file}")
|
|
789
|
+
raise typer.Exit(1)
|
|
790
|
+
msg_text = file.read_text()
|
|
791
|
+
elif text:
|
|
792
|
+
msg_text = text
|
|
793
|
+
else:
|
|
794
|
+
console.print("[bold red]Error:[/bold red] Provide message text or --file")
|
|
795
|
+
raise typer.Exit(1)
|
|
796
|
+
sessions.send_message(sid, msg_text)
|
|
739
797
|
console.print(f"[green]Message sent to {sid}[/green]")
|
|
740
798
|
|
|
741
799
|
@app.command("terminate")
|
|
@@ -895,6 +953,16 @@ def update_playbook_top_cmd(
|
|
|
895
953
|
macro: Optional[str] = typer.Option(None, "--macro"),
|
|
896
954
|
):
|
|
897
955
|
"""Update an existing playbook."""
|
|
956
|
+
data: dict = {}
|
|
957
|
+
if title is not None:
|
|
958
|
+
data["title"] = title
|
|
959
|
+
if body is not None:
|
|
960
|
+
data["body"] = body
|
|
961
|
+
if macro is not None:
|
|
962
|
+
data["macro"] = macro
|
|
963
|
+
if not data:
|
|
964
|
+
console.print("[yellow]Nothing to update. Pass --title, --body, or --macro.[/yellow]")
|
|
965
|
+
return
|
|
898
966
|
playbooks.update_playbook(playbook_id, title=title or "", body=body, macro=macro)
|
|
899
967
|
console.print(f"[green]Playbook {playbook_id} updated.[/green]")
|
|
900
968
|
|
|
@@ -971,9 +1039,12 @@ def chain_cmd(
|
|
|
971
1039
|
console.print(f"[bold cyan]Step {i+1}/{len(steps)}:[/bold cyan] Playbook={step_pb}")
|
|
972
1040
|
|
|
973
1041
|
if i == 0:
|
|
974
|
-
with console.status(
|
|
1042
|
+
with console.status("Starting session..."):
|
|
975
1043
|
resp = sessions.create_session(prompt=step_prompt, playbook_id=step_pb)
|
|
976
|
-
current_sid = resp
|
|
1044
|
+
current_sid = resp.get("session_id")
|
|
1045
|
+
if not current_sid:
|
|
1046
|
+
console.print("[bold red]Error:[/bold red] No session ID returned from API.")
|
|
1047
|
+
raise typer.Exit(1)
|
|
977
1048
|
config.current_session_id = current_sid
|
|
978
1049
|
console.print(f"[green]Session started:[/green] {current_sid}")
|
|
979
1050
|
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
|
|
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
|