@zhin.js/core 1.1.33 → 1.1.35
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/README.md +140 -61
- package/lib/adapter.d.ts +72 -23
- package/lib/adapter.js +222 -58
- package/lib/built/adapter-process.d.ts +20 -5
- package/lib/built/adapter-process.js +54 -7
- package/lib/built/agent-preset.d.ts +1 -2
- package/lib/built/agent-preset.js +1 -2
- package/lib/built/ai-access.d.ts +36 -0
- package/lib/built/ai-access.js +46 -0
- package/lib/built/ai-outbound/adapter-access.d.ts +3 -0
- package/lib/built/ai-outbound/adapter-access.js +9 -0
- package/lib/built/ai-outbound/extensions/onebot-keyboard.d.ts +2 -0
- package/lib/built/ai-outbound/extensions/onebot-keyboard.js +67 -0
- package/lib/built/ai-outbound/extensions/qq-message.d.ts +3 -0
- package/lib/built/ai-outbound/extensions/qq-message.js +23 -0
- package/lib/built/ai-outbound/index.d.ts +9 -0
- package/lib/built/ai-outbound/index.js +9 -0
- package/lib/built/ai-outbound/parse.d.ts +13 -0
- package/lib/built/ai-outbound/parse.js +104 -0
- package/lib/built/ai-outbound/plain-mention-rewrite.d.ts +6 -0
- package/lib/built/ai-outbound/plain-mention-rewrite.js +37 -0
- package/lib/built/ai-outbound/prompt.d.ts +11 -0
- package/lib/built/ai-outbound/prompt.js +44 -0
- package/lib/built/ai-outbound/resolve.d.ts +4 -0
- package/lib/built/ai-outbound/resolve.js +64 -0
- package/lib/built/ai-outbound/structured-detect.d.ts +3 -0
- package/lib/built/ai-outbound/structured-detect.js +6 -0
- package/lib/built/ai-outbound/types.d.ts +58 -0
- package/lib/built/ai-outbound/types.js +5 -0
- package/lib/built/ai-trigger.d.ts +17 -17
- package/lib/built/ai-trigger.js +65 -70
- package/lib/built/authorization.d.ts +10 -0
- package/lib/built/authorization.js +76 -0
- package/lib/built/command.d.ts +9 -5
- package/lib/built/command.js +20 -7
- package/lib/built/common-adapter-tools.d.ts +35 -29
- package/lib/built/common-adapter-tools.js +83 -67
- package/lib/built/component.d.ts +1 -3
- package/lib/built/component.js +2 -4
- package/lib/built/config.d.ts +4 -5
- package/lib/built/config.js +26 -9
- package/lib/built/connect-endpoint-instance.d.ts +17 -0
- package/lib/built/connect-endpoint-instance.js +42 -0
- package/lib/built/database.d.ts +5 -3
- package/lib/built/database.js +10 -4
- package/lib/built/dispatcher.d.ts +10 -8
- package/lib/built/dispatcher.js +31 -9
- package/lib/built/endpoint-commands.d.ts +3 -0
- package/lib/built/endpoint-commands.js +99 -0
- package/lib/built/endpoint-lifecycle-service.d.ts +28 -0
- package/lib/built/endpoint-lifecycle-service.js +242 -0
- package/lib/built/endpoint-lifecycle.d.ts +27 -0
- package/lib/built/endpoint-lifecycle.js +36 -0
- package/lib/built/endpoint-manager.d.ts +34 -0
- package/lib/built/endpoint-manager.js +1 -0
- package/lib/built/generated-qrcode.d.ts +24 -0
- package/lib/built/generated-qrcode.js +45 -0
- package/lib/built/generic-segment-mapper.d.ts +4 -0
- package/lib/built/generic-segment-mapper.js +190 -0
- package/lib/built/html-renderer-loader.d.ts +13 -0
- package/lib/built/html-renderer-loader.js +33 -0
- package/lib/built/html-segment-fallback.d.ts +9 -0
- package/lib/built/html-segment-fallback.js +49 -0
- package/lib/built/html-to-text.d.ts +4 -1
- package/lib/built/html-to-text.js +47 -16
- package/lib/built/inbound-pipeline.d.ts +37 -0
- package/lib/built/inbound-pipeline.js +63 -0
- package/lib/built/inbound-runner.d.ts +0 -1
- package/lib/built/inbound-runner.js +0 -3
- package/lib/built/interactive-segment-contract.d.ts +6 -0
- package/lib/built/interactive-segment-contract.js +9 -0
- package/lib/built/interactive-segments/action.d.ts +17 -0
- package/lib/built/interactive-segments/action.js +69 -0
- package/lib/built/interactive-segments/button-spec.d.ts +10 -0
- package/lib/built/interactive-segments/button-spec.js +21 -0
- package/lib/built/interactive-segments/fallback-store.d.ts +29 -0
- package/lib/built/interactive-segments/fallback-store.js +63 -0
- package/lib/built/interactive-segments/handlers.d.ts +16 -0
- package/lib/built/interactive-segments/handlers.js +74 -0
- package/lib/built/interactive-segments/index.d.ts +8 -0
- package/lib/built/interactive-segments/index.js +8 -0
- package/lib/built/interactive-segments/keyboard-segment.d.ts +11 -0
- package/lib/built/interactive-segments/keyboard-segment.js +12 -0
- package/lib/built/interactive-segments/onebot-keyboard.d.ts +7 -0
- package/lib/built/interactive-segments/onebot-keyboard.js +51 -0
- package/lib/built/interactive-segments/resolve.d.ts +15 -0
- package/lib/built/interactive-segments/resolve.js +110 -0
- package/lib/built/interactive-segments/types.d.ts +50 -0
- package/lib/built/interactive-segments/types.js +9 -0
- package/lib/built/introspection-format.d.ts +10 -0
- package/lib/built/introspection-format.js +28 -0
- package/lib/built/login-assist.d.ts +43 -9
- package/lib/built/login-assist.js +113 -11
- package/lib/built/management-command-guard.d.ts +15 -0
- package/lib/built/management-command-guard.js +25 -0
- package/lib/built/message-enrich.d.ts +38 -0
- package/lib/built/message-enrich.js +75 -0
- package/lib/built/message-filter.d.ts +4 -5
- package/lib/built/message-filter.js +5 -7
- package/lib/built/optional-peer-import.d.ts +3 -0
- package/lib/built/optional-peer-import.js +33 -0
- package/lib/built/outbound-media-contract.d.ts +22 -0
- package/lib/built/outbound-media-contract.js +10 -0
- package/lib/built/outbound-media-utils.d.ts +9 -0
- package/lib/built/outbound-media-utils.js +62 -0
- package/lib/built/permission.d.ts +3 -7
- package/lib/built/permission.js +39 -52
- package/lib/built/permit-check.d.ts +7 -0
- package/lib/built/permit-check.js +35 -0
- package/lib/built/permit-parse.d.ts +16 -0
- package/lib/built/permit-parse.js +32 -0
- package/lib/built/platform-permit.d.ts +20 -0
- package/lib/built/platform-permit.js +91 -0
- package/lib/built/queue-im-field-contract.d.ts +7 -2
- package/lib/built/queue-im-field-contract.js +13 -4
- package/lib/built/rich-segments/adapter-policies.d.ts +9 -0
- package/lib/built/rich-segments/adapter-policies.js +27 -0
- package/lib/built/rich-segments/base.d.ts +11 -0
- package/lib/built/rich-segments/base.js +24 -0
- package/lib/built/rich-segments/builtins.d.ts +4 -0
- package/lib/built/rich-segments/builtins.js +40 -0
- package/lib/built/rich-segments/capabilities.d.ts +6 -0
- package/lib/built/rich-segments/capabilities.js +38 -0
- package/lib/built/rich-segments/html-segment.d.ts +15 -0
- package/lib/built/rich-segments/html-segment.js +62 -0
- package/lib/built/rich-segments/index.d.ts +13 -0
- package/lib/built/rich-segments/index.js +13 -0
- package/lib/built/rich-segments/markdown-segment.d.ts +14 -0
- package/lib/built/rich-segments/markdown-segment.js +58 -0
- package/lib/built/rich-segments/markdown-to-text.d.ts +3 -0
- package/lib/built/rich-segments/markdown-to-text.js +27 -0
- package/lib/built/rich-segments/qrcode-segment.d.ts +18 -0
- package/lib/built/rich-segments/qrcode-segment.js +73 -0
- package/lib/built/rich-segments/registry.d.ts +16 -0
- package/lib/built/rich-segments/registry.js +52 -0
- package/lib/built/rich-segments/resolve.d.ts +5 -0
- package/lib/built/rich-segments/resolve.js +87 -0
- package/lib/built/rich-segments/tts-segment.d.ts +13 -0
- package/lib/built/rich-segments/tts-segment.js +51 -0
- package/lib/built/rich-segments/types.d.ts +79 -0
- package/lib/built/rich-segments/types.js +17 -0
- package/lib/built/roles.d.ts +4 -5
- package/lib/built/roles.js +4 -5
- package/lib/built/runtime-io.d.ts +0 -1
- package/lib/built/runtime-io.js +0 -1
- package/lib/built/schedule.d.ts +54 -0
- package/lib/built/schedule.js +112 -0
- package/lib/built/schema-endpoint-manager.d.ts +17 -0
- package/lib/built/schema-endpoint-manager.js +73 -0
- package/lib/built/schema-feature.d.ts +0 -1
- package/lib/built/schema-feature.js +1 -3
- package/lib/built/segment-contract/assert.d.ts +7 -0
- package/lib/built/segment-contract/assert.js +39 -0
- package/lib/built/segment-contract/delivery.d.ts +5 -0
- package/lib/built/segment-contract/delivery.js +40 -0
- package/lib/built/segment-contract/image.d.ts +5 -0
- package/lib/built/segment-contract/image.js +10 -0
- package/lib/built/segment-contract/index.d.ts +10 -0
- package/lib/built/segment-contract/index.js +9 -0
- package/lib/built/segment-contract/json-schema.d.ts +28 -0
- package/lib/built/segment-contract/json-schema.js +128 -0
- package/lib/built/segment-contract/media.d.ts +12 -0
- package/lib/built/segment-contract/media.js +22 -0
- package/lib/built/segment-contract/mention.d.ts +10 -0
- package/lib/built/segment-contract/mention.js +26 -0
- package/lib/built/segment-contract/preview.d.ts +3 -0
- package/lib/built/segment-contract/preview.js +159 -0
- package/lib/built/segment-contract/text.d.ts +7 -0
- package/lib/built/segment-contract/text.js +34 -0
- package/lib/built/segment-contract/types.d.ts +58 -0
- package/lib/built/segment-contract/types.js +1 -0
- package/lib/built/segment-contract/validate.d.ts +229 -0
- package/lib/built/segment-contract/validate.js +174 -0
- package/lib/built/skill.d.ts +0 -1
- package/lib/built/skill.js +0 -1
- package/lib/built/speech-loader.d.ts +14 -0
- package/lib/built/speech-loader.js +32 -0
- package/lib/built/tool.d.ts +14 -13
- package/lib/built/tool.js +30 -25
- package/lib/built/user-interaction.d.ts +30 -0
- package/lib/built/user-interaction.js +248 -0
- package/lib/command.d.ts +19 -11
- package/lib/command.js +42 -11
- package/lib/component.d.ts +0 -1
- package/lib/component.js +67 -14
- package/lib/endpoint-capabilities.d.ts +46 -0
- package/lib/endpoint-capabilities.js +55 -0
- package/lib/endpoint.d.ts +19 -0
- package/lib/endpoint.js +3 -0
- package/lib/errors.d.ts +2 -3
- package/lib/errors.js +4 -5
- package/lib/feature/adapter.d.ts +2 -0
- package/lib/feature/adapter.js +2 -0
- package/lib/feature/command.d.ts +2 -0
- package/lib/feature/command.js +2 -0
- package/lib/feature/component.d.ts +2 -0
- package/lib/feature/component.js +2 -0
- package/lib/feature/handler.d.ts +52 -0
- package/lib/feature/handler.js +26 -0
- package/lib/feature/middleware.d.ts +2 -0
- package/lib/feature/middleware.js +2 -0
- package/lib/host-plugin-registry.d.ts +8 -0
- package/lib/host-plugin-registry.js +12 -0
- package/lib/im-scene.d.ts +29 -0
- package/lib/im-scene.js +75 -0
- package/lib/im-session-id.d.ts +39 -0
- package/lib/im-session-id.js +47 -0
- package/lib/index.d.ts +59 -21
- package/lib/index.js +53 -28
- package/lib/jsx-dev-runtime.d.ts +0 -1
- package/lib/jsx-dev-runtime.js +0 -1
- package/lib/jsx-runtime.d.ts +1 -1
- package/lib/jsx-runtime.js +0 -1
- package/lib/jsx.d.ts +19 -22
- package/lib/jsx.js +0 -1
- package/lib/message.d.ts +16 -10
- package/lib/message.js +16 -13
- package/lib/models/system-log.d.ts +0 -1
- package/lib/models/system-log.js +0 -1
- package/lib/models/user.d.ts +0 -1
- package/lib/models/user.js +0 -1
- package/lib/notice.d.ts +16 -59
- package/lib/notice.js +1 -4
- package/lib/plugin-context.d.ts +27 -0
- package/lib/plugin-context.js +64 -0
- package/lib/plugin-runtime/im/contracts.d.ts +191 -0
- package/lib/plugin-runtime/im/contracts.js +169 -0
- package/lib/plugin-runtime/im/im-runtime.d.ts +177 -0
- package/lib/plugin-runtime/im/im-runtime.js +1204 -0
- package/lib/plugin-runtime/im/index.d.ts +9 -0
- package/lib/plugin-runtime/im/index.js +9 -0
- package/lib/plugin-runtime/im/interactive.d.ts +26 -0
- package/lib/plugin-runtime/im/interactive.js +46 -0
- package/lib/plugin-runtime/im/login-assist-host.d.ts +6 -0
- package/lib/plugin-runtime/im/login-assist-host.js +6 -0
- package/lib/plugin-runtime/im/message-bus.d.ts +38 -0
- package/lib/plugin-runtime/im/message-bus.js +40 -0
- package/lib/plugin-runtime/im/message-dispatcher.d.ts +18 -0
- package/lib/plugin-runtime/im/message-dispatcher.js +107 -0
- package/lib/plugin-runtime/im/outbound-renderer.d.ts +7 -0
- package/lib/plugin-runtime/im/outbound-renderer.js +70 -0
- package/lib/plugin-runtime/im/outbound-segments.d.ts +72 -0
- package/lib/plugin-runtime/im/outbound-segments.js +220 -0
- package/lib/plugin-runtime/im/public-api.d.ts +6 -0
- package/lib/plugin-runtime/im/public-api.js +6 -0
- package/lib/plugin-runtime/im/service-tokens.d.ts +18 -0
- package/lib/plugin-runtime/im/service-tokens.js +13 -0
- package/lib/plugin.d.ts +34 -24
- package/lib/plugin.js +119 -224
- package/lib/request.d.ts +17 -61
- package/lib/request.js +0 -4
- package/lib/{prompt.d.ts → schema-interaction.d.ts} +6 -7
- package/lib/{prompt.js → schema-interaction.js} +20 -17
- package/lib/side-event/base.d.ts +52 -0
- package/lib/side-event/base.js +30 -0
- package/lib/side-event/dispatch.d.ts +15 -0
- package/lib/side-event/dispatch.js +140 -0
- package/lib/side-event/index.d.ts +4 -0
- package/lib/side-event/index.js +4 -0
- package/lib/side-event/normalize.d.ts +42 -0
- package/lib/side-event/normalize.js +121 -0
- package/lib/side-event/types.d.ts +23 -0
- package/lib/side-event/types.js +55 -0
- package/lib/system-event.d.ts +15 -0
- package/lib/system-event.js +7 -0
- package/lib/tool-zod.d.ts +18 -3
- package/lib/tool-zod.js +140 -54
- package/lib/types.d.ts +44 -85
- package/lib/types.js +0 -1
- package/lib/utils.d.ts +68 -1
- package/lib/utils.js +73 -11
- package/package.json +98 -10
- package/lib/adapter.d.ts.map +0 -1
- package/lib/adapter.js.map +0 -1
- package/lib/agent-prompt.d.ts +0 -37
- package/lib/agent-prompt.d.ts.map +0 -1
- package/lib/agent-prompt.js +0 -2
- package/lib/agent-prompt.js.map +0 -1
- package/lib/bot.d.ts +0 -38
- package/lib/bot.d.ts.map +0 -1
- package/lib/bot.js +0 -2
- package/lib/bot.js.map +0 -1
- package/lib/built/adapter-process.d.ts.map +0 -1
- package/lib/built/adapter-process.js.map +0 -1
- package/lib/built/agent-preset.d.ts.map +0 -1
- package/lib/built/agent-preset.js.map +0 -1
- package/lib/built/ai-trigger.d.ts.map +0 -1
- package/lib/built/ai-trigger.js.map +0 -1
- package/lib/built/command.d.ts.map +0 -1
- package/lib/built/command.js.map +0 -1
- package/lib/built/common-adapter-tools.d.ts.map +0 -1
- package/lib/built/common-adapter-tools.js.map +0 -1
- package/lib/built/component.d.ts.map +0 -1
- package/lib/built/component.js.map +0 -1
- package/lib/built/config.d.ts.map +0 -1
- package/lib/built/config.js.map +0 -1
- package/lib/built/cron.d.ts +0 -75
- package/lib/built/cron.d.ts.map +0 -1
- package/lib/built/cron.js +0 -122
- package/lib/built/cron.js.map +0 -1
- package/lib/built/database.d.ts.map +0 -1
- package/lib/built/database.js.map +0 -1
- package/lib/built/dispatcher.d.ts.map +0 -1
- package/lib/built/dispatcher.js.map +0 -1
- package/lib/built/html-to-text.d.ts.map +0 -1
- package/lib/built/html-to-text.js.map +0 -1
- package/lib/built/inbound-runner.d.ts.map +0 -1
- package/lib/built/inbound-runner.js.map +0 -1
- package/lib/built/login-assist.d.ts.map +0 -1
- package/lib/built/login-assist.js.map +0 -1
- package/lib/built/message-filter.d.ts.map +0 -1
- package/lib/built/message-filter.js.map +0 -1
- package/lib/built/permission.d.ts.map +0 -1
- package/lib/built/permission.js.map +0 -1
- package/lib/built/prepend-quote-context.d.ts +0 -33
- package/lib/built/prepend-quote-context.d.ts.map +0 -1
- package/lib/built/prepend-quote-context.js +0 -129
- package/lib/built/prepend-quote-context.js.map +0 -1
- package/lib/built/queue-im-field-contract.d.ts.map +0 -1
- package/lib/built/queue-im-field-contract.js.map +0 -1
- package/lib/built/roles.d.ts.map +0 -1
- package/lib/built/roles.js.map +0 -1
- package/lib/built/runtime-io.d.ts.map +0 -1
- package/lib/built/runtime-io.js.map +0 -1
- package/lib/built/schema-feature.d.ts.map +0 -1
- package/lib/built/schema-feature.js.map +0 -1
- package/lib/built/skill.d.ts.map +0 -1
- package/lib/built/skill.js.map +0 -1
- package/lib/built/tool.d.ts.map +0 -1
- package/lib/built/tool.js.map +0 -1
- package/lib/command.d.ts.map +0 -1
- package/lib/command.js.map +0 -1
- package/lib/component.d.ts.map +0 -1
- package/lib/component.js.map +0 -1
- package/lib/errors.d.ts.map +0 -1
- package/lib/errors.js.map +0 -1
- package/lib/index.d.ts.map +0 -1
- package/lib/index.js.map +0 -1
- package/lib/jsx-dev-runtime.d.ts.map +0 -1
- package/lib/jsx-dev-runtime.js.map +0 -1
- package/lib/jsx-runtime.d.ts.map +0 -1
- package/lib/jsx-runtime.js.map +0 -1
- package/lib/jsx.d.ts.map +0 -1
- package/lib/jsx.js.map +0 -1
- package/lib/message-quote.d.ts +0 -11
- package/lib/message-quote.d.ts.map +0 -1
- package/lib/message-quote.js +0 -91
- package/lib/message-quote.js.map +0 -1
- package/lib/message.d.ts.map +0 -1
- package/lib/message.js.map +0 -1
- package/lib/models/system-log.d.ts.map +0 -1
- package/lib/models/system-log.js.map +0 -1
- package/lib/models/user.d.ts.map +0 -1
- package/lib/models/user.js.map +0 -1
- package/lib/notice.d.ts.map +0 -1
- package/lib/notice.js.map +0 -1
- package/lib/plugin.d.ts.map +0 -1
- package/lib/plugin.js.map +0 -1
- package/lib/prompt.d.ts.map +0 -1
- package/lib/prompt.js.map +0 -1
- package/lib/request.d.ts.map +0 -1
- package/lib/request.js.map +0 -1
- package/lib/scheduler/scheduler.d.ts +0 -49
- package/lib/scheduler/scheduler.d.ts.map +0 -1
- package/lib/scheduler/scheduler.js +0 -352
- package/lib/scheduler/scheduler.js.map +0 -1
- package/lib/scheduler/types.d.ts +0 -71
- package/lib/scheduler/types.d.ts.map +0 -1
- package/lib/scheduler/types.js +0 -8
- package/lib/scheduler/types.js.map +0 -1
- package/lib/tool-zod.d.ts.map +0 -1
- package/lib/tool-zod.js.map +0 -1
- package/lib/types-generator.d.ts +0 -6
- package/lib/types-generator.d.ts.map +0 -1
- package/lib/types-generator.js +0 -72
- package/lib/types-generator.js.map +0 -1
- package/lib/types.d.ts.map +0 -1
- package/lib/types.js.map +0 -1
- package/lib/utils.d.ts.map +0 -1
- package/lib/utils.js.map +0 -1
package/lib/adapter.js
CHANGED
|
@@ -1,8 +1,16 @@
|
|
|
1
|
+
import { assertOutbound, DEFAULT_ENDPOINT_CAPABILITIES, hasInbound, } from "./endpoint-capabilities.js";
|
|
2
|
+
import { endpointControlOf } from "@zhin.js/adapter";
|
|
3
|
+
import { connectEndpointInstance, disconnectEndpointInstance } from "./built/connect-endpoint-instance.js";
|
|
1
4
|
import { EventEmitter } from "node:events";
|
|
2
5
|
import { getOutboundReplyStore } from "./built/dispatcher.js";
|
|
6
|
+
import { DEFAULT_OUTBOUND_RICH_SEGMENT_POLICY, resolveRichSegments, } from "./built/rich-segments/index.js";
|
|
7
|
+
import { DEFAULT_INTERACTIVE_POLICY, collectKeyboardFallbackMaps, keyboardFallbackStore, resolveKeyboardSegments, } from "./built/interactive-segments/index.js";
|
|
8
|
+
import { DEFAULT_AI_OUTBOUND_CAPABILITIES, } from "./built/ai-outbound/index.js";
|
|
9
|
+
import { createRichSegmentRenderContext } from "./built/rich-segments/capabilities.js";
|
|
10
|
+
import { collectOutboundMediaKinds } from "./built/outbound-media-utils.js";
|
|
3
11
|
import { segment } from "./utils.js";
|
|
4
|
-
import {
|
|
5
|
-
import { formatCompact, truncatePreview } from '@zhin.js/logger';
|
|
12
|
+
import { InboundMessagePipeline } from "./built/inbound-pipeline.js";
|
|
13
|
+
import { formatCompact, truncatePreview, formatContentChainLog, CONTENT_CHAIN_STAGE } from '@zhin.js/logger';
|
|
6
14
|
/**
|
|
7
15
|
* Adapter类:适配器抽象,管理多平台Bot实例。
|
|
8
16
|
* 负责根据配置启动/关闭各平台机器人,统一异常处理。
|
|
@@ -13,8 +21,21 @@ export class Adapter extends EventEmitter {
|
|
|
13
21
|
plugin;
|
|
14
22
|
name;
|
|
15
23
|
config;
|
|
16
|
-
|
|
17
|
-
|
|
24
|
+
endpoints = new Map();
|
|
25
|
+
recallMessageHandler;
|
|
26
|
+
/** Adapter 支持的能力上限(子类覆盖) */
|
|
27
|
+
static capabilities = DEFAULT_ENDPOINT_CAPABILITIES;
|
|
28
|
+
/** 出站富媒体段渲染策略(子类 override static) */
|
|
29
|
+
static outboundRichSegmentPolicy = DEFAULT_OUTBOUND_RICH_SEGMENT_POLICY;
|
|
30
|
+
/** 交互段出站策略:native 保留按钮段,text 降级为编号文本 */
|
|
31
|
+
static interactivePolicy = DEFAULT_INTERACTIVE_POLICY;
|
|
32
|
+
/** AI 结构化出站能力声明(mentions / richSegments / interactive) */
|
|
33
|
+
static aiOutboundCapabilities = DEFAULT_AI_OUTBOUND_CAPABILITIES;
|
|
34
|
+
/** 平台特有 extensions schema + 解析(对齐各 SDK 文档子集) */
|
|
35
|
+
static aiOutboundExtensions;
|
|
36
|
+
getInteractivePolicy() {
|
|
37
|
+
return this.constructor.interactivePolicy;
|
|
38
|
+
}
|
|
18
39
|
/** 入站消息并发计数 */
|
|
19
40
|
#pendingMessages = 0;
|
|
20
41
|
/** 并发上限,0 表示不限制(默认) */
|
|
@@ -34,61 +55,54 @@ export class Adapter extends EventEmitter {
|
|
|
34
55
|
return this.#pendingMessages;
|
|
35
56
|
}
|
|
36
57
|
/**
|
|
37
|
-
*
|
|
58
|
+
* 创建一个适配器运行实例。
|
|
59
|
+
* @param plugin 拥有该适配器的插件实例
|
|
38
60
|
* @param name 适配器名称(如 'process'、'qq' 等)
|
|
39
|
-
* @param
|
|
61
|
+
* @param config Endpoint 配置列表
|
|
40
62
|
*/
|
|
41
63
|
constructor(plugin, name, config) {
|
|
42
64
|
super();
|
|
43
65
|
this.plugin = plugin;
|
|
44
66
|
this.name = name;
|
|
45
67
|
this.config = config;
|
|
46
|
-
this.
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
this.logger
|
|
51
|
-
|
|
68
|
+
this.recallMessageHandler = (endpoint_id, id) => this.recallEndpointMessage(endpoint_id, id);
|
|
69
|
+
this.on('call.recallMessage', this.recallMessageHandler);
|
|
70
|
+
this.inboundPipeline = new InboundMessagePipeline({
|
|
71
|
+
getPlugin: () => this.plugin,
|
|
72
|
+
logger: this.logger,
|
|
73
|
+
getMaxConcurrentMessages: () => this.maxConcurrentMessages,
|
|
74
|
+
getPendingMessages: () => this.#pendingMessages,
|
|
75
|
+
decrementPending: () => {
|
|
76
|
+
// stop() may zero the counter while in-flight receives still finish;
|
|
77
|
+
// never let the budget go negative.
|
|
78
|
+
this.#pendingMessages = Math.max(0, this.#pendingMessages - 1);
|
|
79
|
+
},
|
|
52
80
|
});
|
|
53
81
|
}
|
|
82
|
+
/** 入站消息管线(替代 emit override 的隐式管线) */
|
|
83
|
+
inboundPipeline;
|
|
54
84
|
/**
|
|
55
|
-
* 重写 emit:拦截 message.receive
|
|
56
|
-
*
|
|
57
|
-
*
|
|
58
|
-
* 以属性 + `EventEmitter.prototype.emit` 调用满足 Node @types 25 对泛型 `emit` 的可赋值检查。
|
|
85
|
+
* 重写 emit:拦截 message.receive/notice.receive/request.receive 事件,
|
|
86
|
+
* 将入站处理委托给 InboundMessagePipeline。
|
|
59
87
|
*/
|
|
60
88
|
emit = ((event, ...args) => {
|
|
89
|
+
if (event === 'notice.receive' || event === 'request.receive') {
|
|
90
|
+
return this.inboundPipeline.bridgeNoticeOrRequest(event, args, () => EventEmitter.prototype.emit.call(this, event, ...args));
|
|
91
|
+
}
|
|
61
92
|
if (event !== 'message.receive') {
|
|
62
93
|
return EventEmitter.prototype.emit.call(this, event, ...args);
|
|
63
94
|
}
|
|
64
95
|
const message = args[0];
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
preview: truncatePreview(segment.raw(message.$content)),
|
|
69
|
-
...(message.$quote_id ? { quote_id: message.$quote_id } : {}),
|
|
70
|
-
}));
|
|
71
|
-
// 背压控制:limit > 0 时启用,超出并发上限丢弃消息并告警
|
|
72
|
-
const limit = this.maxConcurrentMessages;
|
|
73
|
-
if (limit > 0 && this.#pendingMessages >= limit) {
|
|
74
|
-
this.logger.warn(formatCompact({ drop: 'concurrency', limit }));
|
|
96
|
+
// 背压控制:同步返回 false 表示丢弃
|
|
97
|
+
if (this.inboundPipeline.shouldDropDueToBackpressure()) {
|
|
98
|
+
this.logger.warn(formatCompact({ op: 'backpressure_drop', limit: this.maxConcurrentMessages }));
|
|
75
99
|
return false;
|
|
76
100
|
}
|
|
101
|
+
// 同步计数,保证背压判断的准确性
|
|
77
102
|
this.#pendingMessages++;
|
|
78
|
-
//
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
plugin: this.plugin,
|
|
82
|
-
message,
|
|
83
|
-
emitAdapterObservers: () => {
|
|
84
|
-
EventEmitter.prototype.emit.call(this, event, ...args);
|
|
85
|
-
},
|
|
86
|
-
});
|
|
87
|
-
};
|
|
88
|
-
processing().catch((e) => {
|
|
89
|
-
this.logger.warn(`message.receive handling error: ${e instanceof Error ? e.message : String(e)}`);
|
|
90
|
-
}).finally(() => {
|
|
91
|
-
this.#pendingMessages--;
|
|
103
|
+
// 异步入站管线(middleware → dispatcher → 生命周期 → 观察者)
|
|
104
|
+
this.inboundPipeline.receive(message, () => {
|
|
105
|
+
EventEmitter.prototype.emit.call(this, event, ...args);
|
|
92
106
|
});
|
|
93
107
|
return true;
|
|
94
108
|
});
|
|
@@ -100,6 +114,28 @@ export class Adapter extends EventEmitter {
|
|
|
100
114
|
binding(plugin) {
|
|
101
115
|
this.plugin = plugin;
|
|
102
116
|
}
|
|
117
|
+
/**
|
|
118
|
+
* 同步等待入站管线结束(middleware → dispatcher → 生命周期 → 观察者)。
|
|
119
|
+
* 用于 QQ 等需在被动回复完成后再 ack 交互的平台事件。
|
|
120
|
+
*/
|
|
121
|
+
async receiveMessageAwait(message) {
|
|
122
|
+
if (this.inboundPipeline.shouldDropDueToBackpressure()) {
|
|
123
|
+
this.logger.warn(formatCompact({ drop: 'concurrency', limit: this.maxConcurrentMessages }));
|
|
124
|
+
return false;
|
|
125
|
+
}
|
|
126
|
+
this.#pendingMessages++;
|
|
127
|
+
try {
|
|
128
|
+
await this.inboundPipeline.receive(message, () => {
|
|
129
|
+
EventEmitter.prototype.emit.call(this, 'message.receive', message);
|
|
130
|
+
});
|
|
131
|
+
return true;
|
|
132
|
+
}
|
|
133
|
+
finally {
|
|
134
|
+
// Inbound pipeline errors must not leak the concurrency budget; the
|
|
135
|
+
// non-await path uses InboundMessagePipeline.decrementPending in finally.
|
|
136
|
+
this.#pendingMessages = Math.max(0, this.#pendingMessages - 1);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
103
139
|
/**
|
|
104
140
|
* 出站富媒体能力(Publisher 按此过滤/降级;各 adapter 可覆盖)。
|
|
105
141
|
*/
|
|
@@ -112,7 +148,52 @@ export class Adapter extends EventEmitter {
|
|
|
112
148
|
maxAttachmentBytes: 26_214_400,
|
|
113
149
|
};
|
|
114
150
|
}
|
|
151
|
+
getOutboundRichSegmentPolicy() {
|
|
152
|
+
return this.constructor.outboundRichSegmentPolicy;
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* 出站两阶段:
|
|
156
|
+
* 1. resolveRichSegments — 语义段 → 标准 IM 段(image/audio/text)
|
|
157
|
+
* 2. Endpoint materializeOutboundMedia — base64/本地路径 → 平台 URL(各 adapter 可选)
|
|
158
|
+
* @see docs/essentials/rich-segment-adapters.md
|
|
159
|
+
*/
|
|
115
160
|
async renderSendMessage(options) {
|
|
161
|
+
if (options.content != null) {
|
|
162
|
+
options = {
|
|
163
|
+
...options,
|
|
164
|
+
content: await resolveRichSegments(options.content, this.getOutboundRichSegmentPolicy(), createRichSegmentRenderContext({
|
|
165
|
+
getConfig: () => {
|
|
166
|
+
const cfg = this.plugin.root.inject('config')?.getPrimary();
|
|
167
|
+
return cfg;
|
|
168
|
+
},
|
|
169
|
+
warn: (msg) => this.logger.warn(msg),
|
|
170
|
+
logContentChain: (fields) => {
|
|
171
|
+
this.logger.debug(formatContentChainLog({ ...fields, adapter: this.name }));
|
|
172
|
+
},
|
|
173
|
+
})),
|
|
174
|
+
};
|
|
175
|
+
// 'text' 策略端点:keyboard 即将降级为编号文本,先把有效 fallback
|
|
176
|
+
// 映射写入中央存储(频道键与入站回跳解析一致),供数字回跳路由。
|
|
177
|
+
if (this.getInteractivePolicy() === 'text') {
|
|
178
|
+
const channelKey = `${this.name}-${options.endpoint}-${options.type}:${options.id}`;
|
|
179
|
+
for (const map of collectKeyboardFallbackMaps(options.content)) {
|
|
180
|
+
keyboardFallbackStore.remember(channelKey, map);
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
options = {
|
|
184
|
+
...options,
|
|
185
|
+
content: resolveKeyboardSegments(options.content, this.getInteractivePolicy()),
|
|
186
|
+
};
|
|
187
|
+
const mediaKinds = collectOutboundMediaKinds(options.content);
|
|
188
|
+
if (mediaKinds.length > 0) {
|
|
189
|
+
this.logger.debug(formatContentChainLog({
|
|
190
|
+
stage: CONTENT_CHAIN_STAGE.OUTBOUND,
|
|
191
|
+
adapter: this.name,
|
|
192
|
+
endpoint: options.endpoint,
|
|
193
|
+
media: mediaKinds.join(','),
|
|
194
|
+
}));
|
|
195
|
+
}
|
|
196
|
+
}
|
|
116
197
|
const fns = this.plugin.root.listeners('before.sendMessage');
|
|
117
198
|
for (const fn of fns) {
|
|
118
199
|
const result = await fn(options);
|
|
@@ -123,15 +204,16 @@ export class Adapter extends EventEmitter {
|
|
|
123
204
|
}
|
|
124
205
|
async sendMessage(options) {
|
|
125
206
|
options = await this.renderSendMessage(options);
|
|
126
|
-
const
|
|
127
|
-
if (!
|
|
128
|
-
throw new Error(`
|
|
129
|
-
|
|
207
|
+
const endpoint = this.endpoints.get(options.endpoint);
|
|
208
|
+
if (!endpoint)
|
|
209
|
+
throw new Error(`Endpoint ${options.endpoint} not found`);
|
|
210
|
+
assertOutbound(endpoint);
|
|
211
|
+
this.logger.debug(formatCompact({
|
|
130
212
|
send: `${options.type}(${options.id})`,
|
|
131
|
-
|
|
213
|
+
endpoint: options.endpoint,
|
|
132
214
|
preview: truncatePreview(segment.raw(options.content)),
|
|
133
215
|
}));
|
|
134
|
-
const messageId = await
|
|
216
|
+
const messageId = await endpoint.$sendMessage(options);
|
|
135
217
|
const replyStore = getOutboundReplyStore();
|
|
136
218
|
this.plugin.root.dispatch('message.send', {
|
|
137
219
|
adapter: this.name,
|
|
@@ -142,7 +224,81 @@ export class Adapter extends EventEmitter {
|
|
|
142
224
|
});
|
|
143
225
|
return messageId;
|
|
144
226
|
}
|
|
227
|
+
/**
|
|
228
|
+
* `call.recallMessage` 事件链(prompt.ts 超时撤回等)的统一出口:
|
|
229
|
+
* 经 canonical `EndpointControl` 端口撤回。
|
|
230
|
+
*/
|
|
231
|
+
async recallEndpointMessage(endpointKey, messageId) {
|
|
232
|
+
const endpoint = this.endpoints.get(endpointKey);
|
|
233
|
+
if (!endpoint)
|
|
234
|
+
throw new Error(`Endpoint ${endpointKey} not found`);
|
|
235
|
+
assertOutbound(endpoint);
|
|
236
|
+
const control = endpointControlOf(endpoint);
|
|
237
|
+
if (!control?.recall) {
|
|
238
|
+
throw new Error(`Endpoint ${endpointKey} does not support recall`);
|
|
239
|
+
}
|
|
240
|
+
this.logger.debug(formatCompact({ op: 'recall_message', msgId: messageId, endpoint: endpointKey }));
|
|
241
|
+
await control.recall({
|
|
242
|
+
conversation: {
|
|
243
|
+
endpoint: { id: endpointKey, adapter: String(this.name) },
|
|
244
|
+
kind: 'private',
|
|
245
|
+
id: endpointKey,
|
|
246
|
+
},
|
|
247
|
+
id: messageId,
|
|
248
|
+
});
|
|
249
|
+
}
|
|
250
|
+
/**
|
|
251
|
+
* 编辑已发送的消息。
|
|
252
|
+
* - 如果 Endpoint 的 control 端口实现了 edit,调用平台编辑 API
|
|
253
|
+
* - 否则 fallback 到发送新消息
|
|
254
|
+
* @returns 消息 ID(编辑时返回原 ID,fallback 时返回新消息 ID)
|
|
255
|
+
*/
|
|
256
|
+
async editMessage(options) {
|
|
257
|
+
const endpoint = this.endpoints.get(options.endpoint);
|
|
258
|
+
if (!endpoint)
|
|
259
|
+
throw new Error(`Endpoint ${options.endpoint} not found`);
|
|
260
|
+
assertOutbound(endpoint);
|
|
261
|
+
const control = endpointControlOf(endpoint);
|
|
262
|
+
if (control?.edit) {
|
|
263
|
+
const rendered = await this.renderSendMessage({
|
|
264
|
+
context: options.context,
|
|
265
|
+
endpoint: options.endpoint,
|
|
266
|
+
id: options.id,
|
|
267
|
+
type: options.type,
|
|
268
|
+
content: options.content,
|
|
269
|
+
});
|
|
270
|
+
await control.edit({
|
|
271
|
+
conversation: {
|
|
272
|
+
endpoint: { id: options.endpoint, adapter: String(this.name) },
|
|
273
|
+
kind: options.type === 'group' ? 'group' : 'private',
|
|
274
|
+
id: options.id,
|
|
275
|
+
},
|
|
276
|
+
id: options.messageId,
|
|
277
|
+
}, rendered.content);
|
|
278
|
+
this.logger.debug(formatCompact({
|
|
279
|
+
edit: `${options.type}(${options.id})`,
|
|
280
|
+
endpoint: options.endpoint,
|
|
281
|
+
messageId: options.messageId,
|
|
282
|
+
}));
|
|
283
|
+
return options.messageId;
|
|
284
|
+
}
|
|
285
|
+
this.logger.debug(formatCompact({
|
|
286
|
+
editFallback: 'sendMessage',
|
|
287
|
+
endpoint: options.endpoint,
|
|
288
|
+
reason: 'control.edit not implemented',
|
|
289
|
+
}));
|
|
290
|
+
return this.sendMessage({
|
|
291
|
+
context: options.context,
|
|
292
|
+
endpoint: options.endpoint,
|
|
293
|
+
id: options.id,
|
|
294
|
+
type: options.type,
|
|
295
|
+
content: options.content,
|
|
296
|
+
});
|
|
297
|
+
}
|
|
145
298
|
async start() {
|
|
299
|
+
if (this.endpoints.size > 0) {
|
|
300
|
+
await this.stop();
|
|
301
|
+
}
|
|
146
302
|
const rootAdapters = this.plugin.root.adapters;
|
|
147
303
|
if (!rootAdapters.some((n) => String(n) === String(this.name))) {
|
|
148
304
|
rootAdapters.push(this.name);
|
|
@@ -150,31 +306,38 @@ export class Adapter extends EventEmitter {
|
|
|
150
306
|
if (!this.config?.length)
|
|
151
307
|
return;
|
|
152
308
|
for (const config of this.config) {
|
|
153
|
-
const
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
309
|
+
const endpoint = await connectEndpointInstance({
|
|
310
|
+
plugin: this.plugin,
|
|
311
|
+
adapter: this,
|
|
312
|
+
config: config,
|
|
313
|
+
});
|
|
314
|
+
this.logger.debug(formatCompact({ connect: endpoint.$id, adapter: this.name }));
|
|
315
|
+
this.endpoints.set(endpoint.$id, endpoint);
|
|
157
316
|
}
|
|
158
317
|
this.logger.debug(formatCompact({ adapter: this.name }));
|
|
159
318
|
}
|
|
160
319
|
/**
|
|
161
|
-
* 停止适配器,断开并移除所有
|
|
162
|
-
* @param plugin 所属插件实例
|
|
320
|
+
* 停止适配器,断开并移除所有 Endpoint 实例
|
|
163
321
|
*/
|
|
164
322
|
async stop() {
|
|
165
323
|
const errors = [];
|
|
166
|
-
for (const [id,
|
|
324
|
+
for (const [id, endpoint] of this.endpoints) {
|
|
167
325
|
try {
|
|
168
|
-
|
|
326
|
+
if (hasInbound(endpoint)) {
|
|
327
|
+
await disconnectEndpointInstance(this.plugin, this, endpoint);
|
|
328
|
+
}
|
|
169
329
|
this.logger.debug(formatCompact({ disconnect: id, adapter: this.name }));
|
|
170
330
|
}
|
|
171
331
|
catch (error) {
|
|
172
332
|
errors.push(error instanceof Error ? error : new Error(String(error)));
|
|
173
|
-
this.logger.error(`
|
|
333
|
+
this.logger.error(`endpoint ${id} of adapter ${this.name} disconnect failed:`, error);
|
|
174
334
|
}
|
|
175
335
|
}
|
|
176
336
|
// 无论是否有错误,始终完成清理
|
|
177
|
-
this.
|
|
337
|
+
this.endpoints.clear();
|
|
338
|
+
// Drop in-flight concurrency counter so a subsequent start() does not
|
|
339
|
+
// inherit a stale backpressure budget from the previous generation.
|
|
340
|
+
this.#pendingMessages = 0;
|
|
178
341
|
// 从 adapters 数组中移除(可能因重复 start 出现多条同名,需全部删掉)
|
|
179
342
|
const rootAdapters = this.plugin.root.adapters;
|
|
180
343
|
for (let i = rootAdapters.length - 1; i >= 0; i--) {
|
|
@@ -183,9 +346,11 @@ export class Adapter extends EventEmitter {
|
|
|
183
346
|
}
|
|
184
347
|
// 移除所有事件监听器
|
|
185
348
|
this.removeAllListeners();
|
|
349
|
+
this.recallMessageHandler = (endpoint_id, id) => this.recallEndpointMessage(endpoint_id, id);
|
|
350
|
+
this.on('call.recallMessage', this.recallMessageHandler);
|
|
186
351
|
this.logger.debug(formatCompact({ stop: this.name }));
|
|
187
352
|
if (errors.length) {
|
|
188
|
-
throw new AggregateError(errors, `adapter ${this.name}: ${errors.length}
|
|
353
|
+
throw new AggregateError(errors, `adapter ${this.name}: ${errors.length} endpoint(s) failed to disconnect`);
|
|
189
354
|
}
|
|
190
355
|
}
|
|
191
356
|
}
|
|
@@ -210,4 +375,3 @@ export class Adapter extends EventEmitter {
|
|
|
210
375
|
}
|
|
211
376
|
Adapter.register = register;
|
|
212
377
|
})(Adapter || (Adapter = {}));
|
|
213
|
-
//# sourceMappingURL=adapter.js.map
|
|
@@ -1,5 +1,10 @@
|
|
|
1
|
-
import { Adapter
|
|
2
|
-
|
|
1
|
+
import { Adapter } from "../adapter.js";
|
|
2
|
+
import { Plugin } from "../plugin.js";
|
|
3
|
+
import { Endpoint } from "../endpoint.js";
|
|
4
|
+
import { Message } from "../message.js";
|
|
5
|
+
import type { SendOptions } from "../types.js";
|
|
6
|
+
import type { OutboundRichSegmentPolicy } from "./rich-segments/types.js";
|
|
7
|
+
export declare class ProcessEndpoint implements Endpoint<{
|
|
3
8
|
owner?: string;
|
|
4
9
|
}, {
|
|
5
10
|
content: string;
|
|
@@ -26,18 +31,28 @@ export declare class ProcessBot implements Bot<{
|
|
|
26
31
|
content: string;
|
|
27
32
|
ts: number;
|
|
28
33
|
}>;
|
|
34
|
+
get control(): {
|
|
35
|
+
recall: (message: {
|
|
36
|
+
id: string;
|
|
37
|
+
}) => Promise<void>;
|
|
38
|
+
};
|
|
29
39
|
$recallMessage(id: string): Promise<void>;
|
|
30
40
|
$sendMessage(options: SendOptions): Promise<string>;
|
|
31
41
|
$connect(): Promise<void>;
|
|
32
42
|
$disconnect(): Promise<void>;
|
|
33
43
|
}
|
|
34
|
-
export declare class ProcessAdapter extends Adapter<
|
|
44
|
+
export declare class ProcessAdapter extends Adapter<ProcessEndpoint> {
|
|
45
|
+
static readonly capabilities: readonly ["inbound", "outbound"];
|
|
46
|
+
static outboundRichSegmentPolicy: OutboundRichSegmentPolicy;
|
|
35
47
|
constructor(plugin: Plugin);
|
|
36
|
-
|
|
48
|
+
/**
|
|
49
|
+
* process 出站由 $sendMessage 写入 stdout;父类 INFO preview 会与终端输出重复,故仅 debug 元数据。
|
|
50
|
+
*/
|
|
51
|
+
sendMessage(options: SendOptions): Promise<string>;
|
|
52
|
+
createEndpoint(config: Adapter.EndpointConfig<ProcessEndpoint>): ProcessEndpoint;
|
|
37
53
|
}
|
|
38
54
|
declare module '../adapter.js' {
|
|
39
55
|
interface Adapters {
|
|
40
56
|
process: ProcessAdapter;
|
|
41
57
|
}
|
|
42
58
|
}
|
|
43
|
-
//# sourceMappingURL=adapter-process.d.ts.map
|
|
@@ -1,6 +1,12 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { formatCompact } from "@zhin.js/logger";
|
|
2
|
+
import { Adapter } from "../adapter.js";
|
|
3
|
+
import { Message } from "../message.js";
|
|
4
|
+
import { segment } from "../utils.js";
|
|
5
|
+
import { assertOutbound } from "../endpoint-capabilities.js";
|
|
6
|
+
import { getOutboundReplyStore } from "./dispatcher.js";
|
|
2
7
|
import { bindStdin, runtimePid, runtimeUser } from "./runtime-io.js";
|
|
3
|
-
|
|
8
|
+
import { interpretOriginQrcodeForProcess } from "./rich-segments/qrcode-segment.js";
|
|
9
|
+
export class ProcessEndpoint {
|
|
4
10
|
adapter;
|
|
5
11
|
$config;
|
|
6
12
|
$id = runtimePid();
|
|
@@ -28,7 +34,7 @@ export class ProcessBot {
|
|
|
28
34
|
const base = {
|
|
29
35
|
$id: `${event.ts}`,
|
|
30
36
|
$adapter: 'process',
|
|
31
|
-
$
|
|
37
|
+
$endpoint: runtimePid(),
|
|
32
38
|
$sender: {
|
|
33
39
|
id: runtimeUser(),
|
|
34
40
|
name: runtimeUser(),
|
|
@@ -47,7 +53,7 @@ export class ProcessBot {
|
|
|
47
53
|
$reply: async (content) => {
|
|
48
54
|
return await this.adapter.sendMessage({
|
|
49
55
|
context: 'process',
|
|
50
|
-
|
|
56
|
+
endpoint: base.$endpoint,
|
|
51
57
|
content,
|
|
52
58
|
id: base.$sender.id,
|
|
53
59
|
type: base.$channel.type,
|
|
@@ -56,9 +62,21 @@ export class ProcessBot {
|
|
|
56
62
|
};
|
|
57
63
|
return Message.from(event, base);
|
|
58
64
|
}
|
|
65
|
+
get control() {
|
|
66
|
+
return {
|
|
67
|
+
recall: async (message) => this.$recallMessage(message.id),
|
|
68
|
+
};
|
|
69
|
+
}
|
|
59
70
|
async $recallMessage(id) {
|
|
60
71
|
}
|
|
61
72
|
async $sendMessage(options) {
|
|
73
|
+
const content = await interpretOriginQrcodeForProcess(options.content ?? '');
|
|
74
|
+
if (content != null) {
|
|
75
|
+
const preview = segment.raw(content);
|
|
76
|
+
if (preview) {
|
|
77
|
+
process.stdout.write(`${preview}\n`);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
62
80
|
return `${Date.now()}`;
|
|
63
81
|
}
|
|
64
82
|
async $connect() {
|
|
@@ -71,11 +89,40 @@ export class ProcessBot {
|
|
|
71
89
|
}
|
|
72
90
|
}
|
|
73
91
|
export class ProcessAdapter extends Adapter {
|
|
92
|
+
static capabilities = ['inbound', 'outbound'];
|
|
93
|
+
static outboundRichSegmentPolicy = {
|
|
94
|
+
qrcode: 'origin',
|
|
95
|
+
html: 'text',
|
|
96
|
+
markdown: 'text',
|
|
97
|
+
};
|
|
74
98
|
constructor(plugin) {
|
|
75
99
|
super(plugin, 'process', [{ owner: runtimePid() }]);
|
|
76
100
|
}
|
|
77
|
-
|
|
78
|
-
|
|
101
|
+
/**
|
|
102
|
+
* process 出站由 $sendMessage 写入 stdout;父类 INFO preview 会与终端输出重复,故仅 debug 元数据。
|
|
103
|
+
*/
|
|
104
|
+
async sendMessage(options) {
|
|
105
|
+
options = await this.renderSendMessage(options);
|
|
106
|
+
const endpoint = this.endpoints.get(options.endpoint);
|
|
107
|
+
if (!endpoint)
|
|
108
|
+
throw new Error(`Endpoint ${options.endpoint} not found`);
|
|
109
|
+
assertOutbound(endpoint);
|
|
110
|
+
this.logger.debug(formatCompact({
|
|
111
|
+
send: `${options.type}(${options.id})`,
|
|
112
|
+
endpoint: options.endpoint,
|
|
113
|
+
}));
|
|
114
|
+
const messageId = await endpoint.$sendMessage(options);
|
|
115
|
+
const replyStore = getOutboundReplyStore();
|
|
116
|
+
this.plugin.root.dispatch('message.send', {
|
|
117
|
+
adapter: this.name,
|
|
118
|
+
options,
|
|
119
|
+
messageId,
|
|
120
|
+
replySource: replyStore?.source,
|
|
121
|
+
replyMessage: replyStore?.message,
|
|
122
|
+
});
|
|
123
|
+
return messageId;
|
|
124
|
+
}
|
|
125
|
+
createEndpoint(config) {
|
|
126
|
+
return new ProcessEndpoint(this, config);
|
|
79
127
|
}
|
|
80
128
|
}
|
|
81
|
-
//# sourceMappingURL=adapter-process.js.map
|
|
@@ -48,7 +48,7 @@ declare module '../plugin.js' {
|
|
|
48
48
|
export declare class AgentPresetFeature extends Feature<AgentPreset> {
|
|
49
49
|
#private;
|
|
50
50
|
readonly name: "agentPreset";
|
|
51
|
-
readonly icon = "
|
|
51
|
+
readonly icon = "Endpoint";
|
|
52
52
|
readonly desc = "Agent \u9884\u8BBE";
|
|
53
53
|
readonly byName: Map<string, AgentPreset>;
|
|
54
54
|
add(preset: AgentPreset, pluginName: string): () => void;
|
|
@@ -62,4 +62,3 @@ export declare class AgentPresetFeature extends Feature<AgentPreset> {
|
|
|
62
62
|
}): AgentPreset[];
|
|
63
63
|
toJSON(pluginName?: string): FeatureJSON;
|
|
64
64
|
}
|
|
65
|
-
//# sourceMappingURL=agent-preset.d.ts.map
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
import { Feature } from '@zhin.js/kernel';
|
|
13
13
|
export class AgentPresetFeature extends Feature {
|
|
14
14
|
name = 'agentPreset';
|
|
15
|
-
icon = '
|
|
15
|
+
icon = 'Endpoint';
|
|
16
16
|
desc = 'Agent 预设';
|
|
17
17
|
byName = new Map();
|
|
18
18
|
add(preset, pluginName) {
|
|
@@ -77,4 +77,3 @@ export class AgentPresetFeature extends Feature {
|
|
|
77
77
|
};
|
|
78
78
|
}
|
|
79
79
|
}
|
|
80
|
-
//# sourceMappingURL=agent-preset.js.map
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AI Access Gate — 控制 LLM 回复路径是否对当前会话开放(平台 AIGC 合规等)
|
|
3
|
+
*/
|
|
4
|
+
import type { Message } from '../message.js';
|
|
5
|
+
export type AIAccessMode = 'open' | 'closed' | 'whitelist';
|
|
6
|
+
/** Endpoint 或全局 ai.access 配置块 */
|
|
7
|
+
export interface AIAccessScopeConfig {
|
|
8
|
+
mode?: AIAccessMode;
|
|
9
|
+
/** 允许触发 AI 的 sender.id */
|
|
10
|
+
users?: string[];
|
|
11
|
+
/** 允许触发 AI 的 group/channel id */
|
|
12
|
+
groups?: string[];
|
|
13
|
+
/** 私聊拒绝时的回复文案 */
|
|
14
|
+
denyMessage?: string;
|
|
15
|
+
}
|
|
16
|
+
/** 全局 ai.access 配置(与 AIAccessScopeConfig 同形) */
|
|
17
|
+
export type AIAccessConfig = AIAccessScopeConfig;
|
|
18
|
+
export interface ResolvedAIAccessConfig {
|
|
19
|
+
mode: AIAccessMode;
|
|
20
|
+
users: string[];
|
|
21
|
+
groups: string[];
|
|
22
|
+
denyMessage: string;
|
|
23
|
+
}
|
|
24
|
+
export interface AIAccessResult {
|
|
25
|
+
allowed: boolean;
|
|
26
|
+
reason: string;
|
|
27
|
+
/** 私聊拒绝时返回;群/频道拒绝为 undefined(静默) */
|
|
28
|
+
replyMessage?: string;
|
|
29
|
+
}
|
|
30
|
+
export declare const DEFAULT_AI_ACCESS_DENY_MESSAGE = "\u5F53\u524D\u4F1A\u8BDD\u672A\u5F00\u653E AI \u529F\u80FD\u3002";
|
|
31
|
+
export declare function resolveAIAccessConfig(global: AIAccessConfig | undefined, endpointScope?: AIAccessScopeConfig): ResolvedAIAccessConfig;
|
|
32
|
+
/**
|
|
33
|
+
* 判定当前消息是否允许进入 AI Handler(LLM 回复路径)。
|
|
34
|
+
* 不影响命令、游戏等其它 Dispatcher 分支。
|
|
35
|
+
*/
|
|
36
|
+
export declare function checkAIAccess(message: Message<any>, globalConfig: AIAccessConfig | undefined, endpointScope?: AIAccessScopeConfig): AIAccessResult;
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
export const DEFAULT_AI_ACCESS_DENY_MESSAGE = '当前会话未开放 AI 功能。';
|
|
2
|
+
const DEFAULT_MODE = 'open';
|
|
3
|
+
export function resolveAIAccessConfig(global, endpointScope) {
|
|
4
|
+
const base = global ?? {};
|
|
5
|
+
const endpoint = endpointScope ?? {};
|
|
6
|
+
return {
|
|
7
|
+
mode: endpoint.mode ?? base.mode ?? DEFAULT_MODE,
|
|
8
|
+
users: endpoint.users ?? base.users ?? [],
|
|
9
|
+
groups: endpoint.groups ?? base.groups ?? [],
|
|
10
|
+
denyMessage: endpoint.denyMessage ?? base.denyMessage ?? DEFAULT_AI_ACCESS_DENY_MESSAGE,
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
function isWhitelisted(message, config) {
|
|
14
|
+
const userId = String(message.$sender?.id ?? '');
|
|
15
|
+
if (userId && config.users.includes(userId))
|
|
16
|
+
return true;
|
|
17
|
+
const scope = message.$channel?.type;
|
|
18
|
+
if (scope === 'group' || scope === 'channel') {
|
|
19
|
+
const channelId = String(message.$channel?.id ?? '');
|
|
20
|
+
if (channelId && config.groups.includes(channelId))
|
|
21
|
+
return true;
|
|
22
|
+
}
|
|
23
|
+
return false;
|
|
24
|
+
}
|
|
25
|
+
function denyResult(message, config, reason) {
|
|
26
|
+
const scope = message.$channel?.type;
|
|
27
|
+
const replyMessage = scope === 'private' ? config.denyMessage : undefined;
|
|
28
|
+
return { allowed: false, reason, replyMessage };
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* 判定当前消息是否允许进入 AI Handler(LLM 回复路径)。
|
|
32
|
+
* 不影响命令、游戏等其它 Dispatcher 分支。
|
|
33
|
+
*/
|
|
34
|
+
export function checkAIAccess(message, globalConfig, endpointScope) {
|
|
35
|
+
const config = resolveAIAccessConfig(globalConfig, endpointScope);
|
|
36
|
+
if (config.mode === 'open') {
|
|
37
|
+
return { allowed: true, reason: 'mode: open' };
|
|
38
|
+
}
|
|
39
|
+
if (config.mode === 'closed') {
|
|
40
|
+
return denyResult(message, config, 'mode: closed');
|
|
41
|
+
}
|
|
42
|
+
if (isWhitelisted(message, config)) {
|
|
43
|
+
return { allowed: true, reason: 'whitelist: matched' };
|
|
44
|
+
}
|
|
45
|
+
return denyResult(message, config, 'whitelist: not matched');
|
|
46
|
+
}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import { type AiOutboundCapabilities, type AiOutboundExtensionDefinition } from './types.js';
|
|
2
|
+
export declare function getAdapterAiOutboundCapabilities(adapterInstance: object): AiOutboundCapabilities;
|
|
3
|
+
export declare function getAdapterAiOutboundExtensions(adapterInstance: object): readonly AiOutboundExtensionDefinition[];
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { DEFAULT_AI_OUTBOUND_CAPABILITIES, } from './types.js';
|
|
2
|
+
export function getAdapterAiOutboundCapabilities(adapterInstance) {
|
|
3
|
+
const ctor = adapterInstance.constructor;
|
|
4
|
+
return ctor.aiOutboundCapabilities ?? DEFAULT_AI_OUTBOUND_CAPABILITIES;
|
|
5
|
+
}
|
|
6
|
+
export function getAdapterAiOutboundExtensions(adapterInstance) {
|
|
7
|
+
const ctor = adapterInstance.constructor;
|
|
8
|
+
return ctor.aiOutboundExtensions ?? [];
|
|
9
|
+
}
|