@downcity/plugins 1.0.254 → 1.0.280
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.
- package/bin/builtin/BuiltinPluginReadmes.d.ts +14 -0
- package/bin/builtin/BuiltinPluginReadmes.d.ts.map +1 -0
- package/bin/builtin/BuiltinPluginReadmes.js +58 -0
- package/bin/builtin/BuiltinPluginReadmes.js.map +1 -0
- package/bin/builtin/BuiltinPluginTypes.d.ts +48 -0
- package/bin/builtin/BuiltinPluginTypes.d.ts.map +1 -0
- package/bin/builtin/BuiltinPluginTypes.js +161 -0
- package/bin/builtin/BuiltinPluginTypes.js.map +1 -0
- package/bin/builtin/PluginSettingsDefinitions.d.ts +9 -0
- package/bin/builtin/PluginSettingsDefinitions.d.ts.map +1 -0
- package/bin/builtin/PluginSettingsDefinitions.js +41 -0
- package/bin/builtin/PluginSettingsDefinitions.js.map +1 -0
- package/bin/builtin/main/PluginSettingsMain.d.ts +6 -0
- package/bin/builtin/main/PluginSettingsMain.d.ts.map +1 -0
- package/bin/builtin/main/PluginSettingsMain.js +65 -0
- package/bin/builtin/main/PluginSettingsMain.js.map +1 -0
- package/bin/builtin/renderer/PluginSettingsRenderer.d.ts +6 -0
- package/bin/builtin/renderer/PluginSettingsRenderer.d.ts.map +1 -0
- package/bin/builtin/renderer/PluginSettingsRenderer.js +76 -0
- package/bin/builtin/renderer/PluginSettingsRenderer.js.map +1 -0
- package/bin/builtin/types/PluginSettings.d.ts +35 -0
- package/bin/builtin/types/PluginSettings.d.ts.map +1 -0
- package/bin/builtin/types/PluginSettings.js +3 -0
- package/bin/builtin/types/PluginSettings.js.map +1 -0
- package/bin/chat/ChatPlugin.d.ts +12 -28
- package/bin/chat/ChatPlugin.d.ts.map +1 -1
- package/bin/chat/ChatPlugin.js +97 -49
- package/bin/chat/ChatPlugin.js.map +1 -1
- package/bin/chat/access/ChatAccessRuntime.js +1 -1
- package/bin/chat/access/ChatAccessRuntime.js.map +1 -1
- package/bin/chat/access/ChatAccessSchema.d.ts +2 -2
- package/bin/chat/access/ChatAccessSchema.d.ts.map +1 -1
- package/bin/chat/access/ChatAccessSchema.js +3 -3
- package/bin/chat/access/ChatAccessSchema.js.map +1 -1
- package/bin/chat/access/ChatAccessService.d.ts +2 -2
- package/bin/chat/access/ChatAccessService.d.ts.map +1 -1
- package/bin/chat/access/ChatAccessService.js +4 -4
- package/bin/chat/access/ChatAccessService.js.map +1 -1
- package/bin/chat/access/ChatAccessStore.d.ts +3 -3
- package/bin/chat/access/ChatAccessStore.d.ts.map +1 -1
- package/bin/chat/access/ChatAccessStore.js +17 -8
- package/bin/chat/access/ChatAccessStore.js.map +1 -1
- package/bin/chat/channels/BaseChatChannel.d.ts +1 -0
- package/bin/chat/channels/BaseChatChannel.d.ts.map +1 -1
- package/bin/chat/channels/BaseChatChannel.js +2 -0
- package/bin/chat/channels/BaseChatChannel.js.map +1 -1
- package/bin/chat/channels/RuntimeChannel.d.ts +4 -4
- package/bin/chat/channels/RuntimeChannel.d.ts.map +1 -1
- package/bin/chat/channels/RuntimeChannel.js +8 -8
- package/bin/chat/channels/RuntimeChannel.js.map +1 -1
- package/bin/chat/channels/feishu/Feishu.js +1 -1
- package/bin/chat/channels/feishu/Feishu.js.map +1 -1
- package/bin/chat/channels/feishu/FeishuPlatformClient.d.ts +1 -0
- package/bin/chat/channels/feishu/FeishuPlatformClient.d.ts.map +1 -1
- package/bin/chat/channels/feishu/FeishuPlatformClient.js +3 -0
- package/bin/chat/channels/feishu/FeishuPlatformClient.js.map +1 -1
- package/bin/chat/channels/feishu/FeishuPlatformLookup.d.ts +2 -0
- package/bin/chat/channels/feishu/FeishuPlatformLookup.d.ts.map +1 -1
- package/bin/chat/channels/feishu/FeishuPlatformLookup.js +1 -1
- package/bin/chat/channels/feishu/FeishuPlatformLookup.js.map +1 -1
- package/bin/chat/channels/qq/QQ.d.ts.map +1 -1
- package/bin/chat/channels/qq/QQ.js +3 -2
- package/bin/chat/channels/qq/QQ.js.map +1 -1
- package/bin/chat/channels/qq/QQEventCapture.d.ts +1 -1
- package/bin/chat/channels/qq/QQEventCapture.d.ts.map +1 -1
- package/bin/chat/channels/qq/QQEventCapture.js +3 -3
- package/bin/chat/channels/qq/QQEventCapture.js.map +1 -1
- package/bin/chat/channels/qq/QQInboundDedupe.d.ts +1 -1
- package/bin/chat/channels/qq/QQInboundDedupe.d.ts.map +1 -1
- package/bin/chat/channels/qq/QQInboundDedupe.js +1 -1
- package/bin/chat/channels/qq/QQInboundDedupe.js.map +1 -1
- package/bin/chat/channels/qq/QQMessageHandler.d.ts +4 -0
- package/bin/chat/channels/qq/QQMessageHandler.d.ts.map +1 -1
- package/bin/chat/channels/qq/QQMessageHandler.js +2 -0
- package/bin/chat/channels/qq/QQMessageHandler.js.map +1 -1
- package/bin/chat/channels/qq/QQSupport.d.ts +4 -0
- package/bin/chat/channels/qq/QQSupport.d.ts.map +1 -1
- package/bin/chat/channels/qq/QQSupport.js +1 -0
- package/bin/chat/channels/qq/QQSupport.js.map +1 -1
- package/bin/chat/channels/qq/VoiceInput.d.ts +3 -0
- package/bin/chat/channels/qq/VoiceInput.d.ts.map +1 -1
- package/bin/chat/channels/qq/VoiceInput.js +1 -1
- package/bin/chat/channels/qq/VoiceInput.js.map +1 -1
- package/bin/chat/channels/telegram/ApiClient.d.ts +3 -1
- package/bin/chat/channels/telegram/ApiClient.d.ts.map +1 -1
- package/bin/chat/channels/telegram/ApiClient.js +4 -2
- package/bin/chat/channels/telegram/ApiClient.js.map +1 -1
- package/bin/chat/channels/telegram/StateStore.d.ts +1 -1
- package/bin/chat/channels/telegram/StateStore.d.ts.map +1 -1
- package/bin/chat/channels/telegram/StateStore.js +2 -2
- package/bin/chat/channels/telegram/StateStore.js.map +1 -1
- package/bin/chat/channels/telegram/TelegramPlatformClient.d.ts.map +1 -1
- package/bin/chat/channels/telegram/TelegramPlatformClient.js +2 -1
- package/bin/chat/channels/telegram/TelegramPlatformClient.js.map +1 -1
- package/bin/chat/main/ChatPluginMain.d.ts +4 -0
- package/bin/chat/main/ChatPluginMain.d.ts.map +1 -0
- package/bin/chat/main/ChatPluginMain.js +137 -0
- package/bin/chat/main/ChatPluginMain.js.map +1 -0
- package/bin/chat/renderer/ChatPluginRenderer.d.ts +4 -0
- package/bin/chat/renderer/ChatPluginRenderer.d.ts.map +1 -0
- package/bin/chat/renderer/ChatPluginRenderer.js +105 -0
- package/bin/chat/renderer/ChatPluginRenderer.js.map +1 -0
- package/bin/chat/runtime/ChannelContextStore.d.ts +2 -2
- package/bin/chat/runtime/ChannelContextStore.js +20 -20
- package/bin/chat/runtime/ChannelContextStore.js.map +1 -1
- package/bin/chat/runtime/ChatActionExecution.js +6 -6
- package/bin/chat/runtime/ChatActionExecution.js.map +1 -1
- package/bin/chat/runtime/ChatChannelConfig.d.ts.map +1 -1
- package/bin/chat/runtime/ChatChannelConfig.js +7 -12
- package/bin/chat/runtime/ChatChannelConfig.js.map +1 -1
- package/bin/chat/runtime/ChatChannelCore.d.ts +3 -3
- package/bin/chat/runtime/ChatChannelCore.d.ts.map +1 -1
- package/bin/chat/runtime/ChatChannelCore.js +5 -5
- package/bin/chat/runtime/ChatChannelCore.js.map +1 -1
- package/bin/chat/runtime/ChatHistoryStore.d.ts +1 -1
- package/bin/chat/runtime/ChatHistoryStore.js +7 -7
- package/bin/chat/runtime/ChatHistoryStore.js.map +1 -1
- package/bin/chat/runtime/ChatMetaStore.d.ts +1 -1
- package/bin/chat/runtime/ChatMetaStore.js +1 -1
- package/bin/chat/runtime/ChatPluginActionRegistry.d.ts +1 -1
- package/bin/chat/runtime/ChatPluginActionRegistry.d.ts.map +1 -1
- package/bin/chat/runtime/ChatPluginActionRegistry.js +9 -9
- package/bin/chat/runtime/ChatPluginActionRegistry.js.map +1 -1
- package/bin/chat/runtime/ChatQueue.d.ts +3 -38
- package/bin/chat/runtime/ChatQueue.d.ts.map +1 -1
- package/bin/chat/runtime/ChatQueue.js +3 -51
- package/bin/chat/runtime/ChatQueue.js.map +1 -1
- package/bin/chat/runtime/ChatQueueStore.d.ts +5 -16
- package/bin/chat/runtime/ChatQueueStore.d.ts.map +1 -1
- package/bin/chat/runtime/ChatQueueStore.js +8 -22
- package/bin/chat/runtime/ChatQueueStore.js.map +1 -1
- package/bin/chat/runtime/ChatQueueWorker.d.ts +1 -1
- package/bin/chat/runtime/ChatQueueWorker.d.ts.map +1 -1
- package/bin/chat/runtime/ChatQueueWorker.js +1 -2
- package/bin/chat/runtime/ChatQueueWorker.js.map +1 -1
- package/bin/chat/runtime/ChatSessionDelete.d.ts +3 -3
- package/bin/chat/runtime/ChatSessionDelete.js +4 -4
- package/bin/chat/runtime/ChatSessionDelete.js.map +1 -1
- package/bin/chat/runtime/ChatStorage.d.ts +7 -7
- package/bin/chat/runtime/ChatStorage.js +24 -24
- package/bin/chat/runtime/ChatStorage.js.map +1 -1
- package/bin/chat/types/ChatAccess.d.ts +2 -2
- package/bin/chat/types/ChatAccess.d.ts.map +1 -1
- package/bin/chat/types/ChatCommand.d.ts +1 -1
- package/bin/chat/types/ChatPluginChannelConfig.d.ts +57 -0
- package/bin/chat/types/ChatPluginChannelConfig.d.ts.map +1 -0
- package/bin/chat/types/ChatPluginChannelConfig.js +3 -0
- package/bin/chat/types/ChatPluginChannelConfig.js.map +1 -0
- package/bin/chat/types/ChatPluginConfig.d.ts +19 -0
- package/bin/chat/types/ChatPluginConfig.d.ts.map +1 -0
- package/bin/chat/types/ChatPluginConfig.js +3 -0
- package/bin/chat/types/ChatPluginConfig.js.map +1 -0
- package/bin/chat/types/ChatPluginOptions.d.ts +4 -4
- package/bin/chat/types/ChatPluginOptions.d.ts.map +1 -1
- package/bin/chat/types/ChatPluginOptions.js +1 -1
- package/bin/chat/types/ChatPluginProfile.d.ts +39 -0
- package/bin/chat/types/ChatPluginProfile.d.ts.map +1 -0
- package/bin/chat/types/ChatPluginProfile.js +3 -0
- package/bin/chat/types/ChatPluginProfile.js.map +1 -0
- package/bin/chat/types/ChatPluginRenderer.d.ts +17 -0
- package/bin/chat/types/ChatPluginRenderer.d.ts.map +1 -0
- package/bin/chat/types/ChatPluginRenderer.js +3 -0
- package/bin/chat/types/ChatPluginRenderer.js.map +1 -0
- package/bin/chat/types/ChatRuntime.d.ts +11 -0
- package/bin/chat/types/ChatRuntime.d.ts.map +1 -1
- package/bin/chat/types/ChatRuntimeAccount.d.ts +3 -3
- package/bin/chat/types/ChatRuntimeAccount.d.ts.map +1 -1
- package/bin/chat/types/ChatRuntimeAccount.js +2 -2
- package/bin/chat/types/ChatStorage.d.ts +2 -2
- package/bin/chat/types/ChatStorage.d.ts.map +1 -1
- package/bin/chat.d.ts +3 -4
- package/bin/chat.d.ts.map +1 -1
- package/bin/chat.js +1 -2
- package/bin/chat.js.map +1 -1
- package/bin/contact/Action.js +5 -5
- package/bin/contact/Action.js.map +1 -1
- package/bin/contact/ContactPlugin.js +15 -15
- package/bin/contact/ContactPlugin.js.map +1 -1
- package/bin/contact/runtime/ChatRuntime.js +3 -3
- package/bin/contact/runtime/ChatRuntime.js.map +1 -1
- package/bin/contact/runtime/ContactStore.d.ts +8 -8
- package/bin/contact/runtime/ContactStore.d.ts.map +1 -1
- package/bin/contact/runtime/ContactStore.js +20 -20
- package/bin/contact/runtime/ContactStore.js.map +1 -1
- package/bin/contact/runtime/EndpointNotice.js +2 -2
- package/bin/contact/runtime/EndpointNotice.js.map +1 -1
- package/bin/contact/runtime/InboxStore.d.ts +6 -6
- package/bin/contact/runtime/InboxStore.d.ts.map +1 -1
- package/bin/contact/runtime/InboxStore.js +16 -16
- package/bin/contact/runtime/InboxStore.js.map +1 -1
- package/bin/contact/runtime/LinkApproval.js +14 -14
- package/bin/contact/runtime/LinkApproval.js.map +1 -1
- package/bin/contact/runtime/LinkStore.d.ts +2 -2
- package/bin/contact/runtime/LinkStore.d.ts.map +1 -1
- package/bin/contact/runtime/LinkStore.js +5 -5
- package/bin/contact/runtime/LinkStore.js.map +1 -1
- package/bin/contact/runtime/Paths.d.ts +15 -15
- package/bin/contact/runtime/Paths.d.ts.map +1 -1
- package/bin/contact/runtime/Paths.js +29 -29
- package/bin/contact/runtime/Paths.js.map +1 -1
- package/bin/contact/runtime/ShareBundle.d.ts +1 -1
- package/bin/contact/runtime/ShareBundle.d.ts.map +1 -1
- package/bin/contact/runtime/ShareBundle.js +4 -4
- package/bin/contact/runtime/ShareBundle.js.map +1 -1
- package/bin/contact/types/ContactApproval.d.ts +2 -2
- package/bin/contact/types/ContactApproval.d.ts.map +1 -1
- package/bin/image/ImagePlugin.d.ts +1 -4
- package/bin/image/ImagePlugin.d.ts.map +1 -1
- package/bin/image/ImagePlugin.js +26 -34
- package/bin/image/ImagePlugin.js.map +1 -1
- package/bin/image/runtime/ImageResultStorage.d.ts +2 -2
- package/bin/image/runtime/ImageResultStorage.d.ts.map +1 -1
- package/bin/image/runtime/ImageResultStorage.js +15 -38
- package/bin/image/runtime/ImageResultStorage.js.map +1 -1
- package/bin/image/types/ImagePlugin.d.ts +23 -16
- package/bin/image/types/ImagePlugin.d.ts.map +1 -1
- package/bin/image/types/ImagePlugin.js +1 -1
- package/bin/image.d.ts +1 -1
- package/bin/image.d.ts.map +1 -1
- package/bin/index.d.ts +2 -0
- package/bin/index.d.ts.map +1 -1
- package/bin/index.js +1 -0
- package/bin/index.js.map +1 -1
- package/bin/memory/MemoryPlugin.d.ts +1 -1
- package/bin/memory/MemoryPlugin.d.ts.map +1 -1
- package/bin/memory/MemoryPlugin.js +17 -7
- package/bin/memory/MemoryPlugin.js.map +1 -1
- package/bin/memory/types/Memory.d.ts +10 -4
- package/bin/memory/types/Memory.d.ts.map +1 -1
- package/bin/memory.d.ts +1 -1
- package/bin/memory.d.ts.map +1 -1
- package/bin/renderers.d.ts +5 -0
- package/bin/renderers.d.ts.map +1 -0
- package/bin/renderers.js +12 -0
- package/bin/renderers.js.map +1 -0
- package/bin/sound/Plugin.d.ts +2 -5
- package/bin/sound/Plugin.d.ts.map +1 -1
- package/bin/sound/Plugin.js +27 -31
- package/bin/sound/Plugin.js.map +1 -1
- package/bin/sound/types/SoundPlugin.d.ts +22 -15
- package/bin/sound/types/SoundPlugin.d.ts.map +1 -1
- package/bin/sound/types/SoundPlugin.js +2 -2
- package/bin/sound.d.ts +1 -1
- package/bin/sound.d.ts.map +1 -1
- package/bin/task/Action.d.ts +6 -6
- package/bin/task/Action.d.ts.map +1 -1
- package/bin/task/Action.js +21 -21
- package/bin/task/Action.js.map +1 -1
- package/bin/task/PROMPT.d.ts +1 -1
- package/bin/task/PROMPT.d.ts.map +1 -1
- package/bin/task/PROMPT.js +1 -1
- package/bin/task/PROMPT.js.map +1 -1
- package/bin/task/Scheduler.js +8 -8
- package/bin/task/Scheduler.js.map +1 -1
- package/bin/task/TaskPlugin.d.ts +7 -14
- package/bin/task/TaskPlugin.d.ts.map +1 -1
- package/bin/task/TaskPlugin.js +54 -43
- package/bin/task/TaskPlugin.js.map +1 -1
- package/bin/task/runtime/Model.d.ts +1 -5
- package/bin/task/runtime/Model.d.ts.map +1 -1
- package/bin/task/runtime/Model.js +2 -13
- package/bin/task/runtime/Model.js.map +1 -1
- package/bin/task/runtime/Paths.d.ts +7 -7
- package/bin/task/runtime/Paths.d.ts.map +1 -1
- package/bin/task/runtime/Paths.js +11 -11
- package/bin/task/runtime/Paths.js.map +1 -1
- package/bin/task/runtime/Runner.d.ts +1 -1
- package/bin/task/runtime/Runner.d.ts.map +1 -1
- package/bin/task/runtime/Runner.js +4 -5
- package/bin/task/runtime/Runner.js.map +1 -1
- package/bin/task/runtime/Store.d.ts +9 -9
- package/bin/task/runtime/Store.d.ts.map +1 -1
- package/bin/task/runtime/Store.js +17 -17
- package/bin/task/runtime/Store.js.map +1 -1
- package/bin/task/runtime/TaskActionExecution.js +6 -6
- package/bin/task/runtime/TaskActionExecution.js.map +1 -1
- package/bin/task/runtime/TaskPluginActionRegistry.js +1 -1
- package/bin/task/runtime/TaskPluginActionRegistry.js.map +1 -1
- package/bin/task/runtime/TaskRunnerRound.d.ts +0 -1
- package/bin/task/runtime/TaskRunnerRound.d.ts.map +1 -1
- package/bin/task/runtime/TaskRunnerRound.js +8 -3
- package/bin/task/runtime/TaskRunnerRound.js.map +1 -1
- package/bin/task/runtime/TaskRunnerScript.d.ts +0 -4
- package/bin/task/runtime/TaskRunnerScript.d.ts.map +1 -1
- package/bin/task/runtime/TaskRunnerScript.js +0 -1
- package/bin/task/runtime/TaskRunnerScript.js.map +1 -1
- package/bin/task/runtime/TaskRunnerSession.d.ts +2 -3
- package/bin/task/runtime/TaskRunnerSession.d.ts.map +1 -1
- package/bin/task/runtime/TaskRunnerSession.js +2 -4
- package/bin/task/runtime/TaskRunnerSession.js.map +1 -1
- package/bin/task/types/TaskWorkspaceRuntime.d.ts +10 -0
- package/bin/task/types/TaskWorkspaceRuntime.d.ts.map +1 -0
- package/bin/task/types/TaskWorkspaceRuntime.js +3 -0
- package/bin/task/types/TaskWorkspaceRuntime.js.map +1 -0
- package/bin/web/Plugin.d.ts +2 -6
- package/bin/web/Plugin.d.ts.map +1 -1
- package/bin/web/Plugin.js +21 -17
- package/bin/web/Plugin.js.map +1 -1
- package/bin/web/providers/PlaywrightBrowserProvider.d.ts.map +1 -1
- package/bin/web/providers/PlaywrightBrowserProvider.js +59 -14
- package/bin/web/providers/PlaywrightBrowserProvider.js.map +1 -1
- package/bin/web/types/WebPlugin.d.ts +15 -9
- package/bin/web/types/WebPlugin.d.ts.map +1 -1
- package/bin/web.d.ts +1 -1
- package/bin/web.d.ts.map +1 -1
- package/bin/workboard/runtime/Collector.js +1 -1
- package/bin/workboard/runtime/Collector.js.map +1 -1
- package/package.json +29 -20
- package/scripts/chat-access.test.mjs +3 -2
- package/scripts/chat-channel-config.test.mjs +3 -3
- package/scripts/chat-storage.test.mjs +10 -14
- package/scripts/memory-plugin.test.mjs +9 -32
- package/scripts/playwright-browser-provider.test.mjs +260 -0
- package/scripts/plugin-main.test.mjs +101 -0
- package/scripts/plugin-subpaths.test.mjs +28 -0
- package/scripts/sound-plugin.test.mjs +21 -9
- package/scripts/unrestricted-sandbox-approval.test.mjs +1 -1
- package/scripts/web-plugin.test.mjs +43 -186
- package/src/builtin/BuiltinPluginReadmes.ts +58 -0
- package/src/builtin/BuiltinPluginTypes.ts +260 -0
- package/src/builtin/PluginSettingsDefinitions.ts +45 -0
- package/src/builtin/main/PluginSettingsMain.ts +75 -0
- package/src/builtin/renderer/PluginSettingsRenderer.tsx +110 -0
- package/src/builtin/types/PluginSettings.ts +46 -0
- package/src/chat/ChatPlugin.ts +99 -51
- package/src/chat/access/ChatAccessRuntime.ts +1 -1
- package/src/chat/access/ChatAccessSchema.ts +5 -5
- package/src/chat/access/ChatAccessService.ts +4 -4
- package/src/chat/access/ChatAccessStore.ts +17 -9
- package/src/chat/channels/BaseChatChannel.ts +2 -0
- package/src/chat/channels/RuntimeChannel.ts +9 -9
- package/src/chat/channels/feishu/Feishu.ts +1 -1
- package/src/chat/channels/feishu/FeishuPlatformClient.ts +3 -0
- package/src/chat/channels/feishu/FeishuPlatformLookup.ts +3 -1
- package/src/chat/channels/qq/QQ.ts +3 -2
- package/src/chat/channels/qq/QQEventCapture.ts +3 -3
- package/src/chat/channels/qq/QQInboundDedupe.ts +2 -3
- package/src/chat/channels/qq/QQMessageHandler.ts +6 -0
- package/src/chat/channels/qq/QQSupport.ts +5 -0
- package/src/chat/channels/qq/VoiceInput.ts +5 -1
- package/src/chat/channels/telegram/ApiClient.ts +10 -3
- package/src/chat/channels/telegram/StateStore.ts +2 -2
- package/src/chat/channels/telegram/TelegramPlatformClient.ts +2 -1
- package/src/chat/main/ChatPluginMain.ts +163 -0
- package/src/chat/renderer/ChatPluginRenderer.tsx +149 -0
- package/src/chat/runtime/ChannelContextStore.ts +20 -20
- package/src/chat/runtime/ChatActionExecution.ts +6 -6
- package/src/chat/runtime/ChatChannelConfig.ts +7 -14
- package/src/chat/runtime/ChatChannelCore.ts +9 -9
- package/src/chat/runtime/ChatHistoryStore.ts +7 -7
- package/src/chat/runtime/ChatMetaStore.ts +1 -1
- package/src/chat/runtime/ChatPluginActionRegistry.ts +10 -10
- package/src/chat/runtime/ChatQueue.ts +2 -69
- package/src/chat/runtime/ChatQueueStore.ts +10 -26
- package/src/chat/runtime/ChatQueueWorker.ts +2 -5
- package/src/chat/runtime/ChatSessionDelete.ts +4 -4
- package/src/chat/runtime/ChatStorage.ts +24 -24
- package/src/chat/types/ChatAccess.ts +2 -2
- package/src/chat/types/ChatCommand.ts +1 -1
- package/src/chat/types/ChatPluginChannelConfig.ts +63 -0
- package/src/chat/types/ChatPluginConfig.ts +21 -0
- package/src/chat/types/ChatPluginOptions.ts +4 -4
- package/src/chat/types/ChatPluginProfile.ts +52 -0
- package/src/chat/types/ChatPluginRenderer.ts +25 -0
- package/src/chat/types/ChatRuntime.ts +14 -0
- package/src/chat/types/ChatRuntimeAccount.ts +3 -3
- package/src/chat/types/ChatStorage.ts +2 -2
- package/src/chat.ts +6 -14
- package/src/contact/Action.ts +5 -5
- package/src/contact/ContactPlugin.ts +15 -15
- package/src/contact/runtime/ChatRuntime.ts +3 -3
- package/src/contact/runtime/ContactStore.ts +20 -20
- package/src/contact/runtime/EndpointNotice.ts +2 -2
- package/src/contact/runtime/InboxStore.ts +16 -16
- package/src/contact/runtime/LinkApproval.ts +16 -16
- package/src/contact/runtime/LinkStore.ts +5 -5
- package/src/contact/runtime/Paths.ts +29 -29
- package/src/contact/runtime/ShareBundle.ts +5 -5
- package/src/contact/types/ContactApproval.ts +2 -2
- package/src/image/ImagePlugin.ts +30 -33
- package/src/image/runtime/ImageResultStorage.ts +36 -62
- package/src/image/types/ImagePlugin.ts +25 -19
- package/src/image.ts +2 -0
- package/src/index.ts +8 -0
- package/src/memory/MemoryPlugin.ts +17 -5
- package/src/memory/types/Memory.ts +11 -4
- package/src/memory.ts +1 -0
- package/src/renderers.ts +18 -0
- package/src/sound/Plugin.ts +34 -33
- package/src/sound/types/SoundPlugin.ts +24 -19
- package/src/sound.ts +2 -0
- package/src/task/Action.ts +27 -27
- package/src/task/PROMPT.ts +1 -1
- package/src/task/PROMPT.ts.txt +5 -6
- package/src/task/Scheduler.ts +8 -8
- package/src/task/TaskPlugin.ts +55 -46
- package/src/task/runtime/Model.ts +3 -13
- package/src/task/runtime/Paths.ts +11 -11
- package/src/task/runtime/Runner.ts +5 -6
- package/src/task/runtime/Store.ts +22 -22
- package/src/task/runtime/TaskActionExecution.ts +6 -6
- package/src/task/runtime/TaskPluginActionRegistry.ts +1 -1
- package/src/task/runtime/TaskRunnerRound.ts +13 -4
- package/src/task/runtime/TaskRunnerScript.ts +0 -5
- package/src/task/runtime/TaskRunnerSession.ts +10 -8
- package/src/task/types/TaskWorkspaceRuntime.ts +12 -0
- package/src/web/Plugin.ts +23 -22
- package/src/web/providers/PlaywrightBrowserProvider.ts +93 -17
- package/src/web/types/WebPlugin.ts +16 -13
- package/src/web.ts +1 -0
- package/src/workboard/runtime/Collector.ts +1 -1
- package/tsconfig.json +4 -1
- package/LICENSE +0 -183
- package/bin/chat/Index.d.ts +0 -15
- package/bin/chat/Index.d.ts.map +0 -1
- package/bin/chat/Index.js +0 -11
- package/bin/chat/Index.js.map +0 -1
- package/bin/chat/config/ChatPluginConfig.d.ts +0 -67
- package/bin/chat/config/ChatPluginConfig.d.ts.map +0 -1
- package/bin/chat/config/ChatPluginConfig.js +0 -237
- package/bin/chat/config/ChatPluginConfig.js.map +0 -1
- package/bin/chat/types/ChatPluginResource.d.ts +0 -68
- package/bin/chat/types/ChatPluginResource.d.ts.map +0 -1
- package/bin/chat/types/ChatPluginResource.js +0 -10
- package/bin/chat/types/ChatPluginResource.js.map +0 -1
- package/bin/contact/Index.d.ts +0 -8
- package/bin/contact/Index.d.ts.map +0 -1
- package/bin/contact/Index.js +0 -8
- package/bin/contact/Index.js.map +0 -1
- package/bin/memory/Index.d.ts +0 -11
- package/bin/memory/Index.d.ts.map +0 -1
- package/bin/memory/Index.js +0 -11
- package/bin/memory/Index.js.map +0 -1
- package/bin/skill/Command.d.ts +0 -29
- package/bin/skill/Command.d.ts.map +0 -1
- package/bin/skill/Command.js +0 -35
- package/bin/skill/Command.js.map +0 -1
- package/bin/task/Index.d.ts +0 -9
- package/bin/task/Index.d.ts.map +0 -1
- package/bin/task/Index.js +0 -9
- package/bin/task/Index.js.map +0 -1
- package/src/chat/Index.ts +0 -36
- package/src/chat/config/ChatPluginConfig.ts +0 -266
- package/src/chat/types/ChatPluginResource.ts +0 -95
- package/src/contact/Index.ts +0 -8
- package/src/memory/Index.ts +0 -14
- package/src/skill/Command.ts +0 -58
- package/src/task/Index.ts +0 -8
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* 关键点(中文)
|
|
5
5
|
* - channel 对象是 ChatPlugin 的运行态配置单元。
|
|
6
6
|
* - env 由 channel 自己读取,ChatPlugin 不理解平台字段。
|
|
7
|
-
* -
|
|
7
|
+
* - 配置已由宿主解析为构造参数,channel 不访问其他外部 Store。
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
10
|
import type { PluginContext } from "@downcity/agent";
|
|
@@ -38,7 +38,7 @@ export interface BaseChatChannelOptions {
|
|
|
38
38
|
*/
|
|
39
39
|
env?: ChatChannelEnv;
|
|
40
40
|
/**
|
|
41
|
-
*
|
|
41
|
+
* Plugin profile 或 SDK 调用方提供的稳定 ID。
|
|
42
42
|
*/
|
|
43
43
|
id?: string;
|
|
44
44
|
/**
|
|
@@ -55,13 +55,13 @@ abstract class BaseRuntimeChatChannel implements ChatChannel {
|
|
|
55
55
|
|
|
56
56
|
protected enabled: boolean;
|
|
57
57
|
protected env: ChatChannelEnv;
|
|
58
|
-
protected
|
|
58
|
+
protected channel_id: string;
|
|
59
59
|
protected display_name: string;
|
|
60
60
|
|
|
61
61
|
protected constructor(options: BaseChatChannelOptions = {}) {
|
|
62
62
|
this.enabled = options.enabled !== false;
|
|
63
63
|
this.env = options.env || {};
|
|
64
|
-
this.
|
|
64
|
+
this.channel_id = String(options.id || "").trim();
|
|
65
65
|
this.display_name = String(options.name || "").trim();
|
|
66
66
|
}
|
|
67
67
|
|
|
@@ -69,8 +69,8 @@ abstract class BaseRuntimeChatChannel implements ChatChannel {
|
|
|
69
69
|
return this.enabled;
|
|
70
70
|
}
|
|
71
71
|
|
|
72
|
-
|
|
73
|
-
return this.
|
|
72
|
+
get_channel_id(_context: PluginContext): string {
|
|
73
|
+
return this.channel_id;
|
|
74
74
|
}
|
|
75
75
|
|
|
76
76
|
protected nowIso(): string {
|
|
@@ -110,7 +110,7 @@ export class TelegramChannel extends BaseRuntimeChatChannel {
|
|
|
110
110
|
if (!token) return null;
|
|
111
111
|
const now = this.nowIso();
|
|
112
112
|
return {
|
|
113
|
-
id: this.
|
|
113
|
+
id: this.channel_id || "chat-sdk-telegram",
|
|
114
114
|
channel: "telegram",
|
|
115
115
|
name: this.display_name || "telegram",
|
|
116
116
|
bot_token: token,
|
|
@@ -163,7 +163,7 @@ export class FeishuChannel extends BaseRuntimeChatChannel {
|
|
|
163
163
|
if (!appId || !appSecret) return null;
|
|
164
164
|
const now = this.nowIso();
|
|
165
165
|
return {
|
|
166
|
-
id: this.
|
|
166
|
+
id: this.channel_id || "chat-sdk-feishu",
|
|
167
167
|
channel: "feishu",
|
|
168
168
|
name: this.display_name || "feishu",
|
|
169
169
|
app_id: appId,
|
|
@@ -218,7 +218,7 @@ export class QqChannel extends BaseRuntimeChatChannel {
|
|
|
218
218
|
if (!appId || !appSecret) return null;
|
|
219
219
|
const now = this.nowIso();
|
|
220
220
|
return {
|
|
221
|
-
id: this.
|
|
221
|
+
id: this.channel_id || "chat-sdk-qq",
|
|
222
222
|
channel: "qq",
|
|
223
223
|
name: this.display_name || "qq",
|
|
224
224
|
app_id: appId,
|
|
@@ -64,7 +64,7 @@ export class FeishuBot extends BaseChatChannel {
|
|
|
64
64
|
this.appId = appId;
|
|
65
65
|
this.appSecret = appSecret;
|
|
66
66
|
this.domain = domain;
|
|
67
|
-
this.dedupeDir = get_feishu_dedupe_dir_path(context.
|
|
67
|
+
this.dedupeDir = get_feishu_dedupe_dir_path(context.data_path);
|
|
68
68
|
this.platform = new FeishuPlatformClient({
|
|
69
69
|
context,
|
|
70
70
|
config: {
|
|
@@ -60,6 +60,7 @@ export interface FeishuPlatformClientOptions {
|
|
|
60
60
|
export class FeishuPlatformClient {
|
|
61
61
|
private readonly context: PluginContext;
|
|
62
62
|
private readonly rootPath: string;
|
|
63
|
+
private readonly dataPath: string;
|
|
63
64
|
private readonly logger: PluginContext["logger"];
|
|
64
65
|
private readonly appId: string;
|
|
65
66
|
private readonly appSecret: string;
|
|
@@ -79,6 +80,7 @@ export class FeishuPlatformClient {
|
|
|
79
80
|
constructor(options: FeishuPlatformClientOptions) {
|
|
80
81
|
this.context = options.context;
|
|
81
82
|
this.rootPath = options.context.workspace_path;
|
|
83
|
+
this.dataPath = options.context.data_path;
|
|
82
84
|
this.logger = options.context.logger;
|
|
83
85
|
this.appId = options.config.appId;
|
|
84
86
|
this.appSecret = options.config.appSecret;
|
|
@@ -394,6 +396,7 @@ export class FeishuPlatformClient {
|
|
|
394
396
|
private getLookupDeps() {
|
|
395
397
|
return {
|
|
396
398
|
rootPath: this.rootPath,
|
|
399
|
+
dataPath: this.dataPath,
|
|
397
400
|
logger: this.logger,
|
|
398
401
|
client: this.client,
|
|
399
402
|
getAppAccessToken: () => this.getAppAccessToken(),
|
|
@@ -26,6 +26,8 @@ export interface FeishuLookupDeps {
|
|
|
26
26
|
* 项目根目录。
|
|
27
27
|
*/
|
|
28
28
|
rootPath: string;
|
|
29
|
+
/** Agent private runtime directory 内部数据根目录。 */
|
|
30
|
+
dataPath: string;
|
|
29
31
|
/**
|
|
30
32
|
* 日志器。
|
|
31
33
|
*/
|
|
@@ -481,7 +483,7 @@ export async function downloadFeishuIncomingAttachments(
|
|
|
481
483
|
): Promise<FeishuDownloadedAttachment[]> {
|
|
482
484
|
if (!deps.client || params.attachments.length === 0) return [];
|
|
483
485
|
|
|
484
|
-
const dir = path.join(deps.
|
|
486
|
+
const dir = path.join(deps.dataPath, ".cache", "feishu");
|
|
485
487
|
await fs.ensureDir(dir);
|
|
486
488
|
|
|
487
489
|
const out: FeishuDownloadedAttachment[] = [];
|
|
@@ -58,7 +58,7 @@ export class QQBot extends BaseChatChannel {
|
|
|
58
58
|
this.appSecret = appSecret;
|
|
59
59
|
this.useSandbox = useSandbox;
|
|
60
60
|
this.inboundDedupeStore = new QqInboundDedupeStore({
|
|
61
|
-
|
|
61
|
+
dataPath: this.dataPath,
|
|
62
62
|
logger: this.logger,
|
|
63
63
|
});
|
|
64
64
|
this.gateway = new QQGatewayClient({
|
|
@@ -67,7 +67,7 @@ export class QQBot extends BaseChatChannel {
|
|
|
67
67
|
appId: this.appId,
|
|
68
68
|
appSecret: this.appSecret,
|
|
69
69
|
useSandbox: this.useSandbox,
|
|
70
|
-
captureConfig: getQqEventCaptureConfig(this.
|
|
70
|
+
captureConfig: getQqEventCaptureConfig(this.dataPath),
|
|
71
71
|
onDispatch: async (params) => {
|
|
72
72
|
await this.handleDispatch(params.eventType, params.data);
|
|
73
73
|
},
|
|
@@ -268,6 +268,7 @@ export class QQBot extends BaseChatChannel {
|
|
|
268
268
|
return {
|
|
269
269
|
context: this.context,
|
|
270
270
|
rootPath: this.rootPath,
|
|
271
|
+
dataPath: this.dataPath,
|
|
271
272
|
logger: this.logger,
|
|
272
273
|
getBotUserId: () => this.botUserId,
|
|
273
274
|
getChatKey: (params) => this.getChatKey(params),
|
|
@@ -14,7 +14,7 @@ import type { QQEventCaptureConfig, QQEventCaptureMode, QQGatewayPayload } from
|
|
|
14
14
|
/**
|
|
15
15
|
* 读取 QQ 原始事件捕获配置。
|
|
16
16
|
*/
|
|
17
|
-
export function getQqEventCaptureConfig(
|
|
17
|
+
export function getQqEventCaptureConfig(data_path: string): QQEventCaptureConfig {
|
|
18
18
|
const raw = String(process.env.SHIP_QQ_CAPTURE_EVENTS ?? "")
|
|
19
19
|
.trim()
|
|
20
20
|
.toLowerCase();
|
|
@@ -22,7 +22,7 @@ export function getQqEventCaptureConfig(project_root: string): QQEventCaptureCon
|
|
|
22
22
|
return {
|
|
23
23
|
enabled: false,
|
|
24
24
|
mode: "dispatch",
|
|
25
|
-
dir: join(
|
|
25
|
+
dir: join(data_path, ".debug", "qq-events"),
|
|
26
26
|
};
|
|
27
27
|
}
|
|
28
28
|
|
|
@@ -32,7 +32,7 @@ export function getQqEventCaptureConfig(project_root: string): QQEventCaptureCon
|
|
|
32
32
|
typeof process.env.SHIP_QQ_CAPTURE_DIR === "string" &&
|
|
33
33
|
process.env.SHIP_QQ_CAPTURE_DIR.trim()
|
|
34
34
|
? process.env.SHIP_QQ_CAPTURE_DIR.trim()
|
|
35
|
-
: join(
|
|
35
|
+
: join(data_path, ".debug", "qq-events");
|
|
36
36
|
|
|
37
37
|
return {
|
|
38
38
|
enabled: true,
|
|
@@ -23,7 +23,7 @@ export class QqInboundDedupeStore {
|
|
|
23
23
|
private loaded: boolean = false;
|
|
24
24
|
|
|
25
25
|
constructor(params: {
|
|
26
|
-
|
|
26
|
+
dataPath: string;
|
|
27
27
|
logger: Logger;
|
|
28
28
|
maxEntries?: number;
|
|
29
29
|
}) {
|
|
@@ -35,8 +35,7 @@ export class QqInboundDedupeStore {
|
|
|
35
35
|
? Math.floor(params.maxEntries)
|
|
36
36
|
: 2000;
|
|
37
37
|
this.filePath = path.join(
|
|
38
|
-
params.
|
|
39
|
-
".downcity",
|
|
38
|
+
params.dataPath,
|
|
40
39
|
".cache",
|
|
41
40
|
"qq",
|
|
42
41
|
"inbound-dedupe.json",
|
|
@@ -57,6 +57,10 @@ export interface QQMessageHandlerOptions {
|
|
|
57
57
|
* 项目根目录。
|
|
58
58
|
*/
|
|
59
59
|
rootPath: string;
|
|
60
|
+
/**
|
|
61
|
+
* 当前 Agent private runtime directory 的私有数据目录。
|
|
62
|
+
*/
|
|
63
|
+
dataPath: string;
|
|
60
64
|
/**
|
|
61
65
|
* 日志器。
|
|
62
66
|
*/
|
|
@@ -256,6 +260,7 @@ export async function handleQqChannelMessage(
|
|
|
256
260
|
const instructions = await buildQqInboundInstructions({
|
|
257
261
|
context: options.context,
|
|
258
262
|
rootPath: options.rootPath,
|
|
263
|
+
dataPath: options.dataPath,
|
|
259
264
|
chatId: channelId,
|
|
260
265
|
chat_key: options.getChatKey({ chatId: channelId, chatType }),
|
|
261
266
|
message_id,
|
|
@@ -410,6 +415,7 @@ async function handleQqInboundMessage(
|
|
|
410
415
|
const instructions = await buildQqInboundInstructions({
|
|
411
416
|
context: options.context,
|
|
412
417
|
rootPath: options.rootPath,
|
|
418
|
+
dataPath: options.dataPath,
|
|
413
419
|
chatId,
|
|
414
420
|
chat_key,
|
|
415
421
|
message_id,
|
|
@@ -57,6 +57,10 @@ export interface BuildQqInboundInstructionsParams {
|
|
|
57
57
|
* 项目根目录。
|
|
58
58
|
*/
|
|
59
59
|
rootPath: string;
|
|
60
|
+
/**
|
|
61
|
+
* 当前 Agent private runtime directory 的私有数据目录。
|
|
62
|
+
*/
|
|
63
|
+
dataPath: string;
|
|
60
64
|
/**
|
|
61
65
|
* 平台 chatId。
|
|
62
66
|
*/
|
|
@@ -233,6 +237,7 @@ export async function buildQqInboundInstructions(
|
|
|
233
237
|
try {
|
|
234
238
|
const localPath = await resolveQqAttachmentLocalPath({
|
|
235
239
|
rootPath: params.rootPath,
|
|
240
|
+
dataPath: params.dataPath,
|
|
236
241
|
attachment,
|
|
237
242
|
authToken,
|
|
238
243
|
});
|
|
@@ -298,6 +298,7 @@ function defaultExtByKind(kind: QqInboundAttachmentKind): string {
|
|
|
298
298
|
}
|
|
299
299
|
|
|
300
300
|
async function downloadRemoteAttachment(params: {
|
|
301
|
+
dataPath: string;
|
|
301
302
|
rootPath: string;
|
|
302
303
|
attachment: QqIncomingAttachment;
|
|
303
304
|
authToken?: string;
|
|
@@ -346,7 +347,7 @@ async function downloadRemoteAttachment(params: {
|
|
|
346
347
|
extFromContentType(responseType) ||
|
|
347
348
|
defaultExtByKind(params.attachment.kind);
|
|
348
349
|
|
|
349
|
-
const dir = path.join(params.
|
|
350
|
+
const dir = path.join(params.dataPath, ".cache", "qq");
|
|
350
351
|
await mkdir(dir, { recursive: true });
|
|
351
352
|
|
|
352
353
|
const stem = safeBase.replace(/\.[^.]+$/, "");
|
|
@@ -364,6 +365,9 @@ async function downloadRemoteAttachment(params: {
|
|
|
364
365
|
* - 远程 URL 会按需下载到 cache,再返回绝对路径。
|
|
365
366
|
*/
|
|
366
367
|
export async function resolveQqAttachmentLocalPath(params: {
|
|
368
|
+
/** 当前 Agent private runtime directory 的私有数据目录,用于保存下载缓存。 */
|
|
369
|
+
dataPath: string;
|
|
370
|
+
/** 项目根目录,用于解析消息中已有的项目相对路径。 */
|
|
367
371
|
rootPath: string;
|
|
368
372
|
attachment: QqIncomingAttachment;
|
|
369
373
|
authToken?: string;
|
|
@@ -38,11 +38,18 @@ function sleep(ms: number): Promise<void> {
|
|
|
38
38
|
export class TelegramApiClient {
|
|
39
39
|
private readonly botToken: string;
|
|
40
40
|
private readonly rootPath: string;
|
|
41
|
+
private readonly dataPath: string;
|
|
41
42
|
private readonly logger: Logger;
|
|
42
43
|
|
|
43
|
-
constructor(opts: {
|
|
44
|
+
constructor(opts: {
|
|
45
|
+
botToken: string;
|
|
46
|
+
project_root: string;
|
|
47
|
+
data_path: string;
|
|
48
|
+
logger: Logger;
|
|
49
|
+
}) {
|
|
44
50
|
this.botToken = opts.botToken;
|
|
45
51
|
this.rootPath = opts.project_root;
|
|
52
|
+
this.dataPath = opts.data_path;
|
|
46
53
|
this.logger = opts.logger;
|
|
47
54
|
}
|
|
48
55
|
|
|
@@ -166,7 +173,7 @@ export class TelegramApiClient {
|
|
|
166
173
|
}
|
|
167
174
|
|
|
168
175
|
/**
|
|
169
|
-
* 下载 Telegram
|
|
176
|
+
* 下载 Telegram 文件并保存到当前 Agent private runtime directory 数据目录的 `.cache/telegram`。
|
|
170
177
|
*
|
|
171
178
|
* 说明(中文)
|
|
172
179
|
* - 文件名会做安全化处理,避免路径注入
|
|
@@ -200,7 +207,7 @@ export class TelegramApiClient {
|
|
|
200
207
|
base.replace(/[^\w.\-()@\u4e00-\u9fff]+/g, "_").slice(0, 160) ||
|
|
201
208
|
`tg-${fileId}`;
|
|
202
209
|
|
|
203
|
-
const dir = path.join(this.
|
|
210
|
+
const dir = path.join(this.dataPath, ".cache", "telegram");
|
|
204
211
|
await fs.ensureDir(dir);
|
|
205
212
|
const uniq = `${Date.now()}-${fileId.slice(0, 8)}`;
|
|
206
213
|
const outPath = path.join(dir, `${uniq}-${safeBase}`);
|
|
@@ -19,8 +19,8 @@ import type { JsonObject } from "@downcity/agent";
|
|
|
19
19
|
export class TelegramStateStore {
|
|
20
20
|
private readonly lastUpdateIdFile: string;
|
|
21
21
|
|
|
22
|
-
constructor(
|
|
23
|
-
const dir = path.join(
|
|
22
|
+
constructor(data_path: string) {
|
|
23
|
+
const dir = path.join(data_path, ".cache", "telegram");
|
|
24
24
|
this.lastUpdateIdFile = path.join(dir, "lastUpdateId.json");
|
|
25
25
|
}
|
|
26
26
|
|
|
@@ -75,9 +75,10 @@ export class TelegramPlatformClient {
|
|
|
75
75
|
this.api = new TelegramApiClient({
|
|
76
76
|
botToken: options.botToken,
|
|
77
77
|
project_root: options.context.workspace_path,
|
|
78
|
+
data_path: options.context.data_path,
|
|
78
79
|
logger: options.context.logger,
|
|
79
80
|
});
|
|
80
|
-
this.stateStore = new TelegramStateStore(options.context.
|
|
81
|
+
this.stateStore = new TelegramStateStore(options.context.data_path);
|
|
81
82
|
this.onMessage = options.onMessage;
|
|
82
83
|
this.onCallbackQuery = options.onCallbackQuery;
|
|
83
84
|
this.onWebhookConflictResolved = options.onWebhookConflictResolved;
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
/** Chat Plugin Profile 的 main actions 与凭据边界。 */
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
define_plugin_main,
|
|
5
|
+
type PluginJsonObject,
|
|
6
|
+
type PluginJsonValue,
|
|
7
|
+
} from "@downcity/plugin";
|
|
8
|
+
import type { ChatPluginChannelConfig } from "@/chat/types/ChatPluginChannelConfig.js";
|
|
9
|
+
import type { ChatPluginConfig } from "@/chat/types/ChatPluginConfig.js";
|
|
10
|
+
import type {
|
|
11
|
+
ChatPluginPublicChannelConfig,
|
|
12
|
+
ChatPluginPublicProfile,
|
|
13
|
+
ChatPluginPublicQueueConfig,
|
|
14
|
+
} from "@/chat/types/ChatPluginProfile.js";
|
|
15
|
+
|
|
16
|
+
/** Chat Plugin 的宿主管理入口。 */
|
|
17
|
+
export const CHAT_PLUGIN_MAIN = define_plugin_main({
|
|
18
|
+
activate({ plugin }) {
|
|
19
|
+
plugin.action({
|
|
20
|
+
id: "profile.read",
|
|
21
|
+
run: async (_input, context) => to_public_profile(
|
|
22
|
+
await context.config.get() as unknown as ChatPluginConfig,
|
|
23
|
+
) as unknown as PluginJsonValue,
|
|
24
|
+
});
|
|
25
|
+
plugin.action({
|
|
26
|
+
id: "profile.save",
|
|
27
|
+
run: async (input, context) => {
|
|
28
|
+
const current = await context.config.get() as unknown as ChatPluginConfig;
|
|
29
|
+
const config = normalize_profile(input, current);
|
|
30
|
+
await context.config.set(config as unknown as PluginJsonObject);
|
|
31
|
+
return to_public_profile(config) as unknown as PluginJsonValue;
|
|
32
|
+
},
|
|
33
|
+
});
|
|
34
|
+
},
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
/** 把完整配置转换为不包含凭据原文的 Mainview 投影。 */
|
|
38
|
+
function to_public_profile(config: ChatPluginConfig): ChatPluginPublicProfile {
|
|
39
|
+
return {
|
|
40
|
+
queue: { ...(config.queue ?? {}) },
|
|
41
|
+
channels: (config.channels ?? []).map((channel) => ({
|
|
42
|
+
id: channel.id,
|
|
43
|
+
type: channel.type,
|
|
44
|
+
name: channel.name,
|
|
45
|
+
...(channel.type !== "telegram" ? { app_id: channel.app_id } : {}),
|
|
46
|
+
...(channel.type === "feishu" && channel.domain ? { domain: channel.domain } : {}),
|
|
47
|
+
...(channel.type === "qq" ? { sandbox: channel.sandbox === true } : {}),
|
|
48
|
+
secret_configured: channel.type === "telegram"
|
|
49
|
+
? Boolean(channel.bot_token)
|
|
50
|
+
: Boolean(channel.app_secret),
|
|
51
|
+
})),
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/** 校验 Mainview 草稿并补回未重新填写的已有凭据。 */
|
|
56
|
+
function normalize_profile(
|
|
57
|
+
input: PluginJsonValue | undefined,
|
|
58
|
+
current: ChatPluginConfig,
|
|
59
|
+
): ChatPluginConfig {
|
|
60
|
+
const profile = as_record(input, "Chat Profile");
|
|
61
|
+
const queue = normalize_queue(profile.queue);
|
|
62
|
+
const channel_values = profile.channels;
|
|
63
|
+
if (!Array.isArray(channel_values)) throw new Error("Chat channels must be an array");
|
|
64
|
+
const channel_types = new Set<string>();
|
|
65
|
+
const channel_ids = new Set<string>();
|
|
66
|
+
const channels = channel_values.map((value) => {
|
|
67
|
+
const channel = normalize_channel(value, current.channels ?? []);
|
|
68
|
+
if (channel_types.has(channel.type)) {
|
|
69
|
+
throw new Error(`Chat Channel type is duplicated: ${channel.type}`);
|
|
70
|
+
}
|
|
71
|
+
if (channel_ids.has(channel.id)) {
|
|
72
|
+
throw new Error(`Chat Channel ID is duplicated: ${channel.id}`);
|
|
73
|
+
}
|
|
74
|
+
channel_types.add(channel.type);
|
|
75
|
+
channel_ids.add(channel.id);
|
|
76
|
+
return channel;
|
|
77
|
+
});
|
|
78
|
+
return {
|
|
79
|
+
...(Object.keys(queue).length > 0 ? { queue } : {}),
|
|
80
|
+
channels,
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/** 校验 Chat 队列配置。 */
|
|
85
|
+
function normalize_queue(value: PluginJsonValue | undefined): ChatPluginPublicQueueConfig {
|
|
86
|
+
if (value === undefined) return {};
|
|
87
|
+
const queue = as_record(value, "Chat queue");
|
|
88
|
+
return {
|
|
89
|
+
...read_integer(queue, "max_concurrency", 1, 32),
|
|
90
|
+
...read_integer(queue, "merge_debounce_ms", 0, 60000),
|
|
91
|
+
...read_integer(queue, "merge_max_wait_ms", 0, 120000),
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/** 校验并规范化一个 Chat Channel。 */
|
|
96
|
+
function normalize_channel(
|
|
97
|
+
value: PluginJsonValue,
|
|
98
|
+
current_channels: ChatPluginChannelConfig[],
|
|
99
|
+
): ChatPluginChannelConfig {
|
|
100
|
+
const channel = as_record(value, "Chat Channel");
|
|
101
|
+
const id = read_required_string(channel, "id");
|
|
102
|
+
const name = read_required_string(channel, "name");
|
|
103
|
+
const type = read_required_string(channel, "type");
|
|
104
|
+
const current = current_channels.find((item) => item.id === id && item.type === type);
|
|
105
|
+
if (type === "telegram") {
|
|
106
|
+
const bot_token = read_optional_string(channel, "bot_token")
|
|
107
|
+
|| (current?.type === "telegram" ? current.bot_token : "");
|
|
108
|
+
if (!bot_token) throw new Error(`Telegram Bot Token is required: ${id}`);
|
|
109
|
+
return { id, type, name, bot_token };
|
|
110
|
+
}
|
|
111
|
+
if (type === "feishu") {
|
|
112
|
+
const app_id = read_required_string(channel, "app_id");
|
|
113
|
+
const app_secret = read_optional_string(channel, "app_secret")
|
|
114
|
+
|| (current?.type === "feishu" ? current.app_secret : "");
|
|
115
|
+
if (!app_secret) throw new Error(`Feishu App Secret is required: ${id}`);
|
|
116
|
+
const domain = read_optional_string(channel, "domain");
|
|
117
|
+
return { id, type, name, app_id, app_secret, ...(domain ? { domain } : {}) };
|
|
118
|
+
}
|
|
119
|
+
if (type === "qq") {
|
|
120
|
+
const app_id = read_required_string(channel, "app_id");
|
|
121
|
+
const app_secret = read_optional_string(channel, "app_secret")
|
|
122
|
+
|| (current?.type === "qq" ? current.app_secret : "");
|
|
123
|
+
if (!app_secret) throw new Error(`QQ App Secret is required: ${id}`);
|
|
124
|
+
return { id, type, name, app_id, app_secret, sandbox: channel.sandbox === true };
|
|
125
|
+
}
|
|
126
|
+
throw new Error(`Unsupported Chat Channel type: ${type}`);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/** 读取一个受范围约束的可选整数字段。 */
|
|
130
|
+
function read_integer(
|
|
131
|
+
source: PluginJsonObject,
|
|
132
|
+
key: string,
|
|
133
|
+
minimum: number,
|
|
134
|
+
maximum: number,
|
|
135
|
+
): Partial<Record<string, number>> {
|
|
136
|
+
const value = source[key];
|
|
137
|
+
if (value === undefined || value === null || value === "") return {};
|
|
138
|
+
if (typeof value !== "number" || !Number.isInteger(value) || value < minimum || value > maximum) {
|
|
139
|
+
throw new Error(`Invalid Chat Profile field: ${key}`);
|
|
140
|
+
}
|
|
141
|
+
return { [key]: value };
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/** 要求一个值是 JSON object。 */
|
|
145
|
+
function as_record(value: PluginJsonValue | undefined, label: string): PluginJsonObject {
|
|
146
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
147
|
+
throw new Error(`${label} must be an object`);
|
|
148
|
+
}
|
|
149
|
+
return value;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/** 读取并规范化必填字符串。 */
|
|
153
|
+
function read_required_string(source: PluginJsonObject, key: string): string {
|
|
154
|
+
const value = read_optional_string(source, key);
|
|
155
|
+
if (!value) throw new Error(`Chat Profile field is required: ${key}`);
|
|
156
|
+
return value;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
/** 读取并规范化可选字符串。 */
|
|
160
|
+
function read_optional_string(source: PluginJsonObject, key: string): string {
|
|
161
|
+
const value = source[key];
|
|
162
|
+
return typeof value === "string" ? value.trim() : "";
|
|
163
|
+
}
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
/** Chat Plugin 使用宿主 UI Components 的唯一 React Mainview。 */
|
|
2
|
+
|
|
3
|
+
import { useCallback, useEffect, useState } from "react";
|
|
4
|
+
import type { PluginJsonValue } from "@downcity/plugin";
|
|
5
|
+
import { define_plugin_renderer } from "@downcity/plugin/react";
|
|
6
|
+
import type {
|
|
7
|
+
ChatPluginPublicChannelConfig,
|
|
8
|
+
ChatPluginPublicProfile,
|
|
9
|
+
ChatPluginPublicQueueConfig,
|
|
10
|
+
} from "@/chat/types/ChatPluginProfile.js";
|
|
11
|
+
import type { ChatPluginChannelEditorProps } from "@/chat/types/ChatPluginRenderer.js";
|
|
12
|
+
|
|
13
|
+
const channel_types: readonly ChatPluginPublicChannelConfig["type"][] = ["telegram", "feishu", "qq"];
|
|
14
|
+
|
|
15
|
+
/** Chat Plugin 唯一 Mainview 组件。 */
|
|
16
|
+
export const CHAT_PLUGIN_RENDERER = define_plugin_renderer(function ChatPluginRenderer({ plugin, ui }) {
|
|
17
|
+
const { Button, Callout, EmptyState, Group, Input, LoadingState, Page, Row, Section, Select, Stack, Switch, Toolbar } = ui.components;
|
|
18
|
+
const [profile, set_profile] = useState<ChatPluginPublicProfile>();
|
|
19
|
+
const [loading, set_loading] = useState(true);
|
|
20
|
+
const [saving, set_saving] = useState(false);
|
|
21
|
+
const [error, set_error] = useState("");
|
|
22
|
+
|
|
23
|
+
const load = useCallback(async () => {
|
|
24
|
+
set_loading(true);
|
|
25
|
+
set_error("");
|
|
26
|
+
try {
|
|
27
|
+
set_profile(await plugin.invoke("profile.read") as unknown as ChatPluginPublicProfile);
|
|
28
|
+
} catch (reason) {
|
|
29
|
+
set_error(to_error_message(reason));
|
|
30
|
+
} finally {
|
|
31
|
+
set_loading(false);
|
|
32
|
+
}
|
|
33
|
+
}, [plugin]);
|
|
34
|
+
|
|
35
|
+
useEffect(() => { void load(); }, [load]);
|
|
36
|
+
|
|
37
|
+
const save = async () => {
|
|
38
|
+
if (!profile) return;
|
|
39
|
+
set_saving(true);
|
|
40
|
+
set_error("");
|
|
41
|
+
try {
|
|
42
|
+
const saved = await plugin.invoke("profile.save", profile as unknown as PluginJsonValue);
|
|
43
|
+
set_profile(saved as unknown as ChatPluginPublicProfile);
|
|
44
|
+
ui.toast({ type: "success", message: "Chat Profile 已保存" });
|
|
45
|
+
} catch (reason) {
|
|
46
|
+
const message = to_error_message(reason);
|
|
47
|
+
set_error(message);
|
|
48
|
+
ui.toast({ type: "error", message });
|
|
49
|
+
} finally {
|
|
50
|
+
set_saving(false);
|
|
51
|
+
}
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
const update_queue = (key: keyof ChatPluginPublicQueueConfig, value: string) => {
|
|
55
|
+
set_profile((current) => current ? {
|
|
56
|
+
...current,
|
|
57
|
+
queue: {
|
|
58
|
+
...current.queue,
|
|
59
|
+
[key]: value === "" ? undefined : Number(value),
|
|
60
|
+
},
|
|
61
|
+
} : current);
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
const add_channel = () => {
|
|
65
|
+
if (!profile) return;
|
|
66
|
+
const used_types = new Set(profile.channels.map((channel) => channel.type));
|
|
67
|
+
const type = channel_types.find((item) => !used_types.has(item));
|
|
68
|
+
if (!type) {
|
|
69
|
+
ui.toast({ type: "info", message: "每种 Channel 类型只能配置一次" });
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
set_profile((current) => current ? {
|
|
73
|
+
...current,
|
|
74
|
+
channels: [...current.channels, { id: "", name: "", type, secret_configured: false }],
|
|
75
|
+
} : current);
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
if (loading && !profile) return <LoadingState label="正在读取 Chat Profile…" />;
|
|
79
|
+
|
|
80
|
+
return <Page>
|
|
81
|
+
<Toolbar
|
|
82
|
+
actions={<Button variant="primary" disabled={!profile || saving} on_click={() => void save()}>{saving ? "保存中…" : "保存"}</Button>}
|
|
83
|
+
/>
|
|
84
|
+
{error ? <Callout tone="danger">{error}</Callout> : null}
|
|
85
|
+
<Section title="Queue" description="控制入站消息的并发与合并等待。" surface={false}>
|
|
86
|
+
<Group>
|
|
87
|
+
<Row label="Maximum concurrency" trailing={<Input type="number" value={number_value(profile?.queue.max_concurrency)} minimum={1} maximum={32} placeholder="4" on_value_change={(value) => update_queue("max_concurrency", value)} />} />
|
|
88
|
+
<Row label="Merge debounce" description="连续消息停止到达后等待的毫秒数。" trailing={<Input type="number" value={number_value(profile?.queue.merge_debounce_ms)} minimum={0} maximum={60000} on_value_change={(value) => update_queue("merge_debounce_ms", value)} />} />
|
|
89
|
+
<Row label="Maximum merge wait" description="一组消息允许等待合并的最大毫秒数。" trailing={<Input type="number" value={number_value(profile?.queue.merge_max_wait_ms)} minimum={0} maximum={120000} on_value_change={(value) => update_queue("merge_max_wait_ms", value)} />} />
|
|
90
|
+
</Group>
|
|
91
|
+
</Section>
|
|
92
|
+
<Section title="Channels" description="同一种 Channel 类型在一个 Profile 中只能出现一次。" action={<Button on_click={add_channel}>添加 Channel</Button>} surface={false}>
|
|
93
|
+
{!profile?.channels.length ? <EmptyState title="还没有消息渠道" description="添加 Telegram、Feishu 或 QQ Channel。" action={<Button variant="primary" on_click={add_channel}>添加 Channel</Button>} size="compact" />
|
|
94
|
+
: <Stack>{profile.channels.map((channel, index) => <ChannelEditor
|
|
95
|
+
key={`${channel.type}:${index}`}
|
|
96
|
+
channel={channel}
|
|
97
|
+
used_types={new Set(profile.channels.filter((_item, item_index) => item_index !== index).map((item) => item.type))}
|
|
98
|
+
components={{ Button, Group, Input, Row, Select, Switch }}
|
|
99
|
+
update={(next) => set_profile((current) => current ? { ...current, channels: current.channels.map((item, item_index) => item_index === index ? next : item) } : current)}
|
|
100
|
+
remove={() => set_profile((current) => current ? { ...current, channels: current.channels.filter((_item, item_index) => item_index !== index) } : current)}
|
|
101
|
+
/>)}</Stack>}
|
|
102
|
+
</Section>
|
|
103
|
+
</Page>;
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
/** 编辑一个具体 Channel,凭据输入只保存在当前草稿。 */
|
|
107
|
+
function ChannelEditor({ channel, used_types, components, update, remove }: ChatPluginChannelEditorProps) {
|
|
108
|
+
const { Button, Group, Input, Row, Select, Switch } = components;
|
|
109
|
+
const set_string = (key: "id" | "name" | "bot_token" | "app_id" | "app_secret" | "domain", value: string) => update({ ...channel, [key]: value });
|
|
110
|
+
const type_options = channel_types.map((type) => ({ value: type, label: channel_type_label(type), disabled: used_types.has(type) }));
|
|
111
|
+
return <Group label={channel.name || channel.id || channel_type_label(channel.type)} action={<Button variant="destructive" on_click={remove}>删除</Button>}>
|
|
112
|
+
<Row label="Type" trailing={<Select value={channel.type} options={type_options} on_value_change={(value) => update({ id: channel.id, name: channel.name, type: value as ChatPluginPublicChannelConfig["type"], secret_configured: false })} />} />
|
|
113
|
+
<Row label="Channel ID" trailing={<Input value={channel.id} on_value_change={(value) => set_string("id", value)} />} />
|
|
114
|
+
<Row label="Name" trailing={<Input value={channel.name} on_value_change={(value) => set_string("name", value)} />} />
|
|
115
|
+
{channel.type === "telegram" ? <Row label="Bot Token" description={secret_description(channel)} trailing={<Input type="password" value={channel.bot_token ?? ""} placeholder={secret_placeholder(channel)} on_value_change={(value) => set_string("bot_token", value)} />} /> : <>
|
|
116
|
+
<Row label="App ID" trailing={<Input value={channel.app_id ?? ""} on_value_change={(value) => set_string("app_id", value)} />} />
|
|
117
|
+
<Row label="App Secret" description={secret_description(channel)} trailing={<Input type="password" value={channel.app_secret ?? ""} placeholder={secret_placeholder(channel)} on_value_change={(value) => set_string("app_secret", value)} />} />
|
|
118
|
+
{channel.type === "feishu" ? <Row label="API Domain" trailing={<Input value={channel.domain ?? ""} placeholder="https://open.feishu.cn" on_value_change={(value) => set_string("domain", value)} />} /> : null}
|
|
119
|
+
{channel.type === "qq" ? <Row label="Sandbox" trailing={<Switch checked={channel.sandbox === true} on_checked_change={(sandbox) => update({ ...channel, sandbox })} aria_label="QQ Sandbox" />} /> : null}
|
|
120
|
+
</>}
|
|
121
|
+
</Group>;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/** 返回 Channel 类型的用户可见名称。 */
|
|
125
|
+
function channel_type_label(type: ChatPluginPublicChannelConfig["type"]): string {
|
|
126
|
+
if (type === "telegram") return "Telegram";
|
|
127
|
+
if (type === "feishu") return "Feishu / Lark";
|
|
128
|
+
return "QQ";
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
/** 把可选数字转换为受控 Input 字符串。 */
|
|
132
|
+
function number_value(value: number | undefined): string {
|
|
133
|
+
return value === undefined ? "" : String(value);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/** 已配置凭据的安全说明。 */
|
|
137
|
+
function secret_description(channel: ChatPluginPublicChannelConfig): string | undefined {
|
|
138
|
+
return channel.secret_configured ? "已有凭据不会显示;留空会保留当前值。" : undefined;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/** 已配置凭据的安全占位符。 */
|
|
142
|
+
function secret_placeholder(channel: ChatPluginPublicChannelConfig): string | undefined {
|
|
143
|
+
return channel.secret_configured ? "已配置;留空保持" : undefined;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
/** 把未知失败转换为用户可见消息。 */
|
|
147
|
+
function to_error_message(reason: unknown): string {
|
|
148
|
+
return reason instanceof Error ? reason.message : String(reason);
|
|
149
|
+
}
|