@zhin.js/core 1.5.13 → 1.5.15
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 +23 -13
- package/lib/plugin-runtime/im/im-runtime.js +136 -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,19 +1,19 @@
|
|
|
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>;
|
|
15
|
+
/** A live pre-route handoff that must run before handlers and commands. */
|
|
16
|
+
shouldRouteBeforeDispatch?(message: Message): boolean;
|
|
17
17
|
route(message: Message, lease: SnapshotLease, requester: PluginId, conversationSequence: number | undefined): Promise<boolean>;
|
|
18
18
|
}
|
|
19
19
|
export declare const ingressRouteToken: import("@zhin.js/plugin-runtime").Token<IngressRoute>;
|
|
@@ -49,12 +49,14 @@ export interface ImRuntimeOptions {
|
|
|
49
49
|
*/
|
|
50
50
|
readonly enrichSender?: (sender: MessageSenderRef | undefined, conversation: IncomingMessage['conversation'], snapshot: RuntimeSnapshot) => MessageSenderRef | undefined;
|
|
51
51
|
}
|
|
52
|
-
export declare class ImRuntime implements
|
|
52
|
+
export declare class ImRuntime implements OutboundMessageService {
|
|
53
53
|
#private;
|
|
54
54
|
conversationEvents: ConversationEventStore;
|
|
55
55
|
constructor(options?: ImRuntimeOptions);
|
|
56
56
|
/** Process composition replaces the bootstrap memory store after required DB activation. */
|
|
57
57
|
replaceConversationEventStore(store: ConversationEventStore): void;
|
|
58
|
+
/** Pins all nested IM operations to the snapshot current at operation ingress. */
|
|
59
|
+
runWithSnapshotView<T>(operation: () => Promise<T>): Promise<T>;
|
|
58
60
|
resolveConversationReference(lease: SnapshotLease, reference: ConversationReference, context: EndpointContentResolveContext): Promise<ConversationResolution>;
|
|
59
61
|
readConversationContext(conversation: ConversationRef, consumer: string, throughSequence: number, limit?: number, excludeMessageId?: string): Promise<Readonly<{
|
|
60
62
|
blocks: readonly ConversationContextBlock[];
|
|
@@ -66,7 +68,11 @@ export declare class ImRuntime implements MessageGateway {
|
|
|
66
68
|
readonly messageBus: MessageBus;
|
|
67
69
|
readonly loginAssist: LoginAssist;
|
|
68
70
|
install(resources: Scope): void;
|
|
69
|
-
|
|
71
|
+
/** The sole Adapter ingress, also installed as endpointEventGatewayToken. */
|
|
72
|
+
readonly endpointEvents: EndpointEventGateway & {
|
|
73
|
+
[generationAdmissionBinder](gate: GenerationAdmissionGate): EndpointEventGateway;
|
|
74
|
+
};
|
|
75
|
+
[generationAdmissionBinder](gate: GenerationAdmissionGate): OutboundMessageService;
|
|
70
76
|
/**
|
|
71
77
|
* 注册 interactive action 回跳 handler(prefix 最长匹配;返回注销函数)。
|
|
72
78
|
* 在 Command dispatch 之前路由:action 段 / 数字回跳 / 指令预填 payload。
|
|
@@ -84,11 +90,10 @@ export declare class ImRuntime implements MessageGateway {
|
|
|
84
90
|
* 返回注销函数。listener 抛错不会阻断消息链路。
|
|
85
91
|
*/
|
|
86
92
|
onMessage(listener: (event: RuntimeMessageEvent) => void): () => void;
|
|
87
|
-
receive(input: IncomingMessage): Promise<MessageDispatchResult>;
|
|
88
93
|
send(request: SendRequest): Promise<DeliveryReceipt>;
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
94
|
+
/** Sends through the exact generation lease that admitted the current operation. */
|
|
95
|
+
sendWithSnapshotLease(lease: SnapshotLease, request: SendRequest): Promise<DeliveryReceipt>;
|
|
96
|
+
receiveEndpointEvent(event: EndpointEvent, admission?: GenerationAdmissionGate): Promise<unknown>;
|
|
92
97
|
/** Console `endpoint.list` — empty until Adapter Feature projection is ready. */
|
|
93
98
|
listEndpoints(): readonly {
|
|
94
99
|
readonly id: string;
|
|
@@ -101,6 +106,11 @@ export declare class ImRuntime implements MessageGateway {
|
|
|
101
106
|
readonly operations: readonly AdapterOperation[];
|
|
102
107
|
readonly managementCapabilities: readonly EndpointManagementCapability[];
|
|
103
108
|
}[];
|
|
109
|
+
/** Exact operation capabilities for one concrete live Endpoint. */
|
|
110
|
+
endpointCapabilities(input: {
|
|
111
|
+
readonly adapter: string;
|
|
112
|
+
readonly endpointKey: string;
|
|
113
|
+
}): EndpointCapabilities | undefined;
|
|
104
114
|
/**
|
|
105
115
|
* Console `GET /api/stats` 同源计数:非 root 插件节点 + AdapterIndex endpoints。
|
|
106
116
|
* 供命令 / 状态卡等在 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,16 @@ export class ImRuntime {
|
|
|
394
402
|
result = Object.freeze({ matched: true, command: 'pre-route', owner: requester });
|
|
395
403
|
return;
|
|
396
404
|
}
|
|
397
|
-
|
|
405
|
+
if (ingressRoute?.shouldRouteBeforeDispatch?.(message) === true) {
|
|
406
|
+
const handled = await ingressRoute.route(message, lease, requester, conversationSequence);
|
|
407
|
+
if (handled) {
|
|
408
|
+
result = Object.freeze({ matched: true, command: 'ai', owner: requester });
|
|
409
|
+
return;
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
await this.#runHandlers(lease.value, 'message.receive', [
|
|
413
|
+
withEndpointEventPayload(source, message),
|
|
414
|
+
]);
|
|
398
415
|
result = await this.#dispatchInteractive(message, requester, admission)
|
|
399
416
|
?? await this.#dispatcher.dispatch(message, lease.value, interactionFactory);
|
|
400
417
|
if (!result.matched && ingressRoute) {
|
|
@@ -425,7 +442,7 @@ export class ImRuntime {
|
|
|
425
442
|
}
|
|
426
443
|
finally {
|
|
427
444
|
active = false;
|
|
428
|
-
|
|
445
|
+
this.#release(lease);
|
|
429
446
|
}
|
|
430
447
|
}
|
|
431
448
|
async send(request) {
|
|
@@ -434,18 +451,26 @@ export class ImRuntime {
|
|
|
434
451
|
return await this.#sendWithSnapshot(request, lease.value);
|
|
435
452
|
}
|
|
436
453
|
finally {
|
|
437
|
-
|
|
454
|
+
this.#release(lease);
|
|
438
455
|
}
|
|
439
456
|
}
|
|
440
|
-
|
|
457
|
+
/** Sends through the exact generation lease that admitted the current operation. */
|
|
458
|
+
async sendWithSnapshotLease(lease, request) {
|
|
459
|
+
if (!this.#snapshots?.owns(lease) || !lease.active) {
|
|
460
|
+
throw new Error('Outbound message generation lease expired');
|
|
461
|
+
}
|
|
462
|
+
return this.#sendWithSnapshot(request, lease.value);
|
|
463
|
+
}
|
|
464
|
+
async #receiveNotice(source) {
|
|
465
|
+
const notice = source.payload;
|
|
441
466
|
const event = conversationEventFromNotice(notice);
|
|
442
467
|
if (event)
|
|
443
468
|
await this.conversationEvents.append(event);
|
|
444
|
-
await this.#receiveSideEvent(
|
|
469
|
+
await this.#receiveSideEvent(withEndpointEventPayload(source, notice));
|
|
445
470
|
}
|
|
446
|
-
async receiveRequest(
|
|
447
|
-
await this.#withRequestActionScope(
|
|
448
|
-
await this.#receiveSideEvent(
|
|
471
|
+
async #receiveRequest(source) {
|
|
472
|
+
await this.#withRequestActionScope(source.payload, async (scoped) => {
|
|
473
|
+
await this.#receiveSideEvent(withEndpointEventPayload(source, scoped));
|
|
449
474
|
});
|
|
450
475
|
}
|
|
451
476
|
async #withRequestActionScope(request, dispatch) {
|
|
@@ -471,16 +496,38 @@ export class ImRuntime {
|
|
|
471
496
|
await Promise.allSettled([...actions]);
|
|
472
497
|
}
|
|
473
498
|
}
|
|
474
|
-
async receiveSystem(
|
|
475
|
-
await this.#receiveSideEvent(
|
|
499
|
+
async #receiveSystem(source) {
|
|
500
|
+
await this.#receiveSideEvent(source);
|
|
476
501
|
}
|
|
477
|
-
async #receiveSideEvent(event
|
|
502
|
+
async #receiveSideEvent(event) {
|
|
478
503
|
const lease = this.#acquire();
|
|
479
504
|
try {
|
|
480
|
-
await this.#runHandlers(lease.value, event, [
|
|
505
|
+
await this.#runHandlers(lease.value, event.name, [event]);
|
|
481
506
|
}
|
|
482
507
|
finally {
|
|
483
|
-
|
|
508
|
+
this.#release(lease);
|
|
509
|
+
}
|
|
510
|
+
}
|
|
511
|
+
async receiveEndpointEvent(event, admission) {
|
|
512
|
+
switch (event.name) {
|
|
513
|
+
case 'message.receive':
|
|
514
|
+
return this.#receive(event, admission);
|
|
515
|
+
case 'notice.receive':
|
|
516
|
+
return this.#receiveNotice(event);
|
|
517
|
+
case 'request.receive':
|
|
518
|
+
return this.#receiveRequest(event);
|
|
519
|
+
case 'system.receive':
|
|
520
|
+
return this.#receiveSystem(event);
|
|
521
|
+
default: {
|
|
522
|
+
const lease = this.#acquire();
|
|
523
|
+
try {
|
|
524
|
+
await this.#runHandlers(lease.value, event.name, [event]);
|
|
525
|
+
return undefined;
|
|
526
|
+
}
|
|
527
|
+
finally {
|
|
528
|
+
this.#release(lease);
|
|
529
|
+
}
|
|
530
|
+
}
|
|
484
531
|
}
|
|
485
532
|
}
|
|
486
533
|
/**
|
|
@@ -518,7 +565,8 @@ export class ImRuntime {
|
|
|
518
565
|
return;
|
|
519
566
|
const options = {
|
|
520
567
|
resolveInteraction: (name, interactionArgs) => {
|
|
521
|
-
const
|
|
568
|
+
const context = interactionArgs[0];
|
|
569
|
+
const payload = context?.payload;
|
|
522
570
|
if (name === 'message.receive' && payload instanceof Message) {
|
|
523
571
|
return this.createInteraction(payload);
|
|
524
572
|
}
|
|
@@ -551,13 +599,30 @@ export class ImRuntime {
|
|
|
551
599
|
}));
|
|
552
600
|
}
|
|
553
601
|
finally {
|
|
554
|
-
|
|
602
|
+
this.#release(lease);
|
|
555
603
|
}
|
|
556
604
|
}
|
|
557
605
|
catch {
|
|
558
606
|
return Object.freeze([]);
|
|
559
607
|
}
|
|
560
608
|
}
|
|
609
|
+
/** Exact operation capabilities for one concrete live Endpoint. */
|
|
610
|
+
endpointCapabilities(input) {
|
|
611
|
+
try {
|
|
612
|
+
const lease = this.#acquire();
|
|
613
|
+
try {
|
|
614
|
+
const index = requireAdapters(lease.value);
|
|
615
|
+
const id = index.resolve(input.adapter, input.endpointKey);
|
|
616
|
+
return id ? index.capabilities(id) : undefined;
|
|
617
|
+
}
|
|
618
|
+
finally {
|
|
619
|
+
this.#release(lease);
|
|
620
|
+
}
|
|
621
|
+
}
|
|
622
|
+
catch {
|
|
623
|
+
return undefined;
|
|
624
|
+
}
|
|
625
|
+
}
|
|
561
626
|
/**
|
|
562
627
|
* Console `GET /api/stats` 同源计数:非 root 插件节点 + AdapterIndex endpoints。
|
|
563
628
|
* 供命令 / 状态卡等在 Plugin Runtime 下读取(legacy `root.adapters` / `root.children` 已不存在)。
|
|
@@ -578,7 +643,7 @@ export class ImRuntime {
|
|
|
578
643
|
});
|
|
579
644
|
}
|
|
580
645
|
finally {
|
|
581
|
-
|
|
646
|
+
this.#release(lease);
|
|
582
647
|
}
|
|
583
648
|
}
|
|
584
649
|
catch {
|
|
@@ -612,7 +677,7 @@ export class ImRuntime {
|
|
|
612
677
|
});
|
|
613
678
|
}
|
|
614
679
|
finally {
|
|
615
|
-
|
|
680
|
+
this.#release(lease);
|
|
616
681
|
}
|
|
617
682
|
}
|
|
618
683
|
catch {
|
|
@@ -640,7 +705,7 @@ export class ImRuntime {
|
|
|
640
705
|
return { messageId: result.message?.id ?? '' };
|
|
641
706
|
}
|
|
642
707
|
finally {
|
|
643
|
-
|
|
708
|
+
this.#release(lease);
|
|
644
709
|
}
|
|
645
710
|
}
|
|
646
711
|
/** Activity-feedback: add a message reaction when the live Endpoint supports it. */
|
|
@@ -678,7 +743,7 @@ export class ImRuntime {
|
|
|
678
743
|
return control ? await run(control) : fallback;
|
|
679
744
|
}
|
|
680
745
|
finally {
|
|
681
|
-
|
|
746
|
+
this.#release(lease);
|
|
682
747
|
}
|
|
683
748
|
}
|
|
684
749
|
/** Run one management operation while the Endpoint generation stays leased. */
|
|
@@ -691,13 +756,13 @@ export class ImRuntime {
|
|
|
691
756
|
return null;
|
|
692
757
|
}
|
|
693
758
|
try {
|
|
694
|
-
const endpoint = requireAdapters(lease.value).
|
|
759
|
+
const endpoint = requireAdapters(lease.value).connection(adapter, endpointKey);
|
|
695
760
|
if (!endpoint)
|
|
696
761
|
return null;
|
|
697
762
|
return await run(resolveEndpointManagement(endpoint) ?? Object.freeze({}));
|
|
698
763
|
}
|
|
699
764
|
finally {
|
|
700
|
-
|
|
765
|
+
this.#release(lease);
|
|
701
766
|
}
|
|
702
767
|
}
|
|
703
768
|
async #sendWithSnapshot(request, snapshot) {
|
|
@@ -710,11 +775,19 @@ export class ImRuntime {
|
|
|
710
775
|
catch {
|
|
711
776
|
return rejectedReceipt('outbound_payload_rejected');
|
|
712
777
|
}
|
|
778
|
+
let adapters;
|
|
779
|
+
try {
|
|
780
|
+
adapters = requireAdapters(snapshot);
|
|
781
|
+
}
|
|
782
|
+
catch (error) {
|
|
783
|
+
return receiptFromEndpointError(error);
|
|
784
|
+
}
|
|
713
785
|
const envelope = createOutboundEnvelope({
|
|
714
786
|
conversation: request.conversation,
|
|
715
787
|
requester: request.requester,
|
|
716
788
|
generation: snapshot.generation,
|
|
717
|
-
|
|
789
|
+
clientAdapter: adapters.clientAdapter(adapter),
|
|
790
|
+
}, initialPayload, () => adapters.clientById(adapter));
|
|
718
791
|
let terminalEntered = false;
|
|
719
792
|
let receipt;
|
|
720
793
|
try {
|
|
@@ -787,10 +860,18 @@ export class ImRuntime {
|
|
|
787
860
|
return receipt ?? failedReceipt('outbound_delivery_incomplete');
|
|
788
861
|
}
|
|
789
862
|
#acquire() {
|
|
863
|
+
const inherited = this.#operationSnapshot.getStore();
|
|
864
|
+
if (inherited?.active)
|
|
865
|
+
return inherited;
|
|
790
866
|
if (!this.#snapshots)
|
|
791
867
|
throw new Error('ImRuntime is not attached to a Root');
|
|
792
868
|
return this.#snapshots.acquire();
|
|
793
869
|
}
|
|
870
|
+
#release(lease) {
|
|
871
|
+
if (this.#operationSnapshot.getStore() === lease)
|
|
872
|
+
return;
|
|
873
|
+
lease.release();
|
|
874
|
+
}
|
|
794
875
|
/**
|
|
795
876
|
* interactive 回跳分发(Command dispatch 之前):action 段 / 中央 fallback
|
|
796
877
|
* 数字回跳 / 指令预填 payload → prefix 最长匹配 handler。
|
|
@@ -1113,3 +1194,11 @@ function abortError(signal, fallback) {
|
|
|
1113
1194
|
return signal.reason;
|
|
1114
1195
|
return new Error(fallback);
|
|
1115
1196
|
}
|
|
1197
|
+
function withEndpointEventPayload(source, payload) {
|
|
1198
|
+
return Object.freeze({
|
|
1199
|
+
name: source.name,
|
|
1200
|
+
payload,
|
|
1201
|
+
endpoint: source.endpoint,
|
|
1202
|
+
client: source.client,
|
|
1203
|
+
});
|
|
1204
|
+
}
|
|
@@ -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.15",
|
|
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/
|
|
82
|
-
"@zhin.js/
|
|
78
|
+
"@zhin.js/adapter": "1.2.1",
|
|
79
|
+
"@zhin.js/command": "1.0.16",
|
|
80
|
+
"@zhin.js/component": "1.0.13",
|
|
81
|
+
"@zhin.js/handler": "1.0.4",
|
|
82
|
+
"@zhin.js/database": "1.0.81",
|
|
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>;
|