@noelclaw/mcp 1.5.7 → 2.2.0
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/dist/convex.js +3 -1
- package/dist/index.js +71 -16
- package/dist/llm.js +64 -0
- package/dist/server.js +23 -18
- package/dist/tools/agents.js +79 -0
- package/dist/tools/automation.js +38 -0
- package/dist/tools/base.js +269 -0
- package/dist/tools/coder.js +347 -0
- package/dist/tools/defi.js +106 -1
- package/dist/tools/humanizer.js +15 -35
- package/dist/tools/insight.js +7 -33
- package/dist/tools/miroshark.js +57 -13
- package/dist/tools/scanner.js +375 -0
- package/dist/tools/swarm.js +127 -0
- package/dist/tools/vault.js +198 -1
- package/package.json +1 -1
package/dist/convex.js
CHANGED
|
@@ -54,7 +54,9 @@ async function callConvex(path, method, body, toolName = "unknown") {
|
|
|
54
54
|
const paymentHeader = process.env.NOELCLAW_PAYMENT_HEADER;
|
|
55
55
|
if (paymentHeader)
|
|
56
56
|
headers["X-Payment"] = paymentHeader;
|
|
57
|
-
// BYOK headers
|
|
57
|
+
// BYOK headers — user pays for their own AI/service costs
|
|
58
|
+
if (process.env.ANTHROPIC_API_KEY)
|
|
59
|
+
headers["X-User-Anthropic-Key"] = process.env.ANTHROPIC_API_KEY;
|
|
58
60
|
if (process.env.GROK_API_KEY)
|
|
59
61
|
headers["X-User-Grok-Key"] = process.env.GROK_API_KEY;
|
|
60
62
|
if (process.env.BANKR_API_KEY)
|
package/dist/index.js
CHANGED
|
@@ -3,29 +3,84 @@
|
|
|
3
3
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
4
|
const server_js_1 = require("./server.js");
|
|
5
5
|
const wallet_js_1 = require("./wallet.js");
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
6
|
+
// ── ANSI helpers ──────────────────────────────────────────────────────────────
|
|
7
|
+
const C = {
|
|
8
|
+
cyan: "\x1b[36m",
|
|
9
|
+
dim: "\x1b[90m",
|
|
10
|
+
white: "\x1b[97m",
|
|
11
|
+
green: "\x1b[32m",
|
|
12
|
+
yellow: "\x1b[33m",
|
|
13
|
+
reset: "\x1b[0m",
|
|
14
|
+
bold: "\x1b[1m",
|
|
15
|
+
};
|
|
16
|
+
const BANNER = `
|
|
17
|
+
${C.cyan}
|
|
18
|
+
███╗ ██╗ ██████╗ ███████╗██╗ ██████╗██╗ █████╗ ██╗ ██╗
|
|
19
|
+
████╗ ██║██╔═══██╗██╔════╝██║ ██╔════╝██║ ██╔══██╗██║ ██║
|
|
20
|
+
██╔██╗ ██║██║ ██║█████╗ ██║ ██║ ██║ ███████║██║ █╗ ██║
|
|
21
|
+
██║╚██╗██║██║ ██║██╔══╝ ██║ ██║ ██║ ██╔══██║██║███╗██║
|
|
22
|
+
██║ ╚████║╚██████╔╝███████╗███████╗╚██████╗███████╗██║ ██║╚███╔███╔╝
|
|
23
|
+
╚═╝ ╚═══╝ ╚═════╝ ╚══════╝╚══════╝ ╚═════╝╚══════╝╚═╝ ╚═╝ ╚══╝╚══╝
|
|
24
|
+
${C.reset}`;
|
|
25
|
+
function line(label, value, color = C.cyan) {
|
|
26
|
+
const pad = " ".repeat(Math.max(0, 12 - label.length));
|
|
27
|
+
process.stderr.write(` ${color}◆ ${label}${C.reset}${pad}${value}\n`);
|
|
28
|
+
}
|
|
29
|
+
function divider() {
|
|
30
|
+
process.stderr.write(` ${C.dim}${"─".repeat(58)}${C.reset}\n`);
|
|
31
|
+
}
|
|
16
32
|
async function main() {
|
|
17
|
-
|
|
33
|
+
process.stderr.write(BANNER);
|
|
34
|
+
// ── Tool category counts ──────────────────────────────────────────────────
|
|
35
|
+
const categories = [
|
|
36
|
+
{ label: "Market", count: 3, tools: "get_market_data · get_token_data · ask_noel" },
|
|
37
|
+
{ label: "DeFi", count: 5, tools: "portfolio · swap · send · scan_wallet · estimate" },
|
|
38
|
+
{ label: "Automation", count: 5, tools: "create · list · pause · delete · runs" },
|
|
39
|
+
{ label: "Scanner", count: 3, tools: "scan_dips · score_token · check_token" },
|
|
40
|
+
{ label: "Agents", count: 2, tools: "list_agents · hire_agent" },
|
|
41
|
+
{ label: "Swarm", count: 6, tools: "start · stop · status · read_memory · write_memory · scores" },
|
|
42
|
+
{ label: "Framework", count: 6, tools: "create_task · list_tasks · list_playbooks · run_playbook · ledger · sentinel" },
|
|
43
|
+
{ label: "Vault", count: 7, tools: "save · read · list · search · history · diff · export" },
|
|
44
|
+
{ label: "MiroShark", count: 3, tools: "simulate · status · stop" },
|
|
45
|
+
{ label: "Wallet", count: 2, tools: "get_wallet_address · set_telegram" },
|
|
46
|
+
{ label: "Social", count: 1, tools: "humanize_text" },
|
|
47
|
+
{ label: "Coder", count: 6, tools: "scaffold_project · generate_component · generate_contract · audit_contract · explain_code · review_code" },
|
|
48
|
+
{ label: "Base", count: 4, tools: "query_vaults · list_markets · prepare_deposit · chain_stats" },
|
|
49
|
+
];
|
|
50
|
+
const total = server_js_1.ALL_TOOLS.length;
|
|
51
|
+
divider();
|
|
52
|
+
process.stderr.write(`\n`);
|
|
53
|
+
line("version", `v2.0.0 ${C.dim}MCP protocol 2.1.0${C.reset}`);
|
|
54
|
+
line("network", `Base mainnet ${C.dim}via 0x Protocol · ethers v6${C.reset}`);
|
|
55
|
+
line("ai", `Bankr LLM ${C.dim}grok-3 · llm.bankr.bot${C.reset}`);
|
|
56
|
+
line("tools", `${C.white}${C.bold}${total} tools loaded${C.reset} ${C.dim}across ${categories.length} categories${C.reset}`);
|
|
57
|
+
process.stderr.write(`\n`);
|
|
58
|
+
divider();
|
|
59
|
+
process.stderr.write(`\n`);
|
|
60
|
+
// ── Categories grid ───────────────────────────────────────────────────────
|
|
61
|
+
for (const cat of categories) {
|
|
62
|
+
const countStr = `${cat.count}`.padStart(2);
|
|
63
|
+
process.stderr.write(` ${C.dim}│${C.reset} ${C.cyan}${cat.label.padEnd(11)}${C.reset} ${C.dim}${countStr}x${C.reset} ${C.dim}${cat.tools}${C.reset}\n`);
|
|
64
|
+
}
|
|
65
|
+
process.stderr.write(`\n`);
|
|
66
|
+
divider();
|
|
67
|
+
// ── Wallet ────────────────────────────────────────────────────────────────
|
|
18
68
|
await (0, server_js_1.startServer)();
|
|
19
69
|
try {
|
|
20
70
|
const wallet = await (0, wallet_js_1.getOrCreateWallet)();
|
|
21
|
-
|
|
22
|
-
|
|
71
|
+
process.stderr.write(`\n`);
|
|
72
|
+
line("wallet", wallet.address);
|
|
73
|
+
line("status", `${C.green}ready${C.reset} ${C.dim}waiting for MCP client...${C.reset}`, C.green);
|
|
74
|
+
process.stderr.write(`\n`);
|
|
23
75
|
}
|
|
24
|
-
catch
|
|
25
|
-
|
|
76
|
+
catch {
|
|
77
|
+
process.stderr.write(`\n`);
|
|
78
|
+
line("wallet", `${C.yellow}not configured${C.reset} ${C.dim}run 'noelclaw-mcp' to init${C.reset}`, C.yellow);
|
|
79
|
+
line("status", `${C.green}ready${C.reset} ${C.dim}wallet tools require setup${C.reset}`, C.green);
|
|
80
|
+
process.stderr.write(`\n`);
|
|
26
81
|
}
|
|
27
82
|
}
|
|
28
83
|
main().catch((err) => {
|
|
29
|
-
|
|
84
|
+
process.stderr.write(`[noelclaw] fatal: ${err}\n`);
|
|
30
85
|
process.exit(1);
|
|
31
86
|
});
|
package/dist/llm.js
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.callLLM = callLLM;
|
|
4
|
+
const ANTHROPIC_URL = "https://api.anthropic.com/v1/messages";
|
|
5
|
+
const BANKR_URL = "https://llm.bankr.bot/v1/chat/completions";
|
|
6
|
+
/**
|
|
7
|
+
* Call the best available LLM.
|
|
8
|
+
* Priority: ANTHROPIC_API_KEY → BANKR_API_KEY → throws
|
|
9
|
+
* Claude Desktop automatically injects ANTHROPIC_API_KEY, so users
|
|
10
|
+
* pay for their own AI usage without the server owner absorbing the cost.
|
|
11
|
+
*/
|
|
12
|
+
async function callLLM(systemPrompt, userPrompt, maxTokens = 1024, history = [], timeoutMs = 60000) {
|
|
13
|
+
const anthropicKey = process.env.ANTHROPIC_API_KEY;
|
|
14
|
+
const bankrKey = process.env.BANKR_API_KEY;
|
|
15
|
+
if (anthropicKey)
|
|
16
|
+
return callAnthropic(anthropicKey, systemPrompt, userPrompt, maxTokens, history, timeoutMs);
|
|
17
|
+
if (bankrKey)
|
|
18
|
+
return callBankr(bankrKey, systemPrompt, userPrompt, maxTokens, history, timeoutMs);
|
|
19
|
+
throw new Error("No LLM API key available. Claude Desktop users: make sure ANTHROPIC_API_KEY is in your MCP config. " +
|
|
20
|
+
"Standalone users: set BANKR_API_KEY.");
|
|
21
|
+
}
|
|
22
|
+
async function callAnthropic(apiKey, systemPrompt, userPrompt, maxTokens, history, timeoutMs) {
|
|
23
|
+
const messages = [...history, { role: "user", content: userPrompt }];
|
|
24
|
+
const model = process.env.ANTHROPIC_MODEL ?? "claude-haiku-4-5-20251001";
|
|
25
|
+
const res = await fetch(ANTHROPIC_URL, {
|
|
26
|
+
method: "POST",
|
|
27
|
+
headers: {
|
|
28
|
+
"Content-Type": "application/json",
|
|
29
|
+
"x-api-key": apiKey,
|
|
30
|
+
"anthropic-version": "2023-06-01",
|
|
31
|
+
},
|
|
32
|
+
body: JSON.stringify({ model, max_tokens: maxTokens, system: systemPrompt, messages }),
|
|
33
|
+
signal: AbortSignal.timeout(timeoutMs),
|
|
34
|
+
});
|
|
35
|
+
if (!res.ok) {
|
|
36
|
+
const body = await res.text().catch(() => "");
|
|
37
|
+
throw new Error(`Anthropic error ${res.status}: ${body.slice(0, 200)}`);
|
|
38
|
+
}
|
|
39
|
+
const data = await res.json();
|
|
40
|
+
return data.content?.find(b => b.type === "text")?.text ?? "";
|
|
41
|
+
}
|
|
42
|
+
async function callBankr(apiKey, systemPrompt, userPrompt, maxTokens, history, timeoutMs) {
|
|
43
|
+
const model = process.env.BANKR_MODEL ?? "grok-3";
|
|
44
|
+
const res = await fetch(BANKR_URL, {
|
|
45
|
+
method: "POST",
|
|
46
|
+
headers: { "Content-Type": "application/json", "X-API-Key": apiKey },
|
|
47
|
+
body: JSON.stringify({
|
|
48
|
+
model,
|
|
49
|
+
messages: [
|
|
50
|
+
{ role: "system", content: systemPrompt },
|
|
51
|
+
...history,
|
|
52
|
+
{ role: "user", content: userPrompt },
|
|
53
|
+
],
|
|
54
|
+
max_tokens: maxTokens,
|
|
55
|
+
}),
|
|
56
|
+
signal: AbortSignal.timeout(timeoutMs),
|
|
57
|
+
});
|
|
58
|
+
if (!res.ok) {
|
|
59
|
+
const body = await res.text().catch(() => "");
|
|
60
|
+
throw new Error(`Bankr error ${res.status}: ${body.slice(0, 200)}`);
|
|
61
|
+
}
|
|
62
|
+
const data = await res.json();
|
|
63
|
+
return data.choices?.[0]?.message?.content ?? "";
|
|
64
|
+
}
|
package/dist/server.js
CHANGED
|
@@ -7,22 +7,23 @@ const stdio_js_1 = require("@modelcontextprotocol/sdk/server/stdio.js");
|
|
|
7
7
|
const types_js_1 = require("@modelcontextprotocol/sdk/types.js");
|
|
8
8
|
const convex_js_1 = require("./convex.js");
|
|
9
9
|
const market_js_1 = require("./tools/market.js");
|
|
10
|
-
const research_js_1 = require("./tools/research.js");
|
|
11
10
|
const defi_js_1 = require("./tools/defi.js");
|
|
12
11
|
const automation_js_1 = require("./tools/automation.js");
|
|
13
12
|
const swarm_js_1 = require("./tools/swarm.js");
|
|
14
13
|
const insight_js_1 = require("./tools/insight.js");
|
|
15
14
|
const framework_js_1 = require("./tools/framework.js");
|
|
16
15
|
const wallet_js_1 = require("./tools/wallet.js");
|
|
17
|
-
const news_js_1 = require("./tools/news.js");
|
|
18
16
|
const vault_js_1 = require("./tools/vault.js");
|
|
19
|
-
const twitter_js_1 = require("./tools/twitter.js");
|
|
20
17
|
const miroshark_js_1 = require("./tools/miroshark.js");
|
|
21
18
|
const humanizer_js_1 = require("./tools/humanizer.js");
|
|
19
|
+
const agents_js_1 = require("./tools/agents.js");
|
|
20
|
+
const scanner_js_1 = require("./tools/scanner.js");
|
|
21
|
+
const coder_js_1 = require("./tools/coder.js");
|
|
22
|
+
const base_js_1 = require("./tools/base.js");
|
|
22
23
|
const PRIVATE_KEY_RESPONSE = {
|
|
23
24
|
content: [{
|
|
24
25
|
type: "text",
|
|
25
|
-
text: "I don't have access to your private key. Your wallet is secured by Noelclaw's encrypted vault. Only you can manage it at noelclaw.
|
|
26
|
+
text: "I don't have access to your private key. Your wallet is secured by Noelclaw's encrypted vault. Only you can manage it at noelclaw.com",
|
|
26
27
|
}],
|
|
27
28
|
};
|
|
28
29
|
function containsSensitiveRequest(args) {
|
|
@@ -33,20 +34,23 @@ function containsSensitiveRequest(args) {
|
|
|
33
34
|
text.includes("privatekey"));
|
|
34
35
|
}
|
|
35
36
|
exports.ALL_TOOLS = [
|
|
36
|
-
...market_js_1.MARKET_TOOLS, // 2 —
|
|
37
|
+
...market_js_1.MARKET_TOOLS, // 2 — get_market_data, get_token_data
|
|
37
38
|
...insight_js_1.INSIGHT_TOOLS, // 1 — ask_noel
|
|
38
|
-
...defi_js_1.DEFI_TOOLS, //
|
|
39
|
-
...automation_js_1.AUTOMATION_TOOLS, //
|
|
40
|
-
...swarm_js_1.SWARM_TOOLS, //
|
|
39
|
+
...defi_js_1.DEFI_TOOLS, // 5 — get_portfolio, estimate_swap, swap_tokens, send_token, scan_wallet
|
|
40
|
+
...automation_js_1.AUTOMATION_TOOLS, // 5 — create, list, pause, delete, get_runs
|
|
41
|
+
...swarm_js_1.SWARM_TOOLS, // 9 — start, stop, status, read/write memory, scores, research, brief, trigger_agent
|
|
41
42
|
...framework_js_1.FRAMEWORK_TOOLS, // 6 — task packets, playbooks, sentinel, ledger
|
|
42
|
-
...vault_js_1.VAULT_TOOLS, //
|
|
43
|
-
...wallet_js_1.WALLET_TOOLS, // 2 —
|
|
44
|
-
...
|
|
45
|
-
...miroshark_js_1.MIROSHARK_TOOLS, // 2 — simulate, status
|
|
43
|
+
...vault_js_1.VAULT_TOOLS, // 13 — save, read, list, search, history, diff, export, remember, context, store_credential, get_credential, publish, explore
|
|
44
|
+
...wallet_js_1.WALLET_TOOLS, // 2 — get_wallet_address, set_telegram
|
|
45
|
+
...miroshark_js_1.MIROSHARK_TOOLS, // 3 — simulate, status, stop
|
|
46
46
|
...humanizer_js_1.HUMANIZER_TOOLS, // 1 — humanize_text
|
|
47
|
-
//
|
|
47
|
+
...agents_js_1.AGENT_TOOLS, // 2 — list_agents, hire_agent
|
|
48
|
+
...scanner_js_1.SCANNER_TOOLS, // 3 — score_token, check_token, scan_dips
|
|
49
|
+
...coder_js_1.CODER_TOOLS, // 6 — scaffold_project, generate_component, generate_contract, audit_contract, explain_code, review_code
|
|
50
|
+
...base_js_1.BASE_TOOLS, // 4 — query_vaults, list_markets, prepare_deposit, chain_stats
|
|
51
|
+
// total: 62
|
|
48
52
|
];
|
|
49
|
-
exports.server = new index_js_1.Server({ name: "noelclaw", version: "2.
|
|
53
|
+
exports.server = new index_js_1.Server({ name: "noelclaw", version: "2.2.0" }, { capabilities: { tools: {} } });
|
|
50
54
|
exports.server.setRequestHandler(types_js_1.ListToolsRequestSchema, async () => ({ tools: exports.ALL_TOOLS }));
|
|
51
55
|
exports.server.setRequestHandler(types_js_1.CallToolRequestSchema, async (request) => {
|
|
52
56
|
const { name, arguments: args } = request.params;
|
|
@@ -54,8 +58,6 @@ exports.server.setRequestHandler(types_js_1.CallToolRequestSchema, async (reques
|
|
|
54
58
|
return PRIVATE_KEY_RESPONSE;
|
|
55
59
|
try {
|
|
56
60
|
const result = await (0, market_js_1.handleMarketTool)(name, args) ??
|
|
57
|
-
await (0, news_js_1.handleNewsTool)(name, args) ??
|
|
58
|
-
await (0, research_js_1.handleResearchTool)(name, args) ??
|
|
59
61
|
await (0, defi_js_1.handleDefiTool)(name, args) ??
|
|
60
62
|
await (0, automation_js_1.handleAutomationTool)(name, args) ??
|
|
61
63
|
await (0, swarm_js_1.handleSwarmTool)(name, args) ??
|
|
@@ -63,9 +65,12 @@ exports.server.setRequestHandler(types_js_1.CallToolRequestSchema, async (reques
|
|
|
63
65
|
await (0, vault_js_1.handleVaultTool)(name, args) ??
|
|
64
66
|
await (0, wallet_js_1.handleWalletTool)(name, args) ??
|
|
65
67
|
await (0, insight_js_1.handleInsightTool)(name, args) ??
|
|
66
|
-
await (0, twitter_js_1.handleTwitterTool)(name, args) ??
|
|
67
68
|
await (0, miroshark_js_1.handleMirosharkTool)(name, args) ??
|
|
68
|
-
await (0, humanizer_js_1.handleHumanizerTool)(name, args)
|
|
69
|
+
await (0, humanizer_js_1.handleHumanizerTool)(name, args) ??
|
|
70
|
+
await (0, agents_js_1.handleAgentTool)(name, args) ??
|
|
71
|
+
await (0, scanner_js_1.handleScannerTool)(name, args) ??
|
|
72
|
+
await (0, coder_js_1.handleCoderTool)(name, args) ??
|
|
73
|
+
await (0, base_js_1.handleBaseTool)(name, args);
|
|
69
74
|
if (result)
|
|
70
75
|
return result;
|
|
71
76
|
return { content: [{ type: "text", text: `Unknown tool: ${name}` }], isError: true };
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.AGENT_TOOLS = void 0;
|
|
4
|
+
exports.handleAgentTool = handleAgentTool;
|
|
5
|
+
const zod_1 = require("zod");
|
|
6
|
+
const convex_js_1 = require("../convex.js");
|
|
7
|
+
exports.AGENT_TOOLS = [
|
|
8
|
+
{
|
|
9
|
+
name: "list_agents",
|
|
10
|
+
description: "List all available specialist agents you can hire — built-in experts (analyst, risk-manager, researcher, executor, scout) plus any community-published agents.",
|
|
11
|
+
inputSchema: { type: "object", properties: {}, required: [] },
|
|
12
|
+
},
|
|
13
|
+
{
|
|
14
|
+
name: "hire_agent",
|
|
15
|
+
description: "Hire a specialist agent to complete a task. The agent runs immediately with its own expertise and returns a focused analysis or execution plan. Use list_agents first to see what's available.",
|
|
16
|
+
inputSchema: {
|
|
17
|
+
type: "object",
|
|
18
|
+
properties: {
|
|
19
|
+
agentId: {
|
|
20
|
+
type: "string",
|
|
21
|
+
description: "Agent ID from list_agents. Built-in: analyst, risk-manager, researcher, executor, scout. Or a custom agent ID.",
|
|
22
|
+
},
|
|
23
|
+
task: {
|
|
24
|
+
type: "string",
|
|
25
|
+
description: "The task or question for the agent. Be specific — better input = better output.",
|
|
26
|
+
},
|
|
27
|
+
maxTokens: {
|
|
28
|
+
type: "number",
|
|
29
|
+
description: "Max response tokens (default 800, max 1200). Lower is faster and cheaper.",
|
|
30
|
+
},
|
|
31
|
+
},
|
|
32
|
+
required: ["agentId", "task"],
|
|
33
|
+
},
|
|
34
|
+
},
|
|
35
|
+
];
|
|
36
|
+
const HireAgentSchema = zod_1.z.object({
|
|
37
|
+
agentId: zod_1.z.string().min(1),
|
|
38
|
+
task: zod_1.z.string().min(1),
|
|
39
|
+
maxTokens: zod_1.z.number().int().min(100).max(1200).optional(),
|
|
40
|
+
});
|
|
41
|
+
async function handleAgentTool(name, args) {
|
|
42
|
+
if (name === "list_agents") {
|
|
43
|
+
const data = await (0, convex_js_1.callConvex)("/agents/list", "GET", undefined, "list_agents");
|
|
44
|
+
const agents = data.agents ?? [];
|
|
45
|
+
const lines = agents.map((a) => {
|
|
46
|
+
const badge = a.pricingType === "free" ? "free" : "token-based";
|
|
47
|
+
const runs = a.runs != null ? ` · ${a.runs} runs` : "";
|
|
48
|
+
return `**${a.name}** (\`${a.id}\`) [${badge}${runs}]\n ${a.description}`;
|
|
49
|
+
});
|
|
50
|
+
return {
|
|
51
|
+
content: [{
|
|
52
|
+
type: "text",
|
|
53
|
+
text: `## Available Agents (${agents.length})\n\n${lines.join("\n\n")}`,
|
|
54
|
+
}],
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
if (name === "hire_agent") {
|
|
58
|
+
const parsed = HireAgentSchema.safeParse(args);
|
|
59
|
+
if (!parsed.success) {
|
|
60
|
+
return {
|
|
61
|
+
content: [{ type: "text", text: `Invalid input: ${parsed.error.issues[0].message}` }],
|
|
62
|
+
isError: true,
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
const { agentId, task, maxTokens } = parsed.data;
|
|
66
|
+
const data = await (0, convex_js_1.callConvex)("/agents/hire", "POST", { agentId, task, maxTokens }, "hire_agent");
|
|
67
|
+
if (data.error) {
|
|
68
|
+
return { content: [{ type: "text", text: `Error: ${data.error}` }], isError: true };
|
|
69
|
+
}
|
|
70
|
+
const footer = data.tokensUsed ? `\n\n*Tokens used: ${data.tokensUsed}*` : "";
|
|
71
|
+
return {
|
|
72
|
+
content: [{
|
|
73
|
+
type: "text",
|
|
74
|
+
text: `## ${data.agent ?? agentId} — Response\n\n${data.result}${footer}`,
|
|
75
|
+
}],
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
return null;
|
|
79
|
+
}
|
package/dist/tools/automation.js
CHANGED
|
@@ -37,9 +37,22 @@ exports.AUTOMATION_TOOLS = [
|
|
|
37
37
|
required: ["automationId"],
|
|
38
38
|
},
|
|
39
39
|
},
|
|
40
|
+
{
|
|
41
|
+
name: "get_automation_runs",
|
|
42
|
+
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.",
|
|
43
|
+
inputSchema: {
|
|
44
|
+
type: "object",
|
|
45
|
+
properties: {
|
|
46
|
+
automationId: { type: "string", description: "Automation ID (from list_automations)" },
|
|
47
|
+
limit: { type: "number", description: "Max runs to return (default 20)" },
|
|
48
|
+
},
|
|
49
|
+
required: ["automationId"],
|
|
50
|
+
},
|
|
51
|
+
},
|
|
40
52
|
];
|
|
41
53
|
const CreateAutomationSchema = zod_1.z.object({ rawInput: zod_1.z.string().min(1) });
|
|
42
54
|
const AutomationIdSchema = zod_1.z.object({ automationId: zod_1.z.string().min(1) });
|
|
55
|
+
const RunsSchema = zod_1.z.object({ automationId: zod_1.z.string().min(1), limit: zod_1.z.number().int().min(1).max(100).optional() });
|
|
43
56
|
async function handleAutomationTool(name, args) {
|
|
44
57
|
switch (name) {
|
|
45
58
|
case "create_automation": {
|
|
@@ -110,6 +123,31 @@ async function handleAutomationTool(name, args) {
|
|
|
110
123
|
return { content: [{ type: "text", text: `Error: ${data.error}` }], isError: true };
|
|
111
124
|
return { content: [{ type: "text", text: "🗑️ Automation deleted." }] };
|
|
112
125
|
}
|
|
126
|
+
case "get_automation_runs": {
|
|
127
|
+
const parsed = RunsSchema.safeParse(args);
|
|
128
|
+
if (!parsed.success)
|
|
129
|
+
return { content: [{ type: "text", text: `Invalid input: automationId ${parsed.error.issues[0].message}` }], isError: true };
|
|
130
|
+
const { automationId, limit = 20 } = parsed.data;
|
|
131
|
+
const qs = `automationId=${encodeURIComponent(automationId)}&limit=${limit}`;
|
|
132
|
+
const data = await (0, convex_js_1.callConvex)(`/automations/runs?${qs}`, "GET", undefined, "get_automation_runs");
|
|
133
|
+
if (data.error)
|
|
134
|
+
return { content: [{ type: "text", text: `Error: ${data.error}` }], isError: true };
|
|
135
|
+
const runs = data.runs ?? [];
|
|
136
|
+
if (!runs.length)
|
|
137
|
+
return { content: [{ type: "text", text: "No runs yet for this automation." }] };
|
|
138
|
+
const statusIcon = { success: "✅", failed: "❌", skipped: "⏭️" };
|
|
139
|
+
const lines = [`**Run History** (${runs.length} shown)`, ""];
|
|
140
|
+
for (const r of runs) {
|
|
141
|
+
const icon = statusIcon[r.status] ?? "•";
|
|
142
|
+
const time = new Date(r.triggeredAt).toUTCString();
|
|
143
|
+
const spent = r.amountUsd != null ? ` · $${Number(r.amountUsd).toFixed(2)}` : "";
|
|
144
|
+
const tx = r.txHash ? ` · [tx](https://basescan.org/tx/${r.txHash})` : "";
|
|
145
|
+
lines.push(`${icon} **${r.status}**${spent}${tx} — ${time}`);
|
|
146
|
+
if (r.error)
|
|
147
|
+
lines.push(` ⚠️ ${r.error}`);
|
|
148
|
+
}
|
|
149
|
+
return { content: [{ type: "text", text: lines.join("\n") }] };
|
|
150
|
+
}
|
|
113
151
|
default:
|
|
114
152
|
return null;
|
|
115
153
|
}
|