@muxoai/platform 1.4.1 → 1.4.3

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.
Files changed (53) hide show
  1. package/.agents/plugins/marketplace.json +1 -1
  2. package/.claude-plugin/marketplace.json +2 -2
  3. package/README.md +1 -1
  4. package/dist/cli.js +94 -3
  5. package/dist/composio-catalog.d.ts +177 -1
  6. package/dist/composio-catalog.js +1427 -7
  7. package/dist/config.d.ts +6 -0
  8. package/dist/config.js +11 -1
  9. package/dist/durable-workflow.d.ts +71 -4
  10. package/dist/durable-workflow.js +199 -5
  11. package/dist/engine.d.ts +82 -3
  12. package/dist/engine.js +406 -41
  13. package/dist/index.d.ts +3 -0
  14. package/dist/index.js +3 -0
  15. package/dist/mcp-schema.d.ts +162 -1
  16. package/dist/mcp-schema.js +1544 -40
  17. package/dist/mcp.d.ts +2 -2
  18. package/dist/mcp.js +474 -26
  19. package/dist/memory-graph.d.ts +26 -2
  20. package/dist/memory-graph.js +127 -7
  21. package/dist/oss-suite.d.ts +217 -0
  22. package/dist/oss-suite.js +836 -0
  23. package/dist/policy.d.ts +108 -1
  24. package/dist/policy.js +406 -1
  25. package/dist/providers/composio-instant.js +38 -3
  26. package/dist/providers/composio-sdk.d.ts +59 -2
  27. package/dist/providers/composio-sdk.js +273 -59
  28. package/dist/providers/stripe-projects.d.ts +4 -0
  29. package/dist/providers/stripe-projects.js +548 -126
  30. package/dist/sdk.d.ts +24 -1
  31. package/dist/sdk.js +53 -2
  32. package/dist/server.js +659 -64
  33. package/dist/store.js +2 -0
  34. package/dist/types.d.ts +34 -1
  35. package/dist/ui/console-html.d.ts +31 -1
  36. package/dist/ui/console-html.js +922 -368
  37. package/dist/ui/design-tokens.js +1 -1
  38. package/dist/version.d.ts +1 -1
  39. package/dist/version.js +1 -1
  40. package/package.json +3 -2
  41. package/plugins/muxo/.claude-plugin/plugin.json +2 -2
  42. package/plugins/muxo/.codex-plugin/plugin.json +15 -8
  43. package/plugins/muxo/.cursor-plugin/plugin.json +30 -0
  44. package/plugins/muxo/hooks/session-start.sh +15 -3
  45. package/plugins/muxo/hooks/user-prompt-submit.sh +14 -1
  46. package/plugins/muxo/mcp.json +0 -10
  47. package/plugins/muxo/plugin.json +4 -4
  48. package/plugins/muxo/skills/muxo/SKILL.md +25 -16
  49. package/plugins/muxo/skills/muxo/references/cli.md +5 -1
  50. package/plugins/muxo/skills/muxo/references/mcp.md +11 -6
  51. package/plugins/muxo/skills/muxo-activity-summary/SKILL.md +81 -0
  52. package/plugins/muxo/skills/setup/SKILL.md +1 -1
  53. package/src/catalogues/stripe-projects-catalog.json +140 -0
package/dist/policy.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import type { GovernancePolicy, HumanFriendlyExplanation, LanguageMode, ParameterPolicyRule } from "./types.js";
1
+ import type { GovernancePolicy, HumanFriendlyExplanation, LanguageMode, ParameterPolicyRule, RiskLevel } from "./types.js";
2
2
  export declare function sanitizeParameterPolicyRule(r: Record<string, unknown>, idx?: number): ParameterPolicyRule;
3
3
  export declare class PolicyValidationError extends Error {
4
4
  }
@@ -81,3 +81,110 @@ export declare function evaluateParameterPolicyRules(paramsOrToolSlug: {
81
81
  violatedRule: ParameterPolicyRule | null;
82
82
  reason: string | null;
83
83
  };
84
+ export declare function describeParameterRuleCompliance(rule: ParameterPolicyRule): string;
85
+ export interface LlmRiskLaneRule {
86
+ riskLevel: RiskLevel;
87
+ status: "auto_approved" | "requires_approval" | "blocked";
88
+ executeTool: string;
89
+ reason: string;
90
+ }
91
+ export interface LlmPolicyAndGovernanceBrief {
92
+ workspaceId?: string;
93
+ posture: "paused" | "read_only_sandbox" | "ask_every_time" | "safe_default" | "hands_off" | "monitor";
94
+ mode: "enforce" | "monitor";
95
+ executionRing: 0 | 1 | 2 | 3;
96
+ headline: string;
97
+ preferredExplanation: string;
98
+ plainEnglish: ReturnType<typeof describePolicyInPlainEnglish>;
99
+ languageMode: LanguageMode;
100
+ customInstructions: string[];
101
+ killSwitch: {
102
+ active: boolean;
103
+ reason: string | null;
104
+ howToToggleMcp: {
105
+ pause: {
106
+ tool: "get_run_context";
107
+ arguments: Record<string, unknown>;
108
+ };
109
+ resume: {
110
+ tool: "get_run_context";
111
+ arguments: Record<string, unknown>;
112
+ };
113
+ };
114
+ };
115
+ budgetGuardrail: {
116
+ maxCreditsPerRun: number;
117
+ maxUsdPerRun: number;
118
+ allowInstantWallet: boolean;
119
+ allowProvisioning: boolean;
120
+ blockDestructiveSql: boolean;
121
+ };
122
+ riskLaneMatrix: Record<RiskLevel, LlmRiskLaneRule>;
123
+ autoApproveRiskLevels: RiskLevel[];
124
+ requireApprovalRiskLevels: RiskLevel[];
125
+ blockedRiskLevels: RiskLevel[];
126
+ blockedToolSlugs: string[];
127
+ parameterRules: Array<ParameterPolicyRule & {
128
+ howToComply: string;
129
+ }>;
130
+ naturalLanguageRules: string[];
131
+ activeDefaults: Record<string, unknown>;
132
+ trustScore?: {
133
+ overall: number;
134
+ tier: string;
135
+ };
136
+ agentDid?: string;
137
+ llmSystemDirective: string;
138
+ agentControlCheatsheet: Array<{
139
+ intent: string;
140
+ mcpTool: string;
141
+ arguments: Record<string, unknown>;
142
+ }>;
143
+ }
144
+ export declare function buildLlmPolicyAndGovernanceBrief(policy?: GovernancePolicy, options?: {
145
+ workspaceId?: string;
146
+ workspaceName?: string;
147
+ workspaceSlug?: string;
148
+ activeDefaults?: Record<string, unknown>;
149
+ trustScore?: {
150
+ overall: number;
151
+ tier: string;
152
+ };
153
+ agentDid?: string;
154
+ }): LlmPolicyAndGovernanceBrief;
155
+ export interface PolicySimulationResult {
156
+ ok: true;
157
+ action: "check_policy";
158
+ toolSlug: string;
159
+ toolName?: string;
160
+ riskLevel: RiskLevel;
161
+ creditCost: number;
162
+ decision: "auto_approved" | "pending_approval" | "blocked";
163
+ approvalStatus: "auto_approved" | "pending_approval" | "blocked";
164
+ allowed: boolean;
165
+ requiresApproval: boolean;
166
+ blocked: boolean;
167
+ executeTool: string;
168
+ effectiveInput: Record<string, unknown>;
169
+ autoFilledInput: Record<string, unknown>;
170
+ reasons: string[];
171
+ matchedParameterRule: ParameterPolicyRule | null;
172
+ violatedParameterRule: ParameterPolicyRule | null;
173
+ remediationForLlm: string;
174
+ nextToolCalls: Array<{
175
+ tool: string;
176
+ input: Record<string, unknown>;
177
+ when: string;
178
+ }>;
179
+ }
180
+ export declare function simulatePolicyEvaluation(params: {
181
+ policy?: GovernancePolicy | null;
182
+ toolSlug: string;
183
+ toolName?: string;
184
+ riskLevel?: RiskLevel;
185
+ creditCost?: number;
186
+ creditsBalance?: number;
187
+ lane?: string;
188
+ input?: Record<string, unknown>;
189
+ activeDefaults?: Record<string, unknown>;
190
+ }): PolicySimulationResult;
package/dist/policy.js CHANGED
@@ -239,6 +239,7 @@ export const DEFAULT_WORKSPACE_POLICY = {
239
239
  killSwitchReason: null,
240
240
  blockDestructiveSql: true,
241
241
  naturalLanguageRules: [],
242
+ parameterRules: [],
242
243
  languageMode: "hybrid",
243
244
  customInstructions: [],
244
245
  };
@@ -267,7 +268,22 @@ export function parseNaturalLanguageGuardrail(prompt, currentPolicy = DEFAULT_WO
267
268
  // Ignore invalid partial fields in optional patch
268
269
  }
269
270
  }
270
- const hasGuardrailIntent = /\b(don'?t\s+(?:go\s+over|spend|exceed|use|run|call|allow|provision|delete|drop|send|post)|never\s+(?:go\s+over|spend|exceed|use|run|call|allow|provision|delete|drop|send|post)|do\s+not\s+(?:go\s+over|spend|exceed|use|run|call|allow|provision|delete|drop|send|post)|cap\s+(?:budget|spend|credits)|budget\s+(?:cap|limit|under|below)|max(?:imum)?\s+\d+\s*credits|limit\s+(?:spend|budget|credits)|block\s+(?:tool|destructive|sql|provisioning|app\.|resource\.|instant\.|billing\.|refunds?|payments?|transfers?|emails?|messages?)|unblock\s+(?:all\s+)?tools|disable\s+(?:tool|provisioning|instant)|enable\s+provisioning|ask\s+(?:me\s+)?before|require\s+approval|auto[- ]?approve|only\s+(?:allow|send|post|permit)|restrict\s+(?:emails?|messages?|slack|github|refunds?)|read[- ]only\s+mode|sandbox\s+mode|strict\s+manual|hands[- ]off\s+mode|safe\s+default|monitor\s+mode|observation\s+mode|enforce\s+mode|execution\s+ring|ring\s+[0123]|non[- ]technical\s+(?:mode|language|explanations?)|technical\s+(?:mode|language|explanations?|detail)|plain\s+english|hybrid\s+(?:mode|language)|custom\s+instruction\s*:|always\s+(?:explain|show|include|format)|guardrail\s*:|rule\s*:|policy\s*:)/i.test(cleanPrompt);
271
+ const hasGuardrailIntent = /\b(don'?t\s+(?:go\s+over|spend|exceed|use|run|call|allow|provision|delete|drop|send|post)|never\s+(?:go\s+over|spend|exceed|use|run|call|allow|provision|delete|drop|send|post)|do\s+not\s+(?:go\s+over|spend|exceed|use|run|call|allow|provision|delete|drop|send|post)|cap\s+(?:budget|spend|credits)|budget\s+(?:cap|limit|under|below)|max(?:imum)?\s+\d+\s*credits|limit\s+(?:spend|budget|credits)|block\s+(?:tool|destructive|sql|provisioning|app\.|resource\.|instant\.|billing\.|refunds?|payments?|transfers?|emails?|messages?)|unblock\s+(?:all\s+)?tools|disable\s+(?:tool|provisioning|instant)|enable\s+provisioning|ask\s+(?:me\s+)?before|require\s+approval|auto[- ]?approve|only\s+(?:allow|send|post|permit)|restrict\s+(?:emails?|messages?|slack|github|refunds?)|read[- ]only\s+mode|sandbox\s+mode|strict\s+manual|hands[- ]off\s+mode|safe\s+default|monitor\s+mode|observation\s+mode|enforce\s+mode|execution\s+ring|ring\s+[0123]|non[- ]technical\s+(?:mode|language|explanations?)|technical\s+(?:mode|language|explanations?|detail)|plain\s+english|hybrid\s+(?:mode|language)|custom\s+instruction\s*:|always\s+(?:explain|show|include|format)|guardrail\s*:|rule\s*:|policy\s*:|(?:reset|clear|restore)\s+(?:all\s+)?(?:guardrails?|policy|safety\s+rules?))/i.test(cleanPrompt);
272
+ // 0. Full policy / guardrail reset ("reset guardrails", "clear all guardrails", "restore default policy")
273
+ if (/\b(reset|clear|restore)\s+(?:all\s+)?(?:custom\s+)?(?:guardrails?|policy|safety\s+rules?)(?:\s+to\s+defaults?)?\b/i.test(lower) &&
274
+ !/\bparameter\s+rules\b/i.test(lower)) {
275
+ patch.mode = DEFAULT_WORKSPACE_POLICY.mode;
276
+ patch.requireApprovalFor = [...DEFAULT_WORKSPACE_POLICY.requireApprovalFor];
277
+ patch.allowInstantWallet = DEFAULT_WORKSPACE_POLICY.allowInstantWallet;
278
+ patch.allowProvisioning = DEFAULT_WORKSPACE_POLICY.allowProvisioning;
279
+ patch.maxCreditsPerRun = DEFAULT_WORKSPACE_POLICY.maxCreditsPerRun;
280
+ patch.blockedToolSlugs = [];
281
+ patch.parameterRules = [];
282
+ patch.executionRing = DEFAULT_WORKSPACE_POLICY.executionRing;
283
+ patch.blockDestructiveSql = DEFAULT_WORKSPACE_POLICY.blockDestructiveSql;
284
+ patch.naturalLanguageRules = [];
285
+ appliedSummaries.push("Reset all workspace guardrails, parameter rules, and approval thresholds to Safe Default");
286
+ }
271
287
  // Detect whether a dollar amount in the sentence refers to a tool-specific transaction
272
288
  // (e.g. "Stripe refunds over $50", "payments over $100", "transfers above $250")
273
289
  // rather than the workspace's Muxo credit budget per run.
@@ -1190,3 +1206,392 @@ export function evaluateParameterPolicyRules(paramsOrToolSlug, maybeInput, maybe
1190
1206
  : null,
1191
1207
  };
1192
1208
  }
1209
+ export function describeParameterRuleCompliance(rule) {
1210
+ const paramLabel = rule.parameter.split(",")[0] || rule.parameter;
1211
+ const valStr = Array.isArray(rule.value)
1212
+ ? rule.value.join(", ")
1213
+ : String(rule.value);
1214
+ const unitSuffix = rule.unit && rule.unit !== "raw" ? ` ${rule.unit.toUpperCase()}` : "";
1215
+ const elseNote = rule.elseAction
1216
+ ? `; otherwise action is '${rule.elseAction}'`
1217
+ : "";
1218
+ switch (rule.operator) {
1219
+ case "must_end_with":
1220
+ case "ends_with":
1221
+ return `For tools matching '${rule.toolPattern}', parameter '${paramLabel}' must end with '${valStr}' (violation -> ${rule.action}${elseNote}).`;
1222
+ case "domain_in":
1223
+ return `For tools matching '${rule.toolPattern}', recipient domain in '${paramLabel}' must be in [${valStr}] (violation -> ${rule.action}${elseNote}).`;
1224
+ case "domain_not_in":
1225
+ return `For tools matching '${rule.toolPattern}', recipient domain in '${paramLabel}' must NOT be in [${valStr}] (violation -> ${rule.action}${elseNote}).`;
1226
+ case "max_number":
1227
+ case "gt":
1228
+ case "gte":
1229
+ return `For tools matching '${rule.toolPattern}', keep '${paramLabel}' <= ${valStr}${unitSuffix} (exceeding ${valStr}${unitSuffix} triggers '${rule.action}'${elseNote}).`;
1230
+ case "min_number":
1231
+ case "lt":
1232
+ case "lte":
1233
+ return `For tools matching '${rule.toolPattern}', keep '${paramLabel}' >= ${valStr}${unitSuffix} (below ${valStr}${unitSuffix} triggers '${rule.action}'${elseNote}).`;
1234
+ case "must_equal":
1235
+ case "equals":
1236
+ return `For tools matching '${rule.toolPattern}', parameter '${paramLabel}' must equal '${valStr}' (violation -> ${rule.action}${elseNote}).`;
1237
+ case "not_equals":
1238
+ return `For tools matching '${rule.toolPattern}', parameter '${paramLabel}' must NOT equal '${valStr}' (violation -> ${rule.action}${elseNote}).`;
1239
+ case "in":
1240
+ return `For tools matching '${rule.toolPattern}', parameter '${paramLabel}' must be one of [${valStr}] (violation -> ${rule.action}${elseNote}).`;
1241
+ case "not_in":
1242
+ return `For tools matching '${rule.toolPattern}', parameter '${paramLabel}' must NOT be in [${valStr}] (violation -> ${rule.action}${elseNote}).`;
1243
+ default:
1244
+ return `${rule.description} (toolPattern='${rule.toolPattern}', parameter='${rule.parameter}', operator='${rule.operator}', value=${JSON.stringify(rule.value)}, action='${rule.action}'${elseNote}).`;
1245
+ }
1246
+ }
1247
+ export function buildLlmPolicyAndGovernanceBrief(policy = DEFAULT_WORKSPACE_POLICY, options) {
1248
+ const plain = describePolicyInPlainEnglish(policy);
1249
+ const reqSet = new Set(policy.requireApprovalFor || []);
1250
+ const ring = (policy.executionRing ?? 1);
1251
+ const isPaused = Boolean(policy.killSwitchActive);
1252
+ const isReadOnly = ring === 3;
1253
+ const isMonitor = policy.mode === "monitor";
1254
+ const posture = isPaused
1255
+ ? "paused"
1256
+ : isReadOnly
1257
+ ? "read_only_sandbox"
1258
+ : isMonitor
1259
+ ? "monitor"
1260
+ : reqSet.has("read")
1261
+ ? "ask_every_time"
1262
+ : !reqSet.has("write")
1263
+ ? "hands_off"
1264
+ : "safe_default";
1265
+ const riskLaneMatrix = {};
1266
+ for (const risk of RISK_LEVELS) {
1267
+ const executeTool = `execute_${risk}`;
1268
+ if (isPaused && !isMonitor) {
1269
+ riskLaneMatrix[risk] = {
1270
+ riskLevel: risk,
1271
+ status: "blocked",
1272
+ executeTool,
1273
+ reason: `Blocked while workspace kill switch is active (${policy.killSwitchReason || "emergency pause"}).`,
1274
+ };
1275
+ }
1276
+ else if (isReadOnly && risk !== "read" && !isMonitor) {
1277
+ riskLaneMatrix[risk] = {
1278
+ riskLevel: risk,
1279
+ status: "blocked",
1280
+ executeTool,
1281
+ reason: "Blocked by Ring 3 Read-Only Sandbox mode (only 'read' tools are permitted).",
1282
+ };
1283
+ }
1284
+ else if (risk === "provisioning" && policy.allowProvisioning === false && !isMonitor) {
1285
+ riskLaneMatrix[risk] = {
1286
+ riskLevel: risk,
1287
+ status: "blocked",
1288
+ executeTool,
1289
+ reason: "Blocked because cloud infrastructure provisioning (allowProvisioning=false) is disabled.",
1290
+ };
1291
+ }
1292
+ else if (reqSet.has(risk) && !isMonitor) {
1293
+ riskLaneMatrix[risk] = {
1294
+ riskLevel: risk,
1295
+ status: "requires_approval",
1296
+ executeTool,
1297
+ reason: `Requires human owner approval before ${executeTool} can run (unless a conditional parameterRule explicitly sets elseAction='auto_approve').`,
1298
+ };
1299
+ }
1300
+ else {
1301
+ riskLaneMatrix[risk] = {
1302
+ riskLevel: risk,
1303
+ status: "auto_approved",
1304
+ executeTool,
1305
+ reason: isMonitor
1306
+ ? `Auto-approved in monitor mode; call ${executeTool} immediately after plan_action.`
1307
+ : `Auto-approved by workspace policy; call ${executeTool} immediately after plan_action.`,
1308
+ };
1309
+ }
1310
+ }
1311
+ const parameterRules = (policy.parameterRules || []).map((r) => ({
1312
+ ...r,
1313
+ howToComply: describeParameterRuleCompliance(r),
1314
+ }));
1315
+ const maxCredits = Number(policy.maxCreditsPerRun ?? 50);
1316
+ const maxUsd = Number((maxCredits * 0.01).toFixed(2));
1317
+ const activeDefaults = options?.activeDefaults || {};
1318
+ const defaultsPairs = Object.entries(activeDefaults).map(([k, v]) => `${k}=${JSON.stringify(v)}`);
1319
+ const autoApproveRiskLevels = RISK_LEVELS.filter((r) => riskLaneMatrix[r].status === "auto_approved");
1320
+ const requireApprovalRiskLevels = RISK_LEVELS.filter((r) => riskLaneMatrix[r].status === "requires_approval");
1321
+ const blockedLanes = RISK_LEVELS.filter((r) => riskLaneMatrix[r].status === "blocked");
1322
+ const directiveLines = [
1323
+ `## Muxo Policy & Governance Contract${options?.workspaceName ? ` (${options.workspaceName})` : ""}`,
1324
+ `- **Posture**: \`${posture}\` (mode=\`${policy.mode || "enforce"}\`, ring=\`Ring ${ring}\`, languageMode=\`${plain.languageMode}\`)`,
1325
+ `- **Summary**: ${plain.preferred}`,
1326
+ `- **Per-Run Budget Cap**: ${maxCredits} credits ($${maxUsd.toFixed(2)}) max per run`,
1327
+ `- **Auto-Approved Risk Lanes**: ${autoApproveRiskLevels.join(", ") || "none"}`,
1328
+ `- **Human-Approval Risk Lanes**: ${requireApprovalRiskLevels.join(", ") || "none"}`,
1329
+ ];
1330
+ if (blockedLanes.length > 0) {
1331
+ directiveLines.push(`- **Blocked Risk Lanes**: ${blockedLanes.join(", ")}`);
1332
+ }
1333
+ if (policy.blockedToolSlugs && policy.blockedToolSlugs.length > 0) {
1334
+ directiveLines.push(`- **Blocked Tools (Never Call)**: ${policy.blockedToolSlugs.join(", ")}`);
1335
+ }
1336
+ if (parameterRules.length > 0) {
1337
+ directiveLines.push(`- **Conditional Parameter Guardrails (${parameterRules.length})**:`);
1338
+ for (const pr of parameterRules) {
1339
+ directiveLines.push(` - \`${pr.id}\`: ${pr.howToComply}`);
1340
+ }
1341
+ }
1342
+ if (defaultsPairs.length > 0) {
1343
+ directiveLines.push(`- **Learned Memory Defaults (Auto-Filled on plan_action)**: ${defaultsPairs.join(", ")}`);
1344
+ }
1345
+ if (plain.customInstructions.length > 0) {
1346
+ directiveLines.push(`- **Operator Custom Instructions**: ${plain.customInstructions.join(" | ")}`);
1347
+ }
1348
+ return {
1349
+ ...(options?.workspaceId ? { workspaceId: options.workspaceId } : {}),
1350
+ posture,
1351
+ mode: (policy.mode || "enforce"),
1352
+ executionRing: ring,
1353
+ headline: plain.headline,
1354
+ preferredExplanation: plain.preferred,
1355
+ plainEnglish: plain,
1356
+ languageMode: plain.languageMode,
1357
+ customInstructions: plain.customInstructions,
1358
+ killSwitch: {
1359
+ active: isPaused,
1360
+ reason: policy.killSwitchReason || null,
1361
+ howToToggleMcp: {
1362
+ pause: {
1363
+ tool: "get_run_context",
1364
+ arguments: {
1365
+ action: "kill_switch",
1366
+ enabled: true,
1367
+ prompt: "Pause all agent executions",
1368
+ },
1369
+ },
1370
+ resume: {
1371
+ tool: "get_run_context",
1372
+ arguments: {
1373
+ action: "kill_switch",
1374
+ enabled: false,
1375
+ prompt: "Resume agent executions",
1376
+ },
1377
+ },
1378
+ },
1379
+ },
1380
+ budgetGuardrail: {
1381
+ maxCreditsPerRun: maxCredits,
1382
+ maxUsdPerRun: maxUsd,
1383
+ allowInstantWallet: policy.allowInstantWallet !== false,
1384
+ allowProvisioning: policy.allowProvisioning !== false,
1385
+ blockDestructiveSql: policy.blockDestructiveSql !== false,
1386
+ },
1387
+ riskLaneMatrix,
1388
+ autoApproveRiskLevels,
1389
+ requireApprovalRiskLevels,
1390
+ blockedRiskLevels: blockedLanes,
1391
+ blockedToolSlugs: policy.blockedToolSlugs || [],
1392
+ parameterRules,
1393
+ naturalLanguageRules: policy.naturalLanguageRules || [],
1394
+ activeDefaults,
1395
+ ...(options?.trustScore ? { trustScore: options.trustScore } : {}),
1396
+ ...(options?.agentDid ? { agentDid: options.agentDid } : {}),
1397
+ llmSystemDirective: directiveLines.join("\n"),
1398
+ agentControlCheatsheet: [
1399
+ {
1400
+ intent: "Inspect active policy, guardrails, and learned memory defaults",
1401
+ mcpTool: "get_run_context",
1402
+ arguments: { action: "governance_status" },
1403
+ },
1404
+ {
1405
+ intent: "Add or update a guardrail in plain English or structured parameter_rules",
1406
+ mcpTool: "get_run_context",
1407
+ arguments: {
1408
+ action: "set_guardrail",
1409
+ prompt: "Require approval for Stripe refunds over $50, auto-approve under $50",
1410
+ },
1411
+ },
1412
+ {
1413
+ intent: "Dry-run test if a tool + input will pass policy before creating a plan",
1414
+ mcpTool: "get_run_context",
1415
+ arguments: {
1416
+ action: "check_policy",
1417
+ tool_slug: "app.gmail.send_email",
1418
+ input: { to: "team@muxo.ai", subject: "Status" },
1419
+ },
1420
+ },
1421
+ {
1422
+ intent: "Reset custom guardrails and parameter rules back to Safe Default",
1423
+ mcpTool: "get_run_context",
1424
+ arguments: { action: "reset_guardrails" },
1425
+ },
1426
+ {
1427
+ intent: "Pause or resume workspace execution via the emergency kill switch",
1428
+ mcpTool: "get_run_context",
1429
+ arguments: { action: "kill_switch", enabled: false },
1430
+ },
1431
+ {
1432
+ intent: "Save a workspace fact or default parameter for automatic recall",
1433
+ mcpTool: "get_run_context",
1434
+ arguments: {
1435
+ action: "remember",
1436
+ prompt: "Remember our default GitHub repo is muxo-ai/muxo",
1437
+ },
1438
+ },
1439
+ ],
1440
+ };
1441
+ }
1442
+ export function simulatePolicyEvaluation(params) {
1443
+ const policy = {
1444
+ ...DEFAULT_WORKSPACE_POLICY,
1445
+ ...(params.policy || {}),
1446
+ };
1447
+ const toolSlug = String(params.toolSlug || "instant.web.search").trim();
1448
+ const riskLevel = params.riskLevel ||
1449
+ (toolSlug.startsWith("instant.")
1450
+ ? "read"
1451
+ : toolSlug.startsWith("resource.")
1452
+ ? "provisioning"
1453
+ : toolSlug.startsWith("billing.")
1454
+ ? "financial"
1455
+ : "write");
1456
+ const creditCost = Number(params.creditCost ?? (riskLevel === "read" ? 2 : 5));
1457
+ const rawInput = { ...(params.input || {}) };
1458
+ const defaults = params.activeDefaults || {};
1459
+ const effectiveInput = { ...rawInput };
1460
+ const autoFilledInput = {};
1461
+ for (const [k, v] of Object.entries(defaults)) {
1462
+ if (effectiveInput[k] === undefined && v !== undefined) {
1463
+ effectiveInput[k] = v;
1464
+ autoFilledInput[k] = v;
1465
+ }
1466
+ }
1467
+ const reasons = [];
1468
+ let decision = "auto_approved";
1469
+ const isMonitor = policy.mode === "monitor";
1470
+ if (policy.killSwitchActive && !isMonitor) {
1471
+ decision = "blocked";
1472
+ reasons.push(`Workspace kill switch is active (${policy.killSwitchReason || "emergency pause"}).`);
1473
+ }
1474
+ if (decision !== "blocked" &&
1475
+ (policy.blockedToolSlugs || []).some((s) => s.toLowerCase() === toolSlug.toLowerCase()) &&
1476
+ !isMonitor) {
1477
+ decision = "blocked";
1478
+ reasons.push(`Tool '${toolSlug}' is on the workspace blockedToolSlugs list.`);
1479
+ }
1480
+ if (decision !== "blocked" &&
1481
+ policy.executionRing === 3 &&
1482
+ riskLevel !== "read" &&
1483
+ !isMonitor) {
1484
+ decision = "blocked";
1485
+ reasons.push(`Workspace is in Ring 3 (Read-Only Sandbox mode), which blocks '${riskLevel}' tools.`);
1486
+ }
1487
+ if (decision !== "blocked" &&
1488
+ riskLevel === "provisioning" &&
1489
+ policy.allowProvisioning === false &&
1490
+ !isMonitor) {
1491
+ decision = "blocked";
1492
+ reasons.push("Cloud infrastructure provisioning is disabled (allowProvisioning=false).");
1493
+ }
1494
+ const maxCredits = Number(policy.maxCreditsPerRun ?? 50);
1495
+ if (decision !== "blocked" && creditCost > maxCredits && !isMonitor) {
1496
+ decision = "blocked";
1497
+ reasons.push(`Tool credit cost (${creditCost} cr) exceeds policy maxCreditsPerRun (${maxCredits} cr).`);
1498
+ }
1499
+ if (decision !== "blocked" &&
1500
+ typeof params.creditsBalance === "number" &&
1501
+ creditCost > params.creditsBalance) {
1502
+ decision = "blocked";
1503
+ reasons.push(`Insufficient workspace credits: tool requires ${creditCost} cr, balance is ${params.creditsBalance} cr.`);
1504
+ }
1505
+ const paramEval = evaluateParameterPolicyRules({
1506
+ policy,
1507
+ toolSlug,
1508
+ input: effectiveInput,
1509
+ });
1510
+ if (decision !== "blocked") {
1511
+ if (paramEval.violated && paramEval.action === "block" && !isMonitor) {
1512
+ decision = "blocked";
1513
+ reasons.push(paramEval.reason || "Blocked by conditional parameter guardrail.");
1514
+ }
1515
+ else if (paramEval.violated &&
1516
+ paramEval.action === "require_approval" &&
1517
+ !isMonitor) {
1518
+ decision = "pending_approval";
1519
+ reasons.push(paramEval.reason || "Parameter guardrail requires human owner approval.");
1520
+ }
1521
+ else if (paramEval.explicitAllow && paramEval.action === "auto_approve") {
1522
+ decision = "auto_approved";
1523
+ reasons.push(paramEval.reason ||
1524
+ "Auto-approved by conditional parameter guardrail (elseAction='auto_approve').");
1525
+ }
1526
+ else if ((policy.requireApprovalFor || []).includes(riskLevel) &&
1527
+ !isMonitor) {
1528
+ decision = "pending_approval";
1529
+ reasons.push(`Risk level '${riskLevel}' requires human owner approval under active workspace policy.`);
1530
+ }
1531
+ else {
1532
+ decision = "auto_approved";
1533
+ reasons.push(`Allowed and auto-approved under workspace policy (riskLevel='${riskLevel}', cost=${creditCost} cr <= ${maxCredits} cr).`);
1534
+ }
1535
+ }
1536
+ const executeTool = `execute_${riskLevel}`;
1537
+ let remediationForLlm = "";
1538
+ const nextToolCalls = [];
1539
+ if (decision === "auto_approved") {
1540
+ remediationForLlm = `Action will be auto_approved. Call plan_action({ tool_slug: '${toolSlug}', input: ${JSON.stringify(effectiveInput)} }) and then ${executeTool}.`;
1541
+ nextToolCalls.push({
1542
+ tool: "plan_action",
1543
+ input: {
1544
+ tool_slug: toolSlug,
1545
+ input: effectiveInput,
1546
+ reason: `Execute ${toolSlug}`,
1547
+ },
1548
+ when: "Ready to create an auto-approved plan",
1549
+ });
1550
+ }
1551
+ else if (decision === "pending_approval") {
1552
+ remediationForLlm = `Action is allowed to be planned but will enter 'pending_approval' (${reasons.join("; ")}). Call plan_action, share humanHandoff.url with the user, and call get_plan({ plan_id, wait_for_approval: true }).`;
1553
+ nextToolCalls.push({
1554
+ tool: "plan_action",
1555
+ input: {
1556
+ tool_slug: toolSlug,
1557
+ input: effectiveInput,
1558
+ reason: `Request approval for ${toolSlug}`,
1559
+ },
1560
+ when: "To generate the plan and human approval URL",
1561
+ });
1562
+ }
1563
+ else {
1564
+ const ruleHint = paramEval.violatedRule
1565
+ ? ` Adjust arguments to satisfy: ${describeParameterRuleCompliance(paramEval.violatedRule)}`
1566
+ : "";
1567
+ remediationForLlm = `Action is currently BLOCKED (${reasons.join("; ")}).${ruleHint} Or ask the user if they want to update the guardrail via get_run_context({ action: 'set_guardrail', prompt: '...' }).`;
1568
+ nextToolCalls.push({
1569
+ tool: "get_run_context",
1570
+ input: {
1571
+ action: "governance_status",
1572
+ },
1573
+ when: "To inspect active guardrails or adjust workspace policy with the user's permission",
1574
+ });
1575
+ }
1576
+ return {
1577
+ ok: true,
1578
+ action: "check_policy",
1579
+ toolSlug,
1580
+ ...(params.toolName ? { toolName: params.toolName } : {}),
1581
+ riskLevel,
1582
+ creditCost,
1583
+ decision,
1584
+ approvalStatus: decision,
1585
+ allowed: decision !== "blocked",
1586
+ requiresApproval: decision === "pending_approval",
1587
+ blocked: decision === "blocked",
1588
+ executeTool,
1589
+ effectiveInput,
1590
+ autoFilledInput,
1591
+ reasons,
1592
+ matchedParameterRule: paramEval.matchedRule,
1593
+ violatedParameterRule: paramEval.violatedRule,
1594
+ remediationForLlm,
1595
+ nextToolCalls,
1596
+ };
1597
+ }
@@ -265,7 +265,8 @@ export class ComposioInstantAdapter {
265
265
  const hasCustomerByok = Boolean((params.composioApiKey && params.composioApiKey.trim()) ||
266
266
  (params.exaApiKey && params.exaApiKey.trim()) ||
267
267
  (params.firecrawlApiKey && params.firecrawlApiKey.trim()));
268
- const activeComposioKey = params.composioApiKey || (isMasterWalletEmpty ? null : this.config.composioApiKey);
268
+ const activeComposioKey = params.composioApiKey ||
269
+ (isMasterWalletEmpty ? null : this.config.composioInstantApiKey || this.config.composioApiKey);
269
270
  const finalizeInstantResult = (res) => {
270
271
  if (isMasterWalletEmpty && !hasCustomerByok) {
271
272
  return {
@@ -377,12 +378,29 @@ export class ComposioInstantAdapter {
377
378
  new Promise((_, reject) => setTimeout(() => reject(new Error("Composio SDK instant timeout")), 8000)),
378
379
  ]);
379
380
  if (sdkRes && !sdkRes.error && sdkRes.successful !== false) {
381
+ const rawData = (sdkRes.data ?? sdkRes);
382
+ const citations = Array.isArray(rawData?.citations)
383
+ ? rawData.citations
384
+ : null;
385
+ const mappedResults = Array.isArray(rawData?.results)
386
+ ? rawData.results
387
+ : citations
388
+ ? citations.map((c) => ({
389
+ title: String(c.title || c.url || c.id || ""),
390
+ url: String(c.url || c.id || ""),
391
+ snippet: String(c.author || rawData.answer || ""),
392
+ source: "composio_instant",
393
+ }))
394
+ : undefined;
380
395
  return finalizeInstantResult({
381
396
  provider: "composio_instant",
382
397
  sdk: "@composio/core",
383
398
  billingMode: "provider_wallet",
384
399
  tool: tool.slug,
385
- data: sdkRes.data ?? sdkRes,
400
+ ...(input.query ? { query: String(input.query) } : {}),
401
+ ...(typeof rawData?.answer === "string" ? { answer: rawData.answer } : {}),
402
+ ...(mappedResults ? { results: mappedResults } : {}),
403
+ data: rawData,
386
404
  });
387
405
  }
388
406
  }
@@ -405,11 +423,28 @@ export class ComposioInstantAdapter {
405
423
  if (res.ok) {
406
424
  const payload = (await res.json());
407
425
  if (!payload.error) {
426
+ const rawData = (payload.data ?? payload);
427
+ const citations = Array.isArray(rawData?.citations)
428
+ ? rawData.citations
429
+ : null;
430
+ const mappedResults = Array.isArray(rawData?.results)
431
+ ? rawData.results
432
+ : citations
433
+ ? citations.map((c) => ({
434
+ title: String(c.title || c.url || c.id || ""),
435
+ url: String(c.url || c.id || ""),
436
+ snippet: String(c.author || rawData.answer || ""),
437
+ source: "composio_instant",
438
+ }))
439
+ : undefined;
408
440
  return finalizeInstantResult({
409
441
  provider: "composio_instant",
410
442
  billingMode: "provider_wallet",
411
443
  tool: tool.slug,
412
- data: payload.data ?? payload,
444
+ ...(input.query ? { query: String(input.query) } : {}),
445
+ ...(typeof rawData?.answer === "string" ? { answer: rawData.answer } : {}),
446
+ ...(mappedResults ? { results: mappedResults } : {}),
447
+ data: rawData,
413
448
  });
414
449
  }
415
450
  }