@zhin.js/adapter-onebot11 1.1.18 → 1.1.20

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. package/CHANGELOG.md +46 -0
  2. package/README.md +13 -6
  3. package/adapters/onebot11/index.js +3 -26
  4. package/adapters/onebot11/index.ts +2 -32
  5. package/commands/onebot11/endpoint/definition.js +0 -2
  6. package/commands/onebot11/endpoint/definition.ts +0 -2
  7. package/lib/adapter.d.ts +20 -0
  8. package/lib/adapter.js +26 -0
  9. package/lib/client.d.ts +13 -11
  10. package/lib/client.js +35 -12
  11. package/lib/console.d.ts +1 -1
  12. package/lib/console.js +2 -5
  13. package/lib/content-port.d.ts +2 -2
  14. package/lib/content-port.js +2 -2
  15. package/lib/endpoint-management.d.ts +2 -2
  16. package/lib/endpoint-management.js +8 -8
  17. package/lib/identity.d.ts +3 -0
  18. package/lib/identity.js +32 -0
  19. package/lib/index.d.ts +3 -2
  20. package/lib/index.js +3 -2
  21. package/lib/self-id.js +1 -1
  22. package/lib/side-event-dispatch.d.ts +8 -1
  23. package/lib/side-event-dispatch.js +2 -1
  24. package/lib/ws-endpoint.d.ts +5 -12
  25. package/lib/ws-endpoint.js +75 -50
  26. package/lib/ws-transport.d.ts +18 -11
  27. package/lib/ws-transport.js +28 -56
  28. package/lib/ws-types.d.ts +0 -6
  29. package/lib/wss-endpoint.d.ts +5 -12
  30. package/lib/wss-endpoint.js +76 -53
  31. package/package.json +18 -18
  32. package/plugin.js +0 -3
  33. package/src/adapter.ts +32 -0
  34. package/src/client.ts +38 -28
  35. package/src/console.ts +2 -5
  36. package/src/content-port.ts +4 -4
  37. package/src/endpoint-management.ts +15 -12
  38. package/src/identity.ts +30 -0
  39. package/src/index.ts +4 -4
  40. package/src/self-id.ts +1 -1
  41. package/src/side-event-dispatch.ts +9 -7
  42. package/src/ws-endpoint.ts +71 -64
  43. package/src/ws-transport.ts +41 -82
  44. package/src/ws-types.ts +0 -7
  45. package/src/wss-endpoint.ts +73 -68
  46. package/lib/onebot11-runtime-state.d.ts +0 -1
  47. package/lib/onebot11-runtime-state.js +0 -6
  48. package/src/onebot11-runtime-state.ts +0 -7
package/CHANGELOG.md CHANGED
@@ -1,5 +1,51 @@
1
1
  # @zhin.js/adapter-onebot11
2
2
 
3
+ ## 1.1.20
4
+
5
+ ### Patch Changes
6
+
7
+ - Updated dependencies [5e878ba]
8
+ - @zhin.js/page@1.1.12
9
+
10
+ ## 1.1.19
11
+
12
+ ### Patch Changes
13
+
14
+ - 2c3610a: Move account lifecycle ownership into the generic Adapter base and let native Endpoints retain their SDK Client inheritance. Infer platform-specific operation Sessions from a single adapter registry while preserving command parameter, option, configuration and factory inference.
15
+
16
+ Bind message replies, management ports, login challenges and Agent cancellation to the captured account incarnation. Persist runtime account intent with encrypted, revision-checked Host storage; keep account management independent of Root process restarts. Require explicit operator confirmation before importing existing accounts, and give replacement accounts a new identity without inheriting previous Sessions.
17
+
18
+ Expose account save, start, stop, update and replacement through the existing adapter Console, with exact account ownership, truthful pending/unknown outcomes and no startup configuration or environment-file rewrites.
19
+
20
+ Complete the target migration across every adapter, the public authoring API, generators, examples and Console. This intentionally removes the old create factory, inheritable Endpoint/ClientEndpoint classes, Client descriptors and file-rewrite account management; plugin authors must use createAdapter, native Client inheritance and the single AdapterRegistry. Satori and OneBot12 require explicit platform/userId selection, and WeCom requires a separate agentId.
21
+
22
+ Verify opaque credential changes before the same configuration snapshot is committed. Drain admitted native callbacks across close/rollback, cancel target work on stop, and keep raw transport parsing, platform ACK timing and SDK native methods under their existing owners. Account metadata conceals credentials carried in URLs.
23
+
24
+ - a9f4e48: PATCH COMPATIBILITY CUTOVER: this batch intentionally changes plugin APIs. The maintainer explicitly chose patch releases with declared version boundaries. Upgrade the complete tested dependency set; patch numbering does not promise compatibility with the removed interfaces.
25
+
26
+ The first planned floors are zhin.js 1.1.19, Core 1.1.54, Adapter 1.1.26, FeatureKit 1.1.10, Plugin Runtime 1.1.18, Runtime/Isolate 1.1.16 and Agent 1.1.45. Keep old-interface plugins with the earlier locked stack until they are migrated. Adapter's independent Feature API changes from 1.0.0 to 2.0.0; official consumers declare ^2.0.0. Existing Feature API admission rejects explicitly incompatible ranges; omitted API metadata keeps its existing behavior and does not certify compatibility. Runtime engine and patch-only release gates remain unchanged.
27
+
28
+ Use the native-Client Adapter target contract, canonical FeatureKit AdapterRegistry augmentation and named Endpoint control/management requests. Route message controls from canonical message/conversation refs; retain exact source authority and propagate caller/account/explicit-Root-stop cancellation. Replace removed Agent activity feedback exports with source-bound feedback. HMR pause/resume belongs to concrete plugin instances; plugins choose accepted-work policy without changing Controller commit/rollback authority. Cooperative worker/process control cancellation does not kill an isolate or reopen retired business admission.
29
+
30
+ Provide authenticated historical-data preview, exact selected binding, transactional application, authoritative inspection and explicit resumption, including active games. Preserve before-images and journals; never replay an unconfirmed effect, infer an account from an alias, or reuse historical permission grants. Owner V2 approvals remain inactive legacy data, while new writes use V3. Rollback requires matching software, lockfile and verified data; installing old code alone cannot read a new V3 approval file. Conflicting after-images are never overwritten.
31
+
32
+ See docs/plans/adapter-operation-version-boundaries.md and the Chinese/English upgrade guide for the complete version inventory, custom-plugin changes, acceptance and recovery sequence. These code and metadata changes do not authorize merging, publication, deployment, login, production migration or removal of installed workspace patches.
33
+
34
+ - Updated dependencies [2c3610a]
35
+ - Updated dependencies [a9f4e48]
36
+ - Updated dependencies [f8505b0]
37
+ - Updated dependencies [2c3610a]
38
+ - @zhin.js/adapter@1.1.26
39
+ - @zhin.js/feature-kit@1.1.10
40
+ - @zhin.js/core@1.1.54
41
+ - @zhin.js/host-http@1.1.12
42
+ - @zhin.js/client@1.1.22
43
+ - @zhin.js/page@1.1.11
44
+ - @zhin.js/agent-feature@1.1.11
45
+ - @zhin.js/skill@1.1.11
46
+ - @zhin.js/tool@1.1.13
47
+ - @zhin.js/permission@1.1.10
48
+
3
49
  ## 1.1.18
4
50
 
5
51
  ### Patch Changes
package/README.md CHANGED
@@ -2,13 +2,15 @@
2
2
 
3
3
  Zhin.js [OneBot 11](https://github.com/botuniverse/onebot-11) 适配器(Plugin Runtime)。生产路径为正向 WebSocket 客户端(`connection: ws`);亦支持反向 WS(`connection: wss`,经 `httpHostToken`)。
4
4
 
5
+ 账号由 `Onebot11Adapter` 管理。Endpoint 直接继承实际 `OneBotV11Client`,保留原生方法与事件;框架生命周期、规范入站与发送经 `endpointSpec` 和 AdapterIndex 接入,不占用 Client 的原生 `start` / `stop` / `send` 方法。
6
+
5
7
  ## 功能特性
6
8
 
7
9
  - [OneBot 11 标准](https://github.com/botuniverse/onebot-11) 兼容(事件 + 动作)
8
10
  - 约定式 `defineAdapter` / `definePlugin`(无需 `usePlugin`)
9
11
  - **正向 WebSocket**(`connection: ws`):应用连 OneBot 实现的 WS 服务器
10
12
  - `access_token` 鉴权(Bearer + query)
11
- - 入站经 `Endpoint.emit(...)`;出站 `send({ conversation, payload })`
13
+ - 入站经 `endpointSpec.events`;出站 `send({ conversation, payload })`
12
14
 
13
15
  ## 安装
14
16
 
@@ -19,19 +21,24 @@ pnpm add @zhin.js/adapter-onebot11
19
21
  ## Plugin Runtime
20
22
 
21
23
  - `@zhin.js/adapter` — 约定式 `adapters/onebot11/index.ts`(`defineAdapter`)
22
- - `@zhin.js/core` — `Endpoint.emit(...)` 入站、`outboundMessageToken` 出站
24
+ - `@zhin.js/core` — `endpointSpec.events` 入站、`outboundMessageToken` 出站
23
25
  - `zhin.js` — `plugin.ts`(`definePlugin`)
24
26
  - 配置经插件 `schema.json` 落到顶层 `<instanceKey>`
25
27
 
26
28
  `AdapterIndex` 会把实例默认值与 `endpoints[]` 的逐项覆盖合并;协议层只接收一个已经展开的 endpoint 配置,不再读取嵌套 endpoint、旧 `type: ws_reverse` 别名或进程环境。
27
29
 
28
- 每个 Endpoint 的 `$client` 是 `@imhelper/onebot-v11` 的 `OneBotV11Client`。业务代码直接调用
30
+ Endpoint 直接继承 `@imhelper/onebot-v11` 的 `OneBotV11Client`;当前操作的 `$client` 就是该实际实例。业务代码直接调用
29
31
  `$client.call(action, params)` 和 Client 的公开平台能力;双工 WS 的 `echo` 响应由 Endpoint
30
32
  先行分流,只有事件帧进入 Client 的 `ingest()` 和公开事件流。
31
33
 
32
- 入站:`gateway.receive({ conversation, message, content, sender, metadata })`(`conversation.kind` 为 `private`/`group`,`id` 为 uid/gid)
34
+ 入站:`endpoint[endpointSpec].events.emit('message.receive', { conversation, message, content, sender, metadata })`(`conversation.kind` 为 `private`/`group`,`id` 为 uid/gid)
35
+
33
36
  出站:`send({ conversation, payload })` → WS `send_private_msg` / `send_group_msg`(payload 已由 gateway/core 渲染;无 segment-mapper)
34
37
 
38
+ ## 操作生命周期
39
+
40
+ 每个实际 Client 的请求关联、定时器与取消由同一个实例级 RPC 模块持有。停止、删除或替换账号时,先取消该实例的等待,再关闭连接;已提交但未收到结果的请求保持“结果未知”,不会重试。框架发送与内容读取还绑定各自的操作信号,取消单个操作不影响其他操作或账号。原生 SDK 方法和事件重载保持不变。
41
+
35
42
  ## 前置条件
36
43
 
37
44
  1. 启动兼容 OneBot 11 的实现,并选定正向或反向 WebSocket。
@@ -84,7 +91,7 @@ onebot11:
84
91
 
85
92
  ## 迁移说明(Plugin Runtime)
86
93
 
87
- - **notice / request / meta 侧事件**:经 the unified `Endpoint.emit(...)` ingress 归一后分发到 `handlers`;消息仍走 `outboundMessageToken`。
94
+ - **notice / request / meta 侧事件**:经统一 `endpointSpec.events` 归一后分发到 `handlers`;消息仍走 `outboundMessageToken`。
88
95
  - **群管工具暂未迁移**:旧 Adapter 经 `createSceneManagementTools` 注册踢人 / 禁言 / 群名片等成套 agent 工具;迁移后仅保留 `onebot11_set_title`,其余群管能力可通过 `$client.call()`(如 `set_group_kick`、`set_group_ban`)作为逃生舱调用。
89
96
  - **平台权限门禁**:`plugin.ts` setup 通过 generation-owned `permissionHostToken` 调用 `host.registerPlatform('onebot11', createSceneRolePlatformChecker())`,`scene_admin` / `scene_owner` 依据入站 metadata 中的 sender `role`(owner / admin)判定。
90
97
 
@@ -98,7 +105,7 @@ onebot11:
98
105
  启动后打开 Console 的「OneBot 11」页(地址 `/onebot11`),可以:
99
106
 
100
107
  - 查看运行中的连接、点「测试连接」做连通性诊断;
101
- - 增删 `plugins.onebot11.endpoints`(凭据写入 `.env`,配置里只保留 `${ENV}` 引用);
108
+ - 经所属 Adapter 增删持久化账号、启停单个 Endpoint;凭据由 Host 加密仓储保存,不改启动 YAML 或 `.env`,不重启进程;
102
109
  - 如果适配器要求登录,页面会显示 LoginAssist 的扫码 / 滑块 / 设备确认待办;
103
110
 
104
111
  读取需要 `onebot11:read`,写操作需要 `onebot11:write`;管理员 full token 不受限。页面里的「添加 endpoint」等价于原来的 `onebot11 endpoint add`。
@@ -3,11 +3,8 @@
3
3
  * Convention entry: discover `adapters/onebot11/index.ts` → defineAdapter.
4
4
  */
5
5
  import { defineAdapter } from 'zhin.js/adapter';
6
- import { httpHostToken } from '@zhin.js/host-http';
7
- import { OneBot11WsEndpoint } from "../../lib/ws-endpoint.js";
8
- import { OneBot11WssEndpoint } from "../../lib/wss-endpoint.js";
9
- import { resolveOneBot11Config, } from "../../lib/protocol.js";
10
- import { onebot11RuntimeStateToken } from "../../lib/onebot11-runtime-state.js";
6
+ import { Onebot11Adapter } from "../../lib/adapter.js";
7
+ import {} from "../../lib/protocol.js";
11
8
  export { OneBot11WsEndpoint } from "../../lib/ws-endpoint.js";
12
9
  export { OneBot11WssEndpoint } from "../../lib/wss-endpoint.js";
13
10
  export default defineAdapter({
@@ -18,25 +15,5 @@ export default defineAdapter({
18
15
  outboundMedia: ['url', 'base64'],
19
16
  interactive: 'text',
20
17
  },
21
- create(context) {
22
- const config = resolveOneBot11Config(context.config);
23
- // 注册到插件运行时状态(onebot11 endpoint list 的"运行中"数据源)
24
- context.use(onebot11RuntimeStateToken).endpoints.set(config.id, {
25
- id: config.id,
26
- mode: config.connection,
27
- });
28
- if (config.connection === 'wss') {
29
- return new OneBot11WssEndpoint({
30
- id: context.id,
31
- http: context.use(httpHostToken),
32
- config,
33
- probeLoginInfo: true,
34
- });
35
- }
36
- return new OneBot11WsEndpoint({
37
- id: context.id,
38
- config,
39
- probeLoginInfo: true,
40
- });
41
- },
18
+ createAdapter: context => new Onebot11Adapter(context),
42
19
  });
@@ -2,14 +2,10 @@
2
2
  * Convention entry: discover `adapters/onebot11/index.ts` → defineAdapter.
3
3
  */
4
4
  import { defineAdapter } from 'zhin.js/adapter';
5
- import { httpHostToken } from '@zhin.js/host-http';
6
- import { OneBot11WsEndpoint } from '../../src/ws-endpoint.js';
7
- import { OneBot11WssEndpoint } from '../../src/wss-endpoint.js';
5
+ import { Onebot11Adapter } from '../../src/adapter.js';
8
6
  import {
9
- resolveOneBot11Config,
10
7
  type OneBot11EndpointConfig,
11
8
  } from '../../src/protocol.js';
12
- import { onebot11RuntimeStateToken } from '../../src/onebot11-runtime-state.js';
13
9
 
14
10
  export { OneBot11WsEndpoint } from '../../src/ws-endpoint.js';
15
11
  export type { OneBot11WsEndpointOptions } from '../../src/ws-endpoint.js';
@@ -17,12 +13,6 @@ export { OneBot11WssEndpoint } from '../../src/wss-endpoint.js';
17
13
  export type { OneBot11WssEndpointOptions } from '../../src/wss-endpoint.js';
18
14
  export type { OneBot11WsSocket, OneBot11WsCreateOptions } from '../../src/ws-types.js';
19
15
 
20
- declare module '@zhin.js/core' {
21
- interface AdapterEndpoints {
22
- onebot11: import('../../src/ws-endpoint.js').OneBot11WsEndpoint;
23
- }
24
- }
25
-
26
16
  export default defineAdapter<OneBot11EndpointConfig>({
27
17
  capabilities: ['inbound', 'outbound'],
28
18
  operations: ['recall'],
@@ -31,25 +21,5 @@ export default defineAdapter<OneBot11EndpointConfig>({
31
21
  outboundMedia: ['url', 'base64'],
32
22
  interactive: 'text',
33
23
  },
34
- create(context) {
35
- const config = resolveOneBot11Config(context.config);
36
- // 注册到插件运行时状态(onebot11 endpoint list 的"运行中"数据源)
37
- context.use(onebot11RuntimeStateToken).endpoints.set(config.id, {
38
- id: config.id,
39
- mode: config.connection,
40
- });
41
- if (config.connection === 'wss') {
42
- return new OneBot11WssEndpoint({
43
- id: context.id,
44
- http: context.use(httpHostToken),
45
- config,
46
- probeLoginInfo: true,
47
- });
48
- }
49
- return new OneBot11WsEndpoint({
50
- id: context.id,
51
- config,
52
- probeLoginInfo: true,
53
- });
54
- },
24
+ createAdapter: context => new Onebot11Adapter(context),
55
25
  });
@@ -5,7 +5,6 @@
5
5
  */
6
6
  import { createEndpointCommands } from 'zhin.js/adapter';
7
7
  import { defineCommand } from 'zhin.js/command';
8
- import { onebot11RuntimeStateToken } from "../../../lib/onebot11-runtime-state.js";
9
8
  export const onebot11EndpointCommands = createEndpointCommands({
10
9
  adapterKey: 'onebot11',
11
10
  adapterDisplayName: 'OneBot 11',
@@ -14,7 +13,6 @@ export const onebot11EndpointCommands = createEndpointCommands({
14
13
  { key: 'path', description: 'reverse-wss 路径(connection: wss)', descriptionI18n: { en: "Reverse WebSocket path (connection: wss)" } },
15
14
  { key: 'access_token', env: true, description: 'OneBot access token' },
16
15
  ],
17
- running: (use) => use(onebot11RuntimeStateToken).endpoints.values(),
18
16
  describeEntry: (entry) => {
19
17
  if (entry.url)
20
18
  return `url: ${String(entry.url)}`;
@@ -4,7 +4,6 @@
4
4
  */
5
5
  import { createEndpointCommands } from 'zhin.js/adapter';
6
6
  import { defineCommand } from 'zhin.js/command';
7
- import { onebot11RuntimeStateToken } from '../../../src/onebot11-runtime-state.js';
8
7
 
9
8
  export const onebot11EndpointCommands = createEndpointCommands({
10
9
  adapterKey: 'onebot11',
@@ -14,7 +13,6 @@ export const onebot11EndpointCommands = createEndpointCommands({
14
13
  { key: 'path', description: 'reverse-wss 路径(connection: wss)', descriptionI18n: { en: "Reverse WebSocket path (connection: wss)" } },
15
14
  { key: 'access_token', env: true, description: 'OneBot access token' },
16
15
  ],
17
- running: (use) => use(onebot11RuntimeStateToken).endpoints.values(),
18
16
  describeEntry: (entry) => {
19
17
  if (entry.url) return `url: ${String(entry.url)}`;
20
18
  if (entry.path) return `path: ${String(entry.path)}`;
@@ -0,0 +1,20 @@
1
+ import { Adapter, type AdapterContext, type EndpointCreationContext } from 'zhin.js/adapter';
2
+ import { type OneBot11EndpointConfig } from './protocol.js';
3
+ import { OneBot11WsEndpoint } from './ws-endpoint.js';
4
+ import { OneBot11WssEndpoint } from './wss-endpoint.js';
5
+ import type { Onebot11ClientEventMap } from './client.js';
6
+ export declare class Onebot11Adapter extends Adapter<OneBot11WsEndpoint | OneBot11WssEndpoint, OneBot11EndpointConfig, Onebot11ClientEventMap> {
7
+ #private;
8
+ constructor(context: AdapterContext<OneBot11EndpointConfig>);
9
+ get configurationIdentityFields(): readonly string[];
10
+ get configurationIdentityProbeFields(): readonly string[];
11
+ get configurationUpdateFields(): readonly string[];
12
+ protected validateConfiguration(config: OneBot11EndpointConfig): void;
13
+ protected identifyConfiguration(input: OneBot11EndpointConfig, signal: AbortSignal): Promise<string | undefined>;
14
+ protected createEndpoint(input: OneBot11EndpointConfig, execution: EndpointCreationContext): OneBot11WsEndpoint | OneBot11WssEndpoint;
15
+ }
16
+ declare module '@zhin.js/feature-kit' {
17
+ interface AdapterRegistry {
18
+ readonly onebot11: Onebot11Adapter;
19
+ }
20
+ }
package/lib/adapter.js ADDED
@@ -0,0 +1,26 @@
1
+ import { Adapter } from 'zhin.js/adapter';
2
+ import { httpHostToken } from '@zhin.js/host-http';
3
+ import { resolveOneBot11Config } from './protocol.js';
4
+ import { OneBot11WsEndpoint } from './ws-endpoint.js';
5
+ import { OneBot11WssEndpoint } from './wss-endpoint.js';
6
+ import { probeOnebot11Identity } from './identity.js';
7
+ export class Onebot11Adapter extends Adapter {
8
+ #context;
9
+ constructor(context) { super(); this.#context = context; }
10
+ get configurationIdentityFields() { return ['id']; }
11
+ get configurationIdentityProbeFields() { return ['connection', 'access_token', 'url']; }
12
+ get configurationUpdateFields() {
13
+ return ['connection', 'url', 'path', 'access_token', 'reconnect_interval', 'heartbeat_interval'];
14
+ }
15
+ validateConfiguration(config) { resolveOneBot11Config(config); }
16
+ async identifyConfiguration(input, signal) {
17
+ const config = resolveOneBot11Config(input);
18
+ return config.connection === 'ws' ? probeOnebot11Identity(config, signal) : undefined;
19
+ }
20
+ createEndpoint(input, execution) {
21
+ const config = resolveOneBot11Config(input);
22
+ return config.connection === 'wss'
23
+ ? new OneBot11WssEndpoint({ id: execution.canonicalId, signal: execution.signal, http: this.#context.use(httpHostToken), config, probeLoginInfo: true })
24
+ : new OneBot11WsEndpoint({ id: execution.canonicalId, signal: execution.signal, config, probeLoginInfo: true });
25
+ }
26
+ }
package/lib/client.d.ts CHANGED
@@ -6,15 +6,17 @@ export { OneBotV11Client as Onebot11Client } from '@imhelper/onebot-v11';
6
6
  export type Onebot11ApiCall = (action: string, params?: Record<string, unknown>) => Promise<OneBotV11Response>;
7
7
  type Onebot11ClientEvents = ImHelperEventMap<number, ImHelperOneBot11Event, EventMap<number>>;
8
8
  export type Onebot11ClientEventMap = ClientEventPayloads<Onebot11ClientEvents>;
9
- export declare function createOnebot11EndpointClient(config: ResolvedOneBot11Config, request: Onebot11ApiCall): OneBotV11Client;
10
- export declare function callOnebot11Client<T = unknown>(client: OneBotV11Client, action: string, params?: Record<string, unknown>): Promise<T | undefined>;
11
- export declare function forwardOnebot11ClientEvents(client: OneBotV11Client, receive: (name: string, payload: unknown) => void): () => void;
12
- declare module '@zhin.js/feature-kit' {
13
- interface AdapterClientRegistry {
14
- readonly onebot11: {
15
- readonly client: OneBotV11Client;
16
- readonly events: Onebot11ClientEventMap;
17
- };
18
- }
9
+ export declare function onebot11ClientOptions(config: ResolvedOneBot11Config, request: Onebot11ApiCall): ConstructorParameters<typeof OneBotV11Client>[0];
10
+ export interface Onebot11ClientRequest {
11
+ readonly client: OneBotV11Client;
12
+ readonly action: string;
13
+ readonly params?: Record<string, unknown>;
19
14
  }
20
- export declare const onebot11Client: import("@zhin.js/adapter").EndpointClientToken<OneBotV11Client, ClientEventPayloads<Onebot11ClientEvents>>;
15
+ /** Native methods retain ProtocolError; framework ports preserve the underlying delivery evidence. */
16
+ export declare function callOnebot11Client<T = unknown>(request: Onebot11ClientRequest): Promise<T | undefined>;
17
+ /**
18
+ * Framework evidence follows the OB11 response envelope, including async/1 submission.
19
+ * @see https://github.com/botuniverse/onebot-11/blob/master/communication/http.md
20
+ */
21
+ export declare function readOnebot11Response<T = unknown>(response: unknown): T | undefined;
22
+ export declare function forwardOnebot11ClientEvents(client: OneBotV11Client, receive: (name: string, payload: unknown) => void): () => void;
package/lib/client.js CHANGED
@@ -1,9 +1,9 @@
1
- import { OneBotV11Client, } from '@imhelper/onebot-v11';
2
- import { EventFactory } from 'imhelper';
3
- import { defineEndpointClient, forwardEndpointClientEvents, } from 'zhin.js/adapter';
1
+ import { EndpointDeliveryError } from '@zhin.js/im-contract';
2
+ import { ProtocolError, EventFactory } from 'imhelper';
3
+ import { forwardEndpointClientEvents, } from 'zhin.js/adapter';
4
4
  export { OneBotV11Client as Onebot11Client } from '@imhelper/onebot-v11';
5
- export function createOnebot11EndpointClient(config, request) {
6
- return new OneBotV11Client({
5
+ export function onebot11ClientOptions(config, request) {
6
+ return {
7
7
  baseUrl: config.connection === 'ws'
8
8
  ? config.url.replace(/^ws(s?):/, 'http$1:')
9
9
  : 'http://localhost',
@@ -11,14 +11,38 @@ export function createOnebot11EndpointClient(config, request) {
11
11
  accessToken: config.access_token,
12
12
  receiveMode: 'manual',
13
13
  call: request,
14
- });
14
+ };
15
15
  }
16
- export async function callOnebot11Client(client, action, params) {
17
- const response = await client.call(action, params);
18
- if (response.status !== 'ok') {
19
- throw new Error(`OneBot 11 API ${action}: retcode=${response.retcode}${response.message ? ` ${response.message}` : ''}`);
16
+ /** Native methods retain ProtocolError; framework ports preserve the underlying delivery evidence. */
17
+ export async function callOnebot11Client(request) {
18
+ try {
19
+ return readOnebot11Response(await request.client.call(request.action, request.params));
20
20
  }
21
- return response.data;
21
+ catch (error) {
22
+ if (error instanceof ProtocolError) {
23
+ if (error.cause instanceof EndpointDeliveryError)
24
+ throw error.cause;
25
+ if (error.response !== undefined)
26
+ readOnebot11Response(error.response);
27
+ }
28
+ throw error;
29
+ }
30
+ }
31
+ /**
32
+ * Framework evidence follows the OB11 response envelope, including async/1 submission.
33
+ * @see https://github.com/botuniverse/onebot-11/blob/master/communication/http.md
34
+ */
35
+ export function readOnebot11Response(response) {
36
+ if (response && typeof response === 'object') {
37
+ const result = response;
38
+ if (result.status === 'ok' && result.retcode === 0)
39
+ return result.data;
40
+ if (result.status === 'failed' && Number.isSafeInteger(result.retcode) && result.retcode !== 0 && result.retcode !== 1) {
41
+ throw new EndpointDeliveryError('platform_rejected', `OneBot 11 API rejected: retcode=${result.retcode}${result.message ? ` ${result.message}` : ''}`, 'rejected');
42
+ }
43
+ }
44
+ // OB11 async/1 acknowledges submission, never the final outcome.
45
+ throw new EndpointDeliveryError('delivery_unconfirmed', 'OneBot 11 response did not confirm the action result', 'unknown');
22
46
  }
23
47
  const onebot11ClientEventNames = Object.freeze([
24
48
  ...EventFactory.getSupportedEventTypes(),
@@ -27,4 +51,3 @@ const onebot11ClientEventNames = Object.freeze([
27
51
  export function forwardOnebot11ClientEvents(client, receive) {
28
52
  return forwardEndpointClientEvents(client, onebot11ClientEventNames, receive);
29
53
  }
30
- export const onebot11Client = defineEndpointClient('onebot11');
package/lib/console.d.ts CHANGED
@@ -5,4 +5,4 @@
5
5
  */
6
6
  import { type AdapterConsoleResources } from 'zhin.js/adapter';
7
7
  import type { PluginConsoleRpc } from 'zhin.js';
8
- export declare function createOnebot11ConsoleRpc(resources: AdapterConsoleResources, getConfig: () => unknown): PluginConsoleRpc;
8
+ export declare function createOnebot11ConsoleRpc(_resources: AdapterConsoleResources, getConfig: () => unknown): PluginConsoleRpc;
package/lib/console.js CHANGED
@@ -4,13 +4,10 @@
4
4
  * 页面绑定 `pages/index`,读取 / 写入分别要求 `<adapter>:read` / `<adapter>:write`。
5
5
  */
6
6
  import { createAdapterConsoleRpc } from 'zhin.js/adapter';
7
- import { onebot11RuntimeStateToken } from './onebot11-runtime-state.js';
8
7
  import { onebot11ConsoleSpec } from './console-spec.js';
9
- export function createOnebot11ConsoleRpc(resources, getConfig) {
10
- const state = resources.use(onebot11RuntimeStateToken);
8
+ export function createOnebot11ConsoleRpc(_resources, getConfig) {
11
9
  return createAdapterConsoleRpc({
12
10
  ...onebot11ConsoleSpec,
13
- running: () => state.endpoints.values(),
14
11
  getConfig,
15
- }, resources);
12
+ });
16
13
  }
@@ -1,4 +1,4 @@
1
- import type { EndpointContentPort } from 'zhin.js/adapter';
2
- type CallApi = (action: string, params?: Record<string, unknown>) => Promise<unknown>;
1
+ import type { EndpointContentPort, PendingRpcRequest } from 'zhin.js/adapter';
2
+ type CallApi = (request: PendingRpcRequest) => Promise<unknown>;
3
3
  export declare function createOneBot11ContentPort(callApi: CallApi): EndpointContentPort;
4
4
  export {};
@@ -10,7 +10,7 @@ export function createOneBot11ContentPort(callApi) {
10
10
  : Object.freeze({ status: 'resolved', reference, value: reference.media });
11
11
  }
12
12
  if (reference.kind === 'message') {
13
- const row = await callApi('get_msg', { message_id: reference.message.id });
13
+ const row = await callApi({ action: 'get_msg', params: { message_id: reference.message.id }, signal: context.signal });
14
14
  context.signal.throwIfAborted();
15
15
  const segments = normalizeSegments(row.message ?? row.raw_message);
16
16
  const sender = row.sender;
@@ -25,7 +25,7 @@ export function createOneBot11ContentPort(callApi) {
25
25
  });
26
26
  return Object.freeze({ status: 'resolved', reference, value });
27
27
  }
28
- const raw = await callApi('get_forward_msg', { id: reference.forwardId });
28
+ const raw = await callApi({ action: 'get_forward_msg', params: { id: reference.forwardId }, signal: context.signal });
29
29
  context.signal.throwIfAborted();
30
30
  const nodes = Array.isArray(raw.messages) ? raw.messages.slice(0, context.maxEntries) : [];
31
31
  const value = Object.freeze(nodes.map((node) => {
@@ -7,9 +7,9 @@
7
7
  * - group → {group_id:number, name: group_name ?? name}
8
8
  * - 群成员列表保持 OneBot11 原生形状,仅保证数组
9
9
  */
10
- import type { EndpointManagement } from 'zhin.js/adapter';
10
+ import { type EndpointManagement, type PendingRpcRequest } from 'zhin.js/adapter';
11
11
  /** 管理面只依赖 endpoint 的 callApi(ws/wss 两种传输各自实现)。 */
12
12
  export interface OneBot11ManagementCaller {
13
- callApi(action: string, params?: Record<string, unknown>): Promise<unknown>;
13
+ callApi(request: PendingRpcRequest): Promise<unknown>;
14
14
  }
15
15
  export declare function createOneBot11EndpointManagement(endpoint: OneBot11ManagementCaller): EndpointManagement;
@@ -1,7 +1,7 @@
1
1
  export function createOneBot11EndpointManagement(endpoint) {
2
2
  return Object.freeze({
3
- async listFriends() {
4
- const data = await endpoint.callApi('get_friend_list');
3
+ async listFriends(request = {}) {
4
+ const data = await endpoint.callApi({ action: 'get_friend_list', signal: request.signal });
5
5
  return toArray(data).map((value) => {
6
6
  const friend = asRecord(value);
7
7
  return {
@@ -11,8 +11,8 @@ export function createOneBot11EndpointManagement(endpoint) {
11
11
  };
12
12
  });
13
13
  },
14
- async listGroups() {
15
- const data = await endpoint.callApi('get_group_list');
14
+ async listGroups(request = {}) {
15
+ const data = await endpoint.callApi({ action: 'get_group_list', signal: request.signal });
16
16
  return toArray(data).map((value) => {
17
17
  const group = asRecord(value);
18
18
  return {
@@ -21,10 +21,10 @@ export function createOneBot11EndpointManagement(endpoint) {
21
21
  };
22
22
  });
23
23
  },
24
- async listGroupMembers(groupId) {
25
- const data = await endpoint.callApi('get_group_member_list', {
26
- group_id: toNumberId(groupId, 'group_id'),
27
- });
24
+ async listGroupMembers({ groupId, signal }) {
25
+ const data = await endpoint.callApi({ action: 'get_group_member_list', signal, params: {
26
+ group_id: toNumberId(groupId, 'group_id'),
27
+ } });
28
28
  return toArray(data);
29
29
  },
30
30
  });
@@ -0,0 +1,3 @@
1
+ import { type OneBot11WsConfig } from './protocol.js';
2
+ /** Separate read-only connection: never changes credentials or state of the running Endpoint. */
3
+ export declare function probeOnebot11Identity(config: OneBot11WsConfig, signal: AbortSignal): Promise<string | undefined>;
@@ -0,0 +1,32 @@
1
+ import WebSocket from 'ws';
2
+ import { buildWsConnectOptions } from './protocol.js';
3
+ import { createOneBot11Rpc } from './ws-transport.js';
4
+ import { resolveOnebot11SelfId } from './self-id.js';
5
+ /** Separate read-only connection: never changes credentials or state of the running Endpoint. */
6
+ export async function probeOnebot11Identity(config, signal) {
7
+ signal.throwIfAborted();
8
+ const { url, headers } = buildWsConnectOptions(config);
9
+ const socket = new WebSocket(url, { headers });
10
+ const rpc = createOneBot11Rpc({ endpointId: config.id, signal, socket: () => socket, });
11
+ let rejectOpen = () => undefined;
12
+ const abort = () => { rejectOpen(signal.reason); rpc.disconnect(); socket.terminate(); };
13
+ signal.addEventListener('abort', abort, { once: true });
14
+ socket.on('message', data => rpc.receive(data, () => undefined));
15
+ socket.on('close', () => { rejectOpen(new Error('Identity connection closed')); rpc.disconnect(); });
16
+ try {
17
+ await new Promise((resolve, reject) => { rejectOpen = reject; socket.once('open', resolve); socket.on('error', reject); });
18
+ signal.throwIfAborted();
19
+ const response = await rpc.call({ action: 'get_login_info' });
20
+ signal.throwIfAborted();
21
+ if (response.status !== 'ok' || response.retcode !== 0)
22
+ throw new Error('OneBot11 identity lookup failed');
23
+ const data = response.data;
24
+ const id = resolveOnebot11SelfId(data && typeof data === 'object' && 'user_id' in data ? data.user_id : undefined);
25
+ return id === undefined ? undefined : `qq:${id}`;
26
+ }
27
+ finally {
28
+ signal.removeEventListener('abort', abort);
29
+ rpc.dispose();
30
+ socket.terminate();
31
+ }
32
+ }
package/lib/index.d.ts CHANGED
@@ -2,9 +2,10 @@ export { buildSendAction, buildWsConnectOptions, extractQuoteId, formatInboundCo
2
2
  export { OneBot11WsEndpoint, type OneBot11WsEndpointOptions, } from './ws-endpoint.js';
3
3
  export { OneBot11WssEndpoint, type OneBot11WssEndpointOptions, } from './wss-endpoint.js';
4
4
  export type { OneBot11WsSocket, OneBot11WsCreateOptions } from './ws-types.js';
5
- export { callOneBot11WsAction, decodeWsPayload, handleOneBot11WsMessage, rejectAllPending, } from './ws-transport.js';
5
+ export { createOneBot11Rpc, type OneBot11Rpc, type OneBot11RpcOptions, decodeWsPayload, } from './ws-transport.js';
6
6
  export { verifyOneBotAccessToken } from './wss-auth.js';
7
- export { Onebot11Client, onebot11Client, type Onebot11ClientEventMap, } from './client.js';
7
+ export { Onebot11Client, type Onebot11ClientEventMap, } from './client.js';
8
8
  export type { OneBotV11ActionUrlResolver, OneBotV11AdapterConfig as ImHelperOneBotV11AdapterConfig, OneBotV11Call, OneBotV11ClientConfig, OneBotV11Event as ImHelperOneBotV11Event, OneBotV11Response, } from '@imhelper/onebot-v11';
9
9
  export { ProtocolError } from '@imhelper/onebot-v11';
10
10
  export type { ProtocolErrorKind, ProtocolErrorOptions } from 'imhelper';
11
+ export { Onebot11Adapter } from './adapter.js';
package/lib/index.js CHANGED
@@ -1,7 +1,8 @@
1
1
  export { buildSendAction, buildWsConnectOptions, extractQuoteId, formatInboundContent, formatInboundMetadata, formatOutboundSegments, getChannelId, isMessageEvent, isOneBot11BotMentioned, mediaRefToOneBotFile, onebot11InboundConversation, resolveOneBot11Config, senderDisplayName, senderNickname, senderUserId, } from './protocol.js';
2
2
  export { OneBot11WsEndpoint, } from './ws-endpoint.js';
3
3
  export { OneBot11WssEndpoint, } from './wss-endpoint.js';
4
- export { callOneBot11WsAction, decodeWsPayload, handleOneBot11WsMessage, rejectAllPending, } from './ws-transport.js';
4
+ export { createOneBot11Rpc, decodeWsPayload, } from './ws-transport.js';
5
5
  export { verifyOneBotAccessToken } from './wss-auth.js';
6
- export { Onebot11Client, onebot11Client, } from './client.js';
6
+ export { Onebot11Client, } from './client.js';
7
7
  export { ProtocolError } from '@imhelper/onebot-v11';
8
+ export { Onebot11Adapter } from './adapter.js';
package/lib/self-id.js CHANGED
@@ -15,7 +15,7 @@ export function resolveOnebot11SelfId(value) {
15
15
  /** Best-effort `get_login_info`;失败返回 undefined 并交给调用方 debug,不抛错。 */
16
16
  export async function probeOnebot11SelfId(client, onError) {
17
17
  try {
18
- const data = await callOnebot11Client(client, 'get_login_info');
18
+ const data = await callOnebot11Client({ client, action: 'get_login_info' });
19
19
  return resolveOnebot11SelfId(data?.user_id);
20
20
  }
21
21
  catch (error) {
@@ -4,4 +4,11 @@ import type { OneBot11Event } from './protocol.js';
4
4
  export interface OneBot11SideEventCaller {
5
5
  callApi(action: string, params?: Record<string, unknown>): Promise<unknown>;
6
6
  }
7
- export declare function receiveOneBot11SideEvent(emit: EndpointEventEmitter, endpointKey: string, caller: OneBot11SideEventCaller, raw: OneBot11Event, logger: ReturnType<typeof getAdapterLogger>): void;
7
+ /** Exact instance-owned dependencies for one canonical side-event projection. */
8
+ export interface OneBot11SideEventContext {
9
+ readonly emit: EndpointEventEmitter;
10
+ readonly endpointKey: string;
11
+ readonly caller: OneBot11SideEventCaller;
12
+ readonly logger: ReturnType<typeof getAdapterLogger>;
13
+ }
14
+ export declare function receiveOneBot11SideEvent(raw: OneBot11Event, context: OneBot11SideEventContext): void;
@@ -1,6 +1,7 @@
1
1
  import { receiveOneBotLikeSideEvent } from '@zhin.js/core';
2
2
  import { formatCompact } from '@zhin.js/logger';
3
- export function receiveOneBot11SideEvent(emit, endpointKey, caller, raw, logger) {
3
+ export function receiveOneBot11SideEvent(raw, context) {
4
+ const { emit, endpointKey, caller, logger } = context;
4
5
  if (!emit)
5
6
  return;
6
7
  const record = raw;
@@ -1,25 +1,18 @@
1
- import { ClientEndpoint, type EndpointControl, type EndpointManagement, type EndpointSendRequest, type EndpointTransportState } from 'zhin.js/adapter';
1
+ import { endpointSpec, type Endpoint, type EndpointSpecification } from 'zhin.js/adapter';
2
2
  import type { CapabilityId } from 'zhin.js';
3
3
  import { type OneBot11WsConfig } from './protocol.js';
4
4
  import { type OneBot11WsCreateOptions, type OneBot11WsSocket } from './ws-types.js';
5
- import { type Onebot11Client } from './client.js';
5
+ import { Onebot11Client } from './client.js';
6
6
  export interface OneBot11WsEndpointOptions {
7
+ readonly signal?: AbortSignal;
7
8
  readonly id: CapabilityId;
8
9
  /** 连接后 best-effort 调用 get_login_info 上报账号(Adapter 工厂开启;默认关闭以免占用首个 echo)。 */
9
10
  readonly probeLoginInfo?: boolean;
10
11
  readonly config: OneBot11WsConfig;
11
12
  readonly createWebSocket?: (url: string, options: OneBot11WsCreateOptions) => OneBot11WsSocket;
12
13
  }
13
- export declare class OneBot11WsEndpoint extends ClientEndpoint<Onebot11Client> {
14
+ export declare class OneBot11WsEndpoint extends Onebot11Client implements Endpoint {
14
15
  #private;
15
- readonly client: Onebot11Client;
16
- readonly management: EndpointManagement;
17
- readonly control: EndpointControl;
18
- readonly content: import("@zhin.js/adapter").EndpointContentPort;
16
+ readonly [endpointSpec]: EndpointSpecification;
19
17
  constructor(options: OneBot11WsEndpointOptions);
20
- get transportState(): EndpointTransportState;
21
- start(): Promise<void>;
22
- stop(): Promise<void>;
23
- send({ conversation, payload }: EndpointSendRequest): Promise<string>;
24
- recallMessage(messageId: string): Promise<void>;
25
18
  }