@zhin.js/adapter-satori 1.1.17 → 1.1.19

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zhin.js/adapter-satori",
3
- "version": "1.1.17",
3
+ "version": "1.1.19",
4
4
  "description": "Zhin.js Satori adapter for Plugin Runtime (WebSocket client)",
5
5
  "type": "module",
6
6
  "main": "./lib/index.js",
@@ -14,6 +14,7 @@
14
14
  "files": [
15
15
  "adapters",
16
16
  "commands",
17
+ "pages",
17
18
  "plugin.js",
18
19
  "schema.json",
19
20
  "src",
@@ -40,27 +41,30 @@
40
41
  "@imhelper/satori-v1": "1.0.7",
41
42
  "imhelper": "1.0.7",
42
43
  "ws": "^8.21.1",
43
- "@zhin.js/adapter": "1.1.24",
44
- "@zhin.js/core": "1.1.52",
45
- "@zhin.js/feature-kit": "1.1.9",
46
- "@zhin.js/host-http": "1.1.11",
47
- "@zhin.js/im-contract": "1.1.8",
44
+ "@zhin.js/adapter": "1.1.26",
45
+ "@zhin.js/client": "1.1.22",
46
+ "@zhin.js/console-contract": "1.1.3",
47
+ "@zhin.js/core": "1.1.54",
48
+ "@zhin.js/feature-kit": "1.1.10",
49
+ "@zhin.js/host-http": "1.1.12",
50
+ "@zhin.js/im-contract": "1.1.9",
48
51
  "@zhin.js/logger": "1.1.2",
49
- "@zhin.js/skill": "1.1.10"
52
+ "@zhin.js/page": "1.1.11",
53
+ "@zhin.js/skill": "1.1.11"
50
54
  },
51
55
  "devDependencies": {
52
56
  "@types/node": "^26.1.2",
53
57
  "@types/ws": "^8.18.1",
54
58
  "typescript": "^6.0.3",
55
59
  "vitest": "^4.1.10",
56
- "@zhin.js/host-http": "1.1.11",
57
- "zhin.js": "1.1.17"
60
+ "@zhin.js/host-http": "1.1.12",
61
+ "zhin.js": "1.1.19"
58
62
  },
59
63
  "peerDependencies": {
60
- "@zhin.js/adapter": "^1.1.24",
61
- "@zhin.js/command": "^1.1.11",
62
- "@zhin.js/core": "^1.1.52",
63
- "zhin.js": "^1.1.17"
64
+ "@zhin.js/adapter": "^1.1.26",
65
+ "@zhin.js/command": "^1.1.12",
66
+ "@zhin.js/core": "^1.1.54",
67
+ "zhin.js": "^1.1.19"
64
68
  },
65
69
  "peerDependenciesMeta": {
66
70
  "@zhin.js/command": {
@@ -91,7 +95,7 @@
91
95
  "features": [
92
96
  {
93
97
  "package": "@zhin.js/adapter",
94
- "api": "^1.0.0"
98
+ "api": "^2.0.0"
95
99
  },
96
100
  {
97
101
  "package": "@zhin.js/command",
@@ -100,6 +104,10 @@
100
104
  {
101
105
  "package": "@zhin.js/skill",
102
106
  "api": "^1.0.0"
107
+ },
108
+ {
109
+ "package": "@zhin.js/page",
110
+ "api": "^1.0.0"
103
111
  }
104
112
  ],
105
113
  "plugins": []
@@ -0,0 +1,15 @@
1
+ // Generated by build-plugin-runtime-entries.mjs. Do not edit.
2
+ import { definePage } from '@zhin.js/console-contract';
3
+ import { createAdapterConsolePage } from '@zhin.js/client';
4
+ export const meta = definePage({
5
+ title: 'Satori',
6
+ titleI18n: { en: 'Satori' },
7
+ icon: 'Sparkles',
8
+ order: 72,
9
+ requiredPermissions: ['satori:read'],
10
+ });
11
+ /**
12
+ * Convention page: `pages/index/index.ts` → `/satori`(插件路径)。
13
+ * 连接状态、连接测试、endpoint 增删;登录待办来自 LoginAssist(ICQQ 等)。
14
+ */
15
+ export default createAdapterConsolePage('satori');
@@ -0,0 +1,16 @@
1
+ import { definePage } from '@zhin.js/console-contract';
2
+ import { createAdapterConsolePage } from '@zhin.js/client';
3
+
4
+ export const meta = definePage({
5
+ title: 'Satori',
6
+ titleI18n: { en: 'Satori' },
7
+ icon: 'Sparkles',
8
+ order: 72,
9
+ requiredPermissions: ['satori:read'],
10
+ });
11
+
12
+ /**
13
+ * Convention page: `pages/index/index.ts` → `/satori`(插件路径)。
14
+ * 连接状态、连接测试、endpoint 增删;登录待办来自 LoginAssist(ICQQ 等)。
15
+ */
16
+ export default createAdapterConsolePage('satori');
package/plugin.js CHANGED
@@ -1,14 +1,12 @@
1
1
  // Generated by build-plugin-runtime-entries.mjs. Do not edit.
2
- import { createEndpointRuntimeState } from 'zhin.js/adapter';
3
- import { definePlugin } from 'zhin.js';
4
- import { satoriRuntimeStateToken } from "./lib/satori-runtime-state.js";
2
+ import { definePlugin, pluginConsoleRpcToken } from 'zhin.js';
3
+ import { createSatoriConsoleRpc } from "./lib/console.js";
5
4
  export default definePlugin({
6
5
  name: 'satori',
7
6
  metadata: {
8
7
  displayName: 'Satori Adapter',
9
8
  },
10
9
  setup(context) {
11
- // 运行中 endpoint 注册表(satori endpoint list 的"运行中"数据源)
12
- context.resources.provide(satoriRuntimeStateToken, createEndpointRuntimeState());
10
+ context.resources.provide(pluginConsoleRpcToken, createSatoriConsoleRpc(context.resources, () => context.config.get()));
13
11
  },
14
12
  });
package/schema.json CHANGED
@@ -48,7 +48,7 @@
48
48
  "endpoints": {
49
49
  "type": "array",
50
50
  "minItems": 1,
51
- "description": "多账号:每项定义一个 endpoint,id/baseUrl 必填,其余字段覆盖实例默认值",
51
+ "description": "多账号:每项明确选择 platform/userId,id/baseUrl 必填,其余字段覆盖实例默认值",
52
52
  "items": {
53
53
  "type": "object",
54
54
  "additionalProperties": false,
@@ -109,16 +109,28 @@
109
109
  "id": {
110
110
  "type": "string",
111
111
  "description": "Satori bot name"
112
+ },
113
+ "platform": {
114
+ "type": "string",
115
+ "minLength": 1,
116
+ "description": "Selected Satori login platform"
117
+ },
118
+ "userId": {
119
+ "type": "string",
120
+ "minLength": 1,
121
+ "description": "Selected Satori login user ID"
112
122
  }
113
123
  },
114
124
  "required": [
115
125
  "id",
116
- "baseUrl"
126
+ "baseUrl",
127
+ "platform",
128
+ "userId"
117
129
  ]
118
130
  },
119
131
  "x-i18n": {
120
132
  "en": {
121
- "description": "Multiple accounts: each entry defines an endpoint. id and baseUrl are required; other fields override instance defaults."
133
+ "description": "Multiple accounts: each entry selects an explicit platform and userId. id and baseUrl are required; remaining fields override instance defaults."
122
134
  }
123
135
  }
124
136
  },
package/src/adapter.ts ADDED
@@ -0,0 +1,32 @@
1
+ import { Adapter, type AdapterContext, type EndpointCreationContext } from 'zhin.js/adapter';
2
+ import { httpHostToken } from '@zhin.js/host-http';
3
+ import { callSatoriApi, resolveSatoriConfig, type SatoriEndpointConfig, type SatoriLogin } from './protocol.js';
4
+ import { SatoriWsEndpoint, SatoriWebhookEndpoint } from './endpoint.js';
5
+ import type { SatoriClientEventMap } from './client.js';
6
+
7
+ export class SatoriAdapter extends Adapter<SatoriWsEndpoint | SatoriWebhookEndpoint, SatoriEndpointConfig, SatoriClientEventMap> {
8
+ readonly #context: AdapterContext<SatoriEndpointConfig>;
9
+ constructor(context: AdapterContext<SatoriEndpointConfig>) { super(); this.#context = context; }
10
+ override get configurationIdentityFields(): readonly string[] { return ['id', 'platform', 'userId']; }
11
+ override get configurationIdentityProbeFields(): readonly string[] { return ['token', 'baseUrl']; }
12
+ override get configurationUpdateFields(): readonly string[] { return ['connection', 'baseUrl', 'token', 'path', 'heartbeat_interval']; }
13
+ protected override validateConfiguration(config: SatoriEndpointConfig): void { resolveSatoriConfig(config); }
14
+ protected override async identifyConfiguration(input: SatoriEndpointConfig, signal: AbortSignal): Promise<string> {
15
+ const config = resolveSatoriConfig(input);
16
+ signal.throwIfAborted();
17
+ const login = await callSatoriApi<SatoriLogin>({ ...config, signal, resource: 'login', method: 'get' });
18
+ signal.throwIfAborted();
19
+ if (!login?.platform || !login.user?.id) throw new Error('Satori login identity is unavailable');
20
+ if (login.platform !== config.platform || login.user.id !== config.userId) throw new Error('Satori returned another login identity');
21
+ return `satori:${JSON.stringify([login.platform, login.user.id])}`;
22
+ }
23
+ protected createEndpoint(input: SatoriEndpointConfig, execution: EndpointCreationContext): SatoriWsEndpoint | SatoriWebhookEndpoint {
24
+ const config = resolveSatoriConfig(input), id = execution.canonicalId, signal = execution.signal;
25
+ return config.connection === 'webhook'
26
+ ? new SatoriWebhookEndpoint({ id, config, signal, http: this.#context.use(httpHostToken) })
27
+ : new SatoriWsEndpoint({ id, config, signal });
28
+ }
29
+ }
30
+ declare module '@zhin.js/feature-kit' {
31
+ interface AdapterRegistry { readonly satori: SatoriAdapter; }
32
+ }
package/src/client.ts CHANGED
@@ -1,16 +1,15 @@
1
+ import { EndpointDeliveryError } from '@zhin.js/im-contract';
1
2
  import {
2
3
  SatoriV1Client,
3
4
  type SatoriV1Event,
4
5
  } from '@imhelper/satori-v1';
5
6
  import { EventFactory, type EventMap, type ImHelperEventMap } from 'imhelper';
6
7
  import {
7
- defineEndpointClient,
8
8
  forwardEndpointClientEvents,
9
9
  type ClientEventPayloads,
10
10
  } from 'zhin.js/adapter';
11
11
  import type {
12
12
  ResolvedSatoriConfig,
13
- SatoriApiOptions,
14
13
  callSatoriApi,
15
14
  } from './protocol.js';
16
15
 
@@ -19,18 +18,35 @@ export { SatoriV1Client as SatoriClient } from '@imhelper/satori-v1';
19
18
  type SatoriClientEvents = ImHelperEventMap<string, SatoriV1Event, EventMap<string>>;
20
19
  export type SatoriClientEventMap = ClientEventPayloads<SatoriClientEvents>;
21
20
 
22
- export function createSatoriEndpointClient(
23
- config: ResolvedSatoriConfig,
24
- request: typeof callSatoriApi,
25
- apiOptions: () => SatoriApiOptions,
26
- ): SatoriV1Client {
27
- return new SatoriV1Client({
28
- baseUrl: config.baseUrl,
29
- selfId: config.id,
30
- accessToken: config.token,
31
- receiveMode: 'manual',
32
- call: (resource, method, params) => request(apiOptions(), resource, method, params ?? {}),
33
- });
21
+ /** One account-bound caller is shared by native SDK and semantic ports. */
22
+ export interface SatoriActionRequest {
23
+ readonly resource: string;
24
+ readonly method: string;
25
+ readonly params?: Record<string, unknown>;
26
+ readonly signal?: AbortSignal;
27
+ }
28
+ export interface SatoriClientBinding {
29
+ readonly config: ResolvedSatoriConfig;
30
+ readonly request: typeof callSatoriApi;
31
+ readonly signal?: AbortSignal;
32
+ }
33
+ export type SatoriActionCaller = (request: SatoriActionRequest) => Promise<unknown>;
34
+ export function createSatoriActionCaller({ config, request, signal }: SatoriClientBinding): SatoriActionCaller {
35
+ return action => {
36
+ const operationSignal = signal && action.signal ? AbortSignal.any([signal, action.signal]) : signal ?? action.signal;
37
+ if (operationSignal?.aborted) throw new EndpointDeliveryError('endpoint_inactive', 'Endpoint request ended before submission', 'not_sent', { cause: operationSignal.reason });
38
+ return request({ baseUrl: config.baseUrl, platform: config.platform, userId: config.userId,
39
+ token: config.token, ...action, signal: operationSignal });
40
+ };
41
+ }
42
+ export function satoriClientOptions({ config, call }: {
43
+ readonly config: ResolvedSatoriConfig;
44
+ readonly call: SatoriActionCaller;
45
+ }): ConstructorParameters<typeof SatoriV1Client>[0] {
46
+ return { baseUrl: config.baseUrl, selfId: config.userId, platform: config.platform,
47
+ accessToken: config.token, receiveMode: 'manual',
48
+ call: (resource, method, params) => call({ resource, method, params: params ?? {} }),
49
+ };
34
50
  }
35
51
 
36
52
  const satoriClientEventNames = Object.freeze([
@@ -44,14 +60,3 @@ export function forwardSatoriClientEvents(
44
60
  ): () => void {
45
61
  return forwardEndpointClientEvents(client, satoriClientEventNames, receive);
46
62
  }
47
-
48
- declare module '@zhin.js/feature-kit' {
49
- interface AdapterClientRegistry {
50
- readonly satori: {
51
- readonly client: SatoriV1Client;
52
- readonly events: SatoriClientEventMap;
53
- };
54
- }
55
- }
56
-
57
- export const satoriClient = defineEndpointClient<SatoriV1Client, SatoriClientEventMap>('satori');
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Satori Console 页面元数据(浏览器与服务端共享;不要在这里 import 服务端代码)。
3
+ */
4
+ import type { AdapterConsoleField } from 'zhin.js/adapter';
5
+
6
+ export const satoriConsoleSpec = {
7
+ adapterKey: 'satori',
8
+ adapterDisplayName: 'Satori',
9
+ fields: [
10
+ { key: 'platform', required: true, description: 'Selected Satori login platform' },
11
+ { key: 'userId', required: true, description: 'Selected Satori login user ID' },
12
+ { key: 'baseUrl', required: true, description: 'Satori 服务 base URL', descriptionI18n: { en: 'Satori service base URL' } },
13
+ { key: 'path', description: 'webhook 路径(connection: webhook)', descriptionI18n: { en: 'Webhook path (connection: webhook)' } },
14
+ { key: 'token', env: true, description: 'Satori access token' },
15
+ ] as readonly AdapterConsoleField[],
16
+ docsUrl: 'https://zhin.js.org/adapters/satori',
17
+ readPermission: 'satori:read',
18
+ writePermission: 'satori:write',
19
+ } as const;
package/src/console.ts ADDED
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Satori Console RPC:运行状态 + endpoint 增删(原 `satori endpoint` 聊天命令)。
3
+ *
4
+ * 页面绑定 `pages/index`,读取 / 写入分别要求 `<adapter>:read` / `<adapter>:write`。
5
+ */
6
+ import { createAdapterConsoleRpc, type AdapterConsoleResources } from 'zhin.js/adapter';
7
+ import type { PluginConsoleRpc } from 'zhin.js';
8
+ import { satoriConsoleSpec } from './console-spec.js';
9
+
10
+ export function createSatoriConsoleRpc(
11
+ _resources: AdapterConsoleResources,
12
+ getConfig: () => unknown,
13
+ ): PluginConsoleRpc {
14
+ return createAdapterConsoleRpc({
15
+ ...satoriConsoleSpec,
16
+ getConfig,
17
+ });
18
+ }