@muxoai/platform 1.3.1 → 1.3.2
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/README.md +10 -2
- package/dist/clerk.d.ts +33 -0
- package/dist/clerk.js +198 -0
- package/dist/cli.js +422 -26
- package/dist/engine.d.ts +21 -1
- package/dist/engine.js +245 -23
- package/dist/mcp.js +2 -1
- package/dist/policy.d.ts +9 -0
- package/dist/policy.js +73 -0
- package/dist/providers/composio-instant.d.ts +3 -0
- package/dist/providers/composio-instant.js +629 -530
- package/dist/providers/microsoft-governance.d.ts +61 -2
- package/dist/providers/microsoft-governance.js +458 -24
- package/dist/providers/stripe-projects.d.ts +4 -1
- package/dist/providers/stripe-projects.js +64 -10
- package/dist/providers/supermemory.d.ts +26 -5
- package/dist/providers/supermemory.js +136 -26
- package/dist/sdk.d.ts +167 -1
- package/dist/sdk.js +113 -2
- package/dist/server.js +176 -16
- package/dist/store.d.ts +25 -1
- package/dist/store.js +236 -3
- package/dist/types.d.ts +86 -0
- package/dist/ui/console-html.d.ts +16 -0
- package/dist/ui/console-html.js +2427 -2226
- package/dist/ui/design-tokens.d.ts +177 -0
- package/dist/ui/design-tokens.js +210 -0
- package/dist/version.d.ts +1 -0
- package/dist/version.js +1 -0
- package/package.json +2 -2
package/dist/engine.js
CHANGED
|
@@ -3,7 +3,7 @@ import { ComposioInstantAdapter } from "./providers/composio-instant.js";
|
|
|
3
3
|
import { ComposioSdkAdapter } from "./providers/composio-sdk.js";
|
|
4
4
|
import { MicrosoftGovernanceAdapter } from "./providers/microsoft-governance.js";
|
|
5
5
|
import { StripeBillingAdapter } from "./providers/stripe-billing.js";
|
|
6
|
-
import { StripeProjectsAdapter } from "./providers/stripe-projects.js";
|
|
6
|
+
import { StripeProjectsAdapter, isPaidCloudProvisioning, } from "./providers/stripe-projects.js";
|
|
7
7
|
import { SupermemoryAdapter } from "./providers/supermemory.js";
|
|
8
8
|
export class MuxoEngine {
|
|
9
9
|
config;
|
|
@@ -396,8 +396,14 @@ export class MuxoEngine {
|
|
|
396
396
|
resolvedInput = nl.input;
|
|
397
397
|
resolvedReason = params.reason || nl.reason || nlSource;
|
|
398
398
|
}
|
|
399
|
-
const byokActive =
|
|
400
|
-
|
|
399
|
+
const byokActive = params.fundingMode === "muxo_funded"
|
|
400
|
+
? false
|
|
401
|
+
: this.store.hasByokForLane(ws.id, tool.lane, tool.slug);
|
|
402
|
+
const isPaidResourcePlan = isPaidCloudProvisioning(tool, resolvedInput);
|
|
403
|
+
const baseCreditCost = isPaidResourcePlan
|
|
404
|
+
? Math.max(tool.creditCost, 25)
|
|
405
|
+
: tool.creditCost;
|
|
406
|
+
const effectiveCreditCost = byokActive ? 0 : baseCreditCost;
|
|
401
407
|
if (ws.monthlyActionsUsed >= ws.monthlyActionsLimit) {
|
|
402
408
|
throw new Error(`Monthly action limit reached (${ws.monthlyActionsUsed}/${ws.monthlyActionsLimit}). Upgrade to Starter ($29/mo) to unlock 5,000 actions/mo.`);
|
|
403
409
|
}
|
|
@@ -421,7 +427,8 @@ export class MuxoEngine {
|
|
|
421
427
|
}
|
|
422
428
|
// 2. Recall Supermemory v5 contextual brain for this workspace + tool intent
|
|
423
429
|
const memoryQuery = `${tool.slug} ${tool.name} ${resolvedReason}`.trim();
|
|
424
|
-
const
|
|
430
|
+
const supermemoryByok = this.store.getByokKey(ws.id, "supermemory");
|
|
431
|
+
const memoryContext = await this.enrichMemoryContext(ws.id, await this.supermemory.getContextForWorkspace(ws.id, memoryQuery, supermemoryByok), memoryQuery);
|
|
425
432
|
const requiresHumanApproval = decisionRecord.verdict === "escalate" ||
|
|
426
433
|
(ws.policy.mode === "enforce" &&
|
|
427
434
|
ws.policy.requireApprovalFor.includes(tool.riskLevel));
|
|
@@ -510,13 +517,13 @@ export class MuxoEngine {
|
|
|
510
517
|
approvedBy: ctx.user.email,
|
|
511
518
|
});
|
|
512
519
|
}
|
|
513
|
-
async enrichMemoryContext(workspaceId, ctx) {
|
|
514
|
-
if (ctx.recalledMemories.length > 0 && ctx.staticFacts.length > 0) {
|
|
515
|
-
return ctx;
|
|
516
|
-
}
|
|
520
|
+
async enrichMemoryContext(workspaceId, ctx, query) {
|
|
517
521
|
const localRecords = this.store.listMemoryRecords(workspaceId, 8);
|
|
518
|
-
|
|
519
|
-
|
|
522
|
+
const temporalFacts = this.store.listTemporalFacts(workspaceId, {
|
|
523
|
+
includeHistorical: false,
|
|
524
|
+
query,
|
|
525
|
+
limit: 15,
|
|
526
|
+
});
|
|
520
527
|
const recalled = ctx.recalledMemories.length > 0
|
|
521
528
|
? ctx.recalledMemories
|
|
522
529
|
: localRecords.slice(0, 5).map((r) => ({
|
|
@@ -524,6 +531,7 @@ export class MuxoEngine {
|
|
|
524
531
|
title: r.title,
|
|
525
532
|
snippet: r.content.slice(0, 240),
|
|
526
533
|
similarity: 1,
|
|
534
|
+
createdAt: r.createdAt,
|
|
527
535
|
}));
|
|
528
536
|
const staticFacts = ctx.staticFacts.length > 0
|
|
529
537
|
? ctx.staticFacts
|
|
@@ -531,14 +539,66 @@ export class MuxoEngine {
|
|
|
531
539
|
.filter((r) => r.kind === "fact" || r.kind === "preference")
|
|
532
540
|
.slice(0, 5)
|
|
533
541
|
.map((r) => `${r.title}: ${r.content.slice(0, 140)}`);
|
|
542
|
+
const dynamicContext = ctx.dynamicContext.length > 0
|
|
543
|
+
? ctx.dynamicContext
|
|
544
|
+
: temporalFacts.slice(0, 6).map((f) => `${f.subject} ${f.predicate} ${f.object}`);
|
|
545
|
+
const combinedText = [
|
|
546
|
+
...staticFacts,
|
|
547
|
+
...dynamicContext,
|
|
548
|
+
...recalled.map((m) => `${m.title}: ${m.snippet}`),
|
|
549
|
+
].join("\n");
|
|
550
|
+
const poisonScan = this.governance.scanMemoryContent({
|
|
551
|
+
workspaceId,
|
|
552
|
+
sessionId: ctx.namespace,
|
|
553
|
+
role: "system",
|
|
554
|
+
content: combinedText,
|
|
555
|
+
recordInDetector: false,
|
|
556
|
+
});
|
|
557
|
+
const promptLines = [
|
|
558
|
+
`[Supermemory Brain — Namespace: ${ctx.namespace}]`,
|
|
559
|
+
];
|
|
560
|
+
if (staticFacts.length > 0) {
|
|
561
|
+
promptLines.push(`Static Facts: ${staticFacts.join(" | ")}`);
|
|
562
|
+
}
|
|
563
|
+
if (dynamicContext.length > 0) {
|
|
564
|
+
promptLines.push(`Dynamic Context: ${dynamicContext.join(" | ")}`);
|
|
565
|
+
}
|
|
566
|
+
if (temporalFacts.length > 0) {
|
|
567
|
+
promptLines.push(`Bi-Temporal Lineage (${temporalFacts.length} active): ${temporalFacts
|
|
568
|
+
.slice(0, 5)
|
|
569
|
+
.map((f) => `${f.subject} -[${f.predicate}]-> ${f.object}`)
|
|
570
|
+
.join(" | ")}`);
|
|
571
|
+
}
|
|
572
|
+
if (recalled.length > 0) {
|
|
573
|
+
promptLines.push(`Recalled Memories: ${recalled.map((m) => `${m.title}: ${m.snippet}`).join(" | ")}`);
|
|
574
|
+
}
|
|
575
|
+
const mdLines = [`## Workspace Brain (${ctx.namespace})`];
|
|
576
|
+
if (staticFacts.length > 0) {
|
|
577
|
+
mdLines.push("### Static Facts", ...staticFacts.map((f) => `- ${f}`));
|
|
578
|
+
}
|
|
579
|
+
if (temporalFacts.length > 0) {
|
|
580
|
+
mdLines.push("### Bi-Temporal Resource & Fact Lineage (Active)", ...temporalFacts
|
|
581
|
+
.slice(0, 8)
|
|
582
|
+
.map((f) => `- **${f.subject}** \`${f.predicate}\` **${f.object}** _(validFrom: ${f.validFrom})_ — ${f.summary}`));
|
|
583
|
+
}
|
|
534
584
|
return {
|
|
535
585
|
...ctx,
|
|
536
586
|
staticFacts,
|
|
587
|
+
dynamicContext,
|
|
537
588
|
recalledMemories: recalled,
|
|
538
589
|
relevantMemories: recalled,
|
|
590
|
+
formattedPromptContext: promptLines.join("\n"),
|
|
591
|
+
profileMarkdown: ctx.profileMarkdown || mdLines.join("\n"),
|
|
539
592
|
profile: {
|
|
540
593
|
...ctx.profile,
|
|
541
594
|
static: staticFacts,
|
|
595
|
+
dynamic: dynamicContext,
|
|
596
|
+
},
|
|
597
|
+
temporalFacts,
|
|
598
|
+
contextPoisoningScan: {
|
|
599
|
+
safe: poisonScan.safe,
|
|
600
|
+
riskLevel: poisonScan.riskLevel,
|
|
601
|
+
findingsCount: poisonScan.findingsCount,
|
|
542
602
|
},
|
|
543
603
|
};
|
|
544
604
|
}
|
|
@@ -552,7 +612,8 @@ export class MuxoEngine {
|
|
|
552
612
|
redactedEnv[k] =
|
|
553
613
|
v.length > 8 ? `${v.slice(0, 4)}••••${v.slice(-3)}` : "••••••••";
|
|
554
614
|
}
|
|
555
|
-
const
|
|
615
|
+
const supermemoryByok = this.store.getByokKey(ws.id, "supermemory");
|
|
616
|
+
const memoryContext = await this.enrichMemoryContext(ws.id, await this.supermemory.getContextForWorkspace(ws.id, query, supermemoryByok), query);
|
|
556
617
|
return {
|
|
557
618
|
workspaceId: ws.id,
|
|
558
619
|
workspaceSlug: ws.slug,
|
|
@@ -563,33 +624,62 @@ export class MuxoEngine {
|
|
|
563
624
|
provisionedResources: resources.filter((r) => r.status === "active"),
|
|
564
625
|
environmentVariablesRedacted: redactedEnv,
|
|
565
626
|
supermemoryBrain: memoryContext,
|
|
627
|
+
temporalFacts: memoryContext.temporalFacts || [],
|
|
566
628
|
governance: this.governance.getStatus(ws),
|
|
629
|
+
trustScore: this.governance.getWorkspaceTrustScore(ws.id),
|
|
567
630
|
envPullHint: "Run `muxo env pull` or call GET /api/v1/resources/env to write decrypted credentials to your local .env file.",
|
|
568
631
|
};
|
|
569
632
|
}
|
|
570
633
|
// Supermemory Workspace Brain Operations
|
|
571
634
|
async getMemoryOverview(ctx, query) {
|
|
572
|
-
const
|
|
635
|
+
const supermemoryByok = this.store.getByokKey(ctx.workspace.id, "supermemory");
|
|
636
|
+
const context = await this.enrichMemoryContext(ctx.workspace.id, await this.supermemory.getContextForWorkspace(ctx.workspace.id, query, supermemoryByok), query);
|
|
573
637
|
const recentMemories = this.store.listMemoryRecords(ctx.workspace.id, 25);
|
|
638
|
+
const allFacts = this.store.listTemporalFacts(ctx.workspace.id, {
|
|
639
|
+
includeHistorical: true,
|
|
640
|
+
query,
|
|
641
|
+
limit: 50,
|
|
642
|
+
});
|
|
574
643
|
return {
|
|
575
644
|
enabled: context.enabled,
|
|
576
645
|
namespace: context.namespace,
|
|
646
|
+
fundingSource: context.fundingSource || "local_fallback",
|
|
577
647
|
context,
|
|
578
648
|
recentMemories,
|
|
579
649
|
memories: recentMemories,
|
|
650
|
+
temporalFacts: allFacts.filter((f) => f.validTo === null),
|
|
651
|
+
historicalFacts: allFacts.filter((f) => f.validTo !== null),
|
|
580
652
|
};
|
|
581
653
|
}
|
|
582
654
|
async addWorkspaceMemory(ctx, params) {
|
|
655
|
+
const ws = this.store.getWorkspace(ctx.workspace.id);
|
|
583
656
|
const kind = params.kind || "fact";
|
|
657
|
+
// Microsoft Agent Governance OWASP ASI-06 ContextPoisoningDetector guard on memory ingestion
|
|
658
|
+
const poisonScan = this.governance.scanMemoryContent({
|
|
659
|
+
workspaceId: ws.id,
|
|
660
|
+
sessionId: this.supermemory.getWorkspaceNamespace(ws.id),
|
|
661
|
+
role: "user",
|
|
662
|
+
content: `${params.title}\n${params.content}`,
|
|
663
|
+
recordInDetector: true,
|
|
664
|
+
});
|
|
665
|
+
if (!poisonScan.safe && ws.policy.mode === "enforce") {
|
|
666
|
+
this.governance.recordAgentOutcome(ws.id, false, 0.1);
|
|
667
|
+
throw new Error(`Blocked by Microsoft ContextPoisoningDetector (OWASP ASI-06, risk=${poisonScan.riskLevel}): ${poisonScan.findings
|
|
668
|
+
.map((f) => `${f.patternName} (${f.description})`)
|
|
669
|
+
.join("; ")}`);
|
|
670
|
+
}
|
|
671
|
+
const supermemoryByok = this.store.getByokKey(ws.id, "supermemory");
|
|
584
672
|
const remote = await this.supermemory.addMemory({
|
|
585
|
-
workspaceId:
|
|
673
|
+
workspaceId: ws.id,
|
|
586
674
|
title: params.title,
|
|
587
675
|
content: params.content,
|
|
588
676
|
kind,
|
|
589
677
|
metadata: params.metadata,
|
|
678
|
+
apiKeyOverride: supermemoryByok,
|
|
679
|
+
dreaming: "instant",
|
|
590
680
|
});
|
|
591
|
-
|
|
592
|
-
workspaceId:
|
|
681
|
+
const record = this.store.saveMemoryRecord({
|
|
682
|
+
workspaceId: ws.id,
|
|
593
683
|
namespace: remote.namespace,
|
|
594
684
|
documentId: remote.documentId,
|
|
595
685
|
title: params.title,
|
|
@@ -598,18 +688,103 @@ export class MuxoEngine {
|
|
|
598
688
|
metadata: {
|
|
599
689
|
...(params.metadata || {}),
|
|
600
690
|
supermemoryStatus: remote.status,
|
|
691
|
+
fundingSource: remote.fundingSource,
|
|
692
|
+
contextPoisoningScan: {
|
|
693
|
+
safe: poisonScan.safe,
|
|
694
|
+
riskLevel: poisonScan.riskLevel,
|
|
695
|
+
findingsCount: poisonScan.findingsCount,
|
|
696
|
+
},
|
|
601
697
|
},
|
|
602
698
|
});
|
|
699
|
+
// Record bi-temporal entity/relationship lineage (auto-superseding prior facts for same subject+predicate)
|
|
700
|
+
const normalizedTitlePred = params.title
|
|
701
|
+
.trim()
|
|
702
|
+
.toUpperCase()
|
|
703
|
+
.replace(/[^A-Z0-9]+/g, "_")
|
|
704
|
+
.replace(/^_|_$/g, "")
|
|
705
|
+
.slice(0, 48);
|
|
706
|
+
const subject = params.subject ||
|
|
707
|
+
(typeof params.metadata?.subject === "string"
|
|
708
|
+
? params.metadata.subject
|
|
709
|
+
: `workspace:${ws.slug}`);
|
|
710
|
+
const predicate = params.predicate ||
|
|
711
|
+
(typeof params.metadata?.predicate === "string"
|
|
712
|
+
? params.metadata.predicate
|
|
713
|
+
: normalizedTitlePred || kind.toUpperCase());
|
|
714
|
+
const object = params.object ||
|
|
715
|
+
(typeof params.metadata?.object === "string"
|
|
716
|
+
? params.metadata.object
|
|
717
|
+
: remote.sanitizedContent.slice(0, 160));
|
|
718
|
+
this.store.upsertTemporalFact({
|
|
719
|
+
workspaceId: ws.id,
|
|
720
|
+
subject,
|
|
721
|
+
predicate,
|
|
722
|
+
object,
|
|
723
|
+
summary: `${params.title}: ${remote.sanitizedContent.slice(0, 240)}`,
|
|
724
|
+
confidence: 0.95,
|
|
725
|
+
sourceKind: kind,
|
|
726
|
+
sourceReferenceId: record.id,
|
|
727
|
+
metadata: params.metadata || {},
|
|
728
|
+
});
|
|
729
|
+
return record;
|
|
603
730
|
}
|
|
604
731
|
async deleteWorkspaceMemory(ctx, idOrDocId) {
|
|
605
732
|
const local = this.store.deleteMemoryRecord(ctx.workspace.id, idOrDocId);
|
|
606
733
|
const docId = local?.documentId || idOrDocId;
|
|
607
|
-
const
|
|
734
|
+
const supermemoryByok = this.store.getByokKey(ctx.workspace.id, "supermemory");
|
|
735
|
+
const remote = await this.supermemory.deleteMemory(ctx.workspace.id, docId, supermemoryByok);
|
|
608
736
|
return {
|
|
609
737
|
deleted: Boolean(local || remote.deleted),
|
|
610
738
|
record: local,
|
|
611
739
|
};
|
|
612
740
|
}
|
|
741
|
+
async forgetWorkspaceMemoryMatching(ctx, query) {
|
|
742
|
+
const localPruned = this.store.forgetMatchingMemoryRecords(ctx.workspace.id, query);
|
|
743
|
+
const supermemoryByok = this.store.getByokKey(ctx.workspace.id, "supermemory");
|
|
744
|
+
const remotePruned = await this.supermemory.forgetMatching({
|
|
745
|
+
workspaceId: ctx.workspace.id,
|
|
746
|
+
query,
|
|
747
|
+
apiKeyOverride: supermemoryByok,
|
|
748
|
+
});
|
|
749
|
+
return {
|
|
750
|
+
query,
|
|
751
|
+
deletedLocalCount: localPruned.deletedMemories.length,
|
|
752
|
+
invalidatedFactsCount: localPruned.invalidatedFacts.length,
|
|
753
|
+
deletedRemoteIds: remotePruned.deletedRemoteIds,
|
|
754
|
+
deletedMemories: localPruned.deletedMemories,
|
|
755
|
+
invalidatedFacts: localPruned.invalidatedFacts,
|
|
756
|
+
};
|
|
757
|
+
}
|
|
758
|
+
async activateWorkspaceKillSwitch(ctx, params) {
|
|
759
|
+
const ws = this.store.getWorkspace(ctx.workspace.id);
|
|
760
|
+
const result = await this.governance.activateKillSwitch(ws.id, params.reason, params.action || "quarantine");
|
|
761
|
+
const updatedWs = this.store.updateWorkspacePolicy(ws.id, {
|
|
762
|
+
...ws.policy,
|
|
763
|
+
killSwitchActive: true,
|
|
764
|
+
killSwitchReason: params.reason,
|
|
765
|
+
});
|
|
766
|
+
return {
|
|
767
|
+
activated: true,
|
|
768
|
+
killSwitch: result,
|
|
769
|
+
policy: updatedWs.policy,
|
|
770
|
+
trustScore: this.governance.getWorkspaceTrustScore(ws.id),
|
|
771
|
+
};
|
|
772
|
+
}
|
|
773
|
+
resumeWorkspaceKillSwitch(ctx) {
|
|
774
|
+
const ws = this.store.getWorkspace(ctx.workspace.id);
|
|
775
|
+
const resumed = this.governance.resumeKillSwitch(ws.id);
|
|
776
|
+
const updatedWs = this.store.updateWorkspacePolicy(ws.id, {
|
|
777
|
+
...ws.policy,
|
|
778
|
+
killSwitchActive: false,
|
|
779
|
+
killSwitchReason: null,
|
|
780
|
+
});
|
|
781
|
+
return {
|
|
782
|
+
...resumed,
|
|
783
|
+
resumed: true,
|
|
784
|
+
policy: updatedWs.policy,
|
|
785
|
+
trustScore: this.governance.getWorkspaceTrustScore(ws.id),
|
|
786
|
+
};
|
|
787
|
+
}
|
|
613
788
|
// 10-15. execute_<risk_level>
|
|
614
789
|
async executePlanForRisk(ctx, planId, expectedRisk) {
|
|
615
790
|
const plan = this.getPlan(ctx, planId);
|
|
@@ -632,8 +807,17 @@ export class MuxoEngine {
|
|
|
632
807
|
}
|
|
633
808
|
const ws = this.store.getWorkspace(ctx.workspace.id);
|
|
634
809
|
const tool = await this.inspectTool(plan.toolSlug);
|
|
635
|
-
const
|
|
636
|
-
const
|
|
810
|
+
const explicitFunding = plan.supplierSettlement?.fundingMode;
|
|
811
|
+
const byokActive = explicitFunding === "byok"
|
|
812
|
+
? true
|
|
813
|
+
: explicitFunding === "muxo_funded"
|
|
814
|
+
? false
|
|
815
|
+
: this.store.hasByokForLane(ws.id, tool.lane, tool.slug);
|
|
816
|
+
const effectiveCreditCost = byokActive
|
|
817
|
+
? 0
|
|
818
|
+
: plan.creditCost > 0
|
|
819
|
+
? plan.creditCost
|
|
820
|
+
: tool.creditCost;
|
|
637
821
|
if (ws.monthlyActionsUsed >= ws.monthlyActionsLimit) {
|
|
638
822
|
throw new Error(`Monthly action limit reached (${ws.monthlyActionsUsed}/${ws.monthlyActionsLimit}). Upgrade to Starter ($29/mo) to unlock 5,000 actions/mo.`);
|
|
639
823
|
}
|
|
@@ -683,16 +867,28 @@ export class MuxoEngine {
|
|
|
683
867
|
});
|
|
684
868
|
}
|
|
685
869
|
else if (plan.lane === "composio_instant") {
|
|
686
|
-
const composioByok =
|
|
870
|
+
const composioByok = byokActive
|
|
871
|
+
? this.store.getByokKey(ctx.workspace.id, "composio")
|
|
872
|
+
: null;
|
|
873
|
+
const exaByok = byokActive
|
|
874
|
+
? this.store.getByokKey(ctx.workspace.id, "exa")
|
|
875
|
+
: null;
|
|
876
|
+
const firecrawlByok = byokActive
|
|
877
|
+
? this.store.getByokKey(ctx.workspace.id, "firecrawl")
|
|
878
|
+
: null;
|
|
687
879
|
output = await this.composioInstant.executeTool({
|
|
688
880
|
workspaceId: ctx.workspace.id,
|
|
689
881
|
tool,
|
|
690
882
|
input: plan.input,
|
|
691
883
|
composioApiKey: composioByok,
|
|
884
|
+
exaApiKey: exaByok,
|
|
885
|
+
firecrawlApiKey: firecrawlByok,
|
|
692
886
|
});
|
|
693
887
|
}
|
|
694
888
|
else if (plan.lane === "composio_sdk") {
|
|
695
|
-
const composioByok =
|
|
889
|
+
const composioByok = byokActive
|
|
890
|
+
? this.store.getByokKey(ctx.workspace.id, "composio")
|
|
891
|
+
: null;
|
|
696
892
|
output = await this.composioSdk.executeTool({
|
|
697
893
|
workspaceId: ctx.workspace.id,
|
|
698
894
|
tool,
|
|
@@ -702,10 +898,14 @@ export class MuxoEngine {
|
|
|
702
898
|
});
|
|
703
899
|
}
|
|
704
900
|
else if (plan.lane === "stripe_projects") {
|
|
901
|
+
const stripeByok = byokActive
|
|
902
|
+
? this.store.getByokKey(ctx.workspace.id, "stripe")
|
|
903
|
+
: null;
|
|
705
904
|
const projResult = await this.stripeProjects.executeTool({
|
|
706
905
|
workspaceId: ctx.workspace.id,
|
|
707
906
|
tool,
|
|
708
907
|
input: plan.input,
|
|
908
|
+
stripeApiKey: stripeByok,
|
|
709
909
|
});
|
|
710
910
|
output = projResult.output;
|
|
711
911
|
if (projResult.provisionedResource) {
|
|
@@ -719,6 +919,7 @@ export class MuxoEngine {
|
|
|
719
919
|
throw new Error(`Unsupported execution lane: ${plan.lane}`);
|
|
720
920
|
}
|
|
721
921
|
const durationMs = Date.now() - startedMs;
|
|
922
|
+
this.governance.recordAgentOutcome(ctx.workspace.id, true, 0.05);
|
|
722
923
|
const finalized = this.store.finalizeRun({
|
|
723
924
|
workspaceId: ctx.workspace.id,
|
|
724
925
|
runId: run.id,
|
|
@@ -729,9 +930,27 @@ export class MuxoEngine {
|
|
|
729
930
|
durationMs,
|
|
730
931
|
decisionRecord: execDecisionRecord,
|
|
731
932
|
});
|
|
933
|
+
this.store.upsertTemporalFact({
|
|
934
|
+
workspaceId: ctx.workspace.id,
|
|
935
|
+
subject: `tool:${plan.toolSlug}`,
|
|
936
|
+
predicate: "LAST_EXECUTION",
|
|
937
|
+
object: `succeeded:${finalized.run.id}`,
|
|
938
|
+
summary: `Executed ${plan.toolSlug} (${plan.lane}, risk=${plan.riskLevel}) -> succeeded [receipt=${finalized.receipt.id}]`,
|
|
939
|
+
confidence: 1.0,
|
|
940
|
+
sourceKind: "execution_outcome",
|
|
941
|
+
sourceReferenceId: finalized.run.id,
|
|
942
|
+
metadata: {
|
|
943
|
+
runId: finalized.run.id,
|
|
944
|
+
receiptId: finalized.receipt.id,
|
|
945
|
+
toolSlug: plan.toolSlug,
|
|
946
|
+
lane: plan.lane,
|
|
947
|
+
riskLevel: plan.riskLevel,
|
|
948
|
+
},
|
|
949
|
+
});
|
|
732
950
|
// Record secret-redacted post-run memory in Supermemory for stateful actions
|
|
733
951
|
if (plan.riskLevel !== "read") {
|
|
734
952
|
const summary = `Executed ${plan.toolSlug} (${plan.lane}, risk=${plan.riskLevel}) for reason "${plan.reason}" -> status=succeeded (receipt=${finalized.receipt.id}).`;
|
|
953
|
+
const supermemoryByok = this.store.getByokKey(ctx.workspace.id, "supermemory");
|
|
735
954
|
this.supermemory
|
|
736
955
|
.recordExecutionMemory({
|
|
737
956
|
workspaceId: ctx.workspace.id,
|
|
@@ -741,6 +960,7 @@ export class MuxoEngine {
|
|
|
741
960
|
reason: plan.reason,
|
|
742
961
|
status: "succeeded",
|
|
743
962
|
summary,
|
|
963
|
+
apiKeyOverride: supermemoryByok,
|
|
744
964
|
})
|
|
745
965
|
.then((docId) => {
|
|
746
966
|
if (docId) {
|
|
@@ -765,6 +985,7 @@ export class MuxoEngine {
|
|
|
765
985
|
}
|
|
766
986
|
catch (err) {
|
|
767
987
|
const durationMs = Date.now() - startedMs;
|
|
988
|
+
this.governance.recordAgentOutcome(ctx.workspace.id, false, 0.08);
|
|
768
989
|
const errorMessage = String(err?.message || err || "Execution failed");
|
|
769
990
|
return this.store.finalizeRun({
|
|
770
991
|
workspaceId: ctx.workspace.id,
|
|
@@ -787,7 +1008,7 @@ export class MuxoEngine {
|
|
|
787
1008
|
return run;
|
|
788
1009
|
}
|
|
789
1010
|
// 17. cancel_run
|
|
790
|
-
cancelRun(ctx, runId) {
|
|
1011
|
+
cancelRun(ctx, runId, reason) {
|
|
791
1012
|
const run = this.getRun(ctx, runId);
|
|
792
1013
|
if (run.status === "succeeded" || run.status === "failed" || run.status === "cancelled") {
|
|
793
1014
|
return {
|
|
@@ -799,8 +1020,8 @@ export class MuxoEngine {
|
|
|
799
1020
|
workspaceId: ctx.workspace.id,
|
|
800
1021
|
runId: run.id,
|
|
801
1022
|
status: "cancelled",
|
|
802
|
-
output: { cancelledBy: ctx.actorId },
|
|
803
|
-
error: "Cancelled by operator",
|
|
1023
|
+
output: { cancelledBy: ctx.actorId, ...(reason ? { reason } : {}) },
|
|
1024
|
+
error: reason || "Cancelled by operator",
|
|
804
1025
|
actionsMetered: 0,
|
|
805
1026
|
creditsMetered: 0,
|
|
806
1027
|
durationMs: Date.now() - new Date(run.startedAt).getTime(),
|
|
@@ -865,6 +1086,7 @@ export class MuxoEngine {
|
|
|
865
1086
|
toolSlug: resolution.tool.slug,
|
|
866
1087
|
input: resolution.input,
|
|
867
1088
|
reason: params.prompt,
|
|
1089
|
+
fundingMode: params.fundingMode,
|
|
868
1090
|
});
|
|
869
1091
|
if (planned.authHandoff?.required) {
|
|
870
1092
|
return {
|
package/dist/mcp.js
CHANGED
|
@@ -2,6 +2,7 @@ import crypto from "node:crypto";
|
|
|
2
2
|
import fs from "node:fs";
|
|
3
3
|
import path from "node:path";
|
|
4
4
|
import { ROOT_DIR } from "./config.js";
|
|
5
|
+
import { MUXO_VERSION } from "./version.js";
|
|
5
6
|
const DEFAULT_TOOL_SECURITY_SCHEMES = [
|
|
6
7
|
{ type: "noauth" },
|
|
7
8
|
{
|
|
@@ -813,7 +814,7 @@ export async function handleJsonRpcMcpRequest(engine, ctx, rpc) {
|
|
|
813
814
|
instructions: MUXO_MCP_SERVER_INSTRUCTIONS,
|
|
814
815
|
serverInfo: {
|
|
815
816
|
name: "muxo-mcp-server",
|
|
816
|
-
version:
|
|
817
|
+
version: MUXO_VERSION,
|
|
817
818
|
},
|
|
818
819
|
capabilities: {
|
|
819
820
|
tools: { listChanged: false },
|
package/dist/policy.d.ts
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { GovernancePolicy } from "./types.js";
|
|
2
|
+
export declare class PolicyValidationError extends Error {
|
|
3
|
+
}
|
|
4
|
+
/**
|
|
5
|
+
* Validates a client-supplied policy patch. Kill-switch fields are rejected so
|
|
6
|
+
* that pausing and resuming always goes through /api/v1/governance/kill-switch,
|
|
7
|
+
* which records the trust-score penalty and audit entry.
|
|
8
|
+
*/
|
|
9
|
+
export declare function sanitizePolicyPatch(body: unknown): Partial<GovernancePolicy>;
|
package/dist/policy.js
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
const RISK_LEVELS = [
|
|
2
|
+
"read",
|
|
3
|
+
"write",
|
|
4
|
+
"admin",
|
|
5
|
+
"financial",
|
|
6
|
+
"provisioning",
|
|
7
|
+
"destructive",
|
|
8
|
+
];
|
|
9
|
+
export class PolicyValidationError extends Error {
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Validates a client-supplied policy patch. Kill-switch fields are rejected so
|
|
13
|
+
* that pausing and resuming always goes through /api/v1/governance/kill-switch,
|
|
14
|
+
* which records the trust-score penalty and audit entry.
|
|
15
|
+
*/
|
|
16
|
+
export function sanitizePolicyPatch(body) {
|
|
17
|
+
if (!body || typeof body !== "object" || Array.isArray(body)) {
|
|
18
|
+
throw new PolicyValidationError("Policy update must be a JSON object");
|
|
19
|
+
}
|
|
20
|
+
const input = body;
|
|
21
|
+
if ("killSwitchActive" in input || "killSwitchReason" in input) {
|
|
22
|
+
throw new PolicyValidationError("Use POST /api/v1/governance/kill-switch to pause or resume agents");
|
|
23
|
+
}
|
|
24
|
+
const patch = {};
|
|
25
|
+
if (input.mode !== undefined) {
|
|
26
|
+
if (input.mode !== "monitor" && input.mode !== "enforce") {
|
|
27
|
+
throw new PolicyValidationError('mode must be "monitor" or "enforce"');
|
|
28
|
+
}
|
|
29
|
+
patch.mode = input.mode;
|
|
30
|
+
}
|
|
31
|
+
if (input.requireApprovalFor !== undefined) {
|
|
32
|
+
if (!Array.isArray(input.requireApprovalFor) ||
|
|
33
|
+
!input.requireApprovalFor.every((r) => RISK_LEVELS.includes(r))) {
|
|
34
|
+
throw new PolicyValidationError(`requireApprovalFor must be a list of: ${RISK_LEVELS.join(", ")}`);
|
|
35
|
+
}
|
|
36
|
+
patch.requireApprovalFor = [...new Set(input.requireApprovalFor)];
|
|
37
|
+
}
|
|
38
|
+
if (input.executionRing !== undefined) {
|
|
39
|
+
const ring = Number(input.executionRing);
|
|
40
|
+
if (![0, 1, 2, 3].includes(ring)) {
|
|
41
|
+
throw new PolicyValidationError("executionRing must be 0, 1, 2, or 3");
|
|
42
|
+
}
|
|
43
|
+
patch.executionRing = ring;
|
|
44
|
+
}
|
|
45
|
+
if (input.maxCreditsPerRun !== undefined) {
|
|
46
|
+
const max = Number(input.maxCreditsPerRun);
|
|
47
|
+
if (!Number.isFinite(max) || max < 0) {
|
|
48
|
+
throw new PolicyValidationError("maxCreditsPerRun must be a non-negative number");
|
|
49
|
+
}
|
|
50
|
+
patch.maxCreditsPerRun = max;
|
|
51
|
+
}
|
|
52
|
+
for (const key of ["allowInstantWallet", "allowProvisioning", "blockDestructiveSql"]) {
|
|
53
|
+
if (input[key] !== undefined) {
|
|
54
|
+
if (typeof input[key] !== "boolean") {
|
|
55
|
+
throw new PolicyValidationError(`${key} must be true or false`);
|
|
56
|
+
}
|
|
57
|
+
patch[key] = input[key];
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
if (input.blockedToolSlugs !== undefined) {
|
|
61
|
+
if (!Array.isArray(input.blockedToolSlugs) ||
|
|
62
|
+
!input.blockedToolSlugs.every((s) => typeof s === "string" && s.trim())) {
|
|
63
|
+
throw new PolicyValidationError("blockedToolSlugs must be a list of tool slugs");
|
|
64
|
+
}
|
|
65
|
+
patch.blockedToolSlugs = [
|
|
66
|
+
...new Set(input.blockedToolSlugs.map((s) => s.trim())),
|
|
67
|
+
];
|
|
68
|
+
}
|
|
69
|
+
if (Object.keys(patch).length === 0) {
|
|
70
|
+
throw new PolicyValidationError("No supported policy fields in request");
|
|
71
|
+
}
|
|
72
|
+
return patch;
|
|
73
|
+
}
|
|
@@ -11,5 +11,8 @@ export declare class ComposioInstantAdapter {
|
|
|
11
11
|
tool: MuxoTool;
|
|
12
12
|
input: Record<string, unknown>;
|
|
13
13
|
composioApiKey?: string | null;
|
|
14
|
+
exaApiKey?: string | null;
|
|
15
|
+
firecrawlApiKey?: string | null;
|
|
16
|
+
masterWalletDepleted?: boolean;
|
|
14
17
|
}): Promise<Record<string, unknown>>;
|
|
15
18
|
}
|