@agentunion/fastaun 0.5.32 → 0.5.34
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 +58 -0
- package/README.md +28 -26
- package/_packed_docs/CHANGELOG.md +58 -0
- package/_packed_docs/INDEX.md +17 -3
- package/_packed_docs/KITE_DOCS_GUIDE.md +10 -4
- package/_packed_docs/protocol/03-Gateway-/350/277/236/346/216/245/346/250/241/345/274/217.md +58 -8
- package/_packed_docs/sdk/0.5.33-SDK/345/272/224/347/224/250/351/233/206/346/210/220/346/214/207/345/215/227.md +464 -0
- package/_packed_docs/sdk/0.5.33-SDK/345/274/200/345/217/221/344/270/216/347/247/273/346/244/215/346/214/207/345/215/227.md +499 -0
- package/_packed_docs/sdk/0.5.34-SDK/345/272/224/347/224/250/351/233/206/346/210/220/346/214/207/345/215/227.md +133 -0
- package/_packed_docs/sdk/0.5.34-SDK/345/274/200/345/217/221/344/270/216/347/247/273/346/244/215/346/214/207/345/215/227.md +107 -0
- package/_packed_docs/sdk/01-/345/277/253/351/200/237/345/274/200/345/247/213.md +16 -13
- package/_packed_docs/sdk/03-/346/240/270/345/277/203/346/246/202/345/277/265.md +13 -1
- package/_packed_docs/sdk/04-/350/277/236/346/216/245/344/270/216/350/256/244/350/257/201.md +17 -7
- package/_packed_docs/sdk/06-API/346/211/213/345/206/214.md +55 -14
- package/_packed_docs/sdk/09-collab-rpc-manual.md +48 -30
- package/_packed_docs/sdk/09-custody-api-manual.md +3 -3
- package/_packed_docs/sdk/09-group-rpc-manual.md +53 -6
- package/_packed_docs/sdk/09-message-rpc-manual.md +22 -0
- package/_packed_docs/sdk/09-meta-rpc-manual.md +2 -1
- package/_packed_docs/sdk/09-payload-reference.md +9 -8
- package/_packed_docs/sdk/09-proxy-rpc-manual.md +20 -14
- package/_packed_docs/sdk/09-storage-rpc-manual.md +1698 -1642
- package/_packed_docs/sdk/09-stream-rpc-manual.md +33 -20
- package/_packed_docs/sdk/AUN_DOCS_GUIDE.md +11 -9
- package/_packed_docs/sdk/AUN/344/272/213/344/273/266/345/217/221/345/270/203/350/256/242/351/230/205/345/272/224/347/224/250/351/233/206/346/210/220/346/214/207/345/215/227.md +53 -28
- package/_packed_docs/sdk/AUN/344/272/213/344/273/266/345/217/221/345/270/203/350/256/242/351/230/205/345/274/200/345/217/221/347/247/273/346/244/215/346/214/207/345/215/227.md +62 -28
- package/_packed_docs/sdk/INDEX.md +21 -9
- package/_packed_docs/sdk/README.md +11 -6
- package/dist/agent-md.d.ts +2 -1
- package/dist/agent-md.js +17 -0
- package/dist/agent-md.js.map +1 -1
- package/dist/auth.js +8 -2
- package/dist/auth.js.map +1 -1
- package/dist/client/control-messages.js +4 -4
- package/dist/client/control-messages.js.map +1 -1
- package/dist/client/delivery.d.ts +5 -0
- package/dist/client/delivery.js +146 -32
- package/dist/client/delivery.js.map +1 -1
- package/dist/client/lifecycle.js +3 -0
- package/dist/client/lifecycle.js.map +1 -1
- package/dist/client/rpc-budget.d.ts +21 -0
- package/dist/client/rpc-budget.js +82 -0
- package/dist/client/rpc-budget.js.map +1 -0
- package/dist/client/rpc-pipeline.d.ts +3 -0
- package/dist/client/rpc-pipeline.js +193 -65
- package/dist/client/rpc-pipeline.js.map +1 -1
- package/dist/client/sync-channels.d.ts +89 -0
- package/dist/client/sync-channels.js +489 -0
- package/dist/client/sync-channels.js.map +1 -0
- package/dist/client/v2-e2ee.d.ts +4 -1
- package/dist/client/v2-e2ee.js +401 -298
- package/dist/client/v2-e2ee.js.map +1 -1
- package/dist/client.d.ts +9 -4
- package/dist/client.js +125 -15
- package/dist/client.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.js.map +1 -1
- package/dist/ownership-workflow.d.ts +23 -3
- package/dist/ownership-workflow.js +36 -13
- package/dist/ownership-workflow.js.map +1 -1
- package/dist/pubsub/binding.js +14 -1
- package/dist/pubsub/binding.js.map +1 -1
- package/dist/pubsub/channel.d.ts +4 -0
- package/dist/pubsub/channel.js +26 -0
- package/dist/pubsub/channel.js.map +1 -1
- package/dist/pubsub/client.d.ts +9 -0
- package/dist/pubsub/client.js +154 -31
- package/dist/pubsub/client.js.map +1 -1
- package/dist/pubsub/credentials.d.ts +3 -0
- package/dist/pubsub/credentials.js +57 -20
- package/dist/pubsub/credentials.js.map +1 -1
- package/dist/pubsub/index.d.ts +3 -0
- package/dist/pubsub/index.js +69 -53
- package/dist/pubsub/index.js.map +1 -1
- package/dist/pubsub/service.d.ts +3 -0
- package/dist/pubsub/service.js +167 -12
- package/dist/pubsub/service.js.map +1 -1
- package/dist/pubsub/types.d.ts +2 -0
- package/dist/storage/lowlevel.d.ts +7 -3
- package/dist/storage/lowlevel.js +15 -0
- package/dist/storage/lowlevel.js.map +1 -1
- package/dist/storage/read-cache.js +12 -0
- package/dist/storage/read-cache.js.map +1 -1
- package/dist/storage/types.d.ts +10 -0
- package/dist/storage/types.js.map +1 -1
- package/dist/storage/vfs.d.ts +7 -3
- package/dist/storage/vfs.js +2 -2
- package/dist/storage/vfs.js.map +1 -1
- package/dist/tools/cross-sdk-agent.d.ts +62 -6
- package/dist/tools/cross-sdk-agent.js +169 -37
- package/dist/tools/cross-sdk-agent.js.map +1 -1
- package/dist/transport.d.ts +12 -0
- package/dist/transport.js +91 -6
- package/dist/transport.js.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +1 -1
|
@@ -25,6 +25,14 @@ const credentialProcessStartupId = crypto.randomUUID();
|
|
|
25
25
|
const { DatabaseSync } = createRequire(import.meta.url)('node:sqlite');
|
|
26
26
|
const cacheReadContext = new AsyncLocalStorage();
|
|
27
27
|
const cacheReadObservers = new WeakMap();
|
|
28
|
+
function storageAclTargets(params) {
|
|
29
|
+
const raw = jsonObjectOf(params.subject), ownership = jsonObjectOf(raw?.ownership);
|
|
30
|
+
return {
|
|
31
|
+
granteeAid: (params.grantee_aid !== undefined ? params.grantee_aid : params.granteeAID),
|
|
32
|
+
granteeAids: (params.grantee_aids !== undefined ? params.grantee_aids : params.granteeAids),
|
|
33
|
+
subject: (raw && ownership ? { ...raw, ownership: { ownerAid: ownership.owner_aid ?? ownership.ownerAid, ...(ownership.scope !== undefined ? { scope: ownership.scope } : {}) } } : params.subject),
|
|
34
|
+
};
|
|
35
|
+
}
|
|
28
36
|
function loadTrustedArchive(configPath, issuer) {
|
|
29
37
|
if (!configPath)
|
|
30
38
|
return undefined;
|
|
@@ -205,6 +213,7 @@ export class CrossSdkTsAgent {
|
|
|
205
213
|
rpcFailures = [];
|
|
206
214
|
messageOperations = new Map();
|
|
207
215
|
rpcObservedTransports = new WeakSet();
|
|
216
|
+
rpcObservedChannelFactories = new WeakSet();
|
|
208
217
|
rpcObservedPipelines = new WeakSet();
|
|
209
218
|
rpcObservedPulls = new WeakMap();
|
|
210
219
|
groupChangedEvents = [];
|
|
@@ -215,6 +224,11 @@ export class CrossSdkTsAgent {
|
|
|
215
224
|
traces = new Map();
|
|
216
225
|
sendResults = new Map();
|
|
217
226
|
inlineRealtimePayloadV1 = true;
|
|
227
|
+
messageClassesV2 = envBool('AUN_TEST_MESSAGE_CLASSES_V2', true);
|
|
228
|
+
controlAdvertisedCapabilities = {};
|
|
229
|
+
controlNegotiatedCapabilities = {};
|
|
230
|
+
controlWireSends = [];
|
|
231
|
+
sdkControlMessages = [];
|
|
218
232
|
constructor() {
|
|
219
233
|
this.client = this.newClient();
|
|
220
234
|
}
|
|
@@ -242,8 +256,41 @@ export class CrossSdkTsAgent {
|
|
|
242
256
|
if (internal._configModel)
|
|
243
257
|
internal._configModel.requireForwardSecrecy = false;
|
|
244
258
|
internal._testSlotId = this.slotId;
|
|
259
|
+
const controls = internal._controlMessages?.();
|
|
260
|
+
if (controls) {
|
|
261
|
+
const consume = controls.consume.bind(controls);
|
|
262
|
+
controls.consume = async (message, admission) => {
|
|
263
|
+
const result = await consume(message, admission);
|
|
264
|
+
if (message.encrypted === true)
|
|
265
|
+
this.sdkControlMessages.push(structuredClone(message));
|
|
266
|
+
return result;
|
|
267
|
+
};
|
|
268
|
+
}
|
|
245
269
|
return client;
|
|
246
270
|
}
|
|
271
|
+
prepareControlMatrixRequest(method, params) {
|
|
272
|
+
if (method === 'auth.connect' && jsonObjectOf(params)) {
|
|
273
|
+
const request = { ...jsonObjectOf(params) };
|
|
274
|
+
const capabilities = { ...(jsonObjectOf(request.capabilities) ?? {}) };
|
|
275
|
+
if (this.inlineRealtimePayloadV1 === false)
|
|
276
|
+
delete capabilities.inline_realtime_payload_v1;
|
|
277
|
+
if (this.messageClassesV2 === false) {
|
|
278
|
+
delete capabilities.message_classes_v2;
|
|
279
|
+
delete capabilities.message_classes_v1;
|
|
280
|
+
delete capabilities.sdk_control_protocols;
|
|
281
|
+
}
|
|
282
|
+
request.capabilities = capabilities;
|
|
283
|
+
this.controlAdvertisedCapabilities = structuredClone(capabilities);
|
|
284
|
+
return request;
|
|
285
|
+
}
|
|
286
|
+
if (['message.send', 'message.v2.send', 'group.send', 'group.v2.send'].includes(method) && params) {
|
|
287
|
+
const envelope = jsonObjectOf(params.envelope) ?? jsonObjectOf(params.payload) ?? {};
|
|
288
|
+
this.controlWireSends.push({ method, message_id: textOf(params.message_id) || textOf(envelope.message_id) || textOf(jsonObjectOf(envelope.aad)?.message_id), to: textOf(params.to),
|
|
289
|
+
group_id: textOf(params.group_id ?? params.group_aid), message_class: params.message_class ?? null, message_class_present: 'message_class' in params, ttl: params.ttl ?? 0,
|
|
290
|
+
payload_type: textOf(envelope.type), protected_headers: structuredClone(jsonObjectOf(envelope.protected_headers) ?? jsonObjectOf(params.protected_headers) ?? {}) });
|
|
291
|
+
}
|
|
292
|
+
return params;
|
|
293
|
+
}
|
|
247
294
|
bindClientEvents() {
|
|
248
295
|
this.eventBoundClients ??= new WeakSet();
|
|
249
296
|
if (this.eventBoundClients.has(this.client)) {
|
|
@@ -275,6 +322,17 @@ export class CrossSdkTsAgent {
|
|
|
275
322
|
for (const event of ['message.read_changed', 'group.read_changed', 'read_state_sync']) {
|
|
276
323
|
this.client.on(event, (payload) => { this.readStateEvents.push({ event, payload: jsonSafe(payload) }); });
|
|
277
324
|
}
|
|
325
|
+
this.client.on('sync.error', (value) => {
|
|
326
|
+
const data = jsonObjectOf(value) ?? {}, error = textOf(data.error), method = textOf(data.method);
|
|
327
|
+
const internal = this.client;
|
|
328
|
+
this.eventLedger.push({
|
|
329
|
+
observation_id: this.rawPushObservationId, event: 'sync.error', event_index: this.eventLedger.length + 1, time_ms: Date.now(),
|
|
330
|
+
scope: method.startsWith('group.') ? 'group' : 'p2p', receiver_aid: this.aid,
|
|
331
|
+
device_id: textOf(internal._deviceId), slot_id: textOf(internal._slotId || this.slotId),
|
|
332
|
+
payload: { namespace: textOf(data.namespace), method, code: textOf(data.code),
|
|
333
|
+
error_sha256: crypto.createHash('sha256').update(error, 'utf8').digest('hex'), error_length: Buffer.byteLength(error, 'utf8') },
|
|
334
|
+
});
|
|
335
|
+
});
|
|
278
336
|
this.client.on('message.peers_snapshot', (payload) => {
|
|
279
337
|
this.peersSnapshots.push({ event: 'message.peers_snapshot', payload: jsonSafe(payload) });
|
|
280
338
|
});
|
|
@@ -296,17 +354,17 @@ export class CrossSdkTsAgent {
|
|
|
296
354
|
this.singleEventCounts ??= { 'message.received': 0, 'group.message_created': 0, 'group.changed': 0 };
|
|
297
355
|
this.singleEventCounts[event] = Number(this.singleEventCounts[event] ?? 0) + 1;
|
|
298
356
|
}
|
|
299
|
-
async storeApplicationEvent(event, value) {
|
|
357
|
+
async storeApplicationEvent(event, value, observationId = this.rawPushObservationId) {
|
|
300
358
|
if (event === 'message.received') {
|
|
301
|
-
this.storeEventLedger(event, value);
|
|
359
|
+
this.storeEventLedger(event, value, observationId);
|
|
302
360
|
await this.storeInboxItem(this.normalizeMessage(value, true));
|
|
303
361
|
}
|
|
304
362
|
else if (event === 'group.message_created') {
|
|
305
|
-
this.storeEventLedger(event, value);
|
|
363
|
+
this.storeEventLedger(event, value, observationId);
|
|
306
364
|
await this.storeGroupInboxItem(this.normalizeGroupMessage(value, true));
|
|
307
365
|
}
|
|
308
366
|
else if (event === 'group.changed')
|
|
309
|
-
this.storeGroupChangedPublicEvent(value);
|
|
367
|
+
this.storeGroupChangedPublicEvent(value, observationId);
|
|
310
368
|
}
|
|
311
369
|
setP2pSubscription(enabled) {
|
|
312
370
|
this.p2pSubscription = enabled;
|
|
@@ -318,10 +376,11 @@ export class CrossSdkTsAgent {
|
|
|
318
376
|
if (enabled && !this.p2pEventHandler) {
|
|
319
377
|
const client = this.client;
|
|
320
378
|
this.p2pEventHandler = async (msg) => {
|
|
379
|
+
const observationId = this.rawPushObservationId;
|
|
380
|
+
this.countSingleEvent('message.received');
|
|
321
381
|
if ((this.p2pDeliveryPaused || this.p2pDeliveryRetiredClients?.has(client)) && !await this.waitForP2pDelivery(client))
|
|
322
382
|
return;
|
|
323
|
-
this.
|
|
324
|
-
await this.storeApplicationEvent('message.received', msg);
|
|
383
|
+
await this.storeApplicationEvent('message.received', msg, observationId);
|
|
325
384
|
};
|
|
326
385
|
this.client.on('message.received', this.p2pEventHandler);
|
|
327
386
|
}
|
|
@@ -378,22 +437,37 @@ export class CrossSdkTsAgent {
|
|
|
378
437
|
const client = this.client;
|
|
379
438
|
for (const event of events) {
|
|
380
439
|
const handler = async (value) => {
|
|
440
|
+
const observationId = this.rawPushObservationId;
|
|
381
441
|
if (event === 'message.batch' && (this.p2pDeliveryPaused || this.p2pDeliveryRetiredClients?.has(client)) && !await this.waitForP2pDelivery(client))
|
|
382
442
|
return;
|
|
383
443
|
const data = jsonObjectOf(value) ?? {};
|
|
384
444
|
const items = JSON.parse(JSON.stringify(jsonSafe(Array.isArray(data.items) ? data.items : [])));
|
|
385
445
|
this.batchEvents ??= [];
|
|
386
|
-
this.batchEvents.push({ observation_id:
|
|
446
|
+
this.batchEvents.push({ observation_id: observationId, time_ms: Date.now(), event,
|
|
387
447
|
namespace: textOf(data.namespace), source: textOf(data.source), items });
|
|
388
448
|
for (const item of items)
|
|
389
|
-
await this.storeApplicationEvent(textOf(item.event), item.payload);
|
|
449
|
+
await this.storeApplicationEvent(textOf(item.event), item.payload, observationId);
|
|
390
450
|
};
|
|
391
451
|
this.batchEventHandlers.push({ event, handler });
|
|
392
452
|
this.client.on(event, handler);
|
|
393
453
|
}
|
|
394
454
|
}
|
|
395
|
-
installTransportRpcObserver() {
|
|
455
|
+
installTransportRpcObserver(transport) {
|
|
396
456
|
const client = this.client;
|
|
457
|
+
if (!transport) {
|
|
458
|
+
const options = this.client._historyChannels?.().options;
|
|
459
|
+
this.rpcObservedChannelFactories ??= new WeakSet();
|
|
460
|
+
if (options && !this.rpcObservedChannelFactories.has(options)) {
|
|
461
|
+
const create = options.create;
|
|
462
|
+
this.rpcObservedChannelFactories.add(options);
|
|
463
|
+
options.create = async (...args) => {
|
|
464
|
+
const channel = await create.apply(options, args);
|
|
465
|
+
this.installTransportRpcObserver(channel.transport);
|
|
466
|
+
return channel;
|
|
467
|
+
};
|
|
468
|
+
}
|
|
469
|
+
transport = client._transport;
|
|
470
|
+
}
|
|
397
471
|
const pipeline = client._rpcPipeline;
|
|
398
472
|
this.rpcObservedPipelines ??= new WeakSet();
|
|
399
473
|
this.rpcObservedPulls ??= new WeakMap();
|
|
@@ -415,7 +489,6 @@ export class CrossSdkTsAgent {
|
|
|
415
489
|
return result;
|
|
416
490
|
};
|
|
417
491
|
}
|
|
418
|
-
const transport = this.client._transport;
|
|
419
492
|
transport?.setTraceMode('diag');
|
|
420
493
|
if (!transport?.call || this.rpcObservedTransports.has(transport))
|
|
421
494
|
return;
|
|
@@ -436,16 +509,7 @@ export class CrossSdkTsAgent {
|
|
|
436
509
|
};
|
|
437
510
|
transport.call = (method, params, timeout, trace, background) => {
|
|
438
511
|
this.storeRawPushRpcMethod({ type: 'rpc', method, request_window: this.rawPushRequestWindow(params) });
|
|
439
|
-
|
|
440
|
-
if (method === 'auth.connect' && !this.inlineRealtimePayloadV1 && jsonObjectOf(params)) {
|
|
441
|
-
const request = { ...jsonObjectOf(params) };
|
|
442
|
-
const capabilities = jsonObjectOf(request.capabilities);
|
|
443
|
-
if (capabilities) {
|
|
444
|
-
delete capabilities.inline_realtime_payload_v1;
|
|
445
|
-
request.capabilities = capabilities;
|
|
446
|
-
}
|
|
447
|
-
requestParams = request;
|
|
448
|
-
}
|
|
512
|
+
const requestParams = this.prepareControlMatrixRequest(method, params);
|
|
449
513
|
const generation = this.observationGeneration;
|
|
450
514
|
const span = this.startRpcSpan(method, requestParams);
|
|
451
515
|
const controller = new AbortController();
|
|
@@ -455,6 +519,8 @@ export class CrossSdkTsAgent {
|
|
|
455
519
|
try {
|
|
456
520
|
request = originalCall.call(transport, method, requestParams, timeout, trace, background);
|
|
457
521
|
const result = await request;
|
|
522
|
+
if (method === 'auth.connect')
|
|
523
|
+
this.controlNegotiatedCapabilities = structuredClone(jsonObjectOf(jsonObjectOf(result)?.negotiated_capabilities) ?? {});
|
|
458
524
|
if (span) {
|
|
459
525
|
this.finishRpcResponse(span, result);
|
|
460
526
|
if (generation === this.observationGeneration && (this.isObservedPull(method) || this.pullBarrier?.method === method)) {
|
|
@@ -483,12 +549,12 @@ export class CrossSdkTsAgent {
|
|
|
483
549
|
return pending;
|
|
484
550
|
};
|
|
485
551
|
}
|
|
486
|
-
storeEventLedger(event, value) {
|
|
552
|
+
storeEventLedger(event, value, observationId = this.rawPushObservationId) {
|
|
487
553
|
const data = jsonObjectOf(value) ?? {};
|
|
488
554
|
const internal = this.client;
|
|
489
555
|
const payload = JSON.parse(stableStringify(jsonSafe(data.payload ?? null)));
|
|
490
556
|
this.eventLedger.push({
|
|
491
|
-
observation_id:
|
|
557
|
+
observation_id: observationId, event, event_index: this.eventLedger.length + 1, time_ms: Date.now(),
|
|
492
558
|
scope: event === 'message.received' ? 'p2p' : 'group', receiver_aid: this.aid,
|
|
493
559
|
device_id: textOf(internal._deviceId), slot_id: textOf(internal._slotId ?? this.slotId),
|
|
494
560
|
sender_aid: textOf(data.sender_aid ?? data.from_aid ?? data.from), group_id: textOf(data.group_id),
|
|
@@ -527,7 +593,7 @@ export class CrossSdkTsAgent {
|
|
|
527
593
|
if (typeof params[key] === 'number' && Number.isSafeInteger(params[key]))
|
|
528
594
|
window[key] = params[key];
|
|
529
595
|
}
|
|
530
|
-
for (const key of ['window_mode', 'cursor_scope', 'sender_aid', 'group_id', 'group_aid', 'device_id', 'slot_id', 'after_volatile_cursor', 'mode', 'after_sender_aid']) {
|
|
596
|
+
for (const key of ['window_mode', 'cursor_scope', 'storage_scope', 'sender_aid', 'group_id', 'group_aid', 'device_id', 'slot_id', 'after_volatile_cursor', 'mode', 'after_sender_aid']) {
|
|
531
597
|
if (typeof params[key] === 'string')
|
|
532
598
|
window[key] = params[key];
|
|
533
599
|
}
|
|
@@ -575,6 +641,22 @@ export class CrossSdkTsAgent {
|
|
|
575
641
|
span.has_more_volatile = typeof response.volatile_has_more === 'boolean' ? response.volatile_has_more : null;
|
|
576
642
|
span.persistent_has_more = span.has_more_persistent;
|
|
577
643
|
span.volatile_has_more = span.has_more_volatile;
|
|
644
|
+
const safeSeq = (value) => typeof value === 'number' && Number.isSafeInteger(value) && value >= 0 ? value : null;
|
|
645
|
+
for (const key of ['head_seq', 'scan_after_seq', 'covered_through_seq', 'next_after_seq', 'retention_floor_seq',
|
|
646
|
+
'retention_floor_message_seq', 'retention_floor_event_seq']) {
|
|
647
|
+
const value = safeSeq(response[key]);
|
|
648
|
+
if (value !== null)
|
|
649
|
+
span[key] = value;
|
|
650
|
+
}
|
|
651
|
+
const cursor = jsonObjectOf(response.cursor);
|
|
652
|
+
if (span.retention_floor_seq === undefined) {
|
|
653
|
+
const cursorRetentionFloor = safeSeq(cursor?.retention_floor_seq);
|
|
654
|
+
if (cursorRetentionFloor !== null)
|
|
655
|
+
span.retention_floor_seq = cursorRetentionFloor;
|
|
656
|
+
}
|
|
657
|
+
const cursorJoinSeq = safeSeq(cursor?.join_seq);
|
|
658
|
+
if (cursorJoinSeq !== null)
|
|
659
|
+
span.join_seq = cursorJoinSeq;
|
|
578
660
|
for (const key of ['peer_ack_seq', 'effective_ack_seq', 'server_ack_seq', 'ack_seq', 'up_to_seq', 'acked_seq']) {
|
|
579
661
|
if (typeof response[key] === 'number' && Number.isSafeInteger(response[key]))
|
|
580
662
|
span[key] = response[key];
|
|
@@ -691,10 +773,10 @@ export class CrossSdkTsAgent {
|
|
|
691
773
|
storeRawGroupChangedObservation(value) {
|
|
692
774
|
this.storeRawPushObservation('_raw.group.changed', 'group', 'changed', value);
|
|
693
775
|
}
|
|
694
|
-
storeGroupChangedPublicEvent(value) {
|
|
776
|
+
storeGroupChangedPublicEvent(value, observationId = this.rawPushObservationId) {
|
|
695
777
|
const data = jsonObjectOf(value) ?? {};
|
|
696
778
|
this.groupChangedEvents.push({
|
|
697
|
-
observation_id:
|
|
779
|
+
observation_id: observationId,
|
|
698
780
|
time: Date.now(),
|
|
699
781
|
group_id: textOf(data.group_id),
|
|
700
782
|
action: textOf(data.action),
|
|
@@ -775,9 +857,12 @@ export class CrossSdkTsAgent {
|
|
|
775
857
|
}
|
|
776
858
|
}
|
|
777
859
|
else {
|
|
778
|
-
const
|
|
779
|
-
if (!
|
|
780
|
-
|
|
860
|
+
const local = store.load(this.aid);
|
|
861
|
+
if (!local.ok || !local.data.aid.isPrivateKeyValid()) {
|
|
862
|
+
const registered = await store.register(this.aid, { type: 'service', owner: textOf(process.env.AUN_TEST_OWNER_AID).trim() });
|
|
863
|
+
if (!registered.ok)
|
|
864
|
+
throw new Error(`${registered.error.code}: ${registered.error.message}`);
|
|
865
|
+
}
|
|
781
866
|
}
|
|
782
867
|
const loaded = store.load(this.aid);
|
|
783
868
|
if (!loaded.ok) {
|
|
@@ -812,7 +897,8 @@ export class CrossSdkTsAgent {
|
|
|
812
897
|
return;
|
|
813
898
|
}
|
|
814
899
|
try {
|
|
815
|
-
const
|
|
900
|
+
const options = body.batch_id === undefined ? [] : [{ batchId: body.batch_id }];
|
|
901
|
+
const task = role === 'owner' ? await this.client.bindSubaid(peerAid, ...options) : await this.client.bindOwneraid(peerAid, ...options);
|
|
816
902
|
sendJson(res, 200, { ok: true, operation_id: task.operation_id, task: jsonSafe(task) });
|
|
817
903
|
}
|
|
818
904
|
catch (err) {
|
|
@@ -826,15 +912,20 @@ export class CrossSdkTsAgent {
|
|
|
826
912
|
async ownershipAction(req, res, action) {
|
|
827
913
|
const body = await readJson(req);
|
|
828
914
|
const operationId = textOf(body.operation_id).trim(), subAid = textOf(body.sub_aid).trim(), newOwnerAid = textOf(body.new_owner_aid).trim();
|
|
829
|
-
if ((action === 'accept' || action === 'reject') ? !operationId : !subAid || action === 'transfer' && !newOwnerAid) {
|
|
915
|
+
if ((action === 'accept' || action === 'reject') ? !operationId && !Array.isArray(body.operation_ids) : !subAid || action === 'transfer' && !newOwnerAid) {
|
|
830
916
|
sendJson(res, 400, { ok: false, error_code: 'bad_request', error_message: action === 'accept' || action === 'reject' ? 'operation_id is required' : 'sub_aid and transfer new_owner_aid are required' });
|
|
831
917
|
return;
|
|
832
918
|
}
|
|
833
919
|
try {
|
|
920
|
+
if ((action === 'accept' || action === 'reject') && Array.isArray(body.operation_ids)) {
|
|
921
|
+
const report = action === 'accept' ? await this.client.acceptOwnershipRequests(body.operation_ids) : await this.client.rejectOwnershipRequests(body.operation_ids, body.reason);
|
|
922
|
+
sendJson(res, 200, { ok: true, report: jsonSafe(report) });
|
|
923
|
+
return;
|
|
924
|
+
}
|
|
834
925
|
const task = action === 'accept' ? await this.client.acceptOwnershipRequest(operationId)
|
|
835
926
|
: action === 'reject' ? await this.client.rejectOwnershipRequest(operationId, body.reason)
|
|
836
927
|
: action === 'release' ? await this.client.releaseSubaid(subAid)
|
|
837
|
-
: await this.client.transferSubaid(subAid, newOwnerAid);
|
|
928
|
+
: await this.client.transferSubaid(subAid, newOwnerAid, ...(body.batch_id === undefined ? [] : [{ batchId: body.batch_id }]));
|
|
838
929
|
sendJson(res, 200, { ok: true, operation_id: task.operation_id, task: jsonSafe(task) });
|
|
839
930
|
}
|
|
840
931
|
catch (err) {
|
|
@@ -928,6 +1019,8 @@ export class CrossSdkTsAgent {
|
|
|
928
1019
|
expires_at: Number(data.expires_at ?? 0) || 0,
|
|
929
1020
|
error_code: errorCode,
|
|
930
1021
|
raw_sha256: sha256Json(data),
|
|
1022
|
+
message_class: data.message_class ?? jsonObjectOf(data.protected_headers)?.message_class ?? 'normal',
|
|
1023
|
+
delivery_class: data.delivery_class ?? data.message_class ?? 'normal',
|
|
931
1024
|
...metadata,
|
|
932
1025
|
...(decrypted && jsonObjectOf(data._semantic_evidence) ? { _semantic_evidence: structuredClone(data._semantic_evidence) } : {}),
|
|
933
1026
|
};
|
|
@@ -950,6 +1043,8 @@ export class CrossSdkTsAgent {
|
|
|
950
1043
|
need_render: data.need_render !== false,
|
|
951
1044
|
error_code: errorCode,
|
|
952
1045
|
raw_sha256: sha256Json(data),
|
|
1046
|
+
message_class: data.message_class ?? jsonObjectOf(data.protected_headers)?.message_class ?? 'normal',
|
|
1047
|
+
delivery_class: data.delivery_class ?? data.message_class ?? 'normal',
|
|
953
1048
|
...metadata,
|
|
954
1049
|
...(decrypted && jsonObjectOf(data._semantic_evidence) ? { _semantic_evidence: structuredClone(data._semantic_evidence) } : {}),
|
|
955
1050
|
};
|
|
@@ -963,6 +1058,20 @@ export class CrossSdkTsAgent {
|
|
|
963
1058
|
async handle(req, res) {
|
|
964
1059
|
const url = new URL(req.url ?? '/', `http://${req.headers.host ?? 'localhost'}`);
|
|
965
1060
|
try {
|
|
1061
|
+
if (req.method === 'POST' && url.pathname === '/control/config') {
|
|
1062
|
+
const body = await readJson(req);
|
|
1063
|
+
this.messageClassesV2 = body.enabled !== false;
|
|
1064
|
+
await this.client.disconnect();
|
|
1065
|
+
await this.client.connect({ auto_reconnect: false, background_sync: true });
|
|
1066
|
+
sendJson(res, 200, { ok: true, requested_capabilities: this.controlAdvertisedCapabilities, negotiated_capabilities: this.controlNegotiatedCapabilities });
|
|
1067
|
+
return;
|
|
1068
|
+
}
|
|
1069
|
+
if (req.method === 'GET' && ['/capabilities', '/control/observations', '/control/state'].includes(url.pathname)) {
|
|
1070
|
+
sendJson(res, 200, { ok: true, enabled: this.messageClassesV2, advertised: this.controlAdvertisedCapabilities,
|
|
1071
|
+
requested_capabilities: this.controlAdvertisedCapabilities, negotiated_capabilities: this.controlNegotiatedCapabilities,
|
|
1072
|
+
wire_sends: this.controlWireSends, sdk_messages: this.sdkControlMessages });
|
|
1073
|
+
return;
|
|
1074
|
+
}
|
|
966
1075
|
if (req.method === 'GET' && url.pathname === '/health') {
|
|
967
1076
|
const state = textOf(this.client.state ?? this.client._state ?? '');
|
|
968
1077
|
sendJson(res, this.startupError ? 503 : 200, {
|
|
@@ -1151,6 +1260,17 @@ export class CrossSdkTsAgent {
|
|
|
1151
1260
|
await this.messageCall(req, res);
|
|
1152
1261
|
return;
|
|
1153
1262
|
}
|
|
1263
|
+
if (req.method === 'POST' && url.pathname === '/sync/channels/drop') {
|
|
1264
|
+
const body = await readJson(req);
|
|
1265
|
+
const connectionId = textOf(body.connection_id);
|
|
1266
|
+
const ok = await this.client._historyChannels().dropChannel(connectionId);
|
|
1267
|
+
sendJson(res, ok ? 200 : 404, { ok, connection_id: connectionId });
|
|
1268
|
+
return;
|
|
1269
|
+
}
|
|
1270
|
+
if (req.method === 'GET' && url.pathname === '/sync/channels/state') {
|
|
1271
|
+
sendJson(res, 200, { ...this.client._historyChannels().snapshot(), metrics: { rss_bytes: process.memoryUsage().rss } });
|
|
1272
|
+
return;
|
|
1273
|
+
}
|
|
1154
1274
|
if (req.method === 'GET' && url.pathname === '/sync/state') {
|
|
1155
1275
|
this.syncState(url, res);
|
|
1156
1276
|
return;
|
|
@@ -1387,6 +1507,11 @@ export class CrossSdkTsAgent {
|
|
|
1387
1507
|
};
|
|
1388
1508
|
if (body.ttl !== undefined)
|
|
1389
1509
|
params.ttl = Number(body.ttl);
|
|
1510
|
+
if (jsonObjectOf(body.payload))
|
|
1511
|
+
params.payload = { ...jsonObjectOf(body.payload), trace_id: traceId };
|
|
1512
|
+
for (const key of ['message_class', 'sdk_control_protocol', 'sdk_control_version', 'protected_headers'])
|
|
1513
|
+
if (key in body)
|
|
1514
|
+
params[key] = body[key];
|
|
1390
1515
|
if (body.need_render !== undefined)
|
|
1391
1516
|
params.need_render = body.need_render;
|
|
1392
1517
|
try {
|
|
@@ -1531,6 +1656,7 @@ export class CrossSdkTsAgent {
|
|
|
1531
1656
|
error_code: err instanceof Error ? err.name : 'Error',
|
|
1532
1657
|
error_message: err instanceof Error ? err.message : String(err),
|
|
1533
1658
|
};
|
|
1659
|
+
error.rpc_error_code = err?.code ?? null;
|
|
1534
1660
|
this.recordTrace(traceId, { stage: 'message_call_error', method, error });
|
|
1535
1661
|
sendJson(res, 500, error);
|
|
1536
1662
|
}
|
|
@@ -1579,7 +1705,7 @@ export class CrossSdkTsAgent {
|
|
|
1579
1705
|
const afterSeq = Number(body.after_seq ?? 0) || 0;
|
|
1580
1706
|
const limit = Number(body.limit ?? 50) || 50;
|
|
1581
1707
|
try {
|
|
1582
|
-
const params = { limit,
|
|
1708
|
+
const params = { limit, ...(tail ? { window_mode: 'tail' } : {}) };
|
|
1583
1709
|
if (scope === 'group' || body.after_seq !== undefined)
|
|
1584
1710
|
params.after_seq = afterSeq;
|
|
1585
1711
|
if (scope === 'p2p' && senderAid)
|
|
@@ -1679,11 +1805,13 @@ export class CrossSdkTsAgent {
|
|
|
1679
1805
|
}
|
|
1680
1806
|
async sessionConnect(req, res) {
|
|
1681
1807
|
const body = await readJson(req);
|
|
1682
|
-
if (['background_sync', 'inline_realtime_payload_v1', 'batch_events'].some((key) => body[key] !== undefined && typeof body[key] !== 'boolean')) {
|
|
1808
|
+
if (['background_sync', 'inline_realtime_payload_v1', 'batch_events', 'message_classes_v2'].some((key) => body[key] !== undefined && typeof body[key] !== 'boolean')) {
|
|
1683
1809
|
sendJson(res, 400, { ok: false, error_code: 'bad_request', error_message: 'invalid session parameters' });
|
|
1684
1810
|
return;
|
|
1685
1811
|
}
|
|
1686
1812
|
const backgroundSync = body.background_sync === true;
|
|
1813
|
+
if (typeof body.message_classes_v2 === 'boolean')
|
|
1814
|
+
this.messageClassesV2 = body.message_classes_v2;
|
|
1687
1815
|
if (Object.prototype.hasOwnProperty.call(body, 'inline_realtime_payload_v1')) {
|
|
1688
1816
|
this.inlineRealtimePayloadV1 = body.inline_realtime_payload_v1 !== false;
|
|
1689
1817
|
}
|
|
@@ -1703,11 +1831,13 @@ export class CrossSdkTsAgent {
|
|
|
1703
1831
|
}
|
|
1704
1832
|
async sessionRestart(req, res) {
|
|
1705
1833
|
const body = await readJson(req);
|
|
1706
|
-
if (['background_sync', 'inline_realtime_payload_v1', 'batch_events'].some((key) => body[key] !== undefined && typeof body[key] !== 'boolean')) {
|
|
1834
|
+
if (['background_sync', 'inline_realtime_payload_v1', 'batch_events', 'message_classes_v2'].some((key) => body[key] !== undefined && typeof body[key] !== 'boolean')) {
|
|
1707
1835
|
sendJson(res, 400, { ok: false, error_code: 'bad_request', error_message: 'invalid session parameters' });
|
|
1708
1836
|
return;
|
|
1709
1837
|
}
|
|
1710
1838
|
const backgroundSync = body.background_sync === true;
|
|
1839
|
+
if (typeof body.message_classes_v2 === 'boolean')
|
|
1840
|
+
this.messageClassesV2 = body.message_classes_v2;
|
|
1711
1841
|
if (Object.prototype.hasOwnProperty.call(body, 'inline_realtime_payload_v1')) {
|
|
1712
1842
|
this.inlineRealtimePayloadV1 = body.inline_realtime_payload_v1 !== false;
|
|
1713
1843
|
}
|
|
@@ -2441,6 +2571,7 @@ export class CrossSdkTsAgent {
|
|
|
2441
2571
|
error_code: err instanceof Error ? err.name : 'Error',
|
|
2442
2572
|
error_message: err instanceof Error ? err.message : String(err),
|
|
2443
2573
|
};
|
|
2574
|
+
error.rpc_error_code = err?.code ?? null;
|
|
2444
2575
|
this.recordTrace(traceId, { stage: 'storage_call_error', action, error });
|
|
2445
2576
|
sendJson(res, 500, error);
|
|
2446
2577
|
}
|
|
@@ -2832,7 +2963,7 @@ export class CrossSdkTsAgent {
|
|
|
2832
2963
|
return await storage.setAcl(path, {
|
|
2833
2964
|
owner,
|
|
2834
2965
|
bucket,
|
|
2835
|
-
|
|
2966
|
+
...storageAclTargets(params),
|
|
2836
2967
|
perms: textOf(params.perms).trim(),
|
|
2837
2968
|
expiresAt: params.expires_at == null && params.expiresAt == null ? undefined : Number(params.expires_at ?? params.expiresAt),
|
|
2838
2969
|
maxUses: params.max_uses == null && params.maxUses == null ? undefined : Number(params.max_uses ?? params.maxUses),
|
|
@@ -2841,7 +2972,7 @@ export class CrossSdkTsAgent {
|
|
|
2841
2972
|
return await storage.removeAcl(path, {
|
|
2842
2973
|
owner,
|
|
2843
2974
|
bucket,
|
|
2844
|
-
|
|
2975
|
+
...storageAclTargets(params),
|
|
2845
2976
|
});
|
|
2846
2977
|
case 'list':
|
|
2847
2978
|
return await storage.list(path, {
|
|
@@ -3127,10 +3258,11 @@ export class CrossSdkTsAgent {
|
|
|
3127
3258
|
try {
|
|
3128
3259
|
const result = await this.client.call('group.send', {
|
|
3129
3260
|
group_id: groupId,
|
|
3130
|
-
payload,
|
|
3261
|
+
payload: jsonObjectOf(body.payload) ? { ...jsonObjectOf(body.payload), trace_id: traceId } : payload,
|
|
3131
3262
|
encrypt: e2ee,
|
|
3132
3263
|
message_id: messageId,
|
|
3133
3264
|
...(body.need_render !== undefined ? { need_render: body.need_render } : {}),
|
|
3265
|
+
...Object.fromEntries(['message_class', 'ttl', 'sdk_control_protocol', 'sdk_control_version', 'protected_headers'].filter(key => key in body).map(key => [key, body[key]])),
|
|
3134
3266
|
});
|
|
3135
3267
|
const resultObj = result && typeof result === 'object' && !Array.isArray(result) ? result : {};
|
|
3136
3268
|
const response = {
|