@agentunion/fastaun-browser 0.5.8 → 0.5.10
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 +62 -0
- package/_packed_docs/CHANGELOG.md +62 -0
- package/_packed_docs/agent.md/examples//347/276/244/347/273/204-/345/274/200/345/217/221/345/233/242/351/230/237.md +21 -0
- package/_packed_docs/sdk/04-/350/277/236/346/216/245/344/270/216/350/256/244/350/257/201.md +6 -5
- package/_packed_docs/sdk/06-API/346/211/213/345/206/214.md +43 -8
- package/_packed_docs/sdk/09-group-rpc-manual.md +18 -3
- package/_packed_docs/sdk/09-message-rpc-manual.md +34 -10
- package/dist/agent-md.d.ts.map +1 -1
- package/dist/agent-md.js +24 -1
- package/dist/agent-md.js.map +1 -1
- package/dist/aid-store.d.ts.map +1 -1
- package/dist/aid-store.js +1 -3
- package/dist/aid-store.js.map +1 -1
- package/dist/auth.d.ts.map +1 -1
- package/dist/auth.js +16 -2
- package/dist/auth.js.map +1 -1
- package/dist/bundle.js +1247 -269
- package/dist/client/delivery.d.ts +30 -7
- package/dist/client/delivery.d.ts.map +1 -1
- package/dist/client/delivery.js +354 -92
- package/dist/client/delivery.js.map +1 -1
- package/dist/client/group-state.js +8 -8
- package/dist/client/group-state.js.map +1 -1
- package/dist/client/lifecycle.d.ts.map +1 -1
- package/dist/client/lifecycle.js +41 -34
- package/dist/client/lifecycle.js.map +1 -1
- package/dist/client/rpc-pipeline.d.ts +12 -0
- package/dist/client/rpc-pipeline.d.ts.map +1 -1
- package/dist/client/rpc-pipeline.js +205 -36
- package/dist/client/rpc-pipeline.js.map +1 -1
- package/dist/client/v2-e2ee.d.ts +1 -1
- package/dist/client/v2-e2ee.d.ts.map +1 -1
- package/dist/client/v2-e2ee.js +72 -18
- package/dist/client/v2-e2ee.js.map +1 -1
- package/dist/client.d.ts +0 -1
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +128 -45
- package/dist/client.js.map +1 -1
- package/dist/events.d.ts +31 -2
- package/dist/events.d.ts.map +1 -1
- package/dist/events.js +167 -7
- package/dist/events.js.map +1 -1
- package/dist/facades.d.ts.map +1 -1
- package/dist/facades.js +7 -3
- package/dist/facades.js.map +1 -1
- package/dist/register-flow.d.ts.map +1 -1
- package/dist/register-flow.js +16 -2
- package/dist/register-flow.js.map +1 -1
- package/dist/transport.d.ts +10 -1
- package/dist/transport.d.ts.map +1 -1
- package/dist/transport.js +283 -29
- package/dist/transport.js.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.d.ts.map +1 -1
- package/dist/version.js +1 -1
- package/dist/version.js.map +1 -1
- package/package.json +1 -1
- package/_packed_docs//345/217/221/345/270/203/346/212/245/345/221/212-0.5.6.md +0 -260
package/dist/transport.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { EventDispatcher } from './events.js';
|
|
2
2
|
import type { ModuleLogger } from './logger.js';
|
|
3
3
|
import { type JsonObject, type RpcMessage, type RpcParams, type RpcResult } from './types.js';
|
|
4
|
+
export declare function createTransportWebSocket(url: string): WebSocket;
|
|
4
5
|
/**
|
|
5
6
|
* JSON-RPC 2.0 传输层 — 基于浏览器原生 WebSocket。
|
|
6
7
|
*
|
|
@@ -33,6 +34,8 @@ export declare class RPCTransport {
|
|
|
33
34
|
private _metaObserver;
|
|
34
35
|
private _traceMode;
|
|
35
36
|
private _traceObserver;
|
|
37
|
+
private _actorTail;
|
|
38
|
+
private _actorBusy;
|
|
36
39
|
constructor(opts: {
|
|
37
40
|
eventDispatcher: EventDispatcher;
|
|
38
41
|
timeout?: number;
|
|
@@ -55,7 +58,7 @@ export declare class RPCTransport {
|
|
|
55
58
|
/** 设置 trace 模式:off / log / diag */
|
|
56
59
|
setTraceMode(mode: string): void;
|
|
57
60
|
/** 注册 trace observer;observer(traceInfo) 在每次 RPC/事件携带 _trace 时调用。 */
|
|
58
|
-
setTraceObserver(observer: ((traceInfo: Record<string, unknown>) => void) | null): void;
|
|
61
|
+
setTraceObserver(observer: ((traceInfo: Record<string, unknown>) => void | Promise<void>) | null): void;
|
|
59
62
|
/** 获取连接时收到的 challenge */
|
|
60
63
|
get challenge(): RpcMessage | null;
|
|
61
64
|
/** 串行化 WebSocket 的清理与握手安装,不持有到 challenge 返回。 */
|
|
@@ -65,8 +68,10 @@ export declare class RPCTransport {
|
|
|
65
68
|
* 等待首条消息,若为 challenge 则返回,否则进入消息路由。
|
|
66
69
|
*/
|
|
67
70
|
connect(url: string): Promise<RpcMessage | null>;
|
|
71
|
+
private _connectImpl;
|
|
68
72
|
/** 关闭连接 */
|
|
69
73
|
close(): Promise<void>;
|
|
74
|
+
private _closeImpl;
|
|
70
75
|
/** 已持有连接建立串行权时关闭当前 WebSocket。 */
|
|
71
76
|
private _closeUnlocked;
|
|
72
77
|
/**
|
|
@@ -74,9 +79,13 @@ export declare class RPCTransport {
|
|
|
74
79
|
* 返回 result 字段的值;若有 error 字段则抛出映射后的错误。
|
|
75
80
|
*/
|
|
76
81
|
call(method: string, params?: RpcParams | null, timeout?: number, trace?: string, background?: boolean): Promise<RpcResult>;
|
|
82
|
+
private _callImpl;
|
|
77
83
|
/** 发送 JSON-RPC 2.0 Notification,不分配 id,也不等待响应。 */
|
|
78
84
|
notify(method: string, params?: RpcParams | null): Promise<void>;
|
|
85
|
+
private _notifyImpl;
|
|
79
86
|
private _enqueueSend;
|
|
87
|
+
private _enqueueActor;
|
|
88
|
+
private _enqueueActorStart;
|
|
80
89
|
private _sendText;
|
|
81
90
|
private _sendFailureError;
|
|
82
91
|
private _waitForCloseCodeIfClosing;
|
package/dist/transport.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"transport.d.ts","sourceRoot":"","sources":["../src/transport.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAC9C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAQhD,OAAO,EAAgB,KAAK,UAAU,EAAkB,KAAK,UAAU,EAAE,KAAK,SAAS,EAAE,KAAK,SAAS,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"transport.d.ts","sourceRoot":"","sources":["../src/transport.ts"],"names":[],"mappings":"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"}
|
package/dist/transport.js
CHANGED
|
@@ -7,6 +7,164 @@ const MAX_BACKGROUND_RPC_INFLIGHT = 8;
|
|
|
7
7
|
const _noopLog = { error: () => { }, warn: () => { }, info: () => { }, debug: () => { } };
|
|
8
8
|
/** RPC 请求递增计数器,避免 Date.now() 高并发碰撞 */
|
|
9
9
|
let _rpcIdCounter = 0;
|
|
10
|
+
const WORKER_WEBSOCKET_SOURCE = `
|
|
11
|
+
let socket = null;
|
|
12
|
+
self.onmessage = (event) => {
|
|
13
|
+
const command = event.data || {};
|
|
14
|
+
if (command.type === 'connect') {
|
|
15
|
+
try {
|
|
16
|
+
socket = new WebSocket(command.url);
|
|
17
|
+
socket.onopen = () => self.postMessage({ type: 'open' });
|
|
18
|
+
socket.onmessage = (message) => self.postMessage({ type: 'message', data: message.data });
|
|
19
|
+
socket.onerror = () => self.postMessage({ type: 'error', message: 'websocket error' });
|
|
20
|
+
socket.onclose = (close) => self.postMessage({
|
|
21
|
+
type: 'close', code: close.code, reason: close.reason || '', wasClean: close.wasClean === true,
|
|
22
|
+
});
|
|
23
|
+
} catch (error) {
|
|
24
|
+
self.postMessage({ type: 'error', message: error instanceof Error ? error.message : String(error) });
|
|
25
|
+
}
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
if (command.type === 'send') {
|
|
29
|
+
try {
|
|
30
|
+
if (!socket || socket.readyState !== WebSocket.OPEN) throw new Error('websocket is not open');
|
|
31
|
+
socket.send(command.data);
|
|
32
|
+
self.postMessage({ type: 'send_result', id: command.id, ok: true });
|
|
33
|
+
} catch (error) {
|
|
34
|
+
self.postMessage({
|
|
35
|
+
type: 'send_result', id: command.id, ok: false,
|
|
36
|
+
error: error instanceof Error ? error.message : String(error),
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
if (command.type === 'close' && socket) socket.close(command.code, command.reason);
|
|
42
|
+
};
|
|
43
|
+
`;
|
|
44
|
+
class WorkerWebSocketProxy {
|
|
45
|
+
static CONNECTING = 0;
|
|
46
|
+
static OPEN = 1;
|
|
47
|
+
static CLOSING = 2;
|
|
48
|
+
static CLOSED = 3;
|
|
49
|
+
readyState = WorkerWebSocketProxy.CONNECTING;
|
|
50
|
+
onopen = null;
|
|
51
|
+
onmessage = null;
|
|
52
|
+
onerror = null;
|
|
53
|
+
onclose = null;
|
|
54
|
+
_worker;
|
|
55
|
+
_workerUrl;
|
|
56
|
+
_listeners = new Map();
|
|
57
|
+
_pendingSends = new Map();
|
|
58
|
+
_sendSeq = 0;
|
|
59
|
+
constructor(url) {
|
|
60
|
+
this._workerUrl = URL.createObjectURL(new Blob([WORKER_WEBSOCKET_SOURCE], { type: 'text/javascript' }));
|
|
61
|
+
try {
|
|
62
|
+
this._worker = new Worker(this._workerUrl);
|
|
63
|
+
}
|
|
64
|
+
catch (error) {
|
|
65
|
+
URL.revokeObjectURL(this._workerUrl);
|
|
66
|
+
throw error;
|
|
67
|
+
}
|
|
68
|
+
this._worker.onmessage = (event) => this._handleWorkerMessage(event.data);
|
|
69
|
+
this._worker.onerror = (event) => this._emitError(event.message || 'websocket worker error');
|
|
70
|
+
this._worker.postMessage({ type: 'connect', url });
|
|
71
|
+
}
|
|
72
|
+
send(data) {
|
|
73
|
+
if (this.readyState !== WorkerWebSocketProxy.OPEN)
|
|
74
|
+
return Promise.reject(new Error('websocket is not open'));
|
|
75
|
+
const id = ++this._sendSeq;
|
|
76
|
+
return new Promise((resolve, reject) => {
|
|
77
|
+
this._pendingSends.set(id, { resolve, reject });
|
|
78
|
+
try {
|
|
79
|
+
this._worker.postMessage({ type: 'send', id, data });
|
|
80
|
+
}
|
|
81
|
+
catch (error) {
|
|
82
|
+
this._pendingSends.delete(id);
|
|
83
|
+
reject(error instanceof Error ? error : new Error(String(error)));
|
|
84
|
+
}
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
close(code, reason) {
|
|
88
|
+
if (this.readyState === WorkerWebSocketProxy.CLOSED)
|
|
89
|
+
return;
|
|
90
|
+
this.readyState = WorkerWebSocketProxy.CLOSING;
|
|
91
|
+
this._worker.postMessage({ type: 'close', code, reason });
|
|
92
|
+
}
|
|
93
|
+
addEventListener(type, listener) {
|
|
94
|
+
const callback = typeof listener === 'function' ? listener : (event) => listener.handleEvent(event);
|
|
95
|
+
const listeners = this._listeners.get(type) ?? new Set();
|
|
96
|
+
listeners.add(callback);
|
|
97
|
+
this._listeners.set(type, listeners);
|
|
98
|
+
}
|
|
99
|
+
removeEventListener(type, listener) {
|
|
100
|
+
if (typeof listener === 'function')
|
|
101
|
+
this._listeners.get(type)?.delete(listener);
|
|
102
|
+
}
|
|
103
|
+
_handleWorkerMessage(reply) {
|
|
104
|
+
if (reply.type === 'send_result' && reply.id !== undefined) {
|
|
105
|
+
const pending = this._pendingSends.get(reply.id);
|
|
106
|
+
if (!pending)
|
|
107
|
+
return;
|
|
108
|
+
this._pendingSends.delete(reply.id);
|
|
109
|
+
if (reply.ok)
|
|
110
|
+
pending.resolve();
|
|
111
|
+
else
|
|
112
|
+
pending.reject(new Error(reply.error || 'websocket send failed'));
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
115
|
+
if (reply.type === 'open') {
|
|
116
|
+
this.readyState = WorkerWebSocketProxy.OPEN;
|
|
117
|
+
const event = new Event('open');
|
|
118
|
+
this.onopen?.(event);
|
|
119
|
+
this._emit('open', event);
|
|
120
|
+
return;
|
|
121
|
+
}
|
|
122
|
+
if (reply.type === 'message') {
|
|
123
|
+
const event = new MessageEvent('message', { data: reply.data });
|
|
124
|
+
this.onmessage?.(event);
|
|
125
|
+
this._emit('message', event);
|
|
126
|
+
return;
|
|
127
|
+
}
|
|
128
|
+
if (reply.type === 'error') {
|
|
129
|
+
this._emitError(reply.message || 'websocket worker error');
|
|
130
|
+
return;
|
|
131
|
+
}
|
|
132
|
+
if (reply.type === 'close') {
|
|
133
|
+
this.readyState = WorkerWebSocketProxy.CLOSED;
|
|
134
|
+
for (const pending of this._pendingSends.values())
|
|
135
|
+
pending.reject(new Error('websocket closed'));
|
|
136
|
+
this._pendingSends.clear();
|
|
137
|
+
const event = new CloseEvent('close', {
|
|
138
|
+
code: reply.code ?? 1006, reason: reply.reason ?? '', wasClean: reply.wasClean === true,
|
|
139
|
+
});
|
|
140
|
+
this.onclose?.(event);
|
|
141
|
+
this._emit('close', event);
|
|
142
|
+
this._worker.terminate();
|
|
143
|
+
URL.revokeObjectURL(this._workerUrl);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
_emitError(message) {
|
|
147
|
+
const event = new ErrorEvent('error', { message });
|
|
148
|
+
this.onerror?.(event);
|
|
149
|
+
this._emit('error', event);
|
|
150
|
+
}
|
|
151
|
+
_emit(type, event) {
|
|
152
|
+
for (const listener of [...(this._listeners.get(type) ?? [])])
|
|
153
|
+
listener(event);
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
export function createTransportWebSocket(url) {
|
|
157
|
+
if (typeof Worker === 'function' && typeof Blob === 'function' && typeof URL !== 'undefined'
|
|
158
|
+
&& typeof URL.createObjectURL === 'function' && typeof URL.revokeObjectURL === 'function') {
|
|
159
|
+
try {
|
|
160
|
+
return new WorkerWebSocketProxy(url);
|
|
161
|
+
}
|
|
162
|
+
catch {
|
|
163
|
+
// Worker/CSP 不可用时保持原生 WebSocket 路径。
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
return new WebSocket(url);
|
|
167
|
+
}
|
|
10
168
|
// ── Trace 树状展示 ─────────────────────────────────────────────
|
|
11
169
|
const TRACE_SPAN_DETAIL_FIELDS = [
|
|
12
170
|
'method', 'route', 'namespace', 'instance_id', 'aid', 'caller_aid',
|
|
@@ -260,6 +418,10 @@ export class RPCTransport {
|
|
|
260
418
|
_traceMode = 'off';
|
|
261
419
|
// Trace observer:observer(traceInfo) 在每次 RPC/事件携带 _trace 时调用
|
|
262
420
|
_traceObserver = null;
|
|
421
|
+
// 每个 transport 实例一个轻量级网络 actor。命令只在此处启动网络操作,
|
|
422
|
+
// 不等待 RPC 响应,避免应用回调中的 send 反向占住收包路径。
|
|
423
|
+
_actorTail = Promise.resolve();
|
|
424
|
+
_actorBusy = false;
|
|
263
425
|
constructor(opts) {
|
|
264
426
|
this._dispatcher = opts.eventDispatcher;
|
|
265
427
|
this._timeout = opts.timeout ?? 10;
|
|
@@ -287,18 +449,21 @@ export class RPCTransport {
|
|
|
287
449
|
setMetaObserver(observer) {
|
|
288
450
|
this._metaObserver = observer;
|
|
289
451
|
}
|
|
290
|
-
|
|
291
|
-
|
|
452
|
+
_notifyMetaObserver(message) {
|
|
453
|
+
const observer = this._metaObserver;
|
|
454
|
+
if (observer === null)
|
|
292
455
|
return;
|
|
293
456
|
const meta = message._meta;
|
|
294
457
|
if (!isJsonObject(meta))
|
|
295
458
|
return;
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
459
|
+
this._dispatcher.enqueueTask(async () => {
|
|
460
|
+
try {
|
|
461
|
+
await observer(meta);
|
|
462
|
+
}
|
|
463
|
+
catch (exc) {
|
|
464
|
+
this._log.debug(`meta_observer raised: ${String(exc)}`);
|
|
465
|
+
}
|
|
466
|
+
});
|
|
302
467
|
}
|
|
303
468
|
/** 设置 trace 模式:off / log / diag */
|
|
304
469
|
setTraceMode(mode) {
|
|
@@ -335,7 +500,10 @@ export class RPCTransport {
|
|
|
335
500
|
* 连接到 WebSocket URL。
|
|
336
501
|
* 等待首条消息,若为 challenge 则返回,否则进入消息路由。
|
|
337
502
|
*/
|
|
338
|
-
|
|
503
|
+
connect(url) {
|
|
504
|
+
return this._enqueueActorStart(() => this._connectImpl(url));
|
|
505
|
+
}
|
|
506
|
+
async _connectImpl(url) {
|
|
339
507
|
const tStart = Date.now();
|
|
340
508
|
this._log.debug(`connect enter: url=${url}`);
|
|
341
509
|
const setup = await this._withConnectionSetup(async () => {
|
|
@@ -345,7 +513,7 @@ export class RPCTransport {
|
|
|
345
513
|
this._lastCloseCode = null;
|
|
346
514
|
this._lastCloseReason = '';
|
|
347
515
|
const handshake = new Promise((resolve, reject) => {
|
|
348
|
-
const ws =
|
|
516
|
+
const ws = createTransportWebSocket(url);
|
|
349
517
|
this._ws = ws;
|
|
350
518
|
this._closed = false;
|
|
351
519
|
let initialResolved = false;
|
|
@@ -489,7 +657,10 @@ export class RPCTransport {
|
|
|
489
657
|
return setup.handshake;
|
|
490
658
|
}
|
|
491
659
|
/** 关闭连接 */
|
|
492
|
-
|
|
660
|
+
close() {
|
|
661
|
+
return this._enqueueActor(() => this._closeImpl());
|
|
662
|
+
}
|
|
663
|
+
async _closeImpl() {
|
|
493
664
|
await this._withConnectionSetup(() => this._closeUnlocked());
|
|
494
665
|
}
|
|
495
666
|
/** 已持有连接建立串行权时关闭当前 WebSocket。 */
|
|
@@ -566,7 +737,10 @@ export class RPCTransport {
|
|
|
566
737
|
* 发起 JSON-RPC 2.0 调用。
|
|
567
738
|
* 返回 result 字段的值;若有 error 字段则抛出映射后的错误。
|
|
568
739
|
*/
|
|
569
|
-
|
|
740
|
+
call(method, params, timeout, trace, background = false) {
|
|
741
|
+
return this._enqueueActorStart(() => this._callImpl(method, params, timeout, trace, background), () => new TimeoutError(`rpc cancelled: ${method}`, { retryable: true }));
|
|
742
|
+
}
|
|
743
|
+
_callImpl(method, params, timeout, trace, background = false) {
|
|
570
744
|
if (this._closed || !this._ws) {
|
|
571
745
|
throw this._notConnectedError();
|
|
572
746
|
}
|
|
@@ -612,7 +786,7 @@ export class RPCTransport {
|
|
|
612
786
|
this._drainRpcQueue();
|
|
613
787
|
}, effectiveTimeout);
|
|
614
788
|
const pending = {
|
|
615
|
-
resolve:
|
|
789
|
+
resolve: (response) => {
|
|
616
790
|
clearTimeout(timer);
|
|
617
791
|
const elapsed = Date.now() - tStart;
|
|
618
792
|
if (response.error !== undefined) {
|
|
@@ -631,7 +805,7 @@ export class RPCTransport {
|
|
|
631
805
|
if (traceId) {
|
|
632
806
|
this._log.info(`[trace=${traceId}] rpc_recv method=${method} rpc_id=${rpcId} duration_ms=${elapsed} status=ok`);
|
|
633
807
|
}
|
|
634
|
-
|
|
808
|
+
this._notifyMetaObserver(response);
|
|
635
809
|
// 处理 success 路径的 _trace
|
|
636
810
|
const respTrace = response._trace;
|
|
637
811
|
if (respTrace && typeof respTrace === 'object' && !Array.isArray(respTrace)) {
|
|
@@ -671,7 +845,10 @@ export class RPCTransport {
|
|
|
671
845
|
return Object.assign(promise, { cancel: () => cancelRpc?.() });
|
|
672
846
|
}
|
|
673
847
|
/** 发送 JSON-RPC 2.0 Notification,不分配 id,也不等待响应。 */
|
|
674
|
-
|
|
848
|
+
notify(method, params) {
|
|
849
|
+
return this._enqueueActorStart(() => this._notifyImpl(method, params));
|
|
850
|
+
}
|
|
851
|
+
async _notifyImpl(method, params) {
|
|
675
852
|
if (this._closed || !this._ws) {
|
|
676
853
|
throw this._notConnectedError();
|
|
677
854
|
}
|
|
@@ -699,6 +876,63 @@ export class RPCTransport {
|
|
|
699
876
|
this._sendChain = run.catch(() => { });
|
|
700
877
|
return run;
|
|
701
878
|
}
|
|
879
|
+
_enqueueActor(operation) {
|
|
880
|
+
this._actorBusy = true;
|
|
881
|
+
const run = this._actorTail.then(async () => {
|
|
882
|
+
return await operation();
|
|
883
|
+
}, async () => {
|
|
884
|
+
return await operation();
|
|
885
|
+
});
|
|
886
|
+
const tail = run.then(() => undefined, () => undefined);
|
|
887
|
+
this._actorTail = tail;
|
|
888
|
+
void tail.then(() => {
|
|
889
|
+
if (this._actorTail === tail)
|
|
890
|
+
this._actorBusy = false;
|
|
891
|
+
});
|
|
892
|
+
return run;
|
|
893
|
+
}
|
|
894
|
+
_enqueueActorStart(operation, cancellationError) {
|
|
895
|
+
let resolveResult;
|
|
896
|
+
let rejectResult;
|
|
897
|
+
const result = new Promise((resolve, reject) => { resolveResult = resolve; rejectResult = reject; });
|
|
898
|
+
let cancel;
|
|
899
|
+
let cancelRequested = false;
|
|
900
|
+
const launch = () => {
|
|
901
|
+
if (cancelRequested)
|
|
902
|
+
return;
|
|
903
|
+
try {
|
|
904
|
+
const inner = operation();
|
|
905
|
+
cancel = inner.cancel;
|
|
906
|
+
inner.then(resolveResult, rejectResult);
|
|
907
|
+
}
|
|
908
|
+
catch (err) {
|
|
909
|
+
rejectResult(err);
|
|
910
|
+
}
|
|
911
|
+
};
|
|
912
|
+
if (this._actorBusy) {
|
|
913
|
+
const gate = this._actorTail.then(launch, launch);
|
|
914
|
+
const tail = gate.then(() => undefined, () => undefined);
|
|
915
|
+
this._actorTail = tail;
|
|
916
|
+
void tail.then(() => {
|
|
917
|
+
if (this._actorTail === tail)
|
|
918
|
+
this._actorBusy = false;
|
|
919
|
+
});
|
|
920
|
+
}
|
|
921
|
+
else {
|
|
922
|
+
launch();
|
|
923
|
+
}
|
|
924
|
+
return Object.assign(result, {
|
|
925
|
+
cancel: () => {
|
|
926
|
+
if (cancelRequested)
|
|
927
|
+
return;
|
|
928
|
+
cancelRequested = true;
|
|
929
|
+
if (cancel)
|
|
930
|
+
cancel();
|
|
931
|
+
else
|
|
932
|
+
rejectResult(cancellationError?.() ?? new TimeoutError('rpc cancelled', { retryable: true }));
|
|
933
|
+
},
|
|
934
|
+
});
|
|
935
|
+
}
|
|
702
936
|
_sendText(payload, context, beforeSend) {
|
|
703
937
|
return this._enqueueSend(async () => {
|
|
704
938
|
if (beforeSend && !beforeSend()) {
|
|
@@ -709,7 +943,7 @@ export class RPCTransport {
|
|
|
709
943
|
}
|
|
710
944
|
const ws = this._ws;
|
|
711
945
|
try {
|
|
712
|
-
ws.send(payload);
|
|
946
|
+
await Promise.resolve(ws.send(payload));
|
|
713
947
|
}
|
|
714
948
|
catch (err) {
|
|
715
949
|
throw await this._sendFailureError(context, err, ws);
|
|
@@ -841,7 +1075,15 @@ export class RPCTransport {
|
|
|
841
1075
|
const enriched = { ...respTrace, spans };
|
|
842
1076
|
this._log.info(traceDisplay(method, status, elapsedMs, respTrace, spans));
|
|
843
1077
|
if (this._traceObserver !== null) {
|
|
844
|
-
this._traceObserver
|
|
1078
|
+
const observer = this._traceObserver;
|
|
1079
|
+
this._dispatcher.enqueueTask(async () => {
|
|
1080
|
+
try {
|
|
1081
|
+
await observer({ type: 'rpc', method, trace: enriched, status, duration_ms: elapsedMs });
|
|
1082
|
+
}
|
|
1083
|
+
catch (err) {
|
|
1084
|
+
this._log.debug(`trace observer raised: ${err instanceof Error ? err.message : String(err)}`);
|
|
1085
|
+
}
|
|
1086
|
+
});
|
|
845
1087
|
}
|
|
846
1088
|
}
|
|
847
1089
|
catch (err) {
|
|
@@ -887,10 +1129,18 @@ export class RPCTransport {
|
|
|
887
1129
|
// 非主动关闭时触发断线回调
|
|
888
1130
|
if (!wasClosed) {
|
|
889
1131
|
const error = new ConnectionError(`websocket closed: code=${event.code} reason=${event.reason}`);
|
|
890
|
-
this._dispatcher.publish('connection.error', { error });
|
|
891
1132
|
if (this._onDisconnect) {
|
|
892
|
-
|
|
1133
|
+
const onDisconnect = this._onDisconnect;
|
|
1134
|
+
this._dispatcher.enqueueTask(async () => {
|
|
1135
|
+
try {
|
|
1136
|
+
await onDisconnect(error, event.code);
|
|
1137
|
+
}
|
|
1138
|
+
catch (exc) {
|
|
1139
|
+
this._log.warn('[aun_core.transport] disconnect callback exception:', exc);
|
|
1140
|
+
}
|
|
1141
|
+
});
|
|
893
1142
|
}
|
|
1143
|
+
this._dispatcher.enqueue('connection.error', { error });
|
|
894
1144
|
}
|
|
895
1145
|
}
|
|
896
1146
|
_notConnectedError() {
|
|
@@ -922,7 +1172,7 @@ export class RPCTransport {
|
|
|
922
1172
|
if (method === 'challenge') {
|
|
923
1173
|
this._challenge = message;
|
|
924
1174
|
this._log.debug('challenge received');
|
|
925
|
-
this._dispatcher.
|
|
1175
|
+
this._dispatcher.enqueue('connection.challenge', message.params ?? {});
|
|
926
1176
|
return;
|
|
927
1177
|
}
|
|
928
1178
|
// 事件推送
|
|
@@ -930,7 +1180,7 @@ export class RPCTransport {
|
|
|
930
1180
|
const protocolEvent = method.slice(6);
|
|
931
1181
|
const sdkEvent = EVENT_NAME_MAP[protocolEvent] ?? protocolEvent;
|
|
932
1182
|
this._log.debug(`event recv: event=${sdkEvent} ${summarizeDict(message.params, DIAG_RESULT_FIELDS)}`);
|
|
933
|
-
|
|
1183
|
+
this._notifyMetaObserver(message);
|
|
934
1184
|
// 提取事件中的 _trace 并回调 observer,然后从 params 中剥离
|
|
935
1185
|
const params = (message.params ?? {});
|
|
936
1186
|
if ('_trace' in params) {
|
|
@@ -938,10 +1188,14 @@ export class RPCTransport {
|
|
|
938
1188
|
delete params._trace;
|
|
939
1189
|
if (eventTrace && typeof eventTrace === 'object' && !Array.isArray(eventTrace)) {
|
|
940
1190
|
if (this._traceObserver !== null) {
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
1191
|
+
const observer = this._traceObserver;
|
|
1192
|
+
const tracePayload = eventTrace;
|
|
1193
|
+
this._dispatcher.enqueueTask(async () => {
|
|
1194
|
+
try {
|
|
1195
|
+
await observer({ type: 'event', event: sdkEvent, trace: tracePayload });
|
|
1196
|
+
}
|
|
1197
|
+
catch { /* observer 抛错被吞 */ }
|
|
1198
|
+
});
|
|
945
1199
|
}
|
|
946
1200
|
const traceObj = eventTrace;
|
|
947
1201
|
this._log.info(`[trace=${String(traceObj.trace_id ?? '')}] event_recv event=${sdkEvent}`);
|
|
@@ -949,16 +1203,16 @@ export class RPCTransport {
|
|
|
949
1203
|
}
|
|
950
1204
|
// 发布为 _raw.{event},由 AUNClient 处理后再发布用户可见的事件
|
|
951
1205
|
if (sdkEvent.startsWith('app.')) {
|
|
952
|
-
this._dispatcher.
|
|
1206
|
+
this._dispatcher.enqueue(sdkEvent, params);
|
|
953
1207
|
return;
|
|
954
1208
|
}
|
|
955
|
-
this._dispatcher.
|
|
1209
|
+
this._dispatcher.enqueue(`_raw.${sdkEvent}`, params);
|
|
956
1210
|
return;
|
|
957
1211
|
}
|
|
958
1212
|
// 其他通知
|
|
959
|
-
|
|
1213
|
+
this._notifyMetaObserver(message);
|
|
960
1214
|
this._log.debug(`notification recv: method=${method || '<no-method>'}`);
|
|
961
|
-
this._dispatcher.
|
|
1215
|
+
this._dispatcher.enqueue('notification', message);
|
|
962
1216
|
}
|
|
963
1217
|
_decodeMessage(raw) {
|
|
964
1218
|
if (isJsonObject(raw)) {
|