@zhin.js/adapter 1.1.11 → 1.2.1

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.
@@ -0,0 +1,163 @@
1
+ import { isAdapterIndex } from './adapter-index.js';
2
+ import { Endpoint } from './endpoint.js';
3
+ import { adapterFeatureId } from './provider.js';
4
+ const endpointClientBrand = 'zhin.endpoint-client/1';
5
+ /**
6
+ * Forward one Client's public event surface through the Endpoint boundary.
7
+ * The returned disposer is useful when a Client can outlive its Endpoint.
8
+ */
9
+ export function forwardEndpointClientEvents(client, names, receive) {
10
+ const subscriptions = names.map((name) => {
11
+ const listener = (payload) => receive(name, payload);
12
+ client.on(name, listener);
13
+ return { name, listener };
14
+ });
15
+ return () => {
16
+ for (const { name, listener } of subscriptions)
17
+ client.off(name, listener);
18
+ };
19
+ }
20
+ /**
21
+ * Deep Endpoint base for SDK/protocol Clients.
22
+ *
23
+ * It owns the open admission gate and the single Client-event → Endpoint-event
24
+ * bridge. Concrete Endpoints only own account transport and raw-event
25
+ * normalization; they do not repeat dispatch plumbing.
26
+ */
27
+ export class ClientEndpoint extends Endpoint {
28
+ #clientEventsOpen = false;
29
+ #clientEventsRelease;
30
+ open() {
31
+ this.#clientEventsOpen = true;
32
+ }
33
+ close() {
34
+ this.#clientEventsOpen = false;
35
+ }
36
+ get clientEventsOpen() {
37
+ return this.#clientEventsOpen;
38
+ }
39
+ bindClientEvents(subscribe, receive, onError) {
40
+ this.#clientEventsRelease?.();
41
+ this.#clientEventsRelease = subscribe((name, payload) => {
42
+ if (!this.#clientEventsOpen)
43
+ return;
44
+ void this.emitPlatform(name, payload).catch((error) => onError?.(name, error));
45
+ try {
46
+ receive?.(name, payload);
47
+ }
48
+ catch (error) {
49
+ onError?.(name, error);
50
+ }
51
+ });
52
+ }
53
+ releaseClientEvents() {
54
+ this.#clientEventsRelease?.();
55
+ this.#clientEventsRelease = undefined;
56
+ }
57
+ }
58
+ /** Declare the native Client type exported by a platform adapter. */
59
+ export function defineEndpointClient(adapter) {
60
+ const normalized = adapter.trim();
61
+ if (!normalized)
62
+ throw new TypeError('Endpoint Client adapter cannot be empty');
63
+ const token = {
64
+ $client: endpointClientBrand,
65
+ adapter: normalized,
66
+ get(context, endpointKey) {
67
+ return resolveEndpointClient(context, token, endpointKey);
68
+ },
69
+ find(context, endpointKey) {
70
+ return findEndpointClient(context, token, endpointKey);
71
+ },
72
+ };
73
+ return Object.freeze(token);
74
+ }
75
+ /**
76
+ * Resolve a platform Client from the current generation.
77
+ *
78
+ * The returned object is valid only for the lifetime of `context`; callers
79
+ * must not retain it beyond the current command, handler, tool, task, or
80
+ * schedule operation.
81
+ */
82
+ function resolveEndpointClient(context, token, endpointKey) {
83
+ if (token.$client !== endpointClientBrand) {
84
+ throw new TypeError('Invalid Endpoint Client token');
85
+ }
86
+ const current = currentClientSource(context);
87
+ if (current && '$client' in current) {
88
+ if (endpointKey && !matchesCurrentEndpoint(current, endpointKey)) {
89
+ throw new Error(`Endpoint Client ${endpointKey} does not match the current operation Endpoint`);
90
+ }
91
+ if (current.clientAdapter && current.clientAdapter !== token.adapter) {
92
+ throw new Error(`Endpoint Client ${token.adapter} cannot access ${current.clientAdapter}`);
93
+ }
94
+ return current.$client;
95
+ }
96
+ const resolvedEndpointKey = endpointKey ?? endpointKeyFromContext(context);
97
+ if (!resolvedEndpointKey) {
98
+ throw new Error('Detached Endpoint Client access requires an explicit endpoint key');
99
+ }
100
+ if (!context.project) {
101
+ throw new Error('Endpoint Client access requires a generation operation context');
102
+ }
103
+ const projection = context.project(adapterFeatureId);
104
+ if (!isAdapterIndex(projection)) {
105
+ throw new Error('Adapter Feature projection is not installed');
106
+ }
107
+ return projection.client(token.adapter, resolvedEndpointKey);
108
+ }
109
+ function findEndpointClient(context, token, endpointKey) {
110
+ const current = currentClientSource(context);
111
+ if (current && '$client' in current) {
112
+ if (current.clientAdapter && current.clientAdapter !== token.adapter)
113
+ return undefined;
114
+ if (endpointKey && !matchesCurrentEndpoint(current, endpointKey))
115
+ return undefined;
116
+ try {
117
+ return current.$client;
118
+ }
119
+ catch {
120
+ return undefined;
121
+ }
122
+ }
123
+ const resolvedEndpointKey = endpointKey ?? endpointKeyFromContext(context);
124
+ if (!resolvedEndpointKey || !context.project)
125
+ return undefined;
126
+ const projection = context.project(adapterFeatureId);
127
+ if (!isAdapterIndex(projection))
128
+ return undefined;
129
+ return projection.findClient(token.adapter, resolvedEndpointKey);
130
+ }
131
+ function currentClientSource(context) {
132
+ for (const candidate of [context, context.message, context.input]) {
133
+ if (candidate && typeof candidate === 'object'
134
+ && ('$client' in candidate || 'clientAdapter' in candidate)) {
135
+ return candidate;
136
+ }
137
+ }
138
+ return undefined;
139
+ }
140
+ function matchesCurrentEndpoint(source, endpointKey) {
141
+ const candidates = [source.endpointId, conversationEndpointId(source.conversation)]
142
+ .filter((value) => typeof value === 'string' && value.length > 0);
143
+ return candidates.length === 0 || candidates.includes(endpointKey);
144
+ }
145
+ function endpointKeyFromContext(context) {
146
+ if (typeof context.endpoint === 'string' && context.endpoint.length > 0)
147
+ return context.endpoint;
148
+ const origin = context.origin;
149
+ if (origin?.kind === 'im' && typeof origin.endpoint === 'string' && origin.endpoint.length > 0) {
150
+ return origin.endpoint;
151
+ }
152
+ return conversationEndpointId(context.conversation)
153
+ ?? conversationEndpointId(context.input?.conversation);
154
+ }
155
+ function conversationEndpointId(value) {
156
+ if (!value || typeof value !== 'object')
157
+ return undefined;
158
+ const endpoint = value.endpoint;
159
+ if (!endpoint || typeof endpoint !== 'object')
160
+ return undefined;
161
+ const id = endpoint.id;
162
+ return typeof id === 'string' && id.length > 0 ? id : undefined;
163
+ }
@@ -2,7 +2,7 @@ import type { ConversationRef, MessageRef } from '@zhin.js/im-contract';
2
2
  /**
3
3
  * Transport-neutral control plane for a live endpoint.
4
4
  *
5
- * Sending belongs to EndpointInstance.send(). This port intentionally owns
5
+ * Sending belongs to Endpoint.send(). This port intentionally owns
6
6
  * operations that address an existing platform message, so Core never needs
7
7
  * to know a protocol's method names or identifier layout.
8
8
  */
@@ -19,9 +19,13 @@ export interface EndpointControl {
19
19
  export interface EndpointWithControl {
20
20
  readonly control?: EndpointControl;
21
21
  }
22
+ /** Bridges the common platform `recall(messageId)` shape into canonical control. */
23
+ export declare function createRecallEndpointControl(recallById: (messageId: string) => void | Promise<void>): Readonly<EndpointControl>;
22
24
  /** Reads the canonical control port without probing protocol-specific methods. */
23
25
  export declare function endpointControlOf(endpoint: unknown): EndpointControl | undefined;
24
26
  /** Checks only an Endpoint's explicit `control` port; protocol methods are never probed. */
25
27
  export declare function hasExplicitEndpointOperation(endpoint: unknown, operation: 'recall' | 'edit' | 'reaction' | 'typing'): boolean;
28
+ /** Lists the semantic operations implemented by an Endpoint's explicit control port. */
29
+ export declare function listExplicitEndpointOperations(endpoint: unknown): readonly ('recall' | 'edit' | 'reaction' | 'typing')[];
26
30
  /** Rejects a declaration that cannot be fulfilled by the explicit control port. */
27
31
  export declare function assertDeclaredEndpointOperations(endpoint: unknown, operations: readonly ('recall' | 'edit' | 'reaction' | 'typing')[] | undefined, id: string): void;
@@ -1,3 +1,9 @@
1
+ /** Bridges the common platform `recall(messageId)` shape into canonical control. */
2
+ export function createRecallEndpointControl(recallById) {
3
+ return Object.freeze({
4
+ recall: (message) => Promise.resolve(recallById(message.id)),
5
+ });
6
+ }
1
7
  /** Reads the canonical control port without probing protocol-specific methods. */
2
8
  export function endpointControlOf(endpoint) {
3
9
  if (!endpoint || typeof endpoint !== 'object')
@@ -19,6 +25,25 @@ export function hasExplicitEndpointOperation(endpoint, operation) {
19
25
  case 'typing': return typeof control.typing === 'function';
20
26
  }
21
27
  }
28
+ /** Lists the semantic operations implemented by an Endpoint's explicit control port. */
29
+ export function listExplicitEndpointOperations(endpoint) {
30
+ if (!endpoint || typeof endpoint !== 'object')
31
+ return Object.freeze([]);
32
+ const control = endpoint.control;
33
+ if (!control || typeof control !== 'object')
34
+ return Object.freeze([]);
35
+ const operations = [];
36
+ if (typeof control.recall === 'function')
37
+ operations.push('recall');
38
+ if (typeof control.edit === 'function')
39
+ operations.push('edit');
40
+ if (typeof control.addReaction === 'function'
41
+ || typeof control.removeReaction === 'function')
42
+ operations.push('reaction');
43
+ if (typeof control.typing === 'function')
44
+ operations.push('typing');
45
+ return Object.freeze(operations);
46
+ }
22
47
  /** Rejects a declaration that cannot be fulfilled by the explicit control port. */
23
48
  export function assertDeclaredEndpointOperations(endpoint, operations, id) {
24
49
  for (const operation of operations ?? []) {
@@ -26,7 +51,19 @@ export function assertDeclaredEndpointOperations(endpoint, operations, id) {
26
51
  throw new TypeError(`Adapter Endpoint ${id} declares ${operation} but control.${controlMethodName(operation)} is missing`);
27
52
  }
28
53
  }
54
+ const declared = new Set(operations ?? []);
55
+ for (const operation of listExplicitEndpointOperations(endpoint)) {
56
+ if (!declared.has(operation)) {
57
+ throw new TypeError(`Adapter Endpoint ${id} exposes control.${explicitControlMethodName(endpoint, operation)} but does not declare ${operation}`);
58
+ }
59
+ }
29
60
  }
30
61
  function controlMethodName(operation) {
31
62
  return operation === 'reaction' ? 'addReaction' : operation;
32
63
  }
64
+ function explicitControlMethodName(endpoint, operation) {
65
+ if (operation !== 'reaction')
66
+ return operation;
67
+ const control = endpoint.control;
68
+ return typeof control?.addReaction === 'function' ? 'addReaction' : 'removeReaction';
69
+ }
@@ -22,25 +22,19 @@
22
22
  * 构造器里 `this.#lifecycle = createEndpointLifecycle({ name: config.id, reconnect, heartbeat })`。
23
23
  * 2. `start()` 改为:
24
24
  * ```ts
25
- * this.#unregisterAgent = registerXxxAgentEndpoint(name, this); // agent 注册仍在适配器侧
26
- * try {
27
- * await this.#lifecycle.start(async (handle) => {
28
- * this.#handle = handle; // ws 'close' 回调引用
29
- * await new Promise<void>((resolve, reject) => {
30
- * const ws = createWebSocket(...); this.#ws = ws;
31
- * ws.on('open', () => { this.#lifecycle.startHeartbeat(() => beat(), interval); resolve(); });
32
- * ws.on('close', (code, reason) => { handle.notifyClosed(...); rejectIfNotSettled(...); });
33
- * ws.on('error', (err) => rejectIfNotSettled(err));
34
- * });
25
+ * await this.#lifecycle.start(async (handle) => {
26
+ * this.#handle = handle; // 供 ws 'close' 回调引用
27
+ * await new Promise<void>((resolve, reject) => {
28
+ * const ws = createWebSocket(...); this.#ws = ws;
29
+ * ws.on('open', () => { this.#lifecycle.startHeartbeat(() => beat(), interval); resolve(); });
30
+ * ws.on('close', (code, reason) => { handle.notifyClosed(...); rejectIfNotSettled(...); });
31
+ * ws.on('error', (err) => rejectIfNotSettled(err));
35
32
  * });
36
- * } catch (err) {
37
- * this.#unregisterAgent?.(); this.#unregisterAgent = undefined; // 反注册对称
38
- * throw err;
39
- * }
33
+ * });
40
34
  * ```
41
- * start 失败复位由基座保证;agent 注册/反注册是适配器专有依赖,刻意不收入基座。
35
+ * start 失败复位由基座保证;Client 由 Endpoint 直接持有,不建立旁路 registry。
42
36
  * 3. `stop()` 改为:先 `await this.#lifecycle.stop()`(清定时器 + 强关 ws + 竞态 settle),
43
- * 再做适配器专有清理(rejectAllPending、deduper.clear、agent 反注册)。
37
+ * 再做适配器专有清理(rejectAllPending、deduper.clear)。
44
38
  * 4. `handle.onForceClose(() => this.#ws?.close())` 在每次拿到新 socket 后注册,
45
39
  * 供心跳看门狗主动断开;ws 'message'/'pong' 回调里调 `notifyHeartbeatAck()` 喂狗。
46
40
  * 5. 退避参数由配置映射:reconnect_interval → initialIntervalMs,可按需覆盖
@@ -0,0 +1,78 @@
1
+ import { type CapabilityId, type GenerationAdmissionGate } from '@zhin.js/plugin-runtime';
2
+ import type { AdapterContext, EndpointSendRequest } from './definition.js';
3
+ import type { EndpointManagement } from './endpoint-management.js';
4
+ import type { EndpointControl } from './endpoint-control.js';
5
+ import type { EndpointContentPort } from './endpoint-content.js';
6
+ /** The one inbound event boundary shared by every platform Endpoint. */
7
+ export interface EndpointEventGateway {
8
+ receive(event: EndpointEvent): Promise<unknown>;
9
+ }
10
+ /** Callback shape used by protocol normalizers which feed Endpoint.emit(). */
11
+ export type EndpointEventEmitter = <TPayload>(name: string, payload: TPayload) => Promise<unknown>;
12
+ /** Generation-bound gateway injected into Endpoint by AdapterIndex. */
13
+ export declare const endpointEventGatewayToken: import("@zhin.js/plugin-runtime").Token<EndpointEventGateway>;
14
+ /** Stable identity of the Endpoint which produced an event. */
15
+ export interface EndpointIdentity {
16
+ readonly id: CapabilityId;
17
+ readonly adapter: string;
18
+ }
19
+ /**
20
+ * The single event context delivered from an Endpoint into Core and plugins.
21
+ * `client` is the actual platform SDK/protocol client owned by the Endpoint.
22
+ */
23
+ export interface EndpointEvent<TPayload = unknown, TClient = unknown, TName extends string = string> {
24
+ readonly name: TName;
25
+ readonly payload: TPayload;
26
+ readonly endpoint: EndpointIdentity;
27
+ readonly client: TClient;
28
+ }
29
+ /** Lossless native event delivered before any optional canonical projection. */
30
+ export interface PlatformEvent<TEvent = unknown, TName extends string = string> {
31
+ /** Native SDK/protocol event name, for example `guild_member_add`. */
32
+ readonly name: TName;
33
+ /** Native SDK/protocol payload without canonicalization. */
34
+ readonly event: TEvent;
35
+ }
36
+ declare const endpointBrand: unique symbol;
37
+ declare const endpointBind: unique symbol;
38
+ /**
39
+ * Deep platform boundary.
40
+ *
41
+ * Platform implementations inherit this class, expose the platform-native
42
+ * `client`, own account/transport lifecycle, and normalize every inbound SDK
43
+ * callback through `emit()`. Core owns dispatch, admission and plugin context.
44
+ */
45
+ export declare abstract class Endpoint<TClient = unknown> {
46
+ #private;
47
+ readonly [endpointBrand] = true;
48
+ /**
49
+ * Platform SDK or protocol client exposed to plugin code.
50
+ * It must be a distinct object: Endpoint owns framework lifecycle, Client
51
+ * owns platform operations.
52
+ */
53
+ abstract readonly client: TClient;
54
+ readonly management?: EndpointManagement;
55
+ readonly control?: EndpointControl;
56
+ readonly content?: EndpointContentPort;
57
+ /** @internal Bound exactly once by the generation-owned AdapterIndex. */
58
+ [endpointBind](context: AdapterContext, admission?: GenerationAdmissionGate): void;
59
+ /** The identity is available after AdapterDefinition.create returns. */
60
+ get identity(): EndpointIdentity;
61
+ /** The only legal platform-to-framework event ingress. */
62
+ protected emit<TPayload, TName extends string>(name: TName, payload: TPayload): Promise<unknown>;
63
+ /**
64
+ * Lossless native-event projection. Adapters call this before deriving
65
+ * message/notice/request/system events, including for unknown event kinds.
66
+ */
67
+ protected emitPlatform<TEvent, TName extends string>(name: TName, event: TEvent): Promise<unknown>;
68
+ abstract start(signal: AbortSignal): void | Promise<void>;
69
+ abstract open(): void;
70
+ abstract close(): void | Promise<void>;
71
+ abstract stop(): void | Promise<void>;
72
+ send?(_request: EndpointSendRequest): string | Promise<string>;
73
+ }
74
+ /** @internal AdapterIndex binding hook; deliberately not exported by name. */
75
+ export declare function bindEndpoint(endpoint: Endpoint, context: AdapterContext, admission?: GenerationAdmissionGate): void;
76
+ /** @internal Cross-generation Endpoint check that survives ESM module re-evaluation. */
77
+ export declare function isEndpoint(value: unknown): value is Endpoint;
78
+ export {};
@@ -0,0 +1,100 @@
1
+ import { createToken, } from '@zhin.js/plugin-runtime';
2
+ /** Generation-bound gateway injected into Endpoint by AdapterIndex. */
3
+ export const endpointEventGatewayToken = createToken('zhin.adapter.endpoint-events');
4
+ const endpointBrand = Symbol.for('zhin.adapter.endpoint/1');
5
+ const endpointBind = Symbol.for('zhin.adapter.endpoint-bind/1');
6
+ const PRE_ADMISSION_EVENT_LIMIT = 256;
7
+ /**
8
+ * Deep platform boundary.
9
+ *
10
+ * Platform implementations inherit this class, expose the platform-native
11
+ * `client`, own account/transport lifecycle, and normalize every inbound SDK
12
+ * callback through `emit()`. Core owns dispatch, admission and plugin context.
13
+ */
14
+ export class Endpoint {
15
+ [endpointBrand] = true;
16
+ management;
17
+ control;
18
+ content;
19
+ #identity;
20
+ #events;
21
+ #admissionState = 'unbound';
22
+ #pendingEvents = [];
23
+ /** @internal Bound exactly once by the generation-owned AdapterIndex. */
24
+ [endpointBind](context, admission) {
25
+ if (this.#events)
26
+ throw new Error(`Endpoint ${context.id} is already bound`);
27
+ this.#identity = Object.freeze({ id: context.id, adapter: context.name });
28
+ this.#events = context.use(endpointEventGatewayToken);
29
+ if (!admission) {
30
+ this.#admissionState = 'active';
31
+ return;
32
+ }
33
+ this.#admissionState = 'pending';
34
+ admission.onActivate(() => {
35
+ if (this.#admissionState !== 'pending')
36
+ return;
37
+ this.#admissionState = 'active';
38
+ admission.onDeactivate(() => {
39
+ this.#admissionState = 'retired';
40
+ this.#pendingEvents.length = 0;
41
+ });
42
+ const pending = this.#pendingEvents.splice(0);
43
+ for (const event of pending) {
44
+ void this.#events?.receive(event).catch(() => undefined);
45
+ }
46
+ });
47
+ }
48
+ /** The identity is available after AdapterDefinition.create returns. */
49
+ get identity() {
50
+ if (!this.#identity)
51
+ throw new Error('Endpoint is not bound to a runtime generation');
52
+ return this.#identity;
53
+ }
54
+ /** The only legal platform-to-framework event ingress. */
55
+ emit(name, payload) {
56
+ if (!this.#events || !this.#identity) {
57
+ throw new Error('Endpoint emitted before it was bound to a runtime generation');
58
+ }
59
+ const event = Object.freeze({
60
+ name,
61
+ payload,
62
+ endpoint: this.#identity,
63
+ client: this.client,
64
+ });
65
+ if (this.#admissionState === 'pending') {
66
+ if (this.#pendingEvents.length >= PRE_ADMISSION_EVENT_LIMIT) {
67
+ this.#pendingEvents.shift();
68
+ }
69
+ this.#pendingEvents.push(event);
70
+ return Promise.resolve(undefined);
71
+ }
72
+ if (this.#admissionState === 'retired')
73
+ return Promise.resolve(undefined);
74
+ return this.#events.receive(event);
75
+ }
76
+ /**
77
+ * Lossless native-event projection. Adapters call this before deriving
78
+ * message/notice/request/system events, including for unknown event kinds.
79
+ */
80
+ emitPlatform(name, event) {
81
+ return this.emit('platform.receive', Object.freeze({ name, event }));
82
+ }
83
+ }
84
+ /** @internal AdapterIndex binding hook; deliberately not exported by name. */
85
+ export function bindEndpoint(endpoint, context, admission) {
86
+ endpoint[endpointBind](context, admission);
87
+ }
88
+ /** @internal Cross-generation Endpoint check that survives ESM module re-evaluation. */
89
+ export function isEndpoint(value) {
90
+ if (!value || typeof value !== 'object')
91
+ return false;
92
+ const candidate = value;
93
+ return candidate[endpointBrand] === true
94
+ && typeof candidate[endpointBind] === 'function'
95
+ && typeof candidate.start === 'function'
96
+ && typeof candidate.open === 'function'
97
+ && typeof candidate.close === 'function'
98
+ && typeof candidate.stop === 'function'
99
+ && 'client' in candidate;
100
+ }
package/lib/index.d.ts CHANGED
@@ -1,12 +1,18 @@
1
+ /**
2
+ * Adapter authoring contracts and platform-neutral Endpoint capabilities.
3
+ * @module @zhin.js/adapter
4
+ */
1
5
  /** @internal 适配器 projection(AdapterIndex),框架内部机制,不承诺不 break。 */
2
6
  export * from './adapter-index.js';
3
7
  export * from './credentials.js';
4
8
  /** @public 用户侧创作面:`defineAdapter`(`adapters/` 约定目录默认导出,承诺 semver)。 */
5
9
  export * from './definition.js';
10
+ export * from './endpoint.js';
6
11
  export * from './endpoint-commands.js';
7
12
  export * from './endpoint-lifecycle.js';
8
13
  export * from './endpoint-management.js';
9
14
  export * from './endpoint-control.js';
10
15
  export * from './endpoint-content.js';
16
+ export * from './endpoint-client.js';
11
17
  export * from './provider.js';
12
18
  export { default } from './provider.js';
package/lib/index.js CHANGED
@@ -1,12 +1,18 @@
1
+ /**
2
+ * Adapter authoring contracts and platform-neutral Endpoint capabilities.
3
+ * @module @zhin.js/adapter
4
+ */
1
5
  /** @internal 适配器 projection(AdapterIndex),框架内部机制,不承诺不 break。 */
2
6
  export * from './adapter-index.js';
3
7
  export * from './credentials.js';
4
8
  /** @public 用户侧创作面:`defineAdapter`(`adapters/` 约定目录默认导出,承诺 semver)。 */
5
9
  export * from './definition.js';
10
+ export * from './endpoint.js';
6
11
  export * from './endpoint-commands.js';
7
12
  export * from './endpoint-lifecycle.js';
8
13
  export * from './endpoint-management.js';
9
14
  export * from './endpoint-control.js';
10
15
  export * from './endpoint-content.js';
16
+ export * from './endpoint-client.js';
11
17
  export * from './provider.js';
12
18
  export { default } from './provider.js';
package/lib/provider.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { AdapterIndex } from './adapter-index.js';
2
2
  export declare const adapterFeatureId: import("@zhin.js/plugin-runtime").FeatureId;
3
- declare const adapterFeature: Readonly<import("@zhin.js/feature-kit").FeatureProvider<import("./definition.js").AdapterDefinition<unknown>, AdapterIndex>>;
3
+ declare const adapterFeature: Readonly<import("@zhin.js/feature-kit").FeatureProvider<import("./definition.js").AdapterDefinition<unknown, unknown>, AdapterIndex>>;
4
4
  export { adapterFeature };
5
5
  export default adapterFeature;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zhin.js/adapter",
3
- "version": "1.1.11",
3
+ "version": "1.2.1",
4
4
  "description": "Convention-based Adapter and Endpoint Feature for Zhin Plugin Runtime",
5
5
  "type": "module",
6
6
  "main": "./lib/index.js",
@@ -18,15 +18,15 @@
18
18
  ],
19
19
  "dependencies": {
20
20
  "yaml": "^2.9.0",
21
+ "@zhin.js/feature-kit": "1.0.13",
21
22
  "@zhin.js/im-contract": "1.0.4",
22
- "@zhin.js/feature-kit": "1.0.12",
23
- "@zhin.js/logger": "1.0.76",
24
- "@zhin.js/plugin-runtime": "1.1.7"
23
+ "@zhin.js/logger": "1.0.77",
24
+ "@zhin.js/plugin-runtime": "1.1.8"
25
25
  },
26
26
  "devDependencies": {
27
27
  "@types/node": "^26.1.2",
28
28
  "typescript": "^6.0.3",
29
- "@zhin.js/command": "1.0.15"
29
+ "@zhin.js/command": "1.0.16"
30
30
  },
31
31
  "zhin": {
32
32
  "protocol": 1,