lingtai 0.1.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.
- lingtai-0.1.0/PKG-INFO +28 -0
- lingtai-0.1.0/pyproject.toml +42 -0
- lingtai-0.1.0/setup.cfg +4 -0
- lingtai-0.1.0/src/lingtai/__init__.py +64 -0
- lingtai-0.1.0/src/lingtai/__main__.py +4 -0
- lingtai-0.1.0/src/lingtai/addons/__init__.py +48 -0
- lingtai-0.1.0/src/lingtai/addons/imap/__init__.py +161 -0
- lingtai-0.1.0/src/lingtai/addons/imap/account.py +1167 -0
- lingtai-0.1.0/src/lingtai/addons/imap/config.example.json +26 -0
- lingtai-0.1.0/src/lingtai/addons/imap/manager.py +689 -0
- lingtai-0.1.0/src/lingtai/addons/imap/service.py +84 -0
- lingtai-0.1.0/src/lingtai/addons/telegram/__init__.py +119 -0
- lingtai-0.1.0/src/lingtai/addons/telegram/account.py +278 -0
- lingtai-0.1.0/src/lingtai/addons/telegram/config.example.json +13 -0
- lingtai-0.1.0/src/lingtai/addons/telegram/manager.py +692 -0
- lingtai-0.1.0/src/lingtai/addons/telegram/service.py +67 -0
- lingtai-0.1.0/src/lingtai/agent.py +578 -0
- lingtai-0.1.0/src/lingtai/capabilities/__init__.py +70 -0
- lingtai-0.1.0/src/lingtai/capabilities/avatar.py +310 -0
- lingtai-0.1.0/src/lingtai/capabilities/bash.py +253 -0
- lingtai-0.1.0/src/lingtai/capabilities/bash_policy.json +12 -0
- lingtai-0.1.0/src/lingtai/capabilities/compose.py +104 -0
- lingtai-0.1.0/src/lingtai/capabilities/daemon.py +395 -0
- lingtai-0.1.0/src/lingtai/capabilities/draw.py +90 -0
- lingtai-0.1.0/src/lingtai/capabilities/edit.py +68 -0
- lingtai-0.1.0/src/lingtai/capabilities/email.py +1036 -0
- lingtai-0.1.0/src/lingtai/capabilities/glob.py +49 -0
- lingtai-0.1.0/src/lingtai/capabilities/grep.py +53 -0
- lingtai-0.1.0/src/lingtai/capabilities/library.py +339 -0
- lingtai-0.1.0/src/lingtai/capabilities/listen.py +271 -0
- lingtai-0.1.0/src/lingtai/capabilities/psyche.py +222 -0
- lingtai-0.1.0/src/lingtai/capabilities/read.py +57 -0
- lingtai-0.1.0/src/lingtai/capabilities/talk.py +116 -0
- lingtai-0.1.0/src/lingtai/capabilities/vision.py +103 -0
- lingtai-0.1.0/src/lingtai/capabilities/web_read.py +75 -0
- lingtai-0.1.0/src/lingtai/capabilities/web_search.py +106 -0
- lingtai-0.1.0/src/lingtai/capabilities/write.py +49 -0
- lingtai-0.1.0/src/lingtai/cli.py +185 -0
- lingtai-0.1.0/src/lingtai/config_resolve.py +93 -0
- lingtai-0.1.0/src/lingtai/i18n/__init__.py +66 -0
- lingtai-0.1.0/src/lingtai/i18n/en.json +113 -0
- lingtai-0.1.0/src/lingtai/i18n/wen.json +113 -0
- lingtai-0.1.0/src/lingtai/i18n/zh.json +113 -0
- lingtai-0.1.0/src/lingtai/init_schema.py +176 -0
- lingtai-0.1.0/src/lingtai/llm/__init__.py +20 -0
- lingtai-0.1.0/src/lingtai/llm/_register.py +50 -0
- lingtai-0.1.0/src/lingtai/llm/anthropic/__init__.py +3 -0
- lingtai-0.1.0/src/lingtai/llm/anthropic/adapter.py +677 -0
- lingtai-0.1.0/src/lingtai/llm/anthropic/defaults.py +6 -0
- lingtai-0.1.0/src/lingtai/llm/api_gate.py +112 -0
- lingtai-0.1.0/src/lingtai/llm/base.py +104 -0
- lingtai-0.1.0/src/lingtai/llm/custom/__init__.py +3 -0
- lingtai-0.1.0/src/lingtai/llm/custom/adapter.py +39 -0
- lingtai-0.1.0/src/lingtai/llm/custom/defaults.py +6 -0
- lingtai-0.1.0/src/lingtai/llm/gemini/__init__.py +3 -0
- lingtai-0.1.0/src/lingtai/llm/gemini/adapter.py +909 -0
- lingtai-0.1.0/src/lingtai/llm/gemini/defaults.py +4 -0
- lingtai-0.1.0/src/lingtai/llm/interface_converters.py +280 -0
- lingtai-0.1.0/src/lingtai/llm/minimax/__init__.py +4 -0
- lingtai-0.1.0/src/lingtai/llm/minimax/adapter.py +50 -0
- lingtai-0.1.0/src/lingtai/llm/minimax/defaults.py +7 -0
- lingtai-0.1.0/src/lingtai/llm/minimax/mcp_client.py +149 -0
- lingtai-0.1.0/src/lingtai/llm/minimax/mcp_media_client.py +100 -0
- lingtai-0.1.0/src/lingtai/llm/openai/__init__.py +3 -0
- lingtai-0.1.0/src/lingtai/llm/openai/adapter.py +846 -0
- lingtai-0.1.0/src/lingtai/llm/openai/defaults.py +7 -0
- lingtai-0.1.0/src/lingtai/llm/service.py +264 -0
- lingtai-0.1.0/src/lingtai/network.py +327 -0
- lingtai-0.1.0/src/lingtai/services/__init__.py +1 -0
- lingtai-0.1.0/src/lingtai/services/file_io.py +134 -0
- lingtai-0.1.0/src/lingtai/services/image_gen/__init__.py +79 -0
- lingtai-0.1.0/src/lingtai/services/image_gen/gemini.py +97 -0
- lingtai-0.1.0/src/lingtai/services/image_gen/minimax.py +116 -0
- lingtai-0.1.0/src/lingtai/services/mail.py +4 -0
- lingtai-0.1.0/src/lingtai/services/mcp.py +254 -0
- lingtai-0.1.0/src/lingtai/services/music_gen/__init__.py +79 -0
- lingtai-0.1.0/src/lingtai/services/music_gen/minimax.py +162 -0
- lingtai-0.1.0/src/lingtai/services/transcription/__init__.py +69 -0
- lingtai-0.1.0/src/lingtai/services/transcription/gemini.py +95 -0
- lingtai-0.1.0/src/lingtai/services/transcription/whisper.py +80 -0
- lingtai-0.1.0/src/lingtai/services/tts/__init__.py +68 -0
- lingtai-0.1.0/src/lingtai/services/tts/gemini.py +128 -0
- lingtai-0.1.0/src/lingtai/services/tts/minimax.py +150 -0
- lingtai-0.1.0/src/lingtai/services/vision/__init__.py +103 -0
- lingtai-0.1.0/src/lingtai/services/vision/anthropic.py +61 -0
- lingtai-0.1.0/src/lingtai/services/vision/gemini.py +53 -0
- lingtai-0.1.0/src/lingtai/services/vision/local.py +78 -0
- lingtai-0.1.0/src/lingtai/services/vision/minimax.py +90 -0
- lingtai-0.1.0/src/lingtai/services/vision/openai.py +56 -0
- lingtai-0.1.0/src/lingtai/services/web_read.py +73 -0
- lingtai-0.1.0/src/lingtai/services/websearch/__init__.py +110 -0
- lingtai-0.1.0/src/lingtai/services/websearch/anthropic.py +68 -0
- lingtai-0.1.0/src/lingtai/services/websearch/duckduckgo.py +31 -0
- lingtai-0.1.0/src/lingtai/services/websearch/gemini.py +69 -0
- lingtai-0.1.0/src/lingtai/services/websearch/minimax.py +103 -0
- lingtai-0.1.0/src/lingtai/services/websearch/openai.py +58 -0
- lingtai-0.1.0/src/lingtai/venv_resolve.py +110 -0
- lingtai-0.1.0/src/lingtai.egg-info/PKG-INFO +28 -0
- lingtai-0.1.0/src/lingtai.egg-info/SOURCES.txt +146 -0
- lingtai-0.1.0/src/lingtai.egg-info/dependency_links.txt +1 -0
- lingtai-0.1.0/src/lingtai.egg-info/entry_points.txt +2 -0
- lingtai-0.1.0/src/lingtai.egg-info/requires.txt +29 -0
- lingtai-0.1.0/src/lingtai.egg-info/top_level.txt +2 -0
- lingtai-0.1.0/tests/test_adapter_registry.py +68 -0
- lingtai-0.1.0/tests/test_addon_imap_account.py +1009 -0
- lingtai-0.1.0/tests/test_addon_imap_manager.py +469 -0
- lingtai-0.1.0/tests/test_addon_imap_service.py +144 -0
- lingtai-0.1.0/tests/test_addon_telegram_account.py +207 -0
- lingtai-0.1.0/tests/test_addon_telegram_manager.py +444 -0
- lingtai-0.1.0/tests/test_addon_telegram_service.py +77 -0
- lingtai-0.1.0/tests/test_addons.py +51 -0
- lingtai-0.1.0/tests/test_agent.py +591 -0
- lingtai-0.1.0/tests/test_agent_capabilities.py +105 -0
- lingtai-0.1.0/tests/test_api_gate.py +134 -0
- lingtai-0.1.0/tests/test_cli.py +286 -0
- lingtai-0.1.0/tests/test_cli_integration.py +114 -0
- lingtai-0.1.0/tests/test_compaction.py +292 -0
- lingtai-0.1.0/tests/test_daemon.py +375 -0
- lingtai-0.1.0/tests/test_deep_refresh.py +261 -0
- lingtai-0.1.0/tests/test_eigen.py +261 -0
- lingtai-0.1.0/tests/test_git_init.py +99 -0
- lingtai-0.1.0/tests/test_handshake.py +60 -0
- lingtai-0.1.0/tests/test_init_schema.py +222 -0
- lingtai-0.1.0/tests/test_intrinsics_comm.py +76 -0
- lingtai-0.1.0/tests/test_karma.py +224 -0
- lingtai-0.1.0/tests/test_layers_avatar.py +197 -0
- lingtai-0.1.0/tests/test_layers_bash.py +203 -0
- lingtai-0.1.0/tests/test_layers_compose.py +163 -0
- lingtai-0.1.0/tests/test_layers_draw.py +209 -0
- lingtai-0.1.0/tests/test_layers_email.py +1470 -0
- lingtai-0.1.0/tests/test_layers_file.py +151 -0
- lingtai-0.1.0/tests/test_layers_listen.py +314 -0
- lingtai-0.1.0/tests/test_layers_talk.py +112 -0
- lingtai-0.1.0/tests/test_library.py +368 -0
- lingtai-0.1.0/tests/test_llm_service.py +43 -0
- lingtai-0.1.0/tests/test_mail_intrinsic.py +526 -0
- lingtai-0.1.0/tests/test_memory.py +212 -0
- lingtai-0.1.0/tests/test_network.py +419 -0
- lingtai-0.1.0/tests/test_override_intrinsic.py +59 -0
- lingtai-0.1.0/tests/test_psyche.py +328 -0
- lingtai-0.1.0/tests/test_services_file_io.py +94 -0
- lingtai-0.1.0/tests/test_services_integration.py +229 -0
- lingtai-0.1.0/tests/test_services_mail.py +303 -0
- lingtai-0.1.0/tests/test_silence_kill.py +190 -0
- lingtai-0.1.0/tests/test_system.py +278 -0
- lingtai-0.1.0/tests/test_three_agent_email.py +306 -0
- lingtai-0.1.0/tests/test_vision_capability.py +151 -0
- lingtai-0.1.0/tests/test_web_search_capability.py +111 -0
lingtai-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: lingtai
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Generic research agent with intrinsic tools and MCP-compatible extension interface
|
|
5
|
+
License-Expression: MIT
|
|
6
|
+
Requires-Python: >=3.11
|
|
7
|
+
Requires-Dist: lingtai-kernel>=0.1.0
|
|
8
|
+
Requires-Dist: httpx>=0.27
|
|
9
|
+
Provides-Extra: minimax
|
|
10
|
+
Requires-Dist: openai>=1.0; extra == "minimax"
|
|
11
|
+
Provides-Extra: gemini
|
|
12
|
+
Requires-Dist: google-genai>=1.0; extra == "gemini"
|
|
13
|
+
Provides-Extra: openai
|
|
14
|
+
Requires-Dist: openai>=1.0; extra == "openai"
|
|
15
|
+
Provides-Extra: anthropic
|
|
16
|
+
Requires-Dist: anthropic>=0.40; extra == "anthropic"
|
|
17
|
+
Provides-Extra: mcp
|
|
18
|
+
Requires-Dist: mcp>=1.0; extra == "mcp"
|
|
19
|
+
Provides-Extra: search
|
|
20
|
+
Requires-Dist: ddgs>=7.0; extra == "search"
|
|
21
|
+
Requires-Dist: trafilatura>=2.0; extra == "search"
|
|
22
|
+
Provides-Extra: all
|
|
23
|
+
Requires-Dist: google-genai>=1.0; extra == "all"
|
|
24
|
+
Requires-Dist: openai>=1.0; extra == "all"
|
|
25
|
+
Requires-Dist: anthropic>=0.40; extra == "all"
|
|
26
|
+
Requires-Dist: mcp>=1.0; extra == "all"
|
|
27
|
+
Requires-Dist: ddgs>=7.0; extra == "all"
|
|
28
|
+
Requires-Dist: trafilatura>=2.0; extra == "all"
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=68.0"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "lingtai"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
description = "Generic research agent with intrinsic tools and MCP-compatible extension interface"
|
|
9
|
+
requires-python = ">=3.11"
|
|
10
|
+
license = "MIT"
|
|
11
|
+
dependencies = [
|
|
12
|
+
"lingtai-kernel>=0.1.0",
|
|
13
|
+
"httpx>=0.27",
|
|
14
|
+
]
|
|
15
|
+
|
|
16
|
+
[project.optional-dependencies]
|
|
17
|
+
minimax = ["openai>=1.0"]
|
|
18
|
+
gemini = ["google-genai>=1.0"]
|
|
19
|
+
openai = ["openai>=1.0"]
|
|
20
|
+
anthropic = ["anthropic>=0.40"]
|
|
21
|
+
mcp = ["mcp>=1.0"]
|
|
22
|
+
search = ["ddgs>=7.0", "trafilatura>=2.0"]
|
|
23
|
+
all = [
|
|
24
|
+
"google-genai>=1.0",
|
|
25
|
+
"openai>=1.0",
|
|
26
|
+
"anthropic>=0.40",
|
|
27
|
+
"mcp>=1.0",
|
|
28
|
+
"ddgs>=7.0",
|
|
29
|
+
"trafilatura>=2.0",
|
|
30
|
+
]
|
|
31
|
+
|
|
32
|
+
[project.scripts]
|
|
33
|
+
lingtai = "lingtai.cli:main"
|
|
34
|
+
|
|
35
|
+
[tool.setuptools.packages.find]
|
|
36
|
+
where = ["src"]
|
|
37
|
+
|
|
38
|
+
[tool.setuptools.package-data]
|
|
39
|
+
lingtai = ["i18n/*.json", "capabilities/*.json", "addons/*/*.json"]
|
|
40
|
+
|
|
41
|
+
[tool.pytest.ini_options]
|
|
42
|
+
pythonpath = ["src"]
|
lingtai-0.1.0/setup.cfg
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
"""lingtai — generic AI agent framework with intrinsic tools, composable capabilities, and pluggable services."""
|
|
2
|
+
|
|
3
|
+
from lingtai_kernel.types import UnknownToolError
|
|
4
|
+
from lingtai_kernel.config import AgentConfig
|
|
5
|
+
from lingtai_kernel.base_agent import BaseAgent
|
|
6
|
+
from .agent import Agent
|
|
7
|
+
from lingtai_kernel.state import AgentState
|
|
8
|
+
from lingtai_kernel.message import Message, MSG_REQUEST, MSG_USER_INPUT
|
|
9
|
+
|
|
10
|
+
# Capabilities
|
|
11
|
+
from .capabilities import setup_capability
|
|
12
|
+
from .capabilities.bash import BashManager
|
|
13
|
+
from .capabilities.avatar import AvatarManager
|
|
14
|
+
from .capabilities.email import EmailManager
|
|
15
|
+
|
|
16
|
+
# Services
|
|
17
|
+
from .services.file_io import FileIOService, LocalFileIOService, GrepMatch
|
|
18
|
+
from lingtai_kernel.services.mail import MailService, FilesystemMailService
|
|
19
|
+
from lingtai_kernel.services.logging import LoggingService, JSONLLoggingService
|
|
20
|
+
from .services.vision import VisionService, create_vision_service
|
|
21
|
+
from .services.websearch import SearchService, SearchResult, create_search_service
|
|
22
|
+
from .services.tts import TTSService, create_tts_service
|
|
23
|
+
from .services.image_gen import ImageGenService, create_image_gen_service
|
|
24
|
+
from .services.transcription import TranscriptionService, TranscriptionResult, create_transcription_service
|
|
25
|
+
from .services.music_gen import MusicGenService, create_music_gen_service
|
|
26
|
+
|
|
27
|
+
__all__ = [
|
|
28
|
+
# Core
|
|
29
|
+
"BaseAgent",
|
|
30
|
+
"Agent",
|
|
31
|
+
"Message",
|
|
32
|
+
"AgentState",
|
|
33
|
+
"MSG_REQUEST",
|
|
34
|
+
"MSG_USER_INPUT",
|
|
35
|
+
"AgentConfig",
|
|
36
|
+
"UnknownToolError",
|
|
37
|
+
# Capabilities
|
|
38
|
+
"setup_capability",
|
|
39
|
+
"BashManager",
|
|
40
|
+
"AvatarManager",
|
|
41
|
+
"EmailManager",
|
|
42
|
+
# Services
|
|
43
|
+
"FileIOService",
|
|
44
|
+
"LocalFileIOService",
|
|
45
|
+
"GrepMatch",
|
|
46
|
+
"MailService",
|
|
47
|
+
"FilesystemMailService",
|
|
48
|
+
"LoggingService",
|
|
49
|
+
"JSONLLoggingService",
|
|
50
|
+
"VisionService",
|
|
51
|
+
"create_vision_service",
|
|
52
|
+
"SearchService",
|
|
53
|
+
"SearchResult",
|
|
54
|
+
"create_search_service",
|
|
55
|
+
"TTSService",
|
|
56
|
+
"create_tts_service",
|
|
57
|
+
"ImageGenService",
|
|
58
|
+
"create_image_gen_service",
|
|
59
|
+
"TranscriptionService",
|
|
60
|
+
"TranscriptionResult",
|
|
61
|
+
"create_transcription_service",
|
|
62
|
+
"MusicGenService",
|
|
63
|
+
"create_music_gen_service",
|
|
64
|
+
]
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
"""Add-ons --- optional extensions that may depend on capabilities.
|
|
2
|
+
|
|
3
|
+
Add-ons are set up after capabilities. They use the same
|
|
4
|
+
setup(agent, **kwargs) interface but live separately to signal
|
|
5
|
+
they are optional and may have external dependencies.
|
|
6
|
+
|
|
7
|
+
Addon managers can implement start() and stop() methods for
|
|
8
|
+
lifecycle hooks --- called by Agent.start() and Agent.stop().
|
|
9
|
+
|
|
10
|
+
Usage:
|
|
11
|
+
agent = Agent(
|
|
12
|
+
capabilities=["email", "file"],
|
|
13
|
+
addons={"imap": {"email_address": "...", "email_password": "..."}},
|
|
14
|
+
)
|
|
15
|
+
"""
|
|
16
|
+
from __future__ import annotations
|
|
17
|
+
|
|
18
|
+
import importlib
|
|
19
|
+
from typing import TYPE_CHECKING, Any
|
|
20
|
+
|
|
21
|
+
if TYPE_CHECKING:
|
|
22
|
+
from lingtai_kernel.base_agent import BaseAgent
|
|
23
|
+
|
|
24
|
+
_BUILTIN: dict[str, str] = {
|
|
25
|
+
"imap": ".imap",
|
|
26
|
+
"telegram": ".telegram",
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def setup_addon(agent: "BaseAgent", name: str, **kwargs: Any) -> Any:
|
|
31
|
+
"""Look up an addon by name and call its setup(agent, **kwargs).
|
|
32
|
+
|
|
33
|
+
Returns whatever the addon's setup function returns (typically a manager).
|
|
34
|
+
Raises ValueError if the name is unknown.
|
|
35
|
+
"""
|
|
36
|
+
module_path = _BUILTIN.get(name)
|
|
37
|
+
if module_path is None:
|
|
38
|
+
raise ValueError(
|
|
39
|
+
f"Unknown addon: {name!r}. "
|
|
40
|
+
f"Available: {', '.join(sorted(_BUILTIN))}"
|
|
41
|
+
)
|
|
42
|
+
mod = importlib.import_module(module_path, package=__package__)
|
|
43
|
+
setup_fn = getattr(mod, "setup", None)
|
|
44
|
+
if setup_fn is None:
|
|
45
|
+
raise ValueError(
|
|
46
|
+
f"Addon module {name!r} does not export a setup() function"
|
|
47
|
+
)
|
|
48
|
+
return setup_fn(agent, **kwargs)
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
"""IMAP addon — real email via IMAP/SMTP.
|
|
2
|
+
|
|
3
|
+
Adds an `imap` tool with its own mailbox (working_dir/imap/).
|
|
4
|
+
An internal TCP bridge port lets other agents relay messages outward.
|
|
5
|
+
|
|
6
|
+
Usage (config file — recommended):
|
|
7
|
+
agent = Agent(
|
|
8
|
+
addons={"imap": {"config": "imap.json"}},
|
|
9
|
+
)
|
|
10
|
+
|
|
11
|
+
Usage (inline, single account):
|
|
12
|
+
agent = Agent(
|
|
13
|
+
addons={"imap": {
|
|
14
|
+
"email_address": "agent@example.com",
|
|
15
|
+
"email_password": "xxxx xxxx xxxx xxxx",
|
|
16
|
+
"imap_host": "imap.gmail.com",
|
|
17
|
+
"smtp_host": "smtp.gmail.com",
|
|
18
|
+
}},
|
|
19
|
+
)
|
|
20
|
+
|
|
21
|
+
Usage (inline, multi-account):
|
|
22
|
+
agent = Agent(
|
|
23
|
+
addons={"imap": {
|
|
24
|
+
"accounts": [
|
|
25
|
+
{"email_address": "a@gmail.com", "email_password": "xxxx"},
|
|
26
|
+
{"email_address": "b@outlook.com", "email_password": "yyyy",
|
|
27
|
+
"imap_host": "imap.outlook.com", "smtp_host": "smtp.outlook.com"},
|
|
28
|
+
],
|
|
29
|
+
}},
|
|
30
|
+
)
|
|
31
|
+
"""
|
|
32
|
+
from __future__ import annotations
|
|
33
|
+
|
|
34
|
+
import json
|
|
35
|
+
import logging
|
|
36
|
+
from pathlib import Path
|
|
37
|
+
from typing import TYPE_CHECKING
|
|
38
|
+
|
|
39
|
+
from lingtai_kernel.services.mail import FilesystemMailService
|
|
40
|
+
from .manager import IMAPMailManager, SCHEMA, DESCRIPTION
|
|
41
|
+
from .service import IMAPMailService
|
|
42
|
+
|
|
43
|
+
if TYPE_CHECKING:
|
|
44
|
+
from lingtai_kernel.base_agent import BaseAgent
|
|
45
|
+
|
|
46
|
+
log = logging.getLogger(__name__)
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def setup(
|
|
50
|
+
agent: "BaseAgent",
|
|
51
|
+
*,
|
|
52
|
+
# Config file
|
|
53
|
+
config: str | Path | None = None,
|
|
54
|
+
# Single-account shorthand
|
|
55
|
+
email_address: str | None = None,
|
|
56
|
+
email_password: str | None = None,
|
|
57
|
+
imap_host: str = "imap.gmail.com",
|
|
58
|
+
imap_port: int = 993,
|
|
59
|
+
smtp_host: str = "smtp.gmail.com",
|
|
60
|
+
smtp_port: int = 587,
|
|
61
|
+
allowed_senders: list[str] | None = None,
|
|
62
|
+
poll_interval: int = 30,
|
|
63
|
+
# Multi-account
|
|
64
|
+
accounts: list[dict] | None = None,
|
|
65
|
+
# Addon-level
|
|
66
|
+
bridge_port: int = 8399,
|
|
67
|
+
) -> IMAPMailManager:
|
|
68
|
+
"""Set up IMAP addon — registers imap tool, creates services.
|
|
69
|
+
|
|
70
|
+
Args:
|
|
71
|
+
config: Path to a JSON config file. Keys are the same as the kwargs.
|
|
72
|
+
Inline kwargs override config file values.
|
|
73
|
+
|
|
74
|
+
Accepts either a flat single-account config or a list of account dicts.
|
|
75
|
+
|
|
76
|
+
Listeners are NOT started here — they start in IMAPMailManager.start(),
|
|
77
|
+
which is called by Agent.start() via the addon lifecycle.
|
|
78
|
+
"""
|
|
79
|
+
# Load config file if provided — inline kwargs override file values
|
|
80
|
+
if config is not None:
|
|
81
|
+
config_path = Path(config)
|
|
82
|
+
if not config_path.is_file():
|
|
83
|
+
raise FileNotFoundError(f"IMAP config not found: {config_path}")
|
|
84
|
+
from lingtai.config_resolve import load_jsonc
|
|
85
|
+
file_cfg = load_jsonc(config_path)
|
|
86
|
+
if accounts is None:
|
|
87
|
+
accounts = file_cfg.get("accounts")
|
|
88
|
+
if email_address is None:
|
|
89
|
+
email_address = file_cfg.get("email_address")
|
|
90
|
+
if email_password is None:
|
|
91
|
+
email_password = file_cfg.get("email_password")
|
|
92
|
+
if imap_host == "imap.gmail.com" and "imap_host" in file_cfg:
|
|
93
|
+
imap_host = file_cfg["imap_host"]
|
|
94
|
+
if imap_port == 993 and "imap_port" in file_cfg:
|
|
95
|
+
imap_port = file_cfg["imap_port"]
|
|
96
|
+
if smtp_host == "smtp.gmail.com" and "smtp_host" in file_cfg:
|
|
97
|
+
smtp_host = file_cfg["smtp_host"]
|
|
98
|
+
if smtp_port == 587 and "smtp_port" in file_cfg:
|
|
99
|
+
smtp_port = file_cfg["smtp_port"]
|
|
100
|
+
if allowed_senders is None:
|
|
101
|
+
allowed_senders = file_cfg.get("allowed_senders")
|
|
102
|
+
if poll_interval == 30 and "poll_interval" in file_cfg:
|
|
103
|
+
poll_interval = file_cfg["poll_interval"]
|
|
104
|
+
if bridge_port == 8399 and "bridge_port" in file_cfg:
|
|
105
|
+
bridge_port = file_cfg["bridge_port"]
|
|
106
|
+
|
|
107
|
+
if accounts is not None:
|
|
108
|
+
account_list = accounts
|
|
109
|
+
elif email_address is not None:
|
|
110
|
+
account_list = [{
|
|
111
|
+
"email_address": email_address,
|
|
112
|
+
"email_password": email_password,
|
|
113
|
+
"imap_host": imap_host,
|
|
114
|
+
"imap_port": imap_port,
|
|
115
|
+
"smtp_host": smtp_host,
|
|
116
|
+
"smtp_port": smtp_port,
|
|
117
|
+
"allowed_senders": allowed_senders,
|
|
118
|
+
"poll_interval": poll_interval,
|
|
119
|
+
}]
|
|
120
|
+
else:
|
|
121
|
+
raise ValueError(
|
|
122
|
+
"imap addon requires 'config', 'accounts', or 'email_address'"
|
|
123
|
+
)
|
|
124
|
+
|
|
125
|
+
working_dir = Path(agent._working_dir)
|
|
126
|
+
bridge_dir = working_dir / "imap_bridge"
|
|
127
|
+
bridge_dir.mkdir(parents=True, exist_ok=True)
|
|
128
|
+
|
|
129
|
+
imap_svc = IMAPMailService(
|
|
130
|
+
accounts=account_list,
|
|
131
|
+
working_dir=working_dir,
|
|
132
|
+
)
|
|
133
|
+
|
|
134
|
+
bridge = FilesystemMailService(working_dir=bridge_dir)
|
|
135
|
+
|
|
136
|
+
mgr = IMAPMailManager(agent, service=imap_svc, tcp_alias=str(bridge_dir))
|
|
137
|
+
mgr._bridge = bridge
|
|
138
|
+
|
|
139
|
+
# Build system prompt listing all configured accounts
|
|
140
|
+
addr_lines = "\n".join(
|
|
141
|
+
f" - {acct['email_address']}"
|
|
142
|
+
for acct in account_list
|
|
143
|
+
)
|
|
144
|
+
system_prompt = (
|
|
145
|
+
f"IMAP email accounts:\n{addr_lines}\n"
|
|
146
|
+
f"Internal bridge: {bridge_dir} "
|
|
147
|
+
f"(other agents can send to this address to relay via IMAP/SMTP)\n"
|
|
148
|
+
f"Use imap(action=...) for external email. "
|
|
149
|
+
f"Use email(action=...) for inter-agent communication."
|
|
150
|
+
)
|
|
151
|
+
|
|
152
|
+
agent.add_tool(
|
|
153
|
+
"imap", schema=SCHEMA, handler=mgr.handle, description=DESCRIPTION,
|
|
154
|
+
system_prompt=system_prompt,
|
|
155
|
+
)
|
|
156
|
+
|
|
157
|
+
log.info(
|
|
158
|
+
"IMAP addon configured: %d account(s) (bridge: %s)",
|
|
159
|
+
len(account_list), bridge_dir,
|
|
160
|
+
)
|
|
161
|
+
return mgr
|