@zhin.js/core 1.5.1 → 1.5.4

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.
Files changed (99) hide show
  1. package/README.md +6 -3
  2. package/lib/adapter.d.ts +7 -1
  3. package/lib/adapter.js +28 -24
  4. package/lib/agent-prompt.d.ts +2 -3
  5. package/lib/agent-prompt.js +5 -0
  6. package/lib/built/ai-outbound/parse.d.ts +1 -1
  7. package/lib/built/ai-outbound/parse.js +2 -6
  8. package/lib/built/ai-outbound/plain-mention-rewrite.js +4 -4
  9. package/lib/built/ai-outbound/resolve.js +8 -8
  10. package/lib/built/ai-outbound/types.d.ts +3 -3
  11. package/lib/built/ai-trigger.d.ts +5 -0
  12. package/lib/built/ai-trigger.js +40 -13
  13. package/lib/built/authorization.js +4 -4
  14. package/lib/built/command.d.ts +2 -2
  15. package/lib/built/command.js +2 -2
  16. package/lib/built/common-adapter-tools.d.ts +11 -11
  17. package/lib/built/common-adapter-tools.js +13 -13
  18. package/lib/built/config.d.ts +0 -4
  19. package/lib/built/config.js +0 -4
  20. package/lib/built/dispatcher.d.ts +2 -0
  21. package/lib/built/dispatcher.js +1 -1
  22. package/lib/built/endpoint-commands.js +2 -2
  23. package/lib/built/endpoint-lifecycle-service.js +13 -13
  24. package/lib/built/endpoint-lifecycle.d.ts +3 -3
  25. package/lib/built/endpoint-lifecycle.js +2 -2
  26. package/lib/built/endpoint-manager.d.ts +1 -1
  27. package/lib/built/interactive-segments/index.d.ts +1 -1
  28. package/lib/built/interactive-segments/index.js +1 -1
  29. package/lib/built/interactive-segments/keyboard-segment.d.ts +0 -1
  30. package/lib/built/interactive-segments/keyboard-segment.js +0 -1
  31. package/lib/built/interactive-segments/onebot-keyboard.d.ts +0 -3
  32. package/lib/built/interactive-segments/onebot-keyboard.js +0 -2
  33. package/lib/built/interactive-segments/resolve.d.ts +0 -3
  34. package/lib/built/interactive-segments/resolve.js +0 -3
  35. package/lib/built/interactive-segments/types.d.ts +8 -20
  36. package/lib/built/interactive-segments/types.js +0 -4
  37. package/lib/built/login-assist.d.ts +2 -2
  38. package/lib/built/login-assist.js +2 -2
  39. package/lib/built/message-enrich.d.ts +1 -1
  40. package/lib/built/message-enrich.js +2 -7
  41. package/lib/built/permission.d.ts +0 -4
  42. package/lib/built/permission.js +0 -4
  43. package/lib/built/prepend-quote-context.js +5 -5
  44. package/lib/built/rich-segments/capabilities.js +0 -1
  45. package/lib/built/rich-segments/html-segment.js +1 -4
  46. package/lib/built/rich-segments/markdown-segment.js +1 -4
  47. package/lib/built/rich-segments/types.d.ts +0 -5
  48. package/lib/built/schema-endpoint-manager.js +6 -6
  49. package/lib/built/tool.d.ts +5 -3
  50. package/lib/built/tool.js +14 -23
  51. package/lib/command.d.ts +4 -4
  52. package/lib/command.js +8 -11
  53. package/lib/endpoint-capabilities.d.ts +2 -3
  54. package/lib/endpoint-capabilities.js +4 -4
  55. package/lib/endpoint.d.ts +2 -0
  56. package/lib/endpoint.js +1 -0
  57. package/lib/errors.d.ts +2 -2
  58. package/lib/errors.js +4 -4
  59. package/lib/host-plugin-registry.d.ts +6 -5
  60. package/lib/host-plugin-registry.js +9 -4
  61. package/lib/im-scene.d.ts +1 -1
  62. package/lib/im-scene.js +5 -5
  63. package/lib/im-session-id.d.ts +2 -2
  64. package/lib/im-session-id.js +4 -4
  65. package/lib/index.d.ts +1 -2
  66. package/lib/index.js +0 -2
  67. package/lib/jsx-runtime.d.ts +1 -0
  68. package/lib/jsx.d.ts +19 -21
  69. package/lib/message.d.ts +1 -1
  70. package/lib/message.js +1 -1
  71. package/lib/notice.d.ts +2 -2
  72. package/lib/plugin-context.d.ts +11 -13
  73. package/lib/plugin-context.js +21 -18
  74. package/lib/plugin-runtime/im/contracts.d.ts +104 -60
  75. package/lib/plugin-runtime/im/contracts.js +87 -17
  76. package/lib/plugin-runtime/im/im-runtime.d.ts +38 -35
  77. package/lib/plugin-runtime/im/im-runtime.js +140 -131
  78. package/lib/plugin-runtime/im/index.d.ts +2 -0
  79. package/lib/plugin-runtime/im/index.js +2 -0
  80. package/lib/plugin-runtime/im/interactive.d.ts +3 -2
  81. package/lib/plugin-runtime/im/interactive.js +9 -4
  82. package/lib/plugin-runtime/im/message-bus.d.ts +38 -0
  83. package/lib/plugin-runtime/im/message-bus.js +40 -0
  84. package/lib/plugin-runtime/im/message-dispatcher.js +14 -74
  85. package/lib/plugin-runtime/im/outbound-renderer.d.ts +3 -2
  86. package/lib/plugin-runtime/im/outbound-renderer.js +44 -8
  87. package/lib/plugin-runtime/im/service-tokens.d.ts +18 -0
  88. package/lib/plugin-runtime/im/service-tokens.js +13 -0
  89. package/lib/plugin.d.ts +4 -7
  90. package/lib/plugin.js +7 -30
  91. package/lib/request.d.ts +2 -2
  92. package/lib/side-event/types.d.ts +0 -4
  93. package/lib/types.d.ts +6 -11
  94. package/lib/utils.js +3 -1
  95. package/package.json +13 -12
  96. package/lib/built/qrcode-segment.d.ts +0 -18
  97. package/lib/built/qrcode-segment.js +0 -78
  98. package/lib/types-generator.d.ts +0 -5
  99. package/lib/types-generator.js +0 -71
@@ -1,4 +1,4 @@
1
- import type { CapabilityId, PluginId, RuntimeSnapshot } from '@zhin.js/plugin-runtime';
1
+ import type { PluginId } from '@zhin.js/plugin-runtime';
2
2
  import type { ConversationRef, DeliveryReceipt, MessageRef } from '@zhin.js/im-contract';
3
3
  import type { MediaRef, Segment } from '../../built/segment-contract/types.js';
4
4
  export type { MediaRef, Segment };
@@ -24,77 +24,74 @@ export declare function isComponentCall(value: SendContent): value is ComponentC
24
24
  export declare function isRawContent(value: SendContent): value is RawContent;
25
25
  /** canonical Segment 一等公民判定(与 ComponentCall/RawContent 的 $content brand 互斥)。 */
26
26
  export declare function isSegmentContent(value: unknown): value is Segment;
27
+ export interface MessageSenderRef {
28
+ readonly id: string;
29
+ readonly name?: string;
30
+ readonly roles?: readonly string[];
31
+ }
27
32
  export interface IncomingMessage {
28
- readonly adapter: CapabilityId;
29
- /** Structured identity supplied by migrated adapters; target remains the bridge. */
30
- readonly conversation?: ConversationRef;
31
- /** Structured native message identity supplied by migrated adapters. */
33
+ readonly conversation: ConversationRef;
32
34
  readonly message?: MessageRef;
33
- readonly target: string;
34
- /**
35
- * 纯文本视图:与 `segments` 同源(adapter 从同一份入站载荷派生二者)。
36
- * 触发判定与 Console 预览读取此字段;命令匹配在有 segments 时优先使用结构化视图。
37
- */
38
35
  readonly content: string;
39
- /**
40
- * 结构化段视图(canonical Segment SSOT,见 built/segment-contract)。
41
- * 与 `content` 同源:segments 承载纯文本无法表达的媒体(image/audio/video/file
42
- * 的 MediaRef)、mention、reply 等信息。旧 adapter 未迁移时可缺省,
43
- * 读取方必须容忍 undefined。
44
- */
45
36
  readonly segments?: readonly Segment[];
46
- readonly id?: string;
47
- readonly sender?: string;
37
+ readonly sender?: MessageSenderRef;
38
+ /** Endpoint 实例名(如 ICQQ uin、sandbox bot name),区别于 conversation.endpoint.id(CapabilityId)。 */
39
+ readonly endpointId?: string;
40
+ /** 消息是否 @了机器人。 */
41
+ readonly mentioned?: boolean;
42
+ /** 引用/回复的原始消息。 */
43
+ readonly replyTo?: {
44
+ readonly id: string;
45
+ };
48
46
  readonly metadata?: Readonly<Record<string, unknown>>;
49
47
  }
48
+ /**
49
+ * 入站消息上下文快照 — 由 reply 闭包捕获,沿出站链路传递到模板编译。
50
+ * 定时任务 / 跨通道发送时整个 incoming 为 undefined。
51
+ */
52
+ export interface IncomingContext {
53
+ readonly sender?: MessageSenderRef;
54
+ /** 收到的消息纯文本内容。 */
55
+ readonly content: string;
56
+ /** 结构化消息段(图片、@、引用等)。 */
57
+ readonly segments?: readonly Segment[];
58
+ /** 平台原生消息 ID。 */
59
+ readonly messageId?: string;
60
+ /** 消息到达时间戳(ms)。 */
61
+ readonly timestamp: number;
62
+ /** Endpoint 实例名(如 ICQQ uin、sandbox bot name)。 */
63
+ readonly endpointId?: string;
64
+ /** 消息是否 @了机器人。 */
65
+ readonly mentioned?: boolean;
66
+ }
50
67
  export interface SendRequest {
51
- readonly adapter: CapabilityId;
52
- /** Structured destination supplied to Adapter endpoints in parallel with target. */
53
- readonly conversation?: ConversationRef;
54
- readonly target: string;
68
+ readonly conversation: ConversationRef;
55
69
  readonly requester: PluginId;
56
70
  readonly content: SendContent;
57
- readonly parent?: ChannelParent;
58
- }
59
- /** Console 通道的来源场景(群临时会话 parent.group / QQ 子频道 parent.guild)。 */
60
- export interface ChannelParent {
61
- readonly type?: string;
62
- readonly id?: string;
63
- readonly name?: string;
71
+ /** Incoming message context (absent for scheduled / cross-channel sends). */
72
+ readonly incoming?: IncomingContext;
64
73
  }
74
+ /**
75
+ * Host 侧未锚定 endpoint 的会话地址(Console RPC / OutboundHost 入参);
76
+ * ImRuntime 解析 adapter/endpointKey 后锚定为完整 ConversationRef。
77
+ */
78
+ export type ConversationAddress = Omit<ConversationRef, 'endpoint'>;
65
79
  export interface OutboundEnvelope {
66
- readonly adapter: CapabilityId;
67
- readonly conversation?: ConversationRef;
68
- readonly target: string;
80
+ readonly conversation: ConversationRef;
69
81
  readonly requester: PluginId;
70
82
  readonly generation: number;
71
83
  readonly payload: unknown;
72
- readonly parent?: ChannelParent;
73
84
  replace(payload: unknown): void;
74
85
  }
75
86
  export interface MessageGateway {
76
87
  receive(input: IncomingMessage): Promise<MessageDispatchResult>;
77
- /**
78
- * Compatibility surface for existing Adapter-facing gateway consumers.
79
- * Runtime callers that need an outcome use DeliveryMessageGateway instead.
80
- */
81
- send(request: SendRequest): Promise<unknown>;
88
+ send(request: SendRequest): Promise<DeliveryReceipt>;
82
89
  /**
83
90
  * 注册 interactive action 回跳 handler(prefix 最长匹配;返回注销函数)。
84
91
  * 平台 callback 的 action 段、'text' 端点的数字回跳与指令预填直出
85
92
  * payload 都会路由到这里。
86
93
  */
87
94
  registerInteractiveHandler(prefix: string, handler: (message: Message) => Promise<boolean> | boolean): () => void;
88
- /**
89
- * Command miss(或非前缀文本)后的回退处理:Host AI 对话、单文件 bot 用。
90
- * 返回 true 表示已处理(回复已发送);后注册者覆盖前者。
91
- * `requester` 是消息所属 Adapter Endpoint 的 owner(用于 CapabilityIngress 继承)。
92
- */
93
- setUnmatchedHandler(handler: (message: Message, snapshot: RuntimeSnapshot, requester: PluginId) => Promise<boolean>): void;
94
- }
95
- /** Structured outbound gateway exposed by the Plugin Runtime. */
96
- export interface DeliveryMessageGateway extends MessageGateway {
97
- send(request: SendRequest): Promise<DeliveryReceipt>;
98
95
  }
99
96
  export interface MessageDispatchResult {
100
97
  readonly matched: boolean;
@@ -103,33 +100,80 @@ export interface MessageDispatchResult {
103
100
  readonly value?: unknown;
104
101
  }
105
102
  export declare class Message {
106
- readonly adapter: CapabilityId;
107
- readonly target: string;
103
+ readonly conversation: ConversationRef;
108
104
  readonly content: string;
109
105
  readonly generation: number;
110
- readonly id?: string | undefined;
111
- readonly sender?: string | undefined;
106
+ readonly sender?: MessageSenderRef | undefined;
112
107
  readonly metadata: Readonly<Record<string, unknown>>;
113
108
  /**
114
109
  * 结构化段视图(与 `content` 纯文本视图同源,见 IncomingMessage.segments)。
115
110
  * Command dispatcher 优先使用此字段,以支持 mention、image 等结构化参数。
116
111
  */
117
112
  readonly segments?: readonly Segment[] | undefined;
118
- /** Structured inbound conversation when supplied by a migrated adapter. */
119
- readonly conversation?: ConversationRef | undefined;
120
- /** Structured inbound message identity when supplied by a migrated adapter. */
113
+ /** 结构化入站消息身份(平台原生 message id MessageRef 传递)。 */
121
114
  readonly message?: MessageRef | undefined;
122
- constructor(adapter: CapabilityId, target: string, content: string, generation: number, reply: (content: SendContent, requester?: PluginId) => Promise<unknown>, id?: string | undefined, sender?: string | undefined, metadata?: Readonly<Record<string, unknown>>,
115
+ readonly endpointId?: string | undefined;
116
+ readonly mentioned?: boolean | undefined;
117
+ readonly replyTo?: {
118
+ readonly id: string;
119
+ } | undefined;
120
+ constructor(conversation: ConversationRef, content: string, generation: number, reply: (content: SendContent, requester?: PluginId, targetConversation?: ConversationAddress) => Promise<DeliveryReceipt>, sender?: MessageSenderRef | undefined, metadata?: Readonly<Record<string, unknown>>,
123
121
  /**
124
122
  * 结构化段视图(与 `content` 纯文本视图同源,见 IncomingMessage.segments)。
125
123
  * Command dispatcher 优先使用此字段,以支持 mention、image 等结构化参数。
126
124
  */
127
125
  segments?: readonly Segment[] | undefined,
128
- /** Structured inbound conversation when supplied by a migrated adapter. */
129
- conversation?: ConversationRef | undefined,
130
- /** Structured inbound message identity when supplied by a migrated adapter. */
131
- message?: MessageRef | undefined);
126
+ /** 结构化入站消息身份(平台原生 message id MessageRef 传递)。 */
127
+ message?: MessageRef | undefined, endpointId?: string | undefined, mentioned?: boolean | undefined, replyTo?: {
128
+ readonly id: string;
129
+ } | undefined);
130
+ /** 平台原生消息 id(`message` 未提供时为 undefined)。 */
131
+ get id(): string | undefined;
132
132
  readonly $reply: (content: SendContent) => Promise<DeliveryReceipt>;
133
133
  readonly $replyFrom: (requester: PluginId, content: SendContent) => Promise<DeliveryReceipt>;
134
+ /**
135
+ * 向同 Endpoint 的另一个通道发送消息(通用)。
136
+ *
137
+ * ```ts
138
+ * await message.$sendTo({ kind: 'channel', id: 'ch-1', parent: { kind: 'channel', id: 'guild-1' } }, '频道通知');
139
+ * ```
140
+ */
141
+ readonly $sendTo: (conversation: ConversationAddress, content: SendContent) => Promise<DeliveryReceipt>;
142
+ /**
143
+ * 私信当前消息的发送者(同 Endpoint)。
144
+ *
145
+ * @param content 消息内容
146
+ * @param from 会话上下文:
147
+ * - `true` — 用当前群/频道作为 parent(要求当前不在私聊中)
148
+ * - `{ kind, id }` — 显式指定 parent(群或子频道)
149
+ * - 省略 — 直接私信
150
+ *
151
+ * ```ts
152
+ * await message.$replyToPrivate('直接私信');
153
+ * await message.$replyToPrivate('群临时私信', true);
154
+ * await message.$replyToPrivate('频道私信', { kind: 'channel', id: '子频道ID' });
155
+ * ```
156
+ */
157
+ readonly $replyToPrivate: (content: SendContent, from?: boolean | {
158
+ readonly kind: 'group' | 'channel';
159
+ readonly id: string;
160
+ }) => Promise<DeliveryReceipt>;
161
+ /**
162
+ * 向指定群发送消息(同 Endpoint)。
163
+ *
164
+ * ```ts
165
+ * await message.$replyToGroup('67890', '群通知');
166
+ * ```
167
+ */
168
+ readonly $replyToGroup: (groupId: string, content: SendContent) => Promise<DeliveryReceipt>;
169
+ /**
170
+ * 向指定频道/子频道发送消息(同 Endpoint)。
171
+ *
172
+ * ```ts
173
+ * await message.$replyToChannel('channel-1', 'guild-1', '频道通知');
174
+ * await message.$replyToChannel('channel-1', 'guild-1', '话题回复', 'thread-1');
175
+ * ```
176
+ */
177
+ readonly $replyToChannel: (channelId: string, guildId: string, content: SendContent, threadId?: string) => Promise<DeliveryReceipt>;
134
178
  }
135
179
  export declare function createOutboundEnvelope(request: Omit<OutboundEnvelope, 'payload' | 'replace'>, initialPayload: unknown): OutboundEnvelope;
@@ -33,46 +33,116 @@ export function isSegmentContent(value) {
33
33
  && value.data !== null;
34
34
  }
35
35
  export class Message {
36
- adapter;
37
- target;
36
+ conversation;
38
37
  content;
39
38
  generation;
40
- id;
41
39
  sender;
42
40
  metadata;
43
41
  segments;
44
- conversation;
45
42
  message;
46
- constructor(adapter, target, content, generation,
47
- // Compatibility at the construction boundary: legacy tests and embedders
48
- // may still supply an untyped reply callback. ImRuntime always supplies a
49
- // DeliveryReceipt-producing implementation.
50
- reply, id, sender, metadata = Object.freeze({}),
43
+ endpointId;
44
+ mentioned;
45
+ replyTo;
46
+ constructor(conversation, content, generation, reply, sender, metadata = Object.freeze({}),
51
47
  /**
52
48
  * 结构化段视图(与 `content` 纯文本视图同源,见 IncomingMessage.segments)。
53
49
  * Command dispatcher 优先使用此字段,以支持 mention、image 等结构化参数。
54
50
  */
55
51
  segments,
56
- /** Structured inbound conversation when supplied by a migrated adapter. */
57
- conversation,
58
- /** Structured inbound message identity when supplied by a migrated adapter. */
59
- message) {
60
- this.adapter = adapter;
61
- this.target = target;
52
+ /** 结构化入站消息身份(平台原生 message id MessageRef 传递)。 */
53
+ message, endpointId, mentioned, replyTo) {
54
+ this.conversation = conversation;
62
55
  this.content = content;
63
56
  this.generation = generation;
64
- this.id = id;
65
57
  this.sender = sender;
66
58
  this.metadata = metadata;
67
59
  this.segments = segments;
68
- this.conversation = conversation;
69
60
  this.message = message;
61
+ this.endpointId = endpointId;
62
+ this.mentioned = mentioned;
63
+ this.replyTo = replyTo;
70
64
  this.$reply = (content) => reply(content);
71
65
  this.$replyFrom = (requester, content) => reply(content, requester);
66
+ this.$sendTo = (target, content) => reply(content, undefined, target);
67
+ this.$replyToPrivate = (content, from) => {
68
+ if (!sender)
69
+ throw new Error('Cannot $replyToPrivate: message has no sender');
70
+ let parent;
71
+ if (from === true) {
72
+ if (conversation.kind !== 'group' && conversation.kind !== 'channel') {
73
+ throw new Error('Cannot $replyToPrivate with from=true: current conversation must be a group or channel');
74
+ }
75
+ parent = { kind: conversation.kind, id: conversation.id };
76
+ }
77
+ else if (from != null && typeof from === 'object') {
78
+ parent = from;
79
+ }
80
+ return reply(content, undefined, {
81
+ kind: 'private',
82
+ id: sender.id,
83
+ ...(parent ? { parent } : {}),
84
+ });
85
+ };
86
+ this.$replyToGroup = (groupId, content) => {
87
+ return reply(content, undefined, { kind: 'group', id: groupId });
88
+ };
89
+ this.$replyToChannel = (channelId, guildId, content, threadId) => {
90
+ return reply(content, undefined, {
91
+ kind: 'channel',
92
+ id: channelId,
93
+ parent: { kind: 'channel', id: guildId },
94
+ ...(threadId ? { threadId } : {}),
95
+ });
96
+ };
72
97
  Object.freeze(this);
73
98
  }
99
+ /** 平台原生消息 id(`message` 未提供时为 undefined)。 */
100
+ get id() {
101
+ return this.message?.id;
102
+ }
74
103
  $reply;
75
104
  $replyFrom;
105
+ /**
106
+ * 向同 Endpoint 的另一个通道发送消息(通用)。
107
+ *
108
+ * ```ts
109
+ * await message.$sendTo({ kind: 'channel', id: 'ch-1', parent: { kind: 'channel', id: 'guild-1' } }, '频道通知');
110
+ * ```
111
+ */
112
+ $sendTo;
113
+ /**
114
+ * 私信当前消息的发送者(同 Endpoint)。
115
+ *
116
+ * @param content 消息内容
117
+ * @param from 会话上下文:
118
+ * - `true` — 用当前群/频道作为 parent(要求当前不在私聊中)
119
+ * - `{ kind, id }` — 显式指定 parent(群或子频道)
120
+ * - 省略 — 直接私信
121
+ *
122
+ * ```ts
123
+ * await message.$replyToPrivate('直接私信');
124
+ * await message.$replyToPrivate('群临时私信', true);
125
+ * await message.$replyToPrivate('频道私信', { kind: 'channel', id: '子频道ID' });
126
+ * ```
127
+ */
128
+ $replyToPrivate;
129
+ /**
130
+ * 向指定群发送消息(同 Endpoint)。
131
+ *
132
+ * ```ts
133
+ * await message.$replyToGroup('67890', '群通知');
134
+ * ```
135
+ */
136
+ $replyToGroup;
137
+ /**
138
+ * 向指定频道/子频道发送消息(同 Endpoint)。
139
+ *
140
+ * ```ts
141
+ * await message.$replyToChannel('channel-1', 'guild-1', '频道通知');
142
+ * await message.$replyToChannel('channel-1', 'guild-1', '话题回复', 'thread-1');
143
+ * ```
144
+ */
145
+ $replyToChannel;
76
146
  }
77
147
  export function createOutboundEnvelope(request, initialPayload) {
78
148
  let payload = initialPayload;
@@ -1,21 +1,24 @@
1
- import { Scope, type CapabilityId, type PluginId, type RuntimeSnapshot, type SnapshotStore } from '@zhin.js/plugin-runtime';
1
+ import { Scope, type PluginId, type SnapshotLease, type SnapshotStore } from '@zhin.js/plugin-runtime';
2
+ import { MessageBus } from './message-bus.js';
2
3
  import { type EndpointManagement, type EndpointManagementCapability } from '@zhin.js/adapter';
3
4
  import { type ConversationRef, type DeliveryReceipt, type MessageRef } from '@zhin.js/im-contract';
4
- import { Message, type ChannelParent, type DeliveryMessageGateway, type IncomingMessage, type MessageDispatchResult, type SendRequest } from './contracts.js';
5
+ import { Message, type ConversationAddress, type IncomingMessage, type MessageDispatchResult, type MessageGateway, type MessageSenderRef, type SendRequest } from './contracts.js';
5
6
  import { OutboundRenderer } from './outbound-renderer.js';
6
7
  import { type RuntimeInteractiveHandler } from './interactive.js';
7
- export declare const messageGatewayToken: import("@zhin.js/plugin-runtime").Token<DeliveryMessageGateway>;
8
+ export declare const messageGatewayToken: import("@zhin.js/plugin-runtime").Token<MessageGateway>;
9
+ /** Generation-owned terminal route after interactive/command routing misses. */
10
+ export interface IngressRoute {
11
+ route(message: Message, lease: SnapshotLease, requester: PluginId): Promise<boolean>;
12
+ }
13
+ export declare const ingressRouteToken: import("@zhin.js/plugin-runtime").Token<IngressRoute>;
8
14
  /** Console 实时消息事件(SSE 推送源;content 仅为截断预览,不含完整原始段)。 */
9
15
  export interface RuntimeMessageEvent {
10
16
  readonly direction: 'inbound' | 'outbound';
11
- readonly adapter: CapabilityId;
12
- readonly target: string;
13
- /** inbound:发送者 id。 */
14
- readonly sender?: string;
17
+ readonly conversation: ConversationRef;
18
+ /** inbound:发送者。 */
19
+ readonly sender?: MessageSenderRef;
15
20
  /** outbound:发起方插件。 */
16
21
  readonly requester?: PluginId;
17
- /** inbound:从 target 前缀解析的场景(`group:xx` → `group`)。 */
18
- readonly channelType?: string;
19
22
  /** 预览文本,截断至 200 字。 */
20
23
  readonly contentPreview: string;
21
24
  readonly messageId?: string;
@@ -29,17 +32,15 @@ export interface ImRuntimeOptions {
29
32
  */
30
33
  readonly commandPrefix?: string;
31
34
  readonly renderer?: OutboundRenderer;
35
+ /** Process-root ingress claim (pending interaction, authentication challenge, etc.). */
36
+ readonly inboundClaim?: (message: Message) => boolean | Promise<boolean>;
32
37
  }
33
- export declare class ImRuntime implements DeliveryMessageGateway {
38
+ export declare class ImRuntime implements MessageGateway {
34
39
  #private;
35
40
  constructor(options?: ImRuntimeOptions);
36
41
  attach(snapshots: SnapshotStore): void;
37
- /**
38
- * Optional Host AI / fallback path after Command miss (or non-prefixed text).
39
- * Return true when the message was handled (reply already sent).
40
- * `requester` is the Adapter Endpoint owner (for CapabilityIngress inheritance).
41
- */
42
- setUnmatchedHandler(handler: (message: Message, snapshot: RuntimeSnapshot, requester: PluginId) => Promise<boolean>): void;
42
+ readonly permissionHost: import("@zhin.js/permission").PermissionHost;
43
+ readonly messageBus: MessageBus;
43
44
  install(resources: Scope): void;
44
45
  /**
45
46
  * 注册 interactive action 回跳 handler(prefix 最长匹配;返回注销函数)。
@@ -63,7 +64,18 @@ export declare class ImRuntime implements DeliveryMessageGateway {
63
64
  readonly phase: 'pending' | 'starting' | 'online' | 'failed' | 'unconfigured';
64
65
  readonly managementCapabilities: readonly EndpointManagementCapability[];
65
66
  }[];
66
- getEndpoint(adapter: string, endpointId: string): {
67
+ /**
68
+ * Console `GET /api/stats` 同源计数:非 root 插件节点 + AdapterIndex endpoints。
69
+ * 供命令 / 状态卡等在 Plugin Runtime 下读取(legacy `root.adapters` / `root.children` 已不存在)。
70
+ */
71
+ inventory(): Readonly<{
72
+ plugins: number;
73
+ endpoints: {
74
+ readonly total: number;
75
+ readonly online: number;
76
+ };
77
+ }>;
78
+ getEndpoint(adapter: string, endpointKey: string): {
67
79
  readonly name: string;
68
80
  readonly adapter: string;
69
81
  readonly connected: boolean;
@@ -73,19 +85,16 @@ export declare class ImRuntime implements DeliveryMessageGateway {
73
85
  } | null;
74
86
  sendEndpointMessage(input: {
75
87
  readonly adapter: string;
76
- readonly endpointId: string;
77
- readonly conversation?: ConversationRef;
78
- readonly channelId?: string;
79
- readonly channelType?: string;
88
+ readonly endpointKey: string;
89
+ readonly conversation: ConversationAddress;
80
90
  readonly content: unknown;
81
- readonly parent?: ChannelParent;
82
91
  }): Promise<{
83
92
  messageId: string;
84
93
  }>;
85
94
  /** Activity-feedback: add a message reaction when the live Endpoint supports it. */
86
95
  addEndpointReaction(input: {
87
96
  readonly adapter: string;
88
- readonly endpointId: string;
97
+ readonly endpointKey: string;
89
98
  readonly message?: MessageRef;
90
99
  readonly messageId?: string;
91
100
  readonly emoji: string;
@@ -94,7 +103,7 @@ export declare class ImRuntime implements DeliveryMessageGateway {
94
103
  }): Promise<string | null>;
95
104
  removeEndpointReaction(input: {
96
105
  readonly adapter: string;
97
- readonly endpointId: string;
106
+ readonly endpointKey: string;
98
107
  readonly message?: MessageRef;
99
108
  readonly messageId?: string;
100
109
  readonly reactionId: string;
@@ -102,33 +111,27 @@ export declare class ImRuntime implements DeliveryMessageGateway {
102
111
  /** Activity-feedback autoRemove: recall a previously sent status message. */
103
112
  recallEndpointMessage(input: {
104
113
  readonly adapter: string;
105
- readonly endpointId: string;
114
+ readonly endpointKey: string;
106
115
  readonly message?: MessageRef;
107
116
  readonly messageId?: string;
108
117
  }): Promise<void>;
109
118
  editEndpointMessage(input: {
110
119
  readonly adapter: string;
111
- readonly endpointId: string;
120
+ readonly endpointKey: string;
112
121
  readonly message?: MessageRef;
113
122
  readonly messageId?: string;
114
123
  readonly content: unknown;
115
124
  }): Promise<string | null>;
116
125
  setEndpointTyping(input: {
117
126
  readonly adapter: string;
118
- readonly endpointId: string;
119
- readonly conversation?: ConversationRef;
120
- readonly target?: string;
127
+ readonly endpointKey: string;
128
+ readonly conversation: ConversationRef;
121
129
  readonly active?: boolean;
122
130
  }): Promise<void>;
123
- /**
124
- * Console endpoint 社交/群管 RPC:解析 live Endpoint 实例(无则 null)。
125
- * @deprecated Host callers should use `getEndpointManagement()`.
126
- */
127
- getLiveEndpoint(adapter: string, endpointId: string): unknown | null;
128
131
  /**
129
132
  * Narrow Host seam for Console social/group management. An empty object means
130
133
  * the Endpoint exists but implements no management operations; null means it
131
134
  * cannot be resolved.
132
135
  */
133
- getEndpointManagement(adapter: string, endpointId: string): EndpointManagement | null;
136
+ getEndpointManagement(adapter: string, endpointKey: string): EndpointManagement | null;
134
137
  }