@finchagentic/mcp 4.6.0 β 4.6.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +7 -7
- package/package.json +5 -6
- package/dist/_http-cache.js +0 -96
- package/dist/agent-loop.js +0 -301
- package/dist/annotations.js +0 -122
- package/dist/cli.js +0 -1391
- package/dist/clink-input.js +0 -15
- package/dist/config.js +0 -132
- package/dist/convex.js +0 -175
- package/dist/dex-pair.js +0 -54
- package/dist/enrichment-router.js +0 -315
- package/dist/index.js +0 -258
- package/dist/llm.js +0 -298
- package/dist/local-memory-file.js +0 -147
- package/dist/local-memory.js +0 -135
- package/dist/local-vault.js +0 -454
- package/dist/output-schemas.js +0 -605
- package/dist/project.js +0 -36
- package/dist/prompts.js +0 -111
- package/dist/public-url.js +0 -107
- package/dist/resources.js +0 -111
- package/dist/server.js +0 -322
- package/dist/signal-gate.js +0 -57
- package/dist/token-decimals.js +0 -26
- package/dist/token-gate.js +0 -88
- package/dist/tool-filter.js +0 -53
- package/dist/tools/_solidity-scan.js +0 -313
- package/dist/tools/agents.js +0 -441
- package/dist/tools/automation.js +0 -354
- package/dist/tools/base-mcp.js +0 -466
- package/dist/tools/base.js +0 -283
- package/dist/tools/chronicle.js +0 -268
- package/dist/tools/coder.js +0 -94
- package/dist/tools/deep-research.js +0 -1421
- package/dist/tools/defi.js +0 -292
- package/dist/tools/equity.js +0 -372
- package/dist/tools/events.js +0 -182
- package/dist/tools/github.js +0 -564
- package/dist/tools/insider.js +0 -264
- package/dist/tools/insight.js +0 -630
- package/dist/tools/market.js +0 -555
- package/dist/tools/memory.js +0 -1044
- package/dist/tools/miroshark.js +0 -350
- package/dist/tools/monitor.js +0 -319
- package/dist/tools/os.js +0 -236
- package/dist/tools/packets.js +0 -296
- package/dist/tools/research-chain.js +0 -226
- package/dist/tools/research-compare.js +0 -280
- package/dist/tools/research.js +0 -188
- package/dist/tools/rh-bridge.js +0 -148
- package/dist/tools/rh-mcp.js +0 -1448
- package/dist/tools/rh-orders.js +0 -556
- package/dist/tools/scanner.js +0 -564
- package/dist/tools/stake.js +0 -369
- package/dist/tools/vault.js +0 -1020
- package/dist/tools/wallet.js +0 -200
- package/dist/types.js +0 -2
- package/dist/wallet.js +0 -372
package/dist/tools/automation.js
DELETED
|
@@ -1,354 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.AUTOMATION_TOOLS = void 0;
|
|
4
|
-
exports.buildAutomationList = buildAutomationList;
|
|
5
|
-
exports.buildAutomationRuns = buildAutomationRuns;
|
|
6
|
-
exports.handleAutomationTool = handleAutomationTool;
|
|
7
|
-
const zod_1 = require("zod");
|
|
8
|
-
const convex_js_1 = require("../convex.js");
|
|
9
|
-
const CATEGORY_PATTERNS = [
|
|
10
|
-
["insufficient_balance", /insufficient|not enough|balance|exceeds|nsf/i],
|
|
11
|
-
["quote_failed", /quote|0x quote|price impact|liquidity|no route|aggregator/i],
|
|
12
|
-
["tx_reverted", /revert|transaction failed|out of gas|execution reverted|nonce/i],
|
|
13
|
-
["rpc_error", /rpc|timeout|network|fetch failed|econnrefused|enotfound|gateway/i],
|
|
14
|
-
["auth_error", /auth|unauthorized|session|token|forbidden|403|401/i],
|
|
15
|
-
["config_missing", /not set|missing|required.*env|env.*required|api_key|api key|wallet not/i],
|
|
16
|
-
];
|
|
17
|
-
const CATEGORY_BADGE = {
|
|
18
|
-
insufficient_balance: "πΈ INSUFFICIENT_BALANCE",
|
|
19
|
-
quote_failed: "π QUOTE_FAILED",
|
|
20
|
-
tx_reverted: "π TX_REVERTED",
|
|
21
|
-
rpc_error: "π RPC_ERROR",
|
|
22
|
-
auth_error: "π AUTH_ERROR",
|
|
23
|
-
config_missing: "βοΈ CONFIG_MISSING",
|
|
24
|
-
unknown: "β UNKNOWN",
|
|
25
|
-
};
|
|
26
|
-
const CATEGORY_FIX = {
|
|
27
|
-
insufficient_balance: "Top up the wallet, lower the per-run amount, or check token allowance.",
|
|
28
|
-
quote_failed: "Token may have low liquidity. Try a different route, smaller size, or wait and retry.",
|
|
29
|
-
tx_reverted: "Check token approvals, slippage, and that you have ETH for gas.",
|
|
30
|
-
rpc_error: "Transient. Re-run shortly. Set FINCH_RPC_URL to a faster provider if it persists.",
|
|
31
|
-
auth_error: "Run `finch login` to refresh session, or re-issue the API key.",
|
|
32
|
-
config_missing: "Backend env var likely missing - check finch doctor for the specific config.",
|
|
33
|
-
unknown: "Unrecognized failure. Open get_automation_runs for the raw error and the chronicle log.",
|
|
34
|
-
};
|
|
35
|
-
function categorizeError(err) {
|
|
36
|
-
if (!err)
|
|
37
|
-
return "unknown";
|
|
38
|
-
for (const [cat, pat] of CATEGORY_PATTERNS) {
|
|
39
|
-
if (pat.test(err))
|
|
40
|
-
return cat;
|
|
41
|
-
}
|
|
42
|
-
return "unknown";
|
|
43
|
-
}
|
|
44
|
-
exports.AUTOMATION_TOOLS = [
|
|
45
|
-
{
|
|
46
|
-
name: "create_automation",
|
|
47
|
-
description: "Create an automation in plain English. Supports DCA, price alerts, conditional buys/sells, and recurring market updates. " +
|
|
48
|
-
"A swap/send automation arms UNATTENDED, REPEATING real fund movement (a backend cron fires it going forward, not just once) - " +
|
|
49
|
-
"requires two calls. First call WITHOUT confirm: returns a preview of the parsed trigger/action, nothing is created yet. " +
|
|
50
|
-
"Show that preview to the user in plain language and get explicit confirmation. Only then call again with the SAME rawInput " +
|
|
51
|
-
"and confirm: true to actually create it. Never pass confirm: true on the first call.",
|
|
52
|
-
inputSchema: {
|
|
53
|
-
type: "object",
|
|
54
|
-
properties: {
|
|
55
|
-
rawInput: { type: "string", description: "Plain English description of the automation" },
|
|
56
|
-
confirm: { type: "boolean", description: "Must be true to actually create. Omit or false to get a preview only - nothing is created." },
|
|
57
|
-
},
|
|
58
|
-
required: ["rawInput"],
|
|
59
|
-
},
|
|
60
|
-
},
|
|
61
|
-
{
|
|
62
|
-
name: "list_automations",
|
|
63
|
-
description: "List all your automations - active, paused, and completed - with status, run counts, and next scheduled run.",
|
|
64
|
-
inputSchema: { type: "object", properties: {}, required: [] },
|
|
65
|
-
},
|
|
66
|
-
{
|
|
67
|
-
name: "pause_automation",
|
|
68
|
-
description: "Pause or resume an automation by ID.",
|
|
69
|
-
inputSchema: {
|
|
70
|
-
type: "object",
|
|
71
|
-
properties: { automationId: { type: "string", description: "Automation ID (from list_automations)" } },
|
|
72
|
-
required: ["automationId"],
|
|
73
|
-
},
|
|
74
|
-
},
|
|
75
|
-
{
|
|
76
|
-
name: "delete_automation",
|
|
77
|
-
description: "PERMANENT. Delete an automation β this cannot be undone. Requires confirm: true. " +
|
|
78
|
-
"Run list_automations first and show the user which automation (id + name) you are about to " +
|
|
79
|
-
"remove. If they only want it to stop running, pause_automation is reversible.",
|
|
80
|
-
inputSchema: {
|
|
81
|
-
type: "object",
|
|
82
|
-
properties: {
|
|
83
|
-
automationId: { type: "string", description: "Automation ID (from list_automations)" },
|
|
84
|
-
confirm: { type: "boolean", description: "Must be true to delete. Guards against irreversible loss." },
|
|
85
|
-
},
|
|
86
|
-
required: ["automationId", "confirm"],
|
|
87
|
-
},
|
|
88
|
-
},
|
|
89
|
-
{
|
|
90
|
-
name: "get_automation_runs",
|
|
91
|
-
description: "Get the execution history for an automation - each run's status (success/failed/skipped), amount spent, tx hash, and error message if any. Useful for debugging why an automation isn't working.",
|
|
92
|
-
inputSchema: {
|
|
93
|
-
type: "object",
|
|
94
|
-
properties: {
|
|
95
|
-
automationId: { type: "string", description: "Automation ID (from list_automations)" },
|
|
96
|
-
limit: { type: "number", description: "Max runs to return (default 20)" },
|
|
97
|
-
},
|
|
98
|
-
required: ["automationId"],
|
|
99
|
-
},
|
|
100
|
-
},
|
|
101
|
-
{
|
|
102
|
-
name: "run_automation",
|
|
103
|
-
description: "Trigger an automation immediately - regardless of its schedule or trigger condition. " +
|
|
104
|
-
"Use to test an automation after creating it, or to run a one-off DCA/swap/alert right now. " +
|
|
105
|
-
"Pass dryRun:true to simulate (no tx broadcast, no funds moved) - useful for verifying config before real money. " +
|
|
106
|
-
"The automation must be active (not paused or deleted). " +
|
|
107
|
-
"Get the ID from list_automations.",
|
|
108
|
-
inputSchema: {
|
|
109
|
-
type: "object",
|
|
110
|
-
properties: {
|
|
111
|
-
automationId: { type: "string", description: "Automation ID to run now (from list_automations)" },
|
|
112
|
-
dryRun: { type: "boolean", description: "Simulate without broadcasting tx. No funds moved. Use to verify config." },
|
|
113
|
-
},
|
|
114
|
-
required: ["automationId"],
|
|
115
|
-
},
|
|
116
|
-
},
|
|
117
|
-
];
|
|
118
|
-
const CreateAutomationSchema = zod_1.z.object({ rawInput: zod_1.z.string().min(1), confirm: zod_1.z.boolean().optional() });
|
|
119
|
-
const AutomationIdSchema = zod_1.z.object({ automationId: zod_1.z.string().min(1) });
|
|
120
|
-
const RunAutomationSchema = zod_1.z.object({ automationId: zod_1.z.string().min(1), dryRun: zod_1.z.boolean().optional() });
|
|
121
|
-
const RunsSchema = zod_1.z.object({ automationId: zod_1.z.string().min(1), limit: zod_1.z.number().int().min(1).max(100).optional() });
|
|
122
|
-
// ββ Structured output builders (schemas in output-schemas.ts) βββββββββββββββ
|
|
123
|
-
function buildAutomationList(automations) {
|
|
124
|
-
return {
|
|
125
|
-
count: automations.length,
|
|
126
|
-
automations: automations.map((a) => ({
|
|
127
|
-
id: a._id,
|
|
128
|
-
name: a.name,
|
|
129
|
-
status: a.status ?? null,
|
|
130
|
-
triggerType: a.triggerType ?? null,
|
|
131
|
-
actionType: a.actionType ?? null,
|
|
132
|
-
totalRuns: a.totalRuns ?? 0,
|
|
133
|
-
totalSpentUsd: a.totalSpentUsd ?? 0,
|
|
134
|
-
nextRunAt: a.nextRunAt ?? null,
|
|
135
|
-
lastError: a.lastError ?? null,
|
|
136
|
-
})),
|
|
137
|
-
};
|
|
138
|
-
}
|
|
139
|
-
function buildAutomationRuns(automationId, runs) {
|
|
140
|
-
return {
|
|
141
|
-
automationId,
|
|
142
|
-
count: runs.length,
|
|
143
|
-
runs: runs.map((r) => ({
|
|
144
|
-
status: r.status ?? null,
|
|
145
|
-
triggeredAt: r.triggeredAt ?? null,
|
|
146
|
-
amountUsd: r.amountUsd ?? null,
|
|
147
|
-
txHash: r.txHash ?? null,
|
|
148
|
-
error: r.error ?? null,
|
|
149
|
-
})),
|
|
150
|
-
};
|
|
151
|
-
}
|
|
152
|
-
async function handleAutomationTool(name, args) {
|
|
153
|
-
switch (name) {
|
|
154
|
-
case "create_automation": {
|
|
155
|
-
const parsed = CreateAutomationSchema.safeParse(args);
|
|
156
|
-
if (!parsed.success)
|
|
157
|
-
return { content: [{ type: "text", text: `Invalid input: rawInput ${parsed.error.issues[0].message}` }], isError: true };
|
|
158
|
-
const triggerLabel = {
|
|
159
|
-
schedule: "β° Schedule", price_drop_pct: "π Price Drop %", price_rise_pct: "π Price Rise %",
|
|
160
|
-
price_below: "β¬οΈ Price Below", price_above: "β¬οΈ Price Above",
|
|
161
|
-
dominance_below: "π Dominance Below", dominance_above: "π Dominance Above",
|
|
162
|
-
};
|
|
163
|
-
const actionLabel = { swap: "π± Swap", send: "π€ Send", alert: "π Alert" };
|
|
164
|
-
// Not confirmed yet - dry-run only (backend validates/parses but does
|
|
165
|
-
// NOT create anything - see http.ts's /automations/create dryRun
|
|
166
|
-
// branch). A swap/send automation arms unattended, repeating real
|
|
167
|
-
// fund movement, so it needs a real preview + explicit confirm, same
|
|
168
|
-
// shape as base_mcp_swap/send - not created blind on the first call.
|
|
169
|
-
if (parsed.data.confirm !== true) {
|
|
170
|
-
const preview = await (0, convex_js_1.callConvex)("/automations/create", "POST", { rawInput: parsed.data.rawInput, dryRun: true }, "create_automation");
|
|
171
|
-
if (!preview.success)
|
|
172
|
-
return { content: [{ type: "text", text: `Could not parse this automation: ${preview.error}` }], isError: true };
|
|
173
|
-
const moneyMoving = preview.actionType === "swap" || preview.actionType === "send";
|
|
174
|
-
return {
|
|
175
|
-
content: [{
|
|
176
|
-
type: "text",
|
|
177
|
-
text: [
|
|
178
|
-
`**Preview - nothing created yet**`, ``,
|
|
179
|
-
`**Trigger:** ${triggerLabel[preview.triggerType] ?? preview.triggerType}`,
|
|
180
|
-
`**Action:** ${actionLabel[preview.actionType] ?? preview.actionType}`,
|
|
181
|
-
preview.fromToken && preview.toToken ? `**Swap:** ${preview.amountUsd ? `$${preview.amountUsd}` : `${preview.amountPct}%`} ${preview.fromToken} β ${preview.toToken}` : ``,
|
|
182
|
-
preview.toAddress ? `**Send:** ${preview.amountUsd ? `$${preview.amountUsd}` : ""} ${preview.fromToken ?? ""} to \`${preview.toAddress}\`` : ``,
|
|
183
|
-
preview.priceToken ? `**Price condition:** ${preview.priceToken} ${preview.triggerType?.includes("above") ? "above" : "below"} ${preview.priceThreshold}` : ``,
|
|
184
|
-
preview.priceBaselineUsd ? `**Baseline price:** $${Number(preview.priceBaselineUsd).toLocaleString()}` : ``,
|
|
185
|
-
moneyMoving
|
|
186
|
-
? `\nβ οΈ This will move real funds, repeatedly, unattended, until paused or deleted. Show this preview to the user and get explicit confirmation.`
|
|
187
|
-
: `\nThis is alert-only - it will not move funds.`,
|
|
188
|
-
`\nIf this is correct, call create_automation again with the same rawInput and confirm: true.`,
|
|
189
|
-
].filter(Boolean).join("\n"),
|
|
190
|
-
}],
|
|
191
|
-
};
|
|
192
|
-
}
|
|
193
|
-
const data = await (0, convex_js_1.callConvex)("/automations/create", "POST", { rawInput: parsed.data.rawInput }, "create_automation");
|
|
194
|
-
if (!data.success)
|
|
195
|
-
return { content: [{ type: "text", text: `Failed: ${data.error}` }], isError: true };
|
|
196
|
-
return {
|
|
197
|
-
content: [{
|
|
198
|
-
type: "text",
|
|
199
|
-
text: [
|
|
200
|
-
`β
**Automation Created**`, ``,
|
|
201
|
-
`**Name:** ${data.name}`, `**ID:** \`${data.automationId}\``,
|
|
202
|
-
`**Trigger:** ${triggerLabel[data.triggerType] ?? data.triggerType}`,
|
|
203
|
-
`**Action:** ${actionLabel[data.actionType] ?? data.actionType}`,
|
|
204
|
-
data.priceBaselineUsd ? `**Baseline price:** $${Number(data.priceBaselineUsd).toLocaleString()}` : ``,
|
|
205
|
-
``, `Use \`list_automations\` to see all your automations.`,
|
|
206
|
-
].filter(Boolean).join("\n"),
|
|
207
|
-
}],
|
|
208
|
-
};
|
|
209
|
-
}
|
|
210
|
-
case "list_automations": {
|
|
211
|
-
const data = await (0, convex_js_1.callConvex)("/automations/list", "GET", undefined, "list_automations");
|
|
212
|
-
if (data.error)
|
|
213
|
-
return { content: [{ type: "text", text: `Error: ${data.error}` }], isError: true };
|
|
214
|
-
const automations = data.automations ?? [];
|
|
215
|
-
if (!automations.length)
|
|
216
|
-
return { content: [{ type: "text", text: "No automations yet. Use `create_automation` to create one." }], structuredContent: buildAutomationList([]) };
|
|
217
|
-
const statusIcon = { active: "π’", paused: "βΈοΈ", completed: "β
", error: "β" };
|
|
218
|
-
const lines = [`**Your Automations** (${automations.length})`, ""];
|
|
219
|
-
for (const auto of automations) {
|
|
220
|
-
lines.push(`${statusIcon[auto.status] ?? "β’"} **${auto.name}** - \`${auto._id}\``);
|
|
221
|
-
lines.push(` Trigger: ${auto.triggerType} | Action: ${auto.actionType} | Runs: ${auto.totalRuns}`);
|
|
222
|
-
if (auto.totalSpentUsd > 0)
|
|
223
|
-
lines.push(` Total spent: $${Number(auto.totalSpentUsd).toFixed(2)}`);
|
|
224
|
-
if (auto.nextRunAt && auto.status === "active")
|
|
225
|
-
lines.push(` Next run: ${new Date(auto.nextRunAt).toUTCString()}`);
|
|
226
|
-
if (auto.lastError) {
|
|
227
|
-
const cat = categorizeError(auto.lastError);
|
|
228
|
-
lines.push(` β οΈ Last error [${CATEGORY_BADGE[cat]}]: ${auto.lastError}`);
|
|
229
|
-
}
|
|
230
|
-
lines.push("");
|
|
231
|
-
}
|
|
232
|
-
return { content: [{ type: "text", text: lines.join("\n") }], structuredContent: buildAutomationList(automations) };
|
|
233
|
-
}
|
|
234
|
-
case "pause_automation": {
|
|
235
|
-
const parsed = AutomationIdSchema.safeParse(args);
|
|
236
|
-
if (!parsed.success)
|
|
237
|
-
return { content: [{ type: "text", text: `Invalid input: automationId ${parsed.error.issues[0].message}` }], isError: true };
|
|
238
|
-
const data = await (0, convex_js_1.callConvex)("/automations/pause", "POST", { automationId: parsed.data.automationId }, "pause_automation");
|
|
239
|
-
if (data.error)
|
|
240
|
-
return { content: [{ type: "text", text: `Error: ${data.error}` }], isError: true };
|
|
241
|
-
const icon = data.status === "active" ? "βΆοΈ Resumed" : "βΈοΈ Paused";
|
|
242
|
-
return { content: [{ type: "text", text: `${icon} successfully.` }] };
|
|
243
|
-
}
|
|
244
|
-
case "delete_automation": {
|
|
245
|
-
const parsed = AutomationIdSchema.safeParse(args);
|
|
246
|
-
if (!parsed.success)
|
|
247
|
-
return { content: [{ type: "text", text: `Invalid input: automationId ${parsed.error.issues[0].message}` }], isError: true };
|
|
248
|
-
if (args?.confirm !== true) {
|
|
249
|
-
return {
|
|
250
|
-
content: [{
|
|
251
|
-
type: "text",
|
|
252
|
-
text: "Refusing to delete: this permanently removes the automation and cannot be undone. " +
|
|
253
|
-
"Show the user which automation this is, then pass `confirm: true`. To stop it " +
|
|
254
|
-
"without losing it, use `pause_automation`.",
|
|
255
|
-
}],
|
|
256
|
-
isError: true,
|
|
257
|
-
};
|
|
258
|
-
}
|
|
259
|
-
const data = await (0, convex_js_1.callConvex)("/automations/delete", "POST", { automationId: parsed.data.automationId }, "delete_automation");
|
|
260
|
-
if (data.error)
|
|
261
|
-
return { content: [{ type: "text", text: `Error: ${data.error}` }], isError: true };
|
|
262
|
-
return { content: [{ type: "text", text: "ποΈ Automation deleted." }] };
|
|
263
|
-
}
|
|
264
|
-
case "get_automation_runs": {
|
|
265
|
-
const parsed = RunsSchema.safeParse(args);
|
|
266
|
-
if (!parsed.success)
|
|
267
|
-
return { content: [{ type: "text", text: `Invalid input: automationId ${parsed.error.issues[0].message}` }], isError: true };
|
|
268
|
-
const { automationId, limit = 20 } = parsed.data;
|
|
269
|
-
const qs = `automationId=${encodeURIComponent(automationId)}&limit=${limit}`;
|
|
270
|
-
const data = await (0, convex_js_1.callConvex)(`/automations/runs?${qs}`, "GET", undefined, "get_automation_runs");
|
|
271
|
-
if (data.error)
|
|
272
|
-
return { content: [{ type: "text", text: `Error: ${data.error}` }], isError: true };
|
|
273
|
-
const runs = data.runs ?? [];
|
|
274
|
-
if (!runs.length)
|
|
275
|
-
return { content: [{ type: "text", text: "No runs yet for this automation." }], structuredContent: buildAutomationRuns(automationId, []) };
|
|
276
|
-
const statusIcon = { success: "β
", failed: "β", skipped: "βοΈ" };
|
|
277
|
-
const lines = [`**Run History** (${runs.length} shown)`, ""];
|
|
278
|
-
// Track failure breakdown so we can show a "top failure cause" line at the bottom.
|
|
279
|
-
const failureCounts = new Map();
|
|
280
|
-
for (const r of runs) {
|
|
281
|
-
const icon = statusIcon[r.status] ?? "β’";
|
|
282
|
-
const time = new Date(r.triggeredAt).toUTCString();
|
|
283
|
-
const spent = r.amountUsd != null ? ` Β· $${Number(r.amountUsd).toFixed(2)}` : "";
|
|
284
|
-
const tx = r.txHash ? ` Β· [tx](https://basescan.org/tx/${r.txHash})` : "";
|
|
285
|
-
lines.push(`${icon} **${r.status}**${spent}${tx} - ${time}`);
|
|
286
|
-
if (r.error) {
|
|
287
|
-
const cat = categorizeError(r.error);
|
|
288
|
-
failureCounts.set(cat, (failureCounts.get(cat) ?? 0) + 1);
|
|
289
|
-
lines.push(` ${CATEGORY_BADGE[cat]} ${r.error}`);
|
|
290
|
-
}
|
|
291
|
-
}
|
|
292
|
-
if (failureCounts.size > 0) {
|
|
293
|
-
const top = [...failureCounts.entries()].sort((a, b) => b[1] - a[1])[0];
|
|
294
|
-
lines.push("", `**Top failure cause:** ${CATEGORY_BADGE[top[0]]} (${top[1]} run${top[1] !== 1 ? "s" : ""})`);
|
|
295
|
-
lines.push(`β ${CATEGORY_FIX[top[0]]}`);
|
|
296
|
-
}
|
|
297
|
-
return { content: [{ type: "text", text: lines.join("\n") }], structuredContent: buildAutomationRuns(automationId, runs) };
|
|
298
|
-
}
|
|
299
|
-
case "run_automation": {
|
|
300
|
-
const parsed = RunAutomationSchema.safeParse(args);
|
|
301
|
-
if (!parsed.success)
|
|
302
|
-
return { content: [{ type: "text", text: `Invalid input: automationId ${parsed.error.issues[0].message}` }], isError: true };
|
|
303
|
-
const { automationId, dryRun } = parsed.data;
|
|
304
|
-
// A real (non-dryRun) trigger moves funds if the automation is a
|
|
305
|
-
// swap/send - noRetry so a lost response never risks re-sending the
|
|
306
|
-
// same trigger. A dryRun call does nothing server-side, so retrying
|
|
307
|
-
// it is harmless and stays on the default retry behavior.
|
|
308
|
-
const data = await (0, convex_js_1.callConvex)("/automations/run", "POST", { automationId, dryRun: !!dryRun }, "run_automation", 30000, !dryRun);
|
|
309
|
-
if (data.error) {
|
|
310
|
-
const cat = categorizeError(data.error);
|
|
311
|
-
return {
|
|
312
|
-
content: [{
|
|
313
|
-
type: "text",
|
|
314
|
-
text: [
|
|
315
|
-
`β **Automation run failed** - ${CATEGORY_BADGE[cat]}`,
|
|
316
|
-
``,
|
|
317
|
-
`Error: ${data.error}`,
|
|
318
|
-
``,
|
|
319
|
-
`β ${CATEGORY_FIX[cat]}`,
|
|
320
|
-
].join("\n"),
|
|
321
|
-
}],
|
|
322
|
-
isError: true,
|
|
323
|
-
};
|
|
324
|
-
}
|
|
325
|
-
const statusIcon = { success: "β
", failed: "β", skipped: "βοΈ" };
|
|
326
|
-
const icon = dryRun ? "π§ͺ" : (statusIcon[data.status] ?? "β‘");
|
|
327
|
-
const spent = data.amountUsd != null ? ` Β· $${Number(data.amountUsd).toFixed(2)}${dryRun ? " simulated" : " spent"}` : "";
|
|
328
|
-
const txLine = data.txHash ? `\nTx: https://basescan.org/tx/${data.txHash}` : "";
|
|
329
|
-
const dryRunNote = dryRun ? `\n${`π§ͺ **DRY RUN** - no transaction broadcast, no funds moved.`}` : "";
|
|
330
|
-
// If backend signaled failure inside the payload, surface the category too.
|
|
331
|
-
let failureLine = "";
|
|
332
|
-
if (data.status === "failed" && data.error) {
|
|
333
|
-
const cat = categorizeError(data.error);
|
|
334
|
-
failureLine = `\n\n${CATEGORY_BADGE[cat]} β ${CATEGORY_FIX[cat]}`;
|
|
335
|
-
}
|
|
336
|
-
return {
|
|
337
|
-
content: [{
|
|
338
|
-
type: "text",
|
|
339
|
-
text: [
|
|
340
|
-
`${icon} **Automation triggered: ${data.status ?? (dryRun ? "simulated" : "executed")}**${spent}`,
|
|
341
|
-
dryRunNote,
|
|
342
|
-
data.message ?? "",
|
|
343
|
-
txLine,
|
|
344
|
-
failureLine,
|
|
345
|
-
``,
|
|
346
|
-
`Use \`get_automation_runs automationId: "${automationId}"\` to see full history.`,
|
|
347
|
-
].filter(Boolean).join("\n"),
|
|
348
|
-
}],
|
|
349
|
-
};
|
|
350
|
-
}
|
|
351
|
-
default:
|
|
352
|
-
return null;
|
|
353
|
-
}
|
|
354
|
-
}
|