aient 1.1.99__tar.gz → 1.2.1__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 (56) hide show
  1. {aient-1.1.99 → aient-1.2.1}/PKG-INFO +1 -1
  2. {aient-1.1.99 → aient-1.2.1}/aient/architext/architext/core.py +58 -10
  3. {aient-1.1.99 → aient-1.2.1}/aient/architext/test/test.py +48 -0
  4. {aient-1.1.99 → aient-1.2.1}/aient/models/chatgpt.py +2 -7
  5. {aient-1.1.99 → aient-1.2.1}/aient.egg-info/PKG-INFO +1 -1
  6. {aient-1.1.99 → aient-1.2.1}/pyproject.toml +1 -1
  7. {aient-1.1.99 → aient-1.2.1}/LICENSE +0 -0
  8. {aient-1.1.99 → aient-1.2.1}/README.md +0 -0
  9. {aient-1.1.99 → aient-1.2.1}/aient/__init__.py +0 -0
  10. {aient-1.1.99 → aient-1.2.1}/aient/architext/architext/__init__.py +0 -0
  11. {aient-1.1.99 → aient-1.2.1}/aient/architext/test/openai_client.py +0 -0
  12. {aient-1.1.99 → aient-1.2.1}/aient/architext/test/test_save_load.py +0 -0
  13. {aient-1.1.99 → aient-1.2.1}/aient/core/__init__.py +0 -0
  14. {aient-1.1.99 → aient-1.2.1}/aient/core/log_config.py +0 -0
  15. {aient-1.1.99 → aient-1.2.1}/aient/core/models.py +0 -0
  16. {aient-1.1.99 → aient-1.2.1}/aient/core/request.py +0 -0
  17. {aient-1.1.99 → aient-1.2.1}/aient/core/response.py +0 -0
  18. {aient-1.1.99 → aient-1.2.1}/aient/core/test/test_base_api.py +0 -0
  19. {aient-1.1.99 → aient-1.2.1}/aient/core/test/test_geminimask.py +0 -0
  20. {aient-1.1.99 → aient-1.2.1}/aient/core/test/test_image.py +0 -0
  21. {aient-1.1.99 → aient-1.2.1}/aient/core/test/test_payload.py +0 -0
  22. {aient-1.1.99 → aient-1.2.1}/aient/core/utils.py +0 -0
  23. {aient-1.1.99 → aient-1.2.1}/aient/models/__init__.py +0 -0
  24. {aient-1.1.99 → aient-1.2.1}/aient/models/audio.py +0 -0
  25. {aient-1.1.99 → aient-1.2.1}/aient/models/base.py +0 -0
  26. {aient-1.1.99 → aient-1.2.1}/aient/plugins/__init__.py +0 -0
  27. {aient-1.1.99 → aient-1.2.1}/aient/plugins/arXiv.py +0 -0
  28. {aient-1.1.99 → aient-1.2.1}/aient/plugins/config.py +0 -0
  29. {aient-1.1.99 → aient-1.2.1}/aient/plugins/excute_command.py +0 -0
  30. {aient-1.1.99 → aient-1.2.1}/aient/plugins/get_time.py +0 -0
  31. {aient-1.1.99 → aient-1.2.1}/aient/plugins/image.py +0 -0
  32. {aient-1.1.99 → aient-1.2.1}/aient/plugins/list_directory.py +0 -0
  33. {aient-1.1.99 → aient-1.2.1}/aient/plugins/read_file.py +0 -0
  34. {aient-1.1.99 → aient-1.2.1}/aient/plugins/read_image.py +0 -0
  35. {aient-1.1.99 → aient-1.2.1}/aient/plugins/readonly.py +0 -0
  36. {aient-1.1.99 → aient-1.2.1}/aient/plugins/registry.py +0 -0
  37. {aient-1.1.99 → aient-1.2.1}/aient/plugins/run_python.py +0 -0
  38. {aient-1.1.99 → aient-1.2.1}/aient/plugins/websearch.py +0 -0
  39. {aient-1.1.99 → aient-1.2.1}/aient/plugins/write_file.py +0 -0
  40. {aient-1.1.99 → aient-1.2.1}/aient/utils/__init__.py +0 -0
  41. {aient-1.1.99 → aient-1.2.1}/aient/utils/prompt.py +0 -0
  42. {aient-1.1.99 → aient-1.2.1}/aient/utils/scripts.py +0 -0
  43. {aient-1.1.99 → aient-1.2.1}/aient.egg-info/SOURCES.txt +0 -0
  44. {aient-1.1.99 → aient-1.2.1}/aient.egg-info/dependency_links.txt +0 -0
  45. {aient-1.1.99 → aient-1.2.1}/aient.egg-info/requires.txt +0 -0
  46. {aient-1.1.99 → aient-1.2.1}/aient.egg-info/top_level.txt +0 -0
  47. {aient-1.1.99 → aient-1.2.1}/setup.cfg +0 -0
  48. {aient-1.1.99 → aient-1.2.1}/test/test_Web_crawler.py +0 -0
  49. {aient-1.1.99 → aient-1.2.1}/test/test_ddg_search.py +0 -0
  50. {aient-1.1.99 → aient-1.2.1}/test/test_google_search.py +0 -0
  51. {aient-1.1.99 → aient-1.2.1}/test/test_ollama.py +0 -0
  52. {aient-1.1.99 → aient-1.2.1}/test/test_plugin.py +0 -0
  53. {aient-1.1.99 → aient-1.2.1}/test/test_search.py +0 -0
  54. {aient-1.1.99 → aient-1.2.1}/test/test_url.py +0 -0
  55. {aient-1.1.99 → aient-1.2.1}/test/test_whisper.py +0 -0
  56. {aient-1.1.99 → aient-1.2.1}/test/test_yjh.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: aient
3
- Version: 1.1.99
3
+ Version: 1.2.1
4
4
  Summary: Aient: The Awakening of Agent.
5
5
  Requires-Python: >=3.11
6
6
  Description-Content-Type: text/markdown
@@ -10,6 +10,30 @@ from dataclasses import dataclass
10
10
  from abc import ABC, abstractmethod
11
11
  from typing import List, Dict, Any, Optional, Union, Callable
12
12
 
13
+ # A wrapper to manage multiple providers with the same name
14
+ class ProviderGroup:
15
+ """A container for multiple providers that share the same name, allowing for bulk operations."""
16
+ def __init__(self, providers: List['ContextProvider']):
17
+ self._providers = providers
18
+ def __getitem__(self, key: int) -> 'ContextProvider':
19
+ """Allows accessing providers by index, e.g., group[-1]."""
20
+ return self._providers[key]
21
+ def __iter__(self):
22
+ """Allows iterating over the providers."""
23
+ return iter(self._providers)
24
+ def __len__(self) -> int:
25
+ """Returns the number of providers in the group."""
26
+ return len(self._providers)
27
+ @property
28
+ def visible(self) -> List[bool]:
29
+ """Gets the visibility of all providers in the group."""
30
+ return [p.visible for p in self._providers]
31
+ @visible.setter
32
+ def visible(self, value: bool):
33
+ """Sets the visibility for all providers in the group."""
34
+ for p in self._providers:
35
+ p.visible = value
36
+
13
37
  # Global, thread-safe registry for providers created within f-strings
14
38
  _fstring_provider_registry = {}
15
39
  _registry_lock = threading.Lock()
@@ -436,22 +460,40 @@ class Messages:
436
460
  def __init__(self, *initial_messages: Message):
437
461
  from typing import Tuple
438
462
  self._messages: List[Message] = []
439
- self._providers_index: Dict[str, Tuple[ContextProvider, Message]] = {}
463
+ self._providers_index: Dict[str, List[Tuple[ContextProvider, Message]]] = {}
440
464
  if initial_messages:
441
465
  for msg in initial_messages:
442
466
  self.append(msg)
443
467
 
444
468
  def _notify_provider_added(self, provider: ContextProvider, message: Message):
445
469
  if provider.name not in self._providers_index:
446
- self._providers_index[provider.name] = (provider, message)
470
+ self._providers_index[provider.name] = []
471
+ self._providers_index[provider.name].append((provider, message))
447
472
 
448
473
  def _notify_provider_removed(self, provider: ContextProvider):
449
474
  if provider.name in self._providers_index:
450
- del self._providers_index[provider.name]
475
+ # Create a new list excluding the provider to be removed.
476
+ # Comparing by object identity (`is`) is crucial here.
477
+ providers_list = self._providers_index[provider.name]
478
+ new_list = [(p, m) for p, m in providers_list if p is not provider]
479
+
480
+ if not new_list:
481
+ # If the list becomes empty, remove the key from the dictionary.
482
+ del self._providers_index[provider.name]
483
+ else:
484
+ # Otherwise, update the dictionary with the new list.
485
+ self._providers_index[provider.name] = new_list
486
+
487
+ def provider(self, name: str) -> Optional[Union[ContextProvider, ProviderGroup]]:
488
+ indexed_list = self._providers_index.get(name)
489
+ if not indexed_list:
490
+ return None
451
491
 
452
- def provider(self, name: str) -> Optional[ContextProvider]:
453
- indexed = self._providers_index.get(name)
454
- return indexed[0] if indexed else None
492
+ providers = [p for p, m in indexed_list]
493
+ if len(providers) == 1:
494
+ return providers[0]
495
+ else:
496
+ return ProviderGroup(providers)
455
497
 
456
498
  def pop(self, key: Optional[Union[str, int]] = None) -> Union[Optional[ContextProvider], Optional[Message]]:
457
499
  # If no key is provided, pop the last message.
@@ -459,10 +501,13 @@ class Messages:
459
501
  key = len(self._messages) - 1
460
502
 
461
503
  if isinstance(key, str):
462
- indexed = self._providers_index.get(key)
463
- if not indexed:
504
+ indexed_list = self._providers_index.get(key)
505
+ if not indexed_list:
464
506
  return None
465
- _provider, parent_message = indexed
507
+ # Pop the first one found, which is consistent with how pop usually works
508
+ _provider, parent_message = indexed_list[0]
509
+ # The actual removal from _providers_index happens in _notify_provider_removed
510
+ # which is called by message.pop()
466
511
  return parent_message.pop(key)
467
512
  elif isinstance(key, int):
468
513
  try:
@@ -481,7 +526,10 @@ class Messages:
481
526
  return None
482
527
 
483
528
  async def refresh(self):
484
- tasks = [provider.refresh() for provider, _ in self._providers_index.values()]
529
+ tasks = []
530
+ for provider_list in self._providers_index.values():
531
+ for provider, _ in provider_list:
532
+ tasks.append(provider.refresh())
485
533
  await asyncio.gather(*tasks)
486
534
 
487
535
  def render(self) -> List[Dict[str, Any]]:
@@ -1053,6 +1053,54 @@ Current time: {Texts(lambda: datetime.now().strftime("%Y-%m-%d %H:%M:%S"))}
1053
1053
  self.assertEqual(len(rendered_visible_again), 1)
1054
1054
  self.assertEqual(rendered_visible_again[0]['content'], "Hello, World!")
1055
1055
 
1056
+ async def test_z8_bulk_provider_visibility_control(self):
1057
+ """测试通过名称批量控制和豁免provider的可见性"""
1058
+ # 1. 创建多个同名 provider
1059
+ messages = Messages(
1060
+ UserMessage(
1061
+ Texts("First explanation.", name="explanation"),
1062
+ Texts("Second explanation.", name="explanation"),
1063
+ Texts("Some other text."),
1064
+ Texts("Third explanation.", name="explanation")
1065
+ )
1066
+ )
1067
+
1068
+ # 2. 初始渲染,所有 "explanation" 都应该可见
1069
+ rendered_initial = await messages.render_latest()
1070
+ self.assertIn("First explanation.", rendered_initial[0]['content'])
1071
+ self.assertIn("Second explanation.", rendered_initial[0]['content'])
1072
+ self.assertIn("Third explanation.", rendered_initial[0]['content'])
1073
+
1074
+ # 3. 获取所有名为 "explanation" 的 provider
1075
+ explanation_providers = messages.provider("explanation")
1076
+ self.assertIsInstance(explanation_providers, ProviderGroup)
1077
+ self.assertEqual(len(explanation_providers), 3)
1078
+
1079
+ # 4. 将所有 "explanation" provider 设置为不可见
1080
+ # 这是需要实现的新语法
1081
+ explanation_providers.visible = False
1082
+ for p in explanation_providers:
1083
+ self.assertFalse(p.visible)
1084
+
1085
+ # 5. 渲染,所有 "explanation" 的内容都应该消失
1086
+ rendered_hidden = await messages.render_latest()
1087
+ self.assertNotIn("First explanation.", rendered_hidden[0]['content'])
1088
+ self.assertNotIn("Second explanation.", rendered_hidden[0]['content'])
1089
+ self.assertNotIn("Third explanation.", rendered_hidden[0]['content'])
1090
+ self.assertIn("Some other text.", rendered_hidden[0]['content'])
1091
+
1092
+ # 6. 将最后一个 "explanation" provider 设置回可见
1093
+ # 这是需要实现的另一个新语法
1094
+ explanation_providers[-1].visible = True
1095
+ self.assertTrue(explanation_providers[-1].visible)
1096
+ self.assertFalse(explanation_providers[0].visible)
1097
+
1098
+ # 7. 最终渲染,只应看到最后一个 "explanation"
1099
+ rendered_final = await messages.render_latest()
1100
+ self.assertNotIn("First explanation.", rendered_final[0]['content'])
1101
+ self.assertNotIn("Second explanation.", rendered_final[0]['content'])
1102
+ self.assertIn("Third explanation.", rendered_final[0]['content'])
1103
+ self.assertIn("Some other text.", rendered_final[0]['content'])
1056
1104
 
1057
1105
  # ==============================================================================
1058
1106
  # 6. 演示
@@ -97,13 +97,8 @@ class chatgpt(BaseLLM):
97
97
  Initialize Chatbot with API key (from https://platform.openai.com/account/api-keys)
98
98
  """
99
99
  super().__init__(api_key, engine, api_url, system_prompt, proxy, timeout, max_tokens, temperature, top_p, presence_penalty, frequency_penalty, reply_count, truncate_limit, use_plugins=use_plugins, print_log=print_log)
100
- self.conversation: dict[str, list[dict]] = {
101
- "default": [
102
- {
103
- "role": "system",
104
- "content": self.system_prompt,
105
- },
106
- ],
100
+ self.conversation: dict[str, Messages] = {
101
+ "default": Messages(SystemMessage(self.system_prompt)),
107
102
  }
108
103
  if cache_messages:
109
104
  self.conversation["default"] = cache_messages
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: aient
3
- Version: 1.1.99
3
+ Version: 1.2.1
4
4
  Summary: Aient: The Awakening of Agent.
5
5
  Requires-Python: >=3.11
6
6
  Description-Content-Type: text/markdown
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "aient"
3
- version = "1.1.99"
3
+ version = "1.2.1"
4
4
  description = "Aient: The Awakening of Agent."
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.11"
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes