@muxoai/platform 1.4.1 → 1.4.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/.agents/plugins/marketplace.json +1 -1
- package/.claude-plugin/marketplace.json +2 -2
- package/README.md +1 -1
- package/dist/cli.js +6 -3
- package/dist/composio-catalog.d.ts +177 -1
- package/dist/composio-catalog.js +1427 -7
- package/dist/config.d.ts +6 -0
- package/dist/config.js +11 -1
- package/dist/engine.d.ts +18 -1
- package/dist/engine.js +259 -35
- package/dist/mcp-schema.d.ts +162 -1
- package/dist/mcp-schema.js +1523 -40
- package/dist/mcp.d.ts +2 -2
- package/dist/mcp.js +412 -23
- package/dist/policy.d.ts +108 -1
- package/dist/policy.js +406 -1
- package/dist/providers/composio-instant.js +38 -3
- package/dist/providers/composio-sdk.d.ts +59 -2
- package/dist/providers/composio-sdk.js +273 -59
- package/dist/providers/stripe-projects.d.ts +4 -0
- package/dist/providers/stripe-projects.js +548 -126
- package/dist/server.js +531 -61
- package/dist/store.js +2 -0
- package/dist/types.d.ts +15 -0
- package/dist/ui/console-html.d.ts +31 -1
- package/dist/ui/console-html.js +922 -368
- package/dist/ui/design-tokens.js +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +3 -2
- package/plugins/muxo/.claude-plugin/plugin.json +2 -2
- package/plugins/muxo/.codex-plugin/plugin.json +15 -8
- package/plugins/muxo/.cursor-plugin/plugin.json +30 -0
- package/plugins/muxo/hooks/session-start.sh +15 -3
- package/plugins/muxo/hooks/user-prompt-submit.sh +14 -1
- package/plugins/muxo/mcp.json +0 -10
- package/plugins/muxo/plugin.json +4 -4
- package/plugins/muxo/skills/muxo/SKILL.md +25 -16
- package/plugins/muxo/skills/muxo/references/cli.md +5 -1
- package/plugins/muxo/skills/muxo/references/mcp.md +11 -6
- package/plugins/muxo/skills/muxo-activity-summary/SKILL.md +81 -0
- package/plugins/muxo/skills/setup/SKILL.md +1 -1
- package/src/catalogues/stripe-projects-catalog.json +140 -0
package/dist/config.d.ts
CHANGED
|
@@ -5,7 +5,13 @@ export interface MuxoConfig {
|
|
|
5
5
|
baseUrl: string;
|
|
6
6
|
dbPath: string;
|
|
7
7
|
composioApiKey: string;
|
|
8
|
+
composioInstantApiKey: string;
|
|
8
9
|
composioBaseUrl: string;
|
|
10
|
+
composioWebhookSecret: string;
|
|
11
|
+
composioWebhookSubscriptionId: string;
|
|
12
|
+
composioProjectId: string;
|
|
13
|
+
composioOrgId: string;
|
|
14
|
+
composioUserId: string;
|
|
9
15
|
stripeSecretKey: string;
|
|
10
16
|
stripePublishableKey: string;
|
|
11
17
|
stripeApiBaseUrl: string;
|
package/dist/config.js
CHANGED
|
@@ -65,8 +65,18 @@ export function getConfig() {
|
|
|
65
65
|
dbPath: process.env.MUXO_DB_PATH || path.join(dataDir, "muxo.db"),
|
|
66
66
|
composioApiKey: process.env.MUXO_EXTERNAL_MODE === "1"
|
|
67
67
|
? ""
|
|
68
|
-
: process.env.COMPOSIO_API_KEY || "",
|
|
68
|
+
: process.env.COMPOSIO_API_KEY || process.env.COMPOSIO_INSTANT_API_KEY || "",
|
|
69
|
+
composioInstantApiKey: process.env.MUXO_EXTERNAL_MODE === "1"
|
|
70
|
+
? ""
|
|
71
|
+
: process.env.COMPOSIO_INSTANT_API_KEY || process.env.COMPOSIO_API_KEY || "",
|
|
69
72
|
composioBaseUrl: process.env.COMPOSIO_BASE_URL || "https://backend.composio.dev/api/v3",
|
|
73
|
+
composioWebhookSecret: process.env.MUXO_EXTERNAL_MODE === "1"
|
|
74
|
+
? ""
|
|
75
|
+
: process.env.COMPOSIO_WEBHOOK_SECRET || "",
|
|
76
|
+
composioWebhookSubscriptionId: process.env.COMPOSIO_WEBHOOK_SUBSCRIPTION_ID || "",
|
|
77
|
+
composioProjectId: process.env.COMPOSIO_PROJECT_ID || "",
|
|
78
|
+
composioOrgId: process.env.COMPOSIO_ORG_ID || "",
|
|
79
|
+
composioUserId: process.env.COMPOSIO_USER_ID || "",
|
|
70
80
|
stripeSecretKey: process.env.MUXO_EXTERNAL_MODE === "1"
|
|
71
81
|
? ""
|
|
72
82
|
: process.env.STRIPE_SECRET_KEY || "",
|
package/dist/engine.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { MuxoConfig } from "./config.js";
|
|
2
2
|
import { type DurableWorkflow } from "./durable-workflow.js";
|
|
3
3
|
import { type NaturalLanguageResolution } from "./nl.js";
|
|
4
|
-
import { describePolicyInPlainEnglish, type GuardrailCompileOptions, type ParsedNaturalLanguageGuardrail } from "./policy.js";
|
|
4
|
+
import { describePolicyInPlainEnglish, type GuardrailCompileOptions, type LlmPolicyAndGovernanceBrief, type ParsedNaturalLanguageGuardrail, type PolicySimulationResult } from "./policy.js";
|
|
5
5
|
import { ComposioInstantAdapter } from "./providers/composio-instant.js";
|
|
6
6
|
import { ComposioSdkAdapter } from "./providers/composio-sdk.js";
|
|
7
7
|
import { MicrosoftGovernanceAdapter } from "./providers/microsoft-governance.js";
|
|
@@ -66,6 +66,7 @@ export declare class MuxoEngine {
|
|
|
66
66
|
provider?: string;
|
|
67
67
|
syncLive?: boolean;
|
|
68
68
|
}): Promise<Record<string, unknown>>;
|
|
69
|
+
getHostedSiteHtml(slug: string, filePath?: string): string | null;
|
|
69
70
|
startConnection(ctx: ExecutionContext, params: {
|
|
70
71
|
provider: string;
|
|
71
72
|
lane?: ProviderLane;
|
|
@@ -287,8 +288,22 @@ export declare class MuxoEngine {
|
|
|
287
288
|
trustScore: ReturnType<MicrosoftGovernanceAdapter["getWorkspaceTrustScore"]>;
|
|
288
289
|
policy: Workspace["policy"];
|
|
289
290
|
plainEnglish: ReturnType<typeof describePolicyInPlainEnglish>;
|
|
291
|
+
llmPolicyBrief: LlmPolicyAndGovernanceBrief;
|
|
290
292
|
explanation: HumanFriendlyExplanation;
|
|
291
293
|
};
|
|
294
|
+
resetWorkspaceGuardrails(ctx: ExecutionContext): {
|
|
295
|
+
ok: true;
|
|
296
|
+
action: "reset_guardrails";
|
|
297
|
+
workspace: Workspace;
|
|
298
|
+
policy: Workspace["policy"];
|
|
299
|
+
plainEnglish: ReturnType<typeof describePolicyInPlainEnglish>;
|
|
300
|
+
llmPolicyBrief: LlmPolicyAndGovernanceBrief;
|
|
301
|
+
explanation: HumanFriendlyExplanation;
|
|
302
|
+
};
|
|
303
|
+
checkToolPolicy(ctx: ExecutionContext, params: {
|
|
304
|
+
toolSlug: string;
|
|
305
|
+
input?: Record<string, unknown>;
|
|
306
|
+
}): Promise<PolicySimulationResult>;
|
|
292
307
|
setKillSwitch(ctx: ExecutionContext, active: boolean, reason?: string): Workspace;
|
|
293
308
|
scanForContextPoisoning(workspaceId: string, text: string): {
|
|
294
309
|
poisoned: boolean;
|
|
@@ -301,6 +316,7 @@ export declare class MuxoEngine {
|
|
|
301
316
|
workspaceId: string;
|
|
302
317
|
policy: Workspace["policy"];
|
|
303
318
|
plainEnglish: ReturnType<typeof describePolicyInPlainEnglish>;
|
|
319
|
+
llmPolicyBrief: LlmPolicyAndGovernanceBrief;
|
|
304
320
|
activeDefaults: ActiveMemoryDefaults;
|
|
305
321
|
activeGuardrails: string[];
|
|
306
322
|
};
|
|
@@ -309,6 +325,7 @@ export declare class MuxoEngine {
|
|
|
309
325
|
workspace: Workspace;
|
|
310
326
|
guardrail: ParsedNaturalLanguageGuardrail;
|
|
311
327
|
plainEnglish: ReturnType<typeof describePolicyInPlainEnglish>;
|
|
328
|
+
llmPolicyBrief: LlmPolicyAndGovernanceBrief;
|
|
312
329
|
memoryRecord?: WorkspaceMemoryRecord;
|
|
313
330
|
}>;
|
|
314
331
|
doNaturalLanguage(ctx: ExecutionContext, params: {
|
package/dist/engine.js
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import crypto from "node:crypto";
|
|
2
|
-
import {
|
|
2
|
+
import { isStripeProjectsExclusiveProvider, normalizeStripeProjectsProviderSlug, wrapMuxoConnectUrl, } from "./composio-catalog.js";
|
|
3
|
+
import { APPROVED_PLAN_STATUSES, approvalRequiredError, buildApprovalHumanHandoff, buildApprovalUrl, buildOAuthHumanHandoff, clampWaitSeconds, looksLikeToolSlug, unknownToolError, } from "./mcp-schema.js";
|
|
3
4
|
import { completeCloudProvisioningWorkflow, createCloudProvisioningWorkflow, normalizeWorkflowTarget, workflowNotFoundError, } from "./durable-workflow.js";
|
|
4
5
|
import { buildMemoryKnowledgeGraph } from "./memory-graph.js";
|
|
5
6
|
import { resolveNaturalLanguageIntent, } from "./nl.js";
|
|
6
|
-
import { compileNaturalLanguageGuardrailWithLlm, describePolicyInPlainEnglish, formatHumanFriendlyExplanation, parseNaturalLanguageGuardrail, } from "./policy.js";
|
|
7
|
+
import { DEFAULT_WORKSPACE_POLICY, buildLlmPolicyAndGovernanceBrief, compileNaturalLanguageGuardrailWithLlm, describePolicyInPlainEnglish, formatHumanFriendlyExplanation, parseNaturalLanguageGuardrail, simulatePolicyEvaluation, } from "./policy.js";
|
|
7
8
|
import { ComposioInstantAdapter } from "./providers/composio-instant.js";
|
|
8
9
|
import { ComposioSdkAdapter } from "./providers/composio-sdk.js";
|
|
9
10
|
import { MicrosoftGovernanceAdapter } from "./providers/microsoft-governance.js";
|
|
@@ -73,6 +74,24 @@ export class MuxoEngine {
|
|
|
73
74
|
const connections = this.store.listConnections(ws.id);
|
|
74
75
|
const supplierSettlementSummary = this.store.getSupplierSettlementSummary(ws.id);
|
|
75
76
|
const plainEnglishPolicy = describePolicyInPlainEnglish(ws.policy);
|
|
77
|
+
const localMemories = this.store.listMemoryRecords(ws.id, 25);
|
|
78
|
+
const activeFacts = this.store.listTemporalFacts(ws.id, {
|
|
79
|
+
includeHistorical: false,
|
|
80
|
+
limit: 30,
|
|
81
|
+
});
|
|
82
|
+
const inferred = extractActiveMemoryDefaults({
|
|
83
|
+
memories: localMemories,
|
|
84
|
+
temporalFacts: activeFacts,
|
|
85
|
+
});
|
|
86
|
+
const trustScore = this.governance.getWorkspaceTrustScore(ws.id);
|
|
87
|
+
const govStatus = this.governance.getStatus(ws);
|
|
88
|
+
const llmPolicyBrief = buildLlmPolicyAndGovernanceBrief(ws.policy, {
|
|
89
|
+
workspaceName: ws.name,
|
|
90
|
+
workspaceSlug: ws.slug,
|
|
91
|
+
activeDefaults: inferred.activeDefaults,
|
|
92
|
+
trustScore: { overall: trustScore.overall, tier: trustScore.tier },
|
|
93
|
+
agentDid: govStatus.agentDid,
|
|
94
|
+
});
|
|
76
95
|
return {
|
|
77
96
|
organization: {
|
|
78
97
|
id: ws.id,
|
|
@@ -88,12 +107,16 @@ export class MuxoEngine {
|
|
|
88
107
|
supplierSettlementSummary,
|
|
89
108
|
policy: ws.policy,
|
|
90
109
|
plainEnglishPolicy,
|
|
110
|
+
llmPolicyBrief,
|
|
111
|
+
activeDefaults: inferred.activeDefaults,
|
|
91
112
|
explanation: plainEnglishPolicy.explanation,
|
|
92
113
|
activeConnectionsCount: connections.filter((c) => c.status === "active").length,
|
|
93
114
|
provisionedResourcesCount: resources.filter((r) => r.status === "active").length,
|
|
94
115
|
projectsEnvironment: ws.projectsEnvName,
|
|
95
116
|
createdAt: ws.createdAt,
|
|
96
117
|
},
|
|
118
|
+
llmPolicyBrief,
|
|
119
|
+
activeDefaults: inferred.activeDefaults,
|
|
97
120
|
};
|
|
98
121
|
}
|
|
99
122
|
// 3. search_tools
|
|
@@ -101,7 +124,16 @@ export class MuxoEngine {
|
|
|
101
124
|
const limit = Math.min(100, Math.max(1, Number(params.limit || 25)));
|
|
102
125
|
const lane = params.lane || "all";
|
|
103
126
|
const query = params.query?.trim();
|
|
127
|
+
const queryTokens = (query || "")
|
|
128
|
+
.toLowerCase()
|
|
129
|
+
.split(/[\s,._/-]+/)
|
|
130
|
+
.filter(Boolean);
|
|
131
|
+
const prefersStripeProjects = queryTokens.some((tok) => isStripeProjectsExclusiveProvider(tok) ||
|
|
132
|
+
/^(provision|deploy|deployment|publish|host|hosting|static|landing|database|postgres|sqlite|redis)$/.test(tok));
|
|
104
133
|
const results = [];
|
|
134
|
+
if (lane === "all" && prefersStripeProjects) {
|
|
135
|
+
results.push(...this.stripeProjects.searchTools(query, limit));
|
|
136
|
+
}
|
|
105
137
|
if (lane === "all" || lane === "composio_instant") {
|
|
106
138
|
results.push(...this.composioInstant.searchTools(query, limit));
|
|
107
139
|
}
|
|
@@ -109,8 +141,10 @@ export class MuxoEngine {
|
|
|
109
141
|
const sdkTools = await this.composioSdk.searchTools(query, limit);
|
|
110
142
|
results.push(...sdkTools);
|
|
111
143
|
}
|
|
112
|
-
if (lane === "
|
|
144
|
+
if (lane === "stripe_projects" || (lane === "all" && !prefersStripeProjects)) {
|
|
113
145
|
results.push(...this.stripeProjects.searchTools(query, limit));
|
|
146
|
+
}
|
|
147
|
+
if (lane === "all" || lane === "stripe_projects") {
|
|
114
148
|
const billingTools = this.stripeBilling.listTools().filter((t) => {
|
|
115
149
|
if (!query)
|
|
116
150
|
return true;
|
|
@@ -131,7 +165,7 @@ export class MuxoEngine {
|
|
|
131
165
|
async listAllCatalogTools() {
|
|
132
166
|
const instant = this.composioInstant.searchTools(undefined, 100);
|
|
133
167
|
const sdk = await this.composioSdk.searchTools(undefined, 100);
|
|
134
|
-
const proj = this.stripeProjects.
|
|
168
|
+
const proj = this.stripeProjects.getTools();
|
|
135
169
|
const billing = this.stripeBilling.listTools();
|
|
136
170
|
return [...instant, ...billing, ...sdk, ...proj];
|
|
137
171
|
}
|
|
@@ -162,6 +196,9 @@ export class MuxoEngine {
|
|
|
162
196
|
const composioByok = this.store.getByokKey(ctx.workspace.id, "composio");
|
|
163
197
|
const liveComposio = await this.composioSdk.listLiveConnections(ctx.workspace.id, composioByok);
|
|
164
198
|
for (const c of liveComposio) {
|
|
199
|
+
if (isStripeProjectsExclusiveProvider(c.providerSlug)) {
|
|
200
|
+
continue;
|
|
201
|
+
}
|
|
165
202
|
this.store.upsertConnection({
|
|
166
203
|
workspaceId: ctx.workspace.id,
|
|
167
204
|
lane: "composio_sdk",
|
|
@@ -191,15 +228,63 @@ export class MuxoEngine {
|
|
|
191
228
|
// Keep cached connections if CLI is busy
|
|
192
229
|
}
|
|
193
230
|
}
|
|
194
|
-
let connections = this.store.listConnections(ctx.workspace.id)
|
|
231
|
+
let connections = this.store.listConnections(ctx.workspace.id).map((c) => {
|
|
232
|
+
if (isStripeProjectsExclusiveProvider(c.providerSlug)) {
|
|
233
|
+
return {
|
|
234
|
+
...c,
|
|
235
|
+
lane: "stripe_projects",
|
|
236
|
+
status: "active",
|
|
237
|
+
redirectUrl: null,
|
|
238
|
+
};
|
|
239
|
+
}
|
|
240
|
+
return c.lane === "composio_sdk" && c.redirectUrl
|
|
241
|
+
? {
|
|
242
|
+
...c,
|
|
243
|
+
redirectUrl: wrapMuxoConnectUrl(c.redirectUrl, this.config.baseUrl, {
|
|
244
|
+
workspaceId: c.workspaceId,
|
|
245
|
+
providerSlug: c.providerSlug,
|
|
246
|
+
externalAccountId: c.externalAccountId,
|
|
247
|
+
}),
|
|
248
|
+
}
|
|
249
|
+
: c;
|
|
250
|
+
});
|
|
195
251
|
if (params?.provider) {
|
|
196
|
-
const target = params.provider.toLowerCase();
|
|
197
|
-
|
|
198
|
-
|
|
252
|
+
const target = normalizeStripeProjectsProviderSlug(params.provider) || params.provider.toLowerCase();
|
|
253
|
+
if (isStripeProjectsExclusiveProvider(target)) {
|
|
254
|
+
const activeRecord = this.store.upsertConnection({
|
|
255
|
+
workspaceId: ctx.workspace.id,
|
|
256
|
+
lane: "stripe_projects",
|
|
257
|
+
providerSlug: target,
|
|
258
|
+
providerName: target.charAt(0).toUpperCase() + target.slice(1),
|
|
259
|
+
status: "active",
|
|
260
|
+
externalAccountId: `sp_conn_${target}`,
|
|
261
|
+
redirectUrl: null,
|
|
262
|
+
metadata: {
|
|
263
|
+
managedBy: "stripe_projects",
|
|
264
|
+
requiresOAuth: false,
|
|
265
|
+
},
|
|
266
|
+
});
|
|
267
|
+
connections = [activeRecord];
|
|
268
|
+
}
|
|
269
|
+
else {
|
|
270
|
+
connections = connections.filter((c) => c.providerSlug.toLowerCase() === target ||
|
|
271
|
+
c.providerName.toLowerCase().includes(target));
|
|
272
|
+
}
|
|
199
273
|
}
|
|
274
|
+
const targetConn = connections[0] || null;
|
|
275
|
+
const isActive = targetConn
|
|
276
|
+
? targetConn.status === "active"
|
|
277
|
+
: connections.some((c) => c.status === "active");
|
|
200
278
|
return {
|
|
279
|
+
ok: true,
|
|
201
280
|
workspaceId: ctx.workspace.id,
|
|
202
281
|
instantWalletStatus: "active",
|
|
282
|
+
connected: isActive,
|
|
283
|
+
ready: isActive,
|
|
284
|
+
timedOut: false,
|
|
285
|
+
status: targetConn?.status || "not_connected",
|
|
286
|
+
redirectUrl: isActive ? null : targetConn?.redirectUrl || null,
|
|
287
|
+
connection: targetConn,
|
|
203
288
|
connections,
|
|
204
289
|
summary: {
|
|
205
290
|
total: connections.length,
|
|
@@ -209,11 +294,18 @@ export class MuxoEngine {
|
|
|
209
294
|
},
|
|
210
295
|
};
|
|
211
296
|
}
|
|
297
|
+
getHostedSiteHtml(slug, filePath) {
|
|
298
|
+
return this.stripeProjects.getHostedSiteHtml(slug, filePath);
|
|
299
|
+
}
|
|
212
300
|
// 6. start_connection
|
|
213
301
|
async startConnection(ctx, params) {
|
|
214
302
|
const rawProvider = params.provider.trim().toLowerCase();
|
|
215
|
-
const
|
|
216
|
-
|
|
303
|
+
const cleanSlug = normalizeStripeProjectsProviderSlug(rawProvider) ||
|
|
304
|
+
rawProvider.replace(/^(app\.|resource\.|projects\.)/, "");
|
|
305
|
+
const isProjectsLane = params.lane === "stripe_projects" ||
|
|
306
|
+
rawProvider.startsWith("resource.") ||
|
|
307
|
+
rawProvider.startsWith("projects.") ||
|
|
308
|
+
isStripeProjectsExclusiveProvider(cleanSlug);
|
|
217
309
|
if (isProjectsLane) {
|
|
218
310
|
const stripeByok = this.store.getByokKey(ctx.workspace.id, "stripe");
|
|
219
311
|
const linked = await this.stripeProjects.linkProvider(cleanSlug, stripeByok);
|
|
@@ -258,10 +350,9 @@ export class MuxoEngine {
|
|
|
258
350
|
}
|
|
259
351
|
// 6b. wait_for_connection (OAuth handoff polling & recovery, like COMPOSIO_WAIT_FOR_CONNECTIONS)
|
|
260
352
|
async waitForConnection(ctx, params) {
|
|
261
|
-
const
|
|
262
|
-
|
|
263
|
-
.
|
|
264
|
-
.replace(/^(app\.|resource\.)/, "");
|
|
353
|
+
const rawProvider = params.provider.trim().toLowerCase();
|
|
354
|
+
const cleanSlug = normalizeStripeProjectsProviderSlug(rawProvider) ||
|
|
355
|
+
rawProvider.replace(/^(app\.|resource\.|projects\.)/, "");
|
|
265
356
|
if (!cleanSlug) {
|
|
266
357
|
throw new Error("provider is required to wait for a connection (e.g. 'github').");
|
|
267
358
|
}
|
|
@@ -283,6 +374,22 @@ export class MuxoEngine {
|
|
|
283
374
|
elapsedMs: Date.now() - startedAt,
|
|
284
375
|
message,
|
|
285
376
|
});
|
|
377
|
+
if (isStripeProjectsExclusiveProvider(cleanSlug)) {
|
|
378
|
+
const activeRecord = this.store.upsertConnection({
|
|
379
|
+
workspaceId: ctx.workspace.id,
|
|
380
|
+
lane: "stripe_projects",
|
|
381
|
+
providerSlug: cleanSlug,
|
|
382
|
+
providerName: cleanSlug.charAt(0).toUpperCase() + cleanSlug.slice(1),
|
|
383
|
+
status: "active",
|
|
384
|
+
externalAccountId: `sp_conn_${cleanSlug}`,
|
|
385
|
+
redirectUrl: null,
|
|
386
|
+
metadata: {
|
|
387
|
+
managedBy: "stripe_projects",
|
|
388
|
+
requiresOAuth: false,
|
|
389
|
+
},
|
|
390
|
+
});
|
|
391
|
+
return connectedResult(activeRecord, `${activeRecord.providerName} is managed via Stripe Projects Cloud Infrastructure and is active immediately (no OAuth required).`);
|
|
392
|
+
}
|
|
286
393
|
let current = this.store
|
|
287
394
|
.listConnections(ctx.workspace.id)
|
|
288
395
|
.find((c) => c.providerSlug.toLowerCase() === cleanSlug);
|
|
@@ -341,6 +448,16 @@ export class MuxoEngine {
|
|
|
341
448
|
if (!current) {
|
|
342
449
|
current = await this.startConnection(ctx, { provider: cleanSlug });
|
|
343
450
|
}
|
|
451
|
+
else if (current.redirectUrl) {
|
|
452
|
+
current = {
|
|
453
|
+
...current,
|
|
454
|
+
redirectUrl: wrapMuxoConnectUrl(current.redirectUrl, this.config.baseUrl, {
|
|
455
|
+
workspaceId: ctx.workspace.id,
|
|
456
|
+
providerSlug: cleanSlug,
|
|
457
|
+
externalAccountId: current.externalAccountId,
|
|
458
|
+
}),
|
|
459
|
+
};
|
|
460
|
+
}
|
|
344
461
|
return {
|
|
345
462
|
ok: true,
|
|
346
463
|
connected: false,
|
|
@@ -527,14 +644,21 @@ export class MuxoEngine {
|
|
|
527
644
|
// Keep existing connection state if offline
|
|
528
645
|
}
|
|
529
646
|
if (!existingConn || existingConn.status !== "active") {
|
|
647
|
+
const wrappedRedirectUrl = existingConn?.redirectUrl
|
|
648
|
+
? wrapMuxoConnectUrl(existingConn.redirectUrl, this.config.baseUrl, {
|
|
649
|
+
workspaceId: ws.id,
|
|
650
|
+
providerSlug: tool.providerSlug,
|
|
651
|
+
externalAccountId: existingConn.externalAccountId,
|
|
652
|
+
})
|
|
653
|
+
: null;
|
|
530
654
|
authHandoff = {
|
|
531
655
|
required: true,
|
|
532
656
|
provider: tool.providerSlug,
|
|
533
657
|
status: existingConn?.status || "pending",
|
|
534
|
-
redirectUrl:
|
|
658
|
+
redirectUrl: wrappedRedirectUrl,
|
|
535
659
|
externalAccountId: existingConn?.externalAccountId || null,
|
|
536
|
-
instructions:
|
|
537
|
-
? `Ask the user to authorize ${tool.providerName} at ${
|
|
660
|
+
instructions: wrappedRedirectUrl
|
|
661
|
+
? `Ask the user to authorize ${tool.providerName} at ${wrappedRedirectUrl}, then call wait_for_connection({ provider: "${tool.providerSlug}" }) before executing ${plan.id}.`
|
|
538
662
|
: `Call start_connection({ provider: "${tool.providerSlug}" }) to authorize ${tool.providerName} before executing ${plan.id}.`,
|
|
539
663
|
};
|
|
540
664
|
}
|
|
@@ -606,25 +730,15 @@ export class MuxoEngine {
|
|
|
606
730
|
});
|
|
607
731
|
}
|
|
608
732
|
buildApprovalHandoff(plan) {
|
|
609
|
-
|
|
610
|
-
return {
|
|
611
|
-
kind: "approval",
|
|
612
|
-
url,
|
|
613
|
-
ctaLabel: "Review & approve",
|
|
614
|
-
headline: `Muxo needs your approval to run ${plan.toolSlug}`,
|
|
615
|
-
instructions: `Open ${url} to review and approve this ${plan.riskLevel}-risk action with one click (or run \`muxo approve ${plan.id}\`). Nothing runs until you approve.`,
|
|
616
|
-
planId: plan.id,
|
|
617
|
-
};
|
|
733
|
+
return buildApprovalHumanHandoff(this.config.baseUrl, plan);
|
|
618
734
|
}
|
|
619
735
|
buildOAuthHandoff(handoff, providerName) {
|
|
620
|
-
return {
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
headline: `Connect ${providerName} to continue`,
|
|
736
|
+
return buildOAuthHumanHandoff({
|
|
737
|
+
providerSlug: handoff.provider,
|
|
738
|
+
providerName,
|
|
739
|
+
redirectUrl: handoff.redirectUrl,
|
|
625
740
|
instructions: handoff.instructions,
|
|
626
|
-
|
|
627
|
-
};
|
|
741
|
+
});
|
|
628
742
|
}
|
|
629
743
|
buildPlanLlmGuidance(plan, authHandoff) {
|
|
630
744
|
const executeTool = `execute_${plan.riskLevel}`;
|
|
@@ -767,6 +881,7 @@ export class MuxoEngine {
|
|
|
767
881
|
}
|
|
768
882
|
const enriched = {
|
|
769
883
|
...ctx,
|
|
884
|
+
enabled: true,
|
|
770
885
|
staticFacts,
|
|
771
886
|
dynamicContext,
|
|
772
887
|
recalledMemories: recalled,
|
|
@@ -833,6 +948,13 @@ export class MuxoEngine {
|
|
|
833
948
|
technical: contextTechnical,
|
|
834
949
|
policy: ws.policy,
|
|
835
950
|
});
|
|
951
|
+
const llmPolicyBrief = buildLlmPolicyAndGovernanceBrief(ws.policy, {
|
|
952
|
+
workspaceName: ws.name,
|
|
953
|
+
workspaceSlug: ws.slug,
|
|
954
|
+
activeDefaults: memoryContext.activeDefaults || {},
|
|
955
|
+
trustScore: { overall: trustScore.overall, tier: trustScore.tier },
|
|
956
|
+
agentDid: governanceStatus.agentDid,
|
|
957
|
+
});
|
|
836
958
|
const llmSystemPrompt = [
|
|
837
959
|
`# Muxo Governed Workspace Context (${ws.name} / ${ws.slug})`,
|
|
838
960
|
`- **Language Preference**: ${ws.policy.languageMode || "hybrid"}${ws.policy.customInstructions?.length ? ` (Custom Instructions: ${ws.policy.customInstructions.join("; ")})` : ""}`,
|
|
@@ -840,6 +962,7 @@ export class MuxoEngine {
|
|
|
840
962
|
`- **Learned Memory Defaults (Auto-Fill)**: ${defaultsList.length > 0 ? defaultsList.join(", ") : "none"}`,
|
|
841
963
|
`- **Credits & Quota**: ${ws.creditsBalance} credits ($${(ws.creditsBalance * 0.01).toFixed(2)}) available, ${actionsRemaining} monthly actions remaining`,
|
|
842
964
|
`- **Active Cloud Resources**: ${activeResources.length > 0 ? activeResources.map((r) => `${r.resourceName} (${r.serviceSlug})`).join(", ") : "none"}`,
|
|
965
|
+
llmPolicyBrief.llmSystemDirective,
|
|
843
966
|
memoryContext.formattedPromptContext,
|
|
844
967
|
].join("\n");
|
|
845
968
|
return {
|
|
@@ -848,6 +971,7 @@ export class MuxoEngine {
|
|
|
848
971
|
projectsEnvironment: ws.projectsEnvName,
|
|
849
972
|
policy: ws.policy,
|
|
850
973
|
plainEnglishPolicy,
|
|
974
|
+
llmPolicyBrief,
|
|
851
975
|
languageMode: ws.policy.languageMode || "hybrid",
|
|
852
976
|
customInstructions: ws.policy.customInstructions || [],
|
|
853
977
|
activeDefaults: (memoryContext.activeDefaults ||
|
|
@@ -1060,7 +1184,10 @@ export class MuxoEngine {
|
|
|
1060
1184
|
// 10-15. execute_<risk_level>
|
|
1061
1185
|
async executePlanForRisk(ctx, planId, expectedRisk) {
|
|
1062
1186
|
const plan = this.getPlan(ctx, planId);
|
|
1063
|
-
|
|
1187
|
+
const isProjectsWriteCompatible = plan.lane === "stripe_projects" &&
|
|
1188
|
+
plan.riskLevel === "provisioning" &&
|
|
1189
|
+
expectedRisk === "write";
|
|
1190
|
+
if (plan.riskLevel !== expectedRisk && !isProjectsWriteCompatible) {
|
|
1064
1191
|
throw new Error(`Risk lane mismatch: Plan '${plan.id}' has risk level '${plan.riskLevel}', so it must be executed with 'execute_${plan.riskLevel}' instead of 'execute_${expectedRisk}'.`);
|
|
1065
1192
|
}
|
|
1066
1193
|
if (plan.runId) {
|
|
@@ -1107,7 +1234,16 @@ export class MuxoEngine {
|
|
|
1107
1234
|
}
|
|
1108
1235
|
let activeConnId = null;
|
|
1109
1236
|
if (plan.lane === "composio_sdk" && tool.requiresAuth) {
|
|
1110
|
-
let connections = this.store.listConnections(ctx.workspace.id)
|
|
1237
|
+
let connections = this.store.listConnections(ctx.workspace.id).map((c) => c.lane === "composio_sdk" && c.redirectUrl
|
|
1238
|
+
? {
|
|
1239
|
+
...c,
|
|
1240
|
+
redirectUrl: wrapMuxoConnectUrl(c.redirectUrl, this.config.baseUrl, {
|
|
1241
|
+
workspaceId: c.workspaceId,
|
|
1242
|
+
providerSlug: c.providerSlug,
|
|
1243
|
+
externalAccountId: c.externalAccountId,
|
|
1244
|
+
}),
|
|
1245
|
+
}
|
|
1246
|
+
: c);
|
|
1111
1247
|
let activeConn = connections.find((c) => c.lane === "composio_sdk" &&
|
|
1112
1248
|
c.providerSlug === tool.providerSlug &&
|
|
1113
1249
|
c.status === "active");
|
|
@@ -1581,6 +1717,22 @@ export class MuxoEngine {
|
|
|
1581
1717
|
const governance = this.governance.getStatus(ws);
|
|
1582
1718
|
const trustScore = this.governance.getWorkspaceTrustScore(ws.id);
|
|
1583
1719
|
const plainEnglish = describePolicyInPlainEnglish(ws.policy);
|
|
1720
|
+
const localMemories = this.store.listMemoryRecords(ws.id, 25);
|
|
1721
|
+
const activeFacts = this.store.listTemporalFacts(ws.id, {
|
|
1722
|
+
includeHistorical: false,
|
|
1723
|
+
limit: 30,
|
|
1724
|
+
});
|
|
1725
|
+
const inferred = extractActiveMemoryDefaults({
|
|
1726
|
+
memories: localMemories,
|
|
1727
|
+
temporalFacts: activeFacts,
|
|
1728
|
+
});
|
|
1729
|
+
const llmPolicyBrief = buildLlmPolicyAndGovernanceBrief(ws.policy, {
|
|
1730
|
+
workspaceName: ws.name,
|
|
1731
|
+
workspaceSlug: ws.slug,
|
|
1732
|
+
activeDefaults: inferred.activeDefaults,
|
|
1733
|
+
trustScore: { overall: trustScore.overall, tier: trustScore.tier },
|
|
1734
|
+
agentDid: governance.agentDid,
|
|
1735
|
+
});
|
|
1584
1736
|
const killSwitch = {
|
|
1585
1737
|
active: Boolean(ws.policy.killSwitchActive),
|
|
1586
1738
|
reason: ws.policy.killSwitchReason || null,
|
|
@@ -1603,9 +1755,70 @@ export class MuxoEngine {
|
|
|
1603
1755
|
trustScore,
|
|
1604
1756
|
policy: ws.policy,
|
|
1605
1757
|
plainEnglish,
|
|
1758
|
+
llmPolicyBrief,
|
|
1606
1759
|
explanation,
|
|
1607
1760
|
};
|
|
1608
1761
|
}
|
|
1762
|
+
resetWorkspaceGuardrails(ctx) {
|
|
1763
|
+
const ws = this.store.getWorkspace(ctx.workspace.id);
|
|
1764
|
+
const updated = this.store.updateWorkspacePolicy(ws.id, {
|
|
1765
|
+
...DEFAULT_WORKSPACE_POLICY,
|
|
1766
|
+
parameterRules: [],
|
|
1767
|
+
customInstructions: [],
|
|
1768
|
+
naturalLanguageRules: [],
|
|
1769
|
+
blockedToolSlugs: [],
|
|
1770
|
+
});
|
|
1771
|
+
this.governance.resumeKillSwitch(ws.id);
|
|
1772
|
+
const plainEnglish = describePolicyInPlainEnglish(updated.policy);
|
|
1773
|
+
const llmPolicyBrief = buildLlmPolicyAndGovernanceBrief(updated.policy, {
|
|
1774
|
+
workspaceName: updated.name,
|
|
1775
|
+
workspaceSlug: updated.slug,
|
|
1776
|
+
});
|
|
1777
|
+
return {
|
|
1778
|
+
ok: true,
|
|
1779
|
+
action: "reset_guardrails",
|
|
1780
|
+
workspace: updated,
|
|
1781
|
+
policy: updated.policy,
|
|
1782
|
+
plainEnglish,
|
|
1783
|
+
llmPolicyBrief,
|
|
1784
|
+
explanation: plainEnglish.explanation,
|
|
1785
|
+
};
|
|
1786
|
+
}
|
|
1787
|
+
async checkToolPolicy(ctx, params) {
|
|
1788
|
+
const ws = this.store.getWorkspace(ctx.workspace.id);
|
|
1789
|
+
const localMemories = this.store.listMemoryRecords(ws.id, 25);
|
|
1790
|
+
const activeFacts = this.store.listTemporalFacts(ws.id, {
|
|
1791
|
+
includeHistorical: false,
|
|
1792
|
+
limit: 30,
|
|
1793
|
+
});
|
|
1794
|
+
const inferred = extractActiveMemoryDefaults({
|
|
1795
|
+
memories: localMemories,
|
|
1796
|
+
temporalFacts: activeFacts,
|
|
1797
|
+
});
|
|
1798
|
+
let riskLevel;
|
|
1799
|
+
let creditCost;
|
|
1800
|
+
let lane;
|
|
1801
|
+
let resolvedSlug = String(params.toolSlug || "instant.web.search").trim();
|
|
1802
|
+
try {
|
|
1803
|
+
const tool = await this.inspectTool(resolvedSlug);
|
|
1804
|
+
resolvedSlug = tool.slug;
|
|
1805
|
+
riskLevel = tool.riskLevel;
|
|
1806
|
+
creditCost = tool.creditCost;
|
|
1807
|
+
lane = tool.lane;
|
|
1808
|
+
}
|
|
1809
|
+
catch {
|
|
1810
|
+
// Fallback to slug prefix heuristics in simulatePolicyEvaluation
|
|
1811
|
+
}
|
|
1812
|
+
return simulatePolicyEvaluation({
|
|
1813
|
+
policy: ws.policy,
|
|
1814
|
+
toolSlug: resolvedSlug,
|
|
1815
|
+
riskLevel,
|
|
1816
|
+
creditCost,
|
|
1817
|
+
lane,
|
|
1818
|
+
input: params.input || {},
|
|
1819
|
+
activeDefaults: inferred.activeDefaults,
|
|
1820
|
+
});
|
|
1821
|
+
}
|
|
1609
1822
|
setKillSwitch(ctx, active, reason) {
|
|
1610
1823
|
const ws = this.store.getWorkspace(ctx.workspace.id);
|
|
1611
1824
|
const updated = this.store.updateWorkspacePolicy(ws.id, {
|
|
@@ -1656,10 +1869,16 @@ export class MuxoEngine {
|
|
|
1656
1869
|
memories: localMemories,
|
|
1657
1870
|
temporalFacts: activeFacts,
|
|
1658
1871
|
});
|
|
1872
|
+
const llmPolicyBrief = buildLlmPolicyAndGovernanceBrief(ws.policy, {
|
|
1873
|
+
workspaceName: ws.name,
|
|
1874
|
+
workspaceSlug: ws.slug,
|
|
1875
|
+
activeDefaults: inferred.activeDefaults,
|
|
1876
|
+
});
|
|
1659
1877
|
return {
|
|
1660
1878
|
workspaceId: ws.id,
|
|
1661
1879
|
policy: ws.policy,
|
|
1662
1880
|
plainEnglish,
|
|
1881
|
+
llmPolicyBrief,
|
|
1663
1882
|
activeDefaults: inferred.activeDefaults,
|
|
1664
1883
|
activeGuardrails: Array.from(new Set([
|
|
1665
1884
|
...(ws.policy.naturalLanguageRules || []),
|
|
@@ -1701,11 +1920,16 @@ export class MuxoEngine {
|
|
|
1701
1920
|
// Non-blocking if memory scan/storage fails
|
|
1702
1921
|
}
|
|
1703
1922
|
const plainEnglish = describePolicyInPlainEnglish(updated.policy);
|
|
1923
|
+
const llmPolicyBrief = buildLlmPolicyAndGovernanceBrief(updated.policy, {
|
|
1924
|
+
workspaceName: updated.name,
|
|
1925
|
+
workspaceSlug: updated.slug,
|
|
1926
|
+
});
|
|
1704
1927
|
return {
|
|
1705
1928
|
ok: true,
|
|
1706
1929
|
workspace: updated,
|
|
1707
1930
|
guardrail: parsed,
|
|
1708
1931
|
plainEnglish,
|
|
1932
|
+
llmPolicyBrief,
|
|
1709
1933
|
memoryRecord,
|
|
1710
1934
|
};
|
|
1711
1935
|
}
|