chainlesschain 0.81.0 → 0.143.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 +62 -0
- package/src/commands/activitypub.js +61 -0
- package/src/commands/agent-network.js +254 -1
- package/src/commands/agent.js +117 -0
- package/src/commands/audit.js +302 -0
- package/src/commands/automation.js +271 -1
- package/src/commands/bi.js +61 -0
- package/src/commands/bm25.js +78 -0
- package/src/commands/browse.js +64 -0
- package/src/commands/ccron.js +78 -0
- package/src/commands/codegen.js +224 -0
- package/src/commands/collab.js +341 -0
- package/src/commands/compliance.js +1075 -0
- package/src/commands/compt.js +78 -0
- package/src/commands/consol.js +231 -0
- package/src/commands/cowork.js +263 -0
- package/src/commands/crosschain.js +62 -0
- package/src/commands/dao.js +62 -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 +61 -0
- package/src/commands/economy.js +56 -0
- package/src/commands/encrypt.js +341 -0
- package/src/commands/evolution.js +56 -0
- package/src/commands/evomap.js +61 -0
- package/src/commands/export.js +256 -1
- package/src/commands/fflag.js +178 -0
- package/src/commands/fusion.js +258 -0
- package/src/commands/git.js +45 -0
- package/src/commands/governance.js +325 -0
- package/src/commands/hardening.js +411 -0
- package/src/commands/hmemory.js +56 -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 +42 -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/itbudget.js +45 -0
- package/src/commands/kg.js +387 -0
- package/src/commands/llm.js +263 -0
- package/src/commands/lowcode.js +44 -0
- package/src/commands/matrix.js +62 -0
- package/src/commands/mcp.js +221 -0
- package/src/commands/mcpscaf.js +41 -0
- package/src/commands/meminj.js +41 -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/nostr.js +62 -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/orchgov.js +45 -0
- package/src/commands/org.js +277 -0
- package/src/commands/p2p.js +390 -0
- package/src/commands/pdfp.js +78 -0
- package/src/commands/perception.js +290 -0
- package/src/commands/perf.js +39 -0
- package/src/commands/perm.js +45 -0
- package/src/commands/permmem.js +251 -0
- package/src/commands/pipeline.js +57 -1
- package/src/commands/planmode.js +45 -0
- package/src/commands/plugin-ecosystem.js +273 -0
- package/src/commands/pqc.js +393 -0
- package/src/commands/promcomp.js +82 -0
- package/src/commands/quantization.js +351 -0
- package/src/commands/rcache.js +271 -0
- package/src/commands/recommend.js +382 -0
- package/src/commands/runtime.js +307 -0
- package/src/commands/scim.js +262 -0
- package/src/commands/seshhook.js +41 -0
- package/src/commands/seshsearch.js +41 -0
- package/src/commands/seshtail.js +41 -0
- package/src/commands/seshu.js +41 -0
- package/src/commands/session.js +258 -0
- package/src/commands/sganal.js +78 -0
- package/src/commands/siem.js +40 -0
- package/src/commands/skill.js +267 -1
- package/src/commands/slotfill.js +41 -0
- package/src/commands/social.js +290 -0
- package/src/commands/sso.js +186 -1
- package/src/commands/svccont.js +45 -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/tms.js +45 -0
- package/src/commands/tokens.js +269 -0
- package/src/commands/topiccls.js +45 -0
- package/src/commands/trust.js +249 -0
- package/src/commands/uprof.js +45 -0
- package/src/commands/vcheck.js +78 -0
- package/src/commands/wallet.js +277 -0
- package/src/commands/webfetch.js +41 -0
- package/src/commands/workflow.js +171 -0
- package/src/commands/zkp.js +62 -0
- package/src/harness/prompt-compressor.js +331 -0
- package/src/index.js +65 -1
- package/src/lib/a2a-protocol.js +105 -0
- package/src/lib/activitypub-bridge.js +105 -0
- package/src/lib/agent-coordinator.js +325 -0
- package/src/lib/agent-economy.js +105 -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 +105 -0
- package/src/lib/audit-logger.js +379 -0
- package/src/lib/automation-engine.js +330 -0
- package/src/lib/autonomous-agent.js +105 -0
- package/src/lib/autonomous-developer.js +350 -0
- package/src/lib/bi-engine.js +105 -0
- package/src/lib/bm25-search.js +81 -0
- package/src/lib/browser-automation.js +105 -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-framework-reporter.js +105 -0
- package/src/lib/compliance-manager.js +434 -0
- package/src/lib/compression-telemetry.js +81 -0
- package/src/lib/content-recommendation.js +469 -0
- package/src/lib/content-recommender.js +105 -0
- package/src/lib/cowork-cron.js +81 -0
- package/src/lib/cowork-task-runner.js +105 -0
- package/src/lib/cross-chain.js +105 -0
- package/src/lib/crypto-manager.js +350 -0
- package/src/lib/dao-governance.js +105 -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 +105 -0
- package/src/lib/evolution-system.js +105 -0
- package/src/lib/evomap-manager.js +105 -0
- package/src/lib/execution-backend.js +105 -0
- package/src/lib/feature-flags.js +85 -0
- package/src/lib/git-integration.js +105 -0
- package/src/lib/hardening-manager.js +348 -0
- package/src/lib/hierarchical-memory.js +105 -0
- package/src/lib/hook-manager.js +380 -0
- package/src/lib/inference-network.js +105 -0
- package/src/lib/instinct-manager.js +332 -0
- package/src/lib/ipfs-storage.js +334 -0
- package/src/lib/iteration-budget.js +105 -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/matrix-bridge.js +105 -0
- package/src/lib/mcp-registry.js +333 -0
- package/src/lib/mcp-scaffold.js +81 -0
- package/src/lib/memory-injection.js +81 -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/nostr-bridge.js +105 -0
- package/src/lib/note-versioning.js +327 -0
- package/src/lib/orchestrator.js +105 -0
- package/src/lib/org-manager.js +323 -0
- package/src/lib/p2p-manager.js +387 -0
- package/src/lib/pdf-parser.js +81 -0
- package/src/lib/perception.js +346 -0
- package/src/lib/perf-tuning.js +109 -1
- package/src/lib/permanent-memory.js +320 -0
- package/src/lib/permission-engine.js +81 -0
- package/src/lib/pipeline-orchestrator.js +105 -0
- package/src/lib/plan-mode.js +81 -0
- package/src/lib/plugin-ecosystem.js +377 -0
- package/src/lib/pqc-manager.js +368 -0
- package/src/lib/prompt-compressor.js +1 -10
- package/src/lib/protocol-fusion.js +417 -0
- package/src/lib/quantization.js +325 -0
- package/src/lib/response-cache.js +327 -0
- package/src/lib/scim-manager.js +329 -0
- package/src/lib/service-container.js +81 -0
- package/src/lib/session-consolidator.js +105 -0
- package/src/lib/session-hooks.js +81 -0
- package/src/lib/session-manager.js +329 -0
- package/src/lib/session-search.js +81 -0
- package/src/lib/session-tail.js +81 -0
- package/src/lib/session-usage.js +83 -0
- package/src/lib/siem-exporter.js +105 -0
- package/src/lib/skill-loader.js +377 -0
- package/src/lib/slot-filler.js +81 -0
- package/src/lib/social-graph-analytics.js +81 -0
- package/src/lib/social-graph.js +81 -0
- package/src/lib/social-manager.js +326 -0
- package/src/lib/sso-manager.js +332 -0
- package/src/lib/sub-agent-registry.js +110 -0
- package/src/lib/sync-manager.js +326 -0
- package/src/lib/task-model-selector.js +81 -0
- package/src/lib/tech-learning-engine.js +369 -0
- package/src/lib/tenant-saas.js +460 -0
- package/src/lib/threat-intel.js +335 -0
- package/src/lib/todo-manager.js +105 -0
- package/src/lib/token-incentive.js +293 -0
- package/src/lib/token-tracker.js +329 -0
- package/src/lib/topic-classifier.js +105 -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/user-profile.js +81 -0
- package/src/lib/version-checker.js +81 -0
- package/src/lib/wallet-manager.js +326 -0
- package/src/lib/web-fetch.js +81 -0
- package/src/lib/workflow-engine.js +322 -0
- package/src/lib/zkp-engine.js +105 -0
package/src/lib/siem-exporter.js
CHANGED
|
@@ -468,3 +468,108 @@ export function listTargetsByStatus(status) {
|
|
|
468
468
|
}
|
|
469
469
|
|
|
470
470
|
export { _severityCEF, _allowedTargetTransitions };
|
|
471
|
+
|
|
472
|
+
|
|
473
|
+
// ===== V2 Surface: SIEM Exporter governance overlay (CLI v0.138.0) =====
|
|
474
|
+
export const SIEM_TARGET_MATURITY_V2 = Object.freeze({
|
|
475
|
+
PENDING: "pending", ACTIVE: "active", DEGRADED: "degraded", RETIRED: "retired",
|
|
476
|
+
});
|
|
477
|
+
export const SIEM_EXPORT_LIFECYCLE_V2 = Object.freeze({
|
|
478
|
+
QUEUED: "queued", SENDING: "sending", DELIVERED: "delivered", FAILED: "failed", CANCELLED: "cancelled",
|
|
479
|
+
});
|
|
480
|
+
|
|
481
|
+
const _siemTargetTrans = new Map([
|
|
482
|
+
[SIEM_TARGET_MATURITY_V2.PENDING, new Set([SIEM_TARGET_MATURITY_V2.ACTIVE, SIEM_TARGET_MATURITY_V2.RETIRED])],
|
|
483
|
+
[SIEM_TARGET_MATURITY_V2.ACTIVE, new Set([SIEM_TARGET_MATURITY_V2.DEGRADED, SIEM_TARGET_MATURITY_V2.RETIRED])],
|
|
484
|
+
[SIEM_TARGET_MATURITY_V2.DEGRADED, new Set([SIEM_TARGET_MATURITY_V2.ACTIVE, SIEM_TARGET_MATURITY_V2.RETIRED])],
|
|
485
|
+
[SIEM_TARGET_MATURITY_V2.RETIRED, new Set()],
|
|
486
|
+
]);
|
|
487
|
+
const _siemTargetTerminal = new Set([SIEM_TARGET_MATURITY_V2.RETIRED]);
|
|
488
|
+
const _siemExportTrans = new Map([
|
|
489
|
+
[SIEM_EXPORT_LIFECYCLE_V2.QUEUED, new Set([SIEM_EXPORT_LIFECYCLE_V2.SENDING, SIEM_EXPORT_LIFECYCLE_V2.CANCELLED])],
|
|
490
|
+
[SIEM_EXPORT_LIFECYCLE_V2.SENDING, new Set([SIEM_EXPORT_LIFECYCLE_V2.DELIVERED, SIEM_EXPORT_LIFECYCLE_V2.FAILED, SIEM_EXPORT_LIFECYCLE_V2.CANCELLED])],
|
|
491
|
+
[SIEM_EXPORT_LIFECYCLE_V2.DELIVERED, new Set()],
|
|
492
|
+
[SIEM_EXPORT_LIFECYCLE_V2.FAILED, new Set()],
|
|
493
|
+
[SIEM_EXPORT_LIFECYCLE_V2.CANCELLED, new Set()],
|
|
494
|
+
]);
|
|
495
|
+
|
|
496
|
+
const _siemTargets = new Map();
|
|
497
|
+
const _siemExportJobs = new Map();
|
|
498
|
+
let _siemMaxActivePerOperator = 8;
|
|
499
|
+
let _siemMaxPendingExportsPerTarget = 50;
|
|
500
|
+
let _siemTargetIdleMs = 24 * 60 * 60 * 1000;
|
|
501
|
+
let _siemExportStuckMs = 5 * 60 * 1000;
|
|
502
|
+
|
|
503
|
+
function _siemPos(n, lbl) { const v = Math.floor(Number(n)); if (!Number.isFinite(v) || v <= 0) throw new Error(`${lbl} must be positive integer`); return v; }
|
|
504
|
+
|
|
505
|
+
export function setMaxActiveSiemTargetsPerOperatorV2(n) { _siemMaxActivePerOperator = _siemPos(n, "maxActiveSiemTargetsPerOperator"); }
|
|
506
|
+
export function getMaxActiveSiemTargetsPerOperatorV2() { return _siemMaxActivePerOperator; }
|
|
507
|
+
export function setMaxPendingSiemExportsPerTargetV2(n) { _siemMaxPendingExportsPerTarget = _siemPos(n, "maxPendingSiemExportsPerTarget"); }
|
|
508
|
+
export function getMaxPendingSiemExportsPerTargetV2() { return _siemMaxPendingExportsPerTarget; }
|
|
509
|
+
export function setSiemTargetIdleMsV2(n) { _siemTargetIdleMs = _siemPos(n, "siemTargetIdleMs"); }
|
|
510
|
+
export function getSiemTargetIdleMsV2() { return _siemTargetIdleMs; }
|
|
511
|
+
export function setSiemExportStuckMsV2(n) { _siemExportStuckMs = _siemPos(n, "siemExportStuckMs"); }
|
|
512
|
+
export function getSiemExportStuckMsV2() { return _siemExportStuckMs; }
|
|
513
|
+
|
|
514
|
+
export function _resetStateSiemExporterV2() {
|
|
515
|
+
_siemTargets.clear(); _siemExportJobs.clear();
|
|
516
|
+
_siemMaxActivePerOperator = 8; _siemMaxPendingExportsPerTarget = 50;
|
|
517
|
+
_siemTargetIdleMs = 24 * 60 * 60 * 1000; _siemExportStuckMs = 5 * 60 * 1000;
|
|
518
|
+
}
|
|
519
|
+
|
|
520
|
+
export function registerSiemTargetV2({ id, operator, kind, metadata } = {}) {
|
|
521
|
+
if (!id || typeof id !== "string") throw new Error("id is required");
|
|
522
|
+
if (!operator || typeof operator !== "string") throw new Error("operator is required");
|
|
523
|
+
if (_siemTargets.has(id)) throw new Error(`siem target ${id} already registered`);
|
|
524
|
+
const now = Date.now();
|
|
525
|
+
const t = { id, operator, kind: kind || "splunk_hec", status: SIEM_TARGET_MATURITY_V2.PENDING, createdAt: now, updatedAt: now, activatedAt: null, retiredAt: null, lastTouchedAt: now, metadata: { ...(metadata || {}) } };
|
|
526
|
+
_siemTargets.set(id, t);
|
|
527
|
+
return { ...t, metadata: { ...t.metadata } };
|
|
528
|
+
}
|
|
529
|
+
function _siemCheckT(from, to) { const a = _siemTargetTrans.get(from); if (!a || !a.has(to)) throw new Error(`invalid siem target transition ${from} → ${to}`); }
|
|
530
|
+
function _siemCountActive(operator) { let n = 0; for (const t of _siemTargets.values()) if (t.operator === operator && t.status === SIEM_TARGET_MATURITY_V2.ACTIVE) n++; return n; }
|
|
531
|
+
|
|
532
|
+
export function activateSiemTargetV2(id) {
|
|
533
|
+
const t = _siemTargets.get(id); if (!t) throw new Error(`siem target ${id} not found`);
|
|
534
|
+
_siemCheckT(t.status, SIEM_TARGET_MATURITY_V2.ACTIVE);
|
|
535
|
+
const recovery = t.status === SIEM_TARGET_MATURITY_V2.DEGRADED;
|
|
536
|
+
if (!recovery) { const c = _siemCountActive(t.operator); if (c >= _siemMaxActivePerOperator) throw new Error(`max active siem targets per operator (${_siemMaxActivePerOperator}) reached for ${t.operator}`); }
|
|
537
|
+
const now = Date.now(); t.status = SIEM_TARGET_MATURITY_V2.ACTIVE; t.updatedAt = now; t.lastTouchedAt = now; if (!t.activatedAt) t.activatedAt = now;
|
|
538
|
+
return { ...t, metadata: { ...t.metadata } };
|
|
539
|
+
}
|
|
540
|
+
export function degradeSiemTargetV2(id) { const t = _siemTargets.get(id); if (!t) throw new Error(`siem target ${id} not found`); _siemCheckT(t.status, SIEM_TARGET_MATURITY_V2.DEGRADED); t.status = SIEM_TARGET_MATURITY_V2.DEGRADED; t.updatedAt = Date.now(); return { ...t, metadata: { ...t.metadata } }; }
|
|
541
|
+
export function retireSiemTargetV2(id) { const t = _siemTargets.get(id); if (!t) throw new Error(`siem target ${id} not found`); _siemCheckT(t.status, SIEM_TARGET_MATURITY_V2.RETIRED); const now = Date.now(); t.status = SIEM_TARGET_MATURITY_V2.RETIRED; t.updatedAt = now; if (!t.retiredAt) t.retiredAt = now; return { ...t, metadata: { ...t.metadata } }; }
|
|
542
|
+
export function touchSiemTargetV2(id) { const t = _siemTargets.get(id); if (!t) throw new Error(`siem target ${id} not found`); if (_siemTargetTerminal.has(t.status)) throw new Error(`cannot touch terminal siem target ${id}`); const now = Date.now(); t.lastTouchedAt = now; t.updatedAt = now; return { ...t, metadata: { ...t.metadata } }; }
|
|
543
|
+
export function getSiemTargetV2(id) { const t = _siemTargets.get(id); if (!t) return null; return { ...t, metadata: { ...t.metadata } }; }
|
|
544
|
+
export function listSiemTargetsV2() { return [..._siemTargets.values()].map((t) => ({ ...t, metadata: { ...t.metadata } })); }
|
|
545
|
+
|
|
546
|
+
function _siemCountPendingExports(tid) { let n = 0; for (const e of _siemExportJobs.values()) if (e.targetId === tid && (e.status === SIEM_EXPORT_LIFECYCLE_V2.QUEUED || e.status === SIEM_EXPORT_LIFECYCLE_V2.SENDING)) n++; return n; }
|
|
547
|
+
|
|
548
|
+
export function createSiemExportV2({ id, targetId, format, metadata } = {}) {
|
|
549
|
+
if (!id || typeof id !== "string") throw new Error("id is required");
|
|
550
|
+
if (!targetId || typeof targetId !== "string") throw new Error("targetId is required");
|
|
551
|
+
if (_siemExportJobs.has(id)) throw new Error(`siem export ${id} already exists`);
|
|
552
|
+
if (!_siemTargets.has(targetId)) throw new Error(`siem target ${targetId} not found`);
|
|
553
|
+
const pending = _siemCountPendingExports(targetId);
|
|
554
|
+
if (pending >= _siemMaxPendingExportsPerTarget) throw new Error(`max pending siem exports per target (${_siemMaxPendingExportsPerTarget}) reached for ${targetId}`);
|
|
555
|
+
const now = Date.now();
|
|
556
|
+
const e = { id, targetId, format: format || "json", status: SIEM_EXPORT_LIFECYCLE_V2.QUEUED, createdAt: now, updatedAt: now, startedAt: null, settledAt: null, metadata: { ...(metadata || {}) } };
|
|
557
|
+
_siemExportJobs.set(id, e);
|
|
558
|
+
return { ...e, metadata: { ...e.metadata } };
|
|
559
|
+
}
|
|
560
|
+
function _siemCheckE(from, to) { const a = _siemExportTrans.get(from); if (!a || !a.has(to)) throw new Error(`invalid siem export transition ${from} → ${to}`); }
|
|
561
|
+
export function startSiemExportV2(id) { const e = _siemExportJobs.get(id); if (!e) throw new Error(`siem export ${id} not found`); _siemCheckE(e.status, SIEM_EXPORT_LIFECYCLE_V2.SENDING); const now = Date.now(); e.status = SIEM_EXPORT_LIFECYCLE_V2.SENDING; e.updatedAt = now; if (!e.startedAt) e.startedAt = now; return { ...e, metadata: { ...e.metadata } }; }
|
|
562
|
+
export function deliverSiemExportV2(id) { const e = _siemExportJobs.get(id); if (!e) throw new Error(`siem export ${id} not found`); _siemCheckE(e.status, SIEM_EXPORT_LIFECYCLE_V2.DELIVERED); const now = Date.now(); e.status = SIEM_EXPORT_LIFECYCLE_V2.DELIVERED; e.updatedAt = now; if (!e.settledAt) e.settledAt = now; return { ...e, metadata: { ...e.metadata } }; }
|
|
563
|
+
export function failSiemExportV2(id, reason) { const e = _siemExportJobs.get(id); if (!e) throw new Error(`siem export ${id} not found`); _siemCheckE(e.status, SIEM_EXPORT_LIFECYCLE_V2.FAILED); const now = Date.now(); e.status = SIEM_EXPORT_LIFECYCLE_V2.FAILED; e.updatedAt = now; if (!e.settledAt) e.settledAt = now; if (reason) e.metadata.failReason = String(reason); return { ...e, metadata: { ...e.metadata } }; }
|
|
564
|
+
export function cancelSiemExportV2(id, reason) { const e = _siemExportJobs.get(id); if (!e) throw new Error(`siem export ${id} not found`); _siemCheckE(e.status, SIEM_EXPORT_LIFECYCLE_V2.CANCELLED); const now = Date.now(); e.status = SIEM_EXPORT_LIFECYCLE_V2.CANCELLED; e.updatedAt = now; if (!e.settledAt) e.settledAt = now; if (reason) e.metadata.cancelReason = String(reason); return { ...e, metadata: { ...e.metadata } }; }
|
|
565
|
+
export function getSiemExportV2(id) { const e = _siemExportJobs.get(id); if (!e) return null; return { ...e, metadata: { ...e.metadata } }; }
|
|
566
|
+
export function listSiemExportsV2() { return [..._siemExportJobs.values()].map((e) => ({ ...e, metadata: { ...e.metadata } })); }
|
|
567
|
+
|
|
568
|
+
export function autoDegradeIdleSiemTargetsV2({ now } = {}) { const t = now ?? Date.now(); const flipped = []; for (const tgt of _siemTargets.values()) if (tgt.status === SIEM_TARGET_MATURITY_V2.ACTIVE && (t - tgt.lastTouchedAt) >= _siemTargetIdleMs) { tgt.status = SIEM_TARGET_MATURITY_V2.DEGRADED; tgt.updatedAt = t; flipped.push(tgt.id); } return { flipped, count: flipped.length }; }
|
|
569
|
+
export function autoFailStuckSiemExportsV2({ now } = {}) { const t = now ?? Date.now(); const flipped = []; for (const e of _siemExportJobs.values()) if (e.status === SIEM_EXPORT_LIFECYCLE_V2.SENDING && e.startedAt != null && (t - e.startedAt) >= _siemExportStuckMs) { e.status = SIEM_EXPORT_LIFECYCLE_V2.FAILED; e.updatedAt = t; if (!e.settledAt) e.settledAt = t; e.metadata.failReason = "auto-fail-stuck"; flipped.push(e.id); } return { flipped, count: flipped.length }; }
|
|
570
|
+
|
|
571
|
+
export function getSiemExporterGovStatsV2() {
|
|
572
|
+
const targetsByStatus = {}; for (const s of Object.values(SIEM_TARGET_MATURITY_V2)) targetsByStatus[s] = 0; for (const t of _siemTargets.values()) targetsByStatus[t.status]++;
|
|
573
|
+
const exportsByStatus = {}; for (const s of Object.values(SIEM_EXPORT_LIFECYCLE_V2)) exportsByStatus[s] = 0; for (const e of _siemExportJobs.values()) exportsByStatus[e.status]++;
|
|
574
|
+
return { totalSiemTargetsV2: _siemTargets.size, totalSiemExportsV2: _siemExportJobs.size, maxActiveSiemTargetsPerOperator: _siemMaxActivePerOperator, maxPendingSiemExportsPerTarget: _siemMaxPendingExportsPerTarget, siemTargetIdleMs: _siemTargetIdleMs, siemExportStuckMs: _siemExportStuckMs, targetsByStatus, exportsByStatus };
|
|
575
|
+
}
|
package/src/lib/skill-loader.js
CHANGED
|
@@ -356,3 +356,380 @@ export class CLISkillLoader {
|
|
|
356
356
|
this._cache = null;
|
|
357
357
|
}
|
|
358
358
|
}
|
|
359
|
+
|
|
360
|
+
// ─── V2 Governance Layer ────────────────────────────────────────────
|
|
361
|
+
//
|
|
362
|
+
// In-memory governance for skill registrations + execution tickets,
|
|
363
|
+
// independent of the file-based 4-layer CLISkillLoader (which scans
|
|
364
|
+
// bundled/marketplace/managed/workspace dirs). V2 tracks maturity
|
|
365
|
+
// transitions, per-owner active-skill caps, per-skill pending-execution
|
|
366
|
+
// caps, stamp-once timestamps, and bulk auto-flip routines.
|
|
367
|
+
|
|
368
|
+
export const SKILL_MATURITY_V2 = Object.freeze({
|
|
369
|
+
PENDING: "pending",
|
|
370
|
+
ACTIVE: "active",
|
|
371
|
+
DEPRECATED: "deprecated",
|
|
372
|
+
ARCHIVED: "archived",
|
|
373
|
+
});
|
|
374
|
+
|
|
375
|
+
export const EXECUTION_LIFECYCLE_V2 = Object.freeze({
|
|
376
|
+
QUEUED: "queued",
|
|
377
|
+
RUNNING: "running",
|
|
378
|
+
SUCCEEDED: "succeeded",
|
|
379
|
+
FAILED: "failed",
|
|
380
|
+
CANCELLED: "cancelled",
|
|
381
|
+
});
|
|
382
|
+
|
|
383
|
+
const _SKILL_TRANSITIONS_V2 = new Map([
|
|
384
|
+
[
|
|
385
|
+
SKILL_MATURITY_V2.PENDING,
|
|
386
|
+
new Set([SKILL_MATURITY_V2.ACTIVE, SKILL_MATURITY_V2.ARCHIVED]),
|
|
387
|
+
],
|
|
388
|
+
[
|
|
389
|
+
SKILL_MATURITY_V2.ACTIVE,
|
|
390
|
+
new Set([SKILL_MATURITY_V2.DEPRECATED, SKILL_MATURITY_V2.ARCHIVED]),
|
|
391
|
+
],
|
|
392
|
+
[
|
|
393
|
+
SKILL_MATURITY_V2.DEPRECATED,
|
|
394
|
+
new Set([SKILL_MATURITY_V2.ACTIVE, SKILL_MATURITY_V2.ARCHIVED]),
|
|
395
|
+
],
|
|
396
|
+
[SKILL_MATURITY_V2.ARCHIVED, new Set()],
|
|
397
|
+
]);
|
|
398
|
+
|
|
399
|
+
const _SKILL_TERMINALS_V2 = new Set([SKILL_MATURITY_V2.ARCHIVED]);
|
|
400
|
+
|
|
401
|
+
const _EXEC_TRANSITIONS_V2 = new Map([
|
|
402
|
+
[
|
|
403
|
+
EXECUTION_LIFECYCLE_V2.QUEUED,
|
|
404
|
+
new Set([EXECUTION_LIFECYCLE_V2.RUNNING, EXECUTION_LIFECYCLE_V2.CANCELLED]),
|
|
405
|
+
],
|
|
406
|
+
[
|
|
407
|
+
EXECUTION_LIFECYCLE_V2.RUNNING,
|
|
408
|
+
new Set([
|
|
409
|
+
EXECUTION_LIFECYCLE_V2.SUCCEEDED,
|
|
410
|
+
EXECUTION_LIFECYCLE_V2.FAILED,
|
|
411
|
+
EXECUTION_LIFECYCLE_V2.CANCELLED,
|
|
412
|
+
]),
|
|
413
|
+
],
|
|
414
|
+
[EXECUTION_LIFECYCLE_V2.SUCCEEDED, new Set()],
|
|
415
|
+
[EXECUTION_LIFECYCLE_V2.FAILED, new Set()],
|
|
416
|
+
[EXECUTION_LIFECYCLE_V2.CANCELLED, new Set()],
|
|
417
|
+
]);
|
|
418
|
+
|
|
419
|
+
const _EXEC_TERMINALS_V2 = new Set([
|
|
420
|
+
EXECUTION_LIFECYCLE_V2.SUCCEEDED,
|
|
421
|
+
EXECUTION_LIFECYCLE_V2.FAILED,
|
|
422
|
+
EXECUTION_LIFECYCLE_V2.CANCELLED,
|
|
423
|
+
]);
|
|
424
|
+
|
|
425
|
+
export const SKILL_DEFAULT_MAX_ACTIVE_PER_OWNER = 30;
|
|
426
|
+
export const SKILL_DEFAULT_MAX_PENDING_EXECUTIONS_PER_SKILL = 5;
|
|
427
|
+
export const SKILL_DEFAULT_SKILL_IDLE_MS = 30 * 24 * 60 * 60 * 1000; // 30 days
|
|
428
|
+
export const SKILL_DEFAULT_EXEC_STUCK_MS = 15 * 60 * 1000; // 15 min
|
|
429
|
+
|
|
430
|
+
const _stateV2 = {
|
|
431
|
+
skills: new Map(),
|
|
432
|
+
executions: new Map(),
|
|
433
|
+
maxActiveSkillsPerOwner: SKILL_DEFAULT_MAX_ACTIVE_PER_OWNER,
|
|
434
|
+
maxPendingExecutionsPerSkill: SKILL_DEFAULT_MAX_PENDING_EXECUTIONS_PER_SKILL,
|
|
435
|
+
skillIdleMs: SKILL_DEFAULT_SKILL_IDLE_MS,
|
|
436
|
+
execStuckMs: SKILL_DEFAULT_EXEC_STUCK_MS,
|
|
437
|
+
};
|
|
438
|
+
|
|
439
|
+
function _posIntSkillV2(n, label) {
|
|
440
|
+
const v = Math.floor(Number(n));
|
|
441
|
+
if (!Number.isFinite(v) || v <= 0) {
|
|
442
|
+
throw new Error(`${label} must be a positive integer, got ${n}`);
|
|
443
|
+
}
|
|
444
|
+
return v;
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
export function getMaxActiveSkillsPerOwnerV2() {
|
|
448
|
+
return _stateV2.maxActiveSkillsPerOwner;
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
export function setMaxActiveSkillsPerOwnerV2(n) {
|
|
452
|
+
_stateV2.maxActiveSkillsPerOwner = _posIntSkillV2(
|
|
453
|
+
n,
|
|
454
|
+
"maxActiveSkillsPerOwner",
|
|
455
|
+
);
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
export function getMaxPendingExecutionsPerSkillV2() {
|
|
459
|
+
return _stateV2.maxPendingExecutionsPerSkill;
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
export function setMaxPendingExecutionsPerSkillV2(n) {
|
|
463
|
+
_stateV2.maxPendingExecutionsPerSkill = _posIntSkillV2(
|
|
464
|
+
n,
|
|
465
|
+
"maxPendingExecutionsPerSkill",
|
|
466
|
+
);
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
export function getSkillIdleMsV2() {
|
|
470
|
+
return _stateV2.skillIdleMs;
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
export function setSkillIdleMsV2(ms) {
|
|
474
|
+
_stateV2.skillIdleMs = _posIntSkillV2(ms, "skillIdleMs");
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
export function getExecStuckMsV2() {
|
|
478
|
+
return _stateV2.execStuckMs;
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
export function setExecStuckMsV2(ms) {
|
|
482
|
+
_stateV2.execStuckMs = _posIntSkillV2(ms, "execStuckMs");
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
function _copySkillV2(s) {
|
|
486
|
+
return { ...s, metadata: { ...s.metadata } };
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
function _copyExecV2(e) {
|
|
490
|
+
return { ...e, metadata: { ...e.metadata } };
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
export function getActiveSkillCountV2(ownerId) {
|
|
494
|
+
let count = 0;
|
|
495
|
+
for (const s of _stateV2.skills.values()) {
|
|
496
|
+
if (s.ownerId === ownerId && s.status === SKILL_MATURITY_V2.ACTIVE) count++;
|
|
497
|
+
}
|
|
498
|
+
return count;
|
|
499
|
+
}
|
|
500
|
+
|
|
501
|
+
export function getPendingExecutionCountV2(skillId) {
|
|
502
|
+
let count = 0;
|
|
503
|
+
for (const e of _stateV2.executions.values()) {
|
|
504
|
+
if (
|
|
505
|
+
e.skillId === skillId &&
|
|
506
|
+
(e.status === EXECUTION_LIFECYCLE_V2.QUEUED ||
|
|
507
|
+
e.status === EXECUTION_LIFECYCLE_V2.RUNNING)
|
|
508
|
+
) {
|
|
509
|
+
count++;
|
|
510
|
+
}
|
|
511
|
+
}
|
|
512
|
+
return count;
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
export function registerSkillV2(id, { ownerId, name, layer, metadata } = {}) {
|
|
516
|
+
if (!id) throw new Error("skill id is required");
|
|
517
|
+
if (!ownerId) throw new Error("ownerId is required");
|
|
518
|
+
if (!name) throw new Error("name is required");
|
|
519
|
+
if (_stateV2.skills.has(id)) throw new Error(`skill ${id} already exists`);
|
|
520
|
+
const now = Date.now();
|
|
521
|
+
const skill = {
|
|
522
|
+
id,
|
|
523
|
+
ownerId,
|
|
524
|
+
name,
|
|
525
|
+
layer: layer || "workspace",
|
|
526
|
+
status: SKILL_MATURITY_V2.PENDING,
|
|
527
|
+
createdAt: now,
|
|
528
|
+
lastSeenAt: now,
|
|
529
|
+
activatedAt: null,
|
|
530
|
+
archivedAt: null,
|
|
531
|
+
metadata: metadata ? { ...metadata } : {},
|
|
532
|
+
};
|
|
533
|
+
_stateV2.skills.set(id, skill);
|
|
534
|
+
return _copySkillV2(skill);
|
|
535
|
+
}
|
|
536
|
+
|
|
537
|
+
export function getSkillV2(id) {
|
|
538
|
+
const s = _stateV2.skills.get(id);
|
|
539
|
+
return s ? _copySkillV2(s) : null;
|
|
540
|
+
}
|
|
541
|
+
|
|
542
|
+
export function listSkillsV2({ ownerId, status, layer } = {}) {
|
|
543
|
+
const out = [];
|
|
544
|
+
for (const s of _stateV2.skills.values()) {
|
|
545
|
+
if (ownerId && s.ownerId !== ownerId) continue;
|
|
546
|
+
if (status && s.status !== status) continue;
|
|
547
|
+
if (layer && s.layer !== layer) continue;
|
|
548
|
+
out.push(_copySkillV2(s));
|
|
549
|
+
}
|
|
550
|
+
return out;
|
|
551
|
+
}
|
|
552
|
+
|
|
553
|
+
export function setSkillStatusV2(id, next) {
|
|
554
|
+
const s = _stateV2.skills.get(id);
|
|
555
|
+
if (!s) throw new Error(`skill ${id} not found`);
|
|
556
|
+
const allowed = _SKILL_TRANSITIONS_V2.get(s.status);
|
|
557
|
+
if (!allowed || !allowed.has(next)) {
|
|
558
|
+
throw new Error(`invalid skill transition: ${s.status} → ${next}`);
|
|
559
|
+
}
|
|
560
|
+
if (
|
|
561
|
+
s.status === SKILL_MATURITY_V2.PENDING &&
|
|
562
|
+
next === SKILL_MATURITY_V2.ACTIVE
|
|
563
|
+
) {
|
|
564
|
+
const count = getActiveSkillCountV2(s.ownerId);
|
|
565
|
+
if (count >= _stateV2.maxActiveSkillsPerOwner) {
|
|
566
|
+
throw new Error(
|
|
567
|
+
`owner ${s.ownerId} active-skill cap reached (${count}/${_stateV2.maxActiveSkillsPerOwner})`,
|
|
568
|
+
);
|
|
569
|
+
}
|
|
570
|
+
}
|
|
571
|
+
const now = Date.now();
|
|
572
|
+
s.status = next;
|
|
573
|
+
s.lastSeenAt = now;
|
|
574
|
+
if (next === SKILL_MATURITY_V2.ACTIVE && !s.activatedAt) s.activatedAt = now;
|
|
575
|
+
if (_SKILL_TERMINALS_V2.has(next) && !s.archivedAt) s.archivedAt = now;
|
|
576
|
+
return _copySkillV2(s);
|
|
577
|
+
}
|
|
578
|
+
|
|
579
|
+
export function activateSkillV2(id) {
|
|
580
|
+
return setSkillStatusV2(id, SKILL_MATURITY_V2.ACTIVE);
|
|
581
|
+
}
|
|
582
|
+
|
|
583
|
+
export function deprecateSkillV2(id) {
|
|
584
|
+
return setSkillStatusV2(id, SKILL_MATURITY_V2.DEPRECATED);
|
|
585
|
+
}
|
|
586
|
+
|
|
587
|
+
export function archiveSkillV2(id) {
|
|
588
|
+
return setSkillStatusV2(id, SKILL_MATURITY_V2.ARCHIVED);
|
|
589
|
+
}
|
|
590
|
+
|
|
591
|
+
export function touchSkillV2(id) {
|
|
592
|
+
const s = _stateV2.skills.get(id);
|
|
593
|
+
if (!s) throw new Error(`skill ${id} not found`);
|
|
594
|
+
s.lastSeenAt = Date.now();
|
|
595
|
+
return _copySkillV2(s);
|
|
596
|
+
}
|
|
597
|
+
|
|
598
|
+
export function createExecutionV2(id, { skillId, kind, metadata } = {}) {
|
|
599
|
+
if (!id) throw new Error("execution id is required");
|
|
600
|
+
if (!skillId) throw new Error("skillId is required");
|
|
601
|
+
if (_stateV2.executions.has(id))
|
|
602
|
+
throw new Error(`execution ${id} already exists`);
|
|
603
|
+
const skill = _stateV2.skills.get(skillId);
|
|
604
|
+
if (!skill) throw new Error(`skill ${skillId} not found`);
|
|
605
|
+
const pending = getPendingExecutionCountV2(skillId);
|
|
606
|
+
if (pending >= _stateV2.maxPendingExecutionsPerSkill) {
|
|
607
|
+
throw new Error(
|
|
608
|
+
`skill ${skillId} pending-execution cap reached (${pending}/${_stateV2.maxPendingExecutionsPerSkill})`,
|
|
609
|
+
);
|
|
610
|
+
}
|
|
611
|
+
const now = Date.now();
|
|
612
|
+
const exec = {
|
|
613
|
+
id,
|
|
614
|
+
skillId,
|
|
615
|
+
kind: kind || "invoke",
|
|
616
|
+
status: EXECUTION_LIFECYCLE_V2.QUEUED,
|
|
617
|
+
createdAt: now,
|
|
618
|
+
lastSeenAt: now,
|
|
619
|
+
startedAt: null,
|
|
620
|
+
settledAt: null,
|
|
621
|
+
metadata: metadata ? { ...metadata } : {},
|
|
622
|
+
};
|
|
623
|
+
_stateV2.executions.set(id, exec);
|
|
624
|
+
return _copyExecV2(exec);
|
|
625
|
+
}
|
|
626
|
+
|
|
627
|
+
export function getExecutionV2(id) {
|
|
628
|
+
const e = _stateV2.executions.get(id);
|
|
629
|
+
return e ? _copyExecV2(e) : null;
|
|
630
|
+
}
|
|
631
|
+
|
|
632
|
+
export function listExecutionsV2({ skillId, status } = {}) {
|
|
633
|
+
const out = [];
|
|
634
|
+
for (const e of _stateV2.executions.values()) {
|
|
635
|
+
if (skillId && e.skillId !== skillId) continue;
|
|
636
|
+
if (status && e.status !== status) continue;
|
|
637
|
+
out.push(_copyExecV2(e));
|
|
638
|
+
}
|
|
639
|
+
return out;
|
|
640
|
+
}
|
|
641
|
+
|
|
642
|
+
export function setExecutionStatusV2(id, next) {
|
|
643
|
+
const e = _stateV2.executions.get(id);
|
|
644
|
+
if (!e) throw new Error(`execution ${id} not found`);
|
|
645
|
+
const allowed = _EXEC_TRANSITIONS_V2.get(e.status);
|
|
646
|
+
if (!allowed || !allowed.has(next)) {
|
|
647
|
+
throw new Error(`invalid execution transition: ${e.status} → ${next}`);
|
|
648
|
+
}
|
|
649
|
+
const now = Date.now();
|
|
650
|
+
e.status = next;
|
|
651
|
+
e.lastSeenAt = now;
|
|
652
|
+
if (next === EXECUTION_LIFECYCLE_V2.RUNNING && !e.startedAt)
|
|
653
|
+
e.startedAt = now;
|
|
654
|
+
if (_EXEC_TERMINALS_V2.has(next) && !e.settledAt) e.settledAt = now;
|
|
655
|
+
return _copyExecV2(e);
|
|
656
|
+
}
|
|
657
|
+
|
|
658
|
+
export function startExecutionV2(id) {
|
|
659
|
+
return setExecutionStatusV2(id, EXECUTION_LIFECYCLE_V2.RUNNING);
|
|
660
|
+
}
|
|
661
|
+
|
|
662
|
+
export function succeedExecutionV2(id) {
|
|
663
|
+
return setExecutionStatusV2(id, EXECUTION_LIFECYCLE_V2.SUCCEEDED);
|
|
664
|
+
}
|
|
665
|
+
|
|
666
|
+
export function failExecutionV2(id) {
|
|
667
|
+
return setExecutionStatusV2(id, EXECUTION_LIFECYCLE_V2.FAILED);
|
|
668
|
+
}
|
|
669
|
+
|
|
670
|
+
export function cancelExecutionV2(id) {
|
|
671
|
+
return setExecutionStatusV2(id, EXECUTION_LIFECYCLE_V2.CANCELLED);
|
|
672
|
+
}
|
|
673
|
+
|
|
674
|
+
export function autoDeprecateIdleSkillsV2({ now = Date.now() } = {}) {
|
|
675
|
+
const flipped = [];
|
|
676
|
+
for (const s of _stateV2.skills.values()) {
|
|
677
|
+
if (
|
|
678
|
+
s.status === SKILL_MATURITY_V2.ACTIVE &&
|
|
679
|
+
now - s.lastSeenAt > _stateV2.skillIdleMs
|
|
680
|
+
) {
|
|
681
|
+
s.status = SKILL_MATURITY_V2.DEPRECATED;
|
|
682
|
+
s.lastSeenAt = now;
|
|
683
|
+
flipped.push(_copySkillV2(s));
|
|
684
|
+
}
|
|
685
|
+
}
|
|
686
|
+
return flipped;
|
|
687
|
+
}
|
|
688
|
+
|
|
689
|
+
export function autoFailStuckExecutionsV2({ now = Date.now() } = {}) {
|
|
690
|
+
const flipped = [];
|
|
691
|
+
for (const e of _stateV2.executions.values()) {
|
|
692
|
+
if (
|
|
693
|
+
e.status === EXECUTION_LIFECYCLE_V2.RUNNING &&
|
|
694
|
+
now - e.lastSeenAt > _stateV2.execStuckMs
|
|
695
|
+
) {
|
|
696
|
+
e.status = EXECUTION_LIFECYCLE_V2.FAILED;
|
|
697
|
+
e.lastSeenAt = now;
|
|
698
|
+
if (!e.settledAt) e.settledAt = now;
|
|
699
|
+
flipped.push(_copyExecV2(e));
|
|
700
|
+
}
|
|
701
|
+
}
|
|
702
|
+
return flipped;
|
|
703
|
+
}
|
|
704
|
+
|
|
705
|
+
export function getSkillLoaderStatsV2() {
|
|
706
|
+
const skillsByStatus = {};
|
|
707
|
+
for (const v of Object.values(SKILL_MATURITY_V2)) skillsByStatus[v] = 0;
|
|
708
|
+
for (const s of _stateV2.skills.values()) skillsByStatus[s.status]++;
|
|
709
|
+
|
|
710
|
+
const executionsByStatus = {};
|
|
711
|
+
for (const v of Object.values(EXECUTION_LIFECYCLE_V2))
|
|
712
|
+
executionsByStatus[v] = 0;
|
|
713
|
+
for (const e of _stateV2.executions.values()) executionsByStatus[e.status]++;
|
|
714
|
+
|
|
715
|
+
return {
|
|
716
|
+
totalSkillsV2: _stateV2.skills.size,
|
|
717
|
+
totalExecutionsV2: _stateV2.executions.size,
|
|
718
|
+
maxActiveSkillsPerOwner: _stateV2.maxActiveSkillsPerOwner,
|
|
719
|
+
maxPendingExecutionsPerSkill: _stateV2.maxPendingExecutionsPerSkill,
|
|
720
|
+
skillIdleMs: _stateV2.skillIdleMs,
|
|
721
|
+
execStuckMs: _stateV2.execStuckMs,
|
|
722
|
+
skillsByStatus,
|
|
723
|
+
executionsByStatus,
|
|
724
|
+
};
|
|
725
|
+
}
|
|
726
|
+
|
|
727
|
+
export function _resetStateSkillLoaderV2() {
|
|
728
|
+
_stateV2.skills.clear();
|
|
729
|
+
_stateV2.executions.clear();
|
|
730
|
+
_stateV2.maxActiveSkillsPerOwner = SKILL_DEFAULT_MAX_ACTIVE_PER_OWNER;
|
|
731
|
+
_stateV2.maxPendingExecutionsPerSkill =
|
|
732
|
+
SKILL_DEFAULT_MAX_PENDING_EXECUTIONS_PER_SKILL;
|
|
733
|
+
_stateV2.skillIdleMs = SKILL_DEFAULT_SKILL_IDLE_MS;
|
|
734
|
+
_stateV2.execStuckMs = SKILL_DEFAULT_EXEC_STUCK_MS;
|
|
735
|
+
}
|
package/src/lib/slot-filler.js
CHANGED
|
@@ -596,3 +596,84 @@ Keep values concise (single words or short strings).`;
|
|
|
596
596
|
return Object.keys(REQUIRED_SLOTS);
|
|
597
597
|
}
|
|
598
598
|
}
|
|
599
|
+
|
|
600
|
+
// ===== V2 Surface: Slot Filler governance overlay (CLI v0.142.0) =====
|
|
601
|
+
export const SLOTF_PROFILE_MATURITY_V2 = Object.freeze({
|
|
602
|
+
PENDING: "pending", ACTIVE: "active", STALE: "stale", ARCHIVED: "archived",
|
|
603
|
+
});
|
|
604
|
+
export const SLOTF_FILL_LIFECYCLE_V2 = Object.freeze({
|
|
605
|
+
QUEUED: "queued", FILLING: "filling", FILLED: "filled", FAILED: "failed", CANCELLED: "cancelled",
|
|
606
|
+
});
|
|
607
|
+
const _slotfPTrans = new Map([
|
|
608
|
+
[SLOTF_PROFILE_MATURITY_V2.PENDING, new Set([SLOTF_PROFILE_MATURITY_V2.ACTIVE, SLOTF_PROFILE_MATURITY_V2.ARCHIVED])],
|
|
609
|
+
[SLOTF_PROFILE_MATURITY_V2.ACTIVE, new Set([SLOTF_PROFILE_MATURITY_V2.STALE, SLOTF_PROFILE_MATURITY_V2.ARCHIVED])],
|
|
610
|
+
[SLOTF_PROFILE_MATURITY_V2.STALE, new Set([SLOTF_PROFILE_MATURITY_V2.ACTIVE, SLOTF_PROFILE_MATURITY_V2.ARCHIVED])],
|
|
611
|
+
[SLOTF_PROFILE_MATURITY_V2.ARCHIVED, new Set()],
|
|
612
|
+
]);
|
|
613
|
+
const _slotfPTerminal = new Set([SLOTF_PROFILE_MATURITY_V2.ARCHIVED]);
|
|
614
|
+
const _slotfFTrans = new Map([
|
|
615
|
+
[SLOTF_FILL_LIFECYCLE_V2.QUEUED, new Set([SLOTF_FILL_LIFECYCLE_V2.FILLING, SLOTF_FILL_LIFECYCLE_V2.CANCELLED])],
|
|
616
|
+
[SLOTF_FILL_LIFECYCLE_V2.FILLING, new Set([SLOTF_FILL_LIFECYCLE_V2.FILLED, SLOTF_FILL_LIFECYCLE_V2.FAILED, SLOTF_FILL_LIFECYCLE_V2.CANCELLED])],
|
|
617
|
+
[SLOTF_FILL_LIFECYCLE_V2.FILLED, new Set()],
|
|
618
|
+
[SLOTF_FILL_LIFECYCLE_V2.FAILED, new Set()],
|
|
619
|
+
[SLOTF_FILL_LIFECYCLE_V2.CANCELLED, new Set()],
|
|
620
|
+
]);
|
|
621
|
+
const _slotfPsV2 = new Map();
|
|
622
|
+
const _slotfFsV2 = new Map();
|
|
623
|
+
let _slotfMaxActive = 10, _slotfMaxPending = 20, _slotfIdleMs = 30 * 24 * 60 * 60 * 1000, _slotfStuckMs = 30 * 1000;
|
|
624
|
+
function _slotfPos(n, label) { const v = Math.floor(Number(n)); if (!Number.isFinite(v) || v <= 0) throw new Error(`${label} must be positive integer`); return v; }
|
|
625
|
+
function _slotfCheckP(from, to) { const a = _slotfPTrans.get(from); if (!a || !a.has(to)) throw new Error(`invalid slotf profile transition ${from} → ${to}`); }
|
|
626
|
+
function _slotfCheckF(from, to) { const a = _slotfFTrans.get(from); if (!a || !a.has(to)) throw new Error(`invalid slotf fill transition ${from} → ${to}`); }
|
|
627
|
+
export function setMaxActiveSlotfTemplatesPerOwnerV2(n) { _slotfMaxActive = _slotfPos(n, "maxActiveSlotfTemplatesPerOwner"); }
|
|
628
|
+
export function getMaxActiveSlotfTemplatesPerOwnerV2() { return _slotfMaxActive; }
|
|
629
|
+
export function setMaxPendingSlotfFillsPerTemplateV2(n) { _slotfMaxPending = _slotfPos(n, "maxPendingSlotfFillsPerTemplate"); }
|
|
630
|
+
export function getMaxPendingSlotfFillsPerTemplateV2() { return _slotfMaxPending; }
|
|
631
|
+
export function setSlotfTemplateIdleMsV2(n) { _slotfIdleMs = _slotfPos(n, "slotfTemplateIdleMs"); }
|
|
632
|
+
export function getSlotfTemplateIdleMsV2() { return _slotfIdleMs; }
|
|
633
|
+
export function setSlotfFillStuckMsV2(n) { _slotfStuckMs = _slotfPos(n, "slotfFillStuckMs"); }
|
|
634
|
+
export function getSlotfFillStuckMsV2() { return _slotfStuckMs; }
|
|
635
|
+
export function _resetStateSlotFillerV2() { _slotfPsV2.clear(); _slotfFsV2.clear(); _slotfMaxActive = 10; _slotfMaxPending = 20; _slotfIdleMs = 30 * 24 * 60 * 60 * 1000; _slotfStuckMs = 30 * 1000; }
|
|
636
|
+
export function registerSlotfTemplateV2({ id, owner, schema, metadata } = {}) {
|
|
637
|
+
if (!id) throw new Error("slotf template id required"); if (!owner) throw new Error("slotf template owner required");
|
|
638
|
+
if (_slotfPsV2.has(id)) throw new Error(`slotf template ${id} already registered`);
|
|
639
|
+
const now = Date.now();
|
|
640
|
+
const p = { id, owner, schema: schema || "{}", status: SLOTF_PROFILE_MATURITY_V2.PENDING, createdAt: now, updatedAt: now, activatedAt: null, archivedAt: null, lastTouchedAt: now, metadata: { ...(metadata || {}) } };
|
|
641
|
+
_slotfPsV2.set(id, p); return { ...p, metadata: { ...p.metadata } };
|
|
642
|
+
}
|
|
643
|
+
function _slotfCountActive(owner) { let n = 0; for (const p of _slotfPsV2.values()) if (p.owner === owner && p.status === SLOTF_PROFILE_MATURITY_V2.ACTIVE) n++; return n; }
|
|
644
|
+
export function activateSlotfTemplateV2(id) {
|
|
645
|
+
const p = _slotfPsV2.get(id); if (!p) throw new Error(`slotf template ${id} not found`);
|
|
646
|
+
_slotfCheckP(p.status, SLOTF_PROFILE_MATURITY_V2.ACTIVE);
|
|
647
|
+
const recovery = p.status === SLOTF_PROFILE_MATURITY_V2.STALE;
|
|
648
|
+
if (!recovery && _slotfCountActive(p.owner) >= _slotfMaxActive) throw new Error(`max active slotf templates for owner ${p.owner} reached`);
|
|
649
|
+
const now = Date.now(); p.status = SLOTF_PROFILE_MATURITY_V2.ACTIVE; p.updatedAt = now; p.lastTouchedAt = now; if (!p.activatedAt) p.activatedAt = now;
|
|
650
|
+
return { ...p, metadata: { ...p.metadata } };
|
|
651
|
+
}
|
|
652
|
+
export function staleSlotfTemplateV2(id) { const p = _slotfPsV2.get(id); if (!p) throw new Error(`slotf template ${id} not found`); _slotfCheckP(p.status, SLOTF_PROFILE_MATURITY_V2.STALE); p.status = SLOTF_PROFILE_MATURITY_V2.STALE; p.updatedAt = Date.now(); return { ...p, metadata: { ...p.metadata } }; }
|
|
653
|
+
export function archiveSlotfTemplateV2(id) { const p = _slotfPsV2.get(id); if (!p) throw new Error(`slotf template ${id} not found`); _slotfCheckP(p.status, SLOTF_PROFILE_MATURITY_V2.ARCHIVED); const now = Date.now(); p.status = SLOTF_PROFILE_MATURITY_V2.ARCHIVED; p.updatedAt = now; if (!p.archivedAt) p.archivedAt = now; return { ...p, metadata: { ...p.metadata } }; }
|
|
654
|
+
export function touchSlotfTemplateV2(id) { const p = _slotfPsV2.get(id); if (!p) throw new Error(`slotf template ${id} not found`); if (_slotfPTerminal.has(p.status)) throw new Error(`cannot touch terminal slotf template ${id}`); const now = Date.now(); p.lastTouchedAt = now; p.updatedAt = now; return { ...p, metadata: { ...p.metadata } }; }
|
|
655
|
+
export function getSlotfTemplateV2(id) { const p = _slotfPsV2.get(id); if (!p) return null; return { ...p, metadata: { ...p.metadata } }; }
|
|
656
|
+
export function listSlotfTemplatesV2() { return [..._slotfPsV2.values()].map((p) => ({ ...p, metadata: { ...p.metadata } })); }
|
|
657
|
+
function _slotfCountPending(templateId) { let n = 0; for (const f of _slotfFsV2.values()) if (f.templateId === templateId && (f.status === SLOTF_FILL_LIFECYCLE_V2.QUEUED || f.status === SLOTF_FILL_LIFECYCLE_V2.FILLING)) n++; return n; }
|
|
658
|
+
export function createSlotfFillV2({ id, templateId, input, metadata } = {}) {
|
|
659
|
+
if (!id) throw new Error("slotf fill id required"); if (!templateId) throw new Error("slotf fill templateId required");
|
|
660
|
+
if (_slotfFsV2.has(id)) throw new Error(`slotf fill ${id} already exists`);
|
|
661
|
+
if (!_slotfPsV2.has(templateId)) throw new Error(`slotf template ${templateId} not found`);
|
|
662
|
+
if (_slotfCountPending(templateId) >= _slotfMaxPending) throw new Error(`max pending slotf fills for template ${templateId} reached`);
|
|
663
|
+
const now = Date.now();
|
|
664
|
+
const f = { id, templateId, input: input || "", status: SLOTF_FILL_LIFECYCLE_V2.QUEUED, createdAt: now, updatedAt: now, startedAt: null, settledAt: null, metadata: { ...(metadata || {}) } };
|
|
665
|
+
_slotfFsV2.set(id, f); return { ...f, metadata: { ...f.metadata } };
|
|
666
|
+
}
|
|
667
|
+
export function fillingSlotfFillV2(id) { const f = _slotfFsV2.get(id); if (!f) throw new Error(`slotf fill ${id} not found`); _slotfCheckF(f.status, SLOTF_FILL_LIFECYCLE_V2.FILLING); const now = Date.now(); f.status = SLOTF_FILL_LIFECYCLE_V2.FILLING; f.updatedAt = now; if (!f.startedAt) f.startedAt = now; return { ...f, metadata: { ...f.metadata } }; }
|
|
668
|
+
export function fillSlotfFillV2(id) { const f = _slotfFsV2.get(id); if (!f) throw new Error(`slotf fill ${id} not found`); _slotfCheckF(f.status, SLOTF_FILL_LIFECYCLE_V2.FILLED); const now = Date.now(); f.status = SLOTF_FILL_LIFECYCLE_V2.FILLED; f.updatedAt = now; if (!f.settledAt) f.settledAt = now; return { ...f, metadata: { ...f.metadata } }; }
|
|
669
|
+
export function failSlotfFillV2(id, reason) { const f = _slotfFsV2.get(id); if (!f) throw new Error(`slotf fill ${id} not found`); _slotfCheckF(f.status, SLOTF_FILL_LIFECYCLE_V2.FAILED); const now = Date.now(); f.status = SLOTF_FILL_LIFECYCLE_V2.FAILED; f.updatedAt = now; if (!f.settledAt) f.settledAt = now; if (reason) f.metadata.failReason = String(reason); return { ...f, metadata: { ...f.metadata } }; }
|
|
670
|
+
export function cancelSlotfFillV2(id, reason) { const f = _slotfFsV2.get(id); if (!f) throw new Error(`slotf fill ${id} not found`); _slotfCheckF(f.status, SLOTF_FILL_LIFECYCLE_V2.CANCELLED); const now = Date.now(); f.status = SLOTF_FILL_LIFECYCLE_V2.CANCELLED; f.updatedAt = now; if (!f.settledAt) f.settledAt = now; if (reason) f.metadata.cancelReason = String(reason); return { ...f, metadata: { ...f.metadata } }; }
|
|
671
|
+
export function getSlotfFillV2(id) { const f = _slotfFsV2.get(id); if (!f) return null; return { ...f, metadata: { ...f.metadata } }; }
|
|
672
|
+
export function listSlotfFillsV2() { return [..._slotfFsV2.values()].map((f) => ({ ...f, metadata: { ...f.metadata } })); }
|
|
673
|
+
export function autoStaleIdleSlotfTemplatesV2({ now } = {}) { const t = now ?? Date.now(); const flipped = []; for (const p of _slotfPsV2.values()) if (p.status === SLOTF_PROFILE_MATURITY_V2.ACTIVE && (t - p.lastTouchedAt) >= _slotfIdleMs) { p.status = SLOTF_PROFILE_MATURITY_V2.STALE; p.updatedAt = t; flipped.push(p.id); } return { flipped, count: flipped.length }; }
|
|
674
|
+
export function autoFailStuckSlotfFillsV2({ now } = {}) { const t = now ?? Date.now(); const flipped = []; for (const f of _slotfFsV2.values()) if (f.status === SLOTF_FILL_LIFECYCLE_V2.FILLING && f.startedAt != null && (t - f.startedAt) >= _slotfStuckMs) { f.status = SLOTF_FILL_LIFECYCLE_V2.FAILED; f.updatedAt = t; if (!f.settledAt) f.settledAt = t; f.metadata.failReason = "auto-fail-stuck"; flipped.push(f.id); } return { flipped, count: flipped.length }; }
|
|
675
|
+
export function getSlotFillerGovStatsV2() {
|
|
676
|
+
const templatesByStatus = {}; for (const v of Object.values(SLOTF_PROFILE_MATURITY_V2)) templatesByStatus[v] = 0; for (const p of _slotfPsV2.values()) templatesByStatus[p.status]++;
|
|
677
|
+
const fillsByStatus = {}; for (const v of Object.values(SLOTF_FILL_LIFECYCLE_V2)) fillsByStatus[v] = 0; for (const f of _slotfFsV2.values()) fillsByStatus[f.status]++;
|
|
678
|
+
return { totalSlotfTemplatesV2: _slotfPsV2.size, totalSlotfFillsV2: _slotfFsV2.size, maxActiveSlotfTemplatesPerOwner: _slotfMaxActive, maxPendingSlotfFillsPerTemplate: _slotfMaxPending, slotfTemplateIdleMs: _slotfIdleMs, slotfFillStuckMs: _slotfStuckMs, templatesByStatus, fillsByStatus };
|
|
679
|
+
}
|