mainsequence 4.4.4__tar.gz → 4.4.5__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 (138) hide show
  1. {mainsequence-4.4.4/mainsequence.egg-info → mainsequence-4.4.5}/PKG-INFO +1 -1
  2. {mainsequence-4.4.4 → mainsequence-4.4.5}/mainsequence/client/agent_runtime_models.py +71 -0
  3. {mainsequence-4.4.4 → mainsequence-4.4.5/mainsequence.egg-info}/PKG-INFO +1 -1
  4. {mainsequence-4.4.4 → mainsequence-4.4.5}/pyproject.toml +1 -1
  5. {mainsequence-4.4.4 → mainsequence-4.4.5}/tests/test_filter_normalization.py +99 -0
  6. {mainsequence-4.4.4 → mainsequence-4.4.5}/LICENSE +0 -0
  7. {mainsequence-4.4.4 → mainsequence-4.4.5}/README.md +0 -0
  8. {mainsequence-4.4.4 → mainsequence-4.4.5}/agent_scaffold/AGENTS.md +0 -0
  9. {mainsequence-4.4.4 → mainsequence-4.4.5}/agent_scaffold/skills/a2a_communication/SKILL.md +0 -0
  10. {mainsequence-4.4.4 → mainsequence-4.4.5}/agent_scaffold/skills/application_surfaces/api_surfaces/SKILL.md +0 -0
  11. {mainsequence-4.4.4 → mainsequence-4.4.5}/agent_scaffold/skills/command_center/adapter_from_api/SKILL.md +0 -0
  12. {mainsequence-4.4.4 → mainsequence-4.4.5}/agent_scaffold/skills/command_center/api_mock_prototyping/SKILL.md +0 -0
  13. {mainsequence-4.4.4 → mainsequence-4.4.5}/agent_scaffold/skills/command_center/app_components/SKILL.md +0 -0
  14. {mainsequence-4.4.4 → mainsequence-4.4.5}/agent_scaffold/skills/command_center/connections/SKILL.md +0 -0
  15. {mainsequence-4.4.4 → mainsequence-4.4.5}/agent_scaffold/skills/command_center/workspace_analysis/SKILL.md +0 -0
  16. {mainsequence-4.4.4 → mainsequence-4.4.5}/agent_scaffold/skills/command_center/workspace_builder/SKILL.md +0 -0
  17. {mainsequence-4.4.4 → mainsequence-4.4.5}/agent_scaffold/skills/command_center/workspace_design/SKILL.md +0 -0
  18. {mainsequence-4.4.4 → mainsequence-4.4.5}/agent_scaffold/skills/dashboards/streamlit/SKILL.md +0 -0
  19. {mainsequence-4.4.4 → mainsequence-4.4.5}/agent_scaffold/skills/data_access/exploration/SKILL.md +0 -0
  20. {mainsequence-4.4.4 → mainsequence-4.4.5}/agent_scaffold/skills/data_publishing/data_nodes/SKILL.md +0 -0
  21. {mainsequence-4.4.4 → mainsequence-4.4.5}/agent_scaffold/skills/data_publishing/meta_table_migrations/SKILL.md +0 -0
  22. {mainsequence-4.4.4 → mainsequence-4.4.5}/agent_scaffold/skills/data_publishing/meta_tables/SKILL.md +0 -0
  23. {mainsequence-4.4.4 → mainsequence-4.4.5}/agent_scaffold/skills/maintenance/bug_auditor/SKILL.md +0 -0
  24. {mainsequence-4.4.4 → mainsequence-4.4.5}/agent_scaffold/skills/ms-markets/SKILL.md +0 -0
  25. {mainsequence-4.4.4 → mainsequence-4.4.5}/agent_scaffold/skills/platform_operations/access_control_and_sharing/SKILL.md +0 -0
  26. {mainsequence-4.4.4 → mainsequence-4.4.5}/agent_scaffold/skills/platform_operations/orchestration_and_releases/SKILL.md +0 -0
  27. {mainsequence-4.4.4 → mainsequence-4.4.5}/agent_scaffold/skills/project_builder/SKILL.md +0 -0
  28. {mainsequence-4.4.4 → mainsequence-4.4.5}/agent_scaffold/skills/project_to_agent/SKILL.md +0 -0
  29. {mainsequence-4.4.4 → mainsequence-4.4.5}/mainsequence/__init__.py +0 -0
  30. {mainsequence-4.4.4 → mainsequence-4.4.5}/mainsequence/__main__.py +0 -0
  31. {mainsequence-4.4.4 → mainsequence-4.4.5}/mainsequence/bootstrap.py +0 -0
  32. {mainsequence-4.4.4 → mainsequence-4.4.5}/mainsequence/cli/__init__.py +0 -0
  33. {mainsequence-4.4.4 → mainsequence-4.4.5}/mainsequence/cli/api.py +0 -0
  34. {mainsequence-4.4.4 → mainsequence-4.4.5}/mainsequence/cli/browser_auth.py +0 -0
  35. {mainsequence-4.4.4 → mainsequence-4.4.5}/mainsequence/cli/cli.py +0 -0
  36. {mainsequence-4.4.4 → mainsequence-4.4.5}/mainsequence/cli/config.py +0 -0
  37. {mainsequence-4.4.4 → mainsequence-4.4.5}/mainsequence/cli/docker_utils.py +0 -0
  38. {mainsequence-4.4.4 → mainsequence-4.4.5}/mainsequence/cli/doctor.py +0 -0
  39. {mainsequence-4.4.4 → mainsequence-4.4.5}/mainsequence/cli/local_ops.py +0 -0
  40. {mainsequence-4.4.4 → mainsequence-4.4.5}/mainsequence/cli/migrations.py +0 -0
  41. {mainsequence-4.4.4 → mainsequence-4.4.5}/mainsequence/cli/model_filters.py +0 -0
  42. {mainsequence-4.4.4 → mainsequence-4.4.5}/mainsequence/cli/project_status.py +0 -0
  43. {mainsequence-4.4.4 → mainsequence-4.4.5}/mainsequence/cli/pydantic_cli.py +0 -0
  44. {mainsequence-4.4.4 → mainsequence-4.4.5}/mainsequence/cli/sdk_utils.py +0 -0
  45. {mainsequence-4.4.4 → mainsequence-4.4.5}/mainsequence/cli/ssh_utils.py +0 -0
  46. {mainsequence-4.4.4 → mainsequence-4.4.5}/mainsequence/cli/ui.py +0 -0
  47. {mainsequence-4.4.4 → mainsequence-4.4.5}/mainsequence/client/__init__.py +0 -0
  48. {mainsequence-4.4.4 → mainsequence-4.4.5}/mainsequence/client/base.py +0 -0
  49. {mainsequence-4.4.4 → mainsequence-4.4.5}/mainsequence/client/client.py +0 -0
  50. {mainsequence-4.4.4 → mainsequence-4.4.5}/mainsequence/client/command_center/__init__.py +0 -0
  51. {mainsequence-4.4.4 → mainsequence-4.4.5}/mainsequence/client/command_center/app_component.py +0 -0
  52. {mainsequence-4.4.4 → mainsequence-4.4.5}/mainsequence/client/command_center/connections.py +0 -0
  53. {mainsequence-4.4.4 → mainsequence-4.4.5}/mainsequence/client/command_center/data_models.py +0 -0
  54. {mainsequence-4.4.4 → mainsequence-4.4.5}/mainsequence/client/command_center/workspace.py +0 -0
  55. {mainsequence-4.4.4 → mainsequence-4.4.5}/mainsequence/client/command_center/workspace_snapshot.py +0 -0
  56. {mainsequence-4.4.4 → mainsequence-4.4.5}/mainsequence/client/compute_validation.py +0 -0
  57. {mainsequence-4.4.4 → mainsequence-4.4.5}/mainsequence/client/data_sources_interfaces/__init__.py +0 -0
  58. {mainsequence-4.4.4 → mainsequence-4.4.5}/mainsequence/client/data_sources_interfaces/duckdb.py +0 -0
  59. {mainsequence-4.4.4 → mainsequence-4.4.5}/mainsequence/client/data_sources_interfaces/local_paths.py +0 -0
  60. {mainsequence-4.4.4 → mainsequence-4.4.5}/mainsequence/client/data_sources_interfaces/sqlite.py +0 -0
  61. {mainsequence-4.4.4 → mainsequence-4.4.5}/mainsequence/client/dtype_codec.py +0 -0
  62. {mainsequence-4.4.4 → mainsequence-4.4.5}/mainsequence/client/exceptions.py +0 -0
  63. {mainsequence-4.4.4 → mainsequence-4.4.5}/mainsequence/client/fastapi/__init__.py +0 -0
  64. {mainsequence-4.4.4 → mainsequence-4.4.5}/mainsequence/client/fastapi/auth.py +0 -0
  65. {mainsequence-4.4.4 → mainsequence-4.4.5}/mainsequence/client/metatables/__init__.py +0 -0
  66. {mainsequence-4.4.4 → mainsequence-4.4.5}/mainsequence/client/metatables/core.py +0 -0
  67. {mainsequence-4.4.4 → mainsequence-4.4.5}/mainsequence/client/models_foundry.py +0 -0
  68. {mainsequence-4.4.4 → mainsequence-4.4.5}/mainsequence/client/models_helpers.py +0 -0
  69. {mainsequence-4.4.4 → mainsequence-4.4.5}/mainsequence/client/models_user.py +0 -0
  70. {mainsequence-4.4.4 → mainsequence-4.4.5}/mainsequence/client/utils.py +0 -0
  71. {mainsequence-4.4.4 → mainsequence-4.4.5}/mainsequence/defaults.py +0 -0
  72. {mainsequence-4.4.4 → mainsequence-4.4.5}/mainsequence/instrumentation/__init__.py +0 -0
  73. {mainsequence-4.4.4 → mainsequence-4.4.5}/mainsequence/instrumentation/utils.py +0 -0
  74. {mainsequence-4.4.4 → mainsequence-4.4.5}/mainsequence/logconf.py +0 -0
  75. {mainsequence-4.4.4 → mainsequence-4.4.5}/mainsequence/meta_tables/__init__.py +0 -0
  76. {mainsequence-4.4.4 → mainsequence-4.4.5}/mainsequence/meta_tables/__main__.py +0 -0
  77. {mainsequence-4.4.4 → mainsequence-4.4.5}/mainsequence/meta_tables/compiled_sql/__init__.py +0 -0
  78. {mainsequence-4.4.4 → mainsequence-4.4.5}/mainsequence/meta_tables/compiled_sql/v1.py +0 -0
  79. {mainsequence-4.4.4 → mainsequence-4.4.5}/mainsequence/meta_tables/data_nodes/__init__.py +0 -0
  80. {mainsequence-4.4.4 → mainsequence-4.4.5}/mainsequence/meta_tables/data_nodes/build_operations.py +0 -0
  81. {mainsequence-4.4.4 → mainsequence-4.4.5}/mainsequence/meta_tables/data_nodes/data_nodes.py +0 -0
  82. {mainsequence-4.4.4 → mainsequence-4.4.5}/mainsequence/meta_tables/data_nodes/models.py +0 -0
  83. {mainsequence-4.4.4 → mainsequence-4.4.5}/mainsequence/meta_tables/data_nodes/namespacing.py +0 -0
  84. {mainsequence-4.4.4 → mainsequence-4.4.5}/mainsequence/meta_tables/data_nodes/persist_managers.py +0 -0
  85. {mainsequence-4.4.4 → mainsequence-4.4.5}/mainsequence/meta_tables/data_nodes/run_operations.py +0 -0
  86. {mainsequence-4.4.4 → mainsequence-4.4.5}/mainsequence/meta_tables/data_nodes/utils.py +0 -0
  87. {mainsequence-4.4.4 → mainsequence-4.4.5}/mainsequence/meta_tables/future_registry.py +0 -0
  88. {mainsequence-4.4.4 → mainsequence-4.4.5}/mainsequence/meta_tables/hashing.py +0 -0
  89. {mainsequence-4.4.4 → mainsequence-4.4.5}/mainsequence/meta_tables/migrations/__init__.py +0 -0
  90. {mainsequence-4.4.4 → mainsequence-4.4.5}/mainsequence/meta_tables/migrations/alembic.py +0 -0
  91. {mainsequence-4.4.4 → mainsequence-4.4.5}/mainsequence/meta_tables/migrations/env.py +0 -0
  92. {mainsequence-4.4.4 → mainsequence-4.4.5}/mainsequence/meta_tables/migrations/provider.py +0 -0
  93. {mainsequence-4.4.4 → mainsequence-4.4.5}/mainsequence/meta_tables/migrations/registry.py +0 -0
  94. {mainsequence-4.4.4 → mainsequence-4.4.5}/mainsequence/meta_tables/migrations/scaffold.py +0 -0
  95. {mainsequence-4.4.4 → mainsequence-4.4.5}/mainsequence/meta_tables/migrations/templates/__init__.py +0 -0
  96. {mainsequence-4.4.4 → mainsequence-4.4.5}/mainsequence/meta_tables/migrations/templates/env.py.mako +0 -0
  97. {mainsequence-4.4.4 → mainsequence-4.4.5}/mainsequence/meta_tables/migrations/templates/script.py.mako +0 -0
  98. {mainsequence-4.4.4 → mainsequence-4.4.5}/mainsequence/meta_tables/pydantic_metadata.py +0 -0
  99. {mainsequence-4.4.4 → mainsequence-4.4.5}/mainsequence/meta_tables/schema_names.py +0 -0
  100. {mainsequence-4.4.4 → mainsequence-4.4.5}/mainsequence/meta_tables/sqlalchemy_contracts.py +0 -0
  101. {mainsequence-4.4.4 → mainsequence-4.4.5}/mainsequence/runtime_flags.py +0 -0
  102. {mainsequence-4.4.4 → mainsequence-4.4.5}/mainsequence.egg-info/SOURCES.txt +0 -0
  103. {mainsequence-4.4.4 → mainsequence-4.4.5}/mainsequence.egg-info/dependency_links.txt +0 -0
  104. {mainsequence-4.4.4 → mainsequence-4.4.5}/mainsequence.egg-info/entry_points.txt +0 -0
  105. {mainsequence-4.4.4 → mainsequence-4.4.5}/mainsequence.egg-info/requires.txt +0 -0
  106. {mainsequence-4.4.4 → mainsequence-4.4.5}/mainsequence.egg-info/top_level.txt +0 -0
  107. {mainsequence-4.4.4 → mainsequence-4.4.5}/setup.cfg +0 -0
  108. {mainsequence-4.4.4 → mainsequence-4.4.5}/tests/test_auth_precedence.py +0 -0
  109. {mainsequence-4.4.4 → mainsequence-4.4.5}/tests/test_build_operations_hashing.py +0 -0
  110. {mainsequence-4.4.4 → mainsequence-4.4.5}/tests/test_cli.py +0 -0
  111. {mainsequence-4.4.4 → mainsequence-4.4.5}/tests/test_cli_browser_auth.py +0 -0
  112. {mainsequence-4.4.4 → mainsequence-4.4.5}/tests/test_cli_migrations.py +0 -0
  113. {mainsequence-4.4.4 → mainsequence-4.4.5}/tests/test_client.py +0 -0
  114. {mainsequence-4.4.4 → mainsequence-4.4.5}/tests/test_command_center_app_component_models.py +0 -0
  115. {mainsequence-4.4.4 → mainsequence-4.4.5}/tests/test_command_center_data_models.py +0 -0
  116. {mainsequence-4.4.4 → mainsequence-4.4.5}/tests/test_command_center_models.py +0 -0
  117. {mainsequence-4.4.4 → mainsequence-4.4.5}/tests/test_data_access_mixin_dimension_audit.py +0 -0
  118. {mainsequence-4.4.4 → mainsequence-4.4.5}/tests/test_data_node_storage_dimension_queries.py +0 -0
  119. {mainsequence-4.4.4 → mainsequence-4.4.5}/tests/test_data_node_update_flow.py +0 -0
  120. {mainsequence-4.4.4 → mainsequence-4.4.5}/tests/test_dependency_extras.py +0 -0
  121. {mainsequence-4.4.4 → mainsequence-4.4.5}/tests/test_duckdb_interface_dimensions.py +0 -0
  122. {mainsequence-4.4.4 → mainsequence-4.4.5}/tests/test_instrumentation.py +0 -0
  123. {mainsequence-4.4.4 → mainsequence-4.4.5}/tests/test_logconf.py +0 -0
  124. {mainsequence-4.4.4 → mainsequence-4.4.5}/tests/test_meta_table_migrations.py +0 -0
  125. {mainsequence-4.4.4 → mainsequence-4.4.5}/tests/test_meta_tables_client_models.py +0 -0
  126. {mainsequence-4.4.4 → mainsequence-4.4.5}/tests/test_meta_tables_sqlalchemy_contracts.py +0 -0
  127. {mainsequence-4.4.4 → mainsequence-4.4.5}/tests/test_models_user_request_bound_auth.py +0 -0
  128. {mainsequence-4.4.4 → mainsequence-4.4.5}/tests/test_pod_project_resolution.py +0 -0
  129. {mainsequence-4.4.4 → mainsequence-4.4.5}/tests/test_project_batch_jobs_from_file.py +0 -0
  130. {mainsequence-4.4.4 → mainsequence-4.4.5}/tests/test_run_configuration.py +0 -0
  131. {mainsequence-4.4.4 → mainsequence-4.4.5}/tests/test_schema_names.py +0 -0
  132. {mainsequence-4.4.4 → mainsequence-4.4.5}/tests/test_secret_client_model.py +0 -0
  133. {mainsequence-4.4.4 → mainsequence-4.4.5}/tests/test_source_table_configuration.py +0 -0
  134. {mainsequence-4.4.4 → mainsequence-4.4.5}/tests/test_sqlite_interface_dimensions.py +0 -0
  135. {mainsequence-4.4.4 → mainsequence-4.4.5}/tests/test_update_runner_uid_runtime.py +0 -0
  136. {mainsequence-4.4.4 → mainsequence-4.4.5}/tests/test_update_statistics.py +0 -0
  137. {mainsequence-4.4.4 → mainsequence-4.4.5}/tests/test_update_uid_guards.py +0 -0
  138. {mainsequence-4.4.4 → mainsequence-4.4.5}/tests/test_workspace_snapshot.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mainsequence
3
- Version: 4.4.4
3
+ Version: 4.4.5
4
4
  Summary: Main Sequence SDK
5
5
  Author-email: Main Sequence GmbH <dev@main-sequence.io>
6
6
  License: MainSequence GmbH SDK License Agreement
@@ -318,6 +318,77 @@ class Agent(ShareableObjectMixin, BaseObjectOrm, BasePydanticModel):
318
318
  raise_for_response(response, payload=payload)
319
319
  return response.json()
320
320
 
321
+ def get_or_create_session_with_handle(
322
+ self,
323
+ *,
324
+ handle_unique_id: str,
325
+ name: str | None = None,
326
+ llm_provider: str | None = None,
327
+ llm_model: str | None = None,
328
+ llm_thinking: str | None = None,
329
+ session_metadata: dict[str, Any] | None = None,
330
+ timeout=None,
331
+ ) -> AgentSession:
332
+ """
333
+ Get or create this user's reusable session slot for this Agent.
334
+
335
+ Hits:
336
+ POST <detail_url>get_or_create_session_with_handle/
337
+
338
+ Request contract:
339
+ - `handle_unique_id` is required and is the stable session-slot key scoped
340
+ by `(agent, authenticated user)`.
341
+ - `name` is optional display text for a newly created session.
342
+ - LLM fields are creation-time overrides only. If the handle already has a
343
+ current session, the backend returns that session unchanged.
344
+ - `session_metadata` is creation-time caller metadata.
345
+
346
+ The response is expected to contain either a top-level `session` object or a
347
+ direct AgentSession payload. The SDK returns the AgentSession object.
348
+ """
349
+ resolved_handle_unique_id = str(handle_unique_id or "").strip()
350
+ if not resolved_handle_unique_id:
351
+ raise ValueError("handle_unique_id is required")
352
+
353
+ body: dict[str, Any] = {
354
+ "handle_unique_id": resolved_handle_unique_id,
355
+ }
356
+ if name is not None:
357
+ body["name"] = str(name)
358
+ if llm_provider is not None:
359
+ body["llm_provider"] = str(llm_provider)
360
+ if llm_model is not None:
361
+ body["llm_model"] = str(llm_model)
362
+ if llm_thinking is not None:
363
+ body["llm_thinking"] = str(llm_thinking)
364
+ if session_metadata is not None:
365
+ body["session_metadata"] = session_metadata
366
+
367
+ url = f"{self.get_detail_url()}get_or_create_session_with_handle/"
368
+ payload = {"json": serialize_to_json(body)}
369
+ response = make_request(
370
+ s=self.build_session(),
371
+ loaders=self.LOADERS,
372
+ r_type="POST",
373
+ url=url,
374
+ payload=payload,
375
+ time_out=timeout,
376
+ )
377
+ if response.status_code not in (200, 201):
378
+ raise_for_response(response, payload=payload)
379
+
380
+ response_payload = response.json()
381
+ session_payload = (
382
+ response_payload.get("session")
383
+ if isinstance(response_payload, dict)
384
+ else response_payload
385
+ )
386
+ if not isinstance(session_payload, dict):
387
+ raise TypeError(
388
+ "get_or_create_session_with_handle response must include a session object"
389
+ )
390
+ return AgentSession(**session_payload)
391
+
321
392
  def get_latest_session(self, timeout=None):
322
393
  """
323
394
  Fetch the latest recorded session for this agent.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mainsequence
3
- Version: 4.4.4
3
+ Version: 4.4.5
4
4
  Summary: Main Sequence SDK
5
5
  Author-email: Main Sequence GmbH <dev@main-sequence.io>
6
6
  License: MainSequence GmbH SDK License Agreement
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "mainsequence"
7
- version = "4.4.4"
7
+ version = "4.4.5"
8
8
  description = "Main Sequence SDK "
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.11"
@@ -1555,6 +1555,105 @@ def test_agent_a2a_allocation_sends_caller_session_uid(monkeypatch):
1555
1555
  }
1556
1556
 
1557
1557
 
1558
+ def test_agent_get_or_create_session_with_handle_posts_stable_handle_contract(monkeypatch):
1559
+ captured = {}
1560
+ agent_uid = "e0e75693-4110-464c-93e0-82c7fd9c9a23"
1561
+ session_uid = "3f1cc452-43ec-49cb-b2ba-87dbac164d29"
1562
+ user_uid = "fdf409f7-d16f-4f71-986b-9057db6c7eca"
1563
+ agent = agent_models_mod.Agent(
1564
+ uid=agent_uid,
1565
+ name="Research Copilot",
1566
+ agent_type="custom",
1567
+ agent_unique_id="research-copilot",
1568
+ description="Research assistant.",
1569
+ agent_card=None,
1570
+ llm_provider="openai",
1571
+ llm_model="gpt-5.4",
1572
+ llm_thinking="medium",
1573
+ )
1574
+
1575
+ class FakeResponse:
1576
+ status_code = 201
1577
+ content = b'{"ok": true}'
1578
+
1579
+ @staticmethod
1580
+ def json():
1581
+ return {
1582
+ "created": True,
1583
+ "handle_unique_id": "portfolio-review-q2-2026",
1584
+ "handle_uid": "6f91f6a7-d706-49c6-a910-8667aa0468a5",
1585
+ "session": {
1586
+ "uid": session_uid,
1587
+ "agent_uid": agent_uid,
1588
+ "agent_name": "Research Copilot",
1589
+ "agent_type": "custom",
1590
+ "created_by_user_uid": user_uid,
1591
+ "parent_session_uid": None,
1592
+ "name": "Quarterly portfolio review",
1593
+ "status": "running",
1594
+ "runtime_state": "running",
1595
+ "working": True,
1596
+ "started_at": "2026-01-01T00:00:00Z",
1597
+ "ended_at": None,
1598
+ "llm_provider": "openai",
1599
+ "llm_model": "gpt-5.4",
1600
+ "llm_thinking": "",
1601
+ "engine_name": "codex",
1602
+ "runtime_config_snapshot": {},
1603
+ "error_detail": "",
1604
+ "thread_id": "",
1605
+ "session_metadata": {"portfolio_uid": "portfolio-123"},
1606
+ "bound_handles": [
1607
+ {
1608
+ "handle_unique_id": "portfolio-review-q2-2026",
1609
+ "owner_user_uid": user_uid,
1610
+ "is_locked": False,
1611
+ }
1612
+ ],
1613
+ },
1614
+ }
1615
+
1616
+ def _fake_make_request(*, s, loaders, r_type, url, payload, time_out=None):
1617
+ captured["r_type"] = r_type
1618
+ captured["url"] = url
1619
+ captured["payload"] = payload
1620
+ captured["timeout"] = time_out
1621
+ return FakeResponse()
1622
+
1623
+ monkeypatch.setattr(agent_models_mod, "make_request", _fake_make_request)
1624
+
1625
+ session = agent.get_or_create_session_with_handle(
1626
+ handle_unique_id="portfolio-review-q2-2026",
1627
+ name="Quarterly portfolio review",
1628
+ llm_provider="openai",
1629
+ llm_model="gpt-5.4",
1630
+ llm_thinking="",
1631
+ session_metadata={"portfolio_uid": "portfolio-123"},
1632
+ timeout=13,
1633
+ )
1634
+
1635
+ assert session.uid == session_uid
1636
+ assert session.name == "Quarterly portfolio review"
1637
+ assert captured == {
1638
+ "r_type": "POST",
1639
+ "url": (
1640
+ f"{agent_models_mod.Agent.get_object_url()}/{agent_uid}/"
1641
+ "get_or_create_session_with_handle/"
1642
+ ),
1643
+ "payload": {
1644
+ "json": {
1645
+ "handle_unique_id": "portfolio-review-q2-2026",
1646
+ "name": "Quarterly portfolio review",
1647
+ "llm_provider": "openai",
1648
+ "llm_model": "gpt-5.4",
1649
+ "llm_thinking": "",
1650
+ "session_metadata": {"portfolio_uid": "portfolio-123"},
1651
+ }
1652
+ },
1653
+ "timeout": 13,
1654
+ }
1655
+
1656
+
1558
1657
  def _class_base_names_from_source(path: pathlib.Path) -> dict[str, list[str]]:
1559
1658
  tree = ast.parse(path.read_text(encoding="utf-8"))
1560
1659
  out: dict[str, list[str]] = {}
File without changes
File without changes
File without changes