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/pdf-parser.js
CHANGED
|
@@ -94,3 +94,84 @@ function decodePdfString(str) {
|
|
|
94
94
|
.replace(/\\\)/g, ")")
|
|
95
95
|
.replace(/\\\\/g, "\\");
|
|
96
96
|
}
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
// =====================================================================
|
|
100
|
+
// PDF Parser V2 governance overlay
|
|
101
|
+
// =====================================================================
|
|
102
|
+
export const PDFP_PROFILE_MATURITY_V2 = Object.freeze({ PENDING: "pending", ACTIVE: "active", STALE: "stale", ARCHIVED: "archived" });
|
|
103
|
+
export const PDFP_PARSE_LIFECYCLE_V2 = Object.freeze({ QUEUED: "queued", PARSING: "parsing", PARSED: "parsed", FAILED: "failed", CANCELLED: "cancelled" });
|
|
104
|
+
const _pdfpPTrans = new Map([
|
|
105
|
+
[PDFP_PROFILE_MATURITY_V2.PENDING, new Set([PDFP_PROFILE_MATURITY_V2.ACTIVE, PDFP_PROFILE_MATURITY_V2.ARCHIVED])],
|
|
106
|
+
[PDFP_PROFILE_MATURITY_V2.ACTIVE, new Set([PDFP_PROFILE_MATURITY_V2.STALE, PDFP_PROFILE_MATURITY_V2.ARCHIVED])],
|
|
107
|
+
[PDFP_PROFILE_MATURITY_V2.STALE, new Set([PDFP_PROFILE_MATURITY_V2.ACTIVE, PDFP_PROFILE_MATURITY_V2.ARCHIVED])],
|
|
108
|
+
[PDFP_PROFILE_MATURITY_V2.ARCHIVED, new Set()],
|
|
109
|
+
]);
|
|
110
|
+
const _pdfpPTerminal = new Set([PDFP_PROFILE_MATURITY_V2.ARCHIVED]);
|
|
111
|
+
const _pdfpJTrans = new Map([
|
|
112
|
+
[PDFP_PARSE_LIFECYCLE_V2.QUEUED, new Set([PDFP_PARSE_LIFECYCLE_V2.PARSING, PDFP_PARSE_LIFECYCLE_V2.CANCELLED])],
|
|
113
|
+
[PDFP_PARSE_LIFECYCLE_V2.PARSING, new Set([PDFP_PARSE_LIFECYCLE_V2.PARSED, PDFP_PARSE_LIFECYCLE_V2.FAILED, PDFP_PARSE_LIFECYCLE_V2.CANCELLED])],
|
|
114
|
+
[PDFP_PARSE_LIFECYCLE_V2.PARSED, new Set()],
|
|
115
|
+
[PDFP_PARSE_LIFECYCLE_V2.FAILED, new Set()],
|
|
116
|
+
[PDFP_PARSE_LIFECYCLE_V2.CANCELLED, new Set()],
|
|
117
|
+
]);
|
|
118
|
+
const _pdfpPsV2 = new Map();
|
|
119
|
+
const _pdfpJsV2 = new Map();
|
|
120
|
+
let _pdfpMaxActive = 6, _pdfpMaxPending = 12, _pdfpIdleMs = 30 * 24 * 60 * 60 * 1000, _pdfpStuckMs = 60 * 1000;
|
|
121
|
+
function _pdfpPos(n, label) { const v = Math.floor(Number(n)); if (!Number.isFinite(v) || v <= 0) throw new Error(`${label} must be positive integer`); return v; }
|
|
122
|
+
function _pdfpCheckP(from, to) { const a = _pdfpPTrans.get(from); if (!a || !a.has(to)) throw new Error(`invalid pdfp profile transition ${from} → ${to}`); }
|
|
123
|
+
function _pdfpCheckJ(from, to) { const a = _pdfpJTrans.get(from); if (!a || !a.has(to)) throw new Error(`invalid pdfp parse transition ${from} → ${to}`); }
|
|
124
|
+
function _pdfpCountActive(owner) { let c = 0; for (const p of _pdfpPsV2.values()) if (p.owner === owner && p.status === PDFP_PROFILE_MATURITY_V2.ACTIVE) c++; return c; }
|
|
125
|
+
function _pdfpCountPending(profileId) { let c = 0; for (const j of _pdfpJsV2.values()) if (j.profileId === profileId && (j.status === PDFP_PARSE_LIFECYCLE_V2.QUEUED || j.status === PDFP_PARSE_LIFECYCLE_V2.PARSING)) c++; return c; }
|
|
126
|
+
export function setMaxActivePdfpProfilesPerOwnerV2(n) { _pdfpMaxActive = _pdfpPos(n, "maxActivePdfpProfilesPerOwner"); }
|
|
127
|
+
export function getMaxActivePdfpProfilesPerOwnerV2() { return _pdfpMaxActive; }
|
|
128
|
+
export function setMaxPendingPdfpParsesPerProfileV2(n) { _pdfpMaxPending = _pdfpPos(n, "maxPendingPdfpParsesPerProfile"); }
|
|
129
|
+
export function getMaxPendingPdfpParsesPerProfileV2() { return _pdfpMaxPending; }
|
|
130
|
+
export function setPdfpProfileIdleMsV2(n) { _pdfpIdleMs = _pdfpPos(n, "pdfpProfileIdleMs"); }
|
|
131
|
+
export function getPdfpProfileIdleMsV2() { return _pdfpIdleMs; }
|
|
132
|
+
export function setPdfpParseStuckMsV2(n) { _pdfpStuckMs = _pdfpPos(n, "pdfpParseStuckMs"); }
|
|
133
|
+
export function getPdfpParseStuckMsV2() { return _pdfpStuckMs; }
|
|
134
|
+
export function _resetStatePdfParserV2() { _pdfpPsV2.clear(); _pdfpJsV2.clear(); _pdfpMaxActive = 6; _pdfpMaxPending = 12; _pdfpIdleMs = 30 * 24 * 60 * 60 * 1000; _pdfpStuckMs = 60 * 1000; }
|
|
135
|
+
export function registerPdfpProfileV2({ id, owner, encoding, metadata } = {}) {
|
|
136
|
+
if (!id || !owner) throw new Error("id and owner required");
|
|
137
|
+
if (_pdfpPsV2.has(id)) throw new Error(`pdfp profile ${id} already exists`);
|
|
138
|
+
const now = Date.now();
|
|
139
|
+
const p = { id, owner, encoding: encoding || "utf-8", status: PDFP_PROFILE_MATURITY_V2.PENDING, createdAt: now, updatedAt: now, lastTouchedAt: now, activatedAt: null, archivedAt: null, metadata: { ...(metadata || {}) } };
|
|
140
|
+
_pdfpPsV2.set(id, p); return { ...p, metadata: { ...p.metadata } };
|
|
141
|
+
}
|
|
142
|
+
export function activatePdfpProfileV2(id) {
|
|
143
|
+
const p = _pdfpPsV2.get(id); if (!p) throw new Error(`pdfp profile ${id} not found`);
|
|
144
|
+
const isInitial = p.status === PDFP_PROFILE_MATURITY_V2.PENDING;
|
|
145
|
+
_pdfpCheckP(p.status, PDFP_PROFILE_MATURITY_V2.ACTIVE);
|
|
146
|
+
if (isInitial && _pdfpCountActive(p.owner) >= _pdfpMaxActive) throw new Error(`max active pdfp profiles for owner ${p.owner} reached`);
|
|
147
|
+
const now = Date.now(); p.status = PDFP_PROFILE_MATURITY_V2.ACTIVE; p.updatedAt = now; p.lastTouchedAt = now;
|
|
148
|
+
if (!p.activatedAt) p.activatedAt = now;
|
|
149
|
+
return { ...p, metadata: { ...p.metadata } };
|
|
150
|
+
}
|
|
151
|
+
export function stalePdfpProfileV2(id) { const p = _pdfpPsV2.get(id); if (!p) throw new Error(`pdfp profile ${id} not found`); _pdfpCheckP(p.status, PDFP_PROFILE_MATURITY_V2.STALE); p.status = PDFP_PROFILE_MATURITY_V2.STALE; p.updatedAt = Date.now(); return { ...p, metadata: { ...p.metadata } }; }
|
|
152
|
+
export function archivePdfpProfileV2(id) { const p = _pdfpPsV2.get(id); if (!p) throw new Error(`pdfp profile ${id} not found`); _pdfpCheckP(p.status, PDFP_PROFILE_MATURITY_V2.ARCHIVED); const now = Date.now(); p.status = PDFP_PROFILE_MATURITY_V2.ARCHIVED; p.updatedAt = now; if (!p.archivedAt) p.archivedAt = now; return { ...p, metadata: { ...p.metadata } }; }
|
|
153
|
+
export function touchPdfpProfileV2(id) { const p = _pdfpPsV2.get(id); if (!p) throw new Error(`pdfp profile ${id} not found`); if (_pdfpPTerminal.has(p.status)) throw new Error(`cannot touch terminal pdfp profile ${id}`); const now = Date.now(); p.lastTouchedAt = now; p.updatedAt = now; return { ...p, metadata: { ...p.metadata } }; }
|
|
154
|
+
export function getPdfpProfileV2(id) { const p = _pdfpPsV2.get(id); if (!p) return null; return { ...p, metadata: { ...p.metadata } }; }
|
|
155
|
+
export function listPdfpProfilesV2() { return [..._pdfpPsV2.values()].map((p) => ({ ...p, metadata: { ...p.metadata } })); }
|
|
156
|
+
export function createPdfpParseV2({ id, profileId, path, metadata } = {}) {
|
|
157
|
+
if (!id || !profileId) throw new Error("id and profileId required");
|
|
158
|
+
if (_pdfpJsV2.has(id)) throw new Error(`pdfp parse ${id} already exists`);
|
|
159
|
+
if (!_pdfpPsV2.has(profileId)) throw new Error(`pdfp profile ${profileId} not found`);
|
|
160
|
+
if (_pdfpCountPending(profileId) >= _pdfpMaxPending) throw new Error(`max pending pdfp parses for profile ${profileId} reached`);
|
|
161
|
+
const now = Date.now();
|
|
162
|
+
const j = { id, profileId, path: path || "", status: PDFP_PARSE_LIFECYCLE_V2.QUEUED, createdAt: now, updatedAt: now, startedAt: null, settledAt: null, metadata: { ...(metadata || {}) } };
|
|
163
|
+
_pdfpJsV2.set(id, j); return { ...j, metadata: { ...j.metadata } };
|
|
164
|
+
}
|
|
165
|
+
export function parsingPdfpParseV2(id) { const j = _pdfpJsV2.get(id); if (!j) throw new Error(`pdfp parse ${id} not found`); _pdfpCheckJ(j.status, PDFP_PARSE_LIFECYCLE_V2.PARSING); const now = Date.now(); j.status = PDFP_PARSE_LIFECYCLE_V2.PARSING; j.updatedAt = now; if (!j.startedAt) j.startedAt = now; return { ...j, metadata: { ...j.metadata } }; }
|
|
166
|
+
export function parsePdfpParseV2(id) { const j = _pdfpJsV2.get(id); if (!j) throw new Error(`pdfp parse ${id} not found`); _pdfpCheckJ(j.status, PDFP_PARSE_LIFECYCLE_V2.PARSED); const now = Date.now(); j.status = PDFP_PARSE_LIFECYCLE_V2.PARSED; j.updatedAt = now; if (!j.settledAt) j.settledAt = now; return { ...j, metadata: { ...j.metadata } }; }
|
|
167
|
+
export function failPdfpParseV2(id, reason) { const j = _pdfpJsV2.get(id); if (!j) throw new Error(`pdfp parse ${id} not found`); _pdfpCheckJ(j.status, PDFP_PARSE_LIFECYCLE_V2.FAILED); const now = Date.now(); j.status = PDFP_PARSE_LIFECYCLE_V2.FAILED; j.updatedAt = now; if (!j.settledAt) j.settledAt = now; if (reason) j.metadata.failReason = String(reason); return { ...j, metadata: { ...j.metadata } }; }
|
|
168
|
+
export function cancelPdfpParseV2(id, reason) { const j = _pdfpJsV2.get(id); if (!j) throw new Error(`pdfp parse ${id} not found`); _pdfpCheckJ(j.status, PDFP_PARSE_LIFECYCLE_V2.CANCELLED); const now = Date.now(); j.status = PDFP_PARSE_LIFECYCLE_V2.CANCELLED; j.updatedAt = now; if (!j.settledAt) j.settledAt = now; if (reason) j.metadata.cancelReason = String(reason); return { ...j, metadata: { ...j.metadata } }; }
|
|
169
|
+
export function getPdfpParseV2(id) { const j = _pdfpJsV2.get(id); if (!j) return null; return { ...j, metadata: { ...j.metadata } }; }
|
|
170
|
+
export function listPdfpParsesV2() { return [..._pdfpJsV2.values()].map((j) => ({ ...j, metadata: { ...j.metadata } })); }
|
|
171
|
+
export function autoStaleIdlePdfpProfilesV2({ now } = {}) { const t = now ?? Date.now(); const flipped = []; for (const p of _pdfpPsV2.values()) if (p.status === PDFP_PROFILE_MATURITY_V2.ACTIVE && (t - p.lastTouchedAt) >= _pdfpIdleMs) { p.status = PDFP_PROFILE_MATURITY_V2.STALE; p.updatedAt = t; flipped.push(p.id); } return { flipped, count: flipped.length }; }
|
|
172
|
+
export function autoFailStuckPdfpParsesV2({ now } = {}) { const t = now ?? Date.now(); const flipped = []; for (const j of _pdfpJsV2.values()) if (j.status === PDFP_PARSE_LIFECYCLE_V2.PARSING && j.startedAt != null && (t - j.startedAt) >= _pdfpStuckMs) { j.status = PDFP_PARSE_LIFECYCLE_V2.FAILED; j.updatedAt = t; if (!j.settledAt) j.settledAt = t; j.metadata.failReason = "auto-fail-stuck"; flipped.push(j.id); } return { flipped, count: flipped.length }; }
|
|
173
|
+
export function getPdfParserGovStatsV2() {
|
|
174
|
+
const profilesByStatus = {}; for (const v of Object.values(PDFP_PROFILE_MATURITY_V2)) profilesByStatus[v] = 0; for (const p of _pdfpPsV2.values()) profilesByStatus[p.status]++;
|
|
175
|
+
const parsesByStatus = {}; for (const v of Object.values(PDFP_PARSE_LIFECYCLE_V2)) parsesByStatus[v] = 0; for (const j of _pdfpJsV2.values()) parsesByStatus[j.status]++;
|
|
176
|
+
return { totalPdfpProfilesV2: _pdfpPsV2.size, totalPdfpParsesV2: _pdfpJsV2.size, maxActivePdfpProfilesPerOwner: _pdfpMaxActive, maxPendingPdfpParsesPerProfile: _pdfpMaxPending, pdfpProfileIdleMs: _pdfpIdleMs, pdfpParseStuckMs: _pdfpStuckMs, profilesByStatus, parsesByStatus };
|
|
177
|
+
}
|
package/src/lib/perception.js
CHANGED
|
@@ -498,3 +498,349 @@ export function _resetState() {
|
|
|
498
498
|
_voiceSessions.clear();
|
|
499
499
|
_indexEntries.clear();
|
|
500
500
|
}
|
|
501
|
+
|
|
502
|
+
/* ═════════════════════════════════════════════════════════ *
|
|
503
|
+
* Phase 84 V2 — Sensor Maturity + Capture Lifecycle
|
|
504
|
+
* ═════════════════════════════════════════════════════════ */
|
|
505
|
+
|
|
506
|
+
export const SENSOR_MATURITY_V2 = Object.freeze({
|
|
507
|
+
ONBOARDING: "onboarding",
|
|
508
|
+
ACTIVE: "active",
|
|
509
|
+
DEGRADED: "degraded",
|
|
510
|
+
OFFLINE: "offline",
|
|
511
|
+
RETIRED: "retired",
|
|
512
|
+
});
|
|
513
|
+
|
|
514
|
+
export const CAPTURE_LIFECYCLE_V2 = Object.freeze({
|
|
515
|
+
PENDING: "pending",
|
|
516
|
+
PROCESSING: "processing",
|
|
517
|
+
READY: "ready",
|
|
518
|
+
FAILED: "failed",
|
|
519
|
+
DISCARDED: "discarded",
|
|
520
|
+
});
|
|
521
|
+
|
|
522
|
+
const SENSOR_TRANSITIONS_V2 = new Map([
|
|
523
|
+
["onboarding", new Set(["active", "retired"])],
|
|
524
|
+
["active", new Set(["degraded", "offline", "retired"])],
|
|
525
|
+
["degraded", new Set(["active", "offline", "retired"])],
|
|
526
|
+
["offline", new Set(["active", "retired"])],
|
|
527
|
+
]);
|
|
528
|
+
const SENSOR_TERMINALS_V2 = new Set(["retired"]);
|
|
529
|
+
|
|
530
|
+
const CAPTURE_TRANSITIONS_V2 = new Map([
|
|
531
|
+
["pending", new Set(["processing", "discarded", "failed"])],
|
|
532
|
+
["processing", new Set(["ready", "failed", "discarded"])],
|
|
533
|
+
["failed", new Set(["pending", "discarded"])],
|
|
534
|
+
]);
|
|
535
|
+
const CAPTURE_TERMINALS_V2 = new Set(["ready", "discarded"]);
|
|
536
|
+
|
|
537
|
+
export const PCP_DEFAULT_MAX_ACTIVE_SENSORS_PER_OPERATOR = 25;
|
|
538
|
+
export const PCP_DEFAULT_MAX_PENDING_CAPTURES_PER_SENSOR = 50;
|
|
539
|
+
export const PCP_DEFAULT_SENSOR_IDLE_MS = 30 * 86400000; // 30d
|
|
540
|
+
export const PCP_DEFAULT_CAPTURE_STUCK_MS = 2 * 3600000; // 2h
|
|
541
|
+
|
|
542
|
+
let _maxActiveSensorsPerOperatorV2 =
|
|
543
|
+
PCP_DEFAULT_MAX_ACTIVE_SENSORS_PER_OPERATOR;
|
|
544
|
+
let _maxPendingCapturesPerSensorV2 =
|
|
545
|
+
PCP_DEFAULT_MAX_PENDING_CAPTURES_PER_SENSOR;
|
|
546
|
+
let _sensorIdleMsV2 = PCP_DEFAULT_SENSOR_IDLE_MS;
|
|
547
|
+
let _captureStuckMsV2 = PCP_DEFAULT_CAPTURE_STUCK_MS;
|
|
548
|
+
|
|
549
|
+
function _positiveIntV2(n, label) {
|
|
550
|
+
const v = Math.floor(Number(n));
|
|
551
|
+
if (!Number.isFinite(v) || v <= 0)
|
|
552
|
+
throw new Error(`${label} must be a positive integer`);
|
|
553
|
+
return v;
|
|
554
|
+
}
|
|
555
|
+
|
|
556
|
+
export function getDefaultMaxActiveSensorsPerOperatorV2() {
|
|
557
|
+
return PCP_DEFAULT_MAX_ACTIVE_SENSORS_PER_OPERATOR;
|
|
558
|
+
}
|
|
559
|
+
export function getMaxActiveSensorsPerOperatorV2() {
|
|
560
|
+
return _maxActiveSensorsPerOperatorV2;
|
|
561
|
+
}
|
|
562
|
+
export function setMaxActiveSensorsPerOperatorV2(n) {
|
|
563
|
+
return (_maxActiveSensorsPerOperatorV2 = _positiveIntV2(
|
|
564
|
+
n,
|
|
565
|
+
"maxActiveSensorsPerOperator",
|
|
566
|
+
));
|
|
567
|
+
}
|
|
568
|
+
export function getDefaultMaxPendingCapturesPerSensorV2() {
|
|
569
|
+
return PCP_DEFAULT_MAX_PENDING_CAPTURES_PER_SENSOR;
|
|
570
|
+
}
|
|
571
|
+
export function getMaxPendingCapturesPerSensorV2() {
|
|
572
|
+
return _maxPendingCapturesPerSensorV2;
|
|
573
|
+
}
|
|
574
|
+
export function setMaxPendingCapturesPerSensorV2(n) {
|
|
575
|
+
return (_maxPendingCapturesPerSensorV2 = _positiveIntV2(
|
|
576
|
+
n,
|
|
577
|
+
"maxPendingCapturesPerSensor",
|
|
578
|
+
));
|
|
579
|
+
}
|
|
580
|
+
export function getDefaultSensorIdleMsV2() {
|
|
581
|
+
return PCP_DEFAULT_SENSOR_IDLE_MS;
|
|
582
|
+
}
|
|
583
|
+
export function getSensorIdleMsV2() {
|
|
584
|
+
return _sensorIdleMsV2;
|
|
585
|
+
}
|
|
586
|
+
export function setSensorIdleMsV2(ms) {
|
|
587
|
+
return (_sensorIdleMsV2 = _positiveIntV2(ms, "sensorIdleMs"));
|
|
588
|
+
}
|
|
589
|
+
export function getDefaultCaptureStuckMsV2() {
|
|
590
|
+
return PCP_DEFAULT_CAPTURE_STUCK_MS;
|
|
591
|
+
}
|
|
592
|
+
export function getCaptureStuckMsV2() {
|
|
593
|
+
return _captureStuckMsV2;
|
|
594
|
+
}
|
|
595
|
+
export function setCaptureStuckMsV2(ms) {
|
|
596
|
+
return (_captureStuckMsV2 = _positiveIntV2(ms, "captureStuckMs"));
|
|
597
|
+
}
|
|
598
|
+
|
|
599
|
+
const _sensorsV2 = new Map();
|
|
600
|
+
const _capturesV2 = new Map();
|
|
601
|
+
|
|
602
|
+
export function registerSensorV2(
|
|
603
|
+
_db,
|
|
604
|
+
{ sensorId, operatorId, modality, initialStatus, metadata } = {},
|
|
605
|
+
) {
|
|
606
|
+
if (!sensorId) throw new Error("sensorId is required");
|
|
607
|
+
if (!operatorId) throw new Error("operatorId is required");
|
|
608
|
+
if (!modality) throw new Error("modality is required");
|
|
609
|
+
if (!Object.values(MODALITY).includes(modality))
|
|
610
|
+
throw new Error(`Invalid modality: ${modality}`);
|
|
611
|
+
if (_sensorsV2.has(sensorId))
|
|
612
|
+
throw new Error(`Sensor ${sensorId} already exists`);
|
|
613
|
+
const status = initialStatus || SENSOR_MATURITY_V2.ONBOARDING;
|
|
614
|
+
if (!Object.values(SENSOR_MATURITY_V2).includes(status))
|
|
615
|
+
throw new Error(`Invalid initial status: ${status}`);
|
|
616
|
+
if (SENSOR_TERMINALS_V2.has(status))
|
|
617
|
+
throw new Error(`Cannot register in terminal status: ${status}`);
|
|
618
|
+
if (status === SENSOR_MATURITY_V2.ACTIVE) {
|
|
619
|
+
if (getActiveSensorCount(operatorId) >= _maxActiveSensorsPerOperatorV2)
|
|
620
|
+
throw new Error(
|
|
621
|
+
`Operator ${operatorId} reached active-sensor cap (${_maxActiveSensorsPerOperatorV2})`,
|
|
622
|
+
);
|
|
623
|
+
}
|
|
624
|
+
const now = Date.now();
|
|
625
|
+
const record = {
|
|
626
|
+
sensorId,
|
|
627
|
+
operatorId,
|
|
628
|
+
modality,
|
|
629
|
+
status,
|
|
630
|
+
metadata: metadata || {},
|
|
631
|
+
createdAt: now,
|
|
632
|
+
updatedAt: now,
|
|
633
|
+
lastHeartbeatAt: now,
|
|
634
|
+
};
|
|
635
|
+
_sensorsV2.set(sensorId, record);
|
|
636
|
+
return { ...record, metadata: { ...record.metadata } };
|
|
637
|
+
}
|
|
638
|
+
|
|
639
|
+
export function getSensorV2(sensorId) {
|
|
640
|
+
const r = _sensorsV2.get(sensorId);
|
|
641
|
+
return r ? { ...r, metadata: { ...r.metadata } } : null;
|
|
642
|
+
}
|
|
643
|
+
|
|
644
|
+
export function setSensorMaturityV2(_db, sensorId, newStatus, patch = {}) {
|
|
645
|
+
const record = _sensorsV2.get(sensorId);
|
|
646
|
+
if (!record) throw new Error(`Unknown sensor: ${sensorId}`);
|
|
647
|
+
if (!Object.values(SENSOR_MATURITY_V2).includes(newStatus))
|
|
648
|
+
throw new Error(`Invalid status: ${newStatus}`);
|
|
649
|
+
const allowed = SENSOR_TRANSITIONS_V2.get(record.status) || new Set();
|
|
650
|
+
if (!allowed.has(newStatus))
|
|
651
|
+
throw new Error(`Invalid transition: ${record.status} -> ${newStatus}`);
|
|
652
|
+
if (newStatus === SENSOR_MATURITY_V2.ACTIVE) {
|
|
653
|
+
if (
|
|
654
|
+
getActiveSensorCount(record.operatorId) >= _maxActiveSensorsPerOperatorV2
|
|
655
|
+
)
|
|
656
|
+
throw new Error(
|
|
657
|
+
`Operator ${record.operatorId} reached active-sensor cap (${_maxActiveSensorsPerOperatorV2})`,
|
|
658
|
+
);
|
|
659
|
+
}
|
|
660
|
+
record.status = newStatus;
|
|
661
|
+
record.updatedAt = Date.now();
|
|
662
|
+
if (patch.reason !== undefined) record.lastReason = patch.reason;
|
|
663
|
+
if (patch.metadata)
|
|
664
|
+
record.metadata = { ...record.metadata, ...patch.metadata };
|
|
665
|
+
return { ...record, metadata: { ...record.metadata } };
|
|
666
|
+
}
|
|
667
|
+
|
|
668
|
+
export function activateSensor(db, id, reason) {
|
|
669
|
+
return setSensorMaturityV2(db, id, SENSOR_MATURITY_V2.ACTIVE, { reason });
|
|
670
|
+
}
|
|
671
|
+
export function degradeSensor(db, id, reason) {
|
|
672
|
+
return setSensorMaturityV2(db, id, SENSOR_MATURITY_V2.DEGRADED, { reason });
|
|
673
|
+
}
|
|
674
|
+
export function offlineSensor(db, id, reason) {
|
|
675
|
+
return setSensorMaturityV2(db, id, SENSOR_MATURITY_V2.OFFLINE, { reason });
|
|
676
|
+
}
|
|
677
|
+
export function retireSensor(db, id, reason) {
|
|
678
|
+
return setSensorMaturityV2(db, id, SENSOR_MATURITY_V2.RETIRED, { reason });
|
|
679
|
+
}
|
|
680
|
+
|
|
681
|
+
export function touchSensorHeartbeat(sensorId) {
|
|
682
|
+
const record = _sensorsV2.get(sensorId);
|
|
683
|
+
if (!record) throw new Error(`Unknown sensor: ${sensorId}`);
|
|
684
|
+
record.lastHeartbeatAt = Date.now();
|
|
685
|
+
record.updatedAt = record.lastHeartbeatAt;
|
|
686
|
+
return { ...record, metadata: { ...record.metadata } };
|
|
687
|
+
}
|
|
688
|
+
|
|
689
|
+
export function registerCaptureV2(
|
|
690
|
+
_db,
|
|
691
|
+
{ captureId, sensorId, initialStatus, metadata } = {},
|
|
692
|
+
) {
|
|
693
|
+
if (!captureId) throw new Error("captureId is required");
|
|
694
|
+
if (!sensorId) throw new Error("sensorId is required");
|
|
695
|
+
if (!_sensorsV2.has(sensorId)) throw new Error(`Unknown sensor: ${sensorId}`);
|
|
696
|
+
if (_capturesV2.has(captureId))
|
|
697
|
+
throw new Error(`Capture ${captureId} already exists`);
|
|
698
|
+
const status = initialStatus || CAPTURE_LIFECYCLE_V2.PENDING;
|
|
699
|
+
if (!Object.values(CAPTURE_LIFECYCLE_V2).includes(status))
|
|
700
|
+
throw new Error(`Invalid initial status: ${status}`);
|
|
701
|
+
if (CAPTURE_TERMINALS_V2.has(status))
|
|
702
|
+
throw new Error(`Cannot register in terminal status: ${status}`);
|
|
703
|
+
if (status === CAPTURE_LIFECYCLE_V2.PENDING) {
|
|
704
|
+
if (getPendingCaptureCount(sensorId) >= _maxPendingCapturesPerSensorV2)
|
|
705
|
+
throw new Error(
|
|
706
|
+
`Sensor ${sensorId} reached pending-capture cap (${_maxPendingCapturesPerSensorV2})`,
|
|
707
|
+
);
|
|
708
|
+
}
|
|
709
|
+
const now = Date.now();
|
|
710
|
+
const record = {
|
|
711
|
+
captureId,
|
|
712
|
+
sensorId,
|
|
713
|
+
status,
|
|
714
|
+
metadata: metadata || {},
|
|
715
|
+
createdAt: now,
|
|
716
|
+
updatedAt: now,
|
|
717
|
+
};
|
|
718
|
+
_capturesV2.set(captureId, record);
|
|
719
|
+
return { ...record, metadata: { ...record.metadata } };
|
|
720
|
+
}
|
|
721
|
+
|
|
722
|
+
export function getCaptureV2(captureId) {
|
|
723
|
+
const r = _capturesV2.get(captureId);
|
|
724
|
+
return r ? { ...r, metadata: { ...r.metadata } } : null;
|
|
725
|
+
}
|
|
726
|
+
|
|
727
|
+
export function setCaptureStatusV2(_db, captureId, newStatus, patch = {}) {
|
|
728
|
+
const record = _capturesV2.get(captureId);
|
|
729
|
+
if (!record) throw new Error(`Unknown capture: ${captureId}`);
|
|
730
|
+
if (!Object.values(CAPTURE_LIFECYCLE_V2).includes(newStatus))
|
|
731
|
+
throw new Error(`Invalid status: ${newStatus}`);
|
|
732
|
+
const allowed = CAPTURE_TRANSITIONS_V2.get(record.status) || new Set();
|
|
733
|
+
if (!allowed.has(newStatus))
|
|
734
|
+
throw new Error(`Invalid transition: ${record.status} -> ${newStatus}`);
|
|
735
|
+
if (
|
|
736
|
+
newStatus === CAPTURE_LIFECYCLE_V2.PROCESSING &&
|
|
737
|
+
!record.processingStartedAt
|
|
738
|
+
) {
|
|
739
|
+
record.processingStartedAt = Date.now();
|
|
740
|
+
}
|
|
741
|
+
record.status = newStatus;
|
|
742
|
+
record.updatedAt = Date.now();
|
|
743
|
+
if (patch.reason !== undefined) record.lastReason = patch.reason;
|
|
744
|
+
if (patch.metadata)
|
|
745
|
+
record.metadata = { ...record.metadata, ...patch.metadata };
|
|
746
|
+
return { ...record, metadata: { ...record.metadata } };
|
|
747
|
+
}
|
|
748
|
+
|
|
749
|
+
export function startProcessingCapture(db, id, reason) {
|
|
750
|
+
return setCaptureStatusV2(db, id, CAPTURE_LIFECYCLE_V2.PROCESSING, {
|
|
751
|
+
reason,
|
|
752
|
+
});
|
|
753
|
+
}
|
|
754
|
+
export function markCaptureReady(db, id, reason) {
|
|
755
|
+
return setCaptureStatusV2(db, id, CAPTURE_LIFECYCLE_V2.READY, { reason });
|
|
756
|
+
}
|
|
757
|
+
export function failCapture(db, id, reason) {
|
|
758
|
+
return setCaptureStatusV2(db, id, CAPTURE_LIFECYCLE_V2.FAILED, { reason });
|
|
759
|
+
}
|
|
760
|
+
export function discardCapture(db, id, reason) {
|
|
761
|
+
return setCaptureStatusV2(db, id, CAPTURE_LIFECYCLE_V2.DISCARDED, { reason });
|
|
762
|
+
}
|
|
763
|
+
|
|
764
|
+
export function getActiveSensorCount(operatorId) {
|
|
765
|
+
let n = 0;
|
|
766
|
+
for (const r of _sensorsV2.values()) {
|
|
767
|
+
if (r.status !== SENSOR_MATURITY_V2.ACTIVE) continue;
|
|
768
|
+
if (operatorId && r.operatorId !== operatorId) continue;
|
|
769
|
+
n++;
|
|
770
|
+
}
|
|
771
|
+
return n;
|
|
772
|
+
}
|
|
773
|
+
|
|
774
|
+
export function getPendingCaptureCount(sensorId) {
|
|
775
|
+
let n = 0;
|
|
776
|
+
for (const r of _capturesV2.values()) {
|
|
777
|
+
if (r.status !== CAPTURE_LIFECYCLE_V2.PENDING) continue;
|
|
778
|
+
if (sensorId && r.sensorId !== sensorId) continue;
|
|
779
|
+
n++;
|
|
780
|
+
}
|
|
781
|
+
return n;
|
|
782
|
+
}
|
|
783
|
+
|
|
784
|
+
export function autoOfflineStaleSensors(_db, nowMs) {
|
|
785
|
+
const now = nowMs ?? Date.now();
|
|
786
|
+
const flipped = [];
|
|
787
|
+
for (const r of _sensorsV2.values()) {
|
|
788
|
+
if (
|
|
789
|
+
r.status === SENSOR_MATURITY_V2.ACTIVE ||
|
|
790
|
+
r.status === SENSOR_MATURITY_V2.DEGRADED
|
|
791
|
+
) {
|
|
792
|
+
if (now - r.lastHeartbeatAt > _sensorIdleMsV2) {
|
|
793
|
+
r.status = SENSOR_MATURITY_V2.OFFLINE;
|
|
794
|
+
r.updatedAt = now;
|
|
795
|
+
r.lastReason = "heartbeat_timeout";
|
|
796
|
+
flipped.push(r.sensorId);
|
|
797
|
+
}
|
|
798
|
+
}
|
|
799
|
+
}
|
|
800
|
+
return { flipped, count: flipped.length };
|
|
801
|
+
}
|
|
802
|
+
|
|
803
|
+
export function autoFailStuckProcessingCaptures(_db, nowMs) {
|
|
804
|
+
const now = nowMs ?? Date.now();
|
|
805
|
+
const flipped = [];
|
|
806
|
+
for (const r of _capturesV2.values()) {
|
|
807
|
+
if (r.status === CAPTURE_LIFECYCLE_V2.PROCESSING) {
|
|
808
|
+
const anchor = r.processingStartedAt || r.createdAt;
|
|
809
|
+
if (now - anchor > _captureStuckMsV2) {
|
|
810
|
+
r.status = CAPTURE_LIFECYCLE_V2.FAILED;
|
|
811
|
+
r.updatedAt = now;
|
|
812
|
+
r.lastReason = "processing_timeout";
|
|
813
|
+
flipped.push(r.captureId);
|
|
814
|
+
}
|
|
815
|
+
}
|
|
816
|
+
}
|
|
817
|
+
return { flipped, count: flipped.length };
|
|
818
|
+
}
|
|
819
|
+
|
|
820
|
+
export function getPerceptionStatsV2() {
|
|
821
|
+
const sensorsByStatus = {};
|
|
822
|
+
for (const s of Object.values(SENSOR_MATURITY_V2)) sensorsByStatus[s] = 0;
|
|
823
|
+
const capturesByStatus = {};
|
|
824
|
+
for (const s of Object.values(CAPTURE_LIFECYCLE_V2)) capturesByStatus[s] = 0;
|
|
825
|
+
for (const r of _sensorsV2.values()) sensorsByStatus[r.status]++;
|
|
826
|
+
for (const r of _capturesV2.values()) capturesByStatus[r.status]++;
|
|
827
|
+
return {
|
|
828
|
+
totalSensorsV2: _sensorsV2.size,
|
|
829
|
+
totalCapturesV2: _capturesV2.size,
|
|
830
|
+
maxActiveSensorsPerOperator: _maxActiveSensorsPerOperatorV2,
|
|
831
|
+
maxPendingCapturesPerSensor: _maxPendingCapturesPerSensorV2,
|
|
832
|
+
sensorIdleMs: _sensorIdleMsV2,
|
|
833
|
+
captureStuckMs: _captureStuckMsV2,
|
|
834
|
+
sensorsByStatus,
|
|
835
|
+
capturesByStatus,
|
|
836
|
+
};
|
|
837
|
+
}
|
|
838
|
+
|
|
839
|
+
export function _resetStateV2() {
|
|
840
|
+
_maxActiveSensorsPerOperatorV2 = PCP_DEFAULT_MAX_ACTIVE_SENSORS_PER_OPERATOR;
|
|
841
|
+
_maxPendingCapturesPerSensorV2 = PCP_DEFAULT_MAX_PENDING_CAPTURES_PER_SENSOR;
|
|
842
|
+
_sensorIdleMsV2 = PCP_DEFAULT_SENSOR_IDLE_MS;
|
|
843
|
+
_captureStuckMsV2 = PCP_DEFAULT_CAPTURE_STUCK_MS;
|
|
844
|
+
_sensorsV2.clear();
|
|
845
|
+
_capturesV2.clear();
|
|
846
|
+
}
|
package/src/lib/perf-tuning.js
CHANGED
|
@@ -102,8 +102,11 @@ export const BUILTIN_RULES = Object.freeze([
|
|
|
102
102
|
|
|
103
103
|
/* ── Helpers ────────────────────────────────────────────── */
|
|
104
104
|
|
|
105
|
+
let _lastNow = 0;
|
|
105
106
|
function _now() {
|
|
106
|
-
|
|
107
|
+
const n = Date.now();
|
|
108
|
+
_lastNow = n > _lastNow ? n : _lastNow + 1;
|
|
109
|
+
return _lastNow;
|
|
107
110
|
}
|
|
108
111
|
|
|
109
112
|
function _strip(row) {
|
|
@@ -732,3 +735,108 @@ export function getPerformanceReport(db) {
|
|
|
732
735
|
export function _resetState() {
|
|
733
736
|
/* CLI is stateless; helper exists for parity with other libs */
|
|
734
737
|
}
|
|
738
|
+
|
|
739
|
+
|
|
740
|
+
// ===== V2 Surface: Perf Tuning governance overlay (CLI v0.140.0) =====
|
|
741
|
+
export const PERF_TUNING_PROFILE_MATURITY_V2 = Object.freeze({
|
|
742
|
+
PENDING: "pending", ACTIVE: "active", STALE: "stale", DECOMMISSIONED: "decommissioned",
|
|
743
|
+
});
|
|
744
|
+
export const PERF_BENCH_LIFECYCLE_V2 = Object.freeze({
|
|
745
|
+
QUEUED: "queued", RUNNING: "running", COMPLETED: "completed", FAILED: "failed", CANCELLED: "cancelled",
|
|
746
|
+
});
|
|
747
|
+
|
|
748
|
+
const _ptpTrans = new Map([
|
|
749
|
+
[PERF_TUNING_PROFILE_MATURITY_V2.PENDING, new Set([PERF_TUNING_PROFILE_MATURITY_V2.ACTIVE, PERF_TUNING_PROFILE_MATURITY_V2.DECOMMISSIONED])],
|
|
750
|
+
[PERF_TUNING_PROFILE_MATURITY_V2.ACTIVE, new Set([PERF_TUNING_PROFILE_MATURITY_V2.STALE, PERF_TUNING_PROFILE_MATURITY_V2.DECOMMISSIONED])],
|
|
751
|
+
[PERF_TUNING_PROFILE_MATURITY_V2.STALE, new Set([PERF_TUNING_PROFILE_MATURITY_V2.ACTIVE, PERF_TUNING_PROFILE_MATURITY_V2.DECOMMISSIONED])],
|
|
752
|
+
[PERF_TUNING_PROFILE_MATURITY_V2.DECOMMISSIONED, new Set()],
|
|
753
|
+
]);
|
|
754
|
+
const _ptpTerminal = new Set([PERF_TUNING_PROFILE_MATURITY_V2.DECOMMISSIONED]);
|
|
755
|
+
const _pbTrans = new Map([
|
|
756
|
+
[PERF_BENCH_LIFECYCLE_V2.QUEUED, new Set([PERF_BENCH_LIFECYCLE_V2.RUNNING, PERF_BENCH_LIFECYCLE_V2.CANCELLED])],
|
|
757
|
+
[PERF_BENCH_LIFECYCLE_V2.RUNNING, new Set([PERF_BENCH_LIFECYCLE_V2.COMPLETED, PERF_BENCH_LIFECYCLE_V2.FAILED, PERF_BENCH_LIFECYCLE_V2.CANCELLED])],
|
|
758
|
+
[PERF_BENCH_LIFECYCLE_V2.COMPLETED, new Set()],
|
|
759
|
+
[PERF_BENCH_LIFECYCLE_V2.FAILED, new Set()],
|
|
760
|
+
[PERF_BENCH_LIFECYCLE_V2.CANCELLED, new Set()],
|
|
761
|
+
]);
|
|
762
|
+
|
|
763
|
+
const _ptpsV2 = new Map();
|
|
764
|
+
const _pbsV2 = new Map();
|
|
765
|
+
let _ptpMaxActivePerOwner = 6;
|
|
766
|
+
let _ptpMaxPendingBenchesPerProfile = 10;
|
|
767
|
+
let _ptpIdleMs = 7 * 24 * 60 * 60 * 1000;
|
|
768
|
+
let _pbStuckMs = 30 * 60 * 1000;
|
|
769
|
+
|
|
770
|
+
function _ptpPos(n, lbl) { const v = Math.floor(Number(n)); if (!Number.isFinite(v) || v <= 0) throw new Error(`${lbl} must be positive integer`); return v; }
|
|
771
|
+
|
|
772
|
+
export function setMaxActivePerfTuningProfilesPerOwnerV2(n) { _ptpMaxActivePerOwner = _ptpPos(n, "maxActivePerfTuningProfilesPerOwner"); }
|
|
773
|
+
export function getMaxActivePerfTuningProfilesPerOwnerV2() { return _ptpMaxActivePerOwner; }
|
|
774
|
+
export function setMaxPendingPerfBenchesPerProfileV2(n) { _ptpMaxPendingBenchesPerProfile = _ptpPos(n, "maxPendingPerfBenchesPerProfile"); }
|
|
775
|
+
export function getMaxPendingPerfBenchesPerProfileV2() { return _ptpMaxPendingBenchesPerProfile; }
|
|
776
|
+
export function setPerfTuningProfileIdleMsV2(n) { _ptpIdleMs = _ptpPos(n, "perfTuningProfileIdleMs"); }
|
|
777
|
+
export function getPerfTuningProfileIdleMsV2() { return _ptpIdleMs; }
|
|
778
|
+
export function setPerfBenchStuckMsV2(n) { _pbStuckMs = _ptpPos(n, "perfBenchStuckMs"); }
|
|
779
|
+
export function getPerfBenchStuckMsV2() { return _pbStuckMs; }
|
|
780
|
+
|
|
781
|
+
export function _resetStatePerfTuningV2() {
|
|
782
|
+
_ptpsV2.clear(); _pbsV2.clear();
|
|
783
|
+
_ptpMaxActivePerOwner = 6; _ptpMaxPendingBenchesPerProfile = 10;
|
|
784
|
+
_ptpIdleMs = 7 * 24 * 60 * 60 * 1000; _pbStuckMs = 30 * 60 * 1000;
|
|
785
|
+
}
|
|
786
|
+
|
|
787
|
+
export function registerPerfTuningProfileV2({ id, owner, target, metadata } = {}) {
|
|
788
|
+
if (!id || typeof id !== "string") throw new Error("id is required");
|
|
789
|
+
if (!owner || typeof owner !== "string") throw new Error("owner is required");
|
|
790
|
+
if (_ptpsV2.has(id)) throw new Error(`perf tuning profile ${id} already registered`);
|
|
791
|
+
const now = Date.now();
|
|
792
|
+
const p = { id, owner, target: target || "default", status: PERF_TUNING_PROFILE_MATURITY_V2.PENDING, createdAt: now, updatedAt: now, activatedAt: null, decommissionedAt: null, lastTouchedAt: now, metadata: { ...(metadata || {}) } };
|
|
793
|
+
_ptpsV2.set(id, p);
|
|
794
|
+
return { ...p, metadata: { ...p.metadata } };
|
|
795
|
+
}
|
|
796
|
+
function _ptpCheckP(from, to) { const a = _ptpTrans.get(from); if (!a || !a.has(to)) throw new Error(`invalid perf tuning profile transition ${from} → ${to}`); }
|
|
797
|
+
function _ptpCountActive(owner) { let n = 0; for (const p of _ptpsV2.values()) if (p.owner === owner && p.status === PERF_TUNING_PROFILE_MATURITY_V2.ACTIVE) n++; return n; }
|
|
798
|
+
|
|
799
|
+
export function activatePerfTuningProfileV2(id) {
|
|
800
|
+
const p = _ptpsV2.get(id); if (!p) throw new Error(`perf tuning profile ${id} not found`);
|
|
801
|
+
_ptpCheckP(p.status, PERF_TUNING_PROFILE_MATURITY_V2.ACTIVE);
|
|
802
|
+
const recovery = p.status === PERF_TUNING_PROFILE_MATURITY_V2.STALE;
|
|
803
|
+
if (!recovery) { const c = _ptpCountActive(p.owner); if (c >= _ptpMaxActivePerOwner) throw new Error(`max active perf tuning profiles per owner (${_ptpMaxActivePerOwner}) reached for ${p.owner}`); }
|
|
804
|
+
const now = Date.now(); p.status = PERF_TUNING_PROFILE_MATURITY_V2.ACTIVE; p.updatedAt = now; p.lastTouchedAt = now; if (!p.activatedAt) p.activatedAt = now;
|
|
805
|
+
return { ...p, metadata: { ...p.metadata } };
|
|
806
|
+
}
|
|
807
|
+
export function stalePerfTuningProfileV2(id) { const p = _ptpsV2.get(id); if (!p) throw new Error(`perf tuning profile ${id} not found`); _ptpCheckP(p.status, PERF_TUNING_PROFILE_MATURITY_V2.STALE); p.status = PERF_TUNING_PROFILE_MATURITY_V2.STALE; p.updatedAt = Date.now(); return { ...p, metadata: { ...p.metadata } }; }
|
|
808
|
+
export function decommissionPerfTuningProfileV2(id) { const p = _ptpsV2.get(id); if (!p) throw new Error(`perf tuning profile ${id} not found`); _ptpCheckP(p.status, PERF_TUNING_PROFILE_MATURITY_V2.DECOMMISSIONED); const now = Date.now(); p.status = PERF_TUNING_PROFILE_MATURITY_V2.DECOMMISSIONED; p.updatedAt = now; if (!p.decommissionedAt) p.decommissionedAt = now; return { ...p, metadata: { ...p.metadata } }; }
|
|
809
|
+
export function touchPerfTuningProfileV2(id) { const p = _ptpsV2.get(id); if (!p) throw new Error(`perf tuning profile ${id} not found`); if (_ptpTerminal.has(p.status)) throw new Error(`cannot touch terminal perf tuning profile ${id}`); const now = Date.now(); p.lastTouchedAt = now; p.updatedAt = now; return { ...p, metadata: { ...p.metadata } }; }
|
|
810
|
+
export function getPerfTuningProfileV2(id) { const p = _ptpsV2.get(id); if (!p) return null; return { ...p, metadata: { ...p.metadata } }; }
|
|
811
|
+
export function listPerfTuningProfilesV2() { return [..._ptpsV2.values()].map((p) => ({ ...p, metadata: { ...p.metadata } })); }
|
|
812
|
+
|
|
813
|
+
function _pbCountPending(profileId) { let n = 0; for (const b of _pbsV2.values()) if (b.profileId === profileId && (b.status === PERF_BENCH_LIFECYCLE_V2.QUEUED || b.status === PERF_BENCH_LIFECYCLE_V2.RUNNING)) n++; return n; }
|
|
814
|
+
|
|
815
|
+
export function createPerfBenchV2({ id, profileId, scenario, metadata } = {}) {
|
|
816
|
+
if (!id || typeof id !== "string") throw new Error("id is required");
|
|
817
|
+
if (!profileId || typeof profileId !== "string") throw new Error("profileId is required");
|
|
818
|
+
if (_pbsV2.has(id)) throw new Error(`perf bench ${id} already exists`);
|
|
819
|
+
if (!_ptpsV2.has(profileId)) throw new Error(`perf tuning profile ${profileId} not found`);
|
|
820
|
+
const pending = _pbCountPending(profileId);
|
|
821
|
+
if (pending >= _ptpMaxPendingBenchesPerProfile) throw new Error(`max pending perf benches per profile (${_ptpMaxPendingBenchesPerProfile}) reached for ${profileId}`);
|
|
822
|
+
const now = Date.now();
|
|
823
|
+
const b = { id, profileId, scenario: scenario || "", status: PERF_BENCH_LIFECYCLE_V2.QUEUED, createdAt: now, updatedAt: now, startedAt: null, settledAt: null, metadata: { ...(metadata || {}) } };
|
|
824
|
+
_pbsV2.set(id, b);
|
|
825
|
+
return { ...b, metadata: { ...b.metadata } };
|
|
826
|
+
}
|
|
827
|
+
function _pbCheckB(from, to) { const a = _pbTrans.get(from); if (!a || !a.has(to)) throw new Error(`invalid perf bench transition ${from} → ${to}`); }
|
|
828
|
+
export function startPerfBenchV2(id) { const b = _pbsV2.get(id); if (!b) throw new Error(`perf bench ${id} not found`); _pbCheckB(b.status, PERF_BENCH_LIFECYCLE_V2.RUNNING); const now = Date.now(); b.status = PERF_BENCH_LIFECYCLE_V2.RUNNING; b.updatedAt = now; if (!b.startedAt) b.startedAt = now; return { ...b, metadata: { ...b.metadata } }; }
|
|
829
|
+
export function completePerfBenchV2(id) { const b = _pbsV2.get(id); if (!b) throw new Error(`perf bench ${id} not found`); _pbCheckB(b.status, PERF_BENCH_LIFECYCLE_V2.COMPLETED); const now = Date.now(); b.status = PERF_BENCH_LIFECYCLE_V2.COMPLETED; b.updatedAt = now; if (!b.settledAt) b.settledAt = now; return { ...b, metadata: { ...b.metadata } }; }
|
|
830
|
+
export function failPerfBenchV2(id, reason) { const b = _pbsV2.get(id); if (!b) throw new Error(`perf bench ${id} not found`); _pbCheckB(b.status, PERF_BENCH_LIFECYCLE_V2.FAILED); const now = Date.now(); b.status = PERF_BENCH_LIFECYCLE_V2.FAILED; b.updatedAt = now; if (!b.settledAt) b.settledAt = now; if (reason) b.metadata.failReason = String(reason); return { ...b, metadata: { ...b.metadata } }; }
|
|
831
|
+
export function cancelPerfBenchV2(id, reason) { const b = _pbsV2.get(id); if (!b) throw new Error(`perf bench ${id} not found`); _pbCheckB(b.status, PERF_BENCH_LIFECYCLE_V2.CANCELLED); const now = Date.now(); b.status = PERF_BENCH_LIFECYCLE_V2.CANCELLED; b.updatedAt = now; if (!b.settledAt) b.settledAt = now; if (reason) b.metadata.cancelReason = String(reason); return { ...b, metadata: { ...b.metadata } }; }
|
|
832
|
+
export function getPerfBenchV2(id) { const b = _pbsV2.get(id); if (!b) return null; return { ...b, metadata: { ...b.metadata } }; }
|
|
833
|
+
export function listPerfBenchesV2() { return [..._pbsV2.values()].map((b) => ({ ...b, metadata: { ...b.metadata } })); }
|
|
834
|
+
|
|
835
|
+
export function autoStaleIdlePerfTuningProfilesV2({ now } = {}) { const t = now ?? Date.now(); const flipped = []; for (const p of _ptpsV2.values()) if (p.status === PERF_TUNING_PROFILE_MATURITY_V2.ACTIVE && (t - p.lastTouchedAt) >= _ptpIdleMs) { p.status = PERF_TUNING_PROFILE_MATURITY_V2.STALE; p.updatedAt = t; flipped.push(p.id); } return { flipped, count: flipped.length }; }
|
|
836
|
+
export function autoFailStuckPerfBenchesV2({ now } = {}) { const t = now ?? Date.now(); const flipped = []; for (const b of _pbsV2.values()) if (b.status === PERF_BENCH_LIFECYCLE_V2.RUNNING && b.startedAt != null && (t - b.startedAt) >= _pbStuckMs) { b.status = PERF_BENCH_LIFECYCLE_V2.FAILED; b.updatedAt = t; if (!b.settledAt) b.settledAt = t; b.metadata.failReason = "auto-fail-stuck"; flipped.push(b.id); } return { flipped, count: flipped.length }; }
|
|
837
|
+
|
|
838
|
+
export function getPerfTuningGovStatsV2() {
|
|
839
|
+
const profilesByStatus = {}; for (const s of Object.values(PERF_TUNING_PROFILE_MATURITY_V2)) profilesByStatus[s] = 0; for (const p of _ptpsV2.values()) profilesByStatus[p.status]++;
|
|
840
|
+
const benchesByStatus = {}; for (const s of Object.values(PERF_BENCH_LIFECYCLE_V2)) benchesByStatus[s] = 0; for (const b of _pbsV2.values()) benchesByStatus[b.status]++;
|
|
841
|
+
return { totalPerfTuningProfilesV2: _ptpsV2.size, totalPerfBenchesV2: _pbsV2.size, maxActivePerfTuningProfilesPerOwner: _ptpMaxActivePerOwner, maxPendingPerfBenchesPerProfile: _ptpMaxPendingBenchesPerProfile, perfTuningProfileIdleMs: _ptpIdleMs, perfBenchStuckMs: _pbStuckMs, profilesByStatus, benchesByStatus };
|
|
842
|
+
}
|