qalita 2.3.2__py3-none-any.whl → 2.5.2__py3-none-any.whl

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 (95) hide show
  1. qalita/__main__.py +213 -9
  2. qalita/commands/{agent.py → worker.py} +89 -89
  3. qalita/internal/config.py +26 -19
  4. qalita/internal/utils.py +1 -1
  5. qalita/web/app.py +97 -14
  6. qalita/web/blueprints/context.py +13 -60
  7. qalita/web/blueprints/dashboard.py +35 -76
  8. qalita/web/blueprints/helpers.py +154 -63
  9. qalita/web/blueprints/sources.py +29 -61
  10. qalita/web/blueprints/{agents.py → workers.py} +108 -185
  11. qalita-2.5.2.dist-info/METADATA +66 -0
  12. qalita-2.5.2.dist-info/RECORD +24 -0
  13. {qalita-2.3.2.dist-info → qalita-2.5.2.dist-info}/WHEEL +1 -1
  14. qalita-2.5.2.dist-info/entry_points.txt +2 -0
  15. qalita/web/blueprints/studio.py +0 -1294
  16. qalita/web/public/chatgpt.svg +0 -3
  17. qalita/web/public/claude.png +0 -0
  18. qalita/web/public/favicon.ico +0 -0
  19. qalita/web/public/gemini.png +0 -0
  20. qalita/web/public/logo-no-slogan.png +0 -0
  21. qalita/web/public/logo-white-no-slogan.svg +0 -11
  22. qalita/web/public/mistral.svg +0 -1
  23. qalita/web/public/noise.webp +0 -0
  24. qalita/web/public/ollama.png +0 -0
  25. qalita/web/public/platform.png +0 -0
  26. qalita/web/public/sources-logos/alloy-db.png +0 -0
  27. qalita/web/public/sources-logos/amazon-athena.png +0 -0
  28. qalita/web/public/sources-logos/amazon-rds.png +0 -0
  29. qalita/web/public/sources-logos/api.svg +0 -2
  30. qalita/web/public/sources-logos/avro.svg +0 -20
  31. qalita/web/public/sources-logos/azure-database-mysql.png +0 -0
  32. qalita/web/public/sources-logos/azure-database-postgresql.png +0 -0
  33. qalita/web/public/sources-logos/azure-sql-database.png +0 -0
  34. qalita/web/public/sources-logos/azure-sql-managed-instance.png +0 -0
  35. qalita/web/public/sources-logos/azure-synapse-analytics.png +0 -0
  36. qalita/web/public/sources-logos/azure_blob.svg +0 -1
  37. qalita/web/public/sources-logos/bigquery.png +0 -0
  38. qalita/web/public/sources-logos/cassandra.svg +0 -254
  39. qalita/web/public/sources-logos/clickhouse.png +0 -0
  40. qalita/web/public/sources-logos/cloud-sql.png +0 -0
  41. qalita/web/public/sources-logos/cockroach-db.png +0 -0
  42. qalita/web/public/sources-logos/csv.svg +0 -1
  43. qalita/web/public/sources-logos/database.svg +0 -3
  44. qalita/web/public/sources-logos/databricks.png +0 -0
  45. qalita/web/public/sources-logos/duckdb.png +0 -0
  46. qalita/web/public/sources-logos/elasticsearch.svg +0 -1
  47. qalita/web/public/sources-logos/excel.svg +0 -1
  48. qalita/web/public/sources-logos/file.svg +0 -1
  49. qalita/web/public/sources-logos/folder.svg +0 -6
  50. qalita/web/public/sources-logos/gcs.png +0 -0
  51. qalita/web/public/sources-logos/hdfs.svg +0 -1
  52. qalita/web/public/sources-logos/ibm-db2.png +0 -0
  53. qalita/web/public/sources-logos/json.png +0 -0
  54. qalita/web/public/sources-logos/maria-db.png +0 -0
  55. qalita/web/public/sources-logos/mongodb.svg +0 -1
  56. qalita/web/public/sources-logos/mssql.svg +0 -1
  57. qalita/web/public/sources-logos/mysql.svg +0 -7
  58. qalita/web/public/sources-logos/oracle.svg +0 -4
  59. qalita/web/public/sources-logos/parquet.svg +0 -16
  60. qalita/web/public/sources-logos/picture.png +0 -0
  61. qalita/web/public/sources-logos/postgresql.svg +0 -22
  62. qalita/web/public/sources-logos/questdb.png +0 -0
  63. qalita/web/public/sources-logos/redshift.png +0 -0
  64. qalita/web/public/sources-logos/s3.svg +0 -34
  65. qalita/web/public/sources-logos/sap-hana.png +0 -0
  66. qalita/web/public/sources-logos/sftp.png +0 -0
  67. qalita/web/public/sources-logos/single-store.png +0 -0
  68. qalita/web/public/sources-logos/snowflake.png +0 -0
  69. qalita/web/public/sources-logos/sqlite.svg +0 -104
  70. qalita/web/public/sources-logos/sqlserver.png +0 -0
  71. qalita/web/public/sources-logos/starburst.png +0 -0
  72. qalita/web/public/sources-logos/stream.png +0 -0
  73. qalita/web/public/sources-logos/teradata.png +0 -0
  74. qalita/web/public/sources-logos/timescale.png +0 -0
  75. qalita/web/public/sources-logos/xls.svg +0 -1
  76. qalita/web/public/sources-logos/xlsx.svg +0 -1
  77. qalita/web/public/sources-logos/yugabyte-db.png +0 -0
  78. qalita/web/public/studio-logo.svg +0 -10
  79. qalita/web/public/studio.css +0 -304
  80. qalita/web/public/studio.png +0 -0
  81. qalita/web/public/styles.css +0 -682
  82. qalita/web/templates/dashboard.html +0 -373
  83. qalita/web/templates/navbar.html +0 -40
  84. qalita/web/templates/sources/added.html +0 -57
  85. qalita/web/templates/sources/edit.html +0 -411
  86. qalita/web/templates/sources/select-source.html +0 -128
  87. qalita/web/templates/studio/agent-panel.html +0 -828
  88. qalita/web/templates/studio/context-panel.html +0 -300
  89. qalita/web/templates/studio/index.html +0 -79
  90. qalita/web/templates/studio/navbar.html +0 -14
  91. qalita/web/templates/studio/view-panel.html +0 -529
  92. qalita-2.3.2.dist-info/METADATA +0 -58
  93. qalita-2.3.2.dist-info/RECORD +0 -101
  94. qalita-2.3.2.dist-info/entry_points.txt +0 -3
  95. {qalita-2.3.2.dist-info → qalita-2.5.2.dist-info}/licenses/LICENSE +0 -0
@@ -10,40 +10,40 @@ from flask import Blueprint, jsonify, current_app
10
10
  from qalita.internal.utils import logger, validate_token
11
11
  from qalita.internal.request import send_request
12
12
  from .helpers import (
13
- agent_status_payload,
13
+ worker_status_payload,
14
14
  read_selected_env,
15
15
  parse_env_file,
16
- agent_log_file_path,
17
- agent_pid_file_path,
16
+ worker_log_file_path,
17
+ worker_pid_file_path,
18
18
  open_path_in_file_explorer,
19
- compute_agent_summary,
19
+ compute_worker_summary,
20
20
  )
21
21
 
22
22
 
23
- bp = Blueprint("agents", __name__)
23
+ bp = Blueprint("workers", __name__)
24
24
 
25
25
 
26
- @bp.get("/agent/status")
27
- def agent_status():
28
- return jsonify(agent_status_payload())
26
+ @bp.get("/worker/status")
27
+ def worker_status():
28
+ return jsonify(worker_status_payload())
29
29
 
30
30
 
31
- @bp.post("/agent/start")
32
- def agent_start():
31
+ @bp.post("/worker/start")
32
+ def worker_start():
33
33
  cfg = current_app.config["QALITA_CONFIG_OBJ"]
34
- agent_name = None
34
+ worker_name = None
35
35
 
36
- st = agent_status_payload()
36
+ st = worker_status_payload()
37
37
  if st.get("running"):
38
38
  return jsonify({"ok": True, "already_running": True, **st})
39
39
 
40
40
  try:
41
41
  sel_path = read_selected_env()
42
42
  if sel_path and os.path.isfile(sel_path):
43
- logger.info(f"agent_start: applying selected env at [{sel_path}]")
43
+ logger.info(f"worker_start: applying selected env at [{sel_path}]")
44
44
  _login_with_env(sel_path)
45
45
  except Exception as exc:
46
- logger.error(f"agent_start: failed applying selected env: {exc}")
46
+ logger.error(f"worker_start: failed applying selected env: {exc}")
47
47
  return (
48
48
  jsonify({"ok": False, "error": f"Failed to apply selected context: {exc}"}),
49
49
  400,
@@ -53,32 +53,32 @@ def agent_start():
53
53
  sel_path = read_selected_env()
54
54
  if sel_path and os.path.isfile(sel_path):
55
55
  data = parse_env_file(sel_path)
56
- agent_name = (
57
- data.get("QALITA_AGENT_NAME")
56
+ worker_name = (
57
+ data.get("QALITA_WORKER_NAME")
58
58
  or data.get("AGENT_NAME")
59
59
  or data.get("NAME")
60
60
  or None
61
61
  )
62
62
  except Exception:
63
- agent_name = None
64
- if not agent_name:
63
+ worker_name = None
64
+ if not worker_name:
65
65
  try:
66
- agent_name = getattr(cfg, "name", None) or None
66
+ worker_name = getattr(cfg, "name", None) or None
67
67
  except Exception:
68
- agent_name = None
69
- if not agent_name:
68
+ worker_name = None
69
+ if not worker_name:
70
70
  try:
71
- raw = cfg.load_agent_config()
71
+ raw = cfg.load_worker_config()
72
72
  if isinstance(raw, dict) and raw:
73
- agent_name = (
73
+ worker_name = (
74
74
  (raw.get("context", {}).get("remote", {}) or {}).get("name")
75
75
  or raw.get("name")
76
76
  or None
77
77
  )
78
78
  except Exception:
79
- agent_name = None
80
- if not agent_name:
81
- agent_name = "agent"
79
+ worker_name = None
80
+ if not worker_name:
81
+ worker_name = "agent"
82
82
 
83
83
  # Ensure we have minimum credentials before preflight
84
84
  if not getattr(cfg, "token", None) or not getattr(cfg, "url", None):
@@ -144,7 +144,7 @@ def agent_start():
144
144
  env["QALITA_HOME"] = cfg.qalita_home # type: ignore[attr-defined]
145
145
  except Exception:
146
146
  env["QALITA_HOME"] = os.path.expanduser("~/.qalita")
147
- logger.info(f"agent_start: QALITA_HOME resolved to [{env.get('QALITA_HOME')}]")
147
+ logger.info(f"worker_start: QALITA_HOME resolved to [{env.get('QALITA_HOME')}]")
148
148
  try:
149
149
  sel_path = read_selected_env()
150
150
  if sel_path and os.path.isfile(sel_path):
@@ -161,12 +161,12 @@ def agent_start():
161
161
  except Exception:
162
162
  pass
163
163
  try:
164
- if not any(env.get(k) for k in ("QALITA_AGENT_MODE", "AGENT_MODE", "MODE")):
165
- env["QALITA_AGENT_MODE"] = "worker"
164
+ if not any(env.get(k) for k in ("QALITA_WORKER_MODE", "AGENT_MODE", "MODE")):
165
+ env["QALITA_WORKER_MODE"] = "worker"
166
166
  except Exception:
167
- env["QALITA_AGENT_MODE"] = "worker"
167
+ env["QALITA_WORKER_MODE"] = "worker"
168
168
  logger.info(
169
- f"agent_start: effective agent mode is [{env.get('QALITA_AGENT_MODE') or env.get('AGENT_MODE') or env.get('MODE')}]"
169
+ f"worker_start: effective agent mode is [{env.get('QALITA_WORKER_MODE') or env.get('AGENT_MODE') or env.get('MODE')}]"
170
170
  )
171
171
  if os.name == "nt":
172
172
  python_bin = sys.executable or "python"
@@ -174,23 +174,23 @@ def agent_start():
174
174
  python_bin,
175
175
  "-m",
176
176
  "qalita",
177
- "agent",
177
+ "worker",
178
178
  "-n",
179
- str(agent_name),
179
+ str(worker_name),
180
180
  "-m",
181
181
  "worker",
182
182
  "run",
183
183
  ]
184
- logger.info(f"agent_start: using python interpreter [{python_bin}]")
184
+ logger.info(f"worker_start: using python interpreter [{python_bin}]")
185
185
  else:
186
- cmd = ["qalita", "agent", "-n", str(agent_name), "-m", "worker", "run"]
187
- logger.info(f"agent_start: executing command: {' '.join(cmd)}")
188
- log_path = agent_log_file_path()
186
+ cmd = ["qalita", "worker", "-n", str(worker_name), "-m", "worker", "run"]
187
+ logger.info(f"worker_start: executing command: {' '.join(cmd)}")
188
+ log_path = worker_log_file_path()
189
189
  try:
190
190
  os.makedirs(os.path.dirname(log_path), exist_ok=True)
191
191
  except Exception:
192
192
  pass
193
- logger.info(f"agent_start: logging to [{log_path}]")
193
+ logger.info(f"worker_start: logging to [{log_path}]")
194
194
  log_file = open(log_path, "a", encoding="utf-8", buffering=1)
195
195
  popen_kwargs = {"stdout": log_file, "stderr": log_file, "env": env}
196
196
  if os.name == "nt":
@@ -202,23 +202,23 @@ def agent_start():
202
202
  DETACHED_PROCESS | CREATE_NEW_PROCESS_GROUP | CREATE_NO_WINDOW
203
203
  )
204
204
  logger.info(
205
- "agent_start: using Windows creation flags DETACHED_PROCESS | CREATE_NEW_PROCESS_GROUP | CREATE_NO_WINDOW"
205
+ "worker_start: using Windows creation flags DETACHED_PROCESS | CREATE_NEW_PROCESS_GROUP | CREATE_NO_WINDOW"
206
206
  )
207
207
  except Exception:
208
208
  pass
209
209
  else:
210
210
  popen_kwargs["start_new_session"] = True
211
- logger.info("agent_start: using POSIX start_new_session=True")
211
+ logger.info("worker_start: using POSIX start_new_session=True")
212
212
  proc = subprocess.Popen(cmd, **popen_kwargs)
213
213
  try:
214
- with open(agent_pid_file_path(), "w", encoding="utf-8") as f:
214
+ with open(worker_pid_file_path(), "w", encoding="utf-8") as f:
215
215
  f.write(str(proc.pid))
216
216
  except Exception:
217
217
  pass
218
- logger.info(f"agent_start: started process with PID [{proc.pid}]")
218
+ logger.info(f"worker_start: started process with PID [{proc.pid}]")
219
219
  return jsonify({"ok": True, "pid": proc.pid, "login_ok": True})
220
220
  except Exception as exc:
221
- logger.error(f"agent_start: primary launch failed: {exc}")
221
+ logger.error(f"worker_start: primary launch failed: {exc}")
222
222
  try:
223
223
  env = dict(os.environ)
224
224
  try:
@@ -226,7 +226,7 @@ def agent_start():
226
226
  except Exception:
227
227
  env["QALITA_HOME"] = os.path.expanduser("~/.qalita")
228
228
  logger.info(
229
- f"agent_start(fallback): QALITA_HOME resolved to [{env.get('QALITA_HOME')}]"
229
+ f"worker_start(fallback): QALITA_HOME resolved to [{env.get('QALITA_HOME')}]"
230
230
  )
231
231
  sel_path = read_selected_env()
232
232
  if sel_path and os.path.isfile(sel_path):
@@ -242,33 +242,33 @@ def agent_start():
242
242
  env[k] = v
243
243
  try:
244
244
  if not any(
245
- env.get(k) for k in ("QALITA_AGENT_MODE", "AGENT_MODE", "MODE")
245
+ env.get(k) for k in ("QALITA_WORKER_MODE", "AGENT_MODE", "MODE")
246
246
  ):
247
- env["QALITA_AGENT_MODE"] = "worker"
247
+ env["QALITA_WORKER_MODE"] = "worker"
248
248
  except Exception:
249
- env["QALITA_AGENT_MODE"] = "worker"
249
+ env["QALITA_WORKER_MODE"] = "worker"
250
250
  logger.info(
251
- f"agent_start(fallback): effective agent mode is [{env.get('QALITA_AGENT_MODE') or env.get('AGENT_MODE') or env.get('MODE')}]"
251
+ f"worker_start(fallback): effective agent mode is [{env.get('QALITA_WORKER_MODE') or env.get('AGENT_MODE') or env.get('MODE')}]"
252
252
  )
253
253
  python_bin = sys.executable or "python3"
254
254
  cmd = [
255
255
  python_bin,
256
256
  "-m",
257
257
  "qalita",
258
- "agent",
258
+ "worker",
259
259
  "-n",
260
- str(agent_name),
260
+ str(worker_name),
261
261
  "-m",
262
262
  "worker",
263
263
  "run",
264
264
  ]
265
- logger.info(f"agent_start(fallback): executing command: {' '.join(cmd)}")
266
- log_path = agent_log_file_path()
265
+ logger.info(f"worker_start(fallback): executing command: {' '.join(cmd)}")
266
+ log_path = worker_log_file_path()
267
267
  try:
268
268
  os.makedirs(os.path.dirname(log_path), exist_ok=True)
269
269
  except Exception:
270
270
  pass
271
- logger.info(f"agent_start(fallback): logging to [{log_path}]")
271
+ logger.info(f"worker_start(fallback): logging to [{log_path}]")
272
272
  log_file = open(log_path, "a", encoding="utf-8", buffering=1)
273
273
  popen_kwargs = {"stdout": log_file, "stderr": log_file, "env": env}
274
274
  if os.name == "nt":
@@ -280,31 +280,31 @@ def agent_start():
280
280
  DETACHED_PROCESS | CREATE_NEW_PROCESS_GROUP | CREATE_NO_WINDOW
281
281
  )
282
282
  logger.info(
283
- "agent_start(fallback): using Windows creation flags DETACHED_PROCESS | CREATE_NEW_PROCESS_GROUP | CREATE_NO_WINDOW"
283
+ "worker_start(fallback): using Windows creation flags DETACHED_PROCESS | CREATE_NEW_PROCESS_GROUP | CREATE_NO_WINDOW"
284
284
  )
285
285
  except Exception:
286
286
  pass
287
287
  else:
288
288
  popen_kwargs["start_new_session"] = True
289
- logger.info("agent_start(fallback): using POSIX start_new_session=True")
289
+ logger.info("worker_start(fallback): using POSIX start_new_session=True")
290
290
  proc = subprocess.Popen(cmd, **popen_kwargs)
291
- with open(agent_pid_file_path(), "w", encoding="utf-8") as f:
291
+ with open(worker_pid_file_path(), "w", encoding="utf-8") as f:
292
292
  f.write(str(proc.pid))
293
- logger.info(f"agent_start(fallback): started process with PID [{proc.pid}]")
293
+ logger.info(f"worker_start(fallback): started process with PID [{proc.pid}]")
294
294
  return jsonify(
295
295
  {"ok": True, "pid": proc.pid, "fallback": True, "login_ok": True}
296
296
  )
297
297
  except Exception as exc2:
298
- logger.error(f"agent_start(fallback): launch failed: {exc2}")
298
+ logger.error(f"worker_start(fallback): launch failed: {exc2}")
299
299
  return (
300
300
  jsonify({"ok": False, "error": f"{exc}", "fallback_error": f"{exc2}"}),
301
301
  500,
302
302
  )
303
303
 
304
304
 
305
- @bp.post("/agent/stop")
306
- def agent_stop():
307
- pid = _read_agent_pid()
305
+ @bp.post("/worker/stop")
306
+ def worker_stop():
307
+ pid = _read_worker_pid()
308
308
  if not pid:
309
309
  return jsonify({"ok": True, "already_stopped": True})
310
310
  if os.name == "nt":
@@ -328,7 +328,7 @@ def agent_stop():
328
328
  except Exception:
329
329
  pass
330
330
  try:
331
- p = agent_pid_file_path()
331
+ p = worker_pid_file_path()
332
332
  if os.path.exists(p):
333
333
  os.remove(p)
334
334
  except Exception:
@@ -336,138 +336,61 @@ def agent_stop():
336
336
  return jsonify({"ok": True})
337
337
 
338
338
 
339
- @bp.get("/agent/summary")
340
- def agent_summary():
339
+ @bp.get("/worker/summary")
340
+ def worker_summary():
341
341
  cfg = current_app.config["QALITA_CONFIG_OBJ"]
342
- agent_conf, agent_runs = compute_agent_summary(cfg)
343
- return jsonify({"agent_conf": agent_conf or {}, "agent_runs": agent_runs})
342
+ worker_conf, worker_runs = compute_worker_summary(cfg)
343
+ return jsonify({"worker_conf": worker_conf or {}, "worker_runs": worker_runs})
344
344
 
345
345
 
346
- @bp.get("/agent/run/<run_name>")
347
- def open_agent_run(run_name: str):
346
+ @bp.get("/worker/run/<run_name>")
347
+ def open_worker_run(run_name: str):
348
348
  cfg = current_app.config["QALITA_CONFIG_OBJ"]
349
- run_root = cfg.get_agent_run_path()
350
- import os
349
+ run_root = cfg.get_worker_run_path()
351
350
 
352
351
  candidate = os.path.normpath(os.path.join(run_root, run_name))
353
352
  if not candidate.startswith(os.path.normpath(run_root) + os.sep):
354
- return (
355
- f"""
356
- <!doctype html><html>
357
- <head><meta charset='utf-8'><title>QALITA CLI - Agent Run</title>
358
- <link rel="icon" href="/static/favicon.ico" />
359
- <link rel="stylesheet" href="/static/styles.css" />
360
- </head>
361
- <body style='background-repeat: no-repeat;'>
362
- <div class="container">
363
- <h2>Agent Run - {candidate}</h2>
364
- <div class="card">
365
- <h1>Invalid path</h1>
366
- <p><a href='/'>Back to Dashboard</a></p>
367
- <hr/>
368
- <p>If the path is invalid it means :</p>
369
- <ul>
370
- <li>Your local agent is not the one that ran the analysis you are trying to get files from</li>
371
- <li>The job failed or was cancelled</li>
372
- </ul>
373
- </div>
374
- </div>
375
- <div class="footer">
376
- <div class="inner">
377
- <div>
378
- <span>&copy; QALITA</span> — QALITA CLI
379
- </div>
380
- <div>
381
- <span id="cli_version"></span>
382
- </div>
383
- </div>
384
- </div>
385
- </body></html>
386
- """,
387
- 400,
388
- )
353
+ return jsonify({
354
+ "ok": False,
355
+ "error": "Invalid path",
356
+ "path": candidate,
357
+ "message": "If the path is invalid it means: Your local agent is not the one that ran the analysis you are trying to get files from, or the job failed or was cancelled.",
358
+ }), 400
359
+
389
360
  if not os.path.isdir(candidate):
390
- return (
391
- f"""
392
- <!doctype html><html>
393
- <head><meta charset='utf-8'><title>QALITA CLI - Agent Run</title>
394
- <link rel="icon" href="/static/favicon.ico" />
395
- <link rel="stylesheet" href="/static/styles.css" />
396
- </head>
397
- <body style='background-repeat: no-repeat;'>
398
- <div class="container">
399
- <h2>Agent Run - {candidate}</h2>
400
- <div class="card">
401
- <h1>Run folder not found</h1>
402
- <p><a href='/'>Back to Dashboard</a></p>
403
- <hr/>
404
- <p>If the run folder does not exist it means :</p>
405
- <ul>
406
- <li>Your local agent is not the one that ran the analysis you are trying to get files from</li>
407
- <li>The job failed or was cancelled</li>
408
- </ul>
409
- </div>
410
- </div>
411
- <div class="footer">
412
- <div class="inner">
413
- <div>
414
- <span>&copy; QALITA</span> — QALITA CLI
415
- </div>
416
- <div>
417
- <span id="cli_version"></span>
418
- </div>
419
- </div>
420
- </div>
421
- </body></html>
422
- """,
423
- 404,
424
- )
361
+ return jsonify({
362
+ "ok": False,
363
+ "error": "Run folder not found",
364
+ "path": candidate,
365
+ "message": "If the run folder does not exist it means: Your local agent is not the one that ran the analysis you are trying to get files from, or the job failed or was cancelled.",
366
+ }), 404
367
+
425
368
  ok, method_used = open_path_in_file_explorer(candidate)
426
369
  status = "Opened" if ok else "Could not open automatically"
427
- return (
428
- f"""
429
- <!doctype html><html>
430
- <head><meta charset='utf-8'><title>QALITA CLI - Agent Run</title>
431
- <link rel="icon" href="/static/favicon.ico" />
432
- <link rel="stylesheet" href="/static/styles.css" />
433
- </head>
434
- <body style='background-repeat: no-repeat;'>
435
- <div class="container">
436
- <h2>Agent Run - {candidate}</h2>
437
- <div class="card">
438
- {status} file explorer
439
- <p>Path: <code>{candidate}</code></p>
440
- <p>Method: <code>{method_used}</code></p>
441
- <p><a href='/'>Back to Dashboard</a></p>
442
- <hr/>
443
- <p>If the explorer did not open, you can navigate to this folder manually.</p>
444
- <ul>
445
- <li>macOS: open Finder and Go to Folder…</li>
446
- <li>Linux: use your file manager or run: <code>xdg-open {candidate}</code></li>
447
- <li>Windows/WSL: use Explorer at <code>\\\\wsl$\\{os.environ.get('WSL_DISTRO_NAME','<distro>')}\\{candidate}</code></li>
448
- </ul>
449
- </div>
450
- </div>
451
- <div class="footer">
452
- <div class="inner">
453
- <div>
454
- <span>&copy; QALITA</span> — QALITA CLI
455
- </div>
456
- <div>
457
- <span id="cli_version"></span>
458
- </div>
459
- </div>
460
- </div>
461
- </body></html>
462
- """,
463
- 200,
464
- {"Content-Type": "text/html; charset=utf-8"},
465
- )
370
+
371
+ # Build instructions for manual navigation
372
+ instructions = []
373
+ if sys.platform == "darwin":
374
+ instructions.append("macOS: open Finder and Go to Folder…")
375
+ elif sys.platform.startswith("linux"):
376
+ instructions.append(f"Linux: use your file manager or run: xdg-open {candidate}")
377
+ elif sys.platform.startswith("win") or "WSL" in os.environ:
378
+ wsl_distro = os.environ.get('WSL_DISTRO_NAME', '<distro>')
379
+ instructions.append(f"Windows/WSL: use Explorer at \\\\wsl$\\{wsl_distro}\\{candidate}")
380
+
381
+ return jsonify({
382
+ "ok": True,
383
+ "status": status,
384
+ "path": candidate,
385
+ "method": method_used,
386
+ "instructions": instructions,
387
+ "message": f"{status} file explorer. If the explorer did not open, you can navigate to this folder manually.",
388
+ })
466
389
 
467
390
 
468
- def _read_agent_pid():
391
+ def _read_worker_pid():
469
392
  try:
470
- with open(agent_pid_file_path(), "r", encoding="utf-8") as f:
393
+ with open(worker_pid_file_path(), "r", encoding="utf-8") as f:
471
394
  raw = f.read().strip()
472
395
  return int(raw) if raw else None
473
396
  except Exception:
@@ -485,19 +408,19 @@ def _login_with_env(env_path: str) -> None:
485
408
  return default
486
409
 
487
410
  name = (
488
- pick("QALITA_AGENT_NAME", "AGENT_NAME", "NAME")
411
+ pick("QALITA_WORKER_NAME", "AGENT_NAME", "NAME")
489
412
  or getattr(cfg, "name", None)
490
413
  or "agent"
491
414
  )
492
415
  mode = (
493
- pick("QALITA_AGENT_MODE", "AGENT_MODE", "MODE")
416
+ pick("QALITA_WORKER_MODE", "AGENT_MODE", "MODE")
494
417
  or getattr(cfg, "mode", None)
495
418
  or "job"
496
419
  )
497
- token = pick("QALITA_AGENT_TOKEN", "QALITA_TOKEN", "TOKEN") or getattr(
420
+ token = pick("QALITA_WORKER_TOKEN", "QALITA_TOKEN", "TOKEN") or getattr(
498
421
  cfg, "token", None
499
422
  )
500
- url = pick("QALITA_AGENT_ENDPOINT", "QALITA_URL", "URL") or getattr(
423
+ url = pick("QALITA_WORKER_ENDPOINT", "QALITA_URL", "URL") or getattr(
501
424
  cfg, "url", None
502
425
  )
503
426
 
@@ -0,0 +1,66 @@
1
+ Metadata-Version: 2.4
2
+ Name: qalita
3
+ Version: 2.5.2
4
+ Summary: QALITA Platform Command Line Interface
5
+ Author-email: QALITA SAS <contact@qalita.io>
6
+ License-File: LICENSE
7
+ Classifier: Development Status :: 5 - Production/Stable
8
+ Classifier: Environment :: Console
9
+ Classifier: Intended Audience :: Developers
10
+ Classifier: Intended Audience :: Information Technology
11
+ Classifier: License :: Other/Proprietary License
12
+ Classifier: Natural Language :: English
13
+ Classifier: Operating System :: Unix
14
+ Classifier: Programming Language :: Python :: 3.10
15
+ Classifier: Programming Language :: Python :: 3.11
16
+ Classifier: Programming Language :: Python :: 3.12
17
+ Classifier: Programming Language :: Python :: 3.13
18
+ Classifier: Topic :: Software Development :: Quality Assurance
19
+ Requires-Python: >=3.10
20
+ Requires-Dist: azure-storage-blob>=12.19.1
21
+ Requires-Dist: boto3>=1.34.81
22
+ Requires-Dist: click>=8.1.3
23
+ Requires-Dist: croniter>=1.4.1
24
+ Requires-Dist: cryptography>=44.0.1
25
+ Requires-Dist: flask-socketio>=5.3.0
26
+ Requires-Dist: flask>=3.0.3
27
+ Requires-Dist: gevent-websocket>=0.10.1
28
+ Requires-Dist: gevent>=24.2.0
29
+ Requires-Dist: google-cloud-storage>=2.16.0
30
+ Requires-Dist: hdfs>=2.7.3
31
+ Requires-Dist: loguru>=0.7.0
32
+ Requires-Dist: openpyxl>=3.1.5
33
+ Requires-Dist: oracledb>=2.5.0
34
+ Requires-Dist: paramiko>=3.4.0
35
+ Requires-Dist: psycopg2-binary>=2.9.9
36
+ Requires-Dist: pymongo>=4.6.3
37
+ Requires-Dist: pymysql>=1.1.0
38
+ Requires-Dist: python-socketio>=5.10.0
39
+ Requires-Dist: pyyaml>=6.0.1
40
+ Requires-Dist: requests>=2.31.0
41
+ Requires-Dist: semver>=3.0.1
42
+ Requires-Dist: setuptools-rust>=1.8.1
43
+ Requires-Dist: tabulate>=0.9.0
44
+ Requires-Dist: toml>=0.10.2
45
+ Requires-Dist: waitress==3.0.2
46
+ Provides-Extra: dev
47
+ Requires-Dist: black>=25.1.0; extra == 'dev'
48
+ Requires-Dist: flake8<4.0,>=3.8.1; extra == 'dev'
49
+ Requires-Dist: pre-commit>=3.3.3; extra == 'dev'
50
+ Requires-Dist: pylint>=2.17.4; extra == 'dev'
51
+ Requires-Dist: pytest>=7.4.0; extra == 'dev'
52
+ Provides-Extra: studio
53
+ Requires-Dist: qalita-studio>=0.1.0; extra == 'studio'
54
+ Description-Content-Type: text/markdown
55
+
56
+ # QALITA Command Line Interface (CLI)
57
+
58
+ <div style="text-align:center;">
59
+ <img width="250px" height="auto" src="https://cloud.platform.qalita.io/logo.svg" style="max-width:250px;"/>
60
+ </div>
61
+
62
+ QALITA Command Line Interface (CLI) is a tool intended to be used by Data Engineers who setup's QALITA Platform's agents, sources and assets.
63
+
64
+ It gives easy to use command to help them make an up & running qalita platform's environment in no time.
65
+
66
+ Find the full documentation [in the online documentation](https://doc.qalita.io/docs/cli)
@@ -0,0 +1,24 @@
1
+ qalita/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
+ qalita/__main__.py,sha256=BIPwbMoOfE3trGx_lMut9L0G0vzrxXFsEwOF4sxCPYI,12654
3
+ qalita/commands/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
4
+ qalita/commands/pack.py,sha256=Eu1h-JJEtUBqr6OKPnwE8EuJOQcHpJtZBvKe0XFQaDg,37224
5
+ qalita/commands/source.py,sha256=ObRD2CcDynGbMrmj__FhWvPvR0H6HEn5QSLNR8awQUQ,30945
6
+ qalita/commands/worker.py,sha256=wDIaljpPpvKikbgC1L4IBTVmSradlWkHu0AeKSIrqXw,50642
7
+ qalita/internal/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
8
+ qalita/internal/config.py,sha256=FVooOC7T-IXOdzl3Q4TPr9ErhqP03QXmRSUo6OhIqIo,4314
9
+ qalita/internal/error_patterns.py,sha256=QDFNZEoTmqVOHkiGFljstY6VOhux7d4p8FIL3pKzwtQ,1447
10
+ qalita/internal/logger.py,sha256=4xWy2BZII89nUw4tKrLXFPOlVGONm8KUBgzX2XZ3u7g,1868
11
+ qalita/internal/request.py,sha256=s-rE9kKRhV9IEveclB2YjAY8FRevKb6qjblM8-PbV20,6209
12
+ qalita/internal/utils.py,sha256=Ph_OffznffqQn5_JuFz2RmKjtcEIhjAVSLB8CzbacxQ,5746
13
+ qalita/web/__init__.py,sha256=NRcQjZSizkqN0a-LutsN7X9LBQ8MhyazXBSuqzUEmXE,62
14
+ qalita/web/app.py,sha256=UvAzP7HcwE7E48ZEQViHHgVPE4Xw4TcIgdC7D_4xW4A,4973
15
+ qalita/web/blueprints/context.py,sha256=Ji0D3yjDF1VeKsqL8rv8PlNNpLSbxPx7GBKEWnrgnlk,4689
16
+ qalita/web/blueprints/dashboard.py,sha256=Zai5bMn50WWOzWRkkeWzKBnshMOZ7CK5tL7_jnTuXcA,5986
17
+ qalita/web/blueprints/helpers.py,sha256=4lSqT01IaWTFkFQB7J2-R5XKKsc4iDAxzeprPhhQIxI,17788
18
+ qalita/web/blueprints/sources.py,sha256=gjQqQMCkmJEh69Y2EJto-wyVDhk4VV9-9_o115W1O7g,33905
19
+ qalita/web/blueprints/workers.py,sha256=fsjLnJHrPmytxpJIrNaScmlgJ6qvYeMaXlBGYpMvFro,15868
20
+ qalita-2.5.2.dist-info/METADATA,sha256=mavlHXU1320kYk0rL40xZC6OqKek0T7pVqx8wo7RzKo,2524
21
+ qalita-2.5.2.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
22
+ qalita-2.5.2.dist-info/entry_points.txt,sha256=h_4bMcWq-LKrSLca7IAPQnqlZkxz7BBH8eio4nqZCVU,48
23
+ qalita-2.5.2.dist-info/licenses/LICENSE,sha256=cZt92dnxw87-VK4HB6KnmYV7mpf4JUdBkAHzFn1kQxM,22458
24
+ qalita-2.5.2.dist-info/RECORD,,
@@ -1,4 +1,4 @@
1
1
  Wheel-Version: 1.0
2
- Generator: poetry-core 2.2.1
2
+ Generator: hatchling 1.28.0
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ qalita = qalita.__main__:main