@agentunion/fastaun-browser 0.5.4 → 0.5.6
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 +130 -94
- package/_packed_docs/AUN/347/246/273/347/272/277/346/216/250/351/200/201/346/216/245/345/205/245/344/270/216/346/274/224/347/244/272/346/214/207/345/215/227.md +290 -0
- package/_packed_docs/AUN/347/246/273/347/272/277/346/216/250/351/200/201/346/234/215/345/212/241/346/236/266/346/236/204/344/270/216/350/257/246/347/273/206/345/256/236/347/216/260/350/256/241/345/210/222-codex.md +994 -0
- package/_packed_docs/AUN/347/246/273/347/272/277/346/216/250/351/200/201/346/234/215/345/212/241/350/277/220/347/273/264/344/270/216/345/217/221/345/270/203/346/214/207/345/215/227.md +144 -0
- package/_packed_docs/CHANGELOG.md +130 -94
- package/_packed_docs/INDEX.md +127 -69
- package/_packed_docs/KITE_DOCS_GUIDE.md +63 -29
- package/_packed_docs/audit/AUN/346/234/215/345/212/241Go/345/214/226/351/207/215/346/236/204/347/262/276/347/273/206/345/214/226/346/272/220/347/240/201/345/256/241/346/237/245-20260718.md +366 -0
- package/_packed_docs/aun/345/205/254/347/275/221/346/265/213/350/257/225/350/277/220/350/241/214/346/214/207/345/215/227.md +227 -0
- package/_packed_docs/aun/345/210/206/345/270/203/345/274/217/346/265/213/350/257/225/350/277/220/350/241/214/346/214/207/345/215/227.md +1004 -0
- package/_packed_docs/aun/346/265/213/350/257/225/350/277/220/350/241/214/346/214/207/345/215/227.md +999 -0
- package/_packed_docs/cli/CLI/346/211/213/345/206/214.md +6 -4
- package/_packed_docs/protocol/06-/346/234/215/345/212/241/345/215/217/350/256/256.md +58 -20
- package/_packed_docs/protocol/10-Group-/345/255/220/345/215/217/350/256/256.md +219 -247
- package/_packed_docs/protocol/12-Stream-/345/255/220/345/215/217/350/256/256.md +14 -14
- package/_packed_docs/protocol/13-Agent/350/241/214/344/270/272/350/247/204/350/214/203.md +3 -3
- package/_packed_docs/protocol/15-/347/246/273/347/272/277/346/216/250/351/200/201/351/200/232/347/237/245/345/215/217/350/256/256.md +165 -421
- package/_packed_docs/protocol/README.md +1 -0
- package/_packed_docs/protocol/aun-docs-guide.md +7 -4
- package/_packed_docs/protocol/index.md +25 -19
- package/_packed_docs/sdk/02-WebSocket/345/215/217/350/256/256.md +62 -17
- package/_packed_docs/sdk/03-/346/240/270/345/277/203/346/246/202/345/277/265.md +22 -0
- package/_packed_docs/sdk/04-/350/277/236/346/216/245/344/270/216/350/256/244/350/257/201.md +67 -78
- package/_packed_docs/sdk/05-E2EE/345/212/240/345/257/206/351/200/232/344/277/241.md +6 -2
- package/_packed_docs/sdk/06-API/346/211/213/345/206/214.md +50 -14
- package/_packed_docs/sdk/08-/346/234/200/344/275/263/345/256/236/350/267/265.md +18 -5
- package/_packed_docs/sdk/09-group-rpc-manual.md +312 -282
- package/_packed_docs/sdk/09-message-rpc-manual.md +142 -103
- package/_packed_docs/sdk/09-payload-reference.md +1 -1
- package/_packed_docs/sdk/09-stream-rpc-manual.md +8 -8
- package/_packed_docs/sdk/AUN_DOCS_GUIDE.md +26 -17
- package/_packed_docs/sdk/INDEX.md +42 -34
- package/_packed_docs/sdk/README.md +7 -6
- package/_packed_docs//346/266/210/346/201/257/345/220/214/346/255/245/344/270/216/345/216/206/345/217/262/346/213/211/345/217/226/344/273/243/347/240/201/345/256/241/346/237/245/351/227/256/351/242/230/346/270/205/345/215/225.md +229 -0
- package/_packed_docs//346/266/210/346/201/257/345/220/214/346/255/245/344/270/216/345/216/206/345/217/262/346/213/211/345/217/226/346/224/271/351/200/240/346/226/271/346/241/210.md +750 -0
- package/dist/agent-md.d.ts +4 -5
- package/dist/agent-md.d.ts.map +1 -1
- package/dist/agent-md.js +66 -43
- package/dist/agent-md.js.map +1 -1
- package/dist/aid-store.d.ts +2 -6
- package/dist/aid-store.d.ts.map +1 -1
- package/dist/aid-store.js +20 -14
- package/dist/aid-store.js.map +1 -1
- package/dist/auth.d.ts.map +1 -1
- package/dist/auth.js +30 -11
- package/dist/auth.js.map +1 -1
- package/dist/bundle.js +3297 -1023
- package/dist/client/delivery.d.ts +75 -8
- package/dist/client/delivery.d.ts.map +1 -1
- package/dist/client/delivery.js +1419 -245
- package/dist/client/delivery.js.map +1 -1
- package/dist/client/group-state.d.ts.map +1 -1
- package/dist/client/group-state.js +27 -24
- package/dist/client/group-state.js.map +1 -1
- package/dist/client/lifecycle.d.ts.map +1 -1
- package/dist/client/lifecycle.js +48 -4
- package/dist/client/lifecycle.js.map +1 -1
- package/dist/client/mention-mode.d.ts +7 -0
- package/dist/client/mention-mode.d.ts.map +1 -0
- package/dist/client/mention-mode.js +184 -0
- package/dist/client/mention-mode.js.map +1 -0
- package/dist/client/peers.d.ts +1 -1
- package/dist/client/peers.d.ts.map +1 -1
- package/dist/client/peers.js +26 -3
- package/dist/client/peers.js.map +1 -1
- package/dist/client/rpc-pipeline.d.ts +22 -1
- package/dist/client/rpc-pipeline.d.ts.map +1 -1
- package/dist/client/rpc-pipeline.js +309 -74
- package/dist/client/rpc-pipeline.js.map +1 -1
- package/dist/client/v2-e2ee.d.ts +25 -2
- package/dist/client/v2-e2ee.d.ts.map +1 -1
- package/dist/client/v2-e2ee.js +606 -97
- package/dist/client/v2-e2ee.js.map +1 -1
- package/dist/client.d.ts +24 -5
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +404 -215
- package/dist/client.js.map +1 -1
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +4 -1
- package/dist/errors.js.map +1 -1
- package/dist/facades.d.ts +3 -0
- package/dist/facades.d.ts.map +1 -1
- package/dist/facades.js +91 -53
- package/dist/facades.js.map +1 -1
- package/dist/group-index.d.ts +6 -1
- package/dist/group-index.d.ts.map +1 -1
- package/dist/group-index.js +44 -25
- package/dist/group-index.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/keystore/index.d.ts +10 -5
- package/dist/keystore/index.d.ts.map +1 -1
- package/dist/keystore/indexeddb-identity-store.d.ts +0 -12
- package/dist/keystore/indexeddb-identity-store.d.ts.map +1 -1
- package/dist/keystore/indexeddb-identity-store.js +0 -60
- package/dist/keystore/indexeddb-identity-store.js.map +1 -1
- package/dist/keystore/indexeddb-shared.d.ts.map +1 -1
- package/dist/keystore/indexeddb-shared.js +9 -5
- package/dist/keystore/indexeddb-shared.js.map +1 -1
- package/dist/keystore/indexeddb-token-store.d.ts +3 -1
- package/dist/keystore/indexeddb-token-store.d.ts.map +1 -1
- package/dist/keystore/indexeddb-token-store.js +47 -2
- package/dist/keystore/indexeddb-token-store.js.map +1 -1
- package/dist/register-flow.d.ts.map +1 -1
- package/dist/register-flow.js +28 -3
- package/dist/register-flow.js.map +1 -1
- package/dist/seq-tracker.d.ts +28 -8
- package/dist/seq-tracker.d.ts.map +1 -1
- package/dist/seq-tracker.js +218 -61
- package/dist/seq-tracker.js.map +1 -1
- package/dist/storage/vfs.d.ts +1 -0
- package/dist/storage/vfs.d.ts.map +1 -1
- package/dist/storage/vfs.js +26 -2
- package/dist/storage/vfs.js.map +1 -1
- package/dist/tools/cross-sdk-agent.js +376 -10
- package/dist/tools/cross-sdk-agent.js.map +1 -1
- package/dist/transport.d.ts +12 -0
- package/dist/transport.d.ts.map +1 -1
- package/dist/transport.js +218 -101
- package/dist/transport.js.map +1 -1
- package/dist/v2/session/session.d.ts.map +1 -1
- package/dist/v2/session/session.js +3 -4
- package/dist/v2/session/session.js.map +1 -1
- package/dist/v2/state/commitment.d.ts.map +1 -1
- package/dist/v2/state/commitment.js +1 -2
- package/dist/v2/state/commitment.js.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +6 -5
- package/dist/group-resources.d.ts +0 -98
- package/dist/group-resources.d.ts.map +0 -1
- package/dist/group-resources.js +0 -635
- package/dist/group-resources.js.map +0 -1
- package/dist/keystore/indexeddb.d.ts +0 -179
- package/dist/keystore/indexeddb.d.ts.map +0 -1
- package/dist/keystore/indexeddb.js +0 -2031
- package/dist/keystore/indexeddb.js.map +0 -1
- package/dist/namespaces/auth.d.ts +0 -98
- package/dist/namespaces/auth.d.ts.map +0 -1
- package/dist/namespaces/auth.js +0 -992
- package/dist/namespaces/auth.js.map +0 -1
- package/dist/namespaces/custody.d.ts +0 -51
- package/dist/namespaces/custody.d.ts.map +0 -1
- package/dist/namespaces/custody.js +0 -302
- package/dist/namespaces/custody.js.map +0 -1
- package/dist/namespaces/meta.d.ts +0 -109
- package/dist/namespaces/meta.d.ts.map +0 -1
- package/dist/namespaces/meta.js +0 -549
- package/dist/namespaces/meta.js.map +0 -1
|
@@ -5,7 +5,7 @@ import * as https from 'node:https';
|
|
|
5
5
|
import * as crypto from 'node:crypto';
|
|
6
6
|
import * as fs from 'node:fs';
|
|
7
7
|
import { URL } from 'node:url';
|
|
8
|
-
import { AIDStore, AUNClient } from '../index.js';
|
|
8
|
+
import { AID, AIDStore, AUNClient, __version__ } from '../index.js';
|
|
9
9
|
import { publicKeyFingerprint } from '../cert-utils.js';
|
|
10
10
|
function installNodeBrowserShims() {
|
|
11
11
|
const root = globalThis;
|
|
@@ -122,7 +122,7 @@ function envelopeMetadata(data) {
|
|
|
122
122
|
}
|
|
123
123
|
class CrossSdkJsAgent {
|
|
124
124
|
language = 'js';
|
|
125
|
-
sdkVersion =
|
|
125
|
+
sdkVersion = __version__;
|
|
126
126
|
aid = textOf(process.env.AUN_TEST_AID || `cross-js-${crypto.randomUUID().slice(0, 8)}.agentid.pub`).trim();
|
|
127
127
|
issuer = textOf(process.env.AUN_TEST_ISSUER || 'agentid.pub').trim() || 'agentid.pub';
|
|
128
128
|
slotId = textOf(process.env.AUN_TEST_SLOT_ID || `cross-sdk-js-${crypto.randomUUID().slice(0, 8)}`).trim();
|
|
@@ -133,15 +133,36 @@ class CrossSdkJsAgent {
|
|
|
133
133
|
startupError = '';
|
|
134
134
|
inbox = [];
|
|
135
135
|
groupInbox = [];
|
|
136
|
+
rawPushObservations = [];
|
|
137
|
+
rawPushObservationId = '';
|
|
138
|
+
rawPushRpcMethods = [];
|
|
139
|
+
rpcObservedTransports = new WeakSet();
|
|
140
|
+
groupChangedEvents = [];
|
|
136
141
|
traces = new Map();
|
|
137
142
|
sendResults = new Map();
|
|
143
|
+
inlineRealtimePayloadV1 = true;
|
|
138
144
|
constructor() {
|
|
139
|
-
this.client =
|
|
140
|
-
|
|
145
|
+
this.client = this.newClient();
|
|
146
|
+
}
|
|
147
|
+
async start() {
|
|
148
|
+
this.bindClientEvents();
|
|
149
|
+
await this.ensureConnected(false);
|
|
150
|
+
this.ready = true;
|
|
151
|
+
}
|
|
152
|
+
newClient() {
|
|
153
|
+
const client = new AUNClient();
|
|
154
|
+
const internal = client;
|
|
141
155
|
if (internal._configModel)
|
|
142
156
|
internal._configModel.requireForwardSecrecy = false;
|
|
157
|
+
return client;
|
|
143
158
|
}
|
|
144
|
-
|
|
159
|
+
bindClientEvents() {
|
|
160
|
+
this.installTransportRpcObserver();
|
|
161
|
+
this.client.on('_raw.message.received', (data) => this.storeRawPushObservation('_raw.message.received', 'p2p', 'legacy', data));
|
|
162
|
+
this.client.on('_raw.peer.v2.message_received', (data) => this.storeRawPushObservation('_raw.peer.v2.message_received', 'p2p', 'v2', data));
|
|
163
|
+
this.client.on('_raw.group.message_created', (data) => this.storeRawPushObservation('_raw.group.message_created', 'group', 'legacy', data));
|
|
164
|
+
this.client.on('_raw.group.v2.message_created', (data) => this.storeRawPushObservation('_raw.group.v2.message_created', 'group', 'v2', data));
|
|
165
|
+
this.client.on('_raw.group.changed', (data) => this.storeRawGroupChangedObservation(data));
|
|
145
166
|
this.client.on('message.received', (msg) => {
|
|
146
167
|
void this.storeInboxItem(this.normalizeMessage(msg, true));
|
|
147
168
|
});
|
|
@@ -154,8 +175,103 @@ class CrossSdkJsAgent {
|
|
|
154
175
|
this.client.on('group.message_undecryptable', (msg) => {
|
|
155
176
|
void this.storeGroupInboxItem(this.normalizeGroupMessage(msg, false, 'undecryptable'));
|
|
156
177
|
});
|
|
157
|
-
|
|
158
|
-
|
|
178
|
+
this.client.on('group.changed', (data) => this.storeGroupChangedPublicEvent(data));
|
|
179
|
+
}
|
|
180
|
+
installTransportRpcObserver() {
|
|
181
|
+
const transport = this.client._transport;
|
|
182
|
+
transport?.setTraceMode('diag');
|
|
183
|
+
if (!transport?.call || this.rpcObservedTransports.has(transport))
|
|
184
|
+
return;
|
|
185
|
+
const originalCall = transport.call;
|
|
186
|
+
this.rpcObservedTransports.add(transport);
|
|
187
|
+
transport.call = async (method, params, timeout, trace, background) => {
|
|
188
|
+
this.storeRawPushRpcMethod({ type: 'rpc', method, request_window: this.rawPushRequestWindow(params) });
|
|
189
|
+
let requestParams = params;
|
|
190
|
+
if (method === 'auth.connect' && !this.inlineRealtimePayloadV1 && jsonObjectOf(params)) {
|
|
191
|
+
const request = { ...jsonObjectOf(params) };
|
|
192
|
+
const capabilities = jsonObjectOf(request.capabilities);
|
|
193
|
+
if (capabilities) {
|
|
194
|
+
delete capabilities.inline_realtime_payload_v1;
|
|
195
|
+
request.capabilities = capabilities;
|
|
196
|
+
}
|
|
197
|
+
requestParams = request;
|
|
198
|
+
}
|
|
199
|
+
return await originalCall.call(transport, method, requestParams, timeout, trace, background);
|
|
200
|
+
};
|
|
201
|
+
}
|
|
202
|
+
storeRawPushObservation(rawEvent, scope, defaultKind, value) {
|
|
203
|
+
const data = jsonObjectOf(value) ?? {};
|
|
204
|
+
const hasInline = Object.prototype.hasOwnProperty.call(data, 'inline_message');
|
|
205
|
+
const inlineMessage = jsonObjectOf(data.inline_message);
|
|
206
|
+
this.rawPushObservations.push({
|
|
207
|
+
observation_id: this.rawPushObservationId,
|
|
208
|
+
time: Date.now(), raw_event: rawEvent, scope, group_id: textOf(data.group_id),
|
|
209
|
+
kind: textOf(data.kind || defaultKind),
|
|
210
|
+
action: textOf(data.action),
|
|
211
|
+
event_seq: Number(data.event_seq ?? 0) || 0,
|
|
212
|
+
seq: Number(data.seq ?? data.message_seq ?? data.msg_seq ?? 0) || 0,
|
|
213
|
+
message_id: textOf(data.message_id ?? data.id ?? ''),
|
|
214
|
+
has_inline: hasInline,
|
|
215
|
+
inline_version: textOf(data.inline_version ?? inlineMessage?.version ?? ''),
|
|
216
|
+
inline_is_object: inlineMessage !== null,
|
|
217
|
+
target_device_present: Boolean(textOf(data.target_device_id)),
|
|
218
|
+
target_slot_present: Boolean(textOf(data.target_slot_id)),
|
|
219
|
+
target_device_id: textOf(data.target_device_id),
|
|
220
|
+
target_slot_id: textOf(data.target_slot_id),
|
|
221
|
+
inline_candidate_keys: Object.keys(data).filter((key) => key.startsWith('inline_') || key.startsWith('_inline_message_candidates_') || key === '_group_inline_plain_source_v1' || key === '_group_inline_v2_source_v1').sort(),
|
|
222
|
+
top_level_sensitive_keys: Object.keys(data).filter((key) => [
|
|
223
|
+
'inline_message', 'payload', 'message', 'envelope_json', 'ciphertext',
|
|
224
|
+
'_inline_message_candidates_v1', '_group_inline_plain_source_v1', '_group_inline_v2_source_v1',
|
|
225
|
+
].includes(key)).sort(),
|
|
226
|
+
});
|
|
227
|
+
if (this.rawPushObservations.length > 1000)
|
|
228
|
+
this.rawPushObservations = this.rawPushObservations.slice(-1000);
|
|
229
|
+
}
|
|
230
|
+
storeRawGroupChangedObservation(value) {
|
|
231
|
+
this.storeRawPushObservation('_raw.group.changed', 'group', 'changed', value);
|
|
232
|
+
}
|
|
233
|
+
storeGroupChangedPublicEvent(value) {
|
|
234
|
+
const data = jsonObjectOf(value) ?? {};
|
|
235
|
+
this.groupChangedEvents.push({
|
|
236
|
+
observation_id: this.rawPushObservationId,
|
|
237
|
+
time: Date.now(),
|
|
238
|
+
group_id: textOf(data.group_id),
|
|
239
|
+
action: textOf(data.action),
|
|
240
|
+
event_seq: Number(data.event_seq ?? 0) || 0,
|
|
241
|
+
event_id: textOf(data.event_id),
|
|
242
|
+
envelope_present: jsonObjectOf(data.envelope) !== null,
|
|
243
|
+
});
|
|
244
|
+
if (this.groupChangedEvents.length > 1000)
|
|
245
|
+
this.groupChangedEvents = this.groupChangedEvents.slice(-1000);
|
|
246
|
+
}
|
|
247
|
+
storeRawPushRpcMethod(traceInfo) {
|
|
248
|
+
if (traceInfo.type !== 'rpc')
|
|
249
|
+
return;
|
|
250
|
+
if (!this.rawPushObservationId)
|
|
251
|
+
return;
|
|
252
|
+
const method = textOf(traceInfo.method).trim();
|
|
253
|
+
if (!method)
|
|
254
|
+
return;
|
|
255
|
+
const requestWindow = jsonObjectOf(traceInfo.request_window) ?? {};
|
|
256
|
+
this.rawPushRpcMethods.push({
|
|
257
|
+
observation_id: this.rawPushObservationId,
|
|
258
|
+
time: Date.now(),
|
|
259
|
+
method,
|
|
260
|
+
...this.rawPushRequestWindow(requestWindow),
|
|
261
|
+
});
|
|
262
|
+
if (this.rawPushRpcMethods.length > 1000)
|
|
263
|
+
this.rawPushRpcMethods = this.rawPushRpcMethods.slice(-1000);
|
|
264
|
+
}
|
|
265
|
+
rawPushRequestWindow(value) {
|
|
266
|
+
const params = jsonObjectOf(value) ?? {};
|
|
267
|
+
const afterSeq = params.after_seq;
|
|
268
|
+
const limit = params.limit;
|
|
269
|
+
// 仅返回恢复窗口元数据;不得将 RPC params(其中可能含正文)暴露给测试接口。
|
|
270
|
+
return {
|
|
271
|
+
window_mode: typeof params.window_mode === 'string' ? params.window_mode : '',
|
|
272
|
+
after_seq: typeof afterSeq === 'number' && Number.isInteger(afterSeq) ? afterSeq : null,
|
|
273
|
+
limit: typeof limit === 'number' && Number.isInteger(limit) ? limit : null,
|
|
274
|
+
};
|
|
159
275
|
}
|
|
160
276
|
async close() {
|
|
161
277
|
try {
|
|
@@ -173,7 +289,7 @@ class CrossSdkJsAgent {
|
|
|
173
289
|
verifySsl: false,
|
|
174
290
|
});
|
|
175
291
|
}
|
|
176
|
-
async ensureConnected() {
|
|
292
|
+
async ensureConnected(backgroundSync = true) {
|
|
177
293
|
const store = this.aidStore();
|
|
178
294
|
try {
|
|
179
295
|
const registered = await store.register(this.aid);
|
|
@@ -187,12 +303,29 @@ class CrossSdkJsAgent {
|
|
|
187
303
|
if (!loaded.ok) {
|
|
188
304
|
throw new Error(`load identity failed: ${loaded.error.code}: ${loaded.error.message}`);
|
|
189
305
|
}
|
|
190
|
-
|
|
306
|
+
let identity = loaded.data.aid;
|
|
307
|
+
if (this.debug && !identity.debug) {
|
|
308
|
+
identity = await AID.create({
|
|
309
|
+
aid: identity.aid,
|
|
310
|
+
aunPath: identity.aunPath,
|
|
311
|
+
certPem: identity.certPem,
|
|
312
|
+
privateKeyPem: identity.privateKeyPem,
|
|
313
|
+
certValid: identity.isCertValid(),
|
|
314
|
+
privateKeyValid: identity.isPrivateKeyValid(),
|
|
315
|
+
deviceId: identity.deviceId,
|
|
316
|
+
slotId: identity.slotId,
|
|
317
|
+
verifySsl: identity.verifySsl,
|
|
318
|
+
rootCaPath: identity.rootCaPath,
|
|
319
|
+
debug: true,
|
|
320
|
+
});
|
|
321
|
+
}
|
|
322
|
+
this.client.loadIdentity(identity);
|
|
323
|
+
this.installTransportRpcObserver();
|
|
191
324
|
}
|
|
192
325
|
finally {
|
|
193
326
|
store.close();
|
|
194
327
|
}
|
|
195
|
-
await this.client.connect({ auto_reconnect: false, background_sync:
|
|
328
|
+
await this.client.connect({ auto_reconnect: false, background_sync: backgroundSync });
|
|
196
329
|
}
|
|
197
330
|
async identity() {
|
|
198
331
|
const internal = this.client;
|
|
@@ -303,6 +436,46 @@ class CrossSdkJsAgent {
|
|
|
303
436
|
sendJson(res, 200, { ok: true });
|
|
304
437
|
return;
|
|
305
438
|
}
|
|
439
|
+
if (req.method === 'POST' && url.pathname === '/test/raw-push/reset') {
|
|
440
|
+
const body = await readJson(req);
|
|
441
|
+
this.rawPushObservations = [];
|
|
442
|
+
this.rawPushRpcMethods = [];
|
|
443
|
+
this.groupChangedEvents = [];
|
|
444
|
+
this.rawPushObservationId = textOf(body.observation_id ?? '');
|
|
445
|
+
sendJson(res, 200, { ok: true, observation_id: this.rawPushObservationId });
|
|
446
|
+
return;
|
|
447
|
+
}
|
|
448
|
+
if (req.method === 'GET' && url.pathname === '/test/raw-push') {
|
|
449
|
+
const filters = {};
|
|
450
|
+
for (const key of ['observation_id', 'scope', 'group_id', 'kind', 'raw_event'])
|
|
451
|
+
filters[key] = textOf(url.searchParams.get(key) ?? '');
|
|
452
|
+
const limit = Math.max(1, Math.min(Number(url.searchParams.get('limit') ?? 1000) || 1000, 1000));
|
|
453
|
+
let items = [...this.rawPushObservations];
|
|
454
|
+
for (const [key, value] of Object.entries(filters))
|
|
455
|
+
if (value)
|
|
456
|
+
items = items.filter((item) => textOf(item[key]) === value);
|
|
457
|
+
items = items.slice(-limit);
|
|
458
|
+
const observationId = filters.observation_id;
|
|
459
|
+
let rpcEntries = [...this.rawPushRpcMethods];
|
|
460
|
+
let groupChangedEvents = [...this.groupChangedEvents];
|
|
461
|
+
if (observationId)
|
|
462
|
+
rpcEntries = rpcEntries.filter((item) => textOf(item.observation_id) === observationId);
|
|
463
|
+
if (observationId)
|
|
464
|
+
groupChangedEvents = groupChangedEvents.filter((item) => textOf(item.observation_id) === observationId);
|
|
465
|
+
if (filters.group_id)
|
|
466
|
+
groupChangedEvents = groupChangedEvents.filter((item) => textOf(item.group_id) === filters.group_id);
|
|
467
|
+
rpcEntries = rpcEntries.slice(-limit);
|
|
468
|
+
const rpcMethods = rpcEntries.map((item) => textOf(item.method));
|
|
469
|
+
const rpcMethodCounts = {};
|
|
470
|
+
for (const method of rpcMethods)
|
|
471
|
+
rpcMethodCounts[method] = Number(rpcMethodCounts[method] ?? 0) + 1;
|
|
472
|
+
sendJson(res, 200, {
|
|
473
|
+
ok: true, items, count: items.length, rpc_methods: rpcMethods, rpc_method_counts: rpcMethodCounts,
|
|
474
|
+
rpc_calls: rpcEntries,
|
|
475
|
+
group_changed_events: groupChangedEvents.slice(-limit),
|
|
476
|
+
});
|
|
477
|
+
return;
|
|
478
|
+
}
|
|
306
479
|
if (req.method === 'GET' && url.pathname === '/identity') {
|
|
307
480
|
sendJson(res, 200, await this.identity());
|
|
308
481
|
return;
|
|
@@ -319,6 +492,34 @@ class CrossSdkJsAgent {
|
|
|
319
492
|
await this.pull(req, res);
|
|
320
493
|
return;
|
|
321
494
|
}
|
|
495
|
+
if (req.method === 'GET' && url.pathname === '/sync/state') {
|
|
496
|
+
this.syncState(url, res);
|
|
497
|
+
return;
|
|
498
|
+
}
|
|
499
|
+
if (req.method === 'POST' && url.pathname === '/sync/tail') {
|
|
500
|
+
await this.syncTail(req, res);
|
|
501
|
+
return;
|
|
502
|
+
}
|
|
503
|
+
if (req.method === 'POST' && url.pathname === '/sync/forward') {
|
|
504
|
+
await this.syncForward(req, res);
|
|
505
|
+
return;
|
|
506
|
+
}
|
|
507
|
+
if (req.method === 'POST' && url.pathname === '/sync/history') {
|
|
508
|
+
await this.syncHistory(req, res);
|
|
509
|
+
return;
|
|
510
|
+
}
|
|
511
|
+
if (req.method === 'POST' && url.pathname === '/session/disconnect') {
|
|
512
|
+
await this.sessionDisconnect(res);
|
|
513
|
+
return;
|
|
514
|
+
}
|
|
515
|
+
if (req.method === 'POST' && url.pathname === '/session/connect') {
|
|
516
|
+
await this.sessionConnect(req, res);
|
|
517
|
+
return;
|
|
518
|
+
}
|
|
519
|
+
if (req.method === 'POST' && url.pathname === '/session/restart') {
|
|
520
|
+
await this.sessionRestart(req, res);
|
|
521
|
+
return;
|
|
522
|
+
}
|
|
322
523
|
if (req.method === 'POST' && url.pathname === '/group/create') {
|
|
323
524
|
await this.groupCreate(req, res);
|
|
324
525
|
return;
|
|
@@ -1105,6 +1306,171 @@ class CrossSdkJsAgent {
|
|
|
1105
1306
|
});
|
|
1106
1307
|
}
|
|
1107
1308
|
}
|
|
1309
|
+
syncNamespace(scope, groupId = '') {
|
|
1310
|
+
if (scope === 'p2p')
|
|
1311
|
+
return `p2p:${this.aid}`;
|
|
1312
|
+
if (scope === 'group' && groupId)
|
|
1313
|
+
return `group:${groupId}`;
|
|
1314
|
+
throw new Error('scope must be p2p, or group with group_id');
|
|
1315
|
+
}
|
|
1316
|
+
syncStateValue(scope, groupId = '') {
|
|
1317
|
+
const namespace = this.syncNamespace(scope, groupId);
|
|
1318
|
+
const tracker = this.client._seqTracker;
|
|
1319
|
+
if (!tracker)
|
|
1320
|
+
throw new Error('SeqTracker is unavailable');
|
|
1321
|
+
return { namespace, state: tracker.getSyncState(namespace) };
|
|
1322
|
+
}
|
|
1323
|
+
syncState(url, res) {
|
|
1324
|
+
const scope = textOf(url.searchParams.get('scope') || 'p2p').trim().toLowerCase();
|
|
1325
|
+
const groupId = textOf(url.searchParams.get('group_id') || '').trim();
|
|
1326
|
+
try {
|
|
1327
|
+
const snapshot = this.syncStateValue(scope, groupId);
|
|
1328
|
+
sendJson(res, 200, { ok: true, scope, ...snapshot });
|
|
1329
|
+
}
|
|
1330
|
+
catch (err) {
|
|
1331
|
+
sendJson(res, 400, {
|
|
1332
|
+
ok: false,
|
|
1333
|
+
error_code: err instanceof Error ? err.name : 'Error',
|
|
1334
|
+
error_message: err instanceof Error ? err.message : String(err),
|
|
1335
|
+
});
|
|
1336
|
+
}
|
|
1337
|
+
}
|
|
1338
|
+
async syncTail(req, res) {
|
|
1339
|
+
await this.syncPull(req, res, true);
|
|
1340
|
+
}
|
|
1341
|
+
async syncForward(req, res) {
|
|
1342
|
+
await this.syncPull(req, res, false);
|
|
1343
|
+
}
|
|
1344
|
+
async syncPull(req, res, tail) {
|
|
1345
|
+
const body = await readJson(req);
|
|
1346
|
+
const scope = textOf(body.scope || 'p2p').trim().toLowerCase();
|
|
1347
|
+
const groupId = textOf(body.group_id || '').trim();
|
|
1348
|
+
const afterSeq = Number(body.after_seq ?? 0) || 0;
|
|
1349
|
+
const limit = Number(body.limit ?? 50) || 50;
|
|
1350
|
+
try {
|
|
1351
|
+
const params = { after_seq: afterSeq, limit };
|
|
1352
|
+
if (tail)
|
|
1353
|
+
params.window_mode = 'tail';
|
|
1354
|
+
const method = scope === 'group' ? 'group.pull' : 'message.pull';
|
|
1355
|
+
if (scope === 'group')
|
|
1356
|
+
params.group_id = groupId;
|
|
1357
|
+
this.syncNamespace(scope, groupId);
|
|
1358
|
+
let result;
|
|
1359
|
+
if (tail) {
|
|
1360
|
+
result = await this.client.call(method, params);
|
|
1361
|
+
}
|
|
1362
|
+
else {
|
|
1363
|
+
const transport = this.client._transport;
|
|
1364
|
+
if (!transport?.call)
|
|
1365
|
+
throw new Error('raw transport is unavailable');
|
|
1366
|
+
const wireMethod = scope === 'group' ? 'group.v2.pull' : 'message.v2.pull';
|
|
1367
|
+
result = await transport.call(wireMethod, params);
|
|
1368
|
+
}
|
|
1369
|
+
const resultObj = jsonObjectOf(result) ?? {};
|
|
1370
|
+
const messages = Array.isArray(resultObj.messages) ? resultObj.messages : [];
|
|
1371
|
+
if (tail) {
|
|
1372
|
+
for (const msg of messages) {
|
|
1373
|
+
if (scope === 'group')
|
|
1374
|
+
await this.storeGroupInboxItem(this.normalizeGroupMessage(msg, true));
|
|
1375
|
+
else
|
|
1376
|
+
await this.storeInboxItem(this.normalizeMessage(msg, true));
|
|
1377
|
+
}
|
|
1378
|
+
}
|
|
1379
|
+
const snapshot = this.syncStateValue(scope, groupId);
|
|
1380
|
+
sendJson(res, 200, { ok: true, scope, ...snapshot, result: jsonSafe(result) });
|
|
1381
|
+
}
|
|
1382
|
+
catch (err) {
|
|
1383
|
+
sendJson(res, 500, {
|
|
1384
|
+
ok: false,
|
|
1385
|
+
scope,
|
|
1386
|
+
error_code: err instanceof Error ? err.name : 'Error',
|
|
1387
|
+
error_message: err instanceof Error ? err.message : String(err),
|
|
1388
|
+
});
|
|
1389
|
+
}
|
|
1390
|
+
}
|
|
1391
|
+
async syncHistory(req, res) {
|
|
1392
|
+
const body = await readJson(req);
|
|
1393
|
+
const scope = textOf(body.scope || 'p2p').trim().toLowerCase();
|
|
1394
|
+
const groupId = textOf(body.group_id || '').trim();
|
|
1395
|
+
const beforeSeq = Number(body.before_seq ?? 0) || 0;
|
|
1396
|
+
const limit = Number(body.limit ?? 50) || 50;
|
|
1397
|
+
try {
|
|
1398
|
+
const params = { before_seq: beforeSeq, limit };
|
|
1399
|
+
const method = scope === 'group' ? 'group.history' : 'message.history';
|
|
1400
|
+
if (scope === 'group')
|
|
1401
|
+
params.group_id = groupId;
|
|
1402
|
+
this.syncNamespace(scope, groupId);
|
|
1403
|
+
const result = await this.client.call(method, params);
|
|
1404
|
+
const snapshot = this.syncStateValue(scope, groupId);
|
|
1405
|
+
sendJson(res, 200, { ok: true, scope, ...snapshot, result: jsonSafe(result) });
|
|
1406
|
+
}
|
|
1407
|
+
catch (err) {
|
|
1408
|
+
sendJson(res, 500, {
|
|
1409
|
+
ok: false,
|
|
1410
|
+
scope,
|
|
1411
|
+
error_code: err instanceof Error ? err.name : 'Error',
|
|
1412
|
+
error_message: err instanceof Error ? err.message : String(err),
|
|
1413
|
+
});
|
|
1414
|
+
}
|
|
1415
|
+
}
|
|
1416
|
+
async sessionDisconnect(res) {
|
|
1417
|
+
try {
|
|
1418
|
+
this.ready = false;
|
|
1419
|
+
await this.client.disconnect();
|
|
1420
|
+
sendJson(res, 200, { ok: true, state: textOf(this.client.state) });
|
|
1421
|
+
}
|
|
1422
|
+
catch (err) {
|
|
1423
|
+
sendJson(res, 500, {
|
|
1424
|
+
ok: false,
|
|
1425
|
+
error_code: err instanceof Error ? err.name : 'Error',
|
|
1426
|
+
error_message: err instanceof Error ? err.message : String(err),
|
|
1427
|
+
});
|
|
1428
|
+
}
|
|
1429
|
+
}
|
|
1430
|
+
async sessionConnect(req, res) {
|
|
1431
|
+
const body = await readJson(req);
|
|
1432
|
+
const backgroundSync = body.background_sync === true;
|
|
1433
|
+
if (Object.prototype.hasOwnProperty.call(body, 'inline_realtime_payload_v1')) {
|
|
1434
|
+
this.inlineRealtimePayloadV1 = body.inline_realtime_payload_v1 !== false;
|
|
1435
|
+
}
|
|
1436
|
+
try {
|
|
1437
|
+
await this.client.connect({ auto_reconnect: false, background_sync: backgroundSync });
|
|
1438
|
+
this.ready = true;
|
|
1439
|
+
sendJson(res, 200, { ok: true, background_sync: backgroundSync, inline_realtime_payload_v1: this.inlineRealtimePayloadV1 });
|
|
1440
|
+
}
|
|
1441
|
+
catch (err) {
|
|
1442
|
+
sendJson(res, 500, {
|
|
1443
|
+
ok: false,
|
|
1444
|
+
error_code: err instanceof Error ? err.name : 'Error',
|
|
1445
|
+
error_message: err instanceof Error ? err.message : String(err),
|
|
1446
|
+
});
|
|
1447
|
+
}
|
|
1448
|
+
}
|
|
1449
|
+
async sessionRestart(req, res) {
|
|
1450
|
+
const body = await readJson(req);
|
|
1451
|
+
const backgroundSync = body.background_sync === true;
|
|
1452
|
+
if (Object.prototype.hasOwnProperty.call(body, 'inline_realtime_payload_v1')) {
|
|
1453
|
+
this.inlineRealtimePayloadV1 = body.inline_realtime_payload_v1 !== false;
|
|
1454
|
+
}
|
|
1455
|
+
this.ready = false;
|
|
1456
|
+
try {
|
|
1457
|
+
await this.client.close();
|
|
1458
|
+
this.client = this.newClient();
|
|
1459
|
+
this.bindClientEvents();
|
|
1460
|
+
await this.ensureConnected(backgroundSync);
|
|
1461
|
+
this.startupError = '';
|
|
1462
|
+
this.ready = true;
|
|
1463
|
+
sendJson(res, 200, { ok: true, background_sync: backgroundSync, inline_realtime_payload_v1: this.inlineRealtimePayloadV1 });
|
|
1464
|
+
}
|
|
1465
|
+
catch (err) {
|
|
1466
|
+
this.startupError = `${err instanceof Error ? err.name : 'Error'}: ${err instanceof Error ? err.message : String(err)}`;
|
|
1467
|
+
sendJson(res, 500, {
|
|
1468
|
+
ok: false,
|
|
1469
|
+
error_code: err instanceof Error ? err.name : 'Error',
|
|
1470
|
+
error_message: err instanceof Error ? err.message : String(err),
|
|
1471
|
+
});
|
|
1472
|
+
}
|
|
1473
|
+
}
|
|
1108
1474
|
async groupCreate(req, res) {
|
|
1109
1475
|
const body = await readJson(req);
|
|
1110
1476
|
const traceId = textOf(body.trace_id || crypto.randomUUID().replace(/-/g, ''));
|