@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
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { Composio } from "@composio/core";
|
|
2
2
|
import type { MuxoConfig } from "../config.js";
|
|
3
3
|
import type { MuxoTool, RiskLevel } from "../types.js";
|
|
4
|
-
import { type ComposioToolkitMetadata, type ComposioTriggerEventRecord, type ComposioTriggerSubscription, type ComposioTriggerType } from "../composio-catalog.js";
|
|
5
|
-
export type { ComposioToolkitMetadata, ComposioTriggerEventRecord, ComposioTriggerSubscription };
|
|
4
|
+
import { parseComposioWebhookEnvelope, type ComposioToolkitMetadata, type ComposioTriggerEventRecord, type ComposioTriggerSubscription, type ComposioTriggerType, type ComposioWebhookEventType } from "../composio-catalog.js";
|
|
5
|
+
export type { ComposioToolkitMetadata, ComposioTriggerEventRecord, ComposioTriggerSubscription, ComposioTriggerType, ComposioWebhookEventType, };
|
|
6
6
|
export declare class ComposioSdkAdapter {
|
|
7
7
|
private readonly config;
|
|
8
8
|
private liveToolsCache;
|
|
@@ -26,6 +26,17 @@ export declare class ComposioSdkAdapter {
|
|
|
26
26
|
cachedToolCount: number;
|
|
27
27
|
capabilities: string[];
|
|
28
28
|
};
|
|
29
|
+
getWebhookConfigInfo(): {
|
|
30
|
+
webhookUrl: string;
|
|
31
|
+
legacyWebhookUrl: string;
|
|
32
|
+
version: "V3";
|
|
33
|
+
events: ComposioWebhookEventType[];
|
|
34
|
+
secretConfigured: boolean;
|
|
35
|
+
subscriptionId: string | null;
|
|
36
|
+
projectId: string | null;
|
|
37
|
+
orgId: string | null;
|
|
38
|
+
userId: string | null;
|
|
39
|
+
};
|
|
29
40
|
getCuratedTools(): MuxoTool[];
|
|
30
41
|
static classifyActionRisk(upstreamSlug: string, description?: string): RiskLevel;
|
|
31
42
|
listToolkits(params?: {
|
|
@@ -55,15 +66,61 @@ export declare class ComposioSdkAdapter {
|
|
|
55
66
|
source: "composio_v3_sdk" | "muxo_managed";
|
|
56
67
|
}>;
|
|
57
68
|
listTriggerTypes(providerSlug?: string): ComposioTriggerType[];
|
|
69
|
+
/**
|
|
70
|
+
* Check what configuration is required for a trigger (`composio.triggers.getType(slug)`).
|
|
71
|
+
*/
|
|
72
|
+
getTriggerType(triggerSlug: string, composioApiKey?: string | null): Promise<ComposioTriggerType & {
|
|
73
|
+
source: "composio_v3_sdk" | "muxo_trigger_catalog";
|
|
74
|
+
}>;
|
|
75
|
+
/**
|
|
76
|
+
* Create a trigger with required config (`composio.triggers.create(userId, slug, { triggerConfig })`)
|
|
77
|
+
* and optionally subscribe to real-time trigger events (`composio.triggers.subscribe`).
|
|
78
|
+
*/
|
|
58
79
|
enableTrigger(params: {
|
|
59
80
|
workspaceId: string;
|
|
81
|
+
userId?: string;
|
|
60
82
|
triggerSlug: string;
|
|
61
83
|
providerSlug: string;
|
|
62
84
|
connectedAccountId?: string;
|
|
63
85
|
webhookUrl?: string;
|
|
64
86
|
config?: Record<string, unknown>;
|
|
87
|
+
subscribe?: boolean;
|
|
65
88
|
composioApiKey?: string | null;
|
|
66
89
|
}): Promise<ComposioTriggerSubscription>;
|
|
90
|
+
/**
|
|
91
|
+
* Subscribe to real-time trigger events via `@composio/core` (`composio.triggers.subscribe`).
|
|
92
|
+
*/
|
|
93
|
+
subscribeToTriggerEvents(params: {
|
|
94
|
+
workspaceId: string;
|
|
95
|
+
triggerId?: string;
|
|
96
|
+
toolkits?: string[];
|
|
97
|
+
onEvent?: (data: Record<string, unknown>) => void;
|
|
98
|
+
composioApiKey?: string | null;
|
|
99
|
+
}): Promise<{
|
|
100
|
+
subscribed: boolean;
|
|
101
|
+
triggerId?: string;
|
|
102
|
+
}>;
|
|
103
|
+
/**
|
|
104
|
+
* Verify an incoming Composio webhook payload and HMAC-SHA256 signature.
|
|
105
|
+
*/
|
|
106
|
+
verifyWebhook(params: {
|
|
107
|
+
rawPayload: string;
|
|
108
|
+
signatureHeader?: string | null;
|
|
109
|
+
webhookIdHeader?: string | null;
|
|
110
|
+
webhookTimestampHeader?: string | null;
|
|
111
|
+
secret?: string | null;
|
|
112
|
+
toleranceSeconds?: number;
|
|
113
|
+
}): Promise<{
|
|
114
|
+
verified: boolean;
|
|
115
|
+
reason?: string;
|
|
116
|
+
envelope: ReturnType<typeof parseComposioWebhookEnvelope>;
|
|
117
|
+
}>;
|
|
118
|
+
disableTriggersMatching(params: {
|
|
119
|
+
workspaceId?: string;
|
|
120
|
+
triggerId?: string;
|
|
121
|
+
triggerSlug?: string;
|
|
122
|
+
connectedAccountId?: string;
|
|
123
|
+
}): number;
|
|
67
124
|
listActiveTriggers(workspaceId: string): ComposioTriggerSubscription[];
|
|
68
125
|
recordTriggerEvent(record: ComposioTriggerEventRecord): void;
|
|
69
126
|
listTriggerEvents(workspaceId: string, limit?: number): ComposioTriggerEventRecord[];
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Composio } from "@composio/core";
|
|
2
2
|
import { matchAppToolSlug } from "../mcp-schema.js";
|
|
3
|
-
import { composioAuthConfigScopes, ENTERPRISE_TOOLKITS_CATALOG, filterComposioToolkits, getSampleActionSchema, listComposioTriggerTypes, } from "../composio-catalog.js";
|
|
3
|
+
import { composioAuthConfigScopes, COMPOSIO_V3_WEBHOOK_EVENTS, ensureOAuthCallbackParams, ENTERPRISE_TOOLKITS_CATALOG, filterComposioToolkits, getComposioTriggerType, getSampleActionSchema, isStripeProjectsExclusiveProvider, listComposioTriggerTypes, parseComposioWebhookEnvelope, verifyComposioWebhookSignature, wrapMuxoConnectUrl, } from "../composio-catalog.js";
|
|
4
4
|
const CURATED_APP_TOOLS = [
|
|
5
5
|
{
|
|
6
6
|
slug: "app.github.list_repos",
|
|
@@ -404,13 +404,17 @@ export class ComposioSdkAdapter {
|
|
|
404
404
|
}
|
|
405
405
|
hydrateEnterpriseSampleActions() {
|
|
406
406
|
for (const tk of ENTERPRISE_TOOLKITS_CATALOG) {
|
|
407
|
+
if (isStripeProjectsExclusiveProvider(tk.slug))
|
|
408
|
+
continue;
|
|
407
409
|
for (const act of tk.sampleActions) {
|
|
410
|
+
if (act.muxoSlug.startsWith("resource."))
|
|
411
|
+
continue;
|
|
408
412
|
if (!this.liveToolsCache.has(act.muxoSlug)) {
|
|
409
413
|
this.liveToolsCache.set(act.muxoSlug, {
|
|
410
414
|
slug: act.muxoSlug,
|
|
411
415
|
upstreamSlug: act.upstreamSlug,
|
|
412
416
|
name: act.name,
|
|
413
|
-
description: `${tk.name}: ${act.name} (
|
|
417
|
+
description: `${tk.name}: ${act.name} (Muxo Connected Apps toolkit v${tk.pinnedVersion})`,
|
|
414
418
|
lane: "composio_sdk",
|
|
415
419
|
providerSlug: tk.slug,
|
|
416
420
|
providerName: tk.name,
|
|
@@ -483,9 +487,26 @@ export class ComposioSdkAdapter {
|
|
|
483
487
|
"connectedAccounts.get",
|
|
484
488
|
"connectedAccounts.list",
|
|
485
489
|
"authConfigs.list",
|
|
490
|
+
"triggers.getType",
|
|
491
|
+
"triggers.create",
|
|
492
|
+
"triggers.subscribe",
|
|
493
|
+
"triggers.verifyWebhook",
|
|
486
494
|
],
|
|
487
495
|
};
|
|
488
496
|
}
|
|
497
|
+
getWebhookConfigInfo() {
|
|
498
|
+
return {
|
|
499
|
+
webhookUrl: "https://api.muxo.ai/webhooks",
|
|
500
|
+
legacyWebhookUrl: "https://api.muxo.ai/api/v1/triggers/webhook",
|
|
501
|
+
version: "V3",
|
|
502
|
+
events: [...COMPOSIO_V3_WEBHOOK_EVENTS],
|
|
503
|
+
secretConfigured: Boolean(this.config.composioWebhookSecret),
|
|
504
|
+
subscriptionId: this.config.composioWebhookSubscriptionId || null,
|
|
505
|
+
projectId: this.config.composioProjectId || null,
|
|
506
|
+
orgId: this.config.composioOrgId || null,
|
|
507
|
+
userId: this.config.composioUserId || null,
|
|
508
|
+
};
|
|
509
|
+
}
|
|
489
510
|
getCuratedTools() {
|
|
490
511
|
return Array.from(this.liveToolsCache.values());
|
|
491
512
|
}
|
|
@@ -563,23 +584,194 @@ export class ComposioSdkAdapter {
|
|
|
563
584
|
listTriggerTypes(providerSlug) {
|
|
564
585
|
return listComposioTriggerTypes(providerSlug);
|
|
565
586
|
}
|
|
587
|
+
/**
|
|
588
|
+
* Check what configuration is required for a trigger (`composio.triggers.getType(slug)`).
|
|
589
|
+
*/
|
|
590
|
+
async getTriggerType(triggerSlug, composioApiKey) {
|
|
591
|
+
const normalizedSlug = String(triggerSlug || "GITHUB_COMMIT_EVENT")
|
|
592
|
+
.toUpperCase()
|
|
593
|
+
.trim();
|
|
594
|
+
const fallback = getComposioTriggerType(normalizedSlug);
|
|
595
|
+
const sdk = this.getComposioClient(composioApiKey);
|
|
596
|
+
if (sdk) {
|
|
597
|
+
try {
|
|
598
|
+
const triggerType = await Promise.race([
|
|
599
|
+
sdk.triggers.getType(normalizedSlug),
|
|
600
|
+
new Promise((_, reject) => setTimeout(() => reject(new Error("Composio SDK triggers.getType timeout")), 4500)),
|
|
601
|
+
]);
|
|
602
|
+
if (triggerType) {
|
|
603
|
+
const toolkitSlug = String(triggerType.toolkit?.slug || fallback.providerSlug).toLowerCase();
|
|
604
|
+
return {
|
|
605
|
+
slug: String(triggerType.slug || normalizedSlug),
|
|
606
|
+
providerSlug: toolkitSlug,
|
|
607
|
+
name: String(triggerType.name || fallback.name),
|
|
608
|
+
description: String(triggerType.description || fallback.description),
|
|
609
|
+
config: triggerType.config && typeof triggerType.config === "object"
|
|
610
|
+
? triggerType.config
|
|
611
|
+
: fallback.config,
|
|
612
|
+
source: "composio_v3_sdk",
|
|
613
|
+
};
|
|
614
|
+
}
|
|
615
|
+
}
|
|
616
|
+
catch {
|
|
617
|
+
// Fall back to Muxo trigger catalog when offline or unconfigured
|
|
618
|
+
}
|
|
619
|
+
}
|
|
620
|
+
return {
|
|
621
|
+
...fallback,
|
|
622
|
+
source: "muxo_trigger_catalog",
|
|
623
|
+
};
|
|
624
|
+
}
|
|
625
|
+
/**
|
|
626
|
+
* Create a trigger with required config (`composio.triggers.create(userId, slug, { triggerConfig })`)
|
|
627
|
+
* and optionally subscribe to real-time trigger events (`composio.triggers.subscribe`).
|
|
628
|
+
*/
|
|
566
629
|
async enableTrigger(params) {
|
|
567
|
-
const
|
|
630
|
+
const normalizedTriggerSlug = params.triggerSlug.toUpperCase().trim();
|
|
631
|
+
const triggerType = await this.getTriggerType(normalizedTriggerSlug, params.composioApiKey);
|
|
632
|
+
const providerSlug = (params.providerSlug ||
|
|
633
|
+
triggerType.providerSlug ||
|
|
634
|
+
"github")
|
|
635
|
+
.toLowerCase()
|
|
636
|
+
.trim();
|
|
637
|
+
const userId = params.userId || this.config.composioUserId || params.workspaceId;
|
|
638
|
+
const triggerConfig = params.config || {};
|
|
639
|
+
let upstreamTriggerId;
|
|
640
|
+
let source = "muxo_managed";
|
|
641
|
+
const sdk = this.getComposioClient(params.composioApiKey);
|
|
642
|
+
if (sdk) {
|
|
643
|
+
try {
|
|
644
|
+
const created = await Promise.race([
|
|
645
|
+
sdk.triggers.create(userId, normalizedTriggerSlug, {
|
|
646
|
+
...(params.connectedAccountId
|
|
647
|
+
? { connectedAccountId: params.connectedAccountId }
|
|
648
|
+
: {}),
|
|
649
|
+
triggerConfig,
|
|
650
|
+
}),
|
|
651
|
+
new Promise((_, reject) => setTimeout(() => reject(new Error("Composio SDK triggers.create timeout")), 6000)),
|
|
652
|
+
]);
|
|
653
|
+
if (created?.triggerId) {
|
|
654
|
+
upstreamTriggerId = String(created.triggerId);
|
|
655
|
+
source = "composio_v3_sdk";
|
|
656
|
+
if (params.subscribe) {
|
|
657
|
+
await this.subscribeToTriggerEvents({
|
|
658
|
+
workspaceId: params.workspaceId,
|
|
659
|
+
triggerId: upstreamTriggerId,
|
|
660
|
+
composioApiKey: params.composioApiKey,
|
|
661
|
+
}).catch(() => { });
|
|
662
|
+
}
|
|
663
|
+
}
|
|
664
|
+
}
|
|
665
|
+
catch {
|
|
666
|
+
// Fall through to deterministic local subscription record
|
|
667
|
+
}
|
|
668
|
+
}
|
|
669
|
+
const id = upstreamTriggerId ||
|
|
670
|
+
`trg_${providerSlug}_${Date.now()}_${Math.random().toString(36).slice(2, 7)}`;
|
|
568
671
|
const sub = {
|
|
569
672
|
id,
|
|
673
|
+
upstreamTriggerId,
|
|
570
674
|
workspaceId: params.workspaceId,
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
675
|
+
userId,
|
|
676
|
+
triggerSlug: normalizedTriggerSlug,
|
|
677
|
+
providerSlug,
|
|
678
|
+
connectedAccountId: params.connectedAccountId || `ca_${providerSlug}_${params.workspaceId.slice(0, 8)}`,
|
|
574
679
|
webhookUrl: params.webhookUrl ||
|
|
575
|
-
`https://api.muxo.ai/
|
|
576
|
-
config:
|
|
680
|
+
`https://api.muxo.ai/webhooks`,
|
|
681
|
+
config: triggerConfig,
|
|
577
682
|
status: "active",
|
|
683
|
+
source,
|
|
578
684
|
createdAt: new Date().toISOString(),
|
|
579
685
|
};
|
|
580
686
|
this.activeTriggers.set(id, sub);
|
|
581
687
|
return sub;
|
|
582
688
|
}
|
|
689
|
+
/**
|
|
690
|
+
* Subscribe to real-time trigger events via `@composio/core` (`composio.triggers.subscribe`).
|
|
691
|
+
*/
|
|
692
|
+
async subscribeToTriggerEvents(params) {
|
|
693
|
+
const sdk = this.getComposioClient(params.composioApiKey);
|
|
694
|
+
if (!sdk) {
|
|
695
|
+
return { subscribed: false, triggerId: params.triggerId };
|
|
696
|
+
}
|
|
697
|
+
await sdk.triggers.subscribe((data) => {
|
|
698
|
+
const recordPayload = (data?.payload || data || {});
|
|
699
|
+
const triggerSlug = String(data?.triggerSlug || "GITHUB_COMMIT_EVENT").toUpperCase();
|
|
700
|
+
const providerSlug = String(data?.toolkitSlug || triggerSlug.split("_")[0] || "github").toLowerCase();
|
|
701
|
+
this.recordTriggerEvent({
|
|
702
|
+
id: `trgevt_${Date.now()}_${Math.random().toString(36).slice(2, 7)}`,
|
|
703
|
+
workspaceId: params.workspaceId,
|
|
704
|
+
eventType: "composio.trigger.message",
|
|
705
|
+
webhookVersion: "V3",
|
|
706
|
+
triggerId: data?.id || params.triggerId,
|
|
707
|
+
triggerSlug,
|
|
708
|
+
providerSlug,
|
|
709
|
+
connectedAccountId: data?.metadata?.connectedAccount?.id,
|
|
710
|
+
userId: data?.userId || data?.metadata?.connectedAccount?.userId,
|
|
711
|
+
receivedAt: new Date().toISOString(),
|
|
712
|
+
promptInjectionScan: {
|
|
713
|
+
safe: true,
|
|
714
|
+
riskScore: 0,
|
|
715
|
+
findings: [],
|
|
716
|
+
},
|
|
717
|
+
disposition: "dispatched",
|
|
718
|
+
payloadPreview: recordPayload,
|
|
719
|
+
});
|
|
720
|
+
params.onEvent?.(data);
|
|
721
|
+
}, {
|
|
722
|
+
...(params.triggerId ? { triggerId: params.triggerId } : {}),
|
|
723
|
+
...(params.toolkits ? { toolkits: params.toolkits } : {}),
|
|
724
|
+
});
|
|
725
|
+
return { subscribed: true, triggerId: params.triggerId };
|
|
726
|
+
}
|
|
727
|
+
/**
|
|
728
|
+
* Verify an incoming Composio webhook payload and HMAC-SHA256 signature.
|
|
729
|
+
*/
|
|
730
|
+
async verifyWebhook(params) {
|
|
731
|
+
const secret = (params.secret ?? this.config.composioWebhookSecret ?? "").trim();
|
|
732
|
+
const sigCheck = await verifyComposioWebhookSignature({
|
|
733
|
+
rawPayload: params.rawPayload,
|
|
734
|
+
signatureHeader: params.signatureHeader,
|
|
735
|
+
webhookIdHeader: params.webhookIdHeader,
|
|
736
|
+
webhookTimestampHeader: params.webhookTimestampHeader,
|
|
737
|
+
secret,
|
|
738
|
+
toleranceSeconds: params.toleranceSeconds,
|
|
739
|
+
});
|
|
740
|
+
let parsedJson = {};
|
|
741
|
+
try {
|
|
742
|
+
parsedJson = JSON.parse(params.rawPayload || "{}");
|
|
743
|
+
}
|
|
744
|
+
catch {
|
|
745
|
+
parsedJson = {};
|
|
746
|
+
}
|
|
747
|
+
const envelope = parseComposioWebhookEnvelope(parsedJson, {
|
|
748
|
+
webhookId: params.webhookIdHeader,
|
|
749
|
+
webhookTimestamp: params.webhookTimestampHeader,
|
|
750
|
+
});
|
|
751
|
+
return {
|
|
752
|
+
verified: sigCheck.verified,
|
|
753
|
+
reason: sigCheck.reason,
|
|
754
|
+
envelope,
|
|
755
|
+
};
|
|
756
|
+
}
|
|
757
|
+
disableTriggersMatching(params) {
|
|
758
|
+
let count = 0;
|
|
759
|
+
for (const sub of this.activeTriggers.values()) {
|
|
760
|
+
if (params.workspaceId && sub.workspaceId !== params.workspaceId)
|
|
761
|
+
continue;
|
|
762
|
+
const matchesTriggerId = Boolean(params.triggerId) &&
|
|
763
|
+
(sub.id === params.triggerId || sub.upstreamTriggerId === params.triggerId);
|
|
764
|
+
const matchesConnectedAccount = Boolean(params.connectedAccountId) &&
|
|
765
|
+
sub.connectedAccountId === params.connectedAccountId;
|
|
766
|
+
const matchesSlug = Boolean(params.triggerSlug) &&
|
|
767
|
+
sub.triggerSlug.toUpperCase() === params.triggerSlug.toUpperCase();
|
|
768
|
+
if (matchesTriggerId || matchesConnectedAccount || matchesSlug) {
|
|
769
|
+
sub.status = "disabled";
|
|
770
|
+
count += 1;
|
|
771
|
+
}
|
|
772
|
+
}
|
|
773
|
+
return count;
|
|
774
|
+
}
|
|
583
775
|
listActiveTriggers(workspaceId) {
|
|
584
776
|
return Array.from(this.activeTriggers.values()).filter((t) => t.workspaceId === workspaceId);
|
|
585
777
|
}
|
|
@@ -601,6 +793,10 @@ export class ComposioSdkAdapter {
|
|
|
601
793
|
return null;
|
|
602
794
|
const toolkitObj = (item.toolkit || {});
|
|
603
795
|
const providerSlug = String(toolkitObj.slug || upstreamSlug.split("_")[0] || "app").toLowerCase();
|
|
796
|
+
// Never surface Stripe Projects cloud infrastructure providers as Composio OAuth tools
|
|
797
|
+
if (isStripeProjectsExclusiveProvider(providerSlug)) {
|
|
798
|
+
return null;
|
|
799
|
+
}
|
|
604
800
|
const providerName = String(toolkitObj.name || providerSlug.charAt(0).toUpperCase() + providerSlug.slice(1));
|
|
605
801
|
const actionPart = upstreamSlug
|
|
606
802
|
.toLowerCase()
|
|
@@ -617,7 +813,7 @@ export class ComposioSdkAdapter {
|
|
|
617
813
|
slug: muxoSlug,
|
|
618
814
|
upstreamSlug,
|
|
619
815
|
name: `${providerName}: ${String(item.name || actionPart)}`,
|
|
620
|
-
description: String(item.description || `Execute ${upstreamSlug} via
|
|
816
|
+
description: String(item.description || `Execute ${upstreamSlug} via Muxo Connected Apps`),
|
|
621
817
|
lane: "composio_sdk",
|
|
622
818
|
providerSlug,
|
|
623
819
|
providerName,
|
|
@@ -634,6 +830,10 @@ export class ComposioSdkAdapter {
|
|
|
634
830
|
async searchTools(query, limit = 15, composioApiKey, toolkit) {
|
|
635
831
|
const q = (query || "").trim().toLowerCase();
|
|
636
832
|
const tk = (toolkit || "").trim().toLowerCase();
|
|
833
|
+
// Stripe Projects infrastructure providers belong to stripe_projects lane, not Composio OAuth
|
|
834
|
+
if (tk && isStripeProjectsExclusiveProvider(tk)) {
|
|
835
|
+
return [];
|
|
836
|
+
}
|
|
637
837
|
const localMatches = this.getCuratedTools().filter((t) => {
|
|
638
838
|
if (tk && t.providerSlug.toLowerCase() !== tk)
|
|
639
839
|
return false;
|
|
@@ -716,6 +916,9 @@ export class ComposioSdkAdapter {
|
|
|
716
916
|
if (!normalizedSlug.startsWith("app.") || !apiKey)
|
|
717
917
|
return null;
|
|
718
918
|
const parts = normalizedSlug.split(".");
|
|
919
|
+
if (parts.length >= 2 && isStripeProjectsExclusiveProvider(parts[1] || "")) {
|
|
920
|
+
return null;
|
|
921
|
+
}
|
|
719
922
|
if (parts.length >= 3) {
|
|
720
923
|
const upstreamCandidate = parts.slice(1).join("_").toUpperCase();
|
|
721
924
|
const sdk = this.getComposioClient(composioApiKey);
|
|
@@ -743,8 +946,15 @@ export class ComposioSdkAdapter {
|
|
|
743
946
|
async startConnection(params) {
|
|
744
947
|
const providerSlug = params.providerSlug.toLowerCase().replace(/^app\./, "");
|
|
745
948
|
const providerName = providerSlug.charAt(0).toUpperCase() + providerSlug.slice(1);
|
|
746
|
-
const
|
|
949
|
+
const rawCallbackUrl = params.callbackUrl ||
|
|
747
950
|
`${this.config.baseUrl}/oauth/callback?workspace_id=${encodeURIComponent(params.workspaceId)}&provider=${encodeURIComponent(providerSlug)}`;
|
|
951
|
+
const callbackUrl = ensureOAuthCallbackParams(rawCallbackUrl, params.workspaceId, providerSlug);
|
|
952
|
+
const wrapRedirect = (url, externalAccountId) => wrapMuxoConnectUrl(url, this.config.baseUrl, {
|
|
953
|
+
workspaceId: params.workspaceId,
|
|
954
|
+
providerSlug,
|
|
955
|
+
callbackUrl,
|
|
956
|
+
externalAccountId: externalAccountId || null,
|
|
957
|
+
});
|
|
748
958
|
const apiKey = this.resolveApiKey(params.composioApiKey);
|
|
749
959
|
if (!apiKey) {
|
|
750
960
|
const externalAccountId = `ca_ext_${providerSlug}_${params.workspaceId.slice(-8)}`;
|
|
@@ -758,7 +968,52 @@ export class ComposioSdkAdapter {
|
|
|
758
968
|
message: `Open the authorization URL to connect ${providerName} to your Muxo workspace.`,
|
|
759
969
|
};
|
|
760
970
|
}
|
|
761
|
-
// 1.
|
|
971
|
+
// 1. Try creating a Tool Router Session & link for the workspace user (supports expected_input_fields + callback_url)
|
|
972
|
+
try {
|
|
973
|
+
const sessionRes = await fetch(`${this.config.composioBaseUrl}/tool_router/session`, {
|
|
974
|
+
method: "POST",
|
|
975
|
+
headers: this.getHeaders(params.composioApiKey),
|
|
976
|
+
body: JSON.stringify({
|
|
977
|
+
user_id: params.workspaceId,
|
|
978
|
+
toolkits: { enable: [providerSlug] },
|
|
979
|
+
}),
|
|
980
|
+
signal: AbortSignal.timeout(8000),
|
|
981
|
+
});
|
|
982
|
+
if (sessionRes.ok) {
|
|
983
|
+
const sessionData = (await sessionRes.json());
|
|
984
|
+
const sessionId = sessionData.session_id;
|
|
985
|
+
if (sessionId) {
|
|
986
|
+
const linkRes = await fetch(`${this.config.composioBaseUrl}/tool_router/session/${sessionId}/link`, {
|
|
987
|
+
method: "POST",
|
|
988
|
+
headers: this.getHeaders(params.composioApiKey),
|
|
989
|
+
body: JSON.stringify({
|
|
990
|
+
toolkit: providerSlug,
|
|
991
|
+
callback_url: callbackUrl,
|
|
992
|
+
}),
|
|
993
|
+
signal: AbortSignal.timeout(8000),
|
|
994
|
+
});
|
|
995
|
+
if (linkRes.ok) {
|
|
996
|
+
const linkData = (await linkRes.json());
|
|
997
|
+
if (linkData.redirect_url) {
|
|
998
|
+
const extId = linkData.connected_account_id || sessionId;
|
|
999
|
+
return {
|
|
1000
|
+
providerSlug,
|
|
1001
|
+
providerName,
|
|
1002
|
+
status: "pending",
|
|
1003
|
+
redirectUrl: wrapRedirect(linkData.redirect_url, extId),
|
|
1004
|
+
callbackUrl,
|
|
1005
|
+
externalAccountId: extId,
|
|
1006
|
+
message: `Open the authorization URL to connect ${providerName} to your Muxo workspace.`,
|
|
1007
|
+
};
|
|
1008
|
+
}
|
|
1009
|
+
}
|
|
1010
|
+
}
|
|
1011
|
+
}
|
|
1012
|
+
}
|
|
1013
|
+
catch {
|
|
1014
|
+
// Fall through to @composio/core SDK / connected_accounts flow
|
|
1015
|
+
}
|
|
1016
|
+
// 2. Official @composio/core SDK Connected Accounts initiation fallback
|
|
762
1017
|
const sdk = this.getComposioClient(params.composioApiKey);
|
|
763
1018
|
if (sdk) {
|
|
764
1019
|
try {
|
|
@@ -776,10 +1031,11 @@ export class ComposioSdkAdapter {
|
|
|
776
1031
|
new Promise((_, reject) => setTimeout(() => reject(new Error("Composio SDK initiate timeout")), 6000)),
|
|
777
1032
|
]);
|
|
778
1033
|
const externalAccountId = connRequest?.id || null;
|
|
779
|
-
const
|
|
1034
|
+
const rawRedirectUrl = connRequest?.redirectUrl ||
|
|
780
1035
|
(externalAccountId
|
|
781
1036
|
? `${callbackUrl}&connected_account_id=${encodeURIComponent(externalAccountId)}`
|
|
782
1037
|
: null);
|
|
1038
|
+
const redirectUrl = wrapRedirect(rawRedirectUrl, externalAccountId);
|
|
783
1039
|
if (redirectUrl) {
|
|
784
1040
|
return {
|
|
785
1041
|
providerSlug,
|
|
@@ -798,10 +1054,11 @@ export class ComposioSdkAdapter {
|
|
|
798
1054
|
new Promise((_, reject) => setTimeout(() => reject(new Error("Composio SDK toolkits.authorize timeout")), 6000)),
|
|
799
1055
|
]);
|
|
800
1056
|
const externalAccountId = authReq?.id || null;
|
|
801
|
-
const
|
|
1057
|
+
const rawRedirectUrl = authReq?.redirectUrl ||
|
|
802
1058
|
(externalAccountId
|
|
803
1059
|
? `${callbackUrl}&connected_account_id=${encodeURIComponent(externalAccountId)}`
|
|
804
1060
|
: null);
|
|
1061
|
+
const redirectUrl = wrapRedirect(rawRedirectUrl, externalAccountId);
|
|
805
1062
|
if (redirectUrl) {
|
|
806
1063
|
return {
|
|
807
1064
|
providerSlug,
|
|
@@ -816,53 +1073,9 @@ export class ComposioSdkAdapter {
|
|
|
816
1073
|
}
|
|
817
1074
|
}
|
|
818
1075
|
catch {
|
|
819
|
-
// Fall through to
|
|
1076
|
+
// Fall through to v3 API fallback
|
|
820
1077
|
}
|
|
821
1078
|
}
|
|
822
|
-
// 2. Try creating a Composio Tool Router Session & link for the workspace user
|
|
823
|
-
try {
|
|
824
|
-
const sessionRes = await fetch(`${this.config.composioBaseUrl}/tool_router/session`, {
|
|
825
|
-
method: "POST",
|
|
826
|
-
headers: this.getHeaders(params.composioApiKey),
|
|
827
|
-
body: JSON.stringify({
|
|
828
|
-
user_id: params.workspaceId,
|
|
829
|
-
toolkits: { enable: [providerSlug] },
|
|
830
|
-
}),
|
|
831
|
-
signal: AbortSignal.timeout(8000),
|
|
832
|
-
});
|
|
833
|
-
if (sessionRes.ok) {
|
|
834
|
-
const sessionData = (await sessionRes.json());
|
|
835
|
-
const sessionId = sessionData.session_id;
|
|
836
|
-
if (sessionId) {
|
|
837
|
-
const linkRes = await fetch(`${this.config.composioBaseUrl}/tool_router/session/${sessionId}/link`, {
|
|
838
|
-
method: "POST",
|
|
839
|
-
headers: this.getHeaders(params.composioApiKey),
|
|
840
|
-
body: JSON.stringify({
|
|
841
|
-
toolkit: providerSlug,
|
|
842
|
-
callback_url: callbackUrl,
|
|
843
|
-
}),
|
|
844
|
-
signal: AbortSignal.timeout(8000),
|
|
845
|
-
});
|
|
846
|
-
if (linkRes.ok) {
|
|
847
|
-
const linkData = (await linkRes.json());
|
|
848
|
-
if (linkData.redirect_url) {
|
|
849
|
-
return {
|
|
850
|
-
providerSlug,
|
|
851
|
-
providerName,
|
|
852
|
-
status: "pending",
|
|
853
|
-
redirectUrl: linkData.redirect_url,
|
|
854
|
-
callbackUrl,
|
|
855
|
-
externalAccountId: linkData.connected_account_id || sessionId,
|
|
856
|
-
message: `Open the authorization URL to connect ${providerName} to your Muxo workspace.`,
|
|
857
|
-
};
|
|
858
|
-
}
|
|
859
|
-
}
|
|
860
|
-
}
|
|
861
|
-
}
|
|
862
|
-
}
|
|
863
|
-
catch {
|
|
864
|
-
// Fall through to auth_configs / connected_accounts flow
|
|
865
|
-
}
|
|
866
1079
|
// 3. Fallback: look up or create an auth_config for the toolkit and initiate connected_accounts
|
|
867
1080
|
const authCfgRes = await fetch(`${this.config.composioBaseUrl}/auth_configs?toolkit_slug=${encodeURIComponent(providerSlug)}&limit=5`, {
|
|
868
1081
|
headers: this.getHeaders(params.composioApiKey),
|
|
@@ -887,9 +1100,10 @@ export class ComposioSdkAdapter {
|
|
|
887
1100
|
if (connRes.ok) {
|
|
888
1101
|
const connData = (await connRes.json());
|
|
889
1102
|
const fallbackRedirect = `${callbackUrl}&connected_account_id=${encodeURIComponent(connData.id || `ca_${providerSlug}`)}`;
|
|
890
|
-
const
|
|
1103
|
+
const rawRedirectUrl = connData.redirect_url ||
|
|
891
1104
|
connData.connectionData?.val?.redirectUrl ||
|
|
892
1105
|
fallbackRedirect;
|
|
1106
|
+
const redirectUrl = wrapRedirect(rawRedirectUrl, connData.id || null);
|
|
893
1107
|
return {
|
|
894
1108
|
providerSlug,
|
|
895
1109
|
providerName,
|
|
@@ -225,9 +225,13 @@ export declare class StripeProjectsAdapter {
|
|
|
225
225
|
getTools(): MuxoTool[];
|
|
226
226
|
searchTools(query?: string, limit?: number): MuxoTool[];
|
|
227
227
|
inspectTool(slug: string): MuxoTool | null;
|
|
228
|
+
hasProvider(providerSlug: string): boolean;
|
|
228
229
|
private runStripeProjectsCli;
|
|
229
230
|
private get hasLocalProjectsWorkdir();
|
|
230
231
|
private provisioningAuditLog;
|
|
232
|
+
private hostedSites;
|
|
233
|
+
getHostedSiteHtml(slug: string, filePath?: string): string | null;
|
|
234
|
+
private attachHostingDeployment;
|
|
231
235
|
getProvisioningAuditLog(limit?: number): StripeProvisioningAuditEntry[];
|
|
232
236
|
private resolveStripeSecretKey;
|
|
233
237
|
isLivemodeKey(apiKeyOverride?: string | null): boolean;
|