@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/server.js
CHANGED
|
@@ -6,7 +6,9 @@ import { getConfig, ROOT_DIR } from "./config.js";
|
|
|
6
6
|
import { MuxoEngine } from "./engine.js";
|
|
7
7
|
import { getMuxoMcpSkills, handleJsonRpcMcpRequest, MUXO_MCP_SERVER_INSTRUCTIONS, MUXO_MCP_TOOLS, } from "./mcp.js";
|
|
8
8
|
import { MuxoStore } from "./store.js";
|
|
9
|
-
import {
|
|
9
|
+
import { sanitizePolicyPatch } from "./policy.js";
|
|
10
|
+
import { MUXO_VERSION } from "./version.js";
|
|
11
|
+
import { isConsolePath, renderConsoleHtml, renderLandingHtml } from "./ui/console-html.js";
|
|
10
12
|
function renderSkillMarkdown(baseUrl) {
|
|
11
13
|
return `---
|
|
12
14
|
name: muxo
|
|
@@ -170,7 +172,7 @@ export function createMuxoServer(customConfig) {
|
|
|
170
172
|
ok: true,
|
|
171
173
|
status: "ready",
|
|
172
174
|
service: "muxo-platform",
|
|
173
|
-
version:
|
|
175
|
+
version: MUXO_VERSION,
|
|
174
176
|
environment: "production",
|
|
175
177
|
live_execution: true,
|
|
176
178
|
customer_billing: true,
|
|
@@ -464,7 +466,7 @@ export function createMuxoServer(customConfig) {
|
|
|
464
466
|
openapi: "3.1.0",
|
|
465
467
|
info: {
|
|
466
468
|
title: "Muxo Unified Agent Execution, Infrastructure, Memory & Governance API",
|
|
467
|
-
version:
|
|
469
|
+
version: MUXO_VERSION,
|
|
468
470
|
description: "One governed boundary over Connected Apps (Composio SDK), Instant Tools (Composio Instant), Cloud Infrastructure (Stripe Projects), Supermemory v5 Brain, and Microsoft Agent Governance Toolkit.",
|
|
469
471
|
},
|
|
470
472
|
servers: [{ url: config.baseUrl }],
|
|
@@ -634,12 +636,20 @@ Users purchase Muxo Credits (\`POST /api/v1/billing/topup\` or \`muxo billing to
|
|
|
634
636
|
});
|
|
635
637
|
return;
|
|
636
638
|
}
|
|
637
|
-
// Web Console UI (app.muxo.ai)
|
|
638
|
-
if ((pathname
|
|
639
|
+
// Web Console UI (app.muxo.ai) & SPA deep-links
|
|
640
|
+
if (isConsolePath(pathname) && req.method === "GET") {
|
|
639
641
|
res.writeHead(200, { "Content-Type": "text/html; charset=utf-8" });
|
|
640
642
|
res.end(renderConsoleHtml());
|
|
641
643
|
return;
|
|
642
644
|
}
|
|
645
|
+
if (pathname === "/downloads/muxo-cli.zip" && req.method === "GET") {
|
|
646
|
+
res.writeHead(302, {
|
|
647
|
+
Location: "https://muxo.ai/plugins/muxo-chatgpt-plugin.zip",
|
|
648
|
+
"Cache-Control": "no-store",
|
|
649
|
+
});
|
|
650
|
+
res.end();
|
|
651
|
+
return;
|
|
652
|
+
}
|
|
643
653
|
// Built-in Interactive Landing & Provider Canvas (muxo.ai)
|
|
644
654
|
if (pathname === "/landing" && req.method === "GET") {
|
|
645
655
|
res.writeHead(200, { "Content-Type": "text/html; charset=utf-8" });
|
|
@@ -753,8 +763,11 @@ Users purchase Muxo Credits (\`POST /api/v1/billing/topup\` or \`muxo billing to
|
|
|
753
763
|
</html>`);
|
|
754
764
|
return;
|
|
755
765
|
}
|
|
756
|
-
// Autonomous Agent 2-Call Signup
|
|
757
|
-
if (pathname === "/api/v1/agents/signup"
|
|
766
|
+
// Autonomous Agent 2-Call Signup — Public
|
|
767
|
+
if ((pathname === "/api/v1/agents/signup" ||
|
|
768
|
+
pathname === "/api/v1/auth/signup" ||
|
|
769
|
+
pathname === "/api/signup") &&
|
|
770
|
+
req.method === "POST") {
|
|
758
771
|
const body = JSON.parse((await readBody(req)) || "{}");
|
|
759
772
|
const created = store.createAutonomousAgentSignup({
|
|
760
773
|
agentName: body.agentName ? String(body.agentName) : undefined,
|
|
@@ -805,7 +818,7 @@ Users purchase Muxo Credits (\`POST /api/v1/billing/topup\` or \`muxo billing to
|
|
|
805
818
|
protocolVersion: "2025-06-18",
|
|
806
819
|
serverInfo: {
|
|
807
820
|
name: "muxo-mcp-server",
|
|
808
|
-
version:
|
|
821
|
+
version: MUXO_VERSION,
|
|
809
822
|
},
|
|
810
823
|
instructions: MUXO_MCP_SERVER_INSTRUCTIONS,
|
|
811
824
|
toolsCount: MUXO_MCP_TOOLS.length,
|
|
@@ -845,6 +858,10 @@ Users purchase Muxo Credits (\`POST /api/v1/billing/topup\` or \`muxo billing to
|
|
|
845
858
|
return;
|
|
846
859
|
}
|
|
847
860
|
// Auth Endpoints
|
|
861
|
+
if (pathname === "/api/v1/auth/config" && req.method === "GET") {
|
|
862
|
+
sendJson(res, 200, { ok: true, provider: "password", clerk: null, signInUrl: "/login" });
|
|
863
|
+
return;
|
|
864
|
+
}
|
|
848
865
|
if (pathname === "/api/v1/auth/register" && req.method === "POST") {
|
|
849
866
|
const body = JSON.parse((await readBody(req)) || "{}");
|
|
850
867
|
const created = store.registerUser({
|
|
@@ -853,7 +870,16 @@ Users purchase Muxo Credits (\`POST /api/v1/billing/topup\` or \`muxo billing to
|
|
|
853
870
|
password: String(body.password || ""),
|
|
854
871
|
workspaceName: body.workspaceName ? String(body.workspaceName) : undefined,
|
|
855
872
|
});
|
|
856
|
-
|
|
873
|
+
const initialKey = store.createApiKey({
|
|
874
|
+
workspaceId: created.workspace.id,
|
|
875
|
+
name: "Default Live Key",
|
|
876
|
+
environment: "live",
|
|
877
|
+
});
|
|
878
|
+
sendJson(res, 201, {
|
|
879
|
+
ok: true,
|
|
880
|
+
...created,
|
|
881
|
+
apiKey: initialKey.secretKey,
|
|
882
|
+
});
|
|
857
883
|
return;
|
|
858
884
|
}
|
|
859
885
|
if (pathname === "/api/v1/auth/login" && req.method === "POST") {
|
|
@@ -917,11 +943,49 @@ Users purchase Muxo Credits (\`POST /api/v1/billing/topup\` or \`muxo billing to
|
|
|
917
943
|
}
|
|
918
944
|
// Microsoft Agent Governance Status & Audit Verification
|
|
919
945
|
if (pathname === "/api/v1/governance" && req.method === "GET") {
|
|
946
|
+
const ws = store.getWorkspace(ctx.workspace.id) || ctx.workspace;
|
|
947
|
+
const fullReport = engine.governance.getGovernanceStatus(ws);
|
|
920
948
|
sendJson(res, 200, {
|
|
921
949
|
ok: true,
|
|
922
|
-
governance:
|
|
923
|
-
|
|
950
|
+
governance: {
|
|
951
|
+
...engine.governance.getStatus(ws),
|
|
952
|
+
modules: fullReport.modules,
|
|
953
|
+
trustScore: fullReport.trustScore,
|
|
954
|
+
killSwitch: fullReport.killSwitch,
|
|
955
|
+
contextPoisoning: fullReport.contextPoisoning,
|
|
956
|
+
auditChain: fullReport.auditChain,
|
|
957
|
+
},
|
|
958
|
+
workspacePolicy: ws.policy,
|
|
959
|
+
});
|
|
960
|
+
return;
|
|
961
|
+
}
|
|
962
|
+
if (pathname === "/api/v1/governance/kill-switch" && req.method === "POST") {
|
|
963
|
+
const body = JSON.parse((await readBody(req)) || "{}");
|
|
964
|
+
const action = String(body.action || "quarantine").toLowerCase();
|
|
965
|
+
if (action === "resume" || body.active === false) {
|
|
966
|
+
const out = engine.resumeWorkspaceKillSwitch(ctx);
|
|
967
|
+
sendJson(res, 200, { ok: true, ...out });
|
|
968
|
+
return;
|
|
969
|
+
}
|
|
970
|
+
const out = await engine.activateWorkspaceKillSwitch(ctx, {
|
|
971
|
+
reason: String(body.reason || "Emergency kill-switch activated by workspace operator"),
|
|
972
|
+
action: action === "terminate" || action === "suspend"
|
|
973
|
+
? action
|
|
974
|
+
: "quarantine",
|
|
975
|
+
});
|
|
976
|
+
sendJson(res, 200, { ok: true, ...out });
|
|
977
|
+
return;
|
|
978
|
+
}
|
|
979
|
+
if (pathname === "/api/v1/governance/scan-context" && req.method === "POST") {
|
|
980
|
+
const body = JSON.parse((await readBody(req)) || "{}");
|
|
981
|
+
const scan = engine.governance.scanMemoryContent({
|
|
982
|
+
workspaceId: ctx.workspace.id,
|
|
983
|
+
sessionId: String(body.sessionId || "default"),
|
|
984
|
+
role: body.role || "user",
|
|
985
|
+
content: String(body.content || ""),
|
|
986
|
+
recordInDetector: Boolean(body.recordInDetector),
|
|
924
987
|
});
|
|
988
|
+
sendJson(res, 200, { ok: true, scan });
|
|
925
989
|
return;
|
|
926
990
|
}
|
|
927
991
|
// Supermemory v5 Workspace Brain Endpoints
|
|
@@ -933,6 +997,37 @@ Users purchase Muxo Credits (\`POST /api/v1/billing/topup\` or \`muxo billing to
|
|
|
933
997
|
sendJson(res, 200, { ok: true, ...overview });
|
|
934
998
|
return;
|
|
935
999
|
}
|
|
1000
|
+
if (pathname === "/api/v1/memory/facts" && req.method === "GET") {
|
|
1001
|
+
const query = url.searchParams.get("query") ||
|
|
1002
|
+
url.searchParams.get("q") ||
|
|
1003
|
+
undefined;
|
|
1004
|
+
const includeHistorical = url.searchParams.get("historical") !== "false";
|
|
1005
|
+
const facts = store.listTemporalFacts(ctx.workspace.id, {
|
|
1006
|
+
includeHistorical,
|
|
1007
|
+
subject: url.searchParams.get("subject") || undefined,
|
|
1008
|
+
predicate: url.searchParams.get("predicate") || undefined,
|
|
1009
|
+
query,
|
|
1010
|
+
limit: Number(url.searchParams.get("limit") || 50),
|
|
1011
|
+
});
|
|
1012
|
+
sendJson(res, 200, {
|
|
1013
|
+
ok: true,
|
|
1014
|
+
activeFacts: facts.filter((f) => f.validTo === null),
|
|
1015
|
+
historicalFacts: facts.filter((f) => f.validTo !== null),
|
|
1016
|
+
facts,
|
|
1017
|
+
});
|
|
1018
|
+
return;
|
|
1019
|
+
}
|
|
1020
|
+
if (pathname === "/api/v1/memory/forget" && req.method === "POST") {
|
|
1021
|
+
const body = JSON.parse((await readBody(req)) || "{}");
|
|
1022
|
+
const query = String(body.query || body.q || "").trim();
|
|
1023
|
+
if (!query) {
|
|
1024
|
+
sendJson(res, 400, { ok: false, error: "query is required to forget matching memories" });
|
|
1025
|
+
return;
|
|
1026
|
+
}
|
|
1027
|
+
const pruned = await engine.forgetWorkspaceMemoryMatching(ctx, query);
|
|
1028
|
+
sendJson(res, 200, { ok: true, ...pruned });
|
|
1029
|
+
return;
|
|
1030
|
+
}
|
|
936
1031
|
if (pathname === "/api/v1/memory" && req.method === "POST") {
|
|
937
1032
|
const body = JSON.parse((await readBody(req)) || "{}");
|
|
938
1033
|
const record = await engine.addWorkspaceMemory(ctx, {
|
|
@@ -940,6 +1035,9 @@ Users purchase Muxo Credits (\`POST /api/v1/billing/topup\` or \`muxo billing to
|
|
|
940
1035
|
content: String(body.content || ""),
|
|
941
1036
|
kind: body.kind || "fact",
|
|
942
1037
|
metadata: body.metadata || {},
|
|
1038
|
+
subject: body.subject ? String(body.subject) : undefined,
|
|
1039
|
+
predicate: body.predicate ? String(body.predicate) : undefined,
|
|
1040
|
+
object: body.object ? String(body.object) : undefined,
|
|
943
1041
|
});
|
|
944
1042
|
sendJson(res, 201, { ok: true, memory: record });
|
|
945
1043
|
return;
|
|
@@ -961,6 +1059,15 @@ Users purchase Muxo Credits (\`POST /api/v1/billing/topup\` or \`muxo billing to
|
|
|
961
1059
|
sendJson(res, 201, { ok: true, ...created });
|
|
962
1060
|
return;
|
|
963
1061
|
}
|
|
1062
|
+
if (pathname.startsWith("/api/v1/api-keys/") && req.method === "DELETE") {
|
|
1063
|
+
const keyId = decodeURIComponent(pathname.slice("/api/v1/api-keys/".length));
|
|
1064
|
+
if (!store.revokeApiKey(ctx.workspace.id, keyId)) {
|
|
1065
|
+
sendJson(res, 404, { ok: false, error: "API key not found" });
|
|
1066
|
+
return;
|
|
1067
|
+
}
|
|
1068
|
+
sendJson(res, 200, { ok: true, revoked: keyId });
|
|
1069
|
+
return;
|
|
1070
|
+
}
|
|
964
1071
|
// Profile & Organization (v1 and api/v1)
|
|
965
1072
|
if ((pathname === "/api/v1/profile" || pathname === "/v1/profile") && req.method === "GET") {
|
|
966
1073
|
sendJson(res, 200, { ok: true, ...engine.getProfile(ctx) });
|
|
@@ -1060,7 +1167,7 @@ Users purchase Muxo Credits (\`POST /api/v1/billing/topup\` or \`muxo billing to
|
|
|
1060
1167
|
// Governance Policy
|
|
1061
1168
|
if (pathname === "/api/v1/policy" && req.method === "POST") {
|
|
1062
1169
|
const body = JSON.parse((await readBody(req)) || "{}");
|
|
1063
|
-
const updated = store.updateWorkspacePolicy(ctx.workspace.id, body);
|
|
1170
|
+
const updated = store.updateWorkspacePolicy(ctx.workspace.id, sanitizePolicyPatch(body));
|
|
1064
1171
|
sendJson(res, 200, { ok: true, workspace: updated });
|
|
1065
1172
|
return;
|
|
1066
1173
|
}
|
|
@@ -1074,10 +1181,17 @@ Users purchase Muxo Credits (\`POST /api/v1/billing/topup\` or \`muxo billing to
|
|
|
1074
1181
|
}
|
|
1075
1182
|
if (pathname === "/api/v1/plans" && req.method === "POST") {
|
|
1076
1183
|
const body = JSON.parse((await readBody(req)) || "{}");
|
|
1184
|
+
const rawFunding = body.fundingMode || body.funding_mode;
|
|
1185
|
+
const fundingMode = rawFunding === "byok" || rawFunding === "customer_funded"
|
|
1186
|
+
? "byok"
|
|
1187
|
+
: rawFunding === "muxo_funded"
|
|
1188
|
+
? "muxo_funded"
|
|
1189
|
+
: undefined;
|
|
1077
1190
|
const planned = await engine.planAction(ctx, {
|
|
1078
1191
|
toolSlug: String(body.toolSlug || body.tool_slug || ""),
|
|
1079
1192
|
input: body.input || {},
|
|
1080
1193
|
reason: body.reason ? String(body.reason) : undefined,
|
|
1194
|
+
fundingMode,
|
|
1081
1195
|
});
|
|
1082
1196
|
sendJson(res, 201, { ok: true, ...planned });
|
|
1083
1197
|
return;
|
|
@@ -1101,6 +1215,13 @@ Users purchase Muxo Credits (\`POST /api/v1/billing/topup\` or \`muxo billing to
|
|
|
1101
1215
|
});
|
|
1102
1216
|
return;
|
|
1103
1217
|
}
|
|
1218
|
+
const planGetMatch = pathname.match(/^\/api\/v1\/plans\/([^/]+)$/);
|
|
1219
|
+
if (planGetMatch && req.method === "GET") {
|
|
1220
|
+
const planId = decodeURIComponent(planGetMatch[1]);
|
|
1221
|
+
const plan = engine.getPlan(ctx, planId);
|
|
1222
|
+
sendJson(res, 200, { ok: true, plan });
|
|
1223
|
+
return;
|
|
1224
|
+
}
|
|
1104
1225
|
// Runs & Receipts
|
|
1105
1226
|
if (pathname === "/api/v1/runs" && req.method === "GET") {
|
|
1106
1227
|
sendJson(res, 200, {
|
|
@@ -1109,6 +1230,21 @@ Users purchase Muxo Credits (\`POST /api/v1/billing/topup\` or \`muxo billing to
|
|
|
1109
1230
|
});
|
|
1110
1231
|
return;
|
|
1111
1232
|
}
|
|
1233
|
+
const runCancelMatch = pathname.match(/^\/api\/v1\/runs\/([^/]+)\/cancel$/);
|
|
1234
|
+
if (runCancelMatch && req.method === "POST") {
|
|
1235
|
+
const runId = decodeURIComponent(runCancelMatch[1]);
|
|
1236
|
+
const body = JSON.parse((await readBody(req)) || "{}");
|
|
1237
|
+
const cancelled = engine.cancelRun(ctx, runId, body.reason ? String(body.reason) : undefined);
|
|
1238
|
+
sendJson(res, 200, { ok: true, ...cancelled });
|
|
1239
|
+
return;
|
|
1240
|
+
}
|
|
1241
|
+
const runGetMatch = pathname.match(/^\/api\/v1\/runs\/([^/]+)$/);
|
|
1242
|
+
if (runGetMatch && req.method === "GET") {
|
|
1243
|
+
const runId = decodeURIComponent(runGetMatch[1]);
|
|
1244
|
+
const run = engine.getRun(ctx, runId);
|
|
1245
|
+
sendJson(res, 200, { ok: true, run });
|
|
1246
|
+
return;
|
|
1247
|
+
}
|
|
1112
1248
|
if (pathname.startsWith("/api/v1/receipts/") && req.method === "GET") {
|
|
1113
1249
|
const receiptId = decodeURIComponent(pathname.slice("/api/v1/receipts/".length));
|
|
1114
1250
|
const verified = engine.getReceipt(ctx, receiptId);
|
|
@@ -1158,7 +1294,13 @@ Users purchase Muxo Credits (\`POST /api/v1/billing/topup\` or \`muxo billing to
|
|
|
1158
1294
|
if ((pathname === "/api/v1/do" || pathname === "/v1/do") &&
|
|
1159
1295
|
req.method === "POST") {
|
|
1160
1296
|
const body = JSON.parse((await readBody(req)) || "{}");
|
|
1161
|
-
const prompt = String(body.prompt ||
|
|
1297
|
+
const prompt = String(body.prompt ||
|
|
1298
|
+
body.instruction ||
|
|
1299
|
+
body.query ||
|
|
1300
|
+
body.command ||
|
|
1301
|
+
body.toolSlug ||
|
|
1302
|
+
body.tool ||
|
|
1303
|
+
"").trim();
|
|
1162
1304
|
if (!prompt) {
|
|
1163
1305
|
sendJson(res, 400, {
|
|
1164
1306
|
ok: false,
|
|
@@ -1166,19 +1308,37 @@ Users purchase Muxo Credits (\`POST /api/v1/billing/topup\` or \`muxo billing to
|
|
|
1166
1308
|
});
|
|
1167
1309
|
return;
|
|
1168
1310
|
}
|
|
1311
|
+
const dryRun = body.dryRun === true ||
|
|
1312
|
+
body.dry_run === true ||
|
|
1313
|
+
body.planOnly === true ||
|
|
1314
|
+
body.autoExecute === false ||
|
|
1315
|
+
body.auto_execute === false;
|
|
1316
|
+
const autoApprove = body.autoApprove !== false &&
|
|
1317
|
+
body.auto_approve !== false &&
|
|
1318
|
+
body.approveRisky !== false &&
|
|
1319
|
+
body.approve_risky !== false;
|
|
1320
|
+
const rawFunding = body.fundingMode || body.funding_mode;
|
|
1321
|
+
const fundingMode = rawFunding === "byok" || rawFunding === "customer_funded"
|
|
1322
|
+
? "byok"
|
|
1323
|
+
: rawFunding === "muxo_funded"
|
|
1324
|
+
? "muxo_funded"
|
|
1325
|
+
: undefined;
|
|
1169
1326
|
const result = await engine.doNaturalLanguage(ctx, {
|
|
1170
1327
|
prompt,
|
|
1171
1328
|
input: body.input && typeof body.input === "object"
|
|
1172
1329
|
? body.input
|
|
1173
1330
|
: undefined,
|
|
1174
|
-
autoApprove
|
|
1175
|
-
dryRun
|
|
1331
|
+
autoApprove,
|
|
1332
|
+
dryRun,
|
|
1333
|
+
planOnly: dryRun,
|
|
1334
|
+
fundingMode,
|
|
1176
1335
|
});
|
|
1177
1336
|
sendJson(res, 200, result);
|
|
1178
1337
|
return;
|
|
1179
1338
|
}
|
|
1180
1339
|
// Live Stripe Billing, Credit Top-Up & Supplier Settlement Ledger
|
|
1181
|
-
if (pathname === "/api/v1/billing/status"
|
|
1340
|
+
if ((pathname === "/api/v1/billing/status" || pathname === "/api/v1/billing") &&
|
|
1341
|
+
req.method === "GET") {
|
|
1182
1342
|
const ws = store.getWorkspace(ctx.workspace.id);
|
|
1183
1343
|
const settlementSummary = store.getSupplierSettlementSummary(ctx.workspace.id);
|
|
1184
1344
|
const byokKeys = store.listByokKeys(ctx.workspace.id);
|
package/dist/store.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { DatabaseSync } from "node:sqlite";
|
|
2
|
-
import type { ActionPlan, ApiKeyRecord, ByokKeyRecord, ConnectionRecord, ExecutionReceipt, ExecutionRun, GovernanceDecisionRecord, GovernancePolicy, LedgerEntry, MemoryContextSummary, ProviderLane, ProvisionedResource, RiskLevel, SupplierSettlement, SupplierSettlementSummary, User, Workspace, WorkspaceMemoryRecord } from "./types.js";
|
|
2
|
+
import type { ActionPlan, ApiKeyRecord, ByokKeyRecord, ConnectionRecord, ExecutionReceipt, ExecutionRun, GovernanceDecisionRecord, GovernancePolicy, LedgerEntry, MemoryContextSummary, ProviderLane, ProvisionedResource, RiskLevel, SupplierSettlement, SupplierSettlementSummary, TemporalGraphFact, User, Workspace, WorkspaceMemoryRecord } from "./types.js";
|
|
3
3
|
export declare const BYOK_PROVIDER_CATALOG: Record<string, {
|
|
4
4
|
category: "llm" | "supplier";
|
|
5
5
|
envVarName: string;
|
|
@@ -173,6 +173,30 @@ export declare class MuxoStore {
|
|
|
173
173
|
}): WorkspaceMemoryRecord;
|
|
174
174
|
listMemoryRecords(workspaceId: string, limit?: number): WorkspaceMemoryRecord[];
|
|
175
175
|
deleteMemoryRecord(workspaceId: string, idOrDocId: string): WorkspaceMemoryRecord | null;
|
|
176
|
+
upsertTemporalFact(params: {
|
|
177
|
+
workspaceId: string;
|
|
178
|
+
subject: string;
|
|
179
|
+
predicate: string;
|
|
180
|
+
object: string;
|
|
181
|
+
summary: string;
|
|
182
|
+
confidence?: number;
|
|
183
|
+
sourceKind?: TemporalGraphFact["sourceKind"];
|
|
184
|
+
sourceReferenceId?: string | null;
|
|
185
|
+
metadata?: Record<string, unknown>;
|
|
186
|
+
supersedeExisting?: boolean;
|
|
187
|
+
}): TemporalGraphFact;
|
|
188
|
+
listTemporalFacts(workspaceId: string, opts?: {
|
|
189
|
+
includeHistorical?: boolean;
|
|
190
|
+
subject?: string;
|
|
191
|
+
predicate?: string;
|
|
192
|
+
query?: string;
|
|
193
|
+
limit?: number;
|
|
194
|
+
}): TemporalGraphFact[];
|
|
195
|
+
forgetMatchingMemoryRecords(workspaceId: string, query: string): {
|
|
196
|
+
deletedMemories: WorkspaceMemoryRecord[];
|
|
197
|
+
invalidatedFacts: TemporalGraphFact[];
|
|
198
|
+
};
|
|
199
|
+
private mapTemporalFact;
|
|
176
200
|
createAutonomousAgentSignup(params?: {
|
|
177
201
|
agentName?: string;
|
|
178
202
|
harness?: string;
|
package/dist/store.js
CHANGED
|
@@ -186,6 +186,23 @@ export class MuxoStore {
|
|
|
186
186
|
created_at TEXT NOT NULL
|
|
187
187
|
);
|
|
188
188
|
|
|
189
|
+
CREATE TABLE IF NOT EXISTS temporal_facts (
|
|
190
|
+
id TEXT PRIMARY KEY,
|
|
191
|
+
workspace_id TEXT NOT NULL,
|
|
192
|
+
subject TEXT NOT NULL,
|
|
193
|
+
predicate TEXT NOT NULL,
|
|
194
|
+
object TEXT NOT NULL,
|
|
195
|
+
summary TEXT NOT NULL,
|
|
196
|
+
confidence REAL NOT NULL DEFAULT 0.95,
|
|
197
|
+
valid_from TEXT NOT NULL,
|
|
198
|
+
valid_to TEXT,
|
|
199
|
+
superseded_by_id TEXT,
|
|
200
|
+
source_kind TEXT NOT NULL DEFAULT 'fact',
|
|
201
|
+
source_reference_id TEXT,
|
|
202
|
+
metadata_json TEXT NOT NULL DEFAULT '{}',
|
|
203
|
+
created_at TEXT NOT NULL
|
|
204
|
+
);
|
|
205
|
+
|
|
189
206
|
CREATE TABLE IF NOT EXISTS agent_claims (
|
|
190
207
|
claim_slug TEXT PRIMARY KEY,
|
|
191
208
|
workspace_id TEXT NOT NULL,
|
|
@@ -516,7 +533,23 @@ export class MuxoStore {
|
|
|
516
533
|
metadata_json = excluded.metadata_json,
|
|
517
534
|
updated_at = excluded.updated_at`)
|
|
518
535
|
.run(id, params.workspaceId, params.lane, params.providerSlug, params.providerName, params.status, params.externalAccountId ?? null, params.redirectUrl ?? null, JSON.stringify(params.metadata || {}), now, now);
|
|
519
|
-
|
|
536
|
+
const connRecord = this.getConnection(id);
|
|
537
|
+
this.upsertTemporalFact({
|
|
538
|
+
workspaceId: params.workspaceId,
|
|
539
|
+
subject: `app:${params.providerSlug}`,
|
|
540
|
+
predicate: "CONNECTION_STATUS",
|
|
541
|
+
object: `${params.lane}:${params.status}`,
|
|
542
|
+
summary: `App ${params.providerName} (${params.providerSlug}) connection on ${params.lane} is ${params.status}`,
|
|
543
|
+
confidence: 1.0,
|
|
544
|
+
sourceKind: "resource_topology",
|
|
545
|
+
sourceReferenceId: connRecord.id,
|
|
546
|
+
metadata: {
|
|
547
|
+
lane: params.lane,
|
|
548
|
+
providerSlug: params.providerSlug,
|
|
549
|
+
status: params.status,
|
|
550
|
+
},
|
|
551
|
+
});
|
|
552
|
+
return connRecord;
|
|
520
553
|
}
|
|
521
554
|
getConnection(id) {
|
|
522
555
|
const row = this.db
|
|
@@ -566,7 +599,25 @@ export class MuxoStore {
|
|
|
566
599
|
metadata_json = excluded.metadata_json,
|
|
567
600
|
updated_at = excluded.updated_at`)
|
|
568
601
|
.run(id, params.workspaceId, params.resourceName, params.providerSlug, params.providerName, params.serviceSlug, params.planSlug ?? null, params.status, JSON.stringify(envVarKeys), encryptedHex, params.externalResourceId ?? null, JSON.stringify(params.metadata || {}), now, now);
|
|
569
|
-
|
|
602
|
+
const resRecord = this.getResource(params.workspaceId, params.resourceName);
|
|
603
|
+
this.upsertTemporalFact({
|
|
604
|
+
workspaceId: params.workspaceId,
|
|
605
|
+
subject: `resource:${params.resourceName}`,
|
|
606
|
+
predicate: "PROVISIONED_ON",
|
|
607
|
+
object: `${params.serviceSlug}:${params.status}`,
|
|
608
|
+
summary: `Resource "${params.resourceName}" provisioned on ${params.serviceSlug} (${params.providerName}) with status ${params.status} [${resRecord.envVarKeys.join(", ") || "no env keys"}]`,
|
|
609
|
+
confidence: 1.0,
|
|
610
|
+
sourceKind: "resource_topology",
|
|
611
|
+
sourceReferenceId: resRecord.id,
|
|
612
|
+
metadata: {
|
|
613
|
+
providerSlug: params.providerSlug,
|
|
614
|
+
serviceSlug: params.serviceSlug,
|
|
615
|
+
planSlug: params.planSlug ?? null,
|
|
616
|
+
status: params.status,
|
|
617
|
+
envVarKeys: resRecord.envVarKeys,
|
|
618
|
+
},
|
|
619
|
+
});
|
|
620
|
+
return resRecord;
|
|
570
621
|
}
|
|
571
622
|
getResource(workspaceId, resourceNameOrId) {
|
|
572
623
|
const row = this.db
|
|
@@ -793,7 +844,8 @@ export class MuxoStore {
|
|
|
793
844
|
SET monthly_actions_used = ?, credits_balance = ?, updated_at = ?
|
|
794
845
|
WHERE id = ?`)
|
|
795
846
|
.run(newActionsUsed, newCreditsBalance, now, params.workspaceId);
|
|
796
|
-
const byokUsed =
|
|
847
|
+
const byokUsed = params.creditsMetered === 0 &&
|
|
848
|
+
this.hasByokForLane(params.workspaceId, run.lane, run.toolSlug);
|
|
797
849
|
const settlement = this.computeSupplierSettlement(run.lane, run.toolSlug, params.creditsMetered, byokUsed ? "settled_by_customer_byok" : "settled_by_muxo_master_wallet", params.workspaceId);
|
|
798
850
|
this.addLedgerEntry({
|
|
799
851
|
workspaceId: params.workspaceId,
|
|
@@ -1138,6 +1190,17 @@ export class MuxoStore {
|
|
|
1138
1190
|
totalSupplierWholesalePaidCents,
|
|
1139
1191
|
totalMuxoNetMarginCents,
|
|
1140
1192
|
bySupplier,
|
|
1193
|
+
masterWalletProtection: {
|
|
1194
|
+
status: process.env.MUXO_MASTER_WALLET_DEPLETED === "true"
|
|
1195
|
+
? "failover_active"
|
|
1196
|
+
: "healthy",
|
|
1197
|
+
zeroChargeOnFailure: true,
|
|
1198
|
+
instantFailoverMode: "zero_cost_native_edge",
|
|
1199
|
+
paidProvisioningPolicy: "muxo_master_wallet_or_customer_stripe_byok",
|
|
1200
|
+
retailToWholesaleCoverageRatio: totalSupplierWholesalePaidCents > 0
|
|
1201
|
+
? Math.round((totalUserRetailSpendCents / totalSupplierWholesalePaidCents) * 100) / 100
|
|
1202
|
+
: 1.67,
|
|
1203
|
+
},
|
|
1141
1204
|
};
|
|
1142
1205
|
}
|
|
1143
1206
|
listLedgerEntries(workspaceId, limit = 50) {
|
|
@@ -1220,6 +1283,15 @@ export class MuxoStore {
|
|
|
1220
1283
|
this.db
|
|
1221
1284
|
.prepare("DELETE FROM memories WHERE id = ? AND workspace_id = ?")
|
|
1222
1285
|
.run(String(row.id), workspaceId);
|
|
1286
|
+
// Also mark any temporal facts sourced from this memory record as invalidated (valid_to = now)
|
|
1287
|
+
const now = new Date().toISOString();
|
|
1288
|
+
this.db
|
|
1289
|
+
.prepare(`UPDATE temporal_facts
|
|
1290
|
+
SET valid_to = ?
|
|
1291
|
+
WHERE workspace_id = ?
|
|
1292
|
+
AND valid_to IS NULL
|
|
1293
|
+
AND (source_reference_id = ? OR source_reference_id = ? OR id = ?)`)
|
|
1294
|
+
.run(now, workspaceId, String(row.id), String(row.document_id), idOrDocId);
|
|
1223
1295
|
return {
|
|
1224
1296
|
id: String(row.id),
|
|
1225
1297
|
workspaceId: String(row.workspace_id),
|
|
@@ -1232,6 +1304,166 @@ export class MuxoStore {
|
|
|
1232
1304
|
createdAt: String(row.created_at),
|
|
1233
1305
|
};
|
|
1234
1306
|
}
|
|
1307
|
+
// --- Bi-Temporal Resource & Fact Lineage (Zero-Dependency Graphiti Alternative) ---
|
|
1308
|
+
upsertTemporalFact(params) {
|
|
1309
|
+
const now = new Date().toISOString();
|
|
1310
|
+
const subject = params.subject.trim();
|
|
1311
|
+
const predicate = params.predicate.trim().toUpperCase().replace(/[^A-Z0-9_]/g, "_");
|
|
1312
|
+
const object = params.object.trim();
|
|
1313
|
+
const confidence = params.confidence !== undefined ? Number(params.confidence) : 0.95;
|
|
1314
|
+
const sourceKind = params.sourceKind || "fact";
|
|
1315
|
+
// Check if an active fact already exists for (workspace_id, subject, predicate)
|
|
1316
|
+
const activeRow = this.db
|
|
1317
|
+
.prepare(`SELECT * FROM temporal_facts
|
|
1318
|
+
WHERE workspace_id = ? AND subject = ? AND predicate = ? AND valid_to IS NULL
|
|
1319
|
+
ORDER BY created_at DESC LIMIT 1`)
|
|
1320
|
+
.get(params.workspaceId, subject, predicate);
|
|
1321
|
+
if (activeRow && String(activeRow.object) === object) {
|
|
1322
|
+
// Same object is still valid — update summary/confidence/metadata in place
|
|
1323
|
+
const existingId = String(activeRow.id);
|
|
1324
|
+
this.db
|
|
1325
|
+
.prepare(`UPDATE temporal_facts
|
|
1326
|
+
SET summary = ?, confidence = ?, metadata_json = ?, source_reference_id = COALESCE(?, source_reference_id)
|
|
1327
|
+
WHERE id = ?`)
|
|
1328
|
+
.run(params.summary, confidence, JSON.stringify(params.metadata || {}), params.sourceReferenceId ?? null, existingId);
|
|
1329
|
+
return this.mapTemporalFact({
|
|
1330
|
+
...activeRow,
|
|
1331
|
+
summary: params.summary,
|
|
1332
|
+
confidence,
|
|
1333
|
+
metadata_json: JSON.stringify(params.metadata || {}),
|
|
1334
|
+
source_reference_id: params.sourceReferenceId ?? activeRow.source_reference_id,
|
|
1335
|
+
});
|
|
1336
|
+
}
|
|
1337
|
+
const newId = `tf_${crypto.randomBytes(8).toString("hex")}`;
|
|
1338
|
+
if (activeRow && params.supersedeExisting !== false) {
|
|
1339
|
+
this.db
|
|
1340
|
+
.prepare(`UPDATE temporal_facts
|
|
1341
|
+
SET valid_to = ?, superseded_by_id = ?
|
|
1342
|
+
WHERE id = ? AND workspace_id = ?`)
|
|
1343
|
+
.run(now, newId, String(activeRow.id), params.workspaceId);
|
|
1344
|
+
}
|
|
1345
|
+
this.db
|
|
1346
|
+
.prepare(`INSERT INTO temporal_facts (
|
|
1347
|
+
id, workspace_id, subject, predicate, object, summary, confidence,
|
|
1348
|
+
valid_from, valid_to, superseded_by_id, source_kind, source_reference_id,
|
|
1349
|
+
metadata_json, created_at
|
|
1350
|
+
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, NULL, NULL, ?, ?, ?, ?)`)
|
|
1351
|
+
.run(newId, params.workspaceId, subject, predicate, object, params.summary, confidence, now, sourceKind, params.sourceReferenceId ?? null, JSON.stringify(params.metadata || {}), now);
|
|
1352
|
+
return {
|
|
1353
|
+
id: newId,
|
|
1354
|
+
workspaceId: params.workspaceId,
|
|
1355
|
+
subject,
|
|
1356
|
+
predicate,
|
|
1357
|
+
object,
|
|
1358
|
+
summary: params.summary,
|
|
1359
|
+
confidence,
|
|
1360
|
+
validFrom: now,
|
|
1361
|
+
validTo: null,
|
|
1362
|
+
supersededById: null,
|
|
1363
|
+
sourceKind,
|
|
1364
|
+
sourceReferenceId: params.sourceReferenceId ?? null,
|
|
1365
|
+
metadata: params.metadata || {},
|
|
1366
|
+
createdAt: now,
|
|
1367
|
+
};
|
|
1368
|
+
}
|
|
1369
|
+
listTemporalFacts(workspaceId, opts) {
|
|
1370
|
+
const limit = Math.min(200, Math.max(1, Number(opts?.limit || 50)));
|
|
1371
|
+
const includeHistorical = Boolean(opts?.includeHistorical);
|
|
1372
|
+
const rows = this.db
|
|
1373
|
+
.prepare(includeHistorical
|
|
1374
|
+
? `SELECT * FROM temporal_facts WHERE workspace_id = ? ORDER BY created_at DESC LIMIT ?`
|
|
1375
|
+
: `SELECT * FROM temporal_facts WHERE workspace_id = ? AND valid_to IS NULL ORDER BY created_at DESC LIMIT ?`)
|
|
1376
|
+
.all(workspaceId, limit);
|
|
1377
|
+
let facts = rows.map((r) => this.mapTemporalFact(r));
|
|
1378
|
+
if (opts?.subject) {
|
|
1379
|
+
const subj = opts.subject.toLowerCase();
|
|
1380
|
+
facts = facts.filter((f) => f.subject.toLowerCase().includes(subj));
|
|
1381
|
+
}
|
|
1382
|
+
if (opts?.predicate) {
|
|
1383
|
+
const pred = opts.predicate.toUpperCase();
|
|
1384
|
+
facts = facts.filter((f) => f.predicate.toUpperCase().includes(pred));
|
|
1385
|
+
}
|
|
1386
|
+
if (opts?.query && opts.query.trim()) {
|
|
1387
|
+
const tokens = opts.query
|
|
1388
|
+
.toLowerCase()
|
|
1389
|
+
.split(/\s+/)
|
|
1390
|
+
.filter((t) => t.length >= 2);
|
|
1391
|
+
if (tokens.length > 0) {
|
|
1392
|
+
facts = facts.filter((f) => {
|
|
1393
|
+
const hay = `${f.subject} ${f.predicate} ${f.object} ${f.summary}`.toLowerCase();
|
|
1394
|
+
return tokens.some((tok) => hay.includes(tok));
|
|
1395
|
+
});
|
|
1396
|
+
}
|
|
1397
|
+
}
|
|
1398
|
+
return facts;
|
|
1399
|
+
}
|
|
1400
|
+
forgetMatchingMemoryRecords(workspaceId, query) {
|
|
1401
|
+
const trimmed = query.trim().toLowerCase();
|
|
1402
|
+
if (!trimmed) {
|
|
1403
|
+
return { deletedMemories: [], invalidatedFacts: [] };
|
|
1404
|
+
}
|
|
1405
|
+
const tokens = trimmed.split(/\s+/).filter((t) => t.length >= 2);
|
|
1406
|
+
const allMemories = this.listMemoryRecords(workspaceId, 200);
|
|
1407
|
+
const matchingMemories = allMemories.filter((m) => {
|
|
1408
|
+
const hay = `${m.title} ${m.content} ${m.kind}`.toLowerCase();
|
|
1409
|
+
return (hay.includes(trimmed) ||
|
|
1410
|
+
(tokens.length > 0 && tokens.every((tok) => hay.includes(tok))));
|
|
1411
|
+
});
|
|
1412
|
+
// Snapshot before deleting: deleteMemoryRecord retires sourced facts itself,
|
|
1413
|
+
// and those must still be reported as invalidated.
|
|
1414
|
+
const activeFacts = this.listTemporalFacts(workspaceId, {
|
|
1415
|
+
includeHistorical: false,
|
|
1416
|
+
limit: 200,
|
|
1417
|
+
});
|
|
1418
|
+
const deletedMemories = [];
|
|
1419
|
+
for (const mem of matchingMemories) {
|
|
1420
|
+
const deleted = this.deleteMemoryRecord(workspaceId, mem.id);
|
|
1421
|
+
if (deleted)
|
|
1422
|
+
deletedMemories.push(deleted);
|
|
1423
|
+
}
|
|
1424
|
+
const deletedSourceIds = new Set(deletedMemories.flatMap((m) => [m.id, m.documentId]));
|
|
1425
|
+
const matchingFacts = activeFacts.filter((f) => {
|
|
1426
|
+
const hay = `${f.subject} ${f.predicate} ${f.object} ${f.summary}`.toLowerCase();
|
|
1427
|
+
return (hay.includes(trimmed) ||
|
|
1428
|
+
(tokens.length > 0 && tokens.every((tok) => hay.includes(tok))) ||
|
|
1429
|
+
Boolean(f.sourceReferenceId && deletedSourceIds.has(f.sourceReferenceId)));
|
|
1430
|
+
});
|
|
1431
|
+
const now = new Date().toISOString();
|
|
1432
|
+
const invalidatedFacts = [];
|
|
1433
|
+
for (const fact of matchingFacts) {
|
|
1434
|
+
this.db
|
|
1435
|
+
.prepare(`UPDATE temporal_facts SET valid_to = ? WHERE id = ? AND workspace_id = ?`)
|
|
1436
|
+
.run(now, fact.id, workspaceId);
|
|
1437
|
+
invalidatedFacts.push({
|
|
1438
|
+
...fact,
|
|
1439
|
+
validTo: now,
|
|
1440
|
+
});
|
|
1441
|
+
}
|
|
1442
|
+
return {
|
|
1443
|
+
deletedMemories,
|
|
1444
|
+
invalidatedFacts,
|
|
1445
|
+
};
|
|
1446
|
+
}
|
|
1447
|
+
mapTemporalFact(row) {
|
|
1448
|
+
return {
|
|
1449
|
+
id: String(row.id),
|
|
1450
|
+
workspaceId: String(row.workspace_id),
|
|
1451
|
+
subject: String(row.subject),
|
|
1452
|
+
predicate: String(row.predicate),
|
|
1453
|
+
object: String(row.object),
|
|
1454
|
+
summary: String(row.summary),
|
|
1455
|
+
confidence: Number(row.confidence ?? 0.95),
|
|
1456
|
+
validFrom: String(row.valid_from),
|
|
1457
|
+
validTo: row.valid_to ? String(row.valid_to) : null,
|
|
1458
|
+
supersededById: row.superseded_by_id ? String(row.superseded_by_id) : null,
|
|
1459
|
+
sourceKind: String(row.source_kind || "fact"),
|
|
1460
|
+
sourceReferenceId: row.source_reference_id
|
|
1461
|
+
? String(row.source_reference_id)
|
|
1462
|
+
: null,
|
|
1463
|
+
metadata: JSON.parse(String(row.metadata_json || "{}")),
|
|
1464
|
+
createdAt: String(row.created_at),
|
|
1465
|
+
};
|
|
1466
|
+
}
|
|
1235
1467
|
// --- Autonomous Agent Onboarding (agents.composio.dev pattern) ---
|
|
1236
1468
|
createAutonomousAgentSignup(params) {
|
|
1237
1469
|
const suffix = crypto.randomBytes(4).toString("hex");
|
|
@@ -1426,6 +1658,7 @@ export class MuxoStore {
|
|
|
1426
1658
|
input: JSON.parse(String(row.input_json || "{}")),
|
|
1427
1659
|
output: row.output_json ? JSON.parse(String(row.output_json)) : null,
|
|
1428
1660
|
error: row.error ? String(row.error) : null,
|
|
1661
|
+
errorMessage: row.error ? String(row.error) : null,
|
|
1429
1662
|
actionsMetered: Number(row.actions_metered),
|
|
1430
1663
|
creditsMetered: Number(row.credits_metered),
|
|
1431
1664
|
durationMs: row.duration_ms !== null ? Number(row.duration_ms) : null,
|