lumera 0.41.0.dev2026090405__tar.gz → 0.41.2.dev20260909__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 (79) hide show
  1. {lumera-0.41.0.dev2026090405 → lumera-0.41.2.dev20260909}/PKG-INFO +5 -5
  2. {lumera-0.41.0.dev2026090405 → lumera-0.41.2.dev20260909}/lumera/agents.py +27 -8
  3. {lumera-0.41.0.dev2026090405 → lumera-0.41.2.dev20260909}/lumera.egg-info/PKG-INFO +5 -5
  4. {lumera-0.41.0.dev2026090405 → lumera-0.41.2.dev20260909}/lumera.egg-info/requires.txt +4 -4
  5. {lumera-0.41.0.dev2026090405 → lumera-0.41.2.dev20260909}/pyproject.toml +5 -5
  6. {lumera-0.41.0.dev2026090405 → lumera-0.41.2.dev20260909}/tests/test_agents_live.py +71 -0
  7. {lumera-0.41.0.dev2026090405 → lumera-0.41.2.dev20260909}/lumera/__init__.py +0 -0
  8. {lumera-0.41.0.dev2026090405 → lumera-0.41.2.dev20260909}/lumera/_live.py +0 -0
  9. {lumera-0.41.0.dev2026090405 → lumera-0.41.2.dev20260909}/lumera/_utils.py +0 -0
  10. {lumera-0.41.0.dev2026090405 → lumera-0.41.2.dev20260909}/lumera/automations.py +0 -0
  11. {lumera-0.41.0.dev2026090405 → lumera-0.41.2.dev20260909}/lumera/email.py +0 -0
  12. {lumera-0.41.0.dev2026090405 → lumera-0.41.2.dev20260909}/lumera/exceptions.py +0 -0
  13. {lumera-0.41.0.dev2026090405 → lumera-0.41.2.dev20260909}/lumera/files.py +0 -0
  14. {lumera-0.41.0.dev2026090405 → lumera-0.41.2.dev20260909}/lumera/flags.py +0 -0
  15. {lumera-0.41.0.dev2026090405 → lumera-0.41.2.dev20260909}/lumera/function_resources.py +0 -0
  16. {lumera-0.41.0.dev2026090405 → lumera-0.41.2.dev20260909}/lumera/functions/__init__.py +0 -0
  17. {lumera-0.41.0.dev2026090405 → lumera-0.41.2.dev20260909}/lumera/functions/__main__.py +0 -0
  18. {lumera-0.41.0.dev2026090405 → lumera-0.41.2.dev20260909}/lumera/functions/_artifacts.py +0 -0
  19. {lumera-0.41.0.dev2026090405 → lumera-0.41.2.dev20260909}/lumera/functions/_config.py +0 -0
  20. {lumera-0.41.0.dev2026090405 → lumera-0.41.2.dev20260909}/lumera/functions/_context.py +0 -0
  21. {lumera-0.41.0.dev2026090405 → lumera-0.41.2.dev20260909}/lumera/functions/_contract.py +0 -0
  22. {lumera-0.41.0.dev2026090405 → lumera-0.41.2.dev20260909}/lumera/functions/_dependencies.py +0 -0
  23. {lumera-0.41.0.dev2026090405 → lumera-0.41.2.dev20260909}/lumera/functions/_errors.py +0 -0
  24. {lumera-0.41.0.dev2026090405 → lumera-0.41.2.dev20260909}/lumera/functions/_execution.py +0 -0
  25. {lumera-0.41.0.dev2026090405 → lumera-0.41.2.dev20260909}/lumera/functions/_jsonschema.py +0 -0
  26. {lumera-0.41.0.dev2026090405 → lumera-0.41.2.dev20260909}/lumera/functions/_registry.py +0 -0
  27. {lumera-0.41.0.dev2026090405 → lumera-0.41.2.dev20260909}/lumera/functions/_remote.py +0 -0
  28. {lumera-0.41.0.dev2026090405 → lumera-0.41.2.dev20260909}/lumera/functions/_runner.py +0 -0
  29. {lumera-0.41.0.dev2026090405 → lumera-0.41.2.dev20260909}/lumera/functions/_runtime.py +0 -0
  30. {lumera-0.41.0.dev2026090405 → lumera-0.41.2.dev20260909}/lumera/functions/testing.py +0 -0
  31. {lumera-0.41.0.dev2026090405 → lumera-0.41.2.dev20260909}/lumera/google.py +0 -0
  32. {lumera-0.41.0.dev2026090405 → lumera-0.41.2.dev20260909}/lumera/integrations/__init__.py +0 -0
  33. {lumera-0.41.0.dev2026090405 → lumera-0.41.2.dev20260909}/lumera/integrations/bill.py +0 -0
  34. {lumera-0.41.0.dev2026090405 → lumera-0.41.2.dev20260909}/lumera/integrations/finch.py +0 -0
  35. {lumera-0.41.0.dev2026090405 → lumera-0.41.2.dev20260909}/lumera/integrations/google.py +0 -0
  36. {lumera-0.41.0.dev2026090405 → lumera-0.41.2.dev20260909}/lumera/integrations/kafka.py +0 -0
  37. {lumera-0.41.0.dev2026090405 → lumera-0.41.2.dev20260909}/lumera/integrations/netsuite.py +0 -0
  38. {lumera-0.41.0.dev2026090405 → lumera-0.41.2.dev20260909}/lumera/integrations/salesforce.py +0 -0
  39. {lumera-0.41.0.dev2026090405 → lumera-0.41.2.dev20260909}/lumera/integrations/slack.py +0 -0
  40. {lumera-0.41.0.dev2026090405 → lumera-0.41.2.dev20260909}/lumera/integrations/snowflake.py +0 -0
  41. {lumera-0.41.0.dev2026090405 → lumera-0.41.2.dev20260909}/lumera/llm.py +0 -0
  42. {lumera-0.41.0.dev2026090405 → lumera-0.41.2.dev20260909}/lumera/pb.py +0 -0
  43. {lumera-0.41.0.dev2026090405 → lumera-0.41.2.dev20260909}/lumera/releases/__init__.py +0 -0
  44. {lumera-0.41.0.dev2026090405 → lumera-0.41.2.dev20260909}/lumera/releases/__main__.py +0 -0
  45. {lumera-0.41.0.dev2026090405 → lumera-0.41.2.dev20260909}/lumera/releases/_api_child.py +0 -0
  46. {lumera-0.41.0.dev2026090405 → lumera-0.41.2.dev20260909}/lumera/releases/_archive.py +0 -0
  47. {lumera-0.41.0.dev2026090405 → lumera-0.41.2.dev20260909}/lumera/releases/_builder.py +0 -0
  48. {lumera-0.41.0.dev2026090405 → lumera-0.41.2.dev20260909}/lumera/releases/_config.py +0 -0
  49. {lumera-0.41.0.dev2026090405 → lumera-0.41.2.dev20260909}/lumera/releases/_contracts.py +0 -0
  50. {lumera-0.41.0.dev2026090405 → lumera-0.41.2.dev20260909}/lumera/releases/_durable_event.py +0 -0
  51. {lumera-0.41.0.dev2026090405 → lumera-0.41.2.dev20260909}/lumera/releases/_errors.py +0 -0
  52. {lumera-0.41.0.dev2026090405 → lumera-0.41.2.dev20260909}/lumera/releases/_function_child.py +0 -0
  53. {lumera-0.41.0.dev2026090405 → lumera-0.41.2.dev20260909}/lumera/releases/_projection.py +0 -0
  54. {lumera-0.41.0.dev2026090405 → lumera-0.41.2.dev20260909}/lumera/releases/_runtime.py +0 -0
  55. {lumera-0.41.0.dev2026090405 → lumera-0.41.2.dev20260909}/lumera/releases/_runtime_child.py +0 -0
  56. {lumera-0.41.0.dev2026090405 → lumera-0.41.2.dev20260909}/lumera/releases/_schemas.py +0 -0
  57. {lumera-0.41.0.dev2026090405 → lumera-0.41.2.dev20260909}/lumera/releases/_target.py +0 -0
  58. {lumera-0.41.0.dev2026090405 → lumera-0.41.2.dev20260909}/lumera/releases/_worker_child.py +0 -0
  59. {lumera-0.41.0.dev2026090405 → lumera-0.41.2.dev20260909}/lumera/releases/_worker_protocol.py +0 -0
  60. {lumera-0.41.0.dev2026090405 → lumera-0.41.2.dev20260909}/lumera/sdk.py +0 -0
  61. {lumera-0.41.0.dev2026090405 → lumera-0.41.2.dev20260909}/lumera/storage.py +0 -0
  62. {lumera-0.41.0.dev2026090405 → lumera-0.41.2.dev20260909}/lumera/webhooks.py +0 -0
  63. {lumera-0.41.0.dev2026090405 → lumera-0.41.2.dev20260909}/lumera.egg-info/SOURCES.txt +0 -0
  64. {lumera-0.41.0.dev2026090405 → lumera-0.41.2.dev20260909}/lumera.egg-info/dependency_links.txt +0 -0
  65. {lumera-0.41.0.dev2026090405 → lumera-0.41.2.dev20260909}/lumera.egg-info/top_level.txt +0 -0
  66. {lumera-0.41.0.dev2026090405 → lumera-0.41.2.dev20260909}/setup.cfg +0 -0
  67. {lumera-0.41.0.dev2026090405 → lumera-0.41.2.dev20260909}/tests/test_automations.py +0 -0
  68. {lumera-0.41.0.dev2026090405 → lumera-0.41.2.dev20260909}/tests/test_flags.py +0 -0
  69. {lumera-0.41.0.dev2026090405 → lumera-0.41.2.dev20260909}/tests/test_function_resources.py +0 -0
  70. {lumera-0.41.0.dev2026090405 → lumera-0.41.2.dev20260909}/tests/test_integrations_bill.py +0 -0
  71. {lumera-0.41.0.dev2026090405 → lumera-0.41.2.dev20260909}/tests/test_integrations_finch.py +0 -0
  72. {lumera-0.41.0.dev2026090405 → lumera-0.41.2.dev20260909}/tests/test_integrations_google.py +0 -0
  73. {lumera-0.41.0.dev2026090405 → lumera-0.41.2.dev20260909}/tests/test_integrations_kafka.py +0 -0
  74. {lumera-0.41.0.dev2026090405 → lumera-0.41.2.dev20260909}/tests/test_integrations_netsuite.py +0 -0
  75. {lumera-0.41.0.dev2026090405 → lumera-0.41.2.dev20260909}/tests/test_integrations_salesforce.py +0 -0
  76. {lumera-0.41.0.dev2026090405 → lumera-0.41.2.dev20260909}/tests/test_integrations_snowflake.py +0 -0
  77. {lumera-0.41.0.dev2026090405 → lumera-0.41.2.dev20260909}/tests/test_lazy_imports.py +0 -0
  78. {lumera-0.41.0.dev2026090405 → lumera-0.41.2.dev20260909}/tests/test_sdk.py +0 -0
  79. {lumera-0.41.0.dev2026090405 → lumera-0.41.2.dev20260909}/tests/test_webhooks.py +0 -0
@@ -1,10 +1,10 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: lumera
3
- Version: 0.41.0.dev2026090405
3
+ Version: 0.41.2.dev20260909
4
4
  Summary: SDK for building on Lumera platform
5
5
  Requires-Python: >=3.11
6
- Requires-Dist: requests
7
- Requires-Dist: python-dotenv
6
+ Requires-Dist: requests>=2.33.0
7
+ Requires-Dist: python-dotenv>=1.2.2
8
8
  Requires-Dist: google-api-python-client==2.173.0
9
9
  Requires-Dist: simple-salesforce==1.12.6
10
10
  Requires-Dist: slack_sdk==3.35.0
@@ -38,10 +38,10 @@ Requires-Dist: pandas==2.3.0; extra == "full"
38
38
  Requires-Dist: pdfplumber; extra == "full"
39
39
  Requires-Dist: pydantic<3.0.0,>=2.12.3; extra == "full"
40
40
  Requires-Dist: PyGithub==2.6.1; extra == "full"
41
- Requires-Dist: python-dotenv==1.1.0; extra == "full"
41
+ Requires-Dist: python-dotenv==1.2.2; extra == "full"
42
42
  Requires-Dist: pyzmq; extra == "full"
43
43
  Requires-Dist: simple-salesforce==1.12.6; extra == "full"
44
44
  Requires-Dist: slack_sdk==3.35.0; extra == "full"
45
45
  Requires-Dist: tabulate; extra == "full"
46
46
  Requires-Dist: xlsxwriter==3.2.5; extra == "full"
47
- Requires-Dist: requests==2.32.4; extra == "full"
47
+ Requires-Dist: requests==2.33.0; extra == "full"
@@ -412,12 +412,31 @@ def _uploaded_file_reference(upload: Mapping[str, Any]) -> str:
412
412
  return f"[Uploaded: {path.strip()}]"
413
413
 
414
414
 
415
- def _message_with_uploaded_files(message: str, uploads: list[dict[str, Any]]) -> str:
416
- refs = [_uploaded_file_reference(upload) for upload in uploads]
417
- if not refs:
418
- return message
419
- prompt = message or "Please review the uploaded file(s)."
420
- return f"{' '.join(refs)}\n\n{prompt}"
415
+ def _prompt_with_uploaded_files(message: str, uploads: list[dict[str, Any]]) -> dict[str, Any]:
416
+ attachments = []
417
+ refs = []
418
+ for upload in uploads:
419
+ # The upload endpoint chooses the delivery mode for this agent.
420
+ attachment_id = (upload.get("attachment_id") or "").strip()
421
+ if attachment_id:
422
+ attachments.append(
423
+ {
424
+ "id": attachment_id,
425
+ "filename": upload["filename"],
426
+ "size": upload["size"],
427
+ "content_type": upload["content_type"],
428
+ }
429
+ )
430
+ else:
431
+ refs.append(_uploaded_file_reference(upload))
432
+
433
+ prompt = (message or "Please review the uploaded file(s).") if uploads else message
434
+ if refs:
435
+ prompt = f"{' '.join(refs)}\n\n{prompt}"
436
+ payload: dict[str, Any] = {"message": prompt}
437
+ if attachments:
438
+ payload["attachments"] = attachments
439
+ return payload
421
440
 
422
441
 
423
442
  # ============================================================================
@@ -449,7 +468,7 @@ def invoke(
449
468
  session_id=session_id,
450
469
  timeout=timeout,
451
470
  )
452
- payload: dict[str, Any] = {"message": _message_with_uploaded_files(message, uploads)}
471
+ payload = _prompt_with_uploaded_files(message, uploads)
453
472
  if session_id:
454
473
  payload["session_id"] = session_id
455
474
  if policy_context is not None:
@@ -493,7 +512,7 @@ def start_live(
493
512
  session_id=session_id,
494
513
  timeout=timeout,
495
514
  )
496
- payload: dict[str, Any] = {"message": _message_with_uploaded_files(message, uploads)}
515
+ payload = _prompt_with_uploaded_files(message, uploads)
497
516
  if session_id:
498
517
  payload["session_id"] = session_id
499
518
  if enqueue_policy:
@@ -1,10 +1,10 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: lumera
3
- Version: 0.41.0.dev2026090405
3
+ Version: 0.41.2.dev20260909
4
4
  Summary: SDK for building on Lumera platform
5
5
  Requires-Python: >=3.11
6
- Requires-Dist: requests
7
- Requires-Dist: python-dotenv
6
+ Requires-Dist: requests>=2.33.0
7
+ Requires-Dist: python-dotenv>=1.2.2
8
8
  Requires-Dist: google-api-python-client==2.173.0
9
9
  Requires-Dist: simple-salesforce==1.12.6
10
10
  Requires-Dist: slack_sdk==3.35.0
@@ -38,10 +38,10 @@ Requires-Dist: pandas==2.3.0; extra == "full"
38
38
  Requires-Dist: pdfplumber; extra == "full"
39
39
  Requires-Dist: pydantic<3.0.0,>=2.12.3; extra == "full"
40
40
  Requires-Dist: PyGithub==2.6.1; extra == "full"
41
- Requires-Dist: python-dotenv==1.1.0; extra == "full"
41
+ Requires-Dist: python-dotenv==1.2.2; extra == "full"
42
42
  Requires-Dist: pyzmq; extra == "full"
43
43
  Requires-Dist: simple-salesforce==1.12.6; extra == "full"
44
44
  Requires-Dist: slack_sdk==3.35.0; extra == "full"
45
45
  Requires-Dist: tabulate; extra == "full"
46
46
  Requires-Dist: xlsxwriter==3.2.5; extra == "full"
47
- Requires-Dist: requests==2.32.4; extra == "full"
47
+ Requires-Dist: requests==2.33.0; extra == "full"
@@ -1,5 +1,5 @@
1
- requests
2
- python-dotenv
1
+ requests>=2.33.0
2
+ python-dotenv>=1.2.2
3
3
  google-api-python-client==2.173.0
4
4
  simple-salesforce==1.12.6
5
5
  slack_sdk==3.35.0
@@ -30,13 +30,13 @@ pandas==2.3.0
30
30
  pdfplumber
31
31
  pydantic<3.0.0,>=2.12.3
32
32
  PyGithub==2.6.1
33
- python-dotenv==1.1.0
33
+ python-dotenv==1.2.2
34
34
  pyzmq
35
35
  simple-salesforce==1.12.6
36
36
  slack_sdk==3.35.0
37
37
  tabulate
38
38
  xlsxwriter==3.2.5
39
- requests==2.32.4
39
+ requests==2.33.0
40
40
 
41
41
  [functions]
42
42
  pydantic<2.14.0,>=2.12.3
@@ -1,11 +1,11 @@
1
1
  [project]
2
2
  name = "lumera"
3
- version = "0.41.0.dev2026090405"
3
+ version = "0.41.2.dev20260909"
4
4
  description = "SDK for building on Lumera platform"
5
5
  requires-python = ">=3.11"
6
6
  dependencies = [
7
- "requests",
8
- "python-dotenv",
7
+ "requests>=2.33.0",
8
+ "python-dotenv>=1.2.2",
9
9
  "google-api-python-client==2.173.0",
10
10
  "simple-salesforce==1.12.6",
11
11
  "slack_sdk==3.35.0",
@@ -50,13 +50,13 @@ full = [
50
50
  "pdfplumber",
51
51
  "pydantic>=2.12.3,<3.0.0",
52
52
  "PyGithub==2.6.1",
53
- "python-dotenv==1.1.0",
53
+ "python-dotenv==1.2.2",
54
54
  "pyzmq",
55
55
  "simple-salesforce==1.12.6",
56
56
  "slack_sdk==3.35.0",
57
57
  "tabulate",
58
58
  "xlsxwriter==3.2.5",
59
- "requests==2.32.4",
59
+ "requests==2.33.0",
60
60
  ]
61
61
 
62
62
  [tool.setuptools.packages.find]
@@ -328,6 +328,77 @@ def test_invoke_uploads_files_before_prompt(
328
328
  assert "files" not in payload
329
329
 
330
330
 
331
+ @pytest.mark.parametrize("method", ["invoke", "start_live"])
332
+ @pytest.mark.parametrize("message", ["Review these", ""])
333
+ @pytest.mark.parametrize("include_legacy", [False, True])
334
+ def test_prompt_uses_attachment_ids_returned_by_upload(
335
+ monkeypatch: pytest.MonkeyPatch,
336
+ tmp_path: pathlib.Path,
337
+ method: str,
338
+ message: str,
339
+ include_legacy: bool,
340
+ ) -> None:
341
+ structured_file = tmp_path / "notes.txt"
342
+ structured_file.write_text("notes")
343
+ second_structured_file = tmp_path / "report.txt"
344
+ second_structured_file.write_text("report")
345
+ legacy_file = tmp_path / "older.txt"
346
+ legacy_file.write_text("older")
347
+ calls = []
348
+
349
+ def fake_api(http_method: str, path: str, **kwargs: object) -> dict[str, object]:
350
+ calls.append((http_method, path, kwargs))
351
+ if path.endswith("/upload"):
352
+ filename = kwargs["files"]["file"][0] # type: ignore[index]
353
+ if filename == "older.txt":
354
+ return {"path": "uploads/older.txt"}
355
+ attachment_id, size = {
356
+ "notes.txt": ("att_123456789012345678901", 5),
357
+ "report.txt": ("att_123456789012345678902", 6),
358
+ }[filename]
359
+ return {
360
+ "attachment_id": attachment_id,
361
+ "filename": filename,
362
+ "size": size,
363
+ "content_type": "text/plain",
364
+ "object_key": f"project-demo/uploads/{attachment_id}--{filename}",
365
+ }
366
+ return {"status": "accepted", "request_id": "req_1", "success": True}
367
+
368
+ monkeypatch.setattr(agents, "_api_request", fake_api)
369
+ files = [structured_file, second_structured_file]
370
+ if include_legacy:
371
+ files.append(legacy_file)
372
+ getattr(agents, method)("support-agent", message, files=files, session_id="case-1")
373
+
374
+ endpoint = "invoke" if method == "invoke" else "live/start"
375
+ assert [path for _, path, _ in calls] == [
376
+ *["agents/support-agent/upload" for _ in files],
377
+ f"agents/support-agent/{endpoint}",
378
+ ]
379
+ expected_message = message or "Please review the uploaded file(s)."
380
+ if include_legacy:
381
+ expected_message = f"[Uploaded: uploads/older.txt]\n\n{expected_message}"
382
+ assert calls[-1][2]["json_body"] == {
383
+ "message": expected_message,
384
+ "session_id": "case-1",
385
+ "attachments": [
386
+ {
387
+ "id": "att_123456789012345678901",
388
+ "filename": "notes.txt",
389
+ "size": 5,
390
+ "content_type": "text/plain",
391
+ },
392
+ {
393
+ "id": "att_123456789012345678902",
394
+ "filename": "report.txt",
395
+ "size": 6,
396
+ "content_type": "text/plain",
397
+ },
398
+ ],
399
+ }
400
+
401
+
331
402
  def test_get_live_state_uses_stream_snapshot_when_request_id_present(
332
403
  monkeypatch: pytest.MonkeyPatch,
333
404
  ) -> None: