revert: restore context.py and manager.py to tanishra baseline (out of scope)
This commit is contained in:
@@ -102,11 +102,8 @@ Your workspace is at: {workspace_path}
|
|||||||
- Custom skills: {workspace_path}/skills/{{skill-name}}/SKILL.md
|
- Custom skills: {workspace_path}/skills/{{skill-name}}/SKILL.md
|
||||||
|
|
||||||
IMPORTANT: When responding to direct questions or conversations, reply directly with your text response.
|
IMPORTANT: When responding to direct questions or conversations, reply directly with your text response.
|
||||||
Use the 'message' tool only when you need explicit channel delivery behavior:
|
Only use the 'message' tool when you need to send a message to a specific chat channel (like WhatsApp).
|
||||||
- Send to a different channel/chat than the current session
|
For normal conversation, just respond with text - do not call the message tool.
|
||||||
- Send one or more file attachments via `media` (local file paths)
|
|
||||||
For normal conversation text, respond directly without calling the message tool.
|
|
||||||
Do not claim that attachments are impossible if a channel supports file send and you can provide local paths.
|
|
||||||
|
|
||||||
Always be helpful, accurate, and concise. Before calling tools, briefly tell the user what you're about to do (one short sentence in the user's language).
|
Always be helpful, accurate, and concise. Before calling tools, briefly tell the user what you're about to do (one short sentence in the user's language).
|
||||||
When remembering something important, write to {workspace_path}/memory/MEMORY.md
|
When remembering something important, write to {workspace_path}/memory/MEMORY.md
|
||||||
|
|||||||
@@ -16,29 +16,28 @@ from nanobot.config.schema import Config
|
|||||||
class ChannelManager:
|
class ChannelManager:
|
||||||
"""
|
"""
|
||||||
Manages chat channels and coordinates message routing.
|
Manages chat channels and coordinates message routing.
|
||||||
|
|
||||||
Responsibilities:
|
Responsibilities:
|
||||||
- Initialize enabled channels (Telegram, WhatsApp, etc.)
|
- Initialize enabled channels (Telegram, WhatsApp, etc.)
|
||||||
- Start/stop channels
|
- Start/stop channels
|
||||||
- Route outbound messages
|
- Route outbound messages
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, config: Config, bus: MessageBus):
|
def __init__(self, config: Config, bus: MessageBus):
|
||||||
self.config = config
|
self.config = config
|
||||||
self.bus = bus
|
self.bus = bus
|
||||||
self.channels: dict[str, BaseChannel] = {}
|
self.channels: dict[str, BaseChannel] = {}
|
||||||
self._dispatch_task: asyncio.Task | None = None
|
self._dispatch_task: asyncio.Task | None = None
|
||||||
|
|
||||||
self._init_channels()
|
self._init_channels()
|
||||||
|
|
||||||
def _init_channels(self) -> None:
|
def _init_channels(self) -> None:
|
||||||
"""Initialize channels based on config."""
|
"""Initialize channels based on config."""
|
||||||
|
|
||||||
# Telegram channel
|
# Telegram channel
|
||||||
if self.config.channels.telegram.enabled:
|
if self.config.channels.telegram.enabled:
|
||||||
try:
|
try:
|
||||||
from nanobot.channels.telegram import TelegramChannel
|
from nanobot.channels.telegram import TelegramChannel
|
||||||
|
|
||||||
self.channels["telegram"] = TelegramChannel(
|
self.channels["telegram"] = TelegramChannel(
|
||||||
self.config.channels.telegram,
|
self.config.channels.telegram,
|
||||||
self.bus,
|
self.bus,
|
||||||
@@ -47,13 +46,14 @@ class ChannelManager:
|
|||||||
logger.info("Telegram channel enabled")
|
logger.info("Telegram channel enabled")
|
||||||
except ImportError as e:
|
except ImportError as e:
|
||||||
logger.warning(f"Telegram channel not available: {e}")
|
logger.warning(f"Telegram channel not available: {e}")
|
||||||
|
|
||||||
# WhatsApp channel
|
# WhatsApp channel
|
||||||
if self.config.channels.whatsapp.enabled:
|
if self.config.channels.whatsapp.enabled:
|
||||||
try:
|
try:
|
||||||
from nanobot.channels.whatsapp import WhatsAppChannel
|
from nanobot.channels.whatsapp import WhatsAppChannel
|
||||||
|
self.channels["whatsapp"] = WhatsAppChannel(
|
||||||
self.channels["whatsapp"] = WhatsAppChannel(self.config.channels.whatsapp, self.bus)
|
self.config.channels.whatsapp, self.bus
|
||||||
|
)
|
||||||
logger.info("WhatsApp channel enabled")
|
logger.info("WhatsApp channel enabled")
|
||||||
except ImportError as e:
|
except ImportError as e:
|
||||||
logger.warning(f"WhatsApp channel not available: {e}")
|
logger.warning(f"WhatsApp channel not available: {e}")
|
||||||
@@ -62,18 +62,20 @@ class ChannelManager:
|
|||||||
if self.config.channels.discord.enabled:
|
if self.config.channels.discord.enabled:
|
||||||
try:
|
try:
|
||||||
from nanobot.channels.discord import DiscordChannel
|
from nanobot.channels.discord import DiscordChannel
|
||||||
|
self.channels["discord"] = DiscordChannel(
|
||||||
self.channels["discord"] = DiscordChannel(self.config.channels.discord, self.bus)
|
self.config.channels.discord, self.bus
|
||||||
|
)
|
||||||
logger.info("Discord channel enabled")
|
logger.info("Discord channel enabled")
|
||||||
except ImportError as e:
|
except ImportError as e:
|
||||||
logger.warning(f"Discord channel not available: {e}")
|
logger.warning(f"Discord channel not available: {e}")
|
||||||
|
|
||||||
# Feishu channel
|
# Feishu channel
|
||||||
if self.config.channels.feishu.enabled:
|
if self.config.channels.feishu.enabled:
|
||||||
try:
|
try:
|
||||||
from nanobot.channels.feishu import FeishuChannel
|
from nanobot.channels.feishu import FeishuChannel
|
||||||
|
self.channels["feishu"] = FeishuChannel(
|
||||||
self.channels["feishu"] = FeishuChannel(self.config.channels.feishu, self.bus)
|
self.config.channels.feishu, self.bus
|
||||||
|
)
|
||||||
logger.info("Feishu channel enabled")
|
logger.info("Feishu channel enabled")
|
||||||
except ImportError as e:
|
except ImportError as e:
|
||||||
logger.warning(f"Feishu channel not available: {e}")
|
logger.warning(f"Feishu channel not available: {e}")
|
||||||
@@ -83,7 +85,9 @@ class ChannelManager:
|
|||||||
try:
|
try:
|
||||||
from nanobot.channels.mochat import MochatChannel
|
from nanobot.channels.mochat import MochatChannel
|
||||||
|
|
||||||
self.channels["mochat"] = MochatChannel(self.config.channels.mochat, self.bus)
|
self.channels["mochat"] = MochatChannel(
|
||||||
|
self.config.channels.mochat, self.bus
|
||||||
|
)
|
||||||
logger.info("Mochat channel enabled")
|
logger.info("Mochat channel enabled")
|
||||||
except ImportError as e:
|
except ImportError as e:
|
||||||
logger.warning(f"Mochat channel not available: {e}")
|
logger.warning(f"Mochat channel not available: {e}")
|
||||||
@@ -92,8 +96,9 @@ class ChannelManager:
|
|||||||
if self.config.channels.dingtalk.enabled:
|
if self.config.channels.dingtalk.enabled:
|
||||||
try:
|
try:
|
||||||
from nanobot.channels.dingtalk import DingTalkChannel
|
from nanobot.channels.dingtalk import DingTalkChannel
|
||||||
|
self.channels["dingtalk"] = DingTalkChannel(
|
||||||
self.channels["dingtalk"] = DingTalkChannel(self.config.channels.dingtalk, self.bus)
|
self.config.channels.dingtalk, self.bus
|
||||||
|
)
|
||||||
logger.info("DingTalk channel enabled")
|
logger.info("DingTalk channel enabled")
|
||||||
except ImportError as e:
|
except ImportError as e:
|
||||||
logger.warning(f"DingTalk channel not available: {e}")
|
logger.warning(f"DingTalk channel not available: {e}")
|
||||||
@@ -102,8 +107,9 @@ class ChannelManager:
|
|||||||
if self.config.channels.email.enabled:
|
if self.config.channels.email.enabled:
|
||||||
try:
|
try:
|
||||||
from nanobot.channels.email import EmailChannel
|
from nanobot.channels.email import EmailChannel
|
||||||
|
self.channels["email"] = EmailChannel(
|
||||||
self.channels["email"] = EmailChannel(self.config.channels.email, self.bus)
|
self.config.channels.email, self.bus
|
||||||
|
)
|
||||||
logger.info("Email channel enabled")
|
logger.info("Email channel enabled")
|
||||||
except ImportError as e:
|
except ImportError as e:
|
||||||
logger.warning(f"Email channel not available: {e}")
|
logger.warning(f"Email channel not available: {e}")
|
||||||
@@ -112,8 +118,9 @@ class ChannelManager:
|
|||||||
if self.config.channels.slack.enabled:
|
if self.config.channels.slack.enabled:
|
||||||
try:
|
try:
|
||||||
from nanobot.channels.slack import SlackChannel
|
from nanobot.channels.slack import SlackChannel
|
||||||
|
self.channels["slack"] = SlackChannel(
|
||||||
self.channels["slack"] = SlackChannel(self.config.channels.slack, self.bus)
|
self.config.channels.slack, self.bus
|
||||||
|
)
|
||||||
logger.info("Slack channel enabled")
|
logger.info("Slack channel enabled")
|
||||||
except ImportError as e:
|
except ImportError as e:
|
||||||
logger.warning(f"Slack channel not available: {e}")
|
logger.warning(f"Slack channel not available: {e}")
|
||||||
@@ -122,7 +129,6 @@ class ChannelManager:
|
|||||||
if self.config.channels.qq.enabled:
|
if self.config.channels.qq.enabled:
|
||||||
try:
|
try:
|
||||||
from nanobot.channels.qq import QQChannel
|
from nanobot.channels.qq import QQChannel
|
||||||
|
|
||||||
self.channels["qq"] = QQChannel(
|
self.channels["qq"] = QQChannel(
|
||||||
self.config.channels.qq,
|
self.config.channels.qq,
|
||||||
self.bus,
|
self.bus,
|
||||||
@@ -130,7 +136,7 @@ class ChannelManager:
|
|||||||
logger.info("QQ channel enabled")
|
logger.info("QQ channel enabled")
|
||||||
except ImportError as e:
|
except ImportError as e:
|
||||||
logger.warning(f"QQ channel not available: {e}")
|
logger.warning(f"QQ channel not available: {e}")
|
||||||
|
|
||||||
async def _start_channel(self, name: str, channel: BaseChannel) -> None:
|
async def _start_channel(self, name: str, channel: BaseChannel) -> None:
|
||||||
"""Start a channel and log any exceptions."""
|
"""Start a channel and log any exceptions."""
|
||||||
try:
|
try:
|
||||||
@@ -143,23 +149,23 @@ class ChannelManager:
|
|||||||
if not self.channels:
|
if not self.channels:
|
||||||
logger.warning("No channels enabled")
|
logger.warning("No channels enabled")
|
||||||
return
|
return
|
||||||
|
|
||||||
# Start outbound dispatcher
|
# Start outbound dispatcher
|
||||||
self._dispatch_task = asyncio.create_task(self._dispatch_outbound())
|
self._dispatch_task = asyncio.create_task(self._dispatch_outbound())
|
||||||
|
|
||||||
# Start channels
|
# Start channels
|
||||||
tasks = []
|
tasks = []
|
||||||
for name, channel in self.channels.items():
|
for name, channel in self.channels.items():
|
||||||
logger.info(f"Starting {name} channel...")
|
logger.info(f"Starting {name} channel...")
|
||||||
tasks.append(asyncio.create_task(self._start_channel(name, channel)))
|
tasks.append(asyncio.create_task(self._start_channel(name, channel)))
|
||||||
|
|
||||||
# Wait for all to complete (they should run forever)
|
# Wait for all to complete (they should run forever)
|
||||||
await asyncio.gather(*tasks, return_exceptions=True)
|
await asyncio.gather(*tasks, return_exceptions=True)
|
||||||
|
|
||||||
async def stop_all(self) -> None:
|
async def stop_all(self) -> None:
|
||||||
"""Stop all channels and the dispatcher."""
|
"""Stop all channels and the dispatcher."""
|
||||||
logger.info("Stopping all channels...")
|
logger.info("Stopping all channels...")
|
||||||
|
|
||||||
# Stop dispatcher
|
# Stop dispatcher
|
||||||
if self._dispatch_task:
|
if self._dispatch_task:
|
||||||
self._dispatch_task.cancel()
|
self._dispatch_task.cancel()
|
||||||
@@ -167,7 +173,7 @@ class ChannelManager:
|
|||||||
await self._dispatch_task
|
await self._dispatch_task
|
||||||
except asyncio.CancelledError:
|
except asyncio.CancelledError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
# Stop all channels
|
# Stop all channels
|
||||||
for name, channel in self.channels.items():
|
for name, channel in self.channels.items():
|
||||||
try:
|
try:
|
||||||
@@ -175,15 +181,18 @@ class ChannelManager:
|
|||||||
logger.info(f"Stopped {name} channel")
|
logger.info(f"Stopped {name} channel")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(f"Error stopping {name}: {e}")
|
logger.error(f"Error stopping {name}: {e}")
|
||||||
|
|
||||||
async def _dispatch_outbound(self) -> None:
|
async def _dispatch_outbound(self) -> None:
|
||||||
"""Dispatch outbound messages to the appropriate channel."""
|
"""Dispatch outbound messages to the appropriate channel."""
|
||||||
logger.info("Outbound dispatcher started")
|
logger.info("Outbound dispatcher started")
|
||||||
|
|
||||||
while True:
|
while True:
|
||||||
try:
|
try:
|
||||||
msg = await asyncio.wait_for(self.bus.consume_outbound(), timeout=1.0)
|
msg = await asyncio.wait_for(
|
||||||
|
self.bus.consume_outbound(),
|
||||||
|
timeout=1.0
|
||||||
|
)
|
||||||
|
|
||||||
channel = self.channels.get(msg.channel)
|
channel = self.channels.get(msg.channel)
|
||||||
if channel:
|
if channel:
|
||||||
try:
|
try:
|
||||||
@@ -192,23 +201,26 @@ class ChannelManager:
|
|||||||
logger.error(f"Error sending to {msg.channel}: {e}")
|
logger.error(f"Error sending to {msg.channel}: {e}")
|
||||||
else:
|
else:
|
||||||
logger.warning(f"Unknown channel: {msg.channel}")
|
logger.warning(f"Unknown channel: {msg.channel}")
|
||||||
|
|
||||||
except asyncio.TimeoutError:
|
except asyncio.TimeoutError:
|
||||||
continue
|
continue
|
||||||
except asyncio.CancelledError:
|
except asyncio.CancelledError:
|
||||||
break
|
break
|
||||||
|
|
||||||
def get_channel(self, name: str) -> BaseChannel | None:
|
def get_channel(self, name: str) -> BaseChannel | None:
|
||||||
"""Get a channel by name."""
|
"""Get a channel by name."""
|
||||||
return self.channels.get(name)
|
return self.channels.get(name)
|
||||||
|
|
||||||
def get_status(self) -> dict[str, Any]:
|
def get_status(self) -> dict[str, Any]:
|
||||||
"""Get status of all channels."""
|
"""Get status of all channels."""
|
||||||
return {
|
return {
|
||||||
name: {"enabled": True, "running": channel.is_running}
|
name: {
|
||||||
|
"enabled": True,
|
||||||
|
"running": channel.is_running
|
||||||
|
}
|
||||||
for name, channel in self.channels.items()
|
for name, channel in self.channels.items()
|
||||||
}
|
}
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def enabled_channels(self) -> list[str]:
|
def enabled_channels(self) -> list[str]:
|
||||||
"""Get list of enabled channel names."""
|
"""Get list of enabled channel names."""
|
||||||
|
|||||||
Reference in New Issue
Block a user