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/aiops.js
CHANGED
|
@@ -521,3 +521,481 @@ export function _resetState() {
|
|
|
521
521
|
_playbooks.clear();
|
|
522
522
|
_baselines.clear();
|
|
523
523
|
}
|
|
524
|
+
|
|
525
|
+
/* ═══════════════════════════════════════════════════════════════
|
|
526
|
+
* V2 SURFACE — Phase 25 AIOps lifecycle state machines
|
|
527
|
+
* ═══════════════════════════════════════════════════════════════
|
|
528
|
+
*
|
|
529
|
+
* V2 adds two parallel lifecycles on top of the legacy incident/playbook
|
|
530
|
+
* store. Nothing above is modified.
|
|
531
|
+
*
|
|
532
|
+
* Playbook maturity: draft → { active, retired }
|
|
533
|
+
* active → { deprecated, retired }
|
|
534
|
+
* deprecated → { active, retired }
|
|
535
|
+
* Terminal: retired
|
|
536
|
+
*
|
|
537
|
+
* Remediation exec: pending → { executing, aborted }
|
|
538
|
+
* executing → { succeeded, failed, aborted }
|
|
539
|
+
* Terminals: succeeded, failed, aborted
|
|
540
|
+
*
|
|
541
|
+
* Caps: per-owner active-playbook count + per-owner in-flight
|
|
542
|
+
* remediation count.
|
|
543
|
+
*
|
|
544
|
+
* Auto-flip: stale-playbook auto-retire + stuck-remediation auto-timeout.
|
|
545
|
+
*
|
|
546
|
+
* Stats: all enum keys zero-initialized for stable CI regression shape.
|
|
547
|
+
* ═════════════════════════════════════════════════════════════ */
|
|
548
|
+
|
|
549
|
+
export const PLAYBOOK_MATURITY_V2 = Object.freeze({
|
|
550
|
+
DRAFT: "draft",
|
|
551
|
+
ACTIVE: "active",
|
|
552
|
+
DEPRECATED: "deprecated",
|
|
553
|
+
RETIRED: "retired",
|
|
554
|
+
});
|
|
555
|
+
|
|
556
|
+
export const REMEDIATION_LIFECYCLE_V2 = Object.freeze({
|
|
557
|
+
PENDING: "pending",
|
|
558
|
+
EXECUTING: "executing",
|
|
559
|
+
SUCCEEDED: "succeeded",
|
|
560
|
+
FAILED: "failed",
|
|
561
|
+
ABORTED: "aborted",
|
|
562
|
+
});
|
|
563
|
+
|
|
564
|
+
const PLAYBOOK_TRANSITIONS_V2 = new Map([
|
|
565
|
+
["draft", new Set(["active", "retired"])],
|
|
566
|
+
["active", new Set(["deprecated", "retired"])],
|
|
567
|
+
["deprecated", new Set(["active", "retired"])],
|
|
568
|
+
]);
|
|
569
|
+
const PLAYBOOK_TERMINALS_V2 = new Set(["retired"]);
|
|
570
|
+
|
|
571
|
+
const REMEDIATION_TRANSITIONS_V2 = new Map([
|
|
572
|
+
["pending", new Set(["executing", "aborted"])],
|
|
573
|
+
["executing", new Set(["succeeded", "failed", "aborted"])],
|
|
574
|
+
]);
|
|
575
|
+
const REMEDIATION_TERMINALS_V2 = new Set(["succeeded", "failed", "aborted"]);
|
|
576
|
+
|
|
577
|
+
export const AIOPS_DEFAULT_MAX_ACTIVE_PLAYBOOKS_PER_OWNER = 50;
|
|
578
|
+
export const AIOPS_DEFAULT_MAX_PENDING_REMEDIATIONS_PER_OWNER = 10;
|
|
579
|
+
export const AIOPS_DEFAULT_PLAYBOOK_STALE_MS = 90 * 86400000; // 90 days
|
|
580
|
+
export const AIOPS_DEFAULT_REMEDIATION_TIMEOUT_MS = 30 * 60 * 1000; // 30 min
|
|
581
|
+
|
|
582
|
+
let _maxActivePlaybooksPerOwnerV2 =
|
|
583
|
+
AIOPS_DEFAULT_MAX_ACTIVE_PLAYBOOKS_PER_OWNER;
|
|
584
|
+
let _maxPendingRemediationsPerOwnerV2 =
|
|
585
|
+
AIOPS_DEFAULT_MAX_PENDING_REMEDIATIONS_PER_OWNER;
|
|
586
|
+
let _playbookStaleMsV2 = AIOPS_DEFAULT_PLAYBOOK_STALE_MS;
|
|
587
|
+
let _remediationTimeoutMsV2 = AIOPS_DEFAULT_REMEDIATION_TIMEOUT_MS;
|
|
588
|
+
|
|
589
|
+
const _playbookStatesV2 = new Map(); // playbookId → V2 record
|
|
590
|
+
const _remediationStatesV2 = new Map(); // remediationId → V2 record
|
|
591
|
+
|
|
592
|
+
function _positiveIntV2(n, label) {
|
|
593
|
+
const num = Number(n);
|
|
594
|
+
if (!Number.isFinite(num) || num <= 0) {
|
|
595
|
+
throw new Error(`${label} must be a positive integer`);
|
|
596
|
+
}
|
|
597
|
+
return Math.floor(num);
|
|
598
|
+
}
|
|
599
|
+
|
|
600
|
+
function _validPlaybookStatusV2(status) {
|
|
601
|
+
return (
|
|
602
|
+
status === "draft" ||
|
|
603
|
+
status === "active" ||
|
|
604
|
+
status === "deprecated" ||
|
|
605
|
+
status === "retired"
|
|
606
|
+
);
|
|
607
|
+
}
|
|
608
|
+
|
|
609
|
+
function _validRemediationStatusV2(status) {
|
|
610
|
+
return (
|
|
611
|
+
status === "pending" ||
|
|
612
|
+
status === "executing" ||
|
|
613
|
+
status === "succeeded" ||
|
|
614
|
+
status === "failed" ||
|
|
615
|
+
status === "aborted"
|
|
616
|
+
);
|
|
617
|
+
}
|
|
618
|
+
|
|
619
|
+
export function getDefaultMaxActivePlaybooksPerOwnerV2() {
|
|
620
|
+
return AIOPS_DEFAULT_MAX_ACTIVE_PLAYBOOKS_PER_OWNER;
|
|
621
|
+
}
|
|
622
|
+
export function getMaxActivePlaybooksPerOwnerV2() {
|
|
623
|
+
return _maxActivePlaybooksPerOwnerV2;
|
|
624
|
+
}
|
|
625
|
+
export function setMaxActivePlaybooksPerOwnerV2(n) {
|
|
626
|
+
_maxActivePlaybooksPerOwnerV2 = _positiveIntV2(
|
|
627
|
+
n,
|
|
628
|
+
"maxActivePlaybooksPerOwner",
|
|
629
|
+
);
|
|
630
|
+
return _maxActivePlaybooksPerOwnerV2;
|
|
631
|
+
}
|
|
632
|
+
|
|
633
|
+
export function getDefaultMaxPendingRemediationsPerOwnerV2() {
|
|
634
|
+
return AIOPS_DEFAULT_MAX_PENDING_REMEDIATIONS_PER_OWNER;
|
|
635
|
+
}
|
|
636
|
+
export function getMaxPendingRemediationsPerOwnerV2() {
|
|
637
|
+
return _maxPendingRemediationsPerOwnerV2;
|
|
638
|
+
}
|
|
639
|
+
export function setMaxPendingRemediationsPerOwnerV2(n) {
|
|
640
|
+
_maxPendingRemediationsPerOwnerV2 = _positiveIntV2(
|
|
641
|
+
n,
|
|
642
|
+
"maxPendingRemediationsPerOwner",
|
|
643
|
+
);
|
|
644
|
+
return _maxPendingRemediationsPerOwnerV2;
|
|
645
|
+
}
|
|
646
|
+
|
|
647
|
+
export function getDefaultPlaybookStaleMsV2() {
|
|
648
|
+
return AIOPS_DEFAULT_PLAYBOOK_STALE_MS;
|
|
649
|
+
}
|
|
650
|
+
export function getPlaybookStaleMsV2() {
|
|
651
|
+
return _playbookStaleMsV2;
|
|
652
|
+
}
|
|
653
|
+
export function setPlaybookStaleMsV2(ms) {
|
|
654
|
+
_playbookStaleMsV2 = _positiveIntV2(ms, "playbookStaleMs");
|
|
655
|
+
return _playbookStaleMsV2;
|
|
656
|
+
}
|
|
657
|
+
|
|
658
|
+
export function getDefaultRemediationTimeoutMsV2() {
|
|
659
|
+
return AIOPS_DEFAULT_REMEDIATION_TIMEOUT_MS;
|
|
660
|
+
}
|
|
661
|
+
export function getRemediationTimeoutMsV2() {
|
|
662
|
+
return _remediationTimeoutMsV2;
|
|
663
|
+
}
|
|
664
|
+
export function setRemediationTimeoutMsV2(ms) {
|
|
665
|
+
_remediationTimeoutMsV2 = _positiveIntV2(ms, "remediationTimeoutMs");
|
|
666
|
+
return _remediationTimeoutMsV2;
|
|
667
|
+
}
|
|
668
|
+
|
|
669
|
+
/* ── Playbook V2 ─────────────────────────────────────────── */
|
|
670
|
+
|
|
671
|
+
export function registerPlaybookV2(db, config = {}) {
|
|
672
|
+
void db;
|
|
673
|
+
const playbookId = String(config.playbookId || "").trim();
|
|
674
|
+
if (!playbookId) throw new Error("playbookId is required");
|
|
675
|
+
const ownerId = String(config.ownerId || "").trim();
|
|
676
|
+
if (!ownerId) throw new Error("ownerId is required");
|
|
677
|
+
if (_playbookStatesV2.has(playbookId)) {
|
|
678
|
+
throw new Error(`Playbook already registered in V2: ${playbookId}`);
|
|
679
|
+
}
|
|
680
|
+
|
|
681
|
+
const now = Number(config.now ?? Date.now());
|
|
682
|
+
const initialStatus = config.initialStatus || "draft";
|
|
683
|
+
if (!_validPlaybookStatusV2(initialStatus)) {
|
|
684
|
+
throw new Error(`Invalid initial status: ${initialStatus}`);
|
|
685
|
+
}
|
|
686
|
+
if (initialStatus === "retired") {
|
|
687
|
+
throw new Error("Cannot register playbook in terminal status 'retired'");
|
|
688
|
+
}
|
|
689
|
+
|
|
690
|
+
if (initialStatus === "active") {
|
|
691
|
+
let activeCount = 0;
|
|
692
|
+
for (const rec of _playbookStatesV2.values()) {
|
|
693
|
+
if (rec.ownerId === ownerId && rec.status === "active") activeCount += 1;
|
|
694
|
+
}
|
|
695
|
+
if (activeCount >= _maxActivePlaybooksPerOwnerV2) {
|
|
696
|
+
throw new Error(
|
|
697
|
+
`Max active playbooks per owner reached (${_maxActivePlaybooksPerOwnerV2})`,
|
|
698
|
+
);
|
|
699
|
+
}
|
|
700
|
+
}
|
|
701
|
+
|
|
702
|
+
const record = {
|
|
703
|
+
playbookId,
|
|
704
|
+
ownerId,
|
|
705
|
+
name: config.name ? String(config.name) : null,
|
|
706
|
+
status: initialStatus,
|
|
707
|
+
metadata: config.metadata ? { ...config.metadata } : {},
|
|
708
|
+
createdAt: now,
|
|
709
|
+
updatedAt: now,
|
|
710
|
+
lastUsedAt: now,
|
|
711
|
+
reason: null,
|
|
712
|
+
};
|
|
713
|
+
_playbookStatesV2.set(playbookId, record);
|
|
714
|
+
return { ...record, metadata: { ...record.metadata } };
|
|
715
|
+
}
|
|
716
|
+
|
|
717
|
+
export function getPlaybookV2(playbookId) {
|
|
718
|
+
const rec = _playbookStatesV2.get(String(playbookId || ""));
|
|
719
|
+
if (!rec) return null;
|
|
720
|
+
return { ...rec, metadata: { ...rec.metadata } };
|
|
721
|
+
}
|
|
722
|
+
|
|
723
|
+
export function setPlaybookMaturityV2(db, playbookId, newStatus, patch = {}) {
|
|
724
|
+
void db;
|
|
725
|
+
const id = String(playbookId || "");
|
|
726
|
+
const record = _playbookStatesV2.get(id);
|
|
727
|
+
if (!record) throw new Error(`Playbook not registered in V2: ${id}`);
|
|
728
|
+
if (!_validPlaybookStatusV2(newStatus)) {
|
|
729
|
+
throw new Error(`Invalid playbook status: ${newStatus}`);
|
|
730
|
+
}
|
|
731
|
+
if (PLAYBOOK_TERMINALS_V2.has(record.status)) {
|
|
732
|
+
throw new Error(
|
|
733
|
+
`Playbook is in terminal status '${record.status}' and cannot transition`,
|
|
734
|
+
);
|
|
735
|
+
}
|
|
736
|
+
const allowed = PLAYBOOK_TRANSITIONS_V2.get(record.status);
|
|
737
|
+
if (!allowed || !allowed.has(newStatus)) {
|
|
738
|
+
throw new Error(`Invalid transition: ${record.status} → ${newStatus}`);
|
|
739
|
+
}
|
|
740
|
+
|
|
741
|
+
if (newStatus === "active" && record.status !== "active") {
|
|
742
|
+
let activeCount = 0;
|
|
743
|
+
for (const rec of _playbookStatesV2.values()) {
|
|
744
|
+
if (rec.ownerId === record.ownerId && rec.status === "active")
|
|
745
|
+
activeCount += 1;
|
|
746
|
+
}
|
|
747
|
+
if (activeCount >= _maxActivePlaybooksPerOwnerV2) {
|
|
748
|
+
throw new Error(
|
|
749
|
+
`Max active playbooks per owner reached (${_maxActivePlaybooksPerOwnerV2})`,
|
|
750
|
+
);
|
|
751
|
+
}
|
|
752
|
+
}
|
|
753
|
+
|
|
754
|
+
record.status = newStatus;
|
|
755
|
+
record.updatedAt = Number(patch.now ?? Date.now());
|
|
756
|
+
if (patch.reason !== undefined) record.reason = patch.reason;
|
|
757
|
+
if (patch.metadata && typeof patch.metadata === "object") {
|
|
758
|
+
record.metadata = { ...record.metadata, ...patch.metadata };
|
|
759
|
+
}
|
|
760
|
+
return { ...record, metadata: { ...record.metadata } };
|
|
761
|
+
}
|
|
762
|
+
|
|
763
|
+
export function activatePlaybook(db, playbookId, reason) {
|
|
764
|
+
return setPlaybookMaturityV2(db, playbookId, "active", { reason });
|
|
765
|
+
}
|
|
766
|
+
export function deprecatePlaybookV2(db, playbookId, reason) {
|
|
767
|
+
return setPlaybookMaturityV2(db, playbookId, "deprecated", { reason });
|
|
768
|
+
}
|
|
769
|
+
export function retirePlaybook(db, playbookId, reason) {
|
|
770
|
+
return setPlaybookMaturityV2(db, playbookId, "retired", { reason });
|
|
771
|
+
}
|
|
772
|
+
|
|
773
|
+
export function touchPlaybookActivity(playbookId) {
|
|
774
|
+
const rec = _playbookStatesV2.get(String(playbookId || ""));
|
|
775
|
+
if (!rec) throw new Error(`Playbook not registered in V2: ${playbookId}`);
|
|
776
|
+
rec.lastUsedAt = Date.now();
|
|
777
|
+
return { ...rec, metadata: { ...rec.metadata } };
|
|
778
|
+
}
|
|
779
|
+
|
|
780
|
+
/* ── Remediation V2 ──────────────────────────────────────── */
|
|
781
|
+
|
|
782
|
+
export function submitRemediationV2(db, config = {}) {
|
|
783
|
+
void db;
|
|
784
|
+
const remediationId = String(config.remediationId || "").trim();
|
|
785
|
+
if (!remediationId) throw new Error("remediationId is required");
|
|
786
|
+
const ownerId = String(config.ownerId || "").trim();
|
|
787
|
+
if (!ownerId) throw new Error("ownerId is required");
|
|
788
|
+
const playbookId = String(config.playbookId || "").trim();
|
|
789
|
+
if (!playbookId) throw new Error("playbookId is required");
|
|
790
|
+
|
|
791
|
+
if (_remediationStatesV2.has(remediationId)) {
|
|
792
|
+
throw new Error(`Remediation already registered in V2: ${remediationId}`);
|
|
793
|
+
}
|
|
794
|
+
|
|
795
|
+
const playbook = _playbookStatesV2.get(playbookId);
|
|
796
|
+
if (!playbook) {
|
|
797
|
+
throw new Error(`Playbook not registered in V2: ${playbookId}`);
|
|
798
|
+
}
|
|
799
|
+
if (playbook.status !== "active" && playbook.status !== "deprecated") {
|
|
800
|
+
throw new Error(
|
|
801
|
+
`Playbook is ${playbook.status}, cannot submit remediation`,
|
|
802
|
+
);
|
|
803
|
+
}
|
|
804
|
+
|
|
805
|
+
let inflightCount = 0;
|
|
806
|
+
for (const rec of _remediationStatesV2.values()) {
|
|
807
|
+
if (
|
|
808
|
+
rec.ownerId === ownerId &&
|
|
809
|
+
(rec.status === "pending" || rec.status === "executing")
|
|
810
|
+
) {
|
|
811
|
+
inflightCount += 1;
|
|
812
|
+
}
|
|
813
|
+
}
|
|
814
|
+
if (inflightCount >= _maxPendingRemediationsPerOwnerV2) {
|
|
815
|
+
throw new Error(
|
|
816
|
+
`Max pending remediations per owner reached (${_maxPendingRemediationsPerOwnerV2})`,
|
|
817
|
+
);
|
|
818
|
+
}
|
|
819
|
+
|
|
820
|
+
const now = Number(config.now ?? Date.now());
|
|
821
|
+
const record = {
|
|
822
|
+
remediationId,
|
|
823
|
+
ownerId,
|
|
824
|
+
playbookId,
|
|
825
|
+
incidentId: config.incidentId ? String(config.incidentId) : null,
|
|
826
|
+
status: "pending",
|
|
827
|
+
metadata: config.metadata ? { ...config.metadata } : {},
|
|
828
|
+
createdAt: now,
|
|
829
|
+
updatedAt: now,
|
|
830
|
+
startedAt: null,
|
|
831
|
+
completedAt: null,
|
|
832
|
+
reason: null,
|
|
833
|
+
};
|
|
834
|
+
_remediationStatesV2.set(remediationId, record);
|
|
835
|
+
return { ...record, metadata: { ...record.metadata } };
|
|
836
|
+
}
|
|
837
|
+
|
|
838
|
+
export function getRemediationV2(remediationId) {
|
|
839
|
+
const rec = _remediationStatesV2.get(String(remediationId || ""));
|
|
840
|
+
if (!rec) return null;
|
|
841
|
+
return { ...rec, metadata: { ...rec.metadata } };
|
|
842
|
+
}
|
|
843
|
+
|
|
844
|
+
export function setRemediationStatusV2(
|
|
845
|
+
db,
|
|
846
|
+
remediationId,
|
|
847
|
+
newStatus,
|
|
848
|
+
patch = {},
|
|
849
|
+
) {
|
|
850
|
+
void db;
|
|
851
|
+
const id = String(remediationId || "");
|
|
852
|
+
const record = _remediationStatesV2.get(id);
|
|
853
|
+
if (!record) throw new Error(`Remediation not registered in V2: ${id}`);
|
|
854
|
+
if (!_validRemediationStatusV2(newStatus)) {
|
|
855
|
+
throw new Error(`Invalid remediation status: ${newStatus}`);
|
|
856
|
+
}
|
|
857
|
+
if (REMEDIATION_TERMINALS_V2.has(record.status)) {
|
|
858
|
+
throw new Error(
|
|
859
|
+
`Remediation is in terminal status '${record.status}' and cannot transition`,
|
|
860
|
+
);
|
|
861
|
+
}
|
|
862
|
+
const allowed = REMEDIATION_TRANSITIONS_V2.get(record.status);
|
|
863
|
+
if (!allowed || !allowed.has(newStatus)) {
|
|
864
|
+
throw new Error(`Invalid transition: ${record.status} → ${newStatus}`);
|
|
865
|
+
}
|
|
866
|
+
const now = Number(patch.now ?? Date.now());
|
|
867
|
+
record.status = newStatus;
|
|
868
|
+
record.updatedAt = now;
|
|
869
|
+
if (newStatus === "executing" && record.startedAt === null) {
|
|
870
|
+
record.startedAt = now;
|
|
871
|
+
}
|
|
872
|
+
if (REMEDIATION_TERMINALS_V2.has(newStatus)) {
|
|
873
|
+
record.completedAt = now;
|
|
874
|
+
}
|
|
875
|
+
if (patch.reason !== undefined) record.reason = patch.reason;
|
|
876
|
+
if (patch.metadata && typeof patch.metadata === "object") {
|
|
877
|
+
record.metadata = { ...record.metadata, ...patch.metadata };
|
|
878
|
+
}
|
|
879
|
+
return { ...record, metadata: { ...record.metadata } };
|
|
880
|
+
}
|
|
881
|
+
|
|
882
|
+
export function startRemediation(db, remediationId, reason) {
|
|
883
|
+
return setRemediationStatusV2(db, remediationId, "executing", { reason });
|
|
884
|
+
}
|
|
885
|
+
export function completeRemediation(db, remediationId, reason) {
|
|
886
|
+
return setRemediationStatusV2(db, remediationId, "succeeded", { reason });
|
|
887
|
+
}
|
|
888
|
+
export function failRemediation(db, remediationId, reason) {
|
|
889
|
+
return setRemediationStatusV2(db, remediationId, "failed", { reason });
|
|
890
|
+
}
|
|
891
|
+
export function abortRemediation(db, remediationId, reason) {
|
|
892
|
+
return setRemediationStatusV2(db, remediationId, "aborted", { reason });
|
|
893
|
+
}
|
|
894
|
+
|
|
895
|
+
/* ── Counts ──────────────────────────────────────────────── */
|
|
896
|
+
|
|
897
|
+
export function getActivePlaybookCount(ownerId) {
|
|
898
|
+
let n = 0;
|
|
899
|
+
for (const rec of _playbookStatesV2.values()) {
|
|
900
|
+
if (rec.status !== "active") continue;
|
|
901
|
+
if (ownerId !== undefined && rec.ownerId !== String(ownerId)) continue;
|
|
902
|
+
n += 1;
|
|
903
|
+
}
|
|
904
|
+
return n;
|
|
905
|
+
}
|
|
906
|
+
|
|
907
|
+
export function getPendingRemediationCount(ownerId) {
|
|
908
|
+
let n = 0;
|
|
909
|
+
for (const rec of _remediationStatesV2.values()) {
|
|
910
|
+
if (rec.status !== "pending" && rec.status !== "executing") continue;
|
|
911
|
+
if (ownerId !== undefined && rec.ownerId !== String(ownerId)) continue;
|
|
912
|
+
n += 1;
|
|
913
|
+
}
|
|
914
|
+
return n;
|
|
915
|
+
}
|
|
916
|
+
|
|
917
|
+
/* ── Auto-flip Bulk Ops ──────────────────────────────────── */
|
|
918
|
+
|
|
919
|
+
export function autoRetireStalePlaybooks(db, nowMs) {
|
|
920
|
+
void db;
|
|
921
|
+
const now = Number(nowMs ?? Date.now());
|
|
922
|
+
const flipped = [];
|
|
923
|
+
for (const rec of _playbookStatesV2.values()) {
|
|
924
|
+
if (PLAYBOOK_TERMINALS_V2.has(rec.status)) continue;
|
|
925
|
+
if (now - rec.lastUsedAt > _playbookStaleMsV2) {
|
|
926
|
+
rec.status = "retired";
|
|
927
|
+
rec.updatedAt = now;
|
|
928
|
+
rec.reason = "stale";
|
|
929
|
+
flipped.push(rec.playbookId);
|
|
930
|
+
}
|
|
931
|
+
}
|
|
932
|
+
return flipped;
|
|
933
|
+
}
|
|
934
|
+
|
|
935
|
+
export function autoTimeoutStuckRemediations(db, nowMs) {
|
|
936
|
+
void db;
|
|
937
|
+
const now = Number(nowMs ?? Date.now());
|
|
938
|
+
const flipped = [];
|
|
939
|
+
for (const rec of _remediationStatesV2.values()) {
|
|
940
|
+
if (rec.status !== "executing") continue;
|
|
941
|
+
const startedAt = rec.startedAt ?? rec.createdAt;
|
|
942
|
+
if (now - startedAt > _remediationTimeoutMsV2) {
|
|
943
|
+
rec.status = "failed";
|
|
944
|
+
rec.updatedAt = now;
|
|
945
|
+
rec.completedAt = now;
|
|
946
|
+
rec.reason = "timeout";
|
|
947
|
+
flipped.push(rec.remediationId);
|
|
948
|
+
}
|
|
949
|
+
}
|
|
950
|
+
return flipped;
|
|
951
|
+
}
|
|
952
|
+
|
|
953
|
+
/* ── Stats V2 ────────────────────────────────────────────── */
|
|
954
|
+
|
|
955
|
+
export function getAiOpsStatsV2() {
|
|
956
|
+
const playbooksByStatus = {
|
|
957
|
+
draft: 0,
|
|
958
|
+
active: 0,
|
|
959
|
+
deprecated: 0,
|
|
960
|
+
retired: 0,
|
|
961
|
+
};
|
|
962
|
+
const remediationsByStatus = {
|
|
963
|
+
pending: 0,
|
|
964
|
+
executing: 0,
|
|
965
|
+
succeeded: 0,
|
|
966
|
+
failed: 0,
|
|
967
|
+
aborted: 0,
|
|
968
|
+
};
|
|
969
|
+
for (const rec of _playbookStatesV2.values()) {
|
|
970
|
+
if (playbooksByStatus[rec.status] !== undefined) {
|
|
971
|
+
playbooksByStatus[rec.status] += 1;
|
|
972
|
+
}
|
|
973
|
+
}
|
|
974
|
+
for (const rec of _remediationStatesV2.values()) {
|
|
975
|
+
if (remediationsByStatus[rec.status] !== undefined) {
|
|
976
|
+
remediationsByStatus[rec.status] += 1;
|
|
977
|
+
}
|
|
978
|
+
}
|
|
979
|
+
return {
|
|
980
|
+
totalPlaybooksV2: _playbookStatesV2.size,
|
|
981
|
+
totalRemediationsV2: _remediationStatesV2.size,
|
|
982
|
+
maxActivePlaybooksPerOwner: _maxActivePlaybooksPerOwnerV2,
|
|
983
|
+
maxPendingRemediationsPerOwner: _maxPendingRemediationsPerOwnerV2,
|
|
984
|
+
playbookStaleMs: _playbookStaleMsV2,
|
|
985
|
+
remediationTimeoutMs: _remediationTimeoutMsV2,
|
|
986
|
+
playbooksByStatus,
|
|
987
|
+
remediationsByStatus,
|
|
988
|
+
};
|
|
989
|
+
}
|
|
990
|
+
|
|
991
|
+
/* ── Reset V2 (tests) ────────────────────────────────────── */
|
|
992
|
+
|
|
993
|
+
export function _resetStateV2() {
|
|
994
|
+
_playbookStatesV2.clear();
|
|
995
|
+
_remediationStatesV2.clear();
|
|
996
|
+
_maxActivePlaybooksPerOwnerV2 = AIOPS_DEFAULT_MAX_ACTIVE_PLAYBOOKS_PER_OWNER;
|
|
997
|
+
_maxPendingRemediationsPerOwnerV2 =
|
|
998
|
+
AIOPS_DEFAULT_MAX_PENDING_REMEDIATIONS_PER_OWNER;
|
|
999
|
+
_playbookStaleMsV2 = AIOPS_DEFAULT_PLAYBOOK_STALE_MS;
|
|
1000
|
+
_remediationTimeoutMsV2 = AIOPS_DEFAULT_REMEDIATION_TIMEOUT_MS;
|
|
1001
|
+
}
|
package/src/lib/app-builder.js
CHANGED
|
@@ -742,3 +742,108 @@ export function _resetV2State() {
|
|
|
742
742
|
_v2DataSources.clear();
|
|
743
743
|
_v2StatusHistory.clear();
|
|
744
744
|
}
|
|
745
|
+
|
|
746
|
+
|
|
747
|
+
// ===== V2 Surface: App Builder governance overlay (CLI v0.138.0) =====
|
|
748
|
+
export const APP_MATURITY_V2 = Object.freeze({
|
|
749
|
+
PENDING: "pending", ACTIVE: "active", PAUSED: "paused", ARCHIVED: "archived",
|
|
750
|
+
});
|
|
751
|
+
export const APP_BUILD_LIFECYCLE_V2 = Object.freeze({
|
|
752
|
+
QUEUED: "queued", BUILDING: "building", SUCCEEDED: "succeeded", FAILED: "failed", CANCELLED: "cancelled",
|
|
753
|
+
});
|
|
754
|
+
|
|
755
|
+
const _appTrans = new Map([
|
|
756
|
+
[APP_MATURITY_V2.PENDING, new Set([APP_MATURITY_V2.ACTIVE, APP_MATURITY_V2.ARCHIVED])],
|
|
757
|
+
[APP_MATURITY_V2.ACTIVE, new Set([APP_MATURITY_V2.PAUSED, APP_MATURITY_V2.ARCHIVED])],
|
|
758
|
+
[APP_MATURITY_V2.PAUSED, new Set([APP_MATURITY_V2.ACTIVE, APP_MATURITY_V2.ARCHIVED])],
|
|
759
|
+
[APP_MATURITY_V2.ARCHIVED, new Set()],
|
|
760
|
+
]);
|
|
761
|
+
const _appTerminal = new Set([APP_MATURITY_V2.ARCHIVED]);
|
|
762
|
+
const _appBuildTrans = new Map([
|
|
763
|
+
[APP_BUILD_LIFECYCLE_V2.QUEUED, new Set([APP_BUILD_LIFECYCLE_V2.BUILDING, APP_BUILD_LIFECYCLE_V2.CANCELLED])],
|
|
764
|
+
[APP_BUILD_LIFECYCLE_V2.BUILDING, new Set([APP_BUILD_LIFECYCLE_V2.SUCCEEDED, APP_BUILD_LIFECYCLE_V2.FAILED, APP_BUILD_LIFECYCLE_V2.CANCELLED])],
|
|
765
|
+
[APP_BUILD_LIFECYCLE_V2.SUCCEEDED, new Set()],
|
|
766
|
+
[APP_BUILD_LIFECYCLE_V2.FAILED, new Set()],
|
|
767
|
+
[APP_BUILD_LIFECYCLE_V2.CANCELLED, new Set()],
|
|
768
|
+
]);
|
|
769
|
+
|
|
770
|
+
const _appsV2 = new Map();
|
|
771
|
+
const _appBuilds = new Map();
|
|
772
|
+
let _appMaxActivePerOwner = 10;
|
|
773
|
+
let _appMaxPendingBuildsPerApp = 20;
|
|
774
|
+
let _appIdleMs = 30 * 24 * 60 * 60 * 1000;
|
|
775
|
+
let _appBuildStuckMs = 10 * 60 * 1000;
|
|
776
|
+
|
|
777
|
+
function _appPos(n, lbl) { const v = Math.floor(Number(n)); if (!Number.isFinite(v) || v <= 0) throw new Error(`${lbl} must be positive integer`); return v; }
|
|
778
|
+
|
|
779
|
+
export function setMaxActiveAppsPerOwnerV2(n) { _appMaxActivePerOwner = _appPos(n, "maxActiveAppsPerOwner"); }
|
|
780
|
+
export function getMaxActiveAppsPerOwnerV2() { return _appMaxActivePerOwner; }
|
|
781
|
+
export function setMaxPendingAppBuildsPerAppV2(n) { _appMaxPendingBuildsPerApp = _appPos(n, "maxPendingAppBuildsPerApp"); }
|
|
782
|
+
export function getMaxPendingAppBuildsPerAppV2() { return _appMaxPendingBuildsPerApp; }
|
|
783
|
+
export function setAppIdleMsV2(n) { _appIdleMs = _appPos(n, "appIdleMs"); }
|
|
784
|
+
export function getAppIdleMsV2() { return _appIdleMs; }
|
|
785
|
+
export function setAppBuildStuckMsV2(n) { _appBuildStuckMs = _appPos(n, "appBuildStuckMs"); }
|
|
786
|
+
export function getAppBuildStuckMsV2() { return _appBuildStuckMs; }
|
|
787
|
+
|
|
788
|
+
export function _resetStateAppBuilderV2() {
|
|
789
|
+
_appsV2.clear(); _appBuilds.clear();
|
|
790
|
+
_appMaxActivePerOwner = 10; _appMaxPendingBuildsPerApp = 20;
|
|
791
|
+
_appIdleMs = 30 * 24 * 60 * 60 * 1000; _appBuildStuckMs = 10 * 60 * 1000;
|
|
792
|
+
}
|
|
793
|
+
|
|
794
|
+
export function registerAppV2({ id, owner, name, metadata } = {}) {
|
|
795
|
+
if (!id || typeof id !== "string") throw new Error("id is required");
|
|
796
|
+
if (!owner || typeof owner !== "string") throw new Error("owner is required");
|
|
797
|
+
if (_appsV2.has(id)) throw new Error(`app ${id} already registered`);
|
|
798
|
+
const now = Date.now();
|
|
799
|
+
const a = { id, owner, name: name || id, status: APP_MATURITY_V2.PENDING, createdAt: now, updatedAt: now, activatedAt: null, archivedAt: null, lastTouchedAt: now, metadata: { ...(metadata || {}) } };
|
|
800
|
+
_appsV2.set(id, a);
|
|
801
|
+
return { ...a, metadata: { ...a.metadata } };
|
|
802
|
+
}
|
|
803
|
+
function _appCheckA(from, to) { const a = _appTrans.get(from); if (!a || !a.has(to)) throw new Error(`invalid app transition ${from} → ${to}`); }
|
|
804
|
+
function _appCountActive(owner) { let n = 0; for (const a of _appsV2.values()) if (a.owner === owner && a.status === APP_MATURITY_V2.ACTIVE) n++; return n; }
|
|
805
|
+
|
|
806
|
+
export function activateAppV2(id) {
|
|
807
|
+
const a = _appsV2.get(id); if (!a) throw new Error(`app ${id} not found`);
|
|
808
|
+
_appCheckA(a.status, APP_MATURITY_V2.ACTIVE);
|
|
809
|
+
const recovery = a.status === APP_MATURITY_V2.PAUSED;
|
|
810
|
+
if (!recovery) { const c = _appCountActive(a.owner); if (c >= _appMaxActivePerOwner) throw new Error(`max active apps per owner (${_appMaxActivePerOwner}) reached for ${a.owner}`); }
|
|
811
|
+
const now = Date.now(); a.status = APP_MATURITY_V2.ACTIVE; a.updatedAt = now; a.lastTouchedAt = now; if (!a.activatedAt) a.activatedAt = now;
|
|
812
|
+
return { ...a, metadata: { ...a.metadata } };
|
|
813
|
+
}
|
|
814
|
+
export function pauseAppV2(id) { const a = _appsV2.get(id); if (!a) throw new Error(`app ${id} not found`); _appCheckA(a.status, APP_MATURITY_V2.PAUSED); a.status = APP_MATURITY_V2.PAUSED; a.updatedAt = Date.now(); return { ...a, metadata: { ...a.metadata } }; }
|
|
815
|
+
export function archiveAppV2(id) { const a = _appsV2.get(id); if (!a) throw new Error(`app ${id} not found`); _appCheckA(a.status, APP_MATURITY_V2.ARCHIVED); const now = Date.now(); a.status = APP_MATURITY_V2.ARCHIVED; a.updatedAt = now; if (!a.archivedAt) a.archivedAt = now; return { ...a, metadata: { ...a.metadata } }; }
|
|
816
|
+
export function touchAppV2(id) { const a = _appsV2.get(id); if (!a) throw new Error(`app ${id} not found`); if (_appTerminal.has(a.status)) throw new Error(`cannot touch terminal app ${id}`); const now = Date.now(); a.lastTouchedAt = now; a.updatedAt = now; return { ...a, metadata: { ...a.metadata } }; }
|
|
817
|
+
export function getAppV2(id) { const a = _appsV2.get(id); if (!a) return null; return { ...a, metadata: { ...a.metadata } }; }
|
|
818
|
+
export function listAppsV2() { return [..._appsV2.values()].map((a) => ({ ...a, metadata: { ...a.metadata } })); }
|
|
819
|
+
|
|
820
|
+
function _appCountPendingBuilds(appId) { let n = 0; for (const b of _appBuilds.values()) if (b.appId === appId && (b.status === APP_BUILD_LIFECYCLE_V2.QUEUED || b.status === APP_BUILD_LIFECYCLE_V2.BUILDING)) n++; return n; }
|
|
821
|
+
|
|
822
|
+
export function createAppBuildV2({ id, appId, target, metadata } = {}) {
|
|
823
|
+
if (!id || typeof id !== "string") throw new Error("id is required");
|
|
824
|
+
if (!appId || typeof appId !== "string") throw new Error("appId is required");
|
|
825
|
+
if (_appBuilds.has(id)) throw new Error(`app build ${id} already exists`);
|
|
826
|
+
if (!_appsV2.has(appId)) throw new Error(`app ${appId} not found`);
|
|
827
|
+
const pending = _appCountPendingBuilds(appId);
|
|
828
|
+
if (pending >= _appMaxPendingBuildsPerApp) throw new Error(`max pending app builds per app (${_appMaxPendingBuildsPerApp}) reached for ${appId}`);
|
|
829
|
+
const now = Date.now();
|
|
830
|
+
const b = { id, appId, target: target || "web", status: APP_BUILD_LIFECYCLE_V2.QUEUED, createdAt: now, updatedAt: now, startedAt: null, settledAt: null, metadata: { ...(metadata || {}) } };
|
|
831
|
+
_appBuilds.set(id, b);
|
|
832
|
+
return { ...b, metadata: { ...b.metadata } };
|
|
833
|
+
}
|
|
834
|
+
function _appCheckB(from, to) { const a = _appBuildTrans.get(from); if (!a || !a.has(to)) throw new Error(`invalid app build transition ${from} → ${to}`); }
|
|
835
|
+
export function startAppBuildV2(id) { const b = _appBuilds.get(id); if (!b) throw new Error(`app build ${id} not found`); _appCheckB(b.status, APP_BUILD_LIFECYCLE_V2.BUILDING); const now = Date.now(); b.status = APP_BUILD_LIFECYCLE_V2.BUILDING; b.updatedAt = now; if (!b.startedAt) b.startedAt = now; return { ...b, metadata: { ...b.metadata } }; }
|
|
836
|
+
export function succeedAppBuildV2(id) { const b = _appBuilds.get(id); if (!b) throw new Error(`app build ${id} not found`); _appCheckB(b.status, APP_BUILD_LIFECYCLE_V2.SUCCEEDED); const now = Date.now(); b.status = APP_BUILD_LIFECYCLE_V2.SUCCEEDED; b.updatedAt = now; if (!b.settledAt) b.settledAt = now; return { ...b, metadata: { ...b.metadata } }; }
|
|
837
|
+
export function failAppBuildV2(id, reason) { const b = _appBuilds.get(id); if (!b) throw new Error(`app build ${id} not found`); _appCheckB(b.status, APP_BUILD_LIFECYCLE_V2.FAILED); const now = Date.now(); b.status = APP_BUILD_LIFECYCLE_V2.FAILED; b.updatedAt = now; if (!b.settledAt) b.settledAt = now; if (reason) b.metadata.failReason = String(reason); return { ...b, metadata: { ...b.metadata } }; }
|
|
838
|
+
export function cancelAppBuildV2(id, reason) { const b = _appBuilds.get(id); if (!b) throw new Error(`app build ${id} not found`); _appCheckB(b.status, APP_BUILD_LIFECYCLE_V2.CANCELLED); const now = Date.now(); b.status = APP_BUILD_LIFECYCLE_V2.CANCELLED; b.updatedAt = now; if (!b.settledAt) b.settledAt = now; if (reason) b.metadata.cancelReason = String(reason); return { ...b, metadata: { ...b.metadata } }; }
|
|
839
|
+
export function getAppBuildV2(id) { const b = _appBuilds.get(id); if (!b) return null; return { ...b, metadata: { ...b.metadata } }; }
|
|
840
|
+
export function listAppBuildsV2() { return [..._appBuilds.values()].map((b) => ({ ...b, metadata: { ...b.metadata } })); }
|
|
841
|
+
|
|
842
|
+
export function autoPauseIdleAppsV2({ now } = {}) { const t = now ?? Date.now(); const flipped = []; for (const a of _appsV2.values()) if (a.status === APP_MATURITY_V2.ACTIVE && (t - a.lastTouchedAt) >= _appIdleMs) { a.status = APP_MATURITY_V2.PAUSED; a.updatedAt = t; flipped.push(a.id); } return { flipped, count: flipped.length }; }
|
|
843
|
+
export function autoFailStuckAppBuildsV2({ now } = {}) { const t = now ?? Date.now(); const flipped = []; for (const b of _appBuilds.values()) if (b.status === APP_BUILD_LIFECYCLE_V2.BUILDING && b.startedAt != null && (t - b.startedAt) >= _appBuildStuckMs) { b.status = APP_BUILD_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 }; }
|
|
844
|
+
|
|
845
|
+
export function getAppBuilderGovStatsV2() {
|
|
846
|
+
const appsByStatus = {}; for (const s of Object.values(APP_MATURITY_V2)) appsByStatus[s] = 0; for (const a of _appsV2.values()) appsByStatus[a.status]++;
|
|
847
|
+
const buildsByStatus = {}; for (const s of Object.values(APP_BUILD_LIFECYCLE_V2)) buildsByStatus[s] = 0; for (const b of _appBuilds.values()) buildsByStatus[b.status]++;
|
|
848
|
+
return { totalAppsV2: _appsV2.size, totalAppBuildsV2: _appBuilds.size, maxActiveAppsPerOwner: _appMaxActivePerOwner, maxPendingAppBuildsPerApp: _appMaxPendingBuildsPerApp, appIdleMs: _appIdleMs, appBuildStuckMs: _appBuildStuckMs, appsByStatus, buildsByStatus };
|
|
849
|
+
}
|