gohumanloop 0.0.2__tar.gz → 0.0.3__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 (35) hide show
  1. {gohumanloop-0.0.2 → gohumanloop-0.0.3}/PKG-INFO +1 -1
  2. {gohumanloop-0.0.2 → gohumanloop-0.0.3}/gohumanloop/adapters/langgraph_adapter.py +39 -41
  3. {gohumanloop-0.0.2 → gohumanloop-0.0.3}/gohumanloop/core/interface.py +342 -21
  4. {gohumanloop-0.0.2 → gohumanloop-0.0.3}/gohumanloop/core/manager.py +302 -39
  5. {gohumanloop-0.0.2 → gohumanloop-0.0.3}/gohumanloop/manager/ghl_manager.py +22 -22
  6. {gohumanloop-0.0.2 → gohumanloop-0.0.3}/gohumanloop/providers/api_provider.py +18 -18
  7. {gohumanloop-0.0.2 → gohumanloop-0.0.3}/gohumanloop/providers/base.py +239 -9
  8. {gohumanloop-0.0.2 → gohumanloop-0.0.3}/gohumanloop/providers/email_provider.py +15 -15
  9. {gohumanloop-0.0.2 → gohumanloop-0.0.3}/gohumanloop/providers/terminal_provider.py +12 -13
  10. {gohumanloop-0.0.2 → gohumanloop-0.0.3}/gohumanloop/utils/utils.py +30 -3
  11. {gohumanloop-0.0.2 → gohumanloop-0.0.3}/gohumanloop.egg-info/PKG-INFO +1 -1
  12. {gohumanloop-0.0.2 → gohumanloop-0.0.3}/pyproject.toml +1 -1
  13. {gohumanloop-0.0.2 → gohumanloop-0.0.3}/LICENSE +0 -0
  14. {gohumanloop-0.0.2 → gohumanloop-0.0.3}/README.md +0 -0
  15. {gohumanloop-0.0.2 → gohumanloop-0.0.3}/gohumanloop/__init__.py +0 -0
  16. {gohumanloop-0.0.2 → gohumanloop-0.0.3}/gohumanloop/__main__.py +0 -0
  17. {gohumanloop-0.0.2 → gohumanloop-0.0.3}/gohumanloop/adapters/__init__.py +0 -0
  18. {gohumanloop-0.0.2 → gohumanloop-0.0.3}/gohumanloop/cli/__init__.py +0 -0
  19. {gohumanloop-0.0.2 → gohumanloop-0.0.3}/gohumanloop/cli/main.py +0 -0
  20. {gohumanloop-0.0.2 → gohumanloop-0.0.3}/gohumanloop/core/__init__.py +0 -0
  21. {gohumanloop-0.0.2 → gohumanloop-0.0.3}/gohumanloop/manager/__init__.py +0 -0
  22. {gohumanloop-0.0.2 → gohumanloop-0.0.3}/gohumanloop/models/__init__.py +0 -0
  23. {gohumanloop-0.0.2 → gohumanloop-0.0.3}/gohumanloop/models/api_model.py +0 -0
  24. {gohumanloop-0.0.2 → gohumanloop-0.0.3}/gohumanloop/models/glh_model.py +0 -0
  25. {gohumanloop-0.0.2 → gohumanloop-0.0.3}/gohumanloop/providers/__init__.py +0 -0
  26. {gohumanloop-0.0.2 → gohumanloop-0.0.3}/gohumanloop/providers/ghl_provider.py +0 -0
  27. {gohumanloop-0.0.2 → gohumanloop-0.0.3}/gohumanloop/utils/__init__.py +0 -0
  28. {gohumanloop-0.0.2 → gohumanloop-0.0.3}/gohumanloop/utils/context_formatter.py +0 -0
  29. {gohumanloop-0.0.2 → gohumanloop-0.0.3}/gohumanloop/utils/threadsafedict.py +0 -0
  30. {gohumanloop-0.0.2 → gohumanloop-0.0.3}/gohumanloop.egg-info/SOURCES.txt +0 -0
  31. {gohumanloop-0.0.2 → gohumanloop-0.0.3}/gohumanloop.egg-info/dependency_links.txt +0 -0
  32. {gohumanloop-0.0.2 → gohumanloop-0.0.3}/gohumanloop.egg-info/entry_points.txt +0 -0
  33. {gohumanloop-0.0.2 → gohumanloop-0.0.3}/gohumanloop.egg-info/requires.txt +0 -0
  34. {gohumanloop-0.0.2 → gohumanloop-0.0.3}/gohumanloop.egg-info/top_level.txt +0 -0
  35. {gohumanloop-0.0.2 → gohumanloop-0.0.3}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: gohumanloop
3
- Version: 0.0.2
3
+ Version: 0.0.3
4
4
  Summary: Perfecting AI workflows with human intelligence
5
5
  Author-email: gohumanloop authors <baird0917@163.com>
6
6
  Project-URL: repository, https://github.com/ptonlix/gohumanloop
@@ -2,6 +2,7 @@ from typing import Dict, Any, Optional, Callable, Awaitable, TypeVar, Union, Lis
2
2
  from functools import wraps
3
3
  import asyncio
4
4
  import uuid
5
+ import time
5
6
  from inspect import iscoroutinefunction
6
7
  from contextlib import asynccontextmanager, contextmanager
7
8
 
@@ -209,7 +210,7 @@ class LangGraphAdapter:
209
210
  else:
210
211
  cb = callback
211
212
 
212
- result = await self.manager.request_humanloop(
213
+ result = await self.manager.async_request_humanloop(
213
214
  task_id=task_id,
214
215
  conversation_id=conversation_id,
215
216
  loop_type=HumanLoopType.APPROVAL,
@@ -374,12 +375,12 @@ class LangGraphAdapter:
374
375
  question_content = f"Please respond to the following information:\n{node_input}"
375
376
 
376
377
  # Check if conversation exists to determine whether to use request_humanloop or continue_humanloop
377
- conversation_requests = await self.manager.check_conversation_exist(task_id, conversation_id)
378
+ conversation_requests = await self.manager.async_check_conversation_exist(task_id, conversation_id)
378
379
 
379
380
  result = None
380
381
  if conversation_requests:
381
382
  # Existing conversation, use continue_humanloop
382
- result = await self.manager.continue_humanloop(
383
+ result = await self.manager.async_continue_humanloop(
383
384
  conversation_id=conversation_id,
384
385
  context={
385
386
  "message": {
@@ -400,7 +401,7 @@ class LangGraphAdapter:
400
401
  )
401
402
  else:
402
403
  # New conversation, use request_humanloop
403
- result = await self.manager.request_humanloop(
404
+ result = await self.manager.async_request_humanloop(
404
405
  task_id=task_id,
405
406
  conversation_id=conversation_id,
406
407
  loop_type=HumanLoopType.CONVERSATION,
@@ -543,7 +544,7 @@ class LangGraphAdapter:
543
544
  else:
544
545
  cb = callback
545
546
 
546
- result = await self.manager.request_humanloop(
547
+ result = await self.manager.async_request_humanloop(
547
548
  task_id=task_id,
548
549
  conversation_id=conversation_id,
549
550
  loop_type=HumanLoopType.INFORMATION,
@@ -608,37 +609,37 @@ class LangGraphHumanLoopCallback(HumanLoopCallback):
608
609
  def __init__(
609
610
  self,
610
611
  state: Any,
611
- on_update: Optional[Callable[[Any, HumanLoopProvider, HumanLoopResult], Awaitable[None]]] = None,
612
- on_timeout: Optional[Callable[[Any, HumanLoopProvider], Awaitable[None]]] = None,
613
- on_error: Optional[Callable[[Any, HumanLoopProvider, Exception], Awaitable[None]]] = None
612
+ async_on_update: Optional[Callable[[Any, HumanLoopProvider, HumanLoopResult], Awaitable[None]]] = None,
613
+ async_on_timeout: Optional[Callable[[Any, HumanLoopProvider], Awaitable[None]]] = None,
614
+ async_on_error: Optional[Callable[[Any, HumanLoopProvider, Exception], Awaitable[None]]] = None,
614
615
  ):
615
616
  self.state = state
616
- self.on_update = on_update
617
- self.on_timeout = on_timeout
618
- self.on_error = on_error
617
+ self.async_on_update = async_on_update
618
+ self.async_on_timeout = async_on_timeout
619
+ self.async_on_error = async_on_error
619
620
 
620
- async def on_humanloop_update(
621
+ async def async_on_humanloop_update(
621
622
  self,
622
623
  provider: HumanLoopProvider,
623
624
  result: HumanLoopResult
624
625
  ):
625
- if self.on_update:
626
- await self.on_update(self.state, provider, result)
626
+ if self.async_on_update:
627
+ await self.async_on_update(self.state, provider, result)
627
628
 
628
- async def on_humanloop_timeout(
629
+ async def async_on_humanloop_timeout(
629
630
  self,
630
631
  provider: HumanLoopProvider,
631
632
  ):
632
- if self.on_timeout:
633
- await self.on_timeout(self.state, provider)
633
+ if self.async_on_timeout:
634
+ await self.async_on_timeout(self.state, provider)
634
635
 
635
- async def on_humanloop_error(
636
+ async def async_humanloop_on_error(
636
637
  self,
637
638
  provider: HumanLoopProvider,
638
639
  error: Exception
639
640
  ):
640
- if self.on_error:
641
- await self.on_error(self.state, provider, error)
641
+ if self.async_on_error:
642
+ await self.async_on_error(self.state, provider, error)
642
643
 
643
644
 
644
645
  def default_langgraph_callback_factory(state: Any) -> LangGraphHumanLoopCallback:
@@ -661,7 +662,7 @@ def default_langgraph_callback_factory(state: Any) -> LangGraphHumanLoopCallback
661
662
 
662
663
  logger = logging.getLogger("gohumanloop.langgraph")
663
664
 
664
- async def on_update(state, provider: HumanLoopProvider, result: HumanLoopResult):
665
+ async def async_on_update(state, provider: HumanLoopProvider, result: HumanLoopResult):
665
666
  """Log human interaction update events"""
666
667
  logger.info(f"Provider ID: {provider.name}")
667
668
  logger.info(
@@ -673,8 +674,9 @@ def default_langgraph_callback_factory(state: Any) -> LangGraphHumanLoopCallback
673
674
  f"feedback={result.feedback}"
674
675
  )
675
676
 
677
+
676
678
 
677
- async def on_timeout(state, provider: HumanLoopProvider):
679
+ async def async_on_timeout(state, provider: HumanLoopProvider):
678
680
  """Log human interaction timeout events"""
679
681
 
680
682
  logger.info(f"Provider ID: {provider.name}")
@@ -685,7 +687,7 @@ def default_langgraph_callback_factory(state: Any) -> LangGraphHumanLoopCallback
685
687
 
686
688
  # Alert logic can be added here, such as sending notifications
687
689
 
688
- async def on_error(state, provider: HumanLoopProvider, error: Exception):
690
+ async def async_on_error(state, provider: HumanLoopProvider, error: Exception):
689
691
  """Log human interaction error events"""
690
692
 
691
693
  logger.info(f"Provider ID: {provider.name}")
@@ -695,9 +697,9 @@ def default_langgraph_callback_factory(state: Any) -> LangGraphHumanLoopCallback
695
697
 
696
698
  return LangGraphHumanLoopCallback(
697
699
  state=state,
698
- on_update=on_update,
699
- on_timeout=on_timeout,
700
- on_error=on_error
700
+ async_on_update=async_on_update,
701
+ async_on_timeout=async_on_timeout,
702
+ async_on_error=async_on_error
701
703
  )
702
704
 
703
705
  from gohumanloop.core.manager import DefaultHumanLoopManager
@@ -731,14 +733,7 @@ def interrupt(value: Any, lg_humanloop: LangGraphAdapter = default_adapter) -> A
731
733
  )
732
734
 
733
735
  # Get current event loop or create new one
734
- try:
735
- loop = asyncio.get_event_loop()
736
- except RuntimeError:
737
- # If no event loop exists, create a new one
738
- loop = asyncio.new_event_loop()
739
- asyncio.set_event_loop(loop)
740
-
741
- loop.create_task(lg_humanloop.manager.request_humanloop(
736
+ lg_humanloop.manager.request_humanloop(
742
737
  task_id="lg_interrupt",
743
738
  conversation_id=default_conversation_id,
744
739
  loop_type=HumanLoopType.INFORMATION,
@@ -747,8 +742,8 @@ def interrupt(value: Any, lg_humanloop: LangGraphAdapter = default_adapter) -> A
747
742
  "question": "The execution has been interrupted. Please review the above information and provide your input to continue.",
748
743
  },
749
744
  blocking=False,
750
- ))
751
-
745
+ )
746
+
752
747
  # Return LangGraph's interrupt
753
748
  return _lg_interrupt(value)
754
749
  def create_resume_command(lg_humanloop: LangGraphAdapter = default_adapter) -> Any:
@@ -770,18 +765,21 @@ def create_resume_command(lg_humanloop: LangGraphAdapter = default_adapter) -> A
770
765
  )
771
766
 
772
767
  # Define async polling function
773
- async def poll_for_result():
768
+ def poll_for_result():
774
769
  poll_interval = 1.0 # Polling interval (seconds)
775
770
  while True:
776
- result = await lg_humanloop.manager.check_conversation_status(default_conversation_id)
771
+ result = lg_humanloop.manager.check_conversation_status(default_conversation_id)
772
+ print(result)
777
773
  # If status is final state (not PENDING), return result
778
774
  if result.status != HumanLoopStatus.PENDING:
779
775
  return result.response
780
776
  # Wait before polling again
781
- await asyncio.sleep(poll_interval)
777
+ time.sleep(poll_interval)
782
778
 
783
779
  # Wait for async result synchronously
784
- response = run_async_safely(poll_for_result())
780
+ # loop = asyncio.get_event_loop() # In synchronous environment
781
+
782
+ response = poll_for_result()
785
783
  return _lg_Command(resume=response)
786
784
 
787
785
  async def acreate_resume_command(lg_humanloop: LangGraphAdapter = default_adapter) -> Any:
@@ -806,7 +804,7 @@ async def acreate_resume_command(lg_humanloop: LangGraphAdapter = default_adapte
806
804
  async def poll_for_result():
807
805
  poll_interval = 1.0 # Polling interval (seconds)
808
806
  while True:
809
- result = await lg_humanloop.manager.check_conversation_status(default_conversation_id)
807
+ result = await lg_humanloop.manager.async_check_conversation_status(default_conversation_id)
810
808
  # If status is final state (not PENDING), return result
811
809
  if result.status != HumanLoopStatus.PENDING:
812
810
  return result.response