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/mcp-registry.js
CHANGED
|
@@ -345,3 +345,336 @@ export function getServer(idOrName) {
|
|
|
345
345
|
) || null
|
|
346
346
|
);
|
|
347
347
|
}
|
|
348
|
+
|
|
349
|
+
// ===== V2 Surface (cli 0.131.0) — in-memory governance =====
|
|
350
|
+
export const MCP_SERVER_MATURITY_V2 = Object.freeze({
|
|
351
|
+
PENDING: "pending",
|
|
352
|
+
ACTIVE: "active",
|
|
353
|
+
DEGRADED: "degraded",
|
|
354
|
+
RETIRED: "retired",
|
|
355
|
+
});
|
|
356
|
+
export const MCP_INVOCATION_LIFECYCLE_V2 = Object.freeze({
|
|
357
|
+
QUEUED: "queued",
|
|
358
|
+
DISPATCHING: "dispatching",
|
|
359
|
+
COMPLETED: "completed",
|
|
360
|
+
FAILED: "failed",
|
|
361
|
+
CANCELLED: "cancelled",
|
|
362
|
+
});
|
|
363
|
+
|
|
364
|
+
const _MS_V2 = MCP_SERVER_MATURITY_V2;
|
|
365
|
+
const _MI_V2 = MCP_INVOCATION_LIFECYCLE_V2;
|
|
366
|
+
const _MS_TRANS_V2 = new Map([
|
|
367
|
+
[_MS_V2.PENDING, new Set([_MS_V2.ACTIVE, _MS_V2.RETIRED])],
|
|
368
|
+
[_MS_V2.ACTIVE, new Set([_MS_V2.DEGRADED, _MS_V2.RETIRED])],
|
|
369
|
+
[_MS_V2.DEGRADED, new Set([_MS_V2.ACTIVE, _MS_V2.RETIRED])],
|
|
370
|
+
[_MS_V2.RETIRED, new Set()],
|
|
371
|
+
]);
|
|
372
|
+
const _MI_TRANS_V2 = new Map([
|
|
373
|
+
[_MI_V2.QUEUED, new Set([_MI_V2.DISPATCHING, _MI_V2.CANCELLED])],
|
|
374
|
+
[
|
|
375
|
+
_MI_V2.DISPATCHING,
|
|
376
|
+
new Set([_MI_V2.COMPLETED, _MI_V2.FAILED, _MI_V2.CANCELLED]),
|
|
377
|
+
],
|
|
378
|
+
[_MI_V2.COMPLETED, new Set()],
|
|
379
|
+
[_MI_V2.FAILED, new Set()],
|
|
380
|
+
[_MI_V2.CANCELLED, new Set()],
|
|
381
|
+
]);
|
|
382
|
+
const _MI_TERM_V2 = new Set([
|
|
383
|
+
_MI_V2.COMPLETED,
|
|
384
|
+
_MI_V2.FAILED,
|
|
385
|
+
_MI_V2.CANCELLED,
|
|
386
|
+
]);
|
|
387
|
+
|
|
388
|
+
const MCP_DEFAULT_MAX_ACTIVE_SERVERS_PER_OWNER = 10;
|
|
389
|
+
const MCP_DEFAULT_MAX_PENDING_INVOCATIONS_PER_SERVER = 20;
|
|
390
|
+
const MCP_DEFAULT_SERVER_IDLE_MS = 7 * 24 * 60 * 60 * 1000;
|
|
391
|
+
const MCP_DEFAULT_INVOCATION_STUCK_MS = 2 * 60 * 1000;
|
|
392
|
+
|
|
393
|
+
const _mcpServersV2 = new Map();
|
|
394
|
+
const _mcpInvocationsV2 = new Map();
|
|
395
|
+
let _mcpConfigV2 = {
|
|
396
|
+
maxActiveServersPerOwner: MCP_DEFAULT_MAX_ACTIVE_SERVERS_PER_OWNER,
|
|
397
|
+
maxPendingInvocationsPerServer:
|
|
398
|
+
MCP_DEFAULT_MAX_PENDING_INVOCATIONS_PER_SERVER,
|
|
399
|
+
serverIdleMs: MCP_DEFAULT_SERVER_IDLE_MS,
|
|
400
|
+
invocationStuckMs: MCP_DEFAULT_INVOCATION_STUCK_MS,
|
|
401
|
+
};
|
|
402
|
+
|
|
403
|
+
function _mcpPosIntV2(n, label) {
|
|
404
|
+
if (typeof n !== "number" || !isFinite(n) || isNaN(n))
|
|
405
|
+
throw new Error(`${label} must be positive integer`);
|
|
406
|
+
const v = Math.floor(n);
|
|
407
|
+
if (v <= 0) throw new Error(`${label} must be positive integer`);
|
|
408
|
+
return v;
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
export function _resetStateMcpRegistryV2() {
|
|
412
|
+
_mcpServersV2.clear();
|
|
413
|
+
_mcpInvocationsV2.clear();
|
|
414
|
+
_mcpConfigV2 = {
|
|
415
|
+
maxActiveServersPerOwner: MCP_DEFAULT_MAX_ACTIVE_SERVERS_PER_OWNER,
|
|
416
|
+
maxPendingInvocationsPerServer:
|
|
417
|
+
MCP_DEFAULT_MAX_PENDING_INVOCATIONS_PER_SERVER,
|
|
418
|
+
serverIdleMs: MCP_DEFAULT_SERVER_IDLE_MS,
|
|
419
|
+
invocationStuckMs: MCP_DEFAULT_INVOCATION_STUCK_MS,
|
|
420
|
+
};
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
export function setMaxActiveServersPerOwnerV2(n) {
|
|
424
|
+
_mcpConfigV2.maxActiveServersPerOwner = _mcpPosIntV2(
|
|
425
|
+
n,
|
|
426
|
+
"maxActiveServersPerOwner",
|
|
427
|
+
);
|
|
428
|
+
}
|
|
429
|
+
export function setMaxPendingInvocationsPerServerV2(n) {
|
|
430
|
+
_mcpConfigV2.maxPendingInvocationsPerServer = _mcpPosIntV2(
|
|
431
|
+
n,
|
|
432
|
+
"maxPendingInvocationsPerServer",
|
|
433
|
+
);
|
|
434
|
+
}
|
|
435
|
+
export function setServerIdleMsV2(n) {
|
|
436
|
+
_mcpConfigV2.serverIdleMs = _mcpPosIntV2(n, "serverIdleMs");
|
|
437
|
+
}
|
|
438
|
+
export function setInvocationStuckMsV2(n) {
|
|
439
|
+
_mcpConfigV2.invocationStuckMs = _mcpPosIntV2(n, "invocationStuckMs");
|
|
440
|
+
}
|
|
441
|
+
export function getMaxActiveServersPerOwnerV2() {
|
|
442
|
+
return _mcpConfigV2.maxActiveServersPerOwner;
|
|
443
|
+
}
|
|
444
|
+
export function getMaxPendingInvocationsPerServerV2() {
|
|
445
|
+
return _mcpConfigV2.maxPendingInvocationsPerServer;
|
|
446
|
+
}
|
|
447
|
+
export function getServerIdleMsV2() {
|
|
448
|
+
return _mcpConfigV2.serverIdleMs;
|
|
449
|
+
}
|
|
450
|
+
export function getInvocationStuckMsV2() {
|
|
451
|
+
return _mcpConfigV2.invocationStuckMs;
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
function _copyServerV2(s) {
|
|
455
|
+
return { ...s, metadata: { ...(s.metadata || {}) } };
|
|
456
|
+
}
|
|
457
|
+
function _copyInvocationV2(i) {
|
|
458
|
+
return { ...i, metadata: { ...(i.metadata || {}) } };
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
export function registerServerV2({
|
|
462
|
+
id,
|
|
463
|
+
owner,
|
|
464
|
+
transport,
|
|
465
|
+
name,
|
|
466
|
+
metadata,
|
|
467
|
+
} = {}) {
|
|
468
|
+
if (!id || typeof id !== "string") throw new Error("id required");
|
|
469
|
+
if (!owner || typeof owner !== "string") throw new Error("owner required");
|
|
470
|
+
if (!transport || typeof transport !== "string")
|
|
471
|
+
throw new Error("transport required");
|
|
472
|
+
if (_mcpServersV2.has(id)) throw new Error(`server ${id} already registered`);
|
|
473
|
+
const now = Date.now();
|
|
474
|
+
const s = {
|
|
475
|
+
id,
|
|
476
|
+
owner,
|
|
477
|
+
transport,
|
|
478
|
+
name: name || id,
|
|
479
|
+
status: _MS_V2.PENDING,
|
|
480
|
+
activatedAt: null,
|
|
481
|
+
retiredAt: null,
|
|
482
|
+
lastSeenAt: now,
|
|
483
|
+
createdAt: now,
|
|
484
|
+
metadata: metadata && typeof metadata === "object" ? { ...metadata } : {},
|
|
485
|
+
};
|
|
486
|
+
_mcpServersV2.set(id, s);
|
|
487
|
+
return _copyServerV2(s);
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
function _activeServerCountForOwnerV2(owner) {
|
|
491
|
+
let c = 0;
|
|
492
|
+
for (const s of _mcpServersV2.values())
|
|
493
|
+
if (s.owner === owner && s.status === _MS_V2.ACTIVE) c++;
|
|
494
|
+
return c;
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
function _transitionServerV2(id, next) {
|
|
498
|
+
const s = _mcpServersV2.get(id);
|
|
499
|
+
if (!s) throw new Error(`server ${id} not found`);
|
|
500
|
+
const allowed = _MS_TRANS_V2.get(s.status);
|
|
501
|
+
if (!allowed || !allowed.has(next))
|
|
502
|
+
throw new Error(`invalid transition ${s.status} -> ${next}`);
|
|
503
|
+
if (next === _MS_V2.ACTIVE && s.status === _MS_V2.PENDING) {
|
|
504
|
+
if (
|
|
505
|
+
_activeServerCountForOwnerV2(s.owner) >=
|
|
506
|
+
_mcpConfigV2.maxActiveServersPerOwner
|
|
507
|
+
) {
|
|
508
|
+
throw new Error(
|
|
509
|
+
`owner ${s.owner} active-server cap reached (${_mcpConfigV2.maxActiveServersPerOwner})`,
|
|
510
|
+
);
|
|
511
|
+
}
|
|
512
|
+
}
|
|
513
|
+
const now = Date.now();
|
|
514
|
+
s.status = next;
|
|
515
|
+
if (next === _MS_V2.ACTIVE && !s.activatedAt) s.activatedAt = now;
|
|
516
|
+
if (next === _MS_V2.RETIRED && !s.retiredAt) s.retiredAt = now;
|
|
517
|
+
s.lastSeenAt = now;
|
|
518
|
+
return _copyServerV2(s);
|
|
519
|
+
}
|
|
520
|
+
|
|
521
|
+
export function activateServerV2(id) {
|
|
522
|
+
return _transitionServerV2(id, _MS_V2.ACTIVE);
|
|
523
|
+
}
|
|
524
|
+
export function degradeServerV2(id) {
|
|
525
|
+
return _transitionServerV2(id, _MS_V2.DEGRADED);
|
|
526
|
+
}
|
|
527
|
+
export function retireServerV2(id) {
|
|
528
|
+
return _transitionServerV2(id, _MS_V2.RETIRED);
|
|
529
|
+
}
|
|
530
|
+
export function touchServerV2(id) {
|
|
531
|
+
const s = _mcpServersV2.get(id);
|
|
532
|
+
if (!s) throw new Error(`server ${id} not found`);
|
|
533
|
+
s.lastSeenAt = Date.now();
|
|
534
|
+
return _copyServerV2(s);
|
|
535
|
+
}
|
|
536
|
+
export function getServerV2(id) {
|
|
537
|
+
const s = _mcpServersV2.get(id);
|
|
538
|
+
return s ? _copyServerV2(s) : null;
|
|
539
|
+
}
|
|
540
|
+
export function listServersV2({ owner, status, transport } = {}) {
|
|
541
|
+
const out = [];
|
|
542
|
+
for (const s of _mcpServersV2.values()) {
|
|
543
|
+
if (owner && s.owner !== owner) continue;
|
|
544
|
+
if (status && s.status !== status) continue;
|
|
545
|
+
if (transport && s.transport !== transport) continue;
|
|
546
|
+
out.push(_copyServerV2(s));
|
|
547
|
+
}
|
|
548
|
+
return out;
|
|
549
|
+
}
|
|
550
|
+
|
|
551
|
+
function _pendingInvocationCountForServerV2(serverId) {
|
|
552
|
+
let c = 0;
|
|
553
|
+
for (const i of _mcpInvocationsV2.values()) {
|
|
554
|
+
if (i.serverId !== serverId) continue;
|
|
555
|
+
if (i.status === _MI_V2.QUEUED || i.status === _MI_V2.DISPATCHING) c++;
|
|
556
|
+
}
|
|
557
|
+
return c;
|
|
558
|
+
}
|
|
559
|
+
|
|
560
|
+
export function createInvocationV2({ id, serverId, tool, metadata } = {}) {
|
|
561
|
+
if (!id || typeof id !== "string") throw new Error("id required");
|
|
562
|
+
if (!serverId || typeof serverId !== "string")
|
|
563
|
+
throw new Error("serverId required");
|
|
564
|
+
if (_mcpInvocationsV2.has(id))
|
|
565
|
+
throw new Error(`invocation ${id} already exists`);
|
|
566
|
+
const server = _mcpServersV2.get(serverId);
|
|
567
|
+
if (!server) throw new Error(`server ${serverId} not found`);
|
|
568
|
+
if (server.status === _MS_V2.RETIRED)
|
|
569
|
+
throw new Error(`server ${serverId} retired`);
|
|
570
|
+
if (
|
|
571
|
+
_pendingInvocationCountForServerV2(serverId) >=
|
|
572
|
+
_mcpConfigV2.maxPendingInvocationsPerServer
|
|
573
|
+
) {
|
|
574
|
+
throw new Error(
|
|
575
|
+
`server ${serverId} pending-invocation cap reached (${_mcpConfigV2.maxPendingInvocationsPerServer})`,
|
|
576
|
+
);
|
|
577
|
+
}
|
|
578
|
+
const now = Date.now();
|
|
579
|
+
const i = {
|
|
580
|
+
id,
|
|
581
|
+
serverId,
|
|
582
|
+
tool: tool || "unknown",
|
|
583
|
+
status: _MI_V2.QUEUED,
|
|
584
|
+
startedAt: null,
|
|
585
|
+
settledAt: null,
|
|
586
|
+
createdAt: now,
|
|
587
|
+
metadata: metadata && typeof metadata === "object" ? { ...metadata } : {},
|
|
588
|
+
};
|
|
589
|
+
_mcpInvocationsV2.set(id, i);
|
|
590
|
+
return _copyInvocationV2(i);
|
|
591
|
+
}
|
|
592
|
+
|
|
593
|
+
function _transitionInvocationV2(id, next, extra = {}) {
|
|
594
|
+
const inv = _mcpInvocationsV2.get(id);
|
|
595
|
+
if (!inv) throw new Error(`invocation ${id} not found`);
|
|
596
|
+
const allowed = _MI_TRANS_V2.get(inv.status);
|
|
597
|
+
if (!allowed || !allowed.has(next))
|
|
598
|
+
throw new Error(`invalid transition ${inv.status} -> ${next}`);
|
|
599
|
+
const now = Date.now();
|
|
600
|
+
inv.status = next;
|
|
601
|
+
if (next === _MI_V2.DISPATCHING && !inv.startedAt) inv.startedAt = now;
|
|
602
|
+
if (_MI_TERM_V2.has(next) && !inv.settledAt) inv.settledAt = now;
|
|
603
|
+
if (extra.error) inv.metadata.error = extra.error;
|
|
604
|
+
return _copyInvocationV2(inv);
|
|
605
|
+
}
|
|
606
|
+
|
|
607
|
+
export function dispatchInvocationV2(id) {
|
|
608
|
+
return _transitionInvocationV2(id, _MI_V2.DISPATCHING);
|
|
609
|
+
}
|
|
610
|
+
export function completeInvocationV2(id) {
|
|
611
|
+
return _transitionInvocationV2(id, _MI_V2.COMPLETED);
|
|
612
|
+
}
|
|
613
|
+
export function failInvocationV2(id, error) {
|
|
614
|
+
return _transitionInvocationV2(id, _MI_V2.FAILED, { error });
|
|
615
|
+
}
|
|
616
|
+
export function cancelInvocationV2(id) {
|
|
617
|
+
return _transitionInvocationV2(id, _MI_V2.CANCELLED);
|
|
618
|
+
}
|
|
619
|
+
export function getInvocationV2(id) {
|
|
620
|
+
const i = _mcpInvocationsV2.get(id);
|
|
621
|
+
return i ? _copyInvocationV2(i) : null;
|
|
622
|
+
}
|
|
623
|
+
export function listInvocationsV2({ serverId, status, tool } = {}) {
|
|
624
|
+
const out = [];
|
|
625
|
+
for (const i of _mcpInvocationsV2.values()) {
|
|
626
|
+
if (serverId && i.serverId !== serverId) continue;
|
|
627
|
+
if (status && i.status !== status) continue;
|
|
628
|
+
if (tool && i.tool !== tool) continue;
|
|
629
|
+
out.push(_copyInvocationV2(i));
|
|
630
|
+
}
|
|
631
|
+
return out;
|
|
632
|
+
}
|
|
633
|
+
|
|
634
|
+
export function autoDegradeIdleServersV2({ now } = {}) {
|
|
635
|
+
const t = typeof now === "number" ? now : Date.now();
|
|
636
|
+
const flipped = [];
|
|
637
|
+
for (const s of _mcpServersV2.values()) {
|
|
638
|
+
if (s.status !== _MS_V2.ACTIVE) continue;
|
|
639
|
+
if (t - s.lastSeenAt > _mcpConfigV2.serverIdleMs) {
|
|
640
|
+
s.status = _MS_V2.DEGRADED;
|
|
641
|
+
s.lastSeenAt = t;
|
|
642
|
+
flipped.push(_copyServerV2(s));
|
|
643
|
+
}
|
|
644
|
+
}
|
|
645
|
+
return flipped;
|
|
646
|
+
}
|
|
647
|
+
|
|
648
|
+
export function autoFailStuckInvocationsV2({ now } = {}) {
|
|
649
|
+
const t = typeof now === "number" ? now : Date.now();
|
|
650
|
+
const flipped = [];
|
|
651
|
+
for (const i of _mcpInvocationsV2.values()) {
|
|
652
|
+
if (i.status !== _MI_V2.DISPATCHING) continue;
|
|
653
|
+
if (i.startedAt && t - i.startedAt > _mcpConfigV2.invocationStuckMs) {
|
|
654
|
+
i.status = _MI_V2.FAILED;
|
|
655
|
+
i.settledAt = t;
|
|
656
|
+
i.metadata.error = "stuck-timeout";
|
|
657
|
+
flipped.push(_copyInvocationV2(i));
|
|
658
|
+
}
|
|
659
|
+
}
|
|
660
|
+
return flipped;
|
|
661
|
+
}
|
|
662
|
+
|
|
663
|
+
export function getMcpRegistryStatsV2() {
|
|
664
|
+
const serversByStatus = {};
|
|
665
|
+
for (const s of Object.values(_MS_V2)) serversByStatus[s] = 0;
|
|
666
|
+
for (const s of _mcpServersV2.values()) serversByStatus[s.status]++;
|
|
667
|
+
const invocationsByStatus = {};
|
|
668
|
+
for (const s of Object.values(_MI_V2)) invocationsByStatus[s] = 0;
|
|
669
|
+
for (const i of _mcpInvocationsV2.values()) invocationsByStatus[i.status]++;
|
|
670
|
+
return {
|
|
671
|
+
totalServersV2: _mcpServersV2.size,
|
|
672
|
+
totalInvocationsV2: _mcpInvocationsV2.size,
|
|
673
|
+
maxActiveServersPerOwner: _mcpConfigV2.maxActiveServersPerOwner,
|
|
674
|
+
maxPendingInvocationsPerServer: _mcpConfigV2.maxPendingInvocationsPerServer,
|
|
675
|
+
serverIdleMs: _mcpConfigV2.serverIdleMs,
|
|
676
|
+
invocationStuckMs: _mcpConfigV2.invocationStuckMs,
|
|
677
|
+
serversByStatus,
|
|
678
|
+
invocationsByStatus,
|
|
679
|
+
};
|
|
680
|
+
}
|
|
@@ -209,3 +209,333 @@ export function updateMemoryFile(memoryDir, content) {
|
|
|
209
209
|
fs.writeFileSync(filePath, content, "utf8");
|
|
210
210
|
return { path: filePath };
|
|
211
211
|
}
|
|
212
|
+
|
|
213
|
+
/* ═══════════════════════════════════════════════════════════════
|
|
214
|
+
* V2 Surface — Memory governance layer.
|
|
215
|
+
* Tracks per-category entry maturity + consolidation job lifecycle
|
|
216
|
+
* independent of legacy SQLite memory_entries table.
|
|
217
|
+
* ═══════════════════════════════════════════════════════════════ */
|
|
218
|
+
|
|
219
|
+
export const ENTRY_MATURITY_V2 = Object.freeze({
|
|
220
|
+
PENDING: "pending",
|
|
221
|
+
ACTIVE: "active",
|
|
222
|
+
PARKED: "parked",
|
|
223
|
+
ARCHIVED: "archived",
|
|
224
|
+
});
|
|
225
|
+
|
|
226
|
+
export const CONSOLIDATION_LIFECYCLE_V2 = Object.freeze({
|
|
227
|
+
QUEUED: "queued",
|
|
228
|
+
RUNNING: "running",
|
|
229
|
+
SUCCEEDED: "succeeded",
|
|
230
|
+
FAILED: "failed",
|
|
231
|
+
CANCELLED: "cancelled",
|
|
232
|
+
});
|
|
233
|
+
|
|
234
|
+
const ENTRY_TRANSITIONS_V2 = new Map([
|
|
235
|
+
["pending", new Set(["active", "archived"])],
|
|
236
|
+
["active", new Set(["parked", "archived"])],
|
|
237
|
+
["parked", new Set(["active", "archived"])],
|
|
238
|
+
["archived", new Set()],
|
|
239
|
+
]);
|
|
240
|
+
const ENTRY_TERMINALS_V2 = new Set(["archived"]);
|
|
241
|
+
|
|
242
|
+
const JOB_TRANSITIONS_V2 = new Map([
|
|
243
|
+
["queued", new Set(["running", "cancelled"])],
|
|
244
|
+
["running", new Set(["succeeded", "failed", "cancelled"])],
|
|
245
|
+
["succeeded", new Set()],
|
|
246
|
+
["failed", new Set()],
|
|
247
|
+
["cancelled", new Set()],
|
|
248
|
+
]);
|
|
249
|
+
const JOB_TERMINALS_V2 = new Set(["succeeded", "failed", "cancelled"]);
|
|
250
|
+
|
|
251
|
+
export const MEMORY_DEFAULT_MAX_ACTIVE_ENTRIES_PER_CATEGORY = 200;
|
|
252
|
+
export const MEMORY_DEFAULT_MAX_RUNNING_JOBS_PER_SOURCE = 2;
|
|
253
|
+
export const MEMORY_DEFAULT_ENTRY_IDLE_MS = 1000 * 60 * 60 * 24 * 90; // 90 days
|
|
254
|
+
export const MEMORY_DEFAULT_JOB_STUCK_MS = 1000 * 60 * 10; // 10 minutes
|
|
255
|
+
|
|
256
|
+
const _entriesV2 = new Map();
|
|
257
|
+
const _jobsV2 = new Map();
|
|
258
|
+
let _maxActiveEntriesPerCategoryV2 =
|
|
259
|
+
MEMORY_DEFAULT_MAX_ACTIVE_ENTRIES_PER_CATEGORY;
|
|
260
|
+
let _maxRunningJobsPerSourceV2 = MEMORY_DEFAULT_MAX_RUNNING_JOBS_PER_SOURCE;
|
|
261
|
+
let _entryIdleMsV2 = MEMORY_DEFAULT_ENTRY_IDLE_MS;
|
|
262
|
+
let _jobStuckMsV2 = MEMORY_DEFAULT_JOB_STUCK_MS;
|
|
263
|
+
|
|
264
|
+
function _posIntMemoryV2(n, label) {
|
|
265
|
+
const v = Math.floor(Number(n));
|
|
266
|
+
if (!Number.isFinite(v) || v <= 0)
|
|
267
|
+
throw new Error(`${label} must be a positive integer`);
|
|
268
|
+
return v;
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
export function getMaxActiveEntriesPerCategoryV2() {
|
|
272
|
+
return _maxActiveEntriesPerCategoryV2;
|
|
273
|
+
}
|
|
274
|
+
export function setMaxActiveEntriesPerCategoryV2(n) {
|
|
275
|
+
_maxActiveEntriesPerCategoryV2 = _posIntMemoryV2(
|
|
276
|
+
n,
|
|
277
|
+
"maxActiveEntriesPerCategory",
|
|
278
|
+
);
|
|
279
|
+
}
|
|
280
|
+
export function getMaxRunningJobsPerSourceV2() {
|
|
281
|
+
return _maxRunningJobsPerSourceV2;
|
|
282
|
+
}
|
|
283
|
+
export function setMaxRunningJobsPerSourceV2(n) {
|
|
284
|
+
_maxRunningJobsPerSourceV2 = _posIntMemoryV2(n, "maxRunningJobsPerSource");
|
|
285
|
+
}
|
|
286
|
+
export function getEntryIdleMsV2() {
|
|
287
|
+
return _entryIdleMsV2;
|
|
288
|
+
}
|
|
289
|
+
export function setEntryIdleMsV2(n) {
|
|
290
|
+
_entryIdleMsV2 = _posIntMemoryV2(n, "entryIdleMs");
|
|
291
|
+
}
|
|
292
|
+
export function getJobStuckMsV2() {
|
|
293
|
+
return _jobStuckMsV2;
|
|
294
|
+
}
|
|
295
|
+
export function setJobStuckMsV2(n) {
|
|
296
|
+
_jobStuckMsV2 = _posIntMemoryV2(n, "jobStuckMs");
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
export function getActiveEntryCountV2(category) {
|
|
300
|
+
let n = 0;
|
|
301
|
+
for (const e of _entriesV2.values()) {
|
|
302
|
+
if (e.category === category && e.status === "active") n += 1;
|
|
303
|
+
}
|
|
304
|
+
return n;
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
export function getRunningJobCountV2(source) {
|
|
308
|
+
let n = 0;
|
|
309
|
+
for (const j of _jobsV2.values()) {
|
|
310
|
+
if (j.source === source && j.status === "running") n += 1;
|
|
311
|
+
}
|
|
312
|
+
return n;
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
function _copyEntryV2(e) {
|
|
316
|
+
return { ...e, metadata: { ...e.metadata } };
|
|
317
|
+
}
|
|
318
|
+
function _copyJobV2(j) {
|
|
319
|
+
return { ...j, metadata: { ...j.metadata } };
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
export function registerEntryV2(
|
|
323
|
+
id,
|
|
324
|
+
{ category, summary, metadata = {}, now = Date.now() } = {},
|
|
325
|
+
) {
|
|
326
|
+
if (!id || typeof id !== "string") throw new Error("id must be a string");
|
|
327
|
+
if (!category || typeof category !== "string")
|
|
328
|
+
throw new Error("category must be a string");
|
|
329
|
+
if (!summary || typeof summary !== "string")
|
|
330
|
+
throw new Error("summary must be a string");
|
|
331
|
+
if (_entriesV2.has(id)) throw new Error(`entry ${id} already exists`);
|
|
332
|
+
const e = {
|
|
333
|
+
id,
|
|
334
|
+
category,
|
|
335
|
+
summary,
|
|
336
|
+
status: "pending",
|
|
337
|
+
createdAt: now,
|
|
338
|
+
lastSeenAt: now,
|
|
339
|
+
activatedAt: null,
|
|
340
|
+
archivedAt: null,
|
|
341
|
+
metadata: { ...metadata },
|
|
342
|
+
};
|
|
343
|
+
_entriesV2.set(id, e);
|
|
344
|
+
return _copyEntryV2(e);
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
export function getEntryV2(id) {
|
|
348
|
+
const e = _entriesV2.get(id);
|
|
349
|
+
return e ? _copyEntryV2(e) : null;
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
export function listEntriesV2({ category, status } = {}) {
|
|
353
|
+
const out = [];
|
|
354
|
+
for (const e of _entriesV2.values()) {
|
|
355
|
+
if (category && e.category !== category) continue;
|
|
356
|
+
if (status && e.status !== status) continue;
|
|
357
|
+
out.push(_copyEntryV2(e));
|
|
358
|
+
}
|
|
359
|
+
return out;
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
export function setEntryStatusV2(id, next, { now = Date.now() } = {}) {
|
|
363
|
+
const e = _entriesV2.get(id);
|
|
364
|
+
if (!e) throw new Error(`entry ${id} not found`);
|
|
365
|
+
if (!ENTRY_TRANSITIONS_V2.has(next))
|
|
366
|
+
throw new Error(`unknown entry status: ${next}`);
|
|
367
|
+
if (ENTRY_TERMINALS_V2.has(e.status))
|
|
368
|
+
throw new Error(`entry ${id} is in terminal state ${e.status}`);
|
|
369
|
+
const allowed = ENTRY_TRANSITIONS_V2.get(e.status);
|
|
370
|
+
if (!allowed.has(next))
|
|
371
|
+
throw new Error(`cannot transition entry from ${e.status} to ${next}`);
|
|
372
|
+
if (next === "active") {
|
|
373
|
+
if (e.status === "pending") {
|
|
374
|
+
const count = getActiveEntryCountV2(e.category);
|
|
375
|
+
if (count >= _maxActiveEntriesPerCategoryV2)
|
|
376
|
+
throw new Error(
|
|
377
|
+
`category ${e.category} already at active-entry cap (${_maxActiveEntriesPerCategoryV2})`,
|
|
378
|
+
);
|
|
379
|
+
}
|
|
380
|
+
if (!e.activatedAt) e.activatedAt = now;
|
|
381
|
+
}
|
|
382
|
+
if (next === "archived" && !e.archivedAt) e.archivedAt = now;
|
|
383
|
+
e.status = next;
|
|
384
|
+
e.lastSeenAt = now;
|
|
385
|
+
return _copyEntryV2(e);
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
export function activateEntryV2(id, opts) {
|
|
389
|
+
return setEntryStatusV2(id, "active", opts);
|
|
390
|
+
}
|
|
391
|
+
export function parkEntryV2(id, opts) {
|
|
392
|
+
return setEntryStatusV2(id, "parked", opts);
|
|
393
|
+
}
|
|
394
|
+
export function archiveEntryV2(id, opts) {
|
|
395
|
+
return setEntryStatusV2(id, "archived", opts);
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
export function touchEntryV2(id, { now = Date.now() } = {}) {
|
|
399
|
+
const e = _entriesV2.get(id);
|
|
400
|
+
if (!e) throw new Error(`entry ${id} not found`);
|
|
401
|
+
e.lastSeenAt = now;
|
|
402
|
+
return _copyEntryV2(e);
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
export function createConsolidationJobV2(
|
|
406
|
+
id,
|
|
407
|
+
{ source, scope, metadata = {}, now = Date.now() } = {},
|
|
408
|
+
) {
|
|
409
|
+
if (!id || typeof id !== "string") throw new Error("id must be a string");
|
|
410
|
+
if (!source || typeof source !== "string")
|
|
411
|
+
throw new Error("source must be a string");
|
|
412
|
+
if (!scope || typeof scope !== "string")
|
|
413
|
+
throw new Error("scope must be a string");
|
|
414
|
+
if (_jobsV2.has(id)) throw new Error(`job ${id} already exists`);
|
|
415
|
+
const j = {
|
|
416
|
+
id,
|
|
417
|
+
source,
|
|
418
|
+
scope,
|
|
419
|
+
status: "queued",
|
|
420
|
+
createdAt: now,
|
|
421
|
+
lastSeenAt: now,
|
|
422
|
+
startedAt: null,
|
|
423
|
+
finishedAt: null,
|
|
424
|
+
metadata: { ...metadata },
|
|
425
|
+
};
|
|
426
|
+
_jobsV2.set(id, j);
|
|
427
|
+
return _copyJobV2(j);
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
export function getConsolidationJobV2(id) {
|
|
431
|
+
const j = _jobsV2.get(id);
|
|
432
|
+
return j ? _copyJobV2(j) : null;
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
export function listConsolidationJobsV2({ source, status } = {}) {
|
|
436
|
+
const out = [];
|
|
437
|
+
for (const j of _jobsV2.values()) {
|
|
438
|
+
if (source && j.source !== source) continue;
|
|
439
|
+
if (status && j.status !== status) continue;
|
|
440
|
+
out.push(_copyJobV2(j));
|
|
441
|
+
}
|
|
442
|
+
return out;
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
export function setJobStatusV2(id, next, { now = Date.now() } = {}) {
|
|
446
|
+
const j = _jobsV2.get(id);
|
|
447
|
+
if (!j) throw new Error(`job ${id} not found`);
|
|
448
|
+
if (!JOB_TRANSITIONS_V2.has(next))
|
|
449
|
+
throw new Error(`unknown job status: ${next}`);
|
|
450
|
+
if (JOB_TERMINALS_V2.has(j.status))
|
|
451
|
+
throw new Error(`job ${id} is in terminal state ${j.status}`);
|
|
452
|
+
const allowed = JOB_TRANSITIONS_V2.get(j.status);
|
|
453
|
+
if (!allowed.has(next))
|
|
454
|
+
throw new Error(`cannot transition job from ${j.status} to ${next}`);
|
|
455
|
+
if (next === "running") {
|
|
456
|
+
if (j.status === "queued") {
|
|
457
|
+
const count = getRunningJobCountV2(j.source);
|
|
458
|
+
if (count >= _maxRunningJobsPerSourceV2)
|
|
459
|
+
throw new Error(
|
|
460
|
+
`source ${j.source} already at running-job cap (${_maxRunningJobsPerSourceV2})`,
|
|
461
|
+
);
|
|
462
|
+
}
|
|
463
|
+
if (!j.startedAt) j.startedAt = now;
|
|
464
|
+
}
|
|
465
|
+
if (JOB_TERMINALS_V2.has(next) && !j.finishedAt) j.finishedAt = now;
|
|
466
|
+
j.status = next;
|
|
467
|
+
j.lastSeenAt = now;
|
|
468
|
+
return _copyJobV2(j);
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
export function startConsolidationJobV2(id, opts) {
|
|
472
|
+
return setJobStatusV2(id, "running", opts);
|
|
473
|
+
}
|
|
474
|
+
export function succeedConsolidationJobV2(id, opts) {
|
|
475
|
+
return setJobStatusV2(id, "succeeded", opts);
|
|
476
|
+
}
|
|
477
|
+
export function failConsolidationJobV2(id, opts) {
|
|
478
|
+
return setJobStatusV2(id, "failed", opts);
|
|
479
|
+
}
|
|
480
|
+
export function cancelConsolidationJobV2(id, opts) {
|
|
481
|
+
return setJobStatusV2(id, "cancelled", opts);
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
export function autoParkIdleEntriesV2({ now = Date.now() } = {}) {
|
|
485
|
+
const flipped = [];
|
|
486
|
+
for (const e of _entriesV2.values()) {
|
|
487
|
+
if (e.status !== "active") continue;
|
|
488
|
+
if (now - e.lastSeenAt > _entryIdleMsV2) {
|
|
489
|
+
e.status = "parked";
|
|
490
|
+
e.lastSeenAt = now;
|
|
491
|
+
flipped.push(_copyEntryV2(e));
|
|
492
|
+
}
|
|
493
|
+
}
|
|
494
|
+
return flipped;
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
export function autoFailStuckJobsV2({ now = Date.now() } = {}) {
|
|
498
|
+
const flipped = [];
|
|
499
|
+
for (const j of _jobsV2.values()) {
|
|
500
|
+
if (j.status !== "running") continue;
|
|
501
|
+
if (now - j.lastSeenAt > _jobStuckMsV2) {
|
|
502
|
+
j.status = "failed";
|
|
503
|
+
j.lastSeenAt = now;
|
|
504
|
+
if (!j.finishedAt) j.finishedAt = now;
|
|
505
|
+
flipped.push(_copyJobV2(j));
|
|
506
|
+
}
|
|
507
|
+
}
|
|
508
|
+
return flipped;
|
|
509
|
+
}
|
|
510
|
+
|
|
511
|
+
export function getMemoryManagerStatsV2() {
|
|
512
|
+
const entriesByStatus = {};
|
|
513
|
+
for (const v of Object.values(ENTRY_MATURITY_V2)) entriesByStatus[v] = 0;
|
|
514
|
+
for (const e of _entriesV2.values()) entriesByStatus[e.status] += 1;
|
|
515
|
+
|
|
516
|
+
const jobsByStatus = {};
|
|
517
|
+
for (const v of Object.values(CONSOLIDATION_LIFECYCLE_V2))
|
|
518
|
+
jobsByStatus[v] = 0;
|
|
519
|
+
for (const j of _jobsV2.values()) jobsByStatus[j.status] += 1;
|
|
520
|
+
|
|
521
|
+
return {
|
|
522
|
+
totalEntriesV2: _entriesV2.size,
|
|
523
|
+
totalJobsV2: _jobsV2.size,
|
|
524
|
+
maxActiveEntriesPerCategory: _maxActiveEntriesPerCategoryV2,
|
|
525
|
+
maxRunningJobsPerSource: _maxRunningJobsPerSourceV2,
|
|
526
|
+
entryIdleMs: _entryIdleMsV2,
|
|
527
|
+
jobStuckMs: _jobStuckMsV2,
|
|
528
|
+
entriesByStatus,
|
|
529
|
+
jobsByStatus,
|
|
530
|
+
};
|
|
531
|
+
}
|
|
532
|
+
|
|
533
|
+
export function _resetStateMemoryManagerV2() {
|
|
534
|
+
_entriesV2.clear();
|
|
535
|
+
_jobsV2.clear();
|
|
536
|
+
_maxActiveEntriesPerCategoryV2 =
|
|
537
|
+
MEMORY_DEFAULT_MAX_ACTIVE_ENTRIES_PER_CATEGORY;
|
|
538
|
+
_maxRunningJobsPerSourceV2 = MEMORY_DEFAULT_MAX_RUNNING_JOBS_PER_SOURCE;
|
|
539
|
+
_entryIdleMsV2 = MEMORY_DEFAULT_ENTRY_IDLE_MS;
|
|
540
|
+
_jobStuckMsV2 = MEMORY_DEFAULT_JOB_STUCK_MS;
|
|
541
|
+
}
|