apteva 0.4.57 → 0.7.1
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 +216 -54
- package/cli.js +35 -0
- package/install.js +92 -0
- package/package.json +15 -76
- package/LICENSE +0 -63
- package/bin/apteva.js +0 -196
- package/dist/ActivityPage.kxzzb4yc.js +0 -3
- package/dist/ApiDocsPage.zq998hbm.js +0 -4
- package/dist/App.55rea8mn.js +0 -61
- package/dist/App.5ywb23z4.js +0 -53
- package/dist/App.6thds120.js +0 -4
- package/dist/App.9tctxzqm.js +0 -8
- package/dist/App.a8r8ttaz.js +0 -4
- package/dist/App.agsv5bje.js +0 -4
- package/dist/App.cepapqmx.js +0 -4
- package/dist/App.dp041gb3.js +0 -221
- package/dist/App.fds72zb5.js +0 -4
- package/dist/App.fg9qj2dq.js +0 -4
- package/dist/App.ndfejbm9.js +0 -4
- package/dist/App.nxmfmq1h.js +0 -13
- package/dist/App.qdfyt8ba.js +0 -4
- package/dist/App.x2d0ygt6.js +0 -4
- package/dist/App.yt9p4nr3.js +0 -20
- package/dist/App.zn4mw16t.js +0 -1
- package/dist/ConnectionsPage.8r96ryw7.js +0 -3
- package/dist/McpPage.3cwh0gnd.js +0 -3
- package/dist/SettingsPage.ykgdh5ev.js +0 -3
- package/dist/SkillsPage.4np1s65b.js +0 -3
- package/dist/TasksPage.4g08t7p6.js +0 -3
- package/dist/TelemetryPage.72w9pwcp.js +0 -3
- package/dist/TestsPage.z4fk3r7r.js +0 -3
- package/dist/ThreadsPage.63tcajeh.js +0 -3
- package/dist/apteva-kit.css +0 -1
- package/dist/icon.png +0 -0
- package/dist/index.html +0 -16
- package/dist/styles.css +0 -1
- package/scripts/postinstall.mjs +0 -102
- package/src/auth/index.ts +0 -394
- package/src/auth/middleware.ts +0 -213
- package/src/binary.ts +0 -536
- package/src/channels/index.ts +0 -40
- package/src/channels/telegram.ts +0 -311
- package/src/crypto.ts +0 -301
- package/src/db-tests.ts +0 -174
- package/src/db.ts +0 -3133
- package/src/integrations/agentdojo.ts +0 -559
- package/src/integrations/composio.ts +0 -437
- package/src/integrations/index.ts +0 -87
- package/src/integrations/skillsmp.ts +0 -318
- package/src/mcp-client.ts +0 -605
- package/src/mcp-handler.ts +0 -394
- package/src/mcp-platform.ts +0 -2403
- package/src/openapi.ts +0 -2410
- package/src/providers.ts +0 -597
- package/src/routes/api/agent-utils.ts +0 -890
- package/src/routes/api/agents.ts +0 -916
- package/src/routes/api/api-keys.ts +0 -95
- package/src/routes/api/channels.ts +0 -182
- package/src/routes/api/helpers.ts +0 -12
- package/src/routes/api/integrations.ts +0 -639
- package/src/routes/api/mcp.ts +0 -574
- package/src/routes/api/meta-agent.ts +0 -195
- package/src/routes/api/projects.ts +0 -112
- package/src/routes/api/providers.ts +0 -424
- package/src/routes/api/skills.ts +0 -537
- package/src/routes/api/system.ts +0 -333
- package/src/routes/api/telemetry.ts +0 -203
- package/src/routes/api/tests.ts +0 -148
- package/src/routes/api/triggers.ts +0 -518
- package/src/routes/api/users.ts +0 -148
- package/src/routes/api/webhooks.ts +0 -171
- package/src/routes/api.ts +0 -53
- package/src/routes/auth.ts +0 -251
- package/src/routes/share.ts +0 -86
- package/src/routes/static.ts +0 -131
- package/src/server.ts +0 -642
- package/src/test-runner.ts +0 -598
- package/src/triggers/agentdojo.ts +0 -253
- package/src/triggers/composio.ts +0 -264
- package/src/triggers/index.ts +0 -71
- package/src/tui/AgentList.tsx +0 -145
- package/src/tui/App.tsx +0 -102
- package/src/tui/Login.tsx +0 -104
- package/src/tui/api.ts +0 -72
- package/src/tui/index.tsx +0 -7
- package/src/web/App.tsx +0 -455
- package/src/web/components/activity/ActivityPage.tsx +0 -314
- package/src/web/components/activity/index.ts +0 -1
- package/src/web/components/agents/AgentCard.tsx +0 -189
- package/src/web/components/agents/AgentPanel.tsx +0 -2244
- package/src/web/components/agents/AgentsView.tsx +0 -180
- package/src/web/components/agents/CreateAgentModal.tsx +0 -475
- package/src/web/components/agents/index.ts +0 -4
- package/src/web/components/api/ApiDocsPage.tsx +0 -842
- package/src/web/components/auth/CreateAccountStep.tsx +0 -176
- package/src/web/components/auth/LoginPage.tsx +0 -91
- package/src/web/components/auth/index.ts +0 -2
- package/src/web/components/common/Icons.tsx +0 -250
- package/src/web/components/common/LoadingSpinner.tsx +0 -44
- package/src/web/components/common/Modal.tsx +0 -199
- package/src/web/components/common/Select.tsx +0 -97
- package/src/web/components/common/index.ts +0 -20
- package/src/web/components/connections/ConnectionsPage.tsx +0 -54
- package/src/web/components/connections/IntegrationsTab.tsx +0 -170
- package/src/web/components/connections/OverviewTab.tsx +0 -137
- package/src/web/components/connections/TriggersTab.tsx +0 -1346
- package/src/web/components/dashboard/Dashboard.tsx +0 -572
- package/src/web/components/dashboard/index.ts +0 -1
- package/src/web/components/index.ts +0 -21
- package/src/web/components/layout/ErrorBanner.tsx +0 -18
- package/src/web/components/layout/Header.tsx +0 -332
- package/src/web/components/layout/Sidebar.tsx +0 -231
- package/src/web/components/layout/index.ts +0 -3
- package/src/web/components/mcp/IntegrationsPanel.tsx +0 -857
- package/src/web/components/mcp/McpPage.tsx +0 -2515
- package/src/web/components/mcp/index.ts +0 -1
- package/src/web/components/meta-agent/MetaAgent.tsx +0 -245
- package/src/web/components/onboarding/OnboardingWizard.tsx +0 -404
- package/src/web/components/onboarding/index.ts +0 -1
- package/src/web/components/settings/SettingsPage.tsx +0 -2776
- package/src/web/components/settings/index.ts +0 -1
- package/src/web/components/skills/SkillsPage.tsx +0 -1200
- package/src/web/components/tasks/TasksPage.tsx +0 -1116
- package/src/web/components/tasks/index.ts +0 -1
- package/src/web/components/telemetry/TelemetryPage.tsx +0 -1129
- package/src/web/components/tests/TestsPage.tsx +0 -594
- package/src/web/components/threads/ThreadsPage.tsx +0 -315
- package/src/web/context/AuthContext.tsx +0 -242
- package/src/web/context/ProjectContext.tsx +0 -214
- package/src/web/context/TelemetryContext.tsx +0 -299
- package/src/web/context/ThemeContext.tsx +0 -90
- package/src/web/context/UIModeContext.tsx +0 -49
- package/src/web/context/index.ts +0 -12
- package/src/web/hooks/index.ts +0 -3
- package/src/web/hooks/useAgents.ts +0 -115
- package/src/web/hooks/useOnboarding.ts +0 -20
- package/src/web/hooks/useProviders.ts +0 -75
- package/src/web/icon.png +0 -0
- package/src/web/index.html +0 -16
- package/src/web/styles.css +0 -118
- package/src/web/themes.ts +0 -162
- package/src/web/types.ts +0 -298
|
@@ -1,253 +0,0 @@
|
|
|
1
|
-
// AgentDojo Trigger Provider
|
|
2
|
-
// Uses our MCP API's subscription and trigger system
|
|
3
|
-
// Docs: POST /subscribe, GET /subscriptions, GET /triggers
|
|
4
|
-
|
|
5
|
-
import { createHmac, timingSafeEqual } from "crypto";
|
|
6
|
-
import type { TriggerProvider, TriggerType, TriggerInstance } from "./index";
|
|
7
|
-
|
|
8
|
-
const AGENTDOJO_API_BASE = process.env.AGENTDOJO_API_BASE || "https://api.agentdojo.dev";
|
|
9
|
-
|
|
10
|
-
function headers(apiKey: string) {
|
|
11
|
-
return { "X-API-Key": apiKey, "Content-Type": "application/json" };
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
export const AgentDojoTriggerProvider: TriggerProvider = {
|
|
15
|
-
id: "agentdojo",
|
|
16
|
-
name: "AgentDojo",
|
|
17
|
-
|
|
18
|
-
async listTriggerTypes(apiKey: string, toolkitSlugs?: string[]): Promise<TriggerType[]> {
|
|
19
|
-
const params = new URLSearchParams({ is_active: "true", limit: "500" });
|
|
20
|
-
if (toolkitSlugs?.length) {
|
|
21
|
-
// Filter by toolkit name(s) — API supports one at a time, so fetch each
|
|
22
|
-
const allItems: any[] = [];
|
|
23
|
-
for (const slug of toolkitSlugs) {
|
|
24
|
-
const res = await fetch(
|
|
25
|
-
`${AGENTDOJO_API_BASE}/triggers?${new URLSearchParams({ toolkit_name: slug, is_active: "true", limit: "500" })}`,
|
|
26
|
-
{ headers: headers(apiKey) },
|
|
27
|
-
);
|
|
28
|
-
if (res.ok) {
|
|
29
|
-
const data = await res.json();
|
|
30
|
-
const items = data.data || data.triggers || [];
|
|
31
|
-
allItems.push(...items);
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
return mapTriggerTypes(allItems);
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
const res = await fetch(`${AGENTDOJO_API_BASE}/triggers?${params}`, {
|
|
38
|
-
headers: headers(apiKey),
|
|
39
|
-
});
|
|
40
|
-
|
|
41
|
-
if (!res.ok) {
|
|
42
|
-
console.error("AgentDojo listTriggerTypes error:", res.status, await res.text());
|
|
43
|
-
return [];
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
const data = await res.json();
|
|
47
|
-
const items = data.data || data.triggers || [];
|
|
48
|
-
return mapTriggerTypes(items);
|
|
49
|
-
},
|
|
50
|
-
|
|
51
|
-
async getTriggerType(apiKey: string, slug: string): Promise<TriggerType | null> {
|
|
52
|
-
const res = await fetch(
|
|
53
|
-
`${AGENTDOJO_API_BASE}/triggers/${encodeURIComponent(slug)}`,
|
|
54
|
-
{ headers: headers(apiKey) },
|
|
55
|
-
);
|
|
56
|
-
|
|
57
|
-
if (!res.ok) {
|
|
58
|
-
if (res.status === 404) return null;
|
|
59
|
-
console.error("AgentDojo getTriggerType error:", res.status, await res.text());
|
|
60
|
-
return null;
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
const data = await res.json();
|
|
64
|
-
const item = data.data || data;
|
|
65
|
-
return {
|
|
66
|
-
slug: item.slug,
|
|
67
|
-
name: item.display_name || item.event_name || item.slug,
|
|
68
|
-
description: item.description || "",
|
|
69
|
-
type: (item.mechanism as "webhook" | "poll") || "webhook",
|
|
70
|
-
toolkit_slug: item.toolkit?.name || item.toolkit_name || "",
|
|
71
|
-
toolkit_name: item.toolkit?.display_name || item.toolkit_display_name || "",
|
|
72
|
-
logo: item.toolkit?.icon_url || null,
|
|
73
|
-
config_schema: item.config_schema || {},
|
|
74
|
-
payload_schema: item.payload_schema || {},
|
|
75
|
-
};
|
|
76
|
-
},
|
|
77
|
-
|
|
78
|
-
async createTrigger(
|
|
79
|
-
apiKey: string,
|
|
80
|
-
slug: string,
|
|
81
|
-
connectedAccountId: string,
|
|
82
|
-
config?: Record<string, unknown>,
|
|
83
|
-
): Promise<{ triggerId: string }> {
|
|
84
|
-
// AgentDojo uses subscriptions — we create a subscription for this trigger
|
|
85
|
-
// The callback_url should be set in config or from stored webhook URL
|
|
86
|
-
const callbackUrl = (config?.callback_url as string) || "";
|
|
87
|
-
if (!callbackUrl) {
|
|
88
|
-
throw new Error("callback_url is required in config for AgentDojo triggers");
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
// Separate known top-level fields from extra config (e.g. owner, repo for GitHub)
|
|
92
|
-
const { callback_url, title, events, server, prompt, agent_id, ...extraConfig } = config || {} as Record<string, unknown>;
|
|
93
|
-
|
|
94
|
-
const body: Record<string, unknown> = {
|
|
95
|
-
trigger_type_slug: slug,
|
|
96
|
-
credential_id: connectedAccountId,
|
|
97
|
-
callback_url: callbackUrl,
|
|
98
|
-
title: (title as string) || `Trigger: ${slug}`,
|
|
99
|
-
};
|
|
100
|
-
|
|
101
|
-
if (events) body.events = events;
|
|
102
|
-
if (server) body.server = server;
|
|
103
|
-
if (prompt) body.prompt = prompt;
|
|
104
|
-
if (agent_id) body.agent_id = agent_id;
|
|
105
|
-
|
|
106
|
-
// Pass extra config fields (owner, repo, etc.) as the config object
|
|
107
|
-
// mcp-subscribe spreads this into the webhook register payload
|
|
108
|
-
if (Object.keys(extraConfig).length > 0) {
|
|
109
|
-
body.config = extraConfig;
|
|
110
|
-
console.log("AgentDojo createTrigger: extra config:", JSON.stringify(extraConfig));
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
const res = await fetch(`${AGENTDOJO_API_BASE}/subscribe`, {
|
|
114
|
-
method: "POST",
|
|
115
|
-
headers: headers(apiKey),
|
|
116
|
-
body: JSON.stringify(body),
|
|
117
|
-
});
|
|
118
|
-
|
|
119
|
-
if (!res.ok) {
|
|
120
|
-
const errText = await res.text();
|
|
121
|
-
console.error("AgentDojo createTrigger error:", res.status, errText);
|
|
122
|
-
throw new Error(`Failed to create AgentDojo subscription: ${errText}`);
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
const data = await res.json();
|
|
126
|
-
return { triggerId: String(data.subscription_id || data.id) };
|
|
127
|
-
},
|
|
128
|
-
|
|
129
|
-
async listTriggers(apiKey: string): Promise<TriggerInstance[]> {
|
|
130
|
-
const res = await fetch(`${AGENTDOJO_API_BASE}/subscriptions?status=active`, {
|
|
131
|
-
headers: headers(apiKey),
|
|
132
|
-
});
|
|
133
|
-
|
|
134
|
-
if (!res.ok) {
|
|
135
|
-
console.error("AgentDojo listTriggers error:", res.status, await res.text());
|
|
136
|
-
return [];
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
const data = await res.json();
|
|
140
|
-
const items = data.subscriptions || data.data || [];
|
|
141
|
-
|
|
142
|
-
return items.map((item: any) => ({
|
|
143
|
-
id: String(item.id || item.subscription_id),
|
|
144
|
-
trigger_slug: item.title || item.server || "",
|
|
145
|
-
connected_account_id: item.credential_id || null,
|
|
146
|
-
status: item.status === "active" ? "active" as const : "disabled" as const,
|
|
147
|
-
config: {
|
|
148
|
-
server: item.server,
|
|
149
|
-
events: item.events,
|
|
150
|
-
callback_url: item.callback_url,
|
|
151
|
-
prompt: item.prompt,
|
|
152
|
-
title: item.title,
|
|
153
|
-
},
|
|
154
|
-
created_at: item.created_at || "",
|
|
155
|
-
}));
|
|
156
|
-
},
|
|
157
|
-
|
|
158
|
-
async enableTrigger(apiKey: string, triggerId: string): Promise<boolean> {
|
|
159
|
-
const res = await fetch(`${AGENTDOJO_API_BASE}/subscription/update`, {
|
|
160
|
-
method: "POST",
|
|
161
|
-
headers: headers(apiKey),
|
|
162
|
-
body: JSON.stringify({ subscription_id: parseInt(triggerId), status: "active" }),
|
|
163
|
-
});
|
|
164
|
-
return res.ok;
|
|
165
|
-
},
|
|
166
|
-
|
|
167
|
-
async disableTrigger(apiKey: string, triggerId: string): Promise<boolean> {
|
|
168
|
-
const res = await fetch(`${AGENTDOJO_API_BASE}/subscription/update`, {
|
|
169
|
-
method: "POST",
|
|
170
|
-
headers: headers(apiKey),
|
|
171
|
-
body: JSON.stringify({ subscription_id: parseInt(triggerId), status: "disabled" }),
|
|
172
|
-
});
|
|
173
|
-
return res.ok;
|
|
174
|
-
},
|
|
175
|
-
|
|
176
|
-
async deleteTrigger(apiKey: string, triggerId: string): Promise<boolean> {
|
|
177
|
-
const res = await fetch(`${AGENTDOJO_API_BASE}/unsubscribe`, {
|
|
178
|
-
method: "POST",
|
|
179
|
-
headers: headers(apiKey),
|
|
180
|
-
body: JSON.stringify({ subscription_id: parseInt(triggerId) }),
|
|
181
|
-
});
|
|
182
|
-
return res.ok;
|
|
183
|
-
},
|
|
184
|
-
|
|
185
|
-
async setupWebhook(apiKey: string, webhookUrl: string): Promise<{ secret?: string }> {
|
|
186
|
-
// AgentDojo uses per-subscription callback URLs, not a global webhook.
|
|
187
|
-
// We just store the base URL locally — it will be passed when creating subscriptions.
|
|
188
|
-
// No remote API call needed.
|
|
189
|
-
return {};
|
|
190
|
-
},
|
|
191
|
-
|
|
192
|
-
async getWebhookConfig(apiKey: string): Promise<{ url: string | null; secret: string | null }> {
|
|
193
|
-
// AgentDojo doesn't have a global webhook config — each subscription has its own callback_url.
|
|
194
|
-
// Return null to indicate per-subscription mode.
|
|
195
|
-
return { url: null, secret: null };
|
|
196
|
-
},
|
|
197
|
-
|
|
198
|
-
verifyWebhook(req: Request, body: string, secret: string): boolean {
|
|
199
|
-
// AgentDojo forwards webhooks with an HMAC signature
|
|
200
|
-
const signature = req.headers.get("x-webhook-signature") || "";
|
|
201
|
-
if (!signature) {
|
|
202
|
-
// If no signature header, check for a simple shared token
|
|
203
|
-
const token = req.headers.get("x-webhook-token") || "";
|
|
204
|
-
return token === secret;
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
// HMAC-SHA256 verification: signature is "sha256=<hex>"
|
|
208
|
-
const sig = signature.startsWith("sha256=") ? signature.slice(7) : signature;
|
|
209
|
-
|
|
210
|
-
try {
|
|
211
|
-
const expected = createHmac("sha256", secret).update(body).digest("hex");
|
|
212
|
-
return timingSafeEqual(Buffer.from(sig, "hex"), Buffer.from(expected, "hex"));
|
|
213
|
-
} catch {
|
|
214
|
-
return false;
|
|
215
|
-
}
|
|
216
|
-
},
|
|
217
|
-
|
|
218
|
-
parseWebhookPayload(body: Record<string, unknown>): {
|
|
219
|
-
triggerSlug: string;
|
|
220
|
-
triggerInstanceId: string | null;
|
|
221
|
-
payload: Record<string, unknown>;
|
|
222
|
-
} {
|
|
223
|
-
// AgentDojo forwarded payload format:
|
|
224
|
-
// { type: "webhook", server: "stripe-payments", event: "payment_intent.succeeded",
|
|
225
|
-
// data: { ... }, prompt: "...", subscription_id: 123, timestamp: "..." }
|
|
226
|
-
|
|
227
|
-
const server = (body.server as string) || "";
|
|
228
|
-
const event = (body.event as string) || "";
|
|
229
|
-
const triggerSlug = event ? `${server}:${event}` : server || (body.type as string) || "unknown";
|
|
230
|
-
|
|
231
|
-
const triggerInstanceId = body.subscription_id
|
|
232
|
-
? String(body.subscription_id)
|
|
233
|
-
: null;
|
|
234
|
-
|
|
235
|
-
const payload = (body.data as Record<string, unknown>) || {};
|
|
236
|
-
|
|
237
|
-
return { triggerSlug, triggerInstanceId, payload };
|
|
238
|
-
},
|
|
239
|
-
};
|
|
240
|
-
|
|
241
|
-
function mapTriggerTypes(items: any[]): TriggerType[] {
|
|
242
|
-
return items.map((item: any) => ({
|
|
243
|
-
slug: item.slug,
|
|
244
|
-
name: item.display_name || item.event_name || item.slug,
|
|
245
|
-
description: item.description || "",
|
|
246
|
-
type: (item.mechanism as "webhook" | "poll") || "webhook",
|
|
247
|
-
toolkit_slug: item.toolkit?.name || item.toolkit_name || "",
|
|
248
|
-
toolkit_name: item.toolkit?.display_name || item.toolkit_display_name || "",
|
|
249
|
-
logo: item.toolkit?.icon_url || null,
|
|
250
|
-
config_schema: item.config_schema || {},
|
|
251
|
-
payload_schema: item.payload_schema || {},
|
|
252
|
-
}));
|
|
253
|
-
}
|
package/src/triggers/composio.ts
DELETED
|
@@ -1,264 +0,0 @@
|
|
|
1
|
-
// Composio Trigger Provider
|
|
2
|
-
// https://docs.composio.dev/api-reference/triggers
|
|
3
|
-
|
|
4
|
-
import { createHmac, timingSafeEqual } from "crypto";
|
|
5
|
-
import type { TriggerProvider, TriggerType, TriggerInstance } from "./index";
|
|
6
|
-
|
|
7
|
-
const COMPOSIO_API_BASE = "https://backend.composio.dev";
|
|
8
|
-
|
|
9
|
-
function headers(apiKey: string) {
|
|
10
|
-
return { "x-api-key": apiKey, "Content-Type": "application/json" };
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
export const ComposioTriggerProvider: TriggerProvider = {
|
|
14
|
-
id: "composio",
|
|
15
|
-
name: "Composio",
|
|
16
|
-
|
|
17
|
-
async listTriggerTypes(apiKey: string, toolkitSlugs?: string[]): Promise<TriggerType[]> {
|
|
18
|
-
const params = new URLSearchParams();
|
|
19
|
-
if (toolkitSlugs?.length) {
|
|
20
|
-
params.set("toolkit_slugs", toolkitSlugs.join(","));
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
const res = await fetch(`${COMPOSIO_API_BASE}/api/v3/triggers_types?${params}`, {
|
|
24
|
-
headers: headers(apiKey),
|
|
25
|
-
});
|
|
26
|
-
|
|
27
|
-
if (!res.ok) {
|
|
28
|
-
console.error("Composio listTriggerTypes error:", res.status, await res.text());
|
|
29
|
-
return [];
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
const data = await res.json();
|
|
33
|
-
const items = data.items || data || [];
|
|
34
|
-
|
|
35
|
-
return items.map((item: any) => ({
|
|
36
|
-
slug: item.slug || item.enum,
|
|
37
|
-
name: item.name || item.slug,
|
|
38
|
-
description: item.description || "",
|
|
39
|
-
type: item.type || "webhook",
|
|
40
|
-
toolkit_slug: item.toolkit?.slug || item.app_slug || "",
|
|
41
|
-
toolkit_name: item.toolkit?.name || item.app_name || "",
|
|
42
|
-
logo: item.toolkit?.logo || item.logo || null,
|
|
43
|
-
config_schema: item.config || {},
|
|
44
|
-
payload_schema: item.payload || {},
|
|
45
|
-
}));
|
|
46
|
-
},
|
|
47
|
-
|
|
48
|
-
async getTriggerType(apiKey: string, slug: string): Promise<TriggerType | null> {
|
|
49
|
-
const res = await fetch(`${COMPOSIO_API_BASE}/api/v3/triggers_types/${encodeURIComponent(slug)}`, {
|
|
50
|
-
headers: headers(apiKey),
|
|
51
|
-
});
|
|
52
|
-
|
|
53
|
-
if (!res.ok) {
|
|
54
|
-
if (res.status === 404) return null;
|
|
55
|
-
console.error("Composio getTriggerType error:", res.status, await res.text());
|
|
56
|
-
return null;
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
const item = await res.json();
|
|
60
|
-
return {
|
|
61
|
-
slug: item.slug || item.enum,
|
|
62
|
-
name: item.name || item.slug,
|
|
63
|
-
description: item.description || "",
|
|
64
|
-
type: item.type || "webhook",
|
|
65
|
-
toolkit_slug: item.toolkit?.slug || item.app_slug || "",
|
|
66
|
-
toolkit_name: item.toolkit?.name || item.app_name || "",
|
|
67
|
-
logo: item.toolkit?.logo || item.logo || null,
|
|
68
|
-
config_schema: item.config || {},
|
|
69
|
-
payload_schema: item.payload || {},
|
|
70
|
-
};
|
|
71
|
-
},
|
|
72
|
-
|
|
73
|
-
async createTrigger(
|
|
74
|
-
apiKey: string,
|
|
75
|
-
slug: string,
|
|
76
|
-
connectedAccountId: string,
|
|
77
|
-
config?: Record<string, unknown>,
|
|
78
|
-
): Promise<{ triggerId: string }> {
|
|
79
|
-
const body: any = {
|
|
80
|
-
connected_account_id: connectedAccountId,
|
|
81
|
-
};
|
|
82
|
-
if (config) {
|
|
83
|
-
body.trigger_config = config;
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
const res = await fetch(
|
|
87
|
-
`${COMPOSIO_API_BASE}/api/v3/trigger_instances/${encodeURIComponent(slug)}/upsert`,
|
|
88
|
-
{
|
|
89
|
-
method: "POST",
|
|
90
|
-
headers: headers(apiKey),
|
|
91
|
-
body: JSON.stringify(body),
|
|
92
|
-
},
|
|
93
|
-
);
|
|
94
|
-
|
|
95
|
-
if (!res.ok) {
|
|
96
|
-
const errText = await res.text();
|
|
97
|
-
console.error("Composio createTrigger error:", res.status, errText);
|
|
98
|
-
throw new Error(`Failed to create trigger: ${errText}`);
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
const data = await res.json();
|
|
102
|
-
return { triggerId: data.trigger_id || data.deprecated?.uuid || data.id };
|
|
103
|
-
},
|
|
104
|
-
|
|
105
|
-
async listTriggers(apiKey: string): Promise<TriggerInstance[]> {
|
|
106
|
-
const res = await fetch(`${COMPOSIO_API_BASE}/api/v3/trigger_instances/active`, {
|
|
107
|
-
headers: headers(apiKey),
|
|
108
|
-
});
|
|
109
|
-
|
|
110
|
-
if (!res.ok) {
|
|
111
|
-
console.error("Composio listTriggers error:", res.status, await res.text());
|
|
112
|
-
return [];
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
const data = await res.json();
|
|
116
|
-
const items = data.items || data.triggers || data || [];
|
|
117
|
-
|
|
118
|
-
return items.map((item: any) => ({
|
|
119
|
-
id: item.id || item.trigger_id,
|
|
120
|
-
trigger_slug: item.trigger_name || item.trigger_slug || item.slug || "",
|
|
121
|
-
connected_account_id: item.connected_account_id || item.connectedAccountId || null,
|
|
122
|
-
status: item.disabled ? "disabled" : "active",
|
|
123
|
-
config: item.trigger_config || item.triggerConfig || {},
|
|
124
|
-
created_at: item.created_at || item.createdAt || "",
|
|
125
|
-
}));
|
|
126
|
-
},
|
|
127
|
-
|
|
128
|
-
async enableTrigger(apiKey: string, triggerId: string): Promise<boolean> {
|
|
129
|
-
const res = await fetch(
|
|
130
|
-
`${COMPOSIO_API_BASE}/api/v3/trigger_instances/manage/${encodeURIComponent(triggerId)}`,
|
|
131
|
-
{
|
|
132
|
-
method: "PATCH",
|
|
133
|
-
headers: headers(apiKey),
|
|
134
|
-
body: JSON.stringify({ status: "enable" }),
|
|
135
|
-
},
|
|
136
|
-
);
|
|
137
|
-
return res.ok;
|
|
138
|
-
},
|
|
139
|
-
|
|
140
|
-
async disableTrigger(apiKey: string, triggerId: string): Promise<boolean> {
|
|
141
|
-
const res = await fetch(
|
|
142
|
-
`${COMPOSIO_API_BASE}/api/v3/trigger_instances/manage/${encodeURIComponent(triggerId)}`,
|
|
143
|
-
{
|
|
144
|
-
method: "PATCH",
|
|
145
|
-
headers: headers(apiKey),
|
|
146
|
-
body: JSON.stringify({ status: "disable" }),
|
|
147
|
-
},
|
|
148
|
-
);
|
|
149
|
-
return res.ok;
|
|
150
|
-
},
|
|
151
|
-
|
|
152
|
-
async deleteTrigger(apiKey: string, triggerId: string): Promise<boolean> {
|
|
153
|
-
const res = await fetch(
|
|
154
|
-
`${COMPOSIO_API_BASE}/api/v3/trigger_instances/manage/${encodeURIComponent(triggerId)}`,
|
|
155
|
-
{
|
|
156
|
-
method: "DELETE",
|
|
157
|
-
headers: headers(apiKey),
|
|
158
|
-
},
|
|
159
|
-
);
|
|
160
|
-
return res.ok;
|
|
161
|
-
},
|
|
162
|
-
|
|
163
|
-
async setupWebhook(apiKey: string, webhookUrl: string): Promise<{ secret?: string }> {
|
|
164
|
-
// Use webhook_subscriptions API (requires HTTPS)
|
|
165
|
-
const res = await fetch(`${COMPOSIO_API_BASE}/api/v3/webhook_subscriptions`, {
|
|
166
|
-
method: "POST",
|
|
167
|
-
headers: headers(apiKey),
|
|
168
|
-
body: JSON.stringify({
|
|
169
|
-
webhook_url: webhookUrl,
|
|
170
|
-
enabled_events: ["composio.trigger.message"],
|
|
171
|
-
version: "V3",
|
|
172
|
-
}),
|
|
173
|
-
});
|
|
174
|
-
|
|
175
|
-
if (!res.ok) {
|
|
176
|
-
const errText = await res.text();
|
|
177
|
-
console.error("Composio setupWebhook error:", res.status, errText);
|
|
178
|
-
throw new Error(`Failed to set webhook URL: ${errText}`);
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
const data = await res.json();
|
|
182
|
-
const secret = data.secret || data.webhook_secret || undefined;
|
|
183
|
-
return { secret };
|
|
184
|
-
},
|
|
185
|
-
|
|
186
|
-
async getWebhookConfig(apiKey: string): Promise<{ url: string | null; secret: string | null }> {
|
|
187
|
-
const res = await fetch(`${COMPOSIO_API_BASE}/api/v3/webhook_subscriptions`, {
|
|
188
|
-
headers: headers(apiKey),
|
|
189
|
-
});
|
|
190
|
-
|
|
191
|
-
if (!res.ok) {
|
|
192
|
-
console.error("Composio getWebhookConfig error:", res.status, await res.text());
|
|
193
|
-
return { url: null, secret: null };
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
const data = await res.json();
|
|
197
|
-
const items = data.items || data.subscriptions || (Array.isArray(data) ? data : [data]);
|
|
198
|
-
const sub = items[0];
|
|
199
|
-
return {
|
|
200
|
-
url: sub?.webhook_url || sub?.callback_url || sub?.url || null,
|
|
201
|
-
secret: sub?.secret || sub?.webhook_secret || null,
|
|
202
|
-
};
|
|
203
|
-
},
|
|
204
|
-
|
|
205
|
-
verifyWebhook(req: Request, body: string, secret: string): boolean {
|
|
206
|
-
const signature = req.headers.get("webhook-signature") || "";
|
|
207
|
-
const webhookId = req.headers.get("webhook-id") || "";
|
|
208
|
-
const timestamp = req.headers.get("webhook-timestamp") || "";
|
|
209
|
-
|
|
210
|
-
if (!signature || !webhookId || !timestamp) return false;
|
|
211
|
-
|
|
212
|
-
// Check timestamp freshness (5-minute window to prevent replay)
|
|
213
|
-
const now = Math.floor(Date.now() / 1000);
|
|
214
|
-
const ts = parseInt(timestamp, 10);
|
|
215
|
-
if (isNaN(ts) || Math.abs(now - ts) > 300) return false;
|
|
216
|
-
|
|
217
|
-
// Composio signature: HMAC-SHA256("{webhook-id}.{timestamp}.{body}", secret)
|
|
218
|
-
const signedContent = `${webhookId}.${timestamp}.${body}`;
|
|
219
|
-
const expectedSignature = createHmac("sha256", secret)
|
|
220
|
-
.update(signedContent)
|
|
221
|
-
.digest("base64");
|
|
222
|
-
|
|
223
|
-
// Signature header format: "v1,<base64>"
|
|
224
|
-
const sig = signature.startsWith("v1,") ? signature.slice(3) : signature;
|
|
225
|
-
|
|
226
|
-
try {
|
|
227
|
-
return timingSafeEqual(
|
|
228
|
-
Buffer.from(sig, "base64"),
|
|
229
|
-
Buffer.from(expectedSignature, "base64"),
|
|
230
|
-
);
|
|
231
|
-
} catch {
|
|
232
|
-
return false;
|
|
233
|
-
}
|
|
234
|
-
},
|
|
235
|
-
|
|
236
|
-
parseWebhookPayload(body: Record<string, unknown>): {
|
|
237
|
-
triggerSlug: string;
|
|
238
|
-
triggerInstanceId: string | null;
|
|
239
|
-
payload: Record<string, unknown>;
|
|
240
|
-
} {
|
|
241
|
-
// V3 format: { type: "composio.trigger.message", metadata: { trigger_slug, trigger_id, ... }, data: { ... } }
|
|
242
|
-
// V2/V1 format: { trigger_name, trigger_id, payload: { ... } }
|
|
243
|
-
const metadata = (body.metadata as Record<string, unknown>) || {};
|
|
244
|
-
const data = (body.data as Record<string, unknown>) || {};
|
|
245
|
-
|
|
246
|
-
const triggerSlug =
|
|
247
|
-
(metadata.trigger_slug as string) ||
|
|
248
|
-
(body.trigger_name as string) ||
|
|
249
|
-
((body.type as string) !== "composio.trigger.message" ? (body.type as string) : null) ||
|
|
250
|
-
"unknown";
|
|
251
|
-
|
|
252
|
-
const triggerInstanceId =
|
|
253
|
-
(metadata.trigger_id as string) ||
|
|
254
|
-
(body.trigger_id as string) ||
|
|
255
|
-
(body.triggerId as string) ||
|
|
256
|
-
null;
|
|
257
|
-
|
|
258
|
-
const payload =
|
|
259
|
-
(body.payload as Record<string, unknown>) ||
|
|
260
|
-
data;
|
|
261
|
-
|
|
262
|
-
return { triggerSlug, triggerInstanceId, payload };
|
|
263
|
-
},
|
|
264
|
-
};
|
package/src/triggers/index.ts
DELETED
|
@@ -1,71 +0,0 @@
|
|
|
1
|
-
// Generic Trigger Provider Interface
|
|
2
|
-
// Allows multiple providers (Composio, AgentDojo, local, etc.) to offer trigger/webhook integrations
|
|
3
|
-
|
|
4
|
-
export interface TriggerType {
|
|
5
|
-
slug: string;
|
|
6
|
-
name: string;
|
|
7
|
-
description: string;
|
|
8
|
-
type: "webhook" | "poll";
|
|
9
|
-
toolkit_slug: string;
|
|
10
|
-
toolkit_name: string;
|
|
11
|
-
logo: string | null;
|
|
12
|
-
config_schema: Record<string, unknown>;
|
|
13
|
-
payload_schema: Record<string, unknown>;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
export interface TriggerInstance {
|
|
17
|
-
id: string;
|
|
18
|
-
trigger_slug: string;
|
|
19
|
-
connected_account_id: string | null;
|
|
20
|
-
status: "active" | "disabled";
|
|
21
|
-
config: Record<string, unknown>;
|
|
22
|
-
created_at: string;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
export interface TriggerProvider {
|
|
26
|
-
id: string;
|
|
27
|
-
name: string;
|
|
28
|
-
|
|
29
|
-
// Browse available trigger types
|
|
30
|
-
listTriggerTypes(apiKey: string, toolkitSlugs?: string[]): Promise<TriggerType[]>;
|
|
31
|
-
getTriggerType(apiKey: string, slug: string): Promise<TriggerType | null>;
|
|
32
|
-
|
|
33
|
-
// CRUD trigger instances (all remote)
|
|
34
|
-
createTrigger(
|
|
35
|
-
apiKey: string,
|
|
36
|
-
slug: string,
|
|
37
|
-
connectedAccountId: string,
|
|
38
|
-
config?: Record<string, unknown>,
|
|
39
|
-
): Promise<{ triggerId: string }>;
|
|
40
|
-
listTriggers(apiKey: string): Promise<TriggerInstance[]>;
|
|
41
|
-
enableTrigger(apiKey: string, triggerId: string): Promise<boolean>;
|
|
42
|
-
disableTrigger(apiKey: string, triggerId: string): Promise<boolean>;
|
|
43
|
-
deleteTrigger(apiKey: string, triggerId: string): Promise<boolean>;
|
|
44
|
-
|
|
45
|
-
// Webhook configuration
|
|
46
|
-
setupWebhook(apiKey: string, webhookUrl: string): Promise<{ secret?: string }>;
|
|
47
|
-
getWebhookConfig(apiKey: string): Promise<{ url: string | null; secret: string | null }>;
|
|
48
|
-
|
|
49
|
-
// Webhook verification and parsing (each provider signs differently)
|
|
50
|
-
verifyWebhook(req: Request, body: string, secret: string): boolean;
|
|
51
|
-
parseWebhookPayload(body: Record<string, unknown>): {
|
|
52
|
-
triggerSlug: string;
|
|
53
|
-
triggerInstanceId: string | null;
|
|
54
|
-
payload: Record<string, unknown>;
|
|
55
|
-
};
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
// Provider registry
|
|
59
|
-
const triggerProviders: Map<string, TriggerProvider> = new Map();
|
|
60
|
-
|
|
61
|
-
export function registerTriggerProvider(provider: TriggerProvider) {
|
|
62
|
-
triggerProviders.set(provider.id, provider);
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
export function getTriggerProvider(id: string): TriggerProvider | undefined {
|
|
66
|
-
return triggerProviders.get(id);
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
export function getTriggerProviderIds(): string[] {
|
|
70
|
-
return Array.from(triggerProviders.keys());
|
|
71
|
-
}
|