@zhin.js/core 1.5.12 → 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 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 endpointFactory Bot工厂函数或构造器
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 endpointFactory Bot工厂函数或构造器
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
- /** @alias OutboundReplySource:出站回复来源(指令 / AI */
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 {
@@ -1,10 +1,52 @@
1
1
  /** Authoring API for Handler Feature — implementation in `@zhin.js/handler`. */
2
- export { defineHandler, parseHandlerDefinition, HandlerIndex, isHandlerIndex, handlerFeatureId, handlerFeature, handlerEventFromLocalName, resolveHandlerEvent, type HandlerEventMap, type HandlerDefinition, type HandlerDescriptor, type HandlerContext, type HandlerDispatchOptions, } from '@zhin.js/handler';
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>>;
@@ -1,2 +1,26 @@
1
1
  /** Authoring API for Handler Feature — implementation in `@zhin.js/handler`. */
2
- export { defineHandler, parseHandlerDefinition, HandlerIndex, isHandlerIndex, handlerFeatureId, handlerFeature, handlerEventFromLocalName, resolveHandlerEvent, } from '@zhin.js/handler';
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
@@ -1,4 +1,5 @@
1
1
  import { isActionMessage as isActionMessageImpl } from "./built/interactive-segments/action.js";
2
+ /** @internal Legacy static helpers; not part of Agent resource authoring. */
2
3
  export var Message;
3
4
  (function (Message) {
4
5
  /**
@@ -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
- export interface MessageGateway {
87
- receive(input: IncomingMessage): Promise<MessageDispatchResult>;
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 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 MessageDispatchResult, type MessageGateway, type MessageSenderRef, type SendRequest } from './contracts.js';
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
- export declare const messageGatewayToken: import("@zhin.js/plugin-runtime").Token<MessageGateway>;
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 MessageGateway {
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
- [generationAdmissionBinder](gate: GenerationAdmissionGate): MessageGateway;
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
- receiveNotice(notice: Notice): Promise<void>;
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;
@@ -98,8 +99,14 @@ export declare class ImRuntime implements MessageGateway {
98
99
  readonly connected: boolean;
99
100
  readonly status: 'online' | 'offline';
100
101
  readonly phase: AdapterEndpointPhase;
102
+ readonly operations: readonly AdapterOperation[];
101
103
  readonly managementCapabilities: readonly EndpointManagementCapability[];
102
104
  }[];
105
+ /** Exact operation capabilities for one concrete live Endpoint. */
106
+ endpointCapabilities(input: {
107
+ readonly adapter: string;
108
+ readonly endpointKey: string;
109
+ }): EndpointCapabilities | undefined;
103
110
  /**
104
111
  * Console `GET /api/stats` 同源计数:非 root 插件节点 + AdapterIndex endpoints。
105
112
  * 供命令 / 状态卡等在 Plugin Runtime 下读取(legacy `root.adapters` / `root.children` 已不存在)。
@@ -117,6 +124,7 @@ export declare class ImRuntime implements MessageGateway {
117
124
  readonly connected: boolean;
118
125
  readonly status: 'online' | 'offline';
119
126
  readonly phase: AdapterEndpointPhase;
127
+ readonly operations: readonly AdapterOperation[];
120
128
  readonly managementCapabilities: readonly EndpointManagementCapability[];
121
129
  } | null;
122
130
  sendEndpointMessage(input: {
@@ -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, endpointControlOf, 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
- export const messageGatewayToken = createToken('zhin.im.message-gateway');
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(messageGatewayToken, this);
106
- resources.provide(sideEventGatewayToken, this.#sideEventGateway);
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
- #sideEventGateway = (() => {
128
+ /** The sole Adapter ingress, also installed as endpointEventGatewayToken. */
129
+ endpointEvents = (() => {
112
130
  const self = this;
113
131
  const gateway = {
114
- receiveNotice: (notice) => self.receiveNotice(notice),
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
- receiveNotice: async (notice) => {
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(input) {
319
- return this.#receive(input);
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', [message]);
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
- lease.release();
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
- lease.release();
447
+ this.#release(lease);
438
448
  }
439
449
  }
440
- async receiveNotice(notice) {
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('notice.receive', notice);
455
+ await this.#receiveSideEvent(withEndpointEventPayload(source, notice));
445
456
  }
446
- async receiveRequest(request) {
447
- await this.#withRequestActionScope(request, async (scoped) => {
448
- await this.#receiveSideEvent('request.receive', scoped);
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(event) {
475
- await this.#receiveSideEvent('system.receive', event);
485
+ async #receiveSystem(source) {
486
+ await this.#receiveSideEvent(source);
476
487
  }
477
- async #receiveSideEvent(event, payload) {
488
+ async #receiveSideEvent(event) {
478
489
  const lease = this.#acquire();
479
490
  try {
480
- await this.#runHandlers(lease.value, event, [payload]);
491
+ await this.#runHandlers(lease.value, event.name, [event]);
481
492
  }
482
493
  finally {
483
- lease.release();
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 payload = interactionArgs[0];
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
  }
@@ -546,17 +580,35 @@ export class ImRuntime {
546
580
  connected: row.connected,
547
581
  status: row.status,
548
582
  phase: row.phase,
583
+ operations: row.operations,
549
584
  managementCapabilities: row.managementCapabilities,
550
585
  }));
551
586
  }
552
587
  finally {
553
- lease.release();
588
+ this.#release(lease);
554
589
  }
555
590
  }
556
591
  catch {
557
592
  return Object.freeze([]);
558
593
  }
559
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
+ }
560
612
  /**
561
613
  * Console `GET /api/stats` 同源计数:非 root 插件节点 + AdapterIndex endpoints。
562
614
  * 供命令 / 状态卡等在 Plugin Runtime 下读取(legacy `root.adapters` / `root.children` 已不存在)。
@@ -577,7 +629,7 @@ export class ImRuntime {
577
629
  });
578
630
  }
579
631
  finally {
580
- lease.release();
632
+ this.#release(lease);
581
633
  }
582
634
  }
583
635
  catch {
@@ -606,11 +658,12 @@ export class ImRuntime {
606
658
  connected: row.connected,
607
659
  status: row.status,
608
660
  phase: row.phase,
661
+ operations: row.operations,
609
662
  managementCapabilities: row.managementCapabilities,
610
663
  });
611
664
  }
612
665
  finally {
613
- lease.release();
666
+ this.#release(lease);
614
667
  }
615
668
  }
616
669
  catch {
@@ -638,30 +691,30 @@ export class ImRuntime {
638
691
  return { messageId: result.message?.id ?? '' };
639
692
  }
640
693
  finally {
641
- lease.release();
694
+ this.#release(lease);
642
695
  }
643
696
  }
644
697
  /** Activity-feedback: add a message reaction when the live Endpoint supports it. */
645
698
  async addEndpointReaction(input) {
646
- return this.#withEndpointControl(input.adapter, input.endpointKey, (control) => control.addReaction?.(input.message, input.emoji, {
699
+ return this.#withEndpointControl(input.adapter, input.endpointKey, 'reaction', (control) => control.addReaction?.(input.message, input.emoji, {
647
700
  sceneType: input.sceneType,
648
701
  channelId: input.channelId,
649
702
  }) ?? null, null);
650
703
  }
651
704
  async removeEndpointReaction(input) {
652
- await this.#withEndpointControl(input.adapter, input.endpointKey, (control) => control.removeReaction?.(input.message, input.reactionId), undefined);
705
+ await this.#withEndpointControl(input.adapter, input.endpointKey, 'reaction', (control) => control.removeReaction?.(input.message, input.reactionId), undefined);
653
706
  }
654
707
  /** Activity-feedback autoRemove: recall a previously sent status message. */
655
708
  async recallEndpointMessage(input) {
656
- await this.#withEndpointControl(input.adapter, input.endpointKey, (control) => control.recall?.(input.message), undefined);
709
+ await this.#withEndpointControl(input.adapter, input.endpointKey, 'recall', (control) => control.recall?.(input.message), undefined);
657
710
  }
658
711
  async editEndpointMessage(input) {
659
- return this.#withEndpointControl(input.adapter, input.endpointKey, (control) => control.edit?.(input.message, input.content) ?? null, null);
712
+ return this.#withEndpointControl(input.adapter, input.endpointKey, 'edit', (control) => control.edit?.(input.message, input.content) ?? null, null);
660
713
  }
661
714
  async setEndpointTyping(input) {
662
- await this.#withEndpointControl(input.adapter, input.endpointKey, (control) => control.typing?.(input.conversation, input.active), undefined);
715
+ await this.#withEndpointControl(input.adapter, input.endpointKey, 'typing', (control) => control.typing?.(input.conversation, input.active), undefined);
663
716
  }
664
- async #withEndpointControl(adapter, endpointKey, run, fallback) {
717
+ async #withEndpointControl(adapter, endpointKey, operation, run, fallback) {
665
718
  let lease;
666
719
  try {
667
720
  lease = this.#acquire();
@@ -670,12 +723,13 @@ export class ImRuntime {
670
723
  return fallback;
671
724
  }
672
725
  try {
673
- const endpoint = requireAdapters(lease.value).instance(adapter, endpointKey);
674
- const control = endpointControlOf(endpoint);
726
+ const index = requireAdapters(lease.value);
727
+ const id = index.resolve(adapter, endpointKey);
728
+ const control = id ? index.control(id, operation) : undefined;
675
729
  return control ? await run(control) : fallback;
676
730
  }
677
731
  finally {
678
- lease.release();
732
+ this.#release(lease);
679
733
  }
680
734
  }
681
735
  /** Run one management operation while the Endpoint generation stays leased. */
@@ -688,13 +742,13 @@ export class ImRuntime {
688
742
  return null;
689
743
  }
690
744
  try {
691
- const endpoint = requireAdapters(lease.value).instance(adapter, endpointKey);
745
+ const endpoint = requireAdapters(lease.value).connection(adapter, endpointKey);
692
746
  if (!endpoint)
693
747
  return null;
694
748
  return await run(resolveEndpointManagement(endpoint) ?? Object.freeze({}));
695
749
  }
696
750
  finally {
697
- lease.release();
751
+ this.#release(lease);
698
752
  }
699
753
  }
700
754
  async #sendWithSnapshot(request, snapshot) {
@@ -707,11 +761,19 @@ export class ImRuntime {
707
761
  catch {
708
762
  return rejectedReceipt('outbound_payload_rejected');
709
763
  }
764
+ let adapters;
765
+ try {
766
+ adapters = requireAdapters(snapshot);
767
+ }
768
+ catch (error) {
769
+ return receiptFromEndpointError(error);
770
+ }
710
771
  const envelope = createOutboundEnvelope({
711
772
  conversation: request.conversation,
712
773
  requester: request.requester,
713
774
  generation: snapshot.generation,
714
- }, initialPayload);
775
+ clientAdapter: adapters.clientAdapter(adapter),
776
+ }, initialPayload, () => adapters.clientById(adapter));
715
777
  let terminalEntered = false;
716
778
  let receipt;
717
779
  try {
@@ -784,10 +846,18 @@ export class ImRuntime {
784
846
  return receipt ?? failedReceipt('outbound_delivery_incomplete');
785
847
  }
786
848
  #acquire() {
849
+ const inherited = this.#operationSnapshot.getStore();
850
+ if (inherited?.active)
851
+ return inherited;
787
852
  if (!this.#snapshots)
788
853
  throw new Error('ImRuntime is not attached to a Root');
789
854
  return this.#snapshots.acquire();
790
855
  }
856
+ #release(lease) {
857
+ if (this.#operationSnapshot.getStore() === lease)
858
+ return;
859
+ lease.release();
860
+ }
791
861
  /**
792
862
  * interactive 回跳分发(Command dispatch 之前):action 段 / 中央 fallback
793
863
  * 数字回跳 / 指令预填 payload → prefix 最长匹配 handler。
@@ -1110,3 +1180,11 @@ function abortError(signal, fallback) {
1110
1180
  return signal.reason;
1111
1181
  return new Error(fallback);
1112
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
+ }
@@ -7,4 +7,3 @@ export * from './message-dispatcher.js';
7
7
  export * from './outbound-renderer.js';
8
8
  export * from './outbound-segments.js';
9
9
  export * from './service-tokens.js';
10
- export * from './side-event-gateway.js';
@@ -7,4 +7,3 @@ export * from './message-dispatcher.js';
7
7
  export * from './outbound-renderer.js';
8
8
  export * from './outbound-segments.js';
9
9
  export * from './service-tokens.js';
10
- export * from './side-event-gateway.js';
@@ -1,6 +1,6 @@
1
1
  import { LoginAssist } from '../../built/login-assist.js';
2
2
  /**
3
- * Plugin Runtime login-assist port(与 messageGatewayToken / sideEventGatewayToken 并列)。
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(与 messageGatewayToken / sideEventGatewayToken 并列)。
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';
@@ -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, } from './contracts.js';
@@ -1,4 +1,4 @@
1
- import type { SideEventGateway } from '../plugin-runtime/im/side-event-gateway.js';
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 forward to SideEventGateway.
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(gateway: SideEventGateway, input: OneBotLikeSideEventInput): Promise<'notice' | 'request' | 'system' | null>;
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 forward to SideEventGateway.
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(gateway, input) {
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 gateway.receiveNotice(notice);
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 gateway.receiveRequest(request);
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 gateway.receiveSystem(system);
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
- /** @alias htmlCard */
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
- /** @alias htmlCard */
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.12",
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.1.11",
79
- "@zhin.js/command": "1.0.15",
80
- "@zhin.js/component": "1.0.12",
81
- "@zhin.js/database": "1.0.79",
82
- "@zhin.js/handler": "1.0.3",
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.7",
86
- "@zhin.js/logger": "1.0.76",
87
- "@zhin.js/middleware": "1.0.12",
88
- "@zhin.js/permission": "1.0.3",
89
- "@zhin.js/plugin-runtime": "1.1.7",
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.6"
105
+ "@zhin.js/ai": "1.5.7"
106
106
  },
107
107
  "repository": {
108
108
  "type": "git",
@@ -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
- }
@@ -1,6 +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 {};
@@ -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>;
@@ -1,2 +0,0 @@
1
- import { createToken } from '@zhin.js/plugin-runtime';
2
- export const sideEventGatewayToken = createToken('zhin.im.side-event-gateway');