@zhin.js/core 1.5.13 → 1.5.14
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/lib/adapter.d.ts +3 -2
- package/lib/adapter.js +3 -2
- package/lib/built/dispatcher.d.ts +1 -1
- package/lib/feature/handler.d.ts +44 -2
- package/lib/feature/handler.js +25 -1
- package/lib/index.d.ts +4 -1
- package/lib/index.js +4 -1
- package/lib/message.d.ts +1 -0
- package/lib/message.js +1 -0
- package/lib/plugin-runtime/im/contracts.d.ts +16 -4
- package/lib/plugin-runtime/im/contracts.js +17 -2
- package/lib/plugin-runtime/im/im-runtime.d.ts +19 -13
- package/lib/plugin-runtime/im/im-runtime.js +122 -47
- package/lib/plugin-runtime/im/index.d.ts +0 -1
- package/lib/plugin-runtime/im/index.js +0 -1
- package/lib/plugin-runtime/im/login-assist-host.d.ts +1 -1
- package/lib/plugin-runtime/im/login-assist-host.js +1 -1
- package/lib/plugin-runtime/im/public-api.d.ts +6 -0
- package/lib/plugin-runtime/im/public-api.js +6 -0
- package/lib/side-event/dispatch.d.ts +3 -3
- package/lib/side-event/dispatch.js +5 -5
- package/lib/utils.d.ts +1 -1
- package/lib/utils.js +1 -1
- package/package.json +12 -12
- package/lib/agent-prompt.d.ts +0 -39
- package/lib/agent-prompt.js +0 -6
- package/lib/plugin-runtime/im/side-event-gateway.d.ts +0 -13
- package/lib/plugin-runtime/im/side-event-gateway.js +0 -2
package/lib/adapter.d.ts
CHANGED
|
@@ -41,9 +41,10 @@ export declare abstract class Adapter<R extends Endpoint = Endpoint, const Caps
|
|
|
41
41
|
/** 当前正在处理的消息数 */
|
|
42
42
|
get pendingMessages(): number;
|
|
43
43
|
/**
|
|
44
|
-
*
|
|
44
|
+
* 创建一个适配器运行实例。
|
|
45
|
+
* @param plugin 拥有该适配器的插件实例
|
|
45
46
|
* @param name 适配器名称(如 'process'、'qq' 等)
|
|
46
|
-
* @param
|
|
47
|
+
* @param config Endpoint 配置列表
|
|
47
48
|
*/
|
|
48
49
|
constructor(plugin: Plugin, name: keyof Plugin.Contexts, config: Adapter.EndpointConfig<R>[]);
|
|
49
50
|
/** 入站消息管线(替代 emit override 的隐式管线) */
|
package/lib/adapter.js
CHANGED
|
@@ -55,9 +55,10 @@ export class Adapter extends EventEmitter {
|
|
|
55
55
|
return this.#pendingMessages;
|
|
56
56
|
}
|
|
57
57
|
/**
|
|
58
|
-
*
|
|
58
|
+
* 创建一个适配器运行实例。
|
|
59
|
+
* @param plugin 拥有该适配器的插件实例
|
|
59
60
|
* @param name 适配器名称(如 'process'、'qq' 等)
|
|
60
|
-
* @param
|
|
61
|
+
* @param config Endpoint 配置列表
|
|
61
62
|
*/
|
|
62
63
|
constructor(plugin, name, config) {
|
|
63
64
|
super();
|
|
@@ -80,7 +80,7 @@ export type AITriggerMatcher = (message: Message<any>) => {
|
|
|
80
80
|
*/
|
|
81
81
|
export type GroupPassiveContextHandler = (message: Message<any>) => MaybePromise<void>;
|
|
82
82
|
export type GuardrailMiddleware = MessageMiddleware<RegisteredAdapter>;
|
|
83
|
-
/**
|
|
83
|
+
/** Backward-compatible name for the command or AI outbound reply source. */
|
|
84
84
|
export type ReplySource = OutboundReplySource;
|
|
85
85
|
/** replyWithPolish 可选参数 */
|
|
86
86
|
export interface ReplyWithPolishOptions {
|
package/lib/feature/handler.d.ts
CHANGED
|
@@ -1,10 +1,52 @@
|
|
|
1
1
|
/** Authoring API for Handler Feature — implementation in `@zhin.js/handler`. */
|
|
2
|
-
export {
|
|
2
|
+
export { parseHandlerDefinition, HandlerIndex, isHandlerIndex, handlerFeatureId, handlerFeature, handlerEventFromLocalName, resolveHandlerEvent, type HandlerEventMap, type HandlerDefinition, type HandlerDescriptor, type HandlerContext, type HandlerDispatchOptions, } from '@zhin.js/handler';
|
|
3
|
+
import { type HandlerContext, type HandlerDefinition, type HandlerEventMap } from '@zhin.js/handler';
|
|
3
4
|
import type { Plugin } from '../plugin.js';
|
|
5
|
+
import type { Message } from '../plugin-runtime/im/contracts.js';
|
|
6
|
+
import type { Notice } from '../notice.js';
|
|
7
|
+
import type { Request } from '../request.js';
|
|
8
|
+
import type { SystemEvent } from '../system-event.js';
|
|
9
|
+
import type { AdapterClient, AdapterEvents, EndpointEvent, EndpointIdentity, PlatformEvent, RegisteredAdapterName } from '@zhin.js/adapter';
|
|
4
10
|
type KnownKeys<T> = {
|
|
5
11
|
[K in keyof T as string extends K ? never : number extends K ? never : K]: T[K];
|
|
6
12
|
};
|
|
7
13
|
declare module '@zhin.js/handler' {
|
|
8
|
-
interface HandlerEventMap extends KnownKeys<Plugin.Lifecycle
|
|
14
|
+
interface HandlerEventMap extends KnownKeys<Omit<Plugin.Lifecycle, 'message.receive' | 'notice.receive' | 'request.receive' | 'system.receive'>> {
|
|
15
|
+
'message.receive': [event: EndpointEvent<Message>];
|
|
16
|
+
'notice.receive': [event: EndpointEvent<Notice>];
|
|
17
|
+
'request.receive': [event: EndpointEvent<Request>];
|
|
18
|
+
'system.receive': [event: EndpointEvent<SystemEvent>];
|
|
19
|
+
'platform.receive': [event: EndpointEvent<PlatformEvent>];
|
|
9
20
|
}
|
|
10
21
|
}
|
|
22
|
+
type NativeEventName<TAdapter extends RegisteredAdapterName> = Extract<keyof AdapterEvents<TAdapter>, string>;
|
|
23
|
+
/** Fully inferred native platform event exposed to plugin handlers. */
|
|
24
|
+
export interface ClientHandlerEvent<TAdapter extends RegisteredAdapterName, TName extends NativeEventName<TAdapter> = NativeEventName<TAdapter>> {
|
|
25
|
+
readonly name: TName;
|
|
26
|
+
readonly event: AdapterEvents<TAdapter>[TName];
|
|
27
|
+
readonly endpoint: EndpointIdentity;
|
|
28
|
+
readonly client: AdapterClient<TAdapter>;
|
|
29
|
+
}
|
|
30
|
+
export interface ClientHandlerOptions<TAdapter extends RegisteredAdapterName, TName extends NativeEventName<TAdapter>> {
|
|
31
|
+
readonly adapter: TAdapter;
|
|
32
|
+
readonly event: TName;
|
|
33
|
+
handle(this: HandlerContext, event: ClientHandlerEvent<TAdapter, TName>): void | Promise<void>;
|
|
34
|
+
}
|
|
35
|
+
export interface ClientHandlerWildcardEvent<TAdapter extends RegisteredAdapterName> {
|
|
36
|
+
readonly name: string;
|
|
37
|
+
readonly event: unknown;
|
|
38
|
+
readonly endpoint: EndpointIdentity;
|
|
39
|
+
readonly client: AdapterClient<TAdapter>;
|
|
40
|
+
}
|
|
41
|
+
export interface ClientHandlerWildcardOptions<TAdapter extends RegisteredAdapterName> {
|
|
42
|
+
readonly adapter: TAdapter;
|
|
43
|
+
readonly event: '*';
|
|
44
|
+
handle(this: HandlerContext, event: ClientHandlerWildcardEvent<TAdapter>): void | Promise<void>;
|
|
45
|
+
}
|
|
46
|
+
export declare function defineHandler<TAdapter extends RegisteredAdapterName, TName extends NativeEventName<TAdapter>>(options: ClientHandlerOptions<TAdapter, TName>): Readonly<HandlerDefinition<'platform.receive'>>;
|
|
47
|
+
/** Handle every native event from one Client without pretending unknown payloads are typed. */
|
|
48
|
+
export declare function defineHandler<TAdapter extends RegisteredAdapterName>(options: ClientHandlerWildcardOptions<TAdapter>): Readonly<HandlerDefinition<'platform.receive'>>;
|
|
49
|
+
export declare function defineHandler<K extends keyof HandlerEventMap & string>(options: {
|
|
50
|
+
readonly event: K;
|
|
51
|
+
handle(this: HandlerContext, ...args: HandlerEventMap[K] extends unknown[] ? HandlerEventMap[K] : unknown[]): void | Promise<void>;
|
|
52
|
+
}): Readonly<HandlerDefinition<K>>;
|
package/lib/feature/handler.js
CHANGED
|
@@ -1,2 +1,26 @@
|
|
|
1
1
|
/** Authoring API for Handler Feature — implementation in `@zhin.js/handler`. */
|
|
2
|
-
export {
|
|
2
|
+
export { parseHandlerDefinition, HandlerIndex, isHandlerIndex, handlerFeatureId, handlerFeature, handlerEventFromLocalName, resolveHandlerEvent, } from '@zhin.js/handler';
|
|
3
|
+
import { defineHandler as defineHandlerFeature, } from '@zhin.js/handler';
|
|
4
|
+
export function defineHandler(options) {
|
|
5
|
+
if (!('adapter' in options) || typeof options.adapter !== 'string') {
|
|
6
|
+
return defineHandlerFeature(options);
|
|
7
|
+
}
|
|
8
|
+
const adapter = options.adapter;
|
|
9
|
+
const expectedName = options.event === '*' ? undefined : options.event;
|
|
10
|
+
return defineHandlerFeature({
|
|
11
|
+
event: 'platform.receive',
|
|
12
|
+
async handle(source) {
|
|
13
|
+
if (source.endpoint.adapter !== adapter)
|
|
14
|
+
return;
|
|
15
|
+
if (expectedName !== undefined && source.payload.name !== expectedName)
|
|
16
|
+
return;
|
|
17
|
+
const event = Object.freeze({
|
|
18
|
+
name: source.payload.name,
|
|
19
|
+
event: source.payload.event,
|
|
20
|
+
endpoint: source.endpoint,
|
|
21
|
+
client: source.client,
|
|
22
|
+
});
|
|
23
|
+
await options.handle.call(this, event);
|
|
24
|
+
},
|
|
25
|
+
});
|
|
26
|
+
}
|
package/lib/index.d.ts
CHANGED
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Canonical IM messages, Endpoints, rendering, and plugin-facing core types.
|
|
3
|
+
* @module @zhin.js/core
|
|
4
|
+
*/
|
|
1
5
|
export * from './endpoint.js';
|
|
2
6
|
export * from './endpoint-capabilities.js';
|
|
3
7
|
export * from './plugin.js';
|
|
@@ -13,7 +17,6 @@ export * from './side-event/index.js';
|
|
|
13
17
|
export * from './schema-interaction.js';
|
|
14
18
|
export type * from '@zhin.js/interaction';
|
|
15
19
|
export * from './types.js';
|
|
16
|
-
export * from './agent-prompt.js';
|
|
17
20
|
export * from './utils.js';
|
|
18
21
|
export * from './errors.js';
|
|
19
22
|
export * from './built/config.js';
|
package/lib/index.js
CHANGED
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Canonical IM messages, Endpoints, rendering, and plugin-facing core types.
|
|
3
|
+
* @module @zhin.js/core
|
|
4
|
+
*/
|
|
1
5
|
// ── Core 类模块 ──────────────────────────────────────────────────────
|
|
2
6
|
export * from './endpoint.js';
|
|
3
7
|
export * from './endpoint-capabilities.js';
|
|
@@ -13,7 +17,6 @@ export * from './system-event.js';
|
|
|
13
17
|
export * from './side-event/index.js';
|
|
14
18
|
export * from './schema-interaction.js';
|
|
15
19
|
export * from './types.js';
|
|
16
|
-
export * from './agent-prompt.js';
|
|
17
20
|
export * from './utils.js';
|
|
18
21
|
export * from './errors.js';
|
|
19
22
|
// ── Built 模块 ──────────────────────────────────────────────────────
|
package/lib/message.d.ts
CHANGED
|
@@ -49,6 +49,7 @@ export interface MessageBase {
|
|
|
49
49
|
* 完整消息类型,支持扩展
|
|
50
50
|
*/
|
|
51
51
|
export type Message<T extends object = {}> = MessageBase & T;
|
|
52
|
+
/** @internal Legacy static helpers; not part of Agent resource authoring. */
|
|
52
53
|
export declare namespace Message {
|
|
53
54
|
/**
|
|
54
55
|
* 工具方法:合并自定义字段与基础消息结构
|
package/lib/message.js
CHANGED
|
@@ -81,10 +81,14 @@ export interface OutboundEnvelope {
|
|
|
81
81
|
readonly requester: PluginId;
|
|
82
82
|
readonly generation: number;
|
|
83
83
|
readonly payload: unknown;
|
|
84
|
+
/** Native platform Client for the Endpoint selected by `conversation`. */
|
|
85
|
+
readonly $client: unknown;
|
|
86
|
+
/** Literal adapter name used to validate adapter-bound middleware. */
|
|
87
|
+
readonly clientAdapter?: string;
|
|
84
88
|
replace(payload: unknown): void;
|
|
85
89
|
}
|
|
86
|
-
|
|
87
|
-
|
|
90
|
+
/** @public Stable IM gateway contract resolved through `outboundMessageToken`. */
|
|
91
|
+
export interface OutboundMessageService {
|
|
88
92
|
send(request: SendRequest): Promise<DeliveryReceipt>;
|
|
89
93
|
/**
|
|
90
94
|
* 注册 interactive action 回跳 handler(prefix 最长匹配;返回注销函数)。
|
|
@@ -100,6 +104,7 @@ export interface MessageDispatchResult {
|
|
|
100
104
|
readonly value?: unknown;
|
|
101
105
|
}
|
|
102
106
|
export declare class Message {
|
|
107
|
+
#private;
|
|
103
108
|
readonly conversation: ConversationRef;
|
|
104
109
|
readonly content: string;
|
|
105
110
|
readonly generation: number;
|
|
@@ -117,6 +122,8 @@ export declare class Message {
|
|
|
117
122
|
readonly replyTo?: {
|
|
118
123
|
readonly id: string;
|
|
119
124
|
} | undefined;
|
|
125
|
+
readonly clientAdapter?: string | undefined;
|
|
126
|
+
/** @internal Constructed only by the generation-owned IM Runtime. */
|
|
120
127
|
constructor(conversation: ConversationRef, content: string, generation: number, reply: (content: SendContent, requester?: PluginId, targetConversation?: ConversationAddress) => Promise<DeliveryReceipt>, sender?: MessageSenderRef | undefined, metadata?: Readonly<Record<string, unknown>>,
|
|
121
128
|
/**
|
|
122
129
|
* 结构化段视图(与 `content` 纯文本视图同源,见 IncomingMessage.segments)。
|
|
@@ -126,10 +133,15 @@ export declare class Message {
|
|
|
126
133
|
/** 结构化入站消息身份(平台原生 message id 经 MessageRef 传递)。 */
|
|
127
134
|
message?: MessageRef | undefined, endpointId?: string | undefined, mentioned?: boolean | undefined, replyTo?: {
|
|
128
135
|
readonly id: string;
|
|
129
|
-
} | undefined);
|
|
136
|
+
} | undefined, client?: () => unknown, clientAdapter?: string | undefined);
|
|
130
137
|
/** 平台原生消息 id(`message` 未提供时为 undefined)。 */
|
|
131
138
|
get id(): string | undefined;
|
|
132
139
|
readonly $reply: (content: SendContent) => Promise<DeliveryReceipt>;
|
|
140
|
+
/**
|
|
141
|
+
* Platform-native Client that received this message. The getter is
|
|
142
|
+
* generation-scoped; retaining the returned Client after dispatch is invalid.
|
|
143
|
+
*/
|
|
144
|
+
get $client(): unknown;
|
|
133
145
|
readonly $replyFrom: (requester: PluginId, content: SendContent) => Promise<DeliveryReceipt>;
|
|
134
146
|
/**
|
|
135
147
|
* 向同 Endpoint 的另一个通道发送消息(通用)。
|
|
@@ -176,4 +188,4 @@ export declare class Message {
|
|
|
176
188
|
*/
|
|
177
189
|
readonly $replyToChannel: (channelId: string, guildId: string, content: SendContent, threadId?: string) => Promise<DeliveryReceipt>;
|
|
178
190
|
}
|
|
179
|
-
export declare function createOutboundEnvelope(request: Omit<OutboundEnvelope, 'payload' | 'replace'>, initialPayload: unknown): OutboundEnvelope;
|
|
191
|
+
export declare function createOutboundEnvelope(request: Omit<OutboundEnvelope, 'payload' | '$client' | 'replace'>, initialPayload: unknown, resolveClient?: () => unknown): OutboundEnvelope;
|
|
@@ -43,6 +43,9 @@ export class Message {
|
|
|
43
43
|
endpointId;
|
|
44
44
|
mentioned;
|
|
45
45
|
replyTo;
|
|
46
|
+
clientAdapter;
|
|
47
|
+
#resolveClient;
|
|
48
|
+
/** @internal Constructed only by the generation-owned IM Runtime. */
|
|
46
49
|
constructor(conversation, content, generation, reply, sender, metadata = Object.freeze({}),
|
|
47
50
|
/**
|
|
48
51
|
* 结构化段视图(与 `content` 纯文本视图同源,见 IncomingMessage.segments)。
|
|
@@ -50,7 +53,9 @@ export class Message {
|
|
|
50
53
|
*/
|
|
51
54
|
segments,
|
|
52
55
|
/** 结构化入站消息身份(平台原生 message id 经 MessageRef 传递)。 */
|
|
53
|
-
message, endpointId, mentioned, replyTo) {
|
|
56
|
+
message, endpointId, mentioned, replyTo, client = () => {
|
|
57
|
+
throw new Error('Message has no Endpoint Client context');
|
|
58
|
+
}, clientAdapter) {
|
|
54
59
|
this.conversation = conversation;
|
|
55
60
|
this.content = content;
|
|
56
61
|
this.generation = generation;
|
|
@@ -61,6 +66,8 @@ export class Message {
|
|
|
61
66
|
this.endpointId = endpointId;
|
|
62
67
|
this.mentioned = mentioned;
|
|
63
68
|
this.replyTo = replyTo;
|
|
69
|
+
this.clientAdapter = clientAdapter;
|
|
70
|
+
this.#resolveClient = client;
|
|
64
71
|
this.$reply = (content) => reply(content);
|
|
65
72
|
this.$replyFrom = (requester, content) => reply(content, requester);
|
|
66
73
|
this.$sendTo = (target, content) => reply(content, undefined, target);
|
|
@@ -101,6 +108,13 @@ export class Message {
|
|
|
101
108
|
return this.message?.id;
|
|
102
109
|
}
|
|
103
110
|
$reply;
|
|
111
|
+
/**
|
|
112
|
+
* Platform-native Client that received this message. The getter is
|
|
113
|
+
* generation-scoped; retaining the returned Client after dispatch is invalid.
|
|
114
|
+
*/
|
|
115
|
+
get $client() {
|
|
116
|
+
return this.#resolveClient();
|
|
117
|
+
}
|
|
104
118
|
$replyFrom;
|
|
105
119
|
/**
|
|
106
120
|
* 向同 Endpoint 的另一个通道发送消息(通用)。
|
|
@@ -144,11 +158,12 @@ export class Message {
|
|
|
144
158
|
*/
|
|
145
159
|
$replyToChannel;
|
|
146
160
|
}
|
|
147
|
-
export function createOutboundEnvelope(request, initialPayload) {
|
|
161
|
+
export function createOutboundEnvelope(request, initialPayload, resolveClient = () => undefined) {
|
|
148
162
|
let payload = initialPayload;
|
|
149
163
|
return Object.freeze({
|
|
150
164
|
...request,
|
|
151
165
|
get payload() { return payload; },
|
|
166
|
+
get $client() { return resolveClient(); },
|
|
152
167
|
replace(next) { payload = next; },
|
|
153
168
|
});
|
|
154
169
|
}
|
|
@@ -1,16 +1,14 @@
|
|
|
1
1
|
import { Scope, generationAdmissionBinder, type GenerationAdmissionGate, type PluginId, type RuntimeSnapshot, type SnapshotLease, type SnapshotReader } from '@zhin.js/plugin-runtime';
|
|
2
2
|
import { MessageBus } from './message-bus.js';
|
|
3
|
-
import { type AdapterOperation, type EndpointManagement, type EndpointManagementCapability, type AdapterEndpointPhase, type EndpointContentResolveContext } from '@zhin.js/adapter';
|
|
4
|
-
import { type ConversationEventStore, type ConversationContextBlock, type ConversationReference, type ConversationResolution, type ConversationRef, type DeliveryReceipt, type MessageRef } from '@zhin.js/im-contract';
|
|
5
|
-
import { Message, type ConversationAddress, type IncomingMessage, type
|
|
3
|
+
import { type AdapterOperation, type EndpointManagement, type EndpointManagementCapability, type AdapterEndpointPhase, type EndpointContentResolveContext, type EndpointEvent, type EndpointEventGateway } from '@zhin.js/adapter';
|
|
4
|
+
import { type ConversationEventStore, type ConversationContextBlock, type ConversationReference, type ConversationResolution, type ConversationRef, type DeliveryReceipt, type EndpointCapabilities, type MessageRef } from '@zhin.js/im-contract';
|
|
5
|
+
import { Message, type ConversationAddress, type IncomingMessage, type OutboundMessageService, type MessageSenderRef, type SendRequest } from './contracts.js';
|
|
6
6
|
import { LoginAssist } from '../../built/login-assist.js';
|
|
7
|
-
import type { Notice } from '../../notice.js';
|
|
8
|
-
import type { Request } from '../../request.js';
|
|
9
|
-
import type { SystemEvent } from '../../system-event.js';
|
|
10
7
|
import type { UserInteraction } from '@zhin.js/interaction';
|
|
11
8
|
import { OutboundRenderer } from './outbound-renderer.js';
|
|
12
9
|
import { type RuntimeInteractiveHandler } from './interactive.js';
|
|
13
|
-
|
|
10
|
+
/** @public Stable inbound and outbound IM gateway token for Adapter integrations. */
|
|
11
|
+
export declare const outboundMessageToken: import("@zhin.js/plugin-runtime").Token<OutboundMessageService>;
|
|
14
12
|
/** Generation-owned ingress hooks before ordinary dispatch and after it misses. */
|
|
15
13
|
export interface IngressRoute {
|
|
16
14
|
preRoute?(message: Message, lease: SnapshotLease, requester: PluginId, conversationSequence: number | undefined): Promise<boolean>;
|
|
@@ -49,12 +47,14 @@ export interface ImRuntimeOptions {
|
|
|
49
47
|
*/
|
|
50
48
|
readonly enrichSender?: (sender: MessageSenderRef | undefined, conversation: IncomingMessage['conversation'], snapshot: RuntimeSnapshot) => MessageSenderRef | undefined;
|
|
51
49
|
}
|
|
52
|
-
export declare class ImRuntime implements
|
|
50
|
+
export declare class ImRuntime implements OutboundMessageService {
|
|
53
51
|
#private;
|
|
54
52
|
conversationEvents: ConversationEventStore;
|
|
55
53
|
constructor(options?: ImRuntimeOptions);
|
|
56
54
|
/** Process composition replaces the bootstrap memory store after required DB activation. */
|
|
57
55
|
replaceConversationEventStore(store: ConversationEventStore): void;
|
|
56
|
+
/** Pins all nested IM operations to the snapshot current at operation ingress. */
|
|
57
|
+
runWithSnapshotView<T>(operation: () => Promise<T>): Promise<T>;
|
|
58
58
|
resolveConversationReference(lease: SnapshotLease, reference: ConversationReference, context: EndpointContentResolveContext): Promise<ConversationResolution>;
|
|
59
59
|
readConversationContext(conversation: ConversationRef, consumer: string, throughSequence: number, limit?: number, excludeMessageId?: string): Promise<Readonly<{
|
|
60
60
|
blocks: readonly ConversationContextBlock[];
|
|
@@ -66,7 +66,11 @@ export declare class ImRuntime implements MessageGateway {
|
|
|
66
66
|
readonly messageBus: MessageBus;
|
|
67
67
|
readonly loginAssist: LoginAssist;
|
|
68
68
|
install(resources: Scope): void;
|
|
69
|
-
|
|
69
|
+
/** The sole Adapter ingress, also installed as endpointEventGatewayToken. */
|
|
70
|
+
readonly endpointEvents: EndpointEventGateway & {
|
|
71
|
+
[generationAdmissionBinder](gate: GenerationAdmissionGate): EndpointEventGateway;
|
|
72
|
+
};
|
|
73
|
+
[generationAdmissionBinder](gate: GenerationAdmissionGate): OutboundMessageService;
|
|
70
74
|
/**
|
|
71
75
|
* 注册 interactive action 回跳 handler(prefix 最长匹配;返回注销函数)。
|
|
72
76
|
* 在 Command dispatch 之前路由:action 段 / 数字回跳 / 指令预填 payload。
|
|
@@ -84,11 +88,8 @@ export declare class ImRuntime implements MessageGateway {
|
|
|
84
88
|
* 返回注销函数。listener 抛错不会阻断消息链路。
|
|
85
89
|
*/
|
|
86
90
|
onMessage(listener: (event: RuntimeMessageEvent) => void): () => void;
|
|
87
|
-
receive(input: IncomingMessage): Promise<MessageDispatchResult>;
|
|
88
91
|
send(request: SendRequest): Promise<DeliveryReceipt>;
|
|
89
|
-
|
|
90
|
-
receiveRequest(request: Request): Promise<void>;
|
|
91
|
-
receiveSystem(event: SystemEvent): Promise<void>;
|
|
92
|
+
receiveEndpointEvent(event: EndpointEvent, admission?: GenerationAdmissionGate): Promise<unknown>;
|
|
92
93
|
/** Console `endpoint.list` — empty until Adapter Feature projection is ready. */
|
|
93
94
|
listEndpoints(): readonly {
|
|
94
95
|
readonly id: string;
|
|
@@ -101,6 +102,11 @@ export declare class ImRuntime implements MessageGateway {
|
|
|
101
102
|
readonly operations: readonly AdapterOperation[];
|
|
102
103
|
readonly managementCapabilities: readonly EndpointManagementCapability[];
|
|
103
104
|
}[];
|
|
105
|
+
/** Exact operation capabilities for one concrete live Endpoint. */
|
|
106
|
+
endpointCapabilities(input: {
|
|
107
|
+
readonly adapter: string;
|
|
108
|
+
readonly endpointKey: string;
|
|
109
|
+
}): EndpointCapabilities | undefined;
|
|
104
110
|
/**
|
|
105
111
|
* Console `GET /api/stats` 同源计数:非 root 插件节点 + AdapterIndex endpoints。
|
|
106
112
|
* 供命令 / 状态卡等在 Plugin Runtime 下读取(legacy `root.adapters` / `root.children` 已不存在)。
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import { createToken, generationAdmissionBinder, htmlRendererToken, } from '@zhin.js/plugin-runtime';
|
|
2
|
+
import { AsyncLocalStorage } from 'node:async_hooks';
|
|
2
3
|
import { createPermissionHost, permissionHostToken } from '@zhin.js/permission';
|
|
3
4
|
import { MessageBus, messageBusToken } from './message-bus.js';
|
|
4
|
-
import { adapterFeatureId, isAdapterIndex, resolveEndpointManagement, } from '@zhin.js/adapter';
|
|
5
|
+
import { adapterFeatureId, isAdapterIndex, resolveEndpointManagement, endpointEventGatewayToken, } from '@zhin.js/adapter';
|
|
5
6
|
import { MemoryConversationEventStore, conversationRefKey, messageRefKey, } from '@zhin.js/im-contract';
|
|
6
7
|
import { segmentsToPlainText } from '../../built/segment-contract/text.js';
|
|
7
8
|
import { isMiddlewareIndex, middlewareFeatureId } from '@zhin.js/middleware';
|
|
8
9
|
import { isHandlerIndex, handlerFeatureId } from '../../feature/handler.js';
|
|
9
10
|
import { formatCompact, getLogger, truncatePreview } from '@zhin.js/logger';
|
|
10
11
|
import { Message, createOutboundEnvelope, } from './contracts.js';
|
|
11
|
-
import { sideEventGatewayToken, } from './side-event-gateway.js';
|
|
12
12
|
import { loginAssistToken } from './login-assist-host.js';
|
|
13
13
|
import { LoginAssist } from '../../built/login-assist.js';
|
|
14
14
|
import { sideEventSendChannel } from '../../side-event/base.js';
|
|
@@ -20,7 +20,8 @@ import { keyboardFallbackStore } from '../../built/interactive-segments/fallback
|
|
|
20
20
|
import { assertUserInteractionRequest, parseUserInteractionAnswer, projectUserInteraction, renderUserInteraction, } from '../../built/user-interaction.js';
|
|
21
21
|
import { findRuntimeInteractiveHandler, resolveRuntimeInteractivePayload, runtimeInteractiveConversationKey, } from './interactive.js';
|
|
22
22
|
const logger = getLogger('im');
|
|
23
|
-
|
|
23
|
+
/** @public Stable inbound and outbound IM gateway token for Adapter integrations. */
|
|
24
|
+
export const outboundMessageToken = createToken('zhin.im.outbound-message');
|
|
24
25
|
export const ingressRouteToken = createToken('zhin.im.ingress-route');
|
|
25
26
|
export const messagePreviewLimit = 200;
|
|
26
27
|
class UserInteractionTimeoutError extends Error {
|
|
@@ -47,6 +48,7 @@ export class ImRuntime {
|
|
|
47
48
|
#messageListeners = new Set();
|
|
48
49
|
#interactiveHandlers = [];
|
|
49
50
|
#interactionClaims = new Map();
|
|
51
|
+
#operationSnapshot = new AsyncLocalStorage();
|
|
50
52
|
#snapshots;
|
|
51
53
|
#inboundClaim;
|
|
52
54
|
#enrichSender;
|
|
@@ -64,6 +66,21 @@ export class ImRuntime {
|
|
|
64
66
|
replaceConversationEventStore(store) {
|
|
65
67
|
this.conversationEvents = store;
|
|
66
68
|
}
|
|
69
|
+
/** Pins all nested IM operations to the snapshot current at operation ingress. */
|
|
70
|
+
async runWithSnapshotView(operation) {
|
|
71
|
+
const inherited = this.#operationSnapshot.getStore();
|
|
72
|
+
if (inherited?.active)
|
|
73
|
+
return operation();
|
|
74
|
+
if (!this.#snapshots)
|
|
75
|
+
throw new Error('ImRuntime is not attached to a Root');
|
|
76
|
+
const lease = this.#snapshots.acquire();
|
|
77
|
+
try {
|
|
78
|
+
return await this.#operationSnapshot.run(lease, operation);
|
|
79
|
+
}
|
|
80
|
+
finally {
|
|
81
|
+
lease.release();
|
|
82
|
+
}
|
|
83
|
+
}
|
|
67
84
|
async resolveConversationReference(lease, reference, context) {
|
|
68
85
|
if (!this.#snapshots?.owns(lease) || !lease.active) {
|
|
69
86
|
return Object.freeze({ status: 'expired', code: 'generation_lease_expired' });
|
|
@@ -102,29 +119,20 @@ export class ImRuntime {
|
|
|
102
119
|
messageBus = new MessageBus();
|
|
103
120
|
loginAssist = new LoginAssist();
|
|
104
121
|
install(resources) {
|
|
105
|
-
resources.provide(
|
|
106
|
-
resources.provide(
|
|
122
|
+
resources.provide(outboundMessageToken, this);
|
|
123
|
+
resources.provide(endpointEventGatewayToken, this.endpointEvents);
|
|
107
124
|
resources.provide(loginAssistToken, this.loginAssist);
|
|
108
125
|
resources.provide(permissionHostToken, this.permissionHost);
|
|
109
126
|
resources.provide(messageBusToken, this.messageBus);
|
|
110
127
|
}
|
|
111
|
-
|
|
128
|
+
/** The sole Adapter ingress, also installed as endpointEventGatewayToken. */
|
|
129
|
+
endpointEvents = (() => {
|
|
112
130
|
const self = this;
|
|
113
131
|
const gateway = {
|
|
114
|
-
|
|
115
|
-
receiveRequest: (request) => self.receiveRequest(request),
|
|
116
|
-
receiveSystem: (event) => self.receiveSystem(event),
|
|
132
|
+
receive: (event) => self.receiveEndpointEvent(event),
|
|
117
133
|
[generationAdmissionBinder](gate) {
|
|
118
134
|
return Object.freeze({
|
|
119
|
-
|
|
120
|
-
await gate.enter(() => self.receiveNotice(notice));
|
|
121
|
-
},
|
|
122
|
-
receiveRequest: async (request) => {
|
|
123
|
-
await gate.enter(() => self.receiveRequest(request));
|
|
124
|
-
},
|
|
125
|
-
receiveSystem: async (event) => {
|
|
126
|
-
await gate.enter(() => self.receiveSystem(event));
|
|
127
|
-
},
|
|
135
|
+
receive: async (event) => gate.enter(() => self.receiveEndpointEvent(event, gate)),
|
|
128
136
|
});
|
|
129
137
|
},
|
|
130
138
|
};
|
|
@@ -132,8 +140,6 @@ export class ImRuntime {
|
|
|
132
140
|
})();
|
|
133
141
|
[generationAdmissionBinder](gate) {
|
|
134
142
|
const gateway = {
|
|
135
|
-
receive: async (input) => gate.enter(() => this.#receive(input, gate))
|
|
136
|
-
?? Object.freeze({ matched: false }),
|
|
137
143
|
send: async (request) => gate.enter(() => this.send(request))
|
|
138
144
|
?? failedReceipt('generation_not_admitted'),
|
|
139
145
|
registerInteractiveHandler: (prefix, handler) => this.#registerInteractiveHandler(prefix, handler, gate),
|
|
@@ -315,10 +321,8 @@ export class ImRuntime {
|
|
|
315
321
|
}
|
|
316
322
|
}
|
|
317
323
|
}
|
|
318
|
-
async receive(
|
|
319
|
-
|
|
320
|
-
}
|
|
321
|
-
async #receive(input, admission) {
|
|
324
|
+
async #receive(source, admission) {
|
|
325
|
+
const input = source.payload;
|
|
322
326
|
const lease = this.#acquire();
|
|
323
327
|
let active = true;
|
|
324
328
|
try {
|
|
@@ -354,7 +358,11 @@ export class ImRuntime {
|
|
|
354
358
|
mentioned: input.mentioned,
|
|
355
359
|
},
|
|
356
360
|
}, lease.value);
|
|
357
|
-
}, enrichedSender, Object.freeze({ ...input.metadata }), input.segments ? Object.freeze([...input.segments]) : undefined, input.message, input.endpointId, input.mentioned, input.replyTo)
|
|
361
|
+
}, enrichedSender, Object.freeze({ ...input.metadata }), input.segments ? Object.freeze([...input.segments]) : undefined, input.message, input.endpointId, input.mentioned, input.replyTo, () => {
|
|
362
|
+
if (!active)
|
|
363
|
+
throw new Error('Message Client scope has ended');
|
|
364
|
+
return source.client;
|
|
365
|
+
}, source.endpoint.adapter);
|
|
358
366
|
let conversationSequence;
|
|
359
367
|
if (input.message?.id) {
|
|
360
368
|
const appended = await this.conversationEvents.append(Object.freeze({
|
|
@@ -394,7 +402,9 @@ export class ImRuntime {
|
|
|
394
402
|
result = Object.freeze({ matched: true, command: 'pre-route', owner: requester });
|
|
395
403
|
return;
|
|
396
404
|
}
|
|
397
|
-
await this.#runHandlers(lease.value, 'message.receive', [
|
|
405
|
+
await this.#runHandlers(lease.value, 'message.receive', [
|
|
406
|
+
withEndpointEventPayload(source, message),
|
|
407
|
+
]);
|
|
398
408
|
result = await this.#dispatchInteractive(message, requester, admission)
|
|
399
409
|
?? await this.#dispatcher.dispatch(message, lease.value, interactionFactory);
|
|
400
410
|
if (!result.matched && ingressRoute) {
|
|
@@ -425,7 +435,7 @@ export class ImRuntime {
|
|
|
425
435
|
}
|
|
426
436
|
finally {
|
|
427
437
|
active = false;
|
|
428
|
-
|
|
438
|
+
this.#release(lease);
|
|
429
439
|
}
|
|
430
440
|
}
|
|
431
441
|
async send(request) {
|
|
@@ -434,18 +444,19 @@ export class ImRuntime {
|
|
|
434
444
|
return await this.#sendWithSnapshot(request, lease.value);
|
|
435
445
|
}
|
|
436
446
|
finally {
|
|
437
|
-
|
|
447
|
+
this.#release(lease);
|
|
438
448
|
}
|
|
439
449
|
}
|
|
440
|
-
async receiveNotice(
|
|
450
|
+
async #receiveNotice(source) {
|
|
451
|
+
const notice = source.payload;
|
|
441
452
|
const event = conversationEventFromNotice(notice);
|
|
442
453
|
if (event)
|
|
443
454
|
await this.conversationEvents.append(event);
|
|
444
|
-
await this.#receiveSideEvent(
|
|
455
|
+
await this.#receiveSideEvent(withEndpointEventPayload(source, notice));
|
|
445
456
|
}
|
|
446
|
-
async receiveRequest(
|
|
447
|
-
await this.#withRequestActionScope(
|
|
448
|
-
await this.#receiveSideEvent(
|
|
457
|
+
async #receiveRequest(source) {
|
|
458
|
+
await this.#withRequestActionScope(source.payload, async (scoped) => {
|
|
459
|
+
await this.#receiveSideEvent(withEndpointEventPayload(source, scoped));
|
|
449
460
|
});
|
|
450
461
|
}
|
|
451
462
|
async #withRequestActionScope(request, dispatch) {
|
|
@@ -471,16 +482,38 @@ export class ImRuntime {
|
|
|
471
482
|
await Promise.allSettled([...actions]);
|
|
472
483
|
}
|
|
473
484
|
}
|
|
474
|
-
async receiveSystem(
|
|
475
|
-
await this.#receiveSideEvent(
|
|
485
|
+
async #receiveSystem(source) {
|
|
486
|
+
await this.#receiveSideEvent(source);
|
|
476
487
|
}
|
|
477
|
-
async #receiveSideEvent(event
|
|
488
|
+
async #receiveSideEvent(event) {
|
|
478
489
|
const lease = this.#acquire();
|
|
479
490
|
try {
|
|
480
|
-
await this.#runHandlers(lease.value, event, [
|
|
491
|
+
await this.#runHandlers(lease.value, event.name, [event]);
|
|
481
492
|
}
|
|
482
493
|
finally {
|
|
483
|
-
|
|
494
|
+
this.#release(lease);
|
|
495
|
+
}
|
|
496
|
+
}
|
|
497
|
+
async receiveEndpointEvent(event, admission) {
|
|
498
|
+
switch (event.name) {
|
|
499
|
+
case 'message.receive':
|
|
500
|
+
return this.#receive(event, admission);
|
|
501
|
+
case 'notice.receive':
|
|
502
|
+
return this.#receiveNotice(event);
|
|
503
|
+
case 'request.receive':
|
|
504
|
+
return this.#receiveRequest(event);
|
|
505
|
+
case 'system.receive':
|
|
506
|
+
return this.#receiveSystem(event);
|
|
507
|
+
default: {
|
|
508
|
+
const lease = this.#acquire();
|
|
509
|
+
try {
|
|
510
|
+
await this.#runHandlers(lease.value, event.name, [event]);
|
|
511
|
+
return undefined;
|
|
512
|
+
}
|
|
513
|
+
finally {
|
|
514
|
+
this.#release(lease);
|
|
515
|
+
}
|
|
516
|
+
}
|
|
484
517
|
}
|
|
485
518
|
}
|
|
486
519
|
/**
|
|
@@ -518,7 +551,8 @@ export class ImRuntime {
|
|
|
518
551
|
return;
|
|
519
552
|
const options = {
|
|
520
553
|
resolveInteraction: (name, interactionArgs) => {
|
|
521
|
-
const
|
|
554
|
+
const context = interactionArgs[0];
|
|
555
|
+
const payload = context?.payload;
|
|
522
556
|
if (name === 'message.receive' && payload instanceof Message) {
|
|
523
557
|
return this.createInteraction(payload);
|
|
524
558
|
}
|
|
@@ -551,13 +585,30 @@ export class ImRuntime {
|
|
|
551
585
|
}));
|
|
552
586
|
}
|
|
553
587
|
finally {
|
|
554
|
-
|
|
588
|
+
this.#release(lease);
|
|
555
589
|
}
|
|
556
590
|
}
|
|
557
591
|
catch {
|
|
558
592
|
return Object.freeze([]);
|
|
559
593
|
}
|
|
560
594
|
}
|
|
595
|
+
/** Exact operation capabilities for one concrete live Endpoint. */
|
|
596
|
+
endpointCapabilities(input) {
|
|
597
|
+
try {
|
|
598
|
+
const lease = this.#acquire();
|
|
599
|
+
try {
|
|
600
|
+
const index = requireAdapters(lease.value);
|
|
601
|
+
const id = index.resolve(input.adapter, input.endpointKey);
|
|
602
|
+
return id ? index.capabilities(id) : undefined;
|
|
603
|
+
}
|
|
604
|
+
finally {
|
|
605
|
+
this.#release(lease);
|
|
606
|
+
}
|
|
607
|
+
}
|
|
608
|
+
catch {
|
|
609
|
+
return undefined;
|
|
610
|
+
}
|
|
611
|
+
}
|
|
561
612
|
/**
|
|
562
613
|
* Console `GET /api/stats` 同源计数:非 root 插件节点 + AdapterIndex endpoints。
|
|
563
614
|
* 供命令 / 状态卡等在 Plugin Runtime 下读取(legacy `root.adapters` / `root.children` 已不存在)。
|
|
@@ -578,7 +629,7 @@ export class ImRuntime {
|
|
|
578
629
|
});
|
|
579
630
|
}
|
|
580
631
|
finally {
|
|
581
|
-
|
|
632
|
+
this.#release(lease);
|
|
582
633
|
}
|
|
583
634
|
}
|
|
584
635
|
catch {
|
|
@@ -612,7 +663,7 @@ export class ImRuntime {
|
|
|
612
663
|
});
|
|
613
664
|
}
|
|
614
665
|
finally {
|
|
615
|
-
|
|
666
|
+
this.#release(lease);
|
|
616
667
|
}
|
|
617
668
|
}
|
|
618
669
|
catch {
|
|
@@ -640,7 +691,7 @@ export class ImRuntime {
|
|
|
640
691
|
return { messageId: result.message?.id ?? '' };
|
|
641
692
|
}
|
|
642
693
|
finally {
|
|
643
|
-
|
|
694
|
+
this.#release(lease);
|
|
644
695
|
}
|
|
645
696
|
}
|
|
646
697
|
/** Activity-feedback: add a message reaction when the live Endpoint supports it. */
|
|
@@ -678,7 +729,7 @@ export class ImRuntime {
|
|
|
678
729
|
return control ? await run(control) : fallback;
|
|
679
730
|
}
|
|
680
731
|
finally {
|
|
681
|
-
|
|
732
|
+
this.#release(lease);
|
|
682
733
|
}
|
|
683
734
|
}
|
|
684
735
|
/** Run one management operation while the Endpoint generation stays leased. */
|
|
@@ -691,13 +742,13 @@ export class ImRuntime {
|
|
|
691
742
|
return null;
|
|
692
743
|
}
|
|
693
744
|
try {
|
|
694
|
-
const endpoint = requireAdapters(lease.value).
|
|
745
|
+
const endpoint = requireAdapters(lease.value).connection(adapter, endpointKey);
|
|
695
746
|
if (!endpoint)
|
|
696
747
|
return null;
|
|
697
748
|
return await run(resolveEndpointManagement(endpoint) ?? Object.freeze({}));
|
|
698
749
|
}
|
|
699
750
|
finally {
|
|
700
|
-
|
|
751
|
+
this.#release(lease);
|
|
701
752
|
}
|
|
702
753
|
}
|
|
703
754
|
async #sendWithSnapshot(request, snapshot) {
|
|
@@ -710,11 +761,19 @@ export class ImRuntime {
|
|
|
710
761
|
catch {
|
|
711
762
|
return rejectedReceipt('outbound_payload_rejected');
|
|
712
763
|
}
|
|
764
|
+
let adapters;
|
|
765
|
+
try {
|
|
766
|
+
adapters = requireAdapters(snapshot);
|
|
767
|
+
}
|
|
768
|
+
catch (error) {
|
|
769
|
+
return receiptFromEndpointError(error);
|
|
770
|
+
}
|
|
713
771
|
const envelope = createOutboundEnvelope({
|
|
714
772
|
conversation: request.conversation,
|
|
715
773
|
requester: request.requester,
|
|
716
774
|
generation: snapshot.generation,
|
|
717
|
-
|
|
775
|
+
clientAdapter: adapters.clientAdapter(adapter),
|
|
776
|
+
}, initialPayload, () => adapters.clientById(adapter));
|
|
718
777
|
let terminalEntered = false;
|
|
719
778
|
let receipt;
|
|
720
779
|
try {
|
|
@@ -787,10 +846,18 @@ export class ImRuntime {
|
|
|
787
846
|
return receipt ?? failedReceipt('outbound_delivery_incomplete');
|
|
788
847
|
}
|
|
789
848
|
#acquire() {
|
|
849
|
+
const inherited = this.#operationSnapshot.getStore();
|
|
850
|
+
if (inherited?.active)
|
|
851
|
+
return inherited;
|
|
790
852
|
if (!this.#snapshots)
|
|
791
853
|
throw new Error('ImRuntime is not attached to a Root');
|
|
792
854
|
return this.#snapshots.acquire();
|
|
793
855
|
}
|
|
856
|
+
#release(lease) {
|
|
857
|
+
if (this.#operationSnapshot.getStore() === lease)
|
|
858
|
+
return;
|
|
859
|
+
lease.release();
|
|
860
|
+
}
|
|
794
861
|
/**
|
|
795
862
|
* interactive 回跳分发(Command dispatch 之前):action 段 / 中央 fallback
|
|
796
863
|
* 数字回跳 / 指令预填 payload → prefix 最长匹配 handler。
|
|
@@ -1113,3 +1180,11 @@ function abortError(signal, fallback) {
|
|
|
1113
1180
|
return signal.reason;
|
|
1114
1181
|
return new Error(fallback);
|
|
1115
1182
|
}
|
|
1183
|
+
function withEndpointEventPayload(source, payload) {
|
|
1184
|
+
return Object.freeze({
|
|
1185
|
+
name: source.name,
|
|
1186
|
+
payload,
|
|
1187
|
+
endpoint: source.endpoint,
|
|
1188
|
+
client: source.client,
|
|
1189
|
+
});
|
|
1190
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { LoginAssist } from '../../built/login-assist.js';
|
|
2
2
|
/**
|
|
3
|
-
* Plugin Runtime login-assist port
|
|
3
|
+
* Plugin Runtime login-assist port(与出站消息服务并列)。
|
|
4
4
|
* 适配器 waitForInput;Console / stdin 经 listPending + submit 消费。
|
|
5
5
|
*/
|
|
6
6
|
export declare const loginAssistToken: import("@zhin.js/plugin-runtime").Token<LoginAssist>;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { createToken } from '@zhin.js/plugin-runtime';
|
|
2
2
|
/**
|
|
3
|
-
* Plugin Runtime login-assist port
|
|
3
|
+
* Plugin Runtime login-assist port(与出站消息服务并列)。
|
|
4
4
|
* 适配器 waitForInput;Console / stdin 经 listPending + submit 消费。
|
|
5
5
|
*/
|
|
6
6
|
export const loginAssistToken = createToken('zhin.im.login-assist');
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Public IM gateway contract exposed from `zhin.js/core/runtime`.
|
|
3
|
+
* @module zhin.js/core/runtime
|
|
4
|
+
*/
|
|
5
|
+
export { outboundMessageToken } from './im-runtime.js';
|
|
6
|
+
export { Message, type ComponentCall, type ConversationAddress, type IncomingContext, type IncomingMessage, type MessageDispatchResult, type OutboundMessageService, type MessageSenderRef, type OutboundEnvelope, type RawContent, type SendContent, type SendRequest, } from './contracts.js';
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { EndpointEventEmitter } from '@zhin.js/adapter';
|
|
2
2
|
import { type OneBotLikeRawEvent, type SideEventPlatform } from './normalize.js';
|
|
3
3
|
export interface OneBotLikeSideEventInput {
|
|
4
4
|
readonly adapter: string;
|
|
@@ -9,7 +9,7 @@ export interface OneBotLikeSideEventInput {
|
|
|
9
9
|
readonly reject?: (flag: string, reason?: string) => void | Promise<void>;
|
|
10
10
|
}
|
|
11
11
|
/**
|
|
12
|
-
* Normalize OneBot / icqq-style notice|request|meta payloads and
|
|
12
|
+
* Normalize OneBot / icqq-style notice|request|meta payloads and feed Endpoint.emit().
|
|
13
13
|
* Returns which kind was dispatched, or null when the payload is not a side event.
|
|
14
14
|
*/
|
|
15
|
-
export declare function receiveOneBotLikeSideEvent(
|
|
15
|
+
export declare function receiveOneBotLikeSideEvent(emit: EndpointEventEmitter, input: OneBotLikeSideEventInput): Promise<'notice' | 'request' | 'system' | null>;
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { buildNotice, buildRequest, buildSystem, mapNoticeParts, mapRequestParts, resolveSideEventDedupeKey, senderFromId, } from './normalize.js';
|
|
2
2
|
/**
|
|
3
|
-
* Normalize OneBot / icqq-style notice|request|meta payloads and
|
|
3
|
+
* Normalize OneBot / icqq-style notice|request|meta payloads and feed Endpoint.emit().
|
|
4
4
|
* Returns which kind was dispatched, or null when the payload is not a side event.
|
|
5
5
|
*/
|
|
6
|
-
export async function receiveOneBotLikeSideEvent(
|
|
6
|
+
export async function receiveOneBotLikeSideEvent(emit, input) {
|
|
7
7
|
const raw = input.raw;
|
|
8
8
|
const platform = input.platform ?? 'onebot';
|
|
9
9
|
const postType = String(raw.post_type ?? raw.type ?? '');
|
|
@@ -47,7 +47,7 @@ export async function receiveOneBotLikeSideEvent(gateway, input) {
|
|
|
47
47
|
? { $role: 'admin', $enabled: String(raw.sub_type ?? '') === 'set' }
|
|
48
48
|
: {}),
|
|
49
49
|
});
|
|
50
|
-
await
|
|
50
|
+
await emit('notice.receive', notice);
|
|
51
51
|
return 'notice';
|
|
52
52
|
}
|
|
53
53
|
if (postType === 'request' || postType.startsWith('request.')) {
|
|
@@ -96,7 +96,7 @@ export async function receiveOneBotLikeSideEvent(gateway, input) {
|
|
|
96
96
|
},
|
|
97
97
|
});
|
|
98
98
|
try {
|
|
99
|
-
await
|
|
99
|
+
await emit('request.receive', request);
|
|
100
100
|
}
|
|
101
101
|
finally {
|
|
102
102
|
active = false;
|
|
@@ -127,7 +127,7 @@ export async function receiveOneBotLikeSideEvent(gateway, input) {
|
|
|
127
127
|
$sub_type: subType ?? metaType,
|
|
128
128
|
$timestamp: toMillis(raw.time),
|
|
129
129
|
});
|
|
130
|
-
await
|
|
130
|
+
await emit('system.receive', system);
|
|
131
131
|
return 'system';
|
|
132
132
|
}
|
|
133
133
|
return null;
|
package/lib/utils.d.ts
CHANGED
|
@@ -70,7 +70,7 @@ export declare namespace segment {
|
|
|
70
70
|
backgroundColor?: string;
|
|
71
71
|
fileName?: string;
|
|
72
72
|
}): HtmlSegment;
|
|
73
|
-
/**
|
|
73
|
+
/** Short alias for {@link htmlCard}. */
|
|
74
74
|
const html: typeof htmlCard;
|
|
75
75
|
/** 出站 Markdown 段(Adapter policy 决定 image/text/origin) */
|
|
76
76
|
function markdown(content: string, options?: Omit<MarkdownSegment['data'], 'content'>): MarkdownSegment;
|
package/lib/utils.js
CHANGED
|
@@ -98,7 +98,7 @@ export function segment(type, data) {
|
|
|
98
98
|
return new HtmlSegment(options);
|
|
99
99
|
}
|
|
100
100
|
segment.htmlCard = htmlCard;
|
|
101
|
-
/**
|
|
101
|
+
/** Short alias for {@link htmlCard}. */
|
|
102
102
|
segment.html = htmlCard;
|
|
103
103
|
/** 出站 Markdown 段(Adapter policy 决定 image/text/origin) */
|
|
104
104
|
function markdown(content, options = {}) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zhin.js/core",
|
|
3
|
-
"version": "1.5.
|
|
3
|
+
"version": "1.5.14",
|
|
4
4
|
"description": "Zhin机器人核心框架",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./lib/index.js",
|
|
@@ -75,18 +75,18 @@
|
|
|
75
75
|
"segment-matcher": "^1.0.5",
|
|
76
76
|
"smol-toml": "^1.7.1",
|
|
77
77
|
"yaml": "^2.9.0",
|
|
78
|
-
"@zhin.js/adapter": "1.2.
|
|
79
|
-
"@zhin.js/
|
|
80
|
-
"@zhin.js/
|
|
81
|
-
"@zhin.js/database": "1.0.
|
|
82
|
-
"@zhin.js/handler": "1.0.
|
|
78
|
+
"@zhin.js/adapter": "1.2.1",
|
|
79
|
+
"@zhin.js/command": "1.0.16",
|
|
80
|
+
"@zhin.js/component": "1.0.13",
|
|
81
|
+
"@zhin.js/database": "1.0.80",
|
|
82
|
+
"@zhin.js/handler": "1.0.4",
|
|
83
83
|
"@zhin.js/im-contract": "1.0.4",
|
|
84
84
|
"@zhin.js/interaction": "1.0.1",
|
|
85
|
-
"@zhin.js/kernel": "1.0.
|
|
86
|
-
"@zhin.js/logger": "1.0.
|
|
87
|
-
"@zhin.js/middleware": "1.0.
|
|
88
|
-
"@zhin.js/
|
|
89
|
-
"@zhin.js/
|
|
85
|
+
"@zhin.js/kernel": "1.0.8",
|
|
86
|
+
"@zhin.js/logger": "1.0.77",
|
|
87
|
+
"@zhin.js/middleware": "1.0.13",
|
|
88
|
+
"@zhin.js/permission": "1.0.4",
|
|
89
|
+
"@zhin.js/plugin-runtime": "1.1.8",
|
|
90
90
|
"@zhin.js/schema": "1.0.73"
|
|
91
91
|
},
|
|
92
92
|
"peerDependencies": {
|
|
@@ -102,7 +102,7 @@
|
|
|
102
102
|
"@types/qrcode": "^1.5.6",
|
|
103
103
|
"ajv": "8.18.0",
|
|
104
104
|
"typescript": "^6.0.3",
|
|
105
|
-
"@zhin.js/ai": "1.5.
|
|
105
|
+
"@zhin.js/ai": "1.5.7"
|
|
106
106
|
},
|
|
107
107
|
"repository": {
|
|
108
108
|
"type": "git",
|
package/lib/agent-prompt.d.ts
DELETED
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Agent system-prompt extension contract (per IM platform / adapter).
|
|
3
|
-
*
|
|
4
|
-
* Implementations live in adapter plugins; resolution runs in @zhin.js/agent.
|
|
5
|
-
*/
|
|
6
|
-
export type AgentPromptSlot = 'orchestrator' | 'deferred_worker';
|
|
7
|
-
/** Minimal tool shape for deferred catalog selection (no @zhin.js/ai import). */
|
|
8
|
-
export interface DeferredToolCatalogItem {
|
|
9
|
-
name: string;
|
|
10
|
-
description: string;
|
|
11
|
-
}
|
|
12
|
-
export interface AgentPromptBuildContext {
|
|
13
|
-
slot: AgentPromptSlot;
|
|
14
|
-
/** Authenticated IM platform projected by the ingress adapter. */
|
|
15
|
-
platform: string;
|
|
16
|
-
/** Truncated user message for intent hints (~500 chars). */
|
|
17
|
-
userMessagePreview?: string;
|
|
18
|
-
deferred?: {
|
|
19
|
-
goal: string;
|
|
20
|
-
toolQuery?: string;
|
|
21
|
-
domainStats?: string;
|
|
22
|
-
};
|
|
23
|
-
}
|
|
24
|
-
export interface AgentPromptSection {
|
|
25
|
-
/** Stable id for debug / logs (e.g. platform.icqq.orchestrator). */
|
|
26
|
-
id: string;
|
|
27
|
-
title?: string;
|
|
28
|
-
body: string;
|
|
29
|
-
/** Lower sorts earlier; default 100. */
|
|
30
|
-
priority?: number;
|
|
31
|
-
}
|
|
32
|
-
export interface AgentPromptContributor {
|
|
33
|
-
readonly platform: string;
|
|
34
|
-
buildSections(ctx: AgentPromptBuildContext): Promise<AgentPromptSection[] | null>;
|
|
35
|
-
/** When true, platform may supply selectDeferredTools for this task. */
|
|
36
|
-
matchesDeferredTask?(ctx: AgentPromptBuildContext): boolean;
|
|
37
|
-
/** Non-null replaces default TF-IDF deferred tool selection. */
|
|
38
|
-
selectDeferredTools?(query: string, goal: string, catalog: DeferredToolCatalogItem[], maxTools: number): DeferredToolCatalogItem[] | null;
|
|
39
|
-
}
|
package/lib/agent-prompt.js
DELETED
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import type { Notice } from '../../notice.js';
|
|
2
|
-
import type { Request } from '../../request.js';
|
|
3
|
-
import type { SystemEvent } from '../../system-event.js';
|
|
4
|
-
/**
|
|
5
|
-
* Plugin Runtime 侧事件入站口(与 messageGatewayToken 并列)。
|
|
6
|
-
* 适配器归一 Notice / Request / SystemEvent 后调用,由 ImRuntime 分发给 HandlerIndex。
|
|
7
|
-
*/
|
|
8
|
-
export interface SideEventGateway {
|
|
9
|
-
receiveNotice(notice: Notice): Promise<void>;
|
|
10
|
-
receiveRequest(request: Request): Promise<void>;
|
|
11
|
-
receiveSystem(event: SystemEvent): Promise<void>;
|
|
12
|
-
}
|
|
13
|
-
export declare const sideEventGatewayToken: import("@zhin.js/plugin-runtime").Token<SideEventGateway>;
|