@downcity/plugins 1.0.253 → 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/Action.d.ts +27 -36
- package/bin/memory/Action.d.ts.map +1 -1
- package/bin/memory/Action.js +71 -311
- package/bin/memory/Action.js.map +1 -1
- package/bin/memory/MemoryPlugin.d.ts +20 -37
- package/bin/memory/MemoryPlugin.d.ts.map +1 -1
- package/bin/memory/MemoryPlugin.js +241 -233
- package/bin/memory/MemoryPlugin.js.map +1 -1
- package/bin/memory/adapters/FileMemoryStorageAdapter.d.ts +43 -0
- package/bin/memory/adapters/FileMemoryStorageAdapter.d.ts.map +1 -0
- package/bin/memory/adapters/FileMemoryStorageAdapter.js +163 -0
- package/bin/memory/adapters/FileMemoryStorageAdapter.js.map +1 -0
- package/bin/memory/providers/BuiltinMemoryProvider.d.ts +63 -0
- package/bin/memory/providers/BuiltinMemoryProvider.d.ts.map +1 -0
- package/bin/memory/providers/BuiltinMemoryProvider.js +772 -0
- package/bin/memory/providers/BuiltinMemoryProvider.js.map +1 -0
- package/bin/memory/runtime/SystemProvider.d.ts +7 -12
- package/bin/memory/runtime/SystemProvider.d.ts.map +1 -1
- package/bin/memory/runtime/SystemProvider.js +30 -89
- package/bin/memory/runtime/SystemProvider.js.map +1 -1
- package/bin/memory/types/BuiltinMemoryProvider.d.ts +88 -0
- package/bin/memory/types/BuiltinMemoryProvider.d.ts.map +1 -0
- package/bin/memory/types/BuiltinMemoryProvider.js +9 -0
- package/bin/memory/types/BuiltinMemoryProvider.js.map +1 -0
- package/bin/memory/types/Memory.d.ts +255 -408
- package/bin/memory/types/Memory.d.ts.map +1 -1
- package/bin/memory/types/Memory.js +4 -4
- package/bin/memory/types/MemoryStorage.d.ts +35 -0
- package/bin/memory/types/MemoryStorage.d.ts.map +1 -0
- package/bin/memory/types/MemoryStorage.js +10 -0
- package/bin/memory/types/MemoryStorage.js.map +1 -0
- package/bin/memory.d.ts +6 -2
- package/bin/memory.d.ts.map +1 -1
- package/bin/memory.js +3 -1
- package/bin/memory.js.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 -19
- 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 +204 -0
- package/scripts/playwright-browser-provider.test.mjs +260 -0
- package/scripts/plugin-main.test.mjs +101 -0
- package/scripts/plugin-subpaths.test.mjs +36 -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/Action.ts +106 -377
- package/src/memory/MemoryPlugin.ts +266 -246
- package/src/memory/adapters/FileMemoryStorageAdapter.ts +197 -0
- package/src/memory/providers/BuiltinMemoryProvider.ts +905 -0
- package/src/memory/runtime/SystemProvider.ts +32 -95
- package/src/memory/types/BuiltinMemoryProvider.ts +121 -0
- package/src/memory/types/Memory.ts +329 -456
- package/src/memory/types/MemoryStorage.ts +44 -0
- package/src/memory.ts +49 -24
- 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 -9
- package/bin/memory/Index.d.ts.map +0 -1
- package/bin/memory/Index.js +0 -9
- package/bin/memory/Index.js.map +0 -1
- package/bin/memory/runtime/Search.d.ts +0 -19
- package/bin/memory/runtime/Search.d.ts.map +0 -1
- package/bin/memory/runtime/Search.js +0 -262
- package/bin/memory/runtime/Search.js.map +0 -1
- package/bin/memory/runtime/Store.d.ts +0 -42
- package/bin/memory/runtime/Store.d.ts.map +0 -1
- package/bin/memory/runtime/Store.js +0 -94
- package/bin/memory/runtime/Store.js.map +0 -1
- package/bin/memory/runtime/Writer.d.ts +0 -61
- package/bin/memory/runtime/Writer.d.ts.map +0 -1
- package/bin/memory/runtime/Writer.js +0 -274
- package/bin/memory/runtime/Writer.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 -9
- package/src/memory/runtime/Search.ts +0 -327
- package/src/memory/runtime/Store.ts +0 -158
- package/src/memory/runtime/Writer.ts +0 -351
- package/src/skill/Command.ts +0 -58
- package/src/task/Index.ts +0 -8
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MemoryPlugin Provider 与本地 Adapter 回归测试。
|
|
3
|
+
*
|
|
4
|
+
* 关键点(中文)
|
|
5
|
+
* - MemoryPlugin 只委托 Provider,不读取 Workspace 文件。
|
|
6
|
+
* - Builtin Provider 只公开 memory_id/citation,不泄漏物理路径。
|
|
7
|
+
* - File Adapter 始终把逻辑 key 限制在独占根目录。
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import assert from "node:assert/strict";
|
|
11
|
+
import fs from "node:fs/promises";
|
|
12
|
+
import os from "node:os";
|
|
13
|
+
import path from "node:path";
|
|
14
|
+
import test from "node:test";
|
|
15
|
+
import {
|
|
16
|
+
BuiltinMemoryProvider,
|
|
17
|
+
FileMemoryStorageAdapter,
|
|
18
|
+
MemoryPlugin,
|
|
19
|
+
get_default_file_memory_root_path,
|
|
20
|
+
} from "@downcity/plugins/memory";
|
|
21
|
+
|
|
22
|
+
/** 创建测试使用的最小 Agent scope。 */
|
|
23
|
+
function create_scope(workspace_path, session_id) {
|
|
24
|
+
return {
|
|
25
|
+
agent_id: "memory_test_agent",
|
|
26
|
+
workspace_id: workspace_path,
|
|
27
|
+
...(session_id ? { session_id } : {}),
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
test("Builtin Provider 把 Memory 数据写入独立 Adapter 根而不是 Workspace", async (context) => {
|
|
32
|
+
const temporary_root = await fs.mkdtemp(path.join(os.tmpdir(), "downcity-memory-"));
|
|
33
|
+
context.after(async () => await fs.rm(temporary_root, { recursive: true, force: true }));
|
|
34
|
+
const workspace_path = path.join(temporary_root, "workspace");
|
|
35
|
+
const memory_root = path.join(temporary_root, "agent-data", "memory");
|
|
36
|
+
await fs.mkdir(workspace_path, { recursive: true });
|
|
37
|
+
const provider = new BuiltinMemoryProvider({
|
|
38
|
+
storage: new FileMemoryStorageAdapter({ root_path: memory_root }),
|
|
39
|
+
});
|
|
40
|
+
await provider.initialize({ agent_id: "memory_test_agent" });
|
|
41
|
+
|
|
42
|
+
const remembered = await provider.remember({
|
|
43
|
+
scope: create_scope(workspace_path),
|
|
44
|
+
content: "The user prefers concise answers.",
|
|
45
|
+
topic: "user-preferences",
|
|
46
|
+
memory_type: "preference",
|
|
47
|
+
source: "explicit user statement",
|
|
48
|
+
});
|
|
49
|
+
assert.equal(remembered.memory_id, "wiki/user-preferences");
|
|
50
|
+
assert.equal(remembered.mode, "created");
|
|
51
|
+
assert.equal(await fs.stat(path.join(memory_root, "wiki", "user-preferences.md")).then(() => true), true);
|
|
52
|
+
assert.equal(await fs.access(path.join(workspace_path, ".downcity", "memory")).then(() => true).catch(() => false), false);
|
|
53
|
+
|
|
54
|
+
const recalled = await provider.recall({
|
|
55
|
+
scope: create_scope(workspace_path),
|
|
56
|
+
query: "concise answers",
|
|
57
|
+
min_score: 0.1,
|
|
58
|
+
});
|
|
59
|
+
assert.equal(recalled.items[0]?.memory.memory_id, "wiki/user-preferences");
|
|
60
|
+
assert.deepEqual(recalled.items[0]?.memory.scope, { agent_id: "memory_test_agent" });
|
|
61
|
+
assert.match(recalled.items[0]?.memory.citation || "", /^memory:\/\/builtin\//);
|
|
62
|
+
assert.equal(JSON.stringify(recalled).includes(memory_root), false);
|
|
63
|
+
|
|
64
|
+
const read = await provider.read({
|
|
65
|
+
scope: create_scope(workspace_path),
|
|
66
|
+
memory_id: remembered.memory_id,
|
|
67
|
+
});
|
|
68
|
+
assert.match(read.memory?.content || "", /concise answers/);
|
|
69
|
+
assert.deepEqual(read.memory?.scope, { agent_id: "memory_test_agent" });
|
|
70
|
+
|
|
71
|
+
await provider.remember({
|
|
72
|
+
scope: create_scope(workspace_path, "session-that-must-not-own-memory"),
|
|
73
|
+
content: "The user also prefers structured results.",
|
|
74
|
+
topic: "user-preferences",
|
|
75
|
+
memory_type: "preference",
|
|
76
|
+
source: "second explicit user statement",
|
|
77
|
+
});
|
|
78
|
+
const updated_read = await provider.read({
|
|
79
|
+
scope: create_scope(workspace_path),
|
|
80
|
+
memory_id: remembered.memory_id,
|
|
81
|
+
});
|
|
82
|
+
assert.equal(updated_read.memory?.source_refs.length, 2);
|
|
83
|
+
assert.deepEqual(updated_read.memory?.scope, { agent_id: "memory_test_agent" });
|
|
84
|
+
|
|
85
|
+
await assert.rejects(provider.read({
|
|
86
|
+
scope: { agent_id: "another_agent" },
|
|
87
|
+
memory_id: remembered.memory_id,
|
|
88
|
+
}), /does not match initialized Provider/);
|
|
89
|
+
await assert.rejects(provider.digest({
|
|
90
|
+
scope: create_scope(workspace_path, "empty-session"),
|
|
91
|
+
session_id: "empty-session",
|
|
92
|
+
transcript: "",
|
|
93
|
+
message_count: 0,
|
|
94
|
+
}), /requires transcript content/);
|
|
95
|
+
|
|
96
|
+
const revised = await provider.revise({
|
|
97
|
+
scope: create_scope(workspace_path),
|
|
98
|
+
memory_id: remembered.memory_id,
|
|
99
|
+
instruction: "Add the latest preference.",
|
|
100
|
+
evidence: "The user also prefers structured results.",
|
|
101
|
+
});
|
|
102
|
+
assert.equal(revised.mode, "appended");
|
|
103
|
+
assert.match(revised.evidence_id || "", /^evidence\/manual\//);
|
|
104
|
+
const revised_read = await provider.read({
|
|
105
|
+
scope: create_scope(workspace_path),
|
|
106
|
+
memory_id: remembered.memory_id,
|
|
107
|
+
});
|
|
108
|
+
assert.match(revised_read.memory?.content || "", /structured results/);
|
|
109
|
+
assert.equal(revised_read.memory?.source_refs.length, 3);
|
|
110
|
+
|
|
111
|
+
const forgotten = await provider.forget({
|
|
112
|
+
scope: create_scope(workspace_path),
|
|
113
|
+
memory_id: remembered.memory_id,
|
|
114
|
+
});
|
|
115
|
+
assert.equal(forgotten.forgotten, true);
|
|
116
|
+
assert.equal((await provider.read({
|
|
117
|
+
scope: create_scope(workspace_path),
|
|
118
|
+
memory_id: remembered.memory_id,
|
|
119
|
+
})).memory, null);
|
|
120
|
+
await provider.dispose();
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
test("File Adapter 拒绝目录穿越并由 Memory Plugin 定义默认路径", async (context) => {
|
|
124
|
+
const temporary_root = await fs.mkdtemp(path.join(os.tmpdir(), "downcity-memory-key-"));
|
|
125
|
+
context.after(async () => await fs.rm(temporary_root, { recursive: true, force: true }));
|
|
126
|
+
const adapter = new FileMemoryStorageAdapter({ root_path: temporary_root });
|
|
127
|
+
await adapter.initialize();
|
|
128
|
+
await assert.rejects(adapter.write("../outside.md", "blocked"), /Invalid Memory storage key/);
|
|
129
|
+
await assert.rejects(adapter.read("wiki/../../outside.md"), /Invalid Memory storage key/);
|
|
130
|
+
if (process.platform !== "win32") {
|
|
131
|
+
const outside_root = path.join(path.dirname(temporary_root), `${path.basename(temporary_root)}-outside`);
|
|
132
|
+
await fs.mkdir(outside_root, { recursive: true });
|
|
133
|
+
context.after(async () => await fs.rm(outside_root, { recursive: true, force: true }));
|
|
134
|
+
await fs.symlink(outside_root, path.join(temporary_root, "linked"), "dir");
|
|
135
|
+
await assert.rejects(
|
|
136
|
+
adapter.write("linked/outside.md", "blocked"),
|
|
137
|
+
/contains symbolic link/,
|
|
138
|
+
);
|
|
139
|
+
}
|
|
140
|
+
const provider = new BuiltinMemoryProvider({ storage: adapter });
|
|
141
|
+
await provider.initialize({ agent_id: "memory_test_agent" });
|
|
142
|
+
await assert.rejects(provider.read({
|
|
143
|
+
scope: { agent_id: "memory_test_agent" },
|
|
144
|
+
memory_id: "wiki/invalid.name",
|
|
145
|
+
}), /Invalid memory_id/);
|
|
146
|
+
assert.equal(
|
|
147
|
+
get_default_file_memory_root_path({
|
|
148
|
+
platform_root_path: "/platform-root",
|
|
149
|
+
agent_id: "memory_test_agent",
|
|
150
|
+
}),
|
|
151
|
+
path.join("/platform-root", "agents", "memory_test_agent", "memory"),
|
|
152
|
+
);
|
|
153
|
+
await provider.dispose();
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
test("Builtin Provider 在 initialize 阶段按 Agent 延迟创建 Adapter", async (context) => {
|
|
157
|
+
const temporary_root = await fs.mkdtemp(path.join(os.tmpdir(), "downcity-memory-factory-"));
|
|
158
|
+
context.after(async () => await fs.rm(temporary_root, { recursive: true, force: true }));
|
|
159
|
+
const initialized_agents = [];
|
|
160
|
+
const provider = new BuiltinMemoryProvider({
|
|
161
|
+
create_storage(input) {
|
|
162
|
+
initialized_agents.push(input.agent_id);
|
|
163
|
+
return new FileMemoryStorageAdapter({
|
|
164
|
+
root_path: path.join(temporary_root, input.agent_id),
|
|
165
|
+
});
|
|
166
|
+
},
|
|
167
|
+
});
|
|
168
|
+
assert.deepEqual(initialized_agents, []);
|
|
169
|
+
await provider.initialize({ agent_id: "memory_test_agent" });
|
|
170
|
+
assert.deepEqual(initialized_agents, ["memory_test_agent"]);
|
|
171
|
+
await provider.dispose();
|
|
172
|
+
await provider.initialize({ agent_id: "memory_test_agent" });
|
|
173
|
+
assert.deepEqual(initialized_agents, ["memory_test_agent", "memory_test_agent"]);
|
|
174
|
+
await provider.dispose();
|
|
175
|
+
});
|
|
176
|
+
|
|
177
|
+
test("MemoryPlugin 使用显式运行时目录并公开完整 Action", async (context) => {
|
|
178
|
+
const memory_root = await fs.mkdtemp(path.join(os.tmpdir(), "downcity-memory-plugin-"));
|
|
179
|
+
context.after(async () => await fs.rm(memory_root, { recursive: true, force: true }));
|
|
180
|
+
const plugin = new MemoryPlugin({ root_path: memory_root });
|
|
181
|
+
const plugin_context = {
|
|
182
|
+
agent_id: "memory_test_agent",
|
|
183
|
+
workspace_path: "/workspace",
|
|
184
|
+
};
|
|
185
|
+
await plugin.lifecycle.start(plugin_context);
|
|
186
|
+
const result = await plugin.actions.remember.execute({
|
|
187
|
+
context: plugin_context,
|
|
188
|
+
input: {
|
|
189
|
+
content: "Remember this",
|
|
190
|
+
topic: "test",
|
|
191
|
+
memory_type: "fact",
|
|
192
|
+
},
|
|
193
|
+
plugin_name: "memory",
|
|
194
|
+
action_name: "remember",
|
|
195
|
+
});
|
|
196
|
+
assert.equal(result.success, true);
|
|
197
|
+
assert.equal(result.data.memory_id, "wiki/test");
|
|
198
|
+
assert.equal(
|
|
199
|
+
await fs.access(path.join(memory_root, "wiki", "test.md")).then(() => true).catch(() => false),
|
|
200
|
+
true,
|
|
201
|
+
);
|
|
202
|
+
assert.equal("files" in plugin_context, false);
|
|
203
|
+
await plugin.lifecycle.stop(plugin_context);
|
|
204
|
+
});
|
|
@@ -0,0 +1,260 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PlaywrightBrowserProvider 的 CDP 连接与页面所有权专项测试。
|
|
3
|
+
*
|
|
4
|
+
* 关键点(中文)
|
|
5
|
+
* - 通过 Node 模块 mock 隔离真实 CDP endpoint,只验证 provider 的连接契约。
|
|
6
|
+
* - 默认 context 和既有 page 均属于外部浏览器,测试确保 provider 不接管或关闭它们。
|
|
7
|
+
* - 每个用例使用独立 provider 和 browser,避免 session registry 在测试之间共享。
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import assert from "node:assert/strict";
|
|
11
|
+
import test, { mock } from "node:test";
|
|
12
|
+
|
|
13
|
+
const connect_calls = [];
|
|
14
|
+
let current_browser;
|
|
15
|
+
|
|
16
|
+
mock.module("playwright-core", {
|
|
17
|
+
namedExports: {
|
|
18
|
+
chromium: {
|
|
19
|
+
async connectOverCDP(...args) {
|
|
20
|
+
connect_calls.push(args);
|
|
21
|
+
if (current_browser instanceof Error) throw current_browser;
|
|
22
|
+
return current_browser;
|
|
23
|
+
},
|
|
24
|
+
},
|
|
25
|
+
},
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
const { PlaywrightBrowserProvider } = await import("../bin/web.js");
|
|
29
|
+
|
|
30
|
+
function create_page(overrides = {}) {
|
|
31
|
+
return {
|
|
32
|
+
closed: false,
|
|
33
|
+
default_timeout: null,
|
|
34
|
+
default_navigation_timeout: null,
|
|
35
|
+
goto_calls: [],
|
|
36
|
+
setDefaultTimeout(value) { this.default_timeout = value; },
|
|
37
|
+
setDefaultNavigationTimeout(value) { this.default_navigation_timeout = value; },
|
|
38
|
+
async goto(...args) { this.goto_calls.push(args); },
|
|
39
|
+
locator() {
|
|
40
|
+
return {
|
|
41
|
+
async innerText() { return "Page body"; },
|
|
42
|
+
async allTextContents() { return ["Page body"]; },
|
|
43
|
+
};
|
|
44
|
+
},
|
|
45
|
+
url() { return "https://example.com/"; },
|
|
46
|
+
async title() { return "Example"; },
|
|
47
|
+
async close() { this.closed = true; },
|
|
48
|
+
...overrides,
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function create_browser(overrides = {}) {
|
|
53
|
+
const disconnected_listeners = [];
|
|
54
|
+
const existing_page = create_page();
|
|
55
|
+
const session_page = create_page();
|
|
56
|
+
const context = {
|
|
57
|
+
closed: false,
|
|
58
|
+
new_page_calls: 0,
|
|
59
|
+
pages() { return [existing_page]; },
|
|
60
|
+
async newPage() {
|
|
61
|
+
this.new_page_calls += 1;
|
|
62
|
+
return session_page;
|
|
63
|
+
},
|
|
64
|
+
async close() { this.closed = true; },
|
|
65
|
+
};
|
|
66
|
+
const browser = {
|
|
67
|
+
context,
|
|
68
|
+
existing_page,
|
|
69
|
+
session_page,
|
|
70
|
+
closed: false,
|
|
71
|
+
new_context_calls: 0,
|
|
72
|
+
connected: true,
|
|
73
|
+
contexts() { return [context]; },
|
|
74
|
+
async newContext() {
|
|
75
|
+
this.new_context_calls += 1;
|
|
76
|
+
throw new Error("newContext must not be called");
|
|
77
|
+
},
|
|
78
|
+
isConnected() { return this.connected; },
|
|
79
|
+
on(event, listener) {
|
|
80
|
+
if (event === "disconnected") disconnected_listeners.push(listener);
|
|
81
|
+
},
|
|
82
|
+
disconnect() {
|
|
83
|
+
this.connected = false;
|
|
84
|
+
for (const listener of disconnected_listeners) listener();
|
|
85
|
+
},
|
|
86
|
+
async close() { this.closed = true; },
|
|
87
|
+
...overrides,
|
|
88
|
+
};
|
|
89
|
+
return browser;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
test.beforeEach(() => {
|
|
93
|
+
connect_calls.length = 0;
|
|
94
|
+
current_browser = create_browser();
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
test("连接传递 timeout 和 noDefaults,并在默认 context 创建独占 page", async () => {
|
|
98
|
+
const provider = new PlaywrightBrowserProvider({
|
|
99
|
+
cdp_url: "http://127.0.0.1:9222",
|
|
100
|
+
timeout_ms: 4_000,
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
const result = await provider.create_session({ url: "https://example.com" });
|
|
104
|
+
|
|
105
|
+
assert.deepEqual(connect_calls, [[
|
|
106
|
+
"http://127.0.0.1:9222",
|
|
107
|
+
{ timeout: 4_000, noDefaults: true },
|
|
108
|
+
]]);
|
|
109
|
+
assert.equal(current_browser.context.new_page_calls, 1);
|
|
110
|
+
assert.equal(current_browser.new_context_calls, 0);
|
|
111
|
+
assert.equal(current_browser.existing_page.closed, false);
|
|
112
|
+
assert.equal(current_browser.session_page.default_timeout, 4_000);
|
|
113
|
+
assert.equal(current_browser.session_page.default_navigation_timeout, 4_000);
|
|
114
|
+
assert.deepEqual(current_browser.session_page.goto_calls, [[
|
|
115
|
+
"https://example.com",
|
|
116
|
+
{ waitUntil: "domcontentloaded" },
|
|
117
|
+
]]);
|
|
118
|
+
assert.equal(result.title, "Example");
|
|
119
|
+
|
|
120
|
+
await provider.close_session({ session_id: result.session_id });
|
|
121
|
+
assert.equal(current_browser.session_page.closed, true);
|
|
122
|
+
assert.equal(current_browser.existing_page.closed, false);
|
|
123
|
+
assert.equal(current_browser.context.closed, false);
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
test("默认 context 不存在时返回 resolve-context 且不创建隔离 context", async () => {
|
|
127
|
+
current_browser = create_browser({ contexts: () => [] });
|
|
128
|
+
const provider = new PlaywrightBrowserProvider({
|
|
129
|
+
cdp_url: "ws://user:password@127.0.0.1:9222/devtools/browser/id?token=secret",
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
await assert.rejects(
|
|
133
|
+
provider.create_session({}),
|
|
134
|
+
(error) => {
|
|
135
|
+
assert.match(error.message, /during resolve-context/);
|
|
136
|
+
assert.match(error.message, /ws:\/\/127\.0\.0\.1:9222/);
|
|
137
|
+
assert.doesNotMatch(error.message, /user|password|token|browser\/id/);
|
|
138
|
+
return true;
|
|
139
|
+
},
|
|
140
|
+
);
|
|
141
|
+
assert.equal(current_browser.new_context_calls, 0);
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
test("page 创建失败时返回 create-page 且保留默认 context", async () => {
|
|
145
|
+
current_browser = create_browser();
|
|
146
|
+
current_browser.context.newPage = async () => {
|
|
147
|
+
throw new Error(
|
|
148
|
+
"Protocol error for ws://user:pass@127.0.0.1:9222/devtools/browser/private?token=secret",
|
|
149
|
+
);
|
|
150
|
+
};
|
|
151
|
+
const provider = new PlaywrightBrowserProvider({
|
|
152
|
+
cdp_url: "ws://user:password@127.0.0.1:9222/devtools/browser/id?token=secret",
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
await assert.rejects(
|
|
156
|
+
provider.create_session({}),
|
|
157
|
+
(error) => {
|
|
158
|
+
assert.match(error.message, /during create-page/);
|
|
159
|
+
assert.match(error.message, /ws:\/\/127\.0\.0\.1:9222/);
|
|
160
|
+
assert.doesNotMatch(error.message, /user|pass|token|private|browser\/id/);
|
|
161
|
+
return true;
|
|
162
|
+
},
|
|
163
|
+
);
|
|
164
|
+
assert.equal(current_browser.context.closed, false);
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
test("页面初始化失败时关闭新 page 并复用 browser connection", async () => {
|
|
168
|
+
current_browser = create_browser();
|
|
169
|
+
const first_page = current_browser.session_page;
|
|
170
|
+
first_page.goto = async () => {
|
|
171
|
+
throw new Error("Navigation failed for https://example.com/private?token=secret");
|
|
172
|
+
};
|
|
173
|
+
const second_page = create_page();
|
|
174
|
+
current_browser.context.newPage = async () => {
|
|
175
|
+
current_browser.context.new_page_calls += 1;
|
|
176
|
+
return current_browser.context.new_page_calls === 1 ? first_page : second_page;
|
|
177
|
+
};
|
|
178
|
+
const provider = new PlaywrightBrowserProvider({
|
|
179
|
+
cdp_url: "http://127.0.0.1:9222",
|
|
180
|
+
});
|
|
181
|
+
|
|
182
|
+
await assert.rejects(
|
|
183
|
+
provider.create_session({ url: "https://example.com/private" }),
|
|
184
|
+
(error) => {
|
|
185
|
+
assert.match(error.message, /during initialize-page/);
|
|
186
|
+
assert.doesNotMatch(error.message, /private|token|secret/);
|
|
187
|
+
return true;
|
|
188
|
+
},
|
|
189
|
+
);
|
|
190
|
+
assert.equal(first_page.closed, true);
|
|
191
|
+
|
|
192
|
+
const result = await provider.create_session({ url: "https://example.com" });
|
|
193
|
+
assert.equal(connect_calls.length, 1);
|
|
194
|
+
assert.equal(second_page.closed, false);
|
|
195
|
+
await provider.close_session({ session_id: result.session_id });
|
|
196
|
+
});
|
|
197
|
+
|
|
198
|
+
test("连接失败返回脱敏 connect 错误", async () => {
|
|
199
|
+
current_browser = new Error(
|
|
200
|
+
"connect ECONNREFUSED ws://user:pass@127.0.0.1:9222/devtools/browser/id?token=secret",
|
|
201
|
+
);
|
|
202
|
+
const provider = new PlaywrightBrowserProvider({
|
|
203
|
+
cdp_url: "ws://user:password@127.0.0.1:9222/devtools/browser/id?token=secret",
|
|
204
|
+
});
|
|
205
|
+
|
|
206
|
+
await assert.rejects(
|
|
207
|
+
provider.create_session({}),
|
|
208
|
+
(error) => {
|
|
209
|
+
assert.match(error.message, /during connect/);
|
|
210
|
+
assert.match(error.message, /ws:\/\/127\.0\.0\.1:9222/);
|
|
211
|
+
assert.doesNotMatch(error.message, /user|pass|token|secret|browser\/id/);
|
|
212
|
+
return true;
|
|
213
|
+
},
|
|
214
|
+
);
|
|
215
|
+
});
|
|
216
|
+
|
|
217
|
+
test("browser disconnected 后清理 session registry", async () => {
|
|
218
|
+
const provider = new PlaywrightBrowserProvider({
|
|
219
|
+
cdp_url: "http://127.0.0.1:9222",
|
|
220
|
+
});
|
|
221
|
+
const result = await provider.create_session({});
|
|
222
|
+
|
|
223
|
+
current_browser.disconnect();
|
|
224
|
+
|
|
225
|
+
await assert.rejects(
|
|
226
|
+
provider.observe({ session_id: result.session_id }),
|
|
227
|
+
/Browser session not found/,
|
|
228
|
+
);
|
|
229
|
+
});
|
|
230
|
+
|
|
231
|
+
test("旧 browser 延迟断开不会清理新连接的 session", async () => {
|
|
232
|
+
const first_browser = current_browser;
|
|
233
|
+
const provider = new PlaywrightBrowserProvider({
|
|
234
|
+
cdp_url: "http://127.0.0.1:9222",
|
|
235
|
+
});
|
|
236
|
+
await provider.create_session({});
|
|
237
|
+
|
|
238
|
+
first_browser.connected = false;
|
|
239
|
+
current_browser = create_browser();
|
|
240
|
+
const result = await provider.create_session({});
|
|
241
|
+
first_browser.disconnect();
|
|
242
|
+
|
|
243
|
+
const observation = await provider.observe({ session_id: result.session_id });
|
|
244
|
+
assert.equal(observation.session_id, result.session_id);
|
|
245
|
+
assert.equal(connect_calls.length, 2);
|
|
246
|
+
});
|
|
247
|
+
|
|
248
|
+
test("dispose 关闭 provider page 和 CDP connection,不关闭默认 context", async () => {
|
|
249
|
+
const provider = new PlaywrightBrowserProvider({
|
|
250
|
+
cdp_url: "http://127.0.0.1:9222",
|
|
251
|
+
});
|
|
252
|
+
await provider.create_session({});
|
|
253
|
+
|
|
254
|
+
await provider.dispose();
|
|
255
|
+
|
|
256
|
+
assert.equal(current_browser.session_page.closed, true);
|
|
257
|
+
assert.equal(current_browser.existing_page.closed, false);
|
|
258
|
+
assert.equal(current_browser.context.closed, false);
|
|
259
|
+
assert.equal(current_browser.closed, true);
|
|
260
|
+
});
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
/** Plugin main 的 Profile action 与凭据边界测试。 */
|
|
2
|
+
|
|
3
|
+
import assert from "node:assert/strict";
|
|
4
|
+
import test from "node:test";
|
|
5
|
+
import { CHAT_PLUGIN_MAIN } from "../bin/chat/main/ChatPluginMain.js";
|
|
6
|
+
|
|
7
|
+
/** 激活 main 并返回按 ID 注册的 action。 */
|
|
8
|
+
async function activate_chat_main() {
|
|
9
|
+
const actions = new Map();
|
|
10
|
+
await CHAT_PLUGIN_MAIN.activate({
|
|
11
|
+
plugin: {
|
|
12
|
+
id: "chat",
|
|
13
|
+
action(action) {
|
|
14
|
+
actions.set(action.id, action);
|
|
15
|
+
},
|
|
16
|
+
},
|
|
17
|
+
logger: {
|
|
18
|
+
debug() {},
|
|
19
|
+
info() {},
|
|
20
|
+
warn() {},
|
|
21
|
+
error() {},
|
|
22
|
+
},
|
|
23
|
+
system: {
|
|
24
|
+
async open_external() {},
|
|
25
|
+
async show_item_in_folder() {},
|
|
26
|
+
async write_clipboard_text() {},
|
|
27
|
+
},
|
|
28
|
+
});
|
|
29
|
+
return actions;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/** 创建可观察完整替换结果的 Profile 配置上下文。 */
|
|
33
|
+
function create_config_context(initial_config) {
|
|
34
|
+
let config = structuredClone(initial_config);
|
|
35
|
+
return {
|
|
36
|
+
context: {
|
|
37
|
+
config: {
|
|
38
|
+
async get() {
|
|
39
|
+
return structuredClone(config);
|
|
40
|
+
},
|
|
41
|
+
async set(next) {
|
|
42
|
+
config = structuredClone(next);
|
|
43
|
+
},
|
|
44
|
+
},
|
|
45
|
+
},
|
|
46
|
+
read: () => structuredClone(config),
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
test("Chat main 读取 Profile 时不泄漏 Channel 凭据", async () => {
|
|
51
|
+
const actions = await activate_chat_main();
|
|
52
|
+
const store = create_config_context({
|
|
53
|
+
channels: [
|
|
54
|
+
{ id: "telegram_main", type: "telegram", name: "Main", bot_token: "telegram-secret" },
|
|
55
|
+
{ id: "feishu_main", type: "feishu", name: "Work", app_id: "cli_a", app_secret: "feishu-secret" },
|
|
56
|
+
],
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
const profile = await actions.get("profile.read").run(undefined, store.context);
|
|
60
|
+
|
|
61
|
+
assert.equal(JSON.stringify(profile).includes("telegram-secret"), false);
|
|
62
|
+
assert.equal(JSON.stringify(profile).includes("feishu-secret"), false);
|
|
63
|
+
assert.deepEqual(profile.channels.map((channel) => channel.secret_configured), [true, true]);
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
test("Chat main 保存时为空的凭据输入会保留已有凭据", async () => {
|
|
67
|
+
const actions = await activate_chat_main();
|
|
68
|
+
const store = create_config_context({
|
|
69
|
+
channels: [
|
|
70
|
+
{ id: "telegram_main", type: "telegram", name: "Old", bot_token: "kept-secret" },
|
|
71
|
+
],
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
const result = await actions.get("profile.save").run({
|
|
75
|
+
queue: { max_concurrency: 4 },
|
|
76
|
+
channels: [{
|
|
77
|
+
id: "telegram_main",
|
|
78
|
+
type: "telegram",
|
|
79
|
+
name: "New",
|
|
80
|
+
bot_token: "",
|
|
81
|
+
secret_configured: true,
|
|
82
|
+
}],
|
|
83
|
+
}, store.context);
|
|
84
|
+
|
|
85
|
+
assert.equal(store.read().channels[0].bot_token, "kept-secret");
|
|
86
|
+
assert.equal(result.channels[0].secret_configured, true);
|
|
87
|
+
assert.equal("bot_token" in result.channels[0], false);
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
test("Chat main 拒绝没有凭据的新 Channel", async () => {
|
|
91
|
+
const actions = await activate_chat_main();
|
|
92
|
+
const store = create_config_context({ channels: [] });
|
|
93
|
+
|
|
94
|
+
await assert.rejects(
|
|
95
|
+
() => actions.get("profile.save").run({
|
|
96
|
+
queue: {},
|
|
97
|
+
channels: [{ id: "telegram_new", type: "telegram", name: "New" }],
|
|
98
|
+
}, store.context),
|
|
99
|
+
/Telegram Bot Token is required/u,
|
|
100
|
+
);
|
|
101
|
+
});
|
|
@@ -48,3 +48,39 @@ test("根入口不再导出默认内建集合工厂", async () => {
|
|
|
48
48
|
assert.equal("createBuiltinPlugins" in plugin_module, false);
|
|
49
49
|
assert.equal("BUILTIN_PLUGIN_CLASSES" in plugin_module, false);
|
|
50
50
|
});
|
|
51
|
+
|
|
52
|
+
test("Renderer 子路径统一导出 React Mainview registry", async () => {
|
|
53
|
+
const plugin_react = await import("@downcity/plugin/react");
|
|
54
|
+
const renderers = await import("@downcity/plugins/renderers");
|
|
55
|
+
assert.equal(typeof plugin_react.define_plugin_renderer, "function");
|
|
56
|
+
assert.deepEqual(Object.keys(renderers.BUILTIN_PLUGIN_RENDERERS).sort(), [
|
|
57
|
+
"chat",
|
|
58
|
+
"image",
|
|
59
|
+
"sound",
|
|
60
|
+
"web",
|
|
61
|
+
]);
|
|
62
|
+
for (const renderer of Object.values(renderers.BUILTIN_PLUGIN_RENDERERS)) {
|
|
63
|
+
assert.equal(typeof renderer, "function");
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
test("内建 Plugin 子路径不再公开宿主通用配置 Schema", async () => {
|
|
68
|
+
const schema_exports = [
|
|
69
|
+
["chat", "CHAT_PLUGIN_CONFIG_JSON_SCHEMA"],
|
|
70
|
+
["image", "IMAGE_PLUGIN_CONFIG_JSON_SCHEMA"],
|
|
71
|
+
["sound", "SOUND_PLUGIN_CONFIG_JSON_SCHEMA"],
|
|
72
|
+
["web", "WEB_PLUGIN_CONFIG_JSON_SCHEMA"],
|
|
73
|
+
];
|
|
74
|
+
for (const [plugin_name, export_name] of schema_exports) {
|
|
75
|
+
const plugin_module = await import(`@downcity/plugins/${plugin_name}`);
|
|
76
|
+
assert.equal(export_name in plugin_module, false, `${plugin_name} 不应导出 ${export_name}`);
|
|
77
|
+
}
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
test("memory 子路径导出 Provider 与 Storage Adapter", async () => {
|
|
81
|
+
const memory_module = await import("@downcity/plugins/memory");
|
|
82
|
+
assert.equal(typeof memory_module.MemoryPlugin, "function");
|
|
83
|
+
assert.equal(typeof memory_module.BuiltinMemoryProvider, "function");
|
|
84
|
+
assert.equal(typeof memory_module.FileMemoryStorageAdapter, "function");
|
|
85
|
+
assert.equal(typeof memory_module.get_default_file_memory_root_path, "function");
|
|
86
|
+
});
|