mirror of
https://github.com/zhayujie/chatgpt-on-wechat.git
synced 2026-09-17 17:21:06 +08:00
fix(startup): keep the app bootable when config is partially broken
This commit is contained in:
+27
-1
@@ -280,6 +280,8 @@ def get_agent_registry() -> AgentRegistry:
|
||||
"""
|
||||
|
||||
global _registry_instance, _registry_signature
|
||||
import os
|
||||
|
||||
from config import conf
|
||||
|
||||
settings = conf()
|
||||
@@ -288,7 +290,31 @@ def get_agent_registry() -> AgentRegistry:
|
||||
if _registry_pinned and _registry_instance is not None:
|
||||
return _registry_instance
|
||||
if _registry_instance is None or _registry_signature != signature:
|
||||
_registry_instance = AgentRegistry.from_config(settings)
|
||||
try:
|
||||
_registry_instance = AgentRegistry.from_config(settings)
|
||||
except AgentRegistryError:
|
||||
# An invalid `agents`/`default_agent_id` block would otherwise
|
||||
# bubble all the way up through load_config() and take the whole
|
||||
# process down before the web console can bind — leaving a
|
||||
# desktop user with no UI to fix the very config that is broken.
|
||||
# Fall back to the default single agent so the app still starts;
|
||||
# the console can then edit the bad block. Source deployments
|
||||
# keep failing loudly so the developer sees the error at once.
|
||||
if os.environ.get("COW_DESKTOP") != "1":
|
||||
raise
|
||||
from common.log import logger
|
||||
|
||||
logger.error(
|
||||
"[AgentRegistry] invalid 'agents' config; ignoring it and "
|
||||
"starting with the default agent. Fix it in the console.",
|
||||
exc_info=True,
|
||||
)
|
||||
fallback = {
|
||||
k: v
|
||||
for k, v in dict(settings).items()
|
||||
if k not in ("agents", "default_agent_id")
|
||||
}
|
||||
_registry_instance = AgentRegistry.from_config(fallback)
|
||||
_registry_signature = signature
|
||||
return _registry_instance
|
||||
|
||||
|
||||
@@ -82,7 +82,18 @@ class ChannelManager:
|
||||
with self._lock:
|
||||
channels = []
|
||||
for name in channel_names:
|
||||
ch = channel_factory.create_channel(name)
|
||||
# One misconfigured channel (e.g. wechatcom_app without its
|
||||
# corp_id/token/aes_key) must not take the whole process down:
|
||||
# instantiating it can raise while parsing config. The web
|
||||
# console in particular has to come up so the desktop shell can
|
||||
# surface the error and let the user fix the config. Skip the
|
||||
# broken channel and keep the rest.
|
||||
try:
|
||||
ch = channel_factory.create_channel(name)
|
||||
except Exception as e:
|
||||
logger.error(f"[ChannelManager] Failed to create channel '{name}', skipping it: {e}")
|
||||
logger.exception(e)
|
||||
continue
|
||||
ch.cloud_mode = self.cloud_mode
|
||||
self._channels[name] = ch
|
||||
channels.append((name, ch))
|
||||
|
||||
@@ -40,6 +40,25 @@ class WechatComAppChannel(ChatChannel):
|
||||
logger.info(
|
||||
"[wechatcom] Initializing WeCom app channel, corp_id: {}, agent_id: {}".format(self.corp_id, self.agent_id)
|
||||
)
|
||||
# Fail fast with a readable message when the channel is enabled but its
|
||||
# required credentials are missing. Otherwise WeChatCrypto concatenates
|
||||
# a None aes_key with a string and raises an opaque
|
||||
# "unsupported operand type(s) for +: 'NoneType' and 'str'".
|
||||
missing = [
|
||||
key
|
||||
for key, val in (
|
||||
("wechatcom_corp_id", self.corp_id),
|
||||
("wechatcomapp_token", self.token),
|
||||
("wechatcomapp_aes_key", self.aes_key),
|
||||
)
|
||||
if not val
|
||||
]
|
||||
if missing:
|
||||
raise RuntimeError(
|
||||
"[wechatcom] WeCom app channel is enabled but missing required config: "
|
||||
+ ", ".join(missing)
|
||||
+ ". Fill them in config.json or remove 'wechatcom_app' from channel_type."
|
||||
)
|
||||
self.crypto = WeChatCrypto(self.token, self.aes_key, self.corp_id)
|
||||
self.client = WechatComAppClient(self.corp_id, self.secret)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user