lumera 0.4.20__py3-none-any.whl → 0.4.22__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.
lumera/__init__.py CHANGED
@@ -21,6 +21,7 @@ from .sdk import (
21
21
  create_record,
22
22
  delete_collection,
23
23
  delete_record,
24
+ get_agent_run,
24
25
  get_collection,
25
26
  get_record,
26
27
  get_record_by_external_id,
@@ -28,6 +29,7 @@ from .sdk import (
28
29
  list_records,
29
30
  query_sql,
30
31
  replay_hook,
32
+ run_agent,
31
33
  save_to_lumera,
32
34
  update_collection,
33
35
  update_record,
@@ -52,6 +54,7 @@ __all__ = [
52
54
  "replay_hook",
53
55
  "query_sql",
54
56
  "run_agent",
57
+ "get_agent_run",
55
58
  "upload_lumera_file",
56
59
  "create_record",
57
60
  "update_record",
lumera/sdk.py CHANGED
@@ -367,8 +367,22 @@ def run_agent(
367
367
  status: str | None = None,
368
368
  error: str | None = None,
369
369
  provenance: Mapping[str, Any] | None = None,
370
+ external_id: str | None = None,
371
+ metadata: Mapping[str, Any] | None = None,
370
372
  ) -> dict[str, Any]:
371
- """Create an agent run and optionally upload files for file inputs."""
373
+ """Create an agent run and optionally upload files for file inputs.
374
+
375
+ Args:
376
+ agent_id: The automation/agent to run. Required.
377
+ inputs: Inputs payload (dict or JSON string). File refs are resolved automatically.
378
+ files: Mapping of input key -> path(s) to upload before run creation.
379
+ status: Optional initial status (defaults to ``queued``).
380
+ error: Optional error string to store alongside the initial status.
381
+ provenance: Custom provenance payload; falls back to environment-derived provenance.
382
+ external_id: Stable idempotency key. If provided, repeated calls with the same value
383
+ will return the existing run (server-side idempotency).
384
+ metadata: Arbitrary JSON metadata to persist with the run (e.g., callback_url).
385
+ """
372
386
 
373
387
  agent_id = agent_id.strip()
374
388
  if not agent_id:
@@ -398,6 +412,10 @@ def run_agent(
398
412
  payload["id"] = run_id
399
413
  if error is not None:
400
414
  payload["error"] = error
415
+ if external_id:
416
+ payload["external_id"] = external_id.strip()
417
+ if metadata is not None:
418
+ payload["metadata"] = _ensure_mapping(metadata, name="metadata")
401
419
  payload["lm_provenance"] = _ensure_mapping(
402
420
  provenance, name="provenance"
403
421
  ) or _default_provenance(agent_id, run_id)
@@ -408,6 +426,90 @@ def run_agent(
408
426
  return run
409
427
 
410
428
 
429
+ def get_agent_run(
430
+ agent_id: str | None = None,
431
+ *,
432
+ run_id: str | None = None,
433
+ external_id: str | None = None,
434
+ ) -> dict[str, Any]:
435
+ """Fetch an agent run by id or by agent_id + external_id idempotency key.
436
+
437
+ Args:
438
+ agent_id: Agent id for external_id lookup. Required when ``run_id`` is not provided.
439
+ run_id: Optional run id. When provided, this takes precedence over external_id lookup.
440
+ external_id: Optional idempotency key to look up the latest run for the agent.
441
+
442
+ Raises:
443
+ ValueError: If required identifiers are missing.
444
+ LumeraAPIError: If no matching run is found.
445
+ """
446
+
447
+ if run_id:
448
+ return _api_request("GET", f"agent-runs/{run_id}")
449
+
450
+ agent_id = agent_id.strip() if isinstance(agent_id, str) else ""
451
+ external_id = external_id.strip() if isinstance(external_id, str) else ""
452
+ if not agent_id:
453
+ raise ValueError("agent_id is required when run_id is not provided")
454
+ if not external_id:
455
+ raise ValueError("external_id is required when run_id is not provided")
456
+
457
+ resp = _api_request(
458
+ "GET",
459
+ "agent-runs",
460
+ params={"agent_id": agent_id, "external_id": external_id, "limit": 1},
461
+ )
462
+ runs = resp.get("agent_runs") if isinstance(resp, dict) else None
463
+ if runs and isinstance(runs, list) and runs and isinstance(runs[0], dict):
464
+ return runs[0]
465
+
466
+ url = _api_url("agent-runs")
467
+ raise _LumeraAPIError(404, "agent run not found", url=url, payload=None)
468
+
469
+
470
+ def update_agent_run(
471
+ run_id: str,
472
+ *,
473
+ result: Mapping[str, Any] | None = None,
474
+ status: str | None = None,
475
+ error: str | None = None,
476
+ metadata: Mapping[str, Any] | None = None,
477
+ ) -> dict[str, Any]:
478
+ """Update an agent run with result, status, or other fields.
479
+
480
+ Args:
481
+ run_id: The run id to update. Required.
482
+ result: Optional result payload to store (max 20KB).
483
+ status: Optional status update.
484
+ error: Optional error string.
485
+ metadata: Optional metadata update.
486
+
487
+ Returns:
488
+ The updated agent run record.
489
+ """
490
+ run_id = run_id.strip() if isinstance(run_id, str) else ""
491
+ if not run_id:
492
+ raise ValueError("run_id is required")
493
+
494
+ payload: dict[str, Any] = {}
495
+ if result is not None:
496
+ payload["result"] = _ensure_mapping(result, name="result")
497
+ if status is not None:
498
+ payload["status"] = status.strip()
499
+ if error is not None:
500
+ payload["error"] = error
501
+ if metadata is not None:
502
+ payload["metadata"] = _ensure_mapping(metadata, name="metadata")
503
+
504
+ if not payload:
505
+ raise ValueError("at least one field to update is required")
506
+
507
+ response = _api_request("PATCH", f"agent-runs/{run_id}", json_body=payload)
508
+ if not isinstance(response, dict):
509
+ raise RuntimeError("unexpected response payload")
510
+ return response
511
+
512
+
411
513
  def create_record(
412
514
  collection_id_or_name: str,
413
515
  payload: Mapping[str, Any] | None = None,
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: lumera
3
- Version: 0.4.20
3
+ Version: 0.4.22
4
4
  Summary: SDK for building on Lumera platform
5
5
  Requires-Python: >=3.11
6
6
  Requires-Dist: requests
@@ -0,0 +1,8 @@
1
+ lumera/__init__.py,sha256=p8lX2fW4iFo3quxQCtRs8Gm3WxNmjEY8wLOqLAYWwXI,1467
2
+ lumera/_utils.py,sha256=QyAaphxXGEK8XNPO0ghKLgTOYhAxcF_j3W0T8StzjxA,23610
3
+ lumera/google.py,sha256=3IVNL1HaOtsTmunl0alnGFuUAkzQQRyCEA3CKjlPqO0,10183
4
+ lumera/sdk.py,sha256=oW3e8X-1kpDE4lm9uFyRDiF9mBM-0XK-9aB7pm2XgOE,25677
5
+ lumera-0.4.22.dist-info/METADATA,sha256=1I7AeCvgTT2i50zU9kguHMuAb4ihA1XZ4SV9Fl0tksw,1576
6
+ lumera-0.4.22.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
7
+ lumera-0.4.22.dist-info/top_level.txt,sha256=HgfK4XQkpMTnM2E5iWM4kB711FnYqUY9dglzib3pWlE,7
8
+ lumera-0.4.22.dist-info/RECORD,,
@@ -1,8 +0,0 @@
1
- lumera/__init__.py,sha256=wiSDU8oEsyLWPx4aKjrOdRuG9xRCU2hx-2tl-0usQCI,1412
2
- lumera/_utils.py,sha256=QyAaphxXGEK8XNPO0ghKLgTOYhAxcF_j3W0T8StzjxA,23610
3
- lumera/google.py,sha256=3IVNL1HaOtsTmunl0alnGFuUAkzQQRyCEA3CKjlPqO0,10183
4
- lumera/sdk.py,sha256=ULWrBjRggaXtesmeBxq_eXM5a9hQMhZ9_f6-sOj4gKs,21827
5
- lumera-0.4.20.dist-info/METADATA,sha256=-oZpdGCUinqh6dvdK803pLbiL1a_e4SLk75wou7utH8,1576
6
- lumera-0.4.20.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
7
- lumera-0.4.20.dist-info/top_level.txt,sha256=HgfK4XQkpMTnM2E5iWM4kB711FnYqUY9dglzib3pWlE,7
8
- lumera-0.4.20.dist-info/RECORD,,