新增了Alexa渠道的所有核心功能模块,包括配置管理、请求校验、会话管理、安全验证、去重、响应格式化、渐进式响应、主动推送、提醒功能、配对绑定以及Webhook端点,并完成了插件注册和配置项定义。
152 lines
6.5 KiB
Python
152 lines
6.5 KiB
Python
import os
|
||
|
||
from yuxi.channel.extensions.alexa.types import AlexaAccount
|
||
|
||
|
||
class AlexaConfig:
|
||
|
||
ENV_MAP = {
|
||
"application_id": "ALEXA_APPLICATION_ID",
|
||
"skill_id": "ALEXA_SKILL_ID",
|
||
"oauth_client_id": "ALEXA_OAUTH_CLIENT_ID",
|
||
"oauth_client_secret": "ALEXA_OAUTH_CLIENT_SECRET",
|
||
"oauth_introspect_url": "ALEXA_OAUTH_INTROSPECT_URL",
|
||
"dm_policy": "ALEXA_DM_POLICY",
|
||
"account_linking_enabled": "ALEXA_ACCOUNT_LINKING_ENABLED",
|
||
"ssm_l_enabled": "ALEXA_SSML_ENABLED",
|
||
"progressive_response_enabled": "ALEXA_PROGRESSIVE_RESPONSE",
|
||
"proactive_events_enabled": "ALEXA_PROACTIVE_EVENTS_ENABLED",
|
||
"reminders_enabled": "ALEXA_REMINDERS_ENABLED",
|
||
"max_response_chars": "ALEXA_MAX_RESPONSE_CHARS",
|
||
"session_persistence_enabled": "ALEXA_SESSION_PERSISTENCE",
|
||
"session_timeout_seconds": "ALEXA_SESSION_TIMEOUT",
|
||
}
|
||
|
||
def list_account_ids(self, config: dict | None = None) -> list[str]:
|
||
if self._resolve_application_id():
|
||
return ["default"]
|
||
return []
|
||
|
||
def resolve_account(self, account_id: str = "default") -> AlexaAccount:
|
||
return AlexaAccount(
|
||
account_id=account_id,
|
||
application_id=self._resolve_application_id() or "",
|
||
skill_id=self._env_or_config("skill_id") or "",
|
||
account_linking_enabled=self._env_or_config("account_linking_enabled") == "true",
|
||
oauth_client_id=self._env_or_config("oauth_client_id") or "",
|
||
oauth_client_secret=self._env_or_config("oauth_client_secret") or "",
|
||
oauth_introspect_url=self._env_or_config("oauth_introspect_url") or "",
|
||
dm_policy=self._env_or_config("dm_policy") or "open",
|
||
ssm_l_enabled=self._env_or_config("ssm_l_enabled") != "false",
|
||
progressive_response_enabled=self._env_or_config("progressive_response_enabled") == "true",
|
||
progressive_response_timeout_ms=self._env_int("progressive_response_timeout_ms", 5500),
|
||
proactive_events_enabled=self._env_or_config("proactive_events_enabled") == "true",
|
||
reminders_enabled=self._env_or_config("reminders_enabled") == "true",
|
||
max_response_chars=self._env_int("max_response_chars", 1000),
|
||
session_persistence_enabled=self._env_or_config("session_persistence_enabled") == "true",
|
||
session_timeout_seconds=self._env_int("session_timeout_seconds", 30),
|
||
)
|
||
|
||
def is_configured(self, account: dict | None = None) -> bool:
|
||
return bool(self._resolve_application_id())
|
||
|
||
def _resolve_application_id(self) -> str | None:
|
||
return self._env_or_config("application_id")
|
||
|
||
def _env_or_config(self, key: str) -> str | None:
|
||
env_key = self.ENV_MAP.get(key, "")
|
||
if env_key:
|
||
val = os.getenv(env_key)
|
||
if val:
|
||
return val
|
||
return None
|
||
|
||
def _env_int(self, key: str, default: int) -> int:
|
||
val = self._env_or_config(key)
|
||
if val:
|
||
try:
|
||
return int(val)
|
||
except ValueError:
|
||
pass
|
||
return default
|
||
|
||
def config_schema(self) -> dict:
|
||
return {
|
||
"$schema": "https://json-schema.org/draft-07/schema#",
|
||
"type": "object",
|
||
"title": "Alexa 渠道配置",
|
||
"properties": {
|
||
"application_id": {
|
||
"type": "string",
|
||
"title": "Skill Application ID",
|
||
"description": "Alexa Developer Console 中的 Skill Application ID (amzn1.ask.skill.*)",
|
||
},
|
||
"skill_id": {
|
||
"type": "string",
|
||
"title": "Skill ID",
|
||
"description": "用于 Skill ID 验证、Proactive Events/Reminders API 的 Skill ID",
|
||
},
|
||
"account_linking_enabled": {
|
||
"type": "boolean",
|
||
"title": "启用 Account Linking",
|
||
"default": False,
|
||
"description": "是否强制要求 Alexa 用户通过 OAuth 2.0 绑定 ForcePilot 账号",
|
||
},
|
||
"oauth_client_id": {
|
||
"type": "string",
|
||
"title": "OAuth Client ID",
|
||
"description": "在 ForcePilot 后台创建的 OAuth Client ID",
|
||
},
|
||
"oauth_client_secret": {
|
||
"type": "string",
|
||
"title": "OAuth Client Secret",
|
||
"x-ui-password": True,
|
||
"description": "OAuth Client Secret",
|
||
},
|
||
"oauth_introspect_url": {
|
||
"type": "string",
|
||
"title": "OAuth Introspect URL",
|
||
"description": "外部 OAuth Token 验证端点 URL,留空则使用 JWT 本地验证",
|
||
},
|
||
"dm_policy": {
|
||
"type": "string",
|
||
"enum": ["open", "pairing", "allowlist", "disabled"],
|
||
"default": "open",
|
||
"title": "DM 策略",
|
||
},
|
||
"progressive_response_enabled": {
|
||
"type": "boolean",
|
||
"title": "启用渐进式响应",
|
||
"default": False,
|
||
"description": "在 LLM 处理期间先发送'正在查询…'的中间语音",
|
||
},
|
||
"proactive_events_enabled": {
|
||
"type": "boolean",
|
||
"title": "启用主动推送通知",
|
||
"default": False,
|
||
"description": "允许 ForcePilot 主动推送通知到 Alexa 设备",
|
||
},
|
||
"reminders_enabled": {
|
||
"type": "boolean",
|
||
"title": "启用提醒功能",
|
||
"default": False,
|
||
"description": "允许为用户创建定时提醒",
|
||
},
|
||
"max_response_chars": {
|
||
"type": "integer",
|
||
"title": "最大回复字符数",
|
||
"default": 1000,
|
||
"minimum": 100,
|
||
"maximum": 8000,
|
||
"description": "单次 SSML 语音响应最大字符数",
|
||
},
|
||
"session_timeout_seconds": {
|
||
"type": "integer",
|
||
"title": "Session 超时时间(秒)",
|
||
"default": 30,
|
||
"minimum": 10,
|
||
"maximum": 300,
|
||
},
|
||
},
|
||
"required": ["application_id"],
|
||
} |