ForcePilot/backend/package/yuxi/channel/extensions/alexa/config.py
Kris 37493b6da6 feat(alexa): 新增Amazon Alexa渠道插件完整实现
新增了Alexa渠道的所有核心功能模块,包括配置管理、请求校验、会话管理、安全验证、去重、响应格式化、渐进式响应、主动推送、提醒功能、配对绑定以及Webhook端点,并完成了插件注册和配置项定义。
2026-05-21 10:38:31 +08:00

152 lines
6.5 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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"],
}