assistant-runtime-sdk 1.10.0__tar.gz → 1.12.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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: assistant_runtime_sdk
3
- Version: 1.10.0
3
+ Version: 1.12.0
4
4
  Summary: Python SDK for FAC Cloud - the Assistant Runtime AI assistant backend
5
5
  Keywords: frappe,ai,assistant,llm,mcp,anthropic,openai,streaming
6
6
  Author: Paul Clinton
@@ -53,7 +53,7 @@ Standalone Functions:
53
53
 
54
54
  """
55
55
 
56
- __version__ = "1.10.0"
56
+ __version__ = "1.12.0"
57
57
  __author__ = "Paul Clinton"
58
58
  __license__ = "AGPL-3.0"
59
59
 
@@ -384,6 +384,7 @@ class AsyncAssistantRuntimeClient(BaseAssistantRuntimeClient):
384
384
  *,
385
385
  web_search: Optional[bool] = None,
386
386
  thinking_enabled: Optional[bool] = None,
387
+ reasoning_effort: Optional[str] = None,
387
388
  ) -> AsyncGenerator[Dict[str, Any], None]:
388
389
  """Async version of AssistantRuntimeClient.stream_chat.
389
390
 
@@ -400,6 +401,7 @@ class AsyncAssistantRuntimeClient(BaseAssistantRuntimeClient):
400
401
  continue_from_message_id=continue_from_message_id,
401
402
  web_search=web_search,
402
403
  thinking_enabled=thinking_enabled,
404
+ reasoning_effort=reasoning_effort,
403
405
  )
404
406
  url = self._build_endpoint_url("streaming.stream_chat")
405
407
  payload = self._with_site_url(payload)
@@ -606,11 +608,13 @@ class AsyncAssistantRuntimeClient(BaseAssistantRuntimeClient):
606
608
  user_id: Optional[str] = None,
607
609
  visibility: Optional[str] = None,
608
610
  shared_with: Optional[List[str]] = None,
611
+ project_id: Optional[str] = None,
609
612
  ) -> Optional[Dict[str, Any]]:
610
613
  """Async version of AssistantRuntimeClient.upload_document."""
611
614
  endpoint, params, f_field, f_name, f_data, c_type = self._prepare_upload_document(
612
615
  file_path, file_data, file_name, content_type,
613
616
  user_id=user_id, visibility=visibility, shared_with=shared_with,
617
+ project_id=project_id,
614
618
  )
615
619
  return await self._request_post_multipart(
616
620
  endpoint, params=params, file_field=f_field,
@@ -619,12 +623,27 @@ class AsyncAssistantRuntimeClient(BaseAssistantRuntimeClient):
619
623
  )
620
624
 
621
625
  async def list_documents(
622
- self, limit: int = 50, offset: int = 0, user_id: Optional[str] = None
626
+ self,
627
+ limit: int = 50,
628
+ offset: int = 0,
629
+ user_id: Optional[str] = None,
630
+ project_id: Optional[str] = None,
631
+ include_project_docs: bool = False,
623
632
  ) -> Optional[Dict[str, Any]]:
624
633
  """Async version of AssistantRuntimeClient.list_documents."""
625
- endpoint, params = self._prepare_list_documents(limit, offset, user_id=user_id)
634
+ endpoint, params = self._prepare_list_documents(
635
+ limit, offset, user_id=user_id,
636
+ project_id=project_id, include_project_docs=include_project_docs,
637
+ )
626
638
  return await self._request_get(endpoint, params, api_base=self.memory_api_base)
627
639
 
640
+ async def unlink_project_documents(
641
+ self, user_id: str, project_id: str
642
+ ) -> Optional[Dict[str, Any]]:
643
+ """Async version of AssistantRuntimeClient.unlink_project_documents."""
644
+ endpoint, payload = self._prepare_unlink_project_documents(user_id, project_id)
645
+ return await self._request_post_json(endpoint, payload, api_base=self.memory_api_base)
646
+
628
647
  async def get_document(self, document_id: str) -> Optional[Dict[str, Any]]:
629
648
  """Async version of AssistantRuntimeClient.get_document."""
630
649
  endpoint, params = self._prepare_get_document(document_id)
@@ -316,6 +316,7 @@ class BaseAssistantRuntimeClient:
316
316
  continue_from_message_id: Optional[str] = None,
317
317
  web_search: Optional[bool] = None,
318
318
  thinking_enabled: Optional[bool] = None,
319
+ reasoning_effort: Optional[str] = None,
319
320
  ) -> Dict[str, Any]:
320
321
  """
321
322
  Prepare JSON payload for stream_chat POST request.
@@ -347,6 +348,8 @@ class BaseAssistantRuntimeClient:
347
348
  previous truncated response from
348
349
  web_search: Optional explicit web-search toggle for this turn
349
350
  thinking_enabled: Optional explicit extended-thinking toggle for this turn
351
+ reasoning_effort: Optional thinking level for this turn — "off", "low", "medium",
352
+ "high", "xhigh" or "max"
350
353
 
351
354
  Returns:
352
355
  Payload dict ready for JSON body
@@ -400,6 +403,9 @@ class BaseAssistantRuntimeClient:
400
403
  if thinking_enabled is not None:
401
404
  payload["thinking_enabled"] = bool(thinking_enabled)
402
405
 
406
+ if reasoning_effort is not None:
407
+ payload["reasoning_effort"] = str(reasoning_effort).strip().lower()
408
+
403
409
  return payload
404
410
 
405
411
  def _prepare_resource_params(
@@ -603,11 +609,14 @@ class BaseAssistantRuntimeClient:
603
609
  user_id: Optional[str] = None,
604
610
  visibility: Optional[str] = None,
605
611
  shared_with: Optional[List[str]] = None,
612
+ project_id: Optional[str] = None,
606
613
  ) -> tuple:
607
614
  """Returns (endpoint, params, file_field, file_name, file_data, content_type)."""
608
615
  import mimetypes as _mt
609
616
  import os as _os
610
617
 
618
+ if project_id and not user_id:
619
+ raise ARConfigurationError("user_id is required with project_id")
611
620
  if file_path and file_data:
612
621
  raise ARConfigurationError("Provide either file_path or file_data, not both")
613
622
  if not file_path and not file_data:
@@ -619,7 +628,7 @@ class BaseAssistantRuntimeClient:
619
628
  raise ARConfigurationError(
620
629
  f"Invalid visibility: {visibility}. Must be public, private, or shared."
621
630
  )
622
- if visibility == "shared" and not shared_with:
631
+ if not project_id and visibility == "shared" and not shared_with:
623
632
  raise ARConfigurationError(
624
633
  "shared_with is required when visibility is 'shared'"
625
634
  )
@@ -639,10 +648,15 @@ class BaseAssistantRuntimeClient:
639
648
  params: Dict[str, Any] = {"tenant_id": self.tenant_id}
640
649
  if user_id:
641
650
  params["user_id"] = user_id
642
- if visibility:
643
- params["visibility"] = visibility
644
- if shared_with:
645
- params["shared_with"] = json.dumps(shared_with)
651
+ if project_id:
652
+ # The server forces project documents to private, so no visibility
653
+ # or sharing is sent alongside a project_id.
654
+ params["project_id"] = project_id
655
+ else:
656
+ if visibility:
657
+ params["visibility"] = visibility
658
+ if shared_with:
659
+ params["shared_with"] = json.dumps(shared_with)
646
660
 
647
661
  return (
648
662
  "documents.upload_document",
@@ -654,8 +668,15 @@ class BaseAssistantRuntimeClient:
654
668
  )
655
669
 
656
670
  def _prepare_list_documents(
657
- self, limit: int = 50, offset: int = 0, user_id: Optional[str] = None
671
+ self,
672
+ limit: int = 50,
673
+ offset: int = 0,
674
+ user_id: Optional[str] = None,
675
+ project_id: Optional[str] = None,
676
+ include_project_docs: bool = False,
658
677
  ) -> tuple:
678
+ if project_id and not user_id:
679
+ raise ARConfigurationError("user_id is required with project_id")
659
680
  params: Dict[str, Any] = {
660
681
  "tenant_id": self.tenant_id,
661
682
  "limit": str(limit),
@@ -663,8 +684,20 @@ class BaseAssistantRuntimeClient:
663
684
  }
664
685
  if user_id:
665
686
  params["user_id"] = user_id
687
+ if project_id:
688
+ params["project_id"] = project_id
689
+ if include_project_docs:
690
+ params["include_project_docs"] = "1"
666
691
  return "documents.list_documents", params
667
692
 
693
+ def _prepare_unlink_project_documents(self, user_id: str, project_id: str) -> tuple:
694
+ """Returns (endpoint, payload) for unlinking a project's documents."""
695
+ return "documents.unlink_project_documents", {
696
+ "tenant_id": self.tenant_id,
697
+ "user_id": user_id,
698
+ "project_id": project_id,
699
+ }
700
+
668
701
  def _prepare_get_document(self, document_id: str) -> tuple:
669
702
  return "documents.get_document", {
670
703
  "tenant_id": self.tenant_id,
@@ -329,6 +329,7 @@ class AssistantRuntimeClient(BaseAssistantRuntimeClient):
329
329
  *,
330
330
  web_search: Optional[bool] = None,
331
331
  thinking_enabled: Optional[bool] = None,
332
+ reasoning_effort: Optional[str] = None,
332
333
  ) -> Generator[Dict[str, Any], None, None]:
333
334
  """
334
335
  Stream chat response from Assistant Runtime.
@@ -361,6 +362,9 @@ class AssistantRuntimeClient(BaseAssistantRuntimeClient):
361
362
  truncated response from
362
363
  web_search: Optional explicit web-search toggle for this turn
363
364
  thinking_enabled: Optional explicit extended-thinking toggle for this turn
365
+ reasoning_effort: Optional thinking level for this turn — "off", "low", "medium",
366
+ "high", "xhigh" or "max". Servers that predate it ignore it, so callers
367
+ should also send thinking_enabled.
364
368
 
365
369
  Yields:
366
370
  Parsed SSE events with structure:
@@ -390,6 +394,7 @@ class AssistantRuntimeClient(BaseAssistantRuntimeClient):
390
394
  continue_from_message_id=continue_from_message_id,
391
395
  web_search=web_search,
392
396
  thinking_enabled=thinking_enabled,
397
+ reasoning_effort=reasoning_effort,
393
398
  )
394
399
  url = self._build_endpoint_url("streaming.stream_chat")
395
400
  payload = self._with_site_url(payload)
@@ -677,6 +682,7 @@ class AssistantRuntimeClient(BaseAssistantRuntimeClient):
677
682
  user_id: Optional[str] = None,
678
683
  visibility: Optional[str] = None,
679
684
  shared_with: Optional[List[str]] = None,
685
+ project_id: Optional[str] = None,
680
686
  ) -> Optional[Dict[str, Any]]:
681
687
  """
682
688
  Upload a document for RAG processing.
@@ -694,6 +700,9 @@ class AssistantRuntimeClient(BaseAssistantRuntimeClient):
694
700
  tenant configuration if omitted.
695
701
  shared_with: List of user IDs to share with. Required when
696
702
  visibility is "shared".
703
+ project_id: Attach the document to a project. Project documents are
704
+ always private to the uploader, so visibility and shared_with
705
+ are not sent.
697
706
 
698
707
  Returns:
699
708
  {"status": "queued", "document_id": str, "file_name": str,
@@ -702,6 +711,7 @@ class AssistantRuntimeClient(BaseAssistantRuntimeClient):
702
711
  endpoint, params, f_field, f_name, f_data, c_type = self._prepare_upload_document(
703
712
  file_path, file_data, file_name, content_type,
704
713
  user_id=user_id, visibility=visibility, shared_with=shared_with,
714
+ project_id=project_id,
705
715
  )
706
716
  return self._request_post_multipart(
707
717
  endpoint, params=params, file_field=f_field,
@@ -710,7 +720,12 @@ class AssistantRuntimeClient(BaseAssistantRuntimeClient):
710
720
  )
711
721
 
712
722
  def list_documents(
713
- self, limit: int = 50, offset: int = 0, user_id: Optional[str] = None
723
+ self,
724
+ limit: int = 50,
725
+ offset: int = 0,
726
+ user_id: Optional[str] = None,
727
+ project_id: Optional[str] = None,
728
+ include_project_docs: bool = False,
714
729
  ) -> Optional[Dict[str, Any]]:
715
730
  """
716
731
  List RAG documents for this tenant.
@@ -723,13 +738,38 @@ class AssistantRuntimeClient(BaseAssistantRuntimeClient):
723
738
  limit: Maximum number of documents to return (default 50).
724
739
  offset: Pagination offset (default 0).
725
740
  user_id: User performing the query. Enables visibility filtering.
741
+ project_id: Only list documents attached to this project.
742
+ include_project_docs: Also include documents attached to projects.
726
743
 
727
744
  Returns:
728
745
  {"documents": [...], "pagination": {...}, "storage": {...}}
729
746
  """
730
- endpoint, params = self._prepare_list_documents(limit, offset, user_id=user_id)
747
+ endpoint, params = self._prepare_list_documents(
748
+ limit, offset, user_id=user_id,
749
+ project_id=project_id, include_project_docs=include_project_docs,
750
+ )
731
751
  return self._request_get(endpoint, params, api_base=self.memory_api_base)
732
752
 
753
+ def unlink_project_documents(
754
+ self, user_id: str, project_id: str
755
+ ) -> Optional[Dict[str, Any]]:
756
+ """
757
+ Unlink a project's documents from the project.
758
+
759
+ Documents attached to a project are removed from that project only;
760
+ the documents themselves are kept.
761
+
762
+ Args:
763
+ user_id: User performing the unlink.
764
+ project_id: The project whose documents should be unlinked.
765
+
766
+ Returns:
767
+ ``{"status": "unlinked", "count": int}``, where count is the number of
768
+ documents released from the project.
769
+ """
770
+ endpoint, payload = self._prepare_unlink_project_documents(user_id, project_id)
771
+ return self._request_post_json(endpoint, payload, api_base=self.memory_api_base)
772
+
733
773
  def get_document(self, document_id: str) -> Optional[Dict[str, Any]]:
734
774
  """
735
775
  Get detailed information about a specific RAG document.
@@ -16,7 +16,15 @@ from typing import TypedDict, List, Optional, Any
16
16
  # =============================================================================
17
17
 
18
18
 
19
- class ModelInfo(TypedDict):
19
+ class _ModelInfoOptional(TypedDict, total=False):
20
+ """Keys newer runtimes add to each model; absent on older ones."""
21
+
22
+ thinking_effective: bool
23
+ reasoning_levels: List[str]
24
+ reasoning_off_floor: bool
25
+
26
+
27
+ class ModelInfo(_ModelInfoOptional):
20
28
  """Information about an available AI model."""
21
29
 
22
30
  model_id: str
@@ -104,7 +112,7 @@ class RoutingReceiptData(TypedDict):
104
112
  shortlist_size: int
105
113
  pick_reason: str
106
114
  notices: List[str]
107
- thinking: dict # requested, applied, effort, not_applied_reason
115
+ thinking: dict # requested, applied, effort {requested, applied}, effective_budget, not_applied_reason
108
116
  credits: dict # actual
109
117
  cycles: int
110
118
  also_ran: List[str]
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "assistant_runtime_sdk"
3
- version = "1.10.0"
3
+ version = "1.12.0"
4
4
  description = "Python SDK for FAC Cloud - the Assistant Runtime AI assistant backend"
5
5
  readme = "README.md"
6
6
  license = {text = "AGPL-3.0"}