stratasynth-cli 0.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.
- stratasynth_cli-0.2.0/.gitignore +63 -0
- stratasynth_cli-0.2.0/CLAUDE.md +54 -0
- stratasynth_cli-0.2.0/PKG-INFO +12 -0
- stratasynth_cli-0.2.0/pyproject.toml +26 -0
- stratasynth_cli-0.2.0/stratasynth_cli/commands/auth.py +54 -0
- stratasynth_cli-0.2.0/stratasynth_cli/commands/evaluate.py +111 -0
- stratasynth_cli-0.2.0/stratasynth_cli/commands/generate.py +112 -0
- stratasynth_cli-0.2.0/stratasynth_cli/commands/humans.py +350 -0
- stratasynth_cli-0.2.0/stratasynth_cli/commands/jobs.py +180 -0
- stratasynth_cli-0.2.0/stratasynth_cli/commands/personas.py +95 -0
- stratasynth_cli-0.2.0/stratasynth_cli/commands/scenarios.py +30 -0
- stratasynth_cli-0.2.0/stratasynth_cli/config.py +90 -0
- stratasynth_cli-0.2.0/stratasynth_cli/output.py +433 -0
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
# Python
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*$py.class
|
|
5
|
+
*.so
|
|
6
|
+
.Python
|
|
7
|
+
.venv/
|
|
8
|
+
venv/
|
|
9
|
+
env/
|
|
10
|
+
.env
|
|
11
|
+
.env.test
|
|
12
|
+
*.egg-info/
|
|
13
|
+
dist/
|
|
14
|
+
build/
|
|
15
|
+
.uv/
|
|
16
|
+
|
|
17
|
+
# Node
|
|
18
|
+
node_modules/
|
|
19
|
+
dist/
|
|
20
|
+
.next/
|
|
21
|
+
|
|
22
|
+
# Playwright
|
|
23
|
+
apps/frontend/e2e/report/
|
|
24
|
+
apps/frontend/test-results/
|
|
25
|
+
apps/frontend/playwright-report/
|
|
26
|
+
out/
|
|
27
|
+
.turbo/
|
|
28
|
+
|
|
29
|
+
# AWS / Serverless
|
|
30
|
+
.serverless/
|
|
31
|
+
*.zip
|
|
32
|
+
|
|
33
|
+
# IDE
|
|
34
|
+
.idea/
|
|
35
|
+
.vscode/
|
|
36
|
+
*.swp
|
|
37
|
+
*.swo
|
|
38
|
+
|
|
39
|
+
# Archivos temporales de scripting con Claude Code
|
|
40
|
+
_*.json
|
|
41
|
+
_*.py
|
|
42
|
+
_*.js
|
|
43
|
+
_token*.txt
|
|
44
|
+
_resp*.json
|
|
45
|
+
_login*.json
|
|
46
|
+
_payload*.json
|
|
47
|
+
|
|
48
|
+
# Secretos y configuración local
|
|
49
|
+
*.local
|
|
50
|
+
.env.test
|
|
51
|
+
.env.production.local
|
|
52
|
+
apps/backend/.env
|
|
53
|
+
apps/frontend/.env.local
|
|
54
|
+
apps/frontend/.env.production
|
|
55
|
+
Docs/CREDENTIALS_DEV.md
|
|
56
|
+
docs/CREDENTIALS_MARKETPULSE.md
|
|
57
|
+
|
|
58
|
+
# Parquet (no en layers — archivos locales de desarrollo)
|
|
59
|
+
*.parquet
|
|
60
|
+
|
|
61
|
+
# OS
|
|
62
|
+
.DS_Store
|
|
63
|
+
Thumbs.db
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
# CLAUDE.md — StrataSynth CLI
|
|
2
|
+
|
|
3
|
+
## Stack
|
|
4
|
+
- Python 3.12
|
|
5
|
+
- uv como package manager
|
|
6
|
+
- Distribuido en PyPI como `stratasynth-cli`
|
|
7
|
+
- Click para CLI framework
|
|
8
|
+
|
|
9
|
+
## Instalación y uso
|
|
10
|
+
```bash
|
|
11
|
+
pip install stratasynth-cli # producción
|
|
12
|
+
uv run stratasynth --help # desarrollo local
|
|
13
|
+
|
|
14
|
+
# Dataset Engine:
|
|
15
|
+
stratasynth auth login --api-key ss_live_...
|
|
16
|
+
stratasynth generate --scenario FAM-01 --count 100 --complexity 3 --adapter llamaindex_nodes
|
|
17
|
+
stratasynth jobs list
|
|
18
|
+
stratasynth jobs status {jobId}
|
|
19
|
+
stratasynth personas generate --archetype working_mother --complexity 4
|
|
20
|
+
stratasynth evaluate start --job-id {jobId}
|
|
21
|
+
stratasynth evaluate results --eval-id {evalId}
|
|
22
|
+
stratasynth evaluate results --eval-id {evalId} --json
|
|
23
|
+
# Humans Engine:
|
|
24
|
+
stratasynth humans generate -d '{"age_range":"28-40","gender":"female","country":"ES"}' -c '{"category":"yogures funcionales","study_brands":["Activia"]}'
|
|
25
|
+
stratasynth humans status --id hu_xxx
|
|
26
|
+
stratasynth humans batch --count 3 -d '{"age_range":"25-45","country":"ES"}'
|
|
27
|
+
stratasynth humans interview --id hu_xxx --interview-style narrative --verbosity high
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## Estructura
|
|
31
|
+
```
|
|
32
|
+
stratasynth_cli/
|
|
33
|
+
commands/
|
|
34
|
+
auth.py ← login, logout, whoami
|
|
35
|
+
generate.py ← generate dataset
|
|
36
|
+
jobs.py ← list, status, download
|
|
37
|
+
personas.py ← generate, view
|
|
38
|
+
evaluate.py ← start evaluation, results
|
|
39
|
+
scenarios.py ← list scenarios
|
|
40
|
+
humans.py ← generate, status, batch, interview (Humans Engine)
|
|
41
|
+
config.py ← Dataset + Humans API URLs, token management
|
|
42
|
+
output.py ← Rich formatting, progress bars
|
|
43
|
+
__main__.py ← CLI entry point
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
## Token management
|
|
47
|
+
- Token guardado en `~/.stratasynth/config.json` (no en código)
|
|
48
|
+
- TTL de 24h — regenerar con `stratasynth auth login`
|
|
49
|
+
|
|
50
|
+
## Deploy
|
|
51
|
+
```bash
|
|
52
|
+
uv build # genera dist/
|
|
53
|
+
uv publish # publicar a PyPI
|
|
54
|
+
```
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: stratasynth-cli
|
|
3
|
+
Version: 0.2.0
|
|
4
|
+
Summary: CLI for StrataSynth — synthetic conversational data with psychological depth
|
|
5
|
+
Project-URL: Homepage, https://stratasynth.com
|
|
6
|
+
Requires-Python: >=3.12
|
|
7
|
+
Requires-Dist: click>=8.1.0
|
|
8
|
+
Requires-Dist: httpx>=0.27.0
|
|
9
|
+
Requires-Dist: pydantic>=2.6.0
|
|
10
|
+
Requires-Dist: python-dotenv>=1.0.0
|
|
11
|
+
Requires-Dist: pyyaml>=6.0
|
|
12
|
+
Requires-Dist: rich>=13.7.0
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["hatchling"]
|
|
3
|
+
build-backend = "hatchling.build"
|
|
4
|
+
|
|
5
|
+
[tool.hatch.build.targets.wheel]
|
|
6
|
+
packages = ["stratasynth_cli"]
|
|
7
|
+
|
|
8
|
+
[project]
|
|
9
|
+
name = "stratasynth-cli"
|
|
10
|
+
version = "0.2.0"
|
|
11
|
+
description = "CLI for StrataSynth — synthetic conversational data with psychological depth"
|
|
12
|
+
requires-python = ">=3.12"
|
|
13
|
+
dependencies = [
|
|
14
|
+
"click>=8.1.0",
|
|
15
|
+
"httpx>=0.27.0",
|
|
16
|
+
"rich>=13.7.0",
|
|
17
|
+
"pydantic>=2.6.0",
|
|
18
|
+
"python-dotenv>=1.0.0",
|
|
19
|
+
"pyyaml>=6.0",
|
|
20
|
+
]
|
|
21
|
+
|
|
22
|
+
[project.scripts]
|
|
23
|
+
stratasynth = "stratasynth_cli.__main__:cli"
|
|
24
|
+
|
|
25
|
+
[project.urls]
|
|
26
|
+
Homepage = "https://stratasynth.com"
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
"""
|
|
2
|
+
CLI auth commands — login, logout, whoami.
|
|
3
|
+
|
|
4
|
+
$ stratasynth auth login --api-key ss_live_...
|
|
5
|
+
$ stratasynth auth logout
|
|
6
|
+
"""
|
|
7
|
+
import click
|
|
8
|
+
import httpx
|
|
9
|
+
from stratasynth_cli.config import get_api_url, save_token, clear_token, get_token
|
|
10
|
+
from stratasynth_cli.output import print_error, print_success, print_login_success, print_whoami
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
@click.group()
|
|
14
|
+
def auth():
|
|
15
|
+
"""Authentication commands."""
|
|
16
|
+
pass
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
@auth.command()
|
|
20
|
+
@click.option("--api-key", required=True, envvar="STRATASYNTH_API_KEY", help="Your StrataSynth API key (ss_live_...)")
|
|
21
|
+
def login(api_key):
|
|
22
|
+
"""Login with your API key."""
|
|
23
|
+
try:
|
|
24
|
+
response = httpx.post(
|
|
25
|
+
f"{get_api_url()}/auth/token",
|
|
26
|
+
json={"api_key": api_key},
|
|
27
|
+
timeout=10,
|
|
28
|
+
)
|
|
29
|
+
if response.status_code == 200:
|
|
30
|
+
token = response.json()["data"]["token"]
|
|
31
|
+
save_token(token)
|
|
32
|
+
print_login_success()
|
|
33
|
+
else:
|
|
34
|
+
msg = response.json().get("message", "Invalid API key")
|
|
35
|
+
print_error(f"Login failed: {msg}")
|
|
36
|
+
raise SystemExit(1)
|
|
37
|
+
except SystemExit:
|
|
38
|
+
raise
|
|
39
|
+
except Exception as e:
|
|
40
|
+
print_error(f"Connection error: {e}")
|
|
41
|
+
raise SystemExit(1)
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
@auth.command()
|
|
45
|
+
def logout():
|
|
46
|
+
"""Logout and remove saved token."""
|
|
47
|
+
clear_token()
|
|
48
|
+
print_success("Logged out.")
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
@auth.command()
|
|
52
|
+
def whoami():
|
|
53
|
+
"""Show current authentication status."""
|
|
54
|
+
print_whoami(authenticated=bool(get_token()))
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
"""
|
|
2
|
+
CLI evaluate commands — evaluar output y ver resultados.
|
|
3
|
+
|
|
4
|
+
$ stratasynth evaluate start --job-id job_xxx
|
|
5
|
+
$ stratasynth evaluate results --eval-id eval_xxx
|
|
6
|
+
$ stratasynth evaluate results --eval-id eval_xxx --json
|
|
7
|
+
"""
|
|
8
|
+
import json
|
|
9
|
+
import time
|
|
10
|
+
|
|
11
|
+
import click
|
|
12
|
+
import httpx
|
|
13
|
+
from stratasynth_cli.config import get_api_url, get_token
|
|
14
|
+
from stratasynth_cli.output import (
|
|
15
|
+
print_error,
|
|
16
|
+
print_eval_started,
|
|
17
|
+
print_eval_results,
|
|
18
|
+
)
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
@click.group()
|
|
22
|
+
def evaluate():
|
|
23
|
+
"""Evaluate your system's output against StrataSynth ground truth."""
|
|
24
|
+
pass
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
@evaluate.command()
|
|
28
|
+
@click.option("--job-id", required=True, help="StrataSynth job ID (el dataset generado)")
|
|
29
|
+
@click.option("--output-url", default=None, help="S3 key del output de tu sistema a evaluar (opcional)")
|
|
30
|
+
@click.option("--json", "json_output", is_flag=True, help="Output as JSON for scripting")
|
|
31
|
+
def start(job_id, output_url, json_output):
|
|
32
|
+
"""Start a new evaluation for a completed job."""
|
|
33
|
+
token = get_token()
|
|
34
|
+
if not token:
|
|
35
|
+
print_error("Not authenticated. Run: stratasynth auth login --api-key ss_live_...")
|
|
36
|
+
raise SystemExit(1)
|
|
37
|
+
|
|
38
|
+
payload: dict = {"jobId": job_id}
|
|
39
|
+
if output_url:
|
|
40
|
+
payload["system_output"] = output_url
|
|
41
|
+
|
|
42
|
+
response = httpx.post(
|
|
43
|
+
f"{get_api_url()}/evaluate",
|
|
44
|
+
json=payload,
|
|
45
|
+
headers={"Authorization": f"Bearer {token}"},
|
|
46
|
+
timeout=10,
|
|
47
|
+
)
|
|
48
|
+
if response.status_code in (200, 201):
|
|
49
|
+
data = response.json()["data"]
|
|
50
|
+
if json_output:
|
|
51
|
+
click.echo(json.dumps(data))
|
|
52
|
+
else:
|
|
53
|
+
print_eval_started(data["evalId"])
|
|
54
|
+
else:
|
|
55
|
+
print_error(response.json().get("message", "Unknown error"))
|
|
56
|
+
raise SystemExit(1)
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
@evaluate.command()
|
|
60
|
+
@click.option("--eval-id", required=True, help="Evaluation ID from 'evaluate start'")
|
|
61
|
+
@click.option("--wait/--no-wait", default=True, help="Wait for evaluation to complete (default: wait)")
|
|
62
|
+
@click.option("--json", "json_output", is_flag=True, help="Output as JSON for scripting")
|
|
63
|
+
def results(eval_id, wait, json_output):
|
|
64
|
+
"""Get evaluation results (polls until COMPLETED if --wait)."""
|
|
65
|
+
token = get_token()
|
|
66
|
+
if not token:
|
|
67
|
+
print_error("Not authenticated. Run: stratasynth auth login --api-key ss_live_...")
|
|
68
|
+
raise SystemExit(1)
|
|
69
|
+
|
|
70
|
+
headers = {"Authorization": f"Bearer {token}"}
|
|
71
|
+
api_url = get_api_url()
|
|
72
|
+
|
|
73
|
+
max_polls = 24 if wait else 1
|
|
74
|
+
result = None
|
|
75
|
+
|
|
76
|
+
for _ in range(max_polls):
|
|
77
|
+
response = httpx.get(
|
|
78
|
+
f"{api_url}/evaluate/{eval_id}",
|
|
79
|
+
headers=headers,
|
|
80
|
+
timeout=10,
|
|
81
|
+
)
|
|
82
|
+
|
|
83
|
+
if response.status_code == 404:
|
|
84
|
+
print_error(f"Evaluation {eval_id} not found.")
|
|
85
|
+
raise SystemExit(1)
|
|
86
|
+
if response.status_code != 200:
|
|
87
|
+
print_error(f"API error: {response.status_code} — {response.text}")
|
|
88
|
+
raise SystemExit(1)
|
|
89
|
+
|
|
90
|
+
result = response.json()["data"]
|
|
91
|
+
status = result.get("status", "UNKNOWN")
|
|
92
|
+
|
|
93
|
+
if status in ("COMPLETED", "FAILED"):
|
|
94
|
+
break
|
|
95
|
+
|
|
96
|
+
if wait:
|
|
97
|
+
time.sleep(5)
|
|
98
|
+
|
|
99
|
+
if json_output:
|
|
100
|
+
click.echo(json.dumps(result))
|
|
101
|
+
return
|
|
102
|
+
|
|
103
|
+
if result.get("status") == "FAILED":
|
|
104
|
+
print_error(f"Evaluation {eval_id} failed.")
|
|
105
|
+
raise SystemExit(1)
|
|
106
|
+
|
|
107
|
+
if result.get("status") != "COMPLETED":
|
|
108
|
+
print_error(f"Evaluation {eval_id} still {result.get('status')}. Use --wait to poll.")
|
|
109
|
+
raise SystemExit(1)
|
|
110
|
+
|
|
111
|
+
print_eval_results(result)
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
"""
|
|
2
|
+
CLI generate command — crear job de generación de dataset.
|
|
3
|
+
"""
|
|
4
|
+
import json
|
|
5
|
+
import click
|
|
6
|
+
import httpx
|
|
7
|
+
from stratasynth_cli.config import get_api_url, get_token
|
|
8
|
+
from stratasynth_cli.output import print_error, print_job_created
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
VALID_ADAPTERS = [
|
|
12
|
+
"flat_jsonl", "llamaindex_nodes", "openai_finetuning",
|
|
13
|
+
"langchain_memory", "huggingface_dataset", "csv_tabular",
|
|
14
|
+
"anthropic_claude", "luminoracore", "custom_adapter",
|
|
15
|
+
]
|
|
16
|
+
VALID_MEDIUMS = ["text_chat", "voice_call", "face_to_face", "email", "unspecified"]
|
|
17
|
+
VALID_LOCATIONS = ["home", "work", "public", "unspecified"]
|
|
18
|
+
VALID_TURN_LENGTHS = ["brief", "natural", "extended"]
|
|
19
|
+
VALID_LANGUAGES = ["en", "es", "de", "fr"]
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
_GENERATE_EPILOG = """
|
|
23
|
+
\b
|
|
24
|
+
SCENARIOS (run `stratasynth scenarios list` to see all 12):
|
|
25
|
+
FAM-01 Family — mother/child accumulated tension
|
|
26
|
+
FAM-02 Family — father/daughter reconnection after estrangement
|
|
27
|
+
ROM-01 Romance — couple in post-relocation crisis
|
|
28
|
+
ROM-02 Romance — relationship slowly ending
|
|
29
|
+
PRO-01 Professional — silent burnout
|
|
30
|
+
VIT-01 Vital — grief after loss of parent
|
|
31
|
+
|
|
32
|
+
\b
|
|
33
|
+
ADAPTERS:
|
|
34
|
+
flat_jsonl Raw JSON per turn. Use for custom pipelines.
|
|
35
|
+
openai_finetuning ChatML format, ready for OpenAI fine-tuning API.
|
|
36
|
+
llamaindex_nodes TextNode objects for LlamaIndex / vector stores.
|
|
37
|
+
langchain_memory HumanMessage/AIMessage for LangChain.
|
|
38
|
+
huggingface_dataset Arrow/Parquet, load with datasets.load_dataset().
|
|
39
|
+
anthropic_claude Anthropic Messages API format.
|
|
40
|
+
csv_tabular One row per turn — good for pandas / Excel.
|
|
41
|
+
|
|
42
|
+
\b
|
|
43
|
+
EXAMPLES:
|
|
44
|
+
# 500 conversations for OpenAI fine-tuning, family conflict
|
|
45
|
+
stratasynth generate --scenario FAM-01 --count 500 --adapter openai_finetuning
|
|
46
|
+
|
|
47
|
+
# Spanish romantic conflict, text chat context, brief turns
|
|
48
|
+
stratasynth generate --scenario ROM-02 --count 200 \\
|
|
49
|
+
--language es --medium text_chat --turn-length brief
|
|
50
|
+
|
|
51
|
+
# Reproducible dataset (same seed = identical output every time)
|
|
52
|
+
stratasynth generate --scenario PRO-01 --count 1000 --seed 42
|
|
53
|
+
|
|
54
|
+
# Pipe job ID to another command
|
|
55
|
+
JOB=$(stratasynth generate --scenario FAM-02 --count 50 --json | jq -r '.jobId')
|
|
56
|
+
stratasynth jobs status --job-id $JOB
|
|
57
|
+
"""
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
@click.command(epilog=_GENERATE_EPILOG)
|
|
61
|
+
@click.option("--scenario", required=True, help="Scenario ID. Run `stratasynth scenarios list` to see all 12.")
|
|
62
|
+
@click.option("--count", default=100, show_default=True, help="Number of conversations to generate.")
|
|
63
|
+
@click.option("--complexity", default=3, show_default=True, type=click.IntRange(1, 5), help="PsycheGraph depth: 1=minimal, 3=standard (recommended), 5=deep.")
|
|
64
|
+
@click.option("--adapter", default="flat_jsonl", show_default=True, type=click.Choice(VALID_ADAPTERS), help="Output format (see ADAPTERS below).")
|
|
65
|
+
@click.option("--language", default="en", show_default=True, type=click.Choice(VALID_LANGUAGES), help="Language for generated conversations.")
|
|
66
|
+
@click.option("--medium", default="unspecified", show_default=True, type=click.Choice(VALID_MEDIUMS), help="Conversation channel — affects tone and style of generated text.")
|
|
67
|
+
@click.option("--location", default="unspecified", show_default=True, type=click.Choice(VALID_LOCATIONS), help="Physical context injected into each turn.")
|
|
68
|
+
@click.option("--turn-length", default="natural", show_default=True, type=click.Choice(VALID_TURN_LENGTHS), help="Turn length: brief (1-2 sentences), natural (3-5), extended (paragraphs).")
|
|
69
|
+
@click.option("--noise", default=0.12, show_default=True, type=click.FloatRange(0.0, 0.5), help="Noise injection rate: fraction of turns with intentional noise (0.0-0.5).")
|
|
70
|
+
@click.option("--seed", default=None, type=int, help="Random seed for reproducible generation.")
|
|
71
|
+
@click.option("--json", "json_output", is_flag=True, help="Output as JSON (for scripting / pipes).")
|
|
72
|
+
def generate(scenario, count, complexity, adapter, language, medium, location, turn_length, noise, seed, json_output):
|
|
73
|
+
"""Generate a synthetic conversational dataset."""
|
|
74
|
+
token = get_token()
|
|
75
|
+
if not token:
|
|
76
|
+
print_error("Not authenticated. Run: stratasynth auth login --api-key ss_live_...")
|
|
77
|
+
raise SystemExit(1)
|
|
78
|
+
|
|
79
|
+
payload = {
|
|
80
|
+
"scenario_id": scenario,
|
|
81
|
+
"conversation_count": count,
|
|
82
|
+
"complexity": complexity,
|
|
83
|
+
"adapter": adapter,
|
|
84
|
+
"language": language,
|
|
85
|
+
"noise_pct": noise,
|
|
86
|
+
"turn_length_target": turn_length,
|
|
87
|
+
"conversation_setting": {"medium": medium, "location": location},
|
|
88
|
+
}
|
|
89
|
+
if seed is not None:
|
|
90
|
+
payload["seed"] = seed
|
|
91
|
+
|
|
92
|
+
try:
|
|
93
|
+
response = httpx.post(
|
|
94
|
+
f"{get_api_url()}/jobs/dataset",
|
|
95
|
+
json=payload,
|
|
96
|
+
headers={"Authorization": f"Bearer {token}"},
|
|
97
|
+
timeout=10,
|
|
98
|
+
)
|
|
99
|
+
if response.status_code == 200:
|
|
100
|
+
data = response.json()["data"]
|
|
101
|
+
if json_output:
|
|
102
|
+
click.echo(json.dumps(data))
|
|
103
|
+
else:
|
|
104
|
+
print_job_created(data)
|
|
105
|
+
else:
|
|
106
|
+
print_error(f"Error {response.status_code}: {response.text}")
|
|
107
|
+
raise SystemExit(1)
|
|
108
|
+
except SystemExit:
|
|
109
|
+
raise
|
|
110
|
+
except Exception as e:
|
|
111
|
+
print_error(f"Connection error: {e}")
|
|
112
|
+
raise SystemExit(1)
|