gohumanloop 0.0.8__py3-none-any.whl → 0.0.10__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.
@@ -434,11 +434,17 @@ class HumanloopAdapter:
434
434
  else:
435
435
  cb = callback
436
436
 
437
- node_input = None
438
- if state:
439
- # Get input information from key fields in State
437
+ # First try to get node_input from kwargs using state_key
438
+ node_input = kwargs.get(state_key)
439
+
440
+ # If not found in kwargs, try to get from first argument (state)
441
+ if node_input is None and state and isinstance(state, dict):
440
442
  node_input = state.get(state_key, {})
441
443
 
444
+ # If still not found, use empty dict as default
445
+ if node_input is None:
446
+ node_input = {}
447
+
442
448
  # Compose question content
443
449
  question_content = (
444
450
  f"Please respond to the following information:\n{node_input}"
@@ -725,7 +731,7 @@ class AgentOpsHumanLoopCallback(HumanLoopCallback):
725
731
  self._operation = operation
726
732
  agentops.init(tags=self.session_tags)
727
733
  else:
728
- logger.debug(
734
+ raise ImportError(
729
735
  "AgentOps package not installed. Features disabled. "
730
736
  "Please install with: pip install agentops"
731
737
  )
@@ -170,12 +170,6 @@ class DefaultHumanLoopManager(HumanLoopManager):
170
170
  pass
171
171
  self._callbacks[(conversation_id, request_id)] = callback
172
172
 
173
- # 如果设置了超时,创建超时任务
174
- if timeout:
175
- await self._async_create_timeout_task(
176
- conversation_id, request_id, timeout, provider, callback
177
- )
178
-
179
173
  # 如果是阻塞模式,等待结果
180
174
  if blocking:
181
175
  return await self._async_wait_for_result(
@@ -308,12 +302,6 @@ class DefaultHumanLoopManager(HumanLoopManager):
308
302
  pass
309
303
  self._callbacks[(conversation_id, request_id)] = callback
310
304
 
311
- # 如果设置了超时,创建超时任务
312
- if timeout:
313
- await self._async_create_timeout_task(
314
- conversation_id, request_id, timeout, provider, callback
315
- )
316
-
317
305
  # 如果是阻塞模式,等待结果
318
306
  if blocking:
319
307
  return await self._async_wait_for_result(
@@ -429,22 +417,31 @@ class DefaultHumanLoopManager(HumanLoopManager):
429
417
 
430
418
  try:
431
419
  # 检查对话指定provider_id或默认provider_id最后一次请求的状态
432
- return await provider.async_check_conversation_status(conversation_id)
433
- except Exception as e:
434
- # 处理检查对话状态过程中的异常
435
- # 尝试找到与此对话关联的最后一个请求的回调
420
+ result = await provider.async_check_conversation_status(conversation_id)
421
+
436
422
  if (
437
423
  conversation_id in self._conversation_requests
438
424
  and self._conversation_requests[conversation_id]
439
425
  ):
440
426
  last_request_id = self._conversation_requests[conversation_id][-1]
441
427
  callback = self._callbacks.get((conversation_id, last_request_id))
442
- if callback:
443
- try:
444
- await callback.async_on_humanloop_error(provider, e)
445
- except Exception:
446
- # 如果错误回调也失败,只能忽略
447
- pass
428
+
429
+ if callback and result.status not in [HumanLoopStatus.PENDING]:
430
+ # 如果有回调且状态不是等待或进行中,触发状态更新回调
431
+ await self._async_trigger_update_callback(
432
+ conversation_id, last_request_id, provider, result
433
+ )
434
+
435
+ return result
436
+ except Exception as e:
437
+ # 处理检查对话状态过程中的异常
438
+ # 尝试找到与此对话关联的最后一个请求的回调
439
+ if callback:
440
+ try:
441
+ await callback.async_on_humanloop_error(provider, e)
442
+ except Exception:
443
+ # 如果错误回调也失败,只能忽略
444
+ pass
448
445
  raise # 重新抛出异常,让调用者知道发生了错误
449
446
 
450
447
  def check_conversation_status(
@@ -632,42 +629,6 @@ class DefaultHumanLoopManager(HumanLoopManager):
632
629
 
633
630
  return result
634
631
 
635
- async def _async_create_timeout_task(
636
- self,
637
- conversation_id: str,
638
- request_id: str,
639
- timeout: int,
640
- provider: HumanLoopProvider,
641
- callback: Optional[HumanLoopCallback],
642
- ) -> None:
643
- """创建超时任务"""
644
-
645
- async def timeout_task() -> None:
646
- await asyncio.sleep(timeout)
647
- # 检查当前状态
648
- result = await self.async_check_request_status(
649
- conversation_id, request_id, provider.name
650
- )
651
-
652
- # 只有当状态为PENDING时才触发超时回调
653
- # INPROGRESS状态表示对话正在进行中,不应视为超时
654
- if result.status == HumanLoopStatus.PENDING:
655
- if callback:
656
- await callback.async_on_humanloop_timeout(
657
- provider=provider, result=result
658
- )
659
- # 如果状态是INPROGRESS,重置超时任务
660
- elif result.status == HumanLoopStatus.INPROGRESS:
661
- # 对于进行中的对话,我们可以选择延长超时时间
662
- # 这里我们简单地重新创建一个超时任务,使用相同的超时时间
663
- if (conversation_id, request_id) in self._timeout_tasks:
664
- self._timeout_tasks[(conversation_id, request_id)].cancel()
665
- new_task = asyncio.create_task(timeout_task())
666
- self._timeout_tasks[(conversation_id, request_id)] = new_task
667
-
668
- task = asyncio.create_task(timeout_task())
669
- self._timeout_tasks[(conversation_id, request_id)] = task
670
-
671
632
  async def _async_wait_for_result(
672
633
  self,
673
634
  conversation_id: str,
@@ -704,6 +665,8 @@ class DefaultHumanLoopManager(HumanLoopManager):
704
665
  if callback:
705
666
  try:
706
667
  await callback.async_on_humanloop_update(provider, result)
668
+ if result.status == HumanLoopStatus.EXPIRED:
669
+ await callback.async_on_humanloop_timeout(provider, result)
707
670
  # 如果状态是最终状态,可以考虑移除回调
708
671
  if result.status not in [
709
672
  HumanLoopStatus.PENDING,
@@ -267,14 +267,9 @@ class APIProvider(BaseProvider):
267
267
  conversation_id,
268
268
  request_id,
269
269
  platform,
270
+ timeout,
270
271
  )
271
272
 
272
- # Create timeout task if timeout is set
273
- if timeout:
274
- await self._async_create_timeout_task(
275
- conversation_id, request_id, timeout
276
- )
277
-
278
273
  return HumanLoopResult(
279
274
  conversation_id=conversation_id,
280
275
  request_id=request_id,
@@ -296,7 +291,11 @@ class APIProvider(BaseProvider):
296
291
  )
297
292
 
298
293
  def _run_async_poll_request_status(
299
- self, conversation_id: str, request_id: str, platform: str
294
+ self,
295
+ conversation_id: str,
296
+ request_id: str,
297
+ platform: str,
298
+ timeout: Optional[int],
300
299
  ) -> None:
301
300
  """Run asynchronous API interaction in a separate thread"""
302
301
  # Create new event loop
@@ -306,7 +305,9 @@ class APIProvider(BaseProvider):
306
305
  try:
307
306
  # Run interaction processing in the new event loop
308
307
  loop.run_until_complete(
309
- self._async_poll_request_status(conversation_id, request_id, platform)
308
+ self._async_poll_request_status_with_timeout(
309
+ conversation_id, request_id, platform, timeout
310
+ )
310
311
  )
311
312
  finally:
312
313
  loop.close()
@@ -579,14 +580,9 @@ class APIProvider(BaseProvider):
579
580
  conversation_id,
580
581
  request_id,
581
582
  platform,
583
+ timeout,
582
584
  )
583
585
 
584
- # Create timeout task if timeout is set
585
- if timeout:
586
- await self._async_create_timeout_task(
587
- conversation_id, request_id, timeout
588
- )
589
-
590
586
  return HumanLoopResult(
591
587
  conversation_id=conversation_id,
592
588
  request_id=request_id,
@@ -606,6 +602,47 @@ class APIProvider(BaseProvider):
606
602
  error=str(e),
607
603
  )
608
604
 
605
+ async def _async_poll_request_status_with_timeout(
606
+ self,
607
+ conversation_id: str,
608
+ request_id: str,
609
+ platform: str,
610
+ timeout: Optional[int],
611
+ ) -> None:
612
+ """Poll request status with optional timeout
613
+
614
+ Args:
615
+ conversation_id: Conversation identifier
616
+ request_id: Request identifier
617
+ platform: Platform identifier
618
+ timeout: Optional timeout in seconds. If specified, polling will stop after timeout period
619
+ """
620
+
621
+ try:
622
+ if timeout:
623
+ # 使用 wait_for 设置超时
624
+ await asyncio.wait_for(
625
+ self._async_poll_request_status(
626
+ conversation_id, request_id, platform
627
+ ),
628
+ timeout=timeout,
629
+ )
630
+ else:
631
+ # 无超时限制
632
+ await self._async_poll_request_status(
633
+ conversation_id, request_id, platform
634
+ )
635
+
636
+ except asyncio.TimeoutError:
637
+ # 超时处理
638
+ request_info = self._get_request(conversation_id, request_id)
639
+ if request_info and request_info.get("status") == HumanLoopStatus.PENDING:
640
+ request_info["status"] = HumanLoopStatus.EXPIRED
641
+ request_info["error"] = "Request timed out"
642
+ logger.info(
643
+ f"\nRequest {request_id} has timed out after {timeout} seconds"
644
+ )
645
+
609
646
  async def _async_poll_request_status(
610
647
  self, conversation_id: str, request_id: str, platform: str
611
648
  ) -> None:
@@ -1,6 +1,5 @@
1
1
  from abc import ABC
2
2
  from typing import Dict, Any, Optional, List, Tuple
3
- import asyncio
4
3
  import json
5
4
  import uuid
6
5
  from datetime import datetime
@@ -33,8 +32,6 @@ class BaseProvider(HumanLoopProvider, ABC):
33
32
  self._conversations: Dict[str, Dict[str, Any]] = {}
34
33
  # For quick lookup of requests in conversations
35
34
  self._conversation_requests: defaultdict[str, List[str]] = defaultdict(list)
36
- # Store timeout tasks
37
- self._timeout_tasks: Dict[Tuple[str, str], asyncio.Task] = {}
38
35
 
39
36
  self.prompt_template = self.config.get("prompt_template", "{context}")
40
37
 
@@ -291,11 +288,6 @@ class BaseProvider(HumanLoopProvider, ABC):
291
288
  bool: Whether cancellation was successful, True indicates success, False indicates failure
292
289
  """
293
290
 
294
- # Cancel timeout task
295
- if (conversation_id, request_id) in self._timeout_tasks:
296
- self._timeout_tasks[(conversation_id, request_id)].cancel()
297
- del self._timeout_tasks[(conversation_id, request_id)]
298
-
299
291
  request_key = (conversation_id, request_id)
300
292
  if request_key in self._requests:
301
293
  # Update request status to cancelled
@@ -346,11 +338,6 @@ class BaseProvider(HumanLoopProvider, ABC):
346
338
  HumanLoopStatus.INPROGRESS,
347
339
  ]:
348
340
  self._requests[request_key]["status"] = HumanLoopStatus.CANCELLED
349
-
350
- # Cancel the timeout task for this request
351
- if request_key in self._timeout_tasks:
352
- self._timeout_tasks[request_key].cancel()
353
- del self._timeout_tasks[request_key]
354
341
  else:
355
342
  success = False
356
343
 
@@ -482,45 +469,6 @@ class BaseProvider(HumanLoopProvider, ABC):
482
469
 
483
470
  return result
484
471
 
485
- async def _async_create_timeout_task(
486
- self, conversation_id: str, request_id: str, timeout: int
487
- ) -> None:
488
- """Create timeout task
489
-
490
- Args:
491
- conversation_id: Conversation ID
492
- request_id: Request ID
493
- timeout: Timeout duration in seconds
494
- """
495
-
496
- async def timeout_task() -> None:
497
- await asyncio.sleep(timeout)
498
-
499
- # Check current status
500
- request_info = self._get_request(conversation_id, request_id)
501
- if not request_info:
502
- return
503
-
504
- current_status = request_info.get("status", HumanLoopStatus.PENDING)
505
-
506
- # Only trigger timeout when status is PENDING
507
- # INPROGRESS status means conversation is ongoing, should not be considered as timeout
508
- if current_status == HumanLoopStatus.PENDING:
509
- # Update request status to expired
510
- request_info["status"] = HumanLoopStatus.EXPIRED
511
- request_info["error"] = "Request timed out"
512
- # If status is INPROGRESS, reset timeout task
513
- elif current_status == HumanLoopStatus.INPROGRESS:
514
- # For ongoing conversations, we can choose to extend the timeout
515
- # Here we simply create a new timeout task with the same timeout duration
516
- if (conversation_id, request_id) in self._timeout_tasks:
517
- self._timeout_tasks[(conversation_id, request_id)].cancel()
518
- new_task = asyncio.create_task(timeout_task())
519
- self._timeout_tasks[(conversation_id, request_id)] = new_task
520
-
521
- task = asyncio.create_task(timeout_task())
522
- self._timeout_tasks[(conversation_id, request_id)] = task
523
-
524
472
  def build_prompt(
525
473
  self,
526
474
  task_id: str,
@@ -213,6 +213,49 @@ class EmailProvider(BaseProvider):
213
213
  logger.exception(f"Unknown error occurred while sending email: {str(e)}")
214
214
  raise
215
215
 
216
+ async def _async_check_emails_with_timeout(
217
+ self,
218
+ conversation_id: str,
219
+ request_id: str,
220
+ recipient_email: str,
221
+ subject: str,
222
+ timeout: Optional[int],
223
+ ) -> None:
224
+ """Check email replies with timeout functionality
225
+
226
+ Args:
227
+ conversation_id: Conversation ID to identify a complete dialogue session
228
+ request_id: Request ID to identify a specific request
229
+ recipient_email: Recipient's email address
230
+ subject: Email subject line
231
+ timeout: Timeout duration in seconds, no timeout if None
232
+ """
233
+
234
+ try:
235
+ if timeout:
236
+ # 使用 wait_for 设置超时
237
+ await asyncio.wait_for(
238
+ self._async_check_emails(
239
+ conversation_id, request_id, recipient_email, subject
240
+ ),
241
+ timeout=timeout,
242
+ )
243
+ else:
244
+ # 无超时限制
245
+ await self._async_check_emails(
246
+ conversation_id, request_id, recipient_email, subject
247
+ )
248
+
249
+ except asyncio.TimeoutError:
250
+ # 超时处理
251
+ request_info = self._get_request(conversation_id, request_id)
252
+ if request_info and request_info.get("status") == HumanLoopStatus.PENDING:
253
+ request_info["status"] = HumanLoopStatus.EXPIRED
254
+ request_info["error"] = "Request timed out"
255
+ logger.info(
256
+ f"\nRequest {request_id} has timed out after {timeout} seconds"
257
+ )
258
+
216
259
  async def _async_check_emails(
217
260
  self, conversation_id: str, request_id: str, recipient_email: str, subject: str
218
261
  ) -> None:
@@ -488,11 +531,6 @@ class EmailProvider(BaseProvider):
488
531
  }
489
532
  )
490
533
 
491
- # 取消超时任务
492
- if request_key in self._timeout_tasks:
493
- self._timeout_tasks[request_key].cancel()
494
- del self._timeout_tasks[request_key]
495
-
496
534
  def _format_email_body(
497
535
  self, body: str, loop_type: HumanLoopType, subject: str
498
536
  ) -> Tuple[str, str]:
@@ -772,12 +810,9 @@ class EmailProvider(BaseProvider):
772
810
  request_id,
773
811
  recipient_email,
774
812
  subject,
813
+ timeout,
775
814
  )
776
815
 
777
- # 如果设置了超时,创建超时任务
778
- if timeout:
779
- await self._async_create_timeout_task(conversation_id, request_id, timeout)
780
-
781
816
  return HumanLoopResult(
782
817
  conversation_id=conversation_id,
783
818
  request_id=request_id,
@@ -786,7 +821,12 @@ class EmailProvider(BaseProvider):
786
821
  )
787
822
 
788
823
  def _run_email_check_task(
789
- self, conversation_id: str, request_id: str, recipient_email: str, subject: str
824
+ self,
825
+ conversation_id: str,
826
+ request_id: str,
827
+ recipient_email: str,
828
+ subject: str,
829
+ timeout: Optional[int],
790
830
  ) -> None:
791
831
  """Run email check task in thread
792
832
 
@@ -803,8 +843,8 @@ class EmailProvider(BaseProvider):
803
843
  try:
804
844
  # Run email check in new event loop
805
845
  loop.run_until_complete(
806
- self._async_check_emails(
807
- conversation_id, request_id, recipient_email, subject
846
+ self._async_check_emails_with_timeout(
847
+ conversation_id, request_id, recipient_email, subject, timeout
808
848
  )
809
849
  )
810
850
  except Exception as e:
@@ -987,12 +1027,9 @@ class EmailProvider(BaseProvider):
987
1027
  request_id,
988
1028
  recipient_email,
989
1029
  subject,
1030
+ timeout,
990
1031
  )
991
1032
 
992
- # 如果设置了超时,创建超时任务
993
- if timeout:
994
- await self._async_create_timeout_task(conversation_id, request_id, timeout)
995
-
996
1033
  return HumanLoopResult(
997
1034
  conversation_id=conversation_id,
998
1035
  request_id=request_id,
@@ -90,17 +90,36 @@ class TerminalProvider(BaseProvider):
90
90
  self._terminal_input_tasks[
91
91
  (conversation_id, request_id)
92
92
  ] = self._executor.submit(
93
- self._run_async_terminal_interaction, conversation_id, request_id
93
+ self._run_async_terminal_interaction, conversation_id, request_id, timeout
94
94
  )
95
95
 
96
- # Create timeout task if timeout is specified
97
- if timeout:
98
- await self._async_create_timeout_task(conversation_id, request_id, timeout)
99
-
100
96
  return result
101
97
 
98
+ async def _process_terminal_interaction_with_timeout(
99
+ self, conversation_id: str, request_id: str, timeout: Optional[int]
100
+ ) -> None:
101
+ """Process terminal interaction with timeout functionality"""
102
+ try:
103
+ if timeout:
104
+ # Set timeout using wait_for
105
+ await asyncio.wait_for(
106
+ self._process_terminal_interaction(conversation_id, request_id),
107
+ timeout=timeout,
108
+ )
109
+ else:
110
+ # No timeout limit
111
+ await self._process_terminal_interaction(conversation_id, request_id)
112
+
113
+ except asyncio.TimeoutError:
114
+ # Handle timeout
115
+ request_info = self._get_request(conversation_id, request_id)
116
+ if request_info and request_info.get("status") == HumanLoopStatus.PENDING:
117
+ request_info["status"] = HumanLoopStatus.EXPIRED
118
+ request_info["error"] = "Request timed out"
119
+ print(f"\nRequest {request_id} has timed out after {timeout} seconds")
120
+
102
121
  def _run_async_terminal_interaction(
103
- self, conversation_id: str, request_id: str
122
+ self, conversation_id: str, request_id: str, timeout: int | None
104
123
  ) -> None:
105
124
  """Run asynchronous terminal interaction in a separate thread"""
106
125
  # Create new event loop
@@ -110,7 +129,9 @@ class TerminalProvider(BaseProvider):
110
129
  try:
111
130
  # Run interaction processing in the new event loop
112
131
  loop.run_until_complete(
113
- self._process_terminal_interaction(conversation_id, request_id)
132
+ self._process_terminal_interaction_with_timeout(
133
+ conversation_id, request_id, timeout
134
+ )
114
135
  )
115
136
  finally:
116
137
  loop.close()
@@ -213,13 +234,9 @@ class TerminalProvider(BaseProvider):
213
234
  self._terminal_input_tasks[
214
235
  (conversation_id, request_id)
215
236
  ] = self._executor.submit(
216
- self._run_async_terminal_interaction, conversation_id, request_id
237
+ self._run_async_terminal_interaction, conversation_id, request_id, timeout
217
238
  )
218
239
 
219
- # Create timeout task if timeout is specified
220
- if timeout:
221
- await self._async_create_timeout_task(conversation_id, request_id, timeout)
222
-
223
240
  return result
224
241
 
225
242
  async def _process_terminal_interaction(
@@ -42,6 +42,7 @@ def run_async_safely(coro: Awaitable[Any]) -> Any:
42
42
  finally:
43
43
  if own_loop and not loop.is_closed():
44
44
  loop.close()
45
+ asyncio.set_event_loop(None)
45
46
 
46
47
 
47
48
  def get_secret_from_env(
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: gohumanloop
3
- Version: 0.0.8
3
+ Version: 0.0.10
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
@@ -33,7 +33,7 @@ Dynamic: license-file
33
33
  **GoHumanLoop**: A Python library empowering AI agents to dynamically request human input (approval/feedback/conversation) at critical stages. Core features:
34
34
 
35
35
  - `Human-in-the-loop control`: Lets AI agent systems pause and escalate decisions, enhancing safety and trust.
36
- - `Multi-channel integration`: Supports Terminal, Email, API, and frameworks like LangGraph/CrewAI (soon).
36
+ - `Multi-channel integration`: Supports Terminal, Email, API, and frameworks like LangGraph/CrewAI/...(soon)
37
37
  - `Flexible workflows`: Combines automated reasoning with human oversight for reliable AI operations.
38
38
 
39
39
  Ensures responsible AI deployment by bridging autonomous agents and human judgment.
@@ -59,9 +59,10 @@ Ensures responsible AI deployment by bridging autonomous agents and human judgme
59
59
 
60
60
  ## 🎹 Getting Started
61
61
 
62
- To get started, check out the following example or jump straight into one of the [Examples](./examples/):
62
+ To get started, check out the following example or jump straight into one of the [Examples Repo](https://github.com/ptonlix/gohumanloop-examples):
63
63
 
64
- - 🦜⛓️ [LangGraph](./examples/langgraph/)
64
+ - 🦜⛓️ [LangGraph](https://github.com/ptonlix/gohumanloop-examples/tree/main/LangGraph)
65
+ - 🚣‍ [CrewAI](https://github.com/ptonlix/gohumanloop-examples/tree/main/CrewAI)
65
66
 
66
67
  ### Installation
67
68
 
@@ -206,7 +207,7 @@ Perform `human-in-the-loop` interaction by entering:
206
207
 
207
208
  🚀🚀🚀 Completed successfully ~
208
209
 
209
- ➡️ Check out more examples in the [Examples Directory](./examples/) and we look foward to your contributions!
210
+ ➡️ Check out more examples in the [Examples Repository](https://github.com/ptonlix/gohumanloop-examples) and we look foward to your contributions!
210
211
 
211
212
  ## 🎵 Why GoHumanloop?
212
213
 
@@ -254,7 +255,7 @@ Through `GoHumanloop`'s encapsulation, you can implement secure and efficient `H
254
255
  ## 📚 Key Features
255
256
 
256
257
  <div align="center">
257
- <img height=360 src="http://cdn.oyster-iot.cloud/202505211030197.png"><br>
258
+ <img height=360 src="http://cdn.oyster-iot.cloud/202505291027894.png"><br>
258
259
  <b face="雅黑"> GoHumanLoop Architecture</b>
259
260
  </div>
260
261
  <br>
@@ -1,31 +1,31 @@
1
1
  gohumanloop/__init__.py,sha256=KiY2ncM6OQvkBYcz5rsbob_GuV8hQHOARA-EsxAylEU,2134
2
2
  gohumanloop/__main__.py,sha256=zdGKN92H9SgwZfL4xLqPkE1YaiRcHhVg_GqC-H1VurA,75
3
3
  gohumanloop/adapters/__init__.py,sha256=_XqJ6eaUBLJJJyjfBQJykBZ4X9HvC3VYOVTn2KnBlqo,484
4
- gohumanloop/adapters/base_adapter.py,sha256=snKd2GWE5SuFxqkNwdwS8YAhQzhMs9fpeOG6hT6VRhc,32600
4
+ gohumanloop/adapters/base_adapter.py,sha256=G1Tw7uzBrJObDdVT2kxifotkGZIptnZh5GUqCx54rSs,32884
5
5
  gohumanloop/adapters/langgraph_adapter.py,sha256=AHJv_b6g8xjeq_9X2cGiW76pSGlfgCGBUvjrZQcbR9s,11621
6
6
  gohumanloop/cli/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
7
7
  gohumanloop/cli/main.py,sha256=Txjk31MlkiX9zeHZfFEXEu0s2IBESY8sxrxBEzZKk2U,767
8
8
  gohumanloop/core/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
9
9
  gohumanloop/core/interface.py,sha256=uzV3xG08DDItgB9TgMvskcKVDSIFTx2qv8HXjVBtJcI,21810
10
- gohumanloop/core/manager.py,sha256=imeDVuQlyBRyVR5-PFwxNaFQYaZaAQ69ZGtmsiUpUDg,31790
10
+ gohumanloop/core/manager.py,sha256=A54smLOrN6IgNey6L_zyYJMEX7uB9ZQ_2JDT2im423g,30207
11
11
  gohumanloop/manager/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
12
12
  gohumanloop/manager/ghl_manager.py,sha256=rmbfaS5mAb9c8RPr9Id24vO5DJT9ZC4D282dHZ26SJE,22695
13
13
  gohumanloop/models/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
14
14
  gohumanloop/models/api_model.py,sha256=1LtSQdx2ZVMzTdPrOVGe1JE1Cn_B0CnNQDp1-LlnqLw,2950
15
15
  gohumanloop/models/glh_model.py,sha256=gix4f_57G4URkwXhCspWhU08Sf1MKu9FtUCx424Vf3A,940
16
16
  gohumanloop/providers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
17
- gohumanloop/providers/api_provider.py,sha256=kgduU2udtBUaaMHOjDic7v3bb5kTJeedmlLRpcaOgJM,25771
18
- gohumanloop/providers/base.py,sha256=JHvkInxLIWkUvypR3fphRGgisSMOkutpl-fRnYSHdOw,21893
19
- gohumanloop/providers/email_provider.py,sha256=n4-k4m3oQ8TocT-yxGLTwUMTXfgddFiGxEKMq9W6FGA,44704
17
+ gohumanloop/providers/api_provider.py,sha256=lp7mMbj01aIFZii_1YJDvUbv4kpPeANBB606S7E4VcI,27023
18
+ gohumanloop/providers/base.py,sha256=rOA9xRTh-rn-64RIZpzcIhWNar8LEzYrEXS5H5r7PpM,19554
19
+ gohumanloop/providers/email_provider.py,sha256=kQA6kG7dqpV6R1cJUeaanLmxMVk9pcIwweNZA4IC-2o,45947
20
20
  gohumanloop/providers/ghl_provider.py,sha256=NmOac2LR0d87pc91sMuYtvTYsKdp4wZrhfmSYuZL2ko,2350
21
- gohumanloop/providers/terminal_provider.py,sha256=6YiATcbc6TIYrmzT2BSd9U6gNnE6o8TX4HO1M5Ejxgc,14613
21
+ gohumanloop/providers/terminal_provider.py,sha256=aBNgGpspiu7fGigN6K-gqGlyjFDFvIqKMGp58PxGyPg,15447
22
22
  gohumanloop/utils/__init__.py,sha256=l0e3lnOVrt6HwaxidNGFXORX4awCKemhJZ_t3k-5u-s,124
23
23
  gohumanloop/utils/context_formatter.py,sha256=sAWrKJpxmsHga6gsyBwFBlAsHW8bjR1hkaGhk1PoE1M,2064
24
24
  gohumanloop/utils/threadsafedict.py,sha256=9uyewnwmvS3u1fCx3SK0YWFxHMcyIwlye1Ev7WW7WHA,9588
25
- gohumanloop/utils/utils.py,sha256=-bti65OaVh5dlvc5BIgiTw6dqxmqdKnOQHE0V-LKjek,2107
26
- gohumanloop-0.0.8.dist-info/licenses/LICENSE,sha256=-U5tuCcSpndQwSKWtZbFbazb-_AtZcZL2kQgHbSLg-M,1064
27
- gohumanloop-0.0.8.dist-info/METADATA,sha256=FvrBF4EDkQXWzC2Jg7A43zdvPPsdpR2BN035wgTMxOo,11216
28
- gohumanloop-0.0.8.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
29
- gohumanloop-0.0.8.dist-info/entry_points.txt,sha256=wM6jqRRD8bQXkvIduRVCuAJIlbyWg_F5EDXo5OZ_PwY,88
30
- gohumanloop-0.0.8.dist-info/top_level.txt,sha256=LvOXBqS6Mspmcuqp81uz0Vjx_m_YI0w06DOPCiI1BfY,12
31
- gohumanloop-0.0.8.dist-info/RECORD,,
25
+ gohumanloop/utils/utils.py,sha256=O0zFtMFloAkWylmZE7WpmAjbDe385ZBfuUEh7NIwgGE,2148
26
+ gohumanloop-0.0.10.dist-info/licenses/LICENSE,sha256=-U5tuCcSpndQwSKWtZbFbazb-_AtZcZL2kQgHbSLg-M,1064
27
+ gohumanloop-0.0.10.dist-info/METADATA,sha256=kpmDmvASjoEsVlgRTtQt87g2ZpGfSeVeRuRVFShq334,11428
28
+ gohumanloop-0.0.10.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
29
+ gohumanloop-0.0.10.dist-info/entry_points.txt,sha256=wM6jqRRD8bQXkvIduRVCuAJIlbyWg_F5EDXo5OZ_PwY,88
30
+ gohumanloop-0.0.10.dist-info/top_level.txt,sha256=LvOXBqS6Mspmcuqp81uz0Vjx_m_YI0w06DOPCiI1BfY,12
31
+ gohumanloop-0.0.10.dist-info/RECORD,,