chainlesschain 0.66.0 → 0.132.0
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/bin/chainlesschain.js +0 -0
- package/package.json +1 -1
- package/src/commands/a2a.js +380 -0
- package/src/commands/agent-network.js +254 -1
- package/src/commands/audit.js +302 -0
- package/src/commands/automation.js +271 -1
- package/src/commands/bi.js +348 -0
- package/src/commands/codegen.js +224 -0
- package/src/commands/collab.js +341 -0
- package/src/commands/compliance.js +1035 -0
- package/src/commands/cowork.js +221 -0
- package/src/commands/crosschain.js +218 -0
- package/src/commands/dbevo.js +284 -0
- package/src/commands/dev.js +252 -0
- package/src/commands/did.js +358 -0
- package/src/commands/dlp.js +341 -0
- package/src/commands/encrypt.js +341 -0
- package/src/commands/evomap.js +394 -0
- package/src/commands/export.js +256 -1
- package/src/commands/federation.js +283 -0
- package/src/commands/fusion.js +258 -0
- package/src/commands/governance.js +325 -0
- package/src/commands/hardening.js +411 -0
- package/src/commands/hook.js +148 -0
- package/src/commands/import.js +252 -0
- package/src/commands/incentive.js +322 -0
- package/src/commands/inference.js +318 -0
- package/src/commands/infra.js +244 -0
- package/src/commands/instinct.js +260 -0
- package/src/commands/ipfs.js +318 -0
- package/src/commands/kg.js +387 -0
- package/src/commands/llm.js +263 -0
- package/src/commands/lowcode.js +356 -0
- package/src/commands/marketplace.js +256 -0
- package/src/commands/mcp.js +221 -0
- package/src/commands/memory.js +248 -0
- package/src/commands/multimodal.js +296 -0
- package/src/commands/nlprog.js +356 -0
- package/src/commands/note.js +244 -0
- package/src/commands/ops.js +354 -0
- package/src/commands/orchestrate.js +166 -0
- package/src/commands/org.js +277 -0
- package/src/commands/p2p.js +390 -0
- package/src/commands/perception.js +290 -0
- package/src/commands/permmem.js +251 -0
- package/src/commands/plugin-ecosystem.js +273 -0
- package/src/commands/pqc.js +393 -0
- package/src/commands/privacy.js +321 -0
- package/src/commands/quantization.js +351 -0
- package/src/commands/rcache.js +271 -0
- package/src/commands/recommend.js +340 -0
- package/src/commands/reputation.js +261 -0
- package/src/commands/runtime.js +307 -0
- package/src/commands/scim.js +262 -0
- package/src/commands/session.js +258 -0
- package/src/commands/siem.js +246 -0
- package/src/commands/skill.js +267 -1
- package/src/commands/sla.js +259 -0
- package/src/commands/social.js +256 -0
- package/src/commands/sso.js +186 -1
- package/src/commands/stress.js +230 -0
- package/src/commands/sync.js +256 -0
- package/src/commands/tech.js +338 -0
- package/src/commands/tenant.js +351 -0
- package/src/commands/terraform.js +245 -0
- package/src/commands/tokens.js +269 -0
- package/src/commands/trust.js +249 -0
- package/src/commands/wallet.js +277 -0
- package/src/commands/workflow.js +171 -0
- package/src/commands/zkp.js +335 -0
- package/src/index.js +4 -0
- package/src/lib/a2a-protocol.js +451 -0
- package/src/lib/agent-coordinator.js +325 -0
- package/src/lib/agent-network.js +387 -0
- package/src/lib/agent-router.js +395 -0
- package/src/lib/aiops.js +478 -0
- package/src/lib/app-builder.js +239 -0
- package/src/lib/audit-logger.js +379 -0
- package/src/lib/automation-engine.js +330 -0
- package/src/lib/autonomous-developer.js +350 -0
- package/src/lib/bi-engine.js +338 -0
- package/src/lib/code-agent.js +323 -0
- package/src/lib/collaboration-governance.js +364 -0
- package/src/lib/community-governance.js +436 -0
- package/src/lib/compliance-manager.js +434 -0
- package/src/lib/content-recommendation.js +469 -0
- package/src/lib/cross-chain.js +345 -0
- package/src/lib/crypto-manager.js +350 -0
- package/src/lib/dbevo.js +338 -0
- package/src/lib/decentral-infra.js +340 -0
- package/src/lib/did-manager.js +367 -0
- package/src/lib/dlp-engine.js +389 -0
- package/src/lib/evomap-federation.js +177 -0
- package/src/lib/evomap-governance.js +276 -0
- package/src/lib/federation-hardening.js +259 -0
- package/src/lib/hardening-manager.js +348 -0
- package/src/lib/hook-manager.js +380 -0
- package/src/lib/inference-network.js +330 -0
- package/src/lib/instinct-manager.js +332 -0
- package/src/lib/ipfs-storage.js +334 -0
- package/src/lib/knowledge-exporter.js +381 -0
- package/src/lib/knowledge-graph.js +432 -0
- package/src/lib/knowledge-importer.js +379 -0
- package/src/lib/llm-providers.js +391 -0
- package/src/lib/mcp-registry.js +333 -0
- package/src/lib/memory-manager.js +330 -0
- package/src/lib/multimodal.js +346 -0
- package/src/lib/nl-programming.js +343 -0
- package/src/lib/note-versioning.js +327 -0
- package/src/lib/org-manager.js +323 -0
- package/src/lib/p2p-manager.js +387 -0
- package/src/lib/perception.js +346 -0
- package/src/lib/perf-tuning.js +4 -1
- package/src/lib/permanent-memory.js +320 -0
- package/src/lib/plugin-ecosystem.js +377 -0
- package/src/lib/pqc-manager.js +368 -0
- package/src/lib/privacy-computing.js +427 -0
- package/src/lib/protocol-fusion.js +417 -0
- package/src/lib/quantization.js +325 -0
- package/src/lib/reputation-optimizer.js +299 -0
- package/src/lib/response-cache.js +327 -0
- package/src/lib/scim-manager.js +329 -0
- package/src/lib/session-manager.js +329 -0
- package/src/lib/siem-exporter.js +333 -0
- package/src/lib/skill-loader.js +377 -0
- package/src/lib/skill-marketplace.js +325 -0
- package/src/lib/sla-manager.js +275 -0
- package/src/lib/social-manager.js +326 -0
- package/src/lib/sso-manager.js +332 -0
- package/src/lib/stress-tester.js +330 -0
- package/src/lib/sync-manager.js +326 -0
- package/src/lib/tech-learning-engine.js +369 -0
- package/src/lib/tenant-saas.js +460 -0
- package/src/lib/terraform-manager.js +363 -0
- package/src/lib/threat-intel.js +335 -0
- package/src/lib/token-incentive.js +293 -0
- package/src/lib/token-tracker.js +329 -0
- package/src/lib/trust-security.js +390 -0
- package/src/lib/ueba.js +389 -0
- package/src/lib/universal-runtime.js +325 -0
- package/src/lib/wallet-manager.js +326 -0
- package/src/lib/workflow-engine.js +322 -0
- package/src/lib/zkp-engine.js +274 -0
package/src/lib/p2p-manager.js
CHANGED
|
@@ -315,3 +315,390 @@ export class P2PBridge extends EventEmitter {
|
|
|
315
315
|
};
|
|
316
316
|
}
|
|
317
317
|
}
|
|
318
|
+
|
|
319
|
+
/* ─────────────────────────────────────────────────────────────────
|
|
320
|
+
* V2 Governance Layer (in-memory, independent of SQLite p2p tables)
|
|
321
|
+
*
|
|
322
|
+
* Peer maturity: pending → active → offline → archived
|
|
323
|
+
* - archived terminal
|
|
324
|
+
* - offline → active recovery (cap-exempt)
|
|
325
|
+
*
|
|
326
|
+
* Message lifecycle: queued → sending → delivered | failed | cancelled
|
|
327
|
+
* - 3 terminals
|
|
328
|
+
* - per-peer pending-message cap counts queued+sending
|
|
329
|
+
*
|
|
330
|
+
* Per-network active-peer cap on pending→active only (recovery exempt).
|
|
331
|
+
* Per-peer pending-message cap enforced at createMessageV2.
|
|
332
|
+
*
|
|
333
|
+
* Auto-flip:
|
|
334
|
+
* - autoOfflineIdlePeersV2 active w/ lastSeenAt past idle threshold → offline
|
|
335
|
+
* - autoFailStuckMessagesV2 sending w/ startedAt past stuck threshold → failed
|
|
336
|
+
* ───────────────────────────────────────────────────────────────── */
|
|
337
|
+
|
|
338
|
+
export const PEER_MATURITY_V2 = Object.freeze({
|
|
339
|
+
PENDING: "pending",
|
|
340
|
+
ACTIVE: "active",
|
|
341
|
+
OFFLINE: "offline",
|
|
342
|
+
ARCHIVED: "archived",
|
|
343
|
+
});
|
|
344
|
+
|
|
345
|
+
export const MESSAGE_LIFECYCLE_V2 = Object.freeze({
|
|
346
|
+
QUEUED: "queued",
|
|
347
|
+
SENDING: "sending",
|
|
348
|
+
DELIVERED: "delivered",
|
|
349
|
+
FAILED: "failed",
|
|
350
|
+
CANCELLED: "cancelled",
|
|
351
|
+
});
|
|
352
|
+
|
|
353
|
+
const _PEER_TRANSITIONS_V2 = new Map([
|
|
354
|
+
[
|
|
355
|
+
PEER_MATURITY_V2.PENDING,
|
|
356
|
+
new Set([PEER_MATURITY_V2.ACTIVE, PEER_MATURITY_V2.ARCHIVED]),
|
|
357
|
+
],
|
|
358
|
+
[
|
|
359
|
+
PEER_MATURITY_V2.ACTIVE,
|
|
360
|
+
new Set([PEER_MATURITY_V2.OFFLINE, PEER_MATURITY_V2.ARCHIVED]),
|
|
361
|
+
],
|
|
362
|
+
[
|
|
363
|
+
PEER_MATURITY_V2.OFFLINE,
|
|
364
|
+
new Set([PEER_MATURITY_V2.ACTIVE, PEER_MATURITY_V2.ARCHIVED]),
|
|
365
|
+
],
|
|
366
|
+
[PEER_MATURITY_V2.ARCHIVED, new Set()],
|
|
367
|
+
]);
|
|
368
|
+
const _PEER_TERMINALS_V2 = new Set([PEER_MATURITY_V2.ARCHIVED]);
|
|
369
|
+
|
|
370
|
+
const _MSG_TRANSITIONS_V2 = new Map([
|
|
371
|
+
[
|
|
372
|
+
MESSAGE_LIFECYCLE_V2.QUEUED,
|
|
373
|
+
new Set([MESSAGE_LIFECYCLE_V2.SENDING, MESSAGE_LIFECYCLE_V2.CANCELLED]),
|
|
374
|
+
],
|
|
375
|
+
[
|
|
376
|
+
MESSAGE_LIFECYCLE_V2.SENDING,
|
|
377
|
+
new Set([
|
|
378
|
+
MESSAGE_LIFECYCLE_V2.DELIVERED,
|
|
379
|
+
MESSAGE_LIFECYCLE_V2.FAILED,
|
|
380
|
+
MESSAGE_LIFECYCLE_V2.CANCELLED,
|
|
381
|
+
]),
|
|
382
|
+
],
|
|
383
|
+
[MESSAGE_LIFECYCLE_V2.DELIVERED, new Set()],
|
|
384
|
+
[MESSAGE_LIFECYCLE_V2.FAILED, new Set()],
|
|
385
|
+
[MESSAGE_LIFECYCLE_V2.CANCELLED, new Set()],
|
|
386
|
+
]);
|
|
387
|
+
const _MSG_TERMINALS_V2 = new Set([
|
|
388
|
+
MESSAGE_LIFECYCLE_V2.DELIVERED,
|
|
389
|
+
MESSAGE_LIFECYCLE_V2.FAILED,
|
|
390
|
+
MESSAGE_LIFECYCLE_V2.CANCELLED,
|
|
391
|
+
]);
|
|
392
|
+
|
|
393
|
+
export const PEER_DEFAULT_MAX_ACTIVE_PER_NETWORK = 100;
|
|
394
|
+
export const PEER_DEFAULT_MAX_PENDING_MESSAGES_PER_PEER = 50;
|
|
395
|
+
export const PEER_DEFAULT_PEER_IDLE_MS = 10 * 60 * 1000;
|
|
396
|
+
export const PEER_DEFAULT_MESSAGE_STUCK_MS = 60 * 1000;
|
|
397
|
+
|
|
398
|
+
const _stateP2pV2 = {
|
|
399
|
+
peers: new Map(),
|
|
400
|
+
messages: new Map(),
|
|
401
|
+
maxActivePeersPerNetwork: PEER_DEFAULT_MAX_ACTIVE_PER_NETWORK,
|
|
402
|
+
maxPendingMessagesPerPeer: PEER_DEFAULT_MAX_PENDING_MESSAGES_PER_PEER,
|
|
403
|
+
peerIdleMs: PEER_DEFAULT_PEER_IDLE_MS,
|
|
404
|
+
messageStuckMs: PEER_DEFAULT_MESSAGE_STUCK_MS,
|
|
405
|
+
};
|
|
406
|
+
|
|
407
|
+
function _posIntP2pV2(n, label) {
|
|
408
|
+
const v = Math.floor(n);
|
|
409
|
+
if (!Number.isFinite(v) || v <= 0) {
|
|
410
|
+
throw new Error(`${label} must be a positive integer`);
|
|
411
|
+
}
|
|
412
|
+
return v;
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
function _copyPeerV2(p) {
|
|
416
|
+
return { ...p, metadata: { ...p.metadata } };
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
function _copyMsgV2(m) {
|
|
420
|
+
return { ...m, metadata: { ...m.metadata } };
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
export function getMaxActivePeersPerNetworkV2() {
|
|
424
|
+
return _stateP2pV2.maxActivePeersPerNetwork;
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
export function setMaxActivePeersPerNetworkV2(n) {
|
|
428
|
+
_stateP2pV2.maxActivePeersPerNetwork = _posIntP2pV2(
|
|
429
|
+
n,
|
|
430
|
+
"maxActivePeersPerNetwork",
|
|
431
|
+
);
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
export function getMaxPendingMessagesPerPeerV2() {
|
|
435
|
+
return _stateP2pV2.maxPendingMessagesPerPeer;
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
export function setMaxPendingMessagesPerPeerV2(n) {
|
|
439
|
+
_stateP2pV2.maxPendingMessagesPerPeer = _posIntP2pV2(
|
|
440
|
+
n,
|
|
441
|
+
"maxPendingMessagesPerPeer",
|
|
442
|
+
);
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
export function getPeerIdleMsV2() {
|
|
446
|
+
return _stateP2pV2.peerIdleMs;
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
export function setPeerIdleMsV2(ms) {
|
|
450
|
+
_stateP2pV2.peerIdleMs = _posIntP2pV2(ms, "peerIdleMs");
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
export function getMessageStuckMsV2() {
|
|
454
|
+
return _stateP2pV2.messageStuckMs;
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
export function setMessageStuckMsV2(ms) {
|
|
458
|
+
_stateP2pV2.messageStuckMs = _posIntP2pV2(ms, "messageStuckMs");
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
export function getActivePeerCountV2(networkId) {
|
|
462
|
+
let count = 0;
|
|
463
|
+
for (const p of _stateP2pV2.peers.values()) {
|
|
464
|
+
if (p.networkId === networkId && p.status === PEER_MATURITY_V2.ACTIVE) {
|
|
465
|
+
count++;
|
|
466
|
+
}
|
|
467
|
+
}
|
|
468
|
+
return count;
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
export function getPendingMessageCountV2(peerId) {
|
|
472
|
+
let count = 0;
|
|
473
|
+
for (const m of _stateP2pV2.messages.values()) {
|
|
474
|
+
if (
|
|
475
|
+
m.peerId === peerId &&
|
|
476
|
+
(m.status === MESSAGE_LIFECYCLE_V2.QUEUED ||
|
|
477
|
+
m.status === MESSAGE_LIFECYCLE_V2.SENDING)
|
|
478
|
+
) {
|
|
479
|
+
count++;
|
|
480
|
+
}
|
|
481
|
+
}
|
|
482
|
+
return count;
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
export function registerPeerV2(
|
|
486
|
+
id,
|
|
487
|
+
{ networkId, deviceName, deviceType, metadata } = {},
|
|
488
|
+
) {
|
|
489
|
+
if (!id) throw new Error("peer id is required");
|
|
490
|
+
if (!networkId) throw new Error("networkId is required");
|
|
491
|
+
if (_stateP2pV2.peers.has(id)) throw new Error(`peer ${id} already exists`);
|
|
492
|
+
const now = Date.now();
|
|
493
|
+
const peer = {
|
|
494
|
+
id,
|
|
495
|
+
networkId,
|
|
496
|
+
deviceName: deviceName || id,
|
|
497
|
+
deviceType: deviceType || "desktop",
|
|
498
|
+
status: PEER_MATURITY_V2.PENDING,
|
|
499
|
+
createdAt: now,
|
|
500
|
+
lastSeenAt: now,
|
|
501
|
+
activatedAt: null,
|
|
502
|
+
archivedAt: null,
|
|
503
|
+
metadata: metadata ? { ...metadata } : {},
|
|
504
|
+
};
|
|
505
|
+
_stateP2pV2.peers.set(id, peer);
|
|
506
|
+
return _copyPeerV2(peer);
|
|
507
|
+
}
|
|
508
|
+
|
|
509
|
+
export function getPeerV2(id) {
|
|
510
|
+
const p = _stateP2pV2.peers.get(id);
|
|
511
|
+
return p ? _copyPeerV2(p) : null;
|
|
512
|
+
}
|
|
513
|
+
|
|
514
|
+
export function listPeersV2({ networkId, status, deviceType } = {}) {
|
|
515
|
+
const out = [];
|
|
516
|
+
for (const p of _stateP2pV2.peers.values()) {
|
|
517
|
+
if (networkId && p.networkId !== networkId) continue;
|
|
518
|
+
if (status && p.status !== status) continue;
|
|
519
|
+
if (deviceType && p.deviceType !== deviceType) continue;
|
|
520
|
+
out.push(_copyPeerV2(p));
|
|
521
|
+
}
|
|
522
|
+
return out;
|
|
523
|
+
}
|
|
524
|
+
|
|
525
|
+
export function setPeerStatusV2(id, next) {
|
|
526
|
+
const p = _stateP2pV2.peers.get(id);
|
|
527
|
+
if (!p) throw new Error(`peer ${id} not found`);
|
|
528
|
+
const allowed = _PEER_TRANSITIONS_V2.get(p.status);
|
|
529
|
+
if (!allowed || !allowed.has(next)) {
|
|
530
|
+
throw new Error(`invalid peer transition: ${p.status} → ${next}`);
|
|
531
|
+
}
|
|
532
|
+
if (
|
|
533
|
+
p.status === PEER_MATURITY_V2.PENDING &&
|
|
534
|
+
next === PEER_MATURITY_V2.ACTIVE
|
|
535
|
+
) {
|
|
536
|
+
const count = getActivePeerCountV2(p.networkId);
|
|
537
|
+
if (count >= _stateP2pV2.maxActivePeersPerNetwork) {
|
|
538
|
+
throw new Error(
|
|
539
|
+
`network ${p.networkId} active-peer cap reached (${count}/${_stateP2pV2.maxActivePeersPerNetwork})`,
|
|
540
|
+
);
|
|
541
|
+
}
|
|
542
|
+
}
|
|
543
|
+
const now = Date.now();
|
|
544
|
+
p.status = next;
|
|
545
|
+
p.lastSeenAt = now;
|
|
546
|
+
if (next === PEER_MATURITY_V2.ACTIVE && !p.activatedAt) p.activatedAt = now;
|
|
547
|
+
if (_PEER_TERMINALS_V2.has(next) && !p.archivedAt) p.archivedAt = now;
|
|
548
|
+
return _copyPeerV2(p);
|
|
549
|
+
}
|
|
550
|
+
|
|
551
|
+
export function activatePeerV2(id) {
|
|
552
|
+
return setPeerStatusV2(id, PEER_MATURITY_V2.ACTIVE);
|
|
553
|
+
}
|
|
554
|
+
|
|
555
|
+
export function offlinePeerV2(id) {
|
|
556
|
+
return setPeerStatusV2(id, PEER_MATURITY_V2.OFFLINE);
|
|
557
|
+
}
|
|
558
|
+
|
|
559
|
+
export function archivePeerV2(id) {
|
|
560
|
+
return setPeerStatusV2(id, PEER_MATURITY_V2.ARCHIVED);
|
|
561
|
+
}
|
|
562
|
+
|
|
563
|
+
export function touchPeerV2(id) {
|
|
564
|
+
const p = _stateP2pV2.peers.get(id);
|
|
565
|
+
if (!p) throw new Error(`peer ${id} not found`);
|
|
566
|
+
p.lastSeenAt = Date.now();
|
|
567
|
+
return _copyPeerV2(p);
|
|
568
|
+
}
|
|
569
|
+
|
|
570
|
+
export function createMessageV2(id, { peerId, kind, metadata } = {}) {
|
|
571
|
+
if (!id) throw new Error("message id is required");
|
|
572
|
+
if (!peerId) throw new Error("peerId is required");
|
|
573
|
+
if (_stateP2pV2.messages.has(id))
|
|
574
|
+
throw new Error(`message ${id} already exists`);
|
|
575
|
+
const peer = _stateP2pV2.peers.get(peerId);
|
|
576
|
+
if (!peer) throw new Error(`peer ${peerId} not found`);
|
|
577
|
+
const pending = getPendingMessageCountV2(peerId);
|
|
578
|
+
if (pending >= _stateP2pV2.maxPendingMessagesPerPeer) {
|
|
579
|
+
throw new Error(
|
|
580
|
+
`peer ${peerId} pending-message cap reached (${pending}/${_stateP2pV2.maxPendingMessagesPerPeer})`,
|
|
581
|
+
);
|
|
582
|
+
}
|
|
583
|
+
const now = Date.now();
|
|
584
|
+
const msg = {
|
|
585
|
+
id,
|
|
586
|
+
peerId,
|
|
587
|
+
kind: kind || "text",
|
|
588
|
+
status: MESSAGE_LIFECYCLE_V2.QUEUED,
|
|
589
|
+
createdAt: now,
|
|
590
|
+
lastSeenAt: now,
|
|
591
|
+
startedAt: null,
|
|
592
|
+
settledAt: null,
|
|
593
|
+
metadata: metadata ? { ...metadata } : {},
|
|
594
|
+
};
|
|
595
|
+
_stateP2pV2.messages.set(id, msg);
|
|
596
|
+
return _copyMsgV2(msg);
|
|
597
|
+
}
|
|
598
|
+
|
|
599
|
+
export function getMessageV2(id) {
|
|
600
|
+
const m = _stateP2pV2.messages.get(id);
|
|
601
|
+
return m ? _copyMsgV2(m) : null;
|
|
602
|
+
}
|
|
603
|
+
|
|
604
|
+
export function listMessagesV2({ peerId, status } = {}) {
|
|
605
|
+
const out = [];
|
|
606
|
+
for (const m of _stateP2pV2.messages.values()) {
|
|
607
|
+
if (peerId && m.peerId !== peerId) continue;
|
|
608
|
+
if (status && m.status !== status) continue;
|
|
609
|
+
out.push(_copyMsgV2(m));
|
|
610
|
+
}
|
|
611
|
+
return out;
|
|
612
|
+
}
|
|
613
|
+
|
|
614
|
+
export function setMessageStatusV2(id, next) {
|
|
615
|
+
const m = _stateP2pV2.messages.get(id);
|
|
616
|
+
if (!m) throw new Error(`message ${id} not found`);
|
|
617
|
+
const allowed = _MSG_TRANSITIONS_V2.get(m.status);
|
|
618
|
+
if (!allowed || !allowed.has(next)) {
|
|
619
|
+
throw new Error(`invalid message transition: ${m.status} → ${next}`);
|
|
620
|
+
}
|
|
621
|
+
const now = Date.now();
|
|
622
|
+
m.status = next;
|
|
623
|
+
m.lastSeenAt = now;
|
|
624
|
+
if (next === MESSAGE_LIFECYCLE_V2.SENDING && !m.startedAt) m.startedAt = now;
|
|
625
|
+
if (_MSG_TERMINALS_V2.has(next) && !m.settledAt) m.settledAt = now;
|
|
626
|
+
return _copyMsgV2(m);
|
|
627
|
+
}
|
|
628
|
+
|
|
629
|
+
export function startMessageV2(id) {
|
|
630
|
+
return setMessageStatusV2(id, MESSAGE_LIFECYCLE_V2.SENDING);
|
|
631
|
+
}
|
|
632
|
+
|
|
633
|
+
export function deliverMessageV2(id) {
|
|
634
|
+
return setMessageStatusV2(id, MESSAGE_LIFECYCLE_V2.DELIVERED);
|
|
635
|
+
}
|
|
636
|
+
|
|
637
|
+
export function failMessageV2(id) {
|
|
638
|
+
return setMessageStatusV2(id, MESSAGE_LIFECYCLE_V2.FAILED);
|
|
639
|
+
}
|
|
640
|
+
|
|
641
|
+
export function cancelMessageV2(id) {
|
|
642
|
+
return setMessageStatusV2(id, MESSAGE_LIFECYCLE_V2.CANCELLED);
|
|
643
|
+
}
|
|
644
|
+
|
|
645
|
+
export function autoOfflineIdlePeersV2({ now = Date.now() } = {}) {
|
|
646
|
+
const flipped = [];
|
|
647
|
+
for (const p of _stateP2pV2.peers.values()) {
|
|
648
|
+
if (
|
|
649
|
+
p.status === PEER_MATURITY_V2.ACTIVE &&
|
|
650
|
+
now - p.lastSeenAt >= _stateP2pV2.peerIdleMs
|
|
651
|
+
) {
|
|
652
|
+
p.status = PEER_MATURITY_V2.OFFLINE;
|
|
653
|
+
p.lastSeenAt = now;
|
|
654
|
+
flipped.push(p.id);
|
|
655
|
+
}
|
|
656
|
+
}
|
|
657
|
+
return { flipped, count: flipped.length };
|
|
658
|
+
}
|
|
659
|
+
|
|
660
|
+
export function autoFailStuckMessagesV2({ now = Date.now() } = {}) {
|
|
661
|
+
const flipped = [];
|
|
662
|
+
for (const m of _stateP2pV2.messages.values()) {
|
|
663
|
+
if (
|
|
664
|
+
m.status === MESSAGE_LIFECYCLE_V2.SENDING &&
|
|
665
|
+
m.startedAt &&
|
|
666
|
+
now - m.startedAt >= _stateP2pV2.messageStuckMs
|
|
667
|
+
) {
|
|
668
|
+
m.status = MESSAGE_LIFECYCLE_V2.FAILED;
|
|
669
|
+
m.lastSeenAt = now;
|
|
670
|
+
if (!m.settledAt) m.settledAt = now;
|
|
671
|
+
flipped.push(m.id);
|
|
672
|
+
}
|
|
673
|
+
}
|
|
674
|
+
return { flipped, count: flipped.length };
|
|
675
|
+
}
|
|
676
|
+
|
|
677
|
+
export function getP2pManagerStatsV2() {
|
|
678
|
+
const peersByStatus = {};
|
|
679
|
+
for (const s of Object.values(PEER_MATURITY_V2)) peersByStatus[s] = 0;
|
|
680
|
+
for (const p of _stateP2pV2.peers.values()) peersByStatus[p.status]++;
|
|
681
|
+
const messagesByStatus = {};
|
|
682
|
+
for (const s of Object.values(MESSAGE_LIFECYCLE_V2)) messagesByStatus[s] = 0;
|
|
683
|
+
for (const m of _stateP2pV2.messages.values()) messagesByStatus[m.status]++;
|
|
684
|
+
return {
|
|
685
|
+
totalPeersV2: _stateP2pV2.peers.size,
|
|
686
|
+
totalMessagesV2: _stateP2pV2.messages.size,
|
|
687
|
+
maxActivePeersPerNetwork: _stateP2pV2.maxActivePeersPerNetwork,
|
|
688
|
+
maxPendingMessagesPerPeer: _stateP2pV2.maxPendingMessagesPerPeer,
|
|
689
|
+
peerIdleMs: _stateP2pV2.peerIdleMs,
|
|
690
|
+
messageStuckMs: _stateP2pV2.messageStuckMs,
|
|
691
|
+
peersByStatus,
|
|
692
|
+
messagesByStatus,
|
|
693
|
+
};
|
|
694
|
+
}
|
|
695
|
+
|
|
696
|
+
export function _resetStateP2pManagerV2() {
|
|
697
|
+
_stateP2pV2.peers.clear();
|
|
698
|
+
_stateP2pV2.messages.clear();
|
|
699
|
+
_stateP2pV2.maxActivePeersPerNetwork = PEER_DEFAULT_MAX_ACTIVE_PER_NETWORK;
|
|
700
|
+
_stateP2pV2.maxPendingMessagesPerPeer =
|
|
701
|
+
PEER_DEFAULT_MAX_PENDING_MESSAGES_PER_PEER;
|
|
702
|
+
_stateP2pV2.peerIdleMs = PEER_DEFAULT_PEER_IDLE_MS;
|
|
703
|
+
_stateP2pV2.messageStuckMs = PEER_DEFAULT_MESSAGE_STUCK_MS;
|
|
704
|
+
}
|