@zhin.js/adapter-satori 1.1.18 → 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/CHANGELOG.md +36 -0
- package/README.md +15 -9
- package/adapters/satori/index.js +3 -23
- package/adapters/satori/index.ts +2 -23
- package/commands/satori/endpoint/definition.js +2 -2
- package/commands/satori/endpoint/definition.ts +2 -2
- package/lib/adapter.d.ts +19 -0
- package/lib/adapter.js +29 -0
- package/lib/client.d.ts +19 -11
- package/lib/client.js +16 -11
- package/lib/console-spec.js +2 -0
- package/lib/console.d.ts +1 -1
- package/lib/console.js +2 -5
- package/lib/endpoint.d.ts +15 -24
- package/lib/endpoint.js +152 -119
- package/lib/index.d.ts +3 -2
- package/lib/index.js +2 -1
- package/lib/protocol.d.ts +14 -1
- package/lib/protocol.js +18 -11
- package/package.json +15 -15
- package/plugin.js +0 -4
- package/schema.json +15 -3
- package/src/adapter.ts +32 -0
- package/src/client.ts +30 -25
- package/src/console-spec.ts +2 -0
- package/src/console.ts +2 -5
- package/src/endpoint.ts +142 -131
- package/src/index.ts +2 -1
- package/src/protocol.ts +31 -11
- package/lib/satori-runtime-state.d.ts +0 -1
- package/lib/satori-runtime-state.js +0 -6
- package/src/satori-runtime-state.ts +0 -7
package/src/protocol.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/** Satori protocol helpers. Spec: https://satori.chat/zh-CN/protocol/overview.html */
|
|
2
2
|
|
|
3
|
-
import { isMediaRef, type ConversationKind, type ConversationRef } from '@zhin.js/im-contract';
|
|
3
|
+
import { EndpointDeliveryError, isMediaRef, type ConversationKind, type ConversationRef } from '@zhin.js/im-contract';
|
|
4
4
|
import { formatCompact, getLogger } from '@zhin.js/logger';
|
|
5
5
|
|
|
6
6
|
const logger = getLogger('satori');
|
|
@@ -69,6 +69,7 @@ export interface SatoriApiOptions {
|
|
|
69
69
|
readonly platform: string;
|
|
70
70
|
readonly userId: string;
|
|
71
71
|
readonly token?: string;
|
|
72
|
+
readonly signal?: AbortSignal;
|
|
72
73
|
}
|
|
73
74
|
|
|
74
75
|
export interface SatoriWireSegment {
|
|
@@ -79,6 +80,9 @@ export interface SatoriWireSegment {
|
|
|
79
80
|
/** One endpoint config after AdapterIndex expands `plugins.<instanceKey>.endpoints`. */
|
|
80
81
|
export interface SatoriEndpointConfig {
|
|
81
82
|
readonly id: string;
|
|
83
|
+
/** Exact remote login selected by this configured Endpoint. */
|
|
84
|
+
readonly platform: string;
|
|
85
|
+
readonly userId: string;
|
|
82
86
|
readonly connection?: 'ws' | 'webhook';
|
|
83
87
|
readonly baseUrl: string;
|
|
84
88
|
readonly token?: string;
|
|
@@ -91,6 +95,8 @@ export interface ResolvedSatoriWsConfig {
|
|
|
91
95
|
readonly context: 'satori';
|
|
92
96
|
readonly connection: 'ws';
|
|
93
97
|
readonly id: string;
|
|
98
|
+
readonly platform: string;
|
|
99
|
+
readonly userId: string;
|
|
94
100
|
readonly baseUrl: string;
|
|
95
101
|
readonly token?: string;
|
|
96
102
|
readonly heartbeat_interval: number;
|
|
@@ -100,6 +106,8 @@ export interface ResolvedSatoriWebhookConfig {
|
|
|
100
106
|
readonly context: 'satori';
|
|
101
107
|
readonly connection: 'webhook';
|
|
102
108
|
readonly id: string;
|
|
109
|
+
readonly platform: string;
|
|
110
|
+
readonly userId: string;
|
|
103
111
|
readonly baseUrl: string;
|
|
104
112
|
readonly token?: string;
|
|
105
113
|
readonly path: string;
|
|
@@ -110,6 +118,8 @@ export type ResolvedSatoriConfig = ResolvedSatoriWsConfig | ResolvedSatoriWebhoo
|
|
|
110
118
|
export function resolveSatoriConfig(config: SatoriEndpointConfig): ResolvedSatoriConfig {
|
|
111
119
|
const connection = config.connection ?? 'ws';
|
|
112
120
|
const id = requiredEndpointField(config.id, 'id');
|
|
121
|
+
const platform = requiredEndpointField(config.platform, 'platform');
|
|
122
|
+
const userId = requiredEndpointField(config.userId, 'userId');
|
|
113
123
|
const baseUrl = requiredEndpointField(config.baseUrl, 'baseUrl');
|
|
114
124
|
const token = typeof config.token === 'string' && config.token.trim()
|
|
115
125
|
? config.token.trim()
|
|
@@ -121,6 +131,8 @@ export function resolveSatoriConfig(config: SatoriEndpointConfig): ResolvedSator
|
|
|
121
131
|
context: 'satori',
|
|
122
132
|
connection: 'webhook',
|
|
123
133
|
id,
|
|
134
|
+
platform,
|
|
135
|
+
userId,
|
|
124
136
|
baseUrl,
|
|
125
137
|
token,
|
|
126
138
|
path,
|
|
@@ -132,6 +144,8 @@ export function resolveSatoriConfig(config: SatoriEndpointConfig): ResolvedSator
|
|
|
132
144
|
context: 'satori',
|
|
133
145
|
connection: 'ws',
|
|
134
146
|
id,
|
|
147
|
+
platform,
|
|
148
|
+
userId,
|
|
135
149
|
baseUrl,
|
|
136
150
|
token,
|
|
137
151
|
heartbeat_interval: heartbeat,
|
|
@@ -140,7 +154,7 @@ export function resolveSatoriConfig(config: SatoriEndpointConfig): ResolvedSator
|
|
|
140
154
|
|
|
141
155
|
function requiredEndpointField(
|
|
142
156
|
value: unknown,
|
|
143
|
-
field: 'id' | 'baseUrl' | 'path',
|
|
157
|
+
field: 'id' | 'baseUrl' | 'path' | 'platform' | 'userId',
|
|
144
158
|
): string {
|
|
145
159
|
if (typeof value !== 'string' || !value.trim()) {
|
|
146
160
|
throw new TypeError(`Satori endpoint requires a non-empty ${field}`);
|
|
@@ -170,11 +184,14 @@ export function buildWsUrl(baseUrl: string, token?: string): string {
|
|
|
170
184
|
* Call Satori HTTP API: POST {baseUrl}/v1/{resource}.{method}
|
|
171
185
|
* @see https://satori.chat/en-US/protocol/api.html
|
|
172
186
|
*/
|
|
187
|
+
export interface SatoriApiRequest extends SatoriApiOptions {
|
|
188
|
+
readonly resource: string;
|
|
189
|
+
readonly method: string;
|
|
190
|
+
readonly params?: Record<string, unknown>;
|
|
191
|
+
}
|
|
192
|
+
|
|
173
193
|
export async function callSatoriApi<T = unknown>(
|
|
174
|
-
options:
|
|
175
|
-
resource: string,
|
|
176
|
-
method: string,
|
|
177
|
-
params: Record<string, unknown> = {},
|
|
194
|
+
{ resource, method, params = {}, ...options }: SatoriApiRequest,
|
|
178
195
|
): Promise<T> {
|
|
179
196
|
const { baseUrl, platform, userId, token } = options;
|
|
180
197
|
const url = `${baseUrl.replace(/\/$/, '')}/v1/${resource}.${method}`;
|
|
@@ -185,11 +202,14 @@ export async function callSatoriApi<T = unknown>(
|
|
|
185
202
|
};
|
|
186
203
|
if (token) headers.Authorization = `Bearer ${token}`;
|
|
187
204
|
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
205
|
+
if (options.signal?.aborted) throw new EndpointDeliveryError('endpoint_inactive', 'Satori request ended before submission', 'not_sent', { cause: options.signal.reason });
|
|
206
|
+
const body = JSON.stringify(params);
|
|
207
|
+
let res: Response;
|
|
208
|
+
try {
|
|
209
|
+
res = await fetch(url, { method: 'POST', headers, body, signal: options.signal });
|
|
210
|
+
} catch (cause) {
|
|
211
|
+
throw new EndpointDeliveryError('delivery_unconfirmed', 'Satori HTTP request outcome is unknown', 'unknown', { cause });
|
|
212
|
+
}
|
|
193
213
|
|
|
194
214
|
const text = await res.text();
|
|
195
215
|
if (res.status === 401) throw new Error(`Satori API 认证失败: ${text}`);
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export declare const satoriRuntimeStateToken: import("zhin.js").Token<import("@zhin.js/adapter").EndpointRuntimeState>;
|
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Satori 插件实例的运行时状态:adapter create() 注册的 endpoint 列表。
|
|
3
|
-
* 由 plugin.ts setup() provide,adapter create 与 `satori endpoint` 命令共享(同一 owner generation)。
|
|
4
|
-
*/
|
|
5
|
-
import { defineEndpointRuntimeStateToken } from 'zhin.js/adapter';
|
|
6
|
-
export const satoriRuntimeStateToken = defineEndpointRuntimeStateToken('satori');
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Satori 插件实例的运行时状态:adapter create() 注册的 endpoint 列表。
|
|
3
|
-
* 由 plugin.ts setup() provide,adapter create 与 `satori endpoint` 命令共享(同一 owner generation)。
|
|
4
|
-
*/
|
|
5
|
-
import { defineEndpointRuntimeStateToken } from 'zhin.js/adapter';
|
|
6
|
-
|
|
7
|
-
export const satoriRuntimeStateToken = defineEndpointRuntimeStateToken('satori');
|