@nookplot/cli 0.6.79 → 0.6.80
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/commands/gpu.d.ts +11 -6
- package/dist/commands/gpu.js +479 -6
- package/dist/commands/gpu.js.map +1 -1
- package/dist/commands/listen.js +1220 -16
- package/dist/commands/listen.js.map +1 -1
- package/dist/utils/agentLoop.js +962 -17
- package/dist/utils/agentLoop.js.map +1 -1
- package/package.json +2 -2
package/dist/commands/listen.js
CHANGED
|
@@ -45,6 +45,116 @@ const VALID_EVENT_TYPES = new Set([
|
|
|
45
45
|
"proactive.action.completed",
|
|
46
46
|
"proactive.signal",
|
|
47
47
|
]);
|
|
48
|
+
// ── Autoresearch: strategy definitions + TSV parser ──────────────
|
|
49
|
+
// Ported from mcp-server/src/tools/autoresearch.ts so CLI can execute
|
|
50
|
+
// these tools natively without routing through MCP infrastructure.
|
|
51
|
+
const AUTORESEARCH_STRATEGIES = {
|
|
52
|
+
architecture_search: {
|
|
53
|
+
title: "Architecture Search",
|
|
54
|
+
description: "Explore architectural modifications to the transformer model.",
|
|
55
|
+
subtasks: [
|
|
56
|
+
{ title: "Attention pattern exploration", description: "Experiment with attention mechanisms: sliding window, flash attention, multi-head vs multi-query, grouped-query attention.", skillTags: ["ml-research", "attention", "transformers"] },
|
|
57
|
+
{ title: "Layer depth vs width tradeoff", description: "Explore depth-width tradeoff within 5-minute budget. Try deeper-narrower and shallower-wider configurations.", skillTags: ["ml-research", "architecture", "scaling"] },
|
|
58
|
+
{ title: "Normalization and residual connections", description: "Experiment with RMSNorm placement, pre-norm vs post-norm, residual scaling, value embedding gating.", skillTags: ["ml-research", "normalization", "residuals"] },
|
|
59
|
+
{ title: "Activation functions and FFN variants", description: "Test GELU, SwiGLU, ReLU^2 and FFN architectures within 5-min window.", skillTags: ["ml-research", "activations", "ffn"] },
|
|
60
|
+
],
|
|
61
|
+
},
|
|
62
|
+
optimizer_tuning: {
|
|
63
|
+
title: "Optimizer Tuning",
|
|
64
|
+
description: "Systematic exploration of optimizer configurations.",
|
|
65
|
+
subtasks: [
|
|
66
|
+
{ title: "Learning rate schedules", description: "Explore LR warmup, decay, scheduling strategies. Test peak LRs, warmup durations, cosine vs linear decay.", skillTags: ["ml-research", "optimizer", "learning-rate"] },
|
|
67
|
+
{ title: "Muon vs AdamW allocation", description: "Experiment with Muon vs AdamW parameter allocation, momentum values, nesterov settings.", skillTags: ["ml-research", "optimizer", "muon"] },
|
|
68
|
+
{ title: "Regularization and weight decay", description: "Explore weight decay schedules, dropout patterns, gradient clipping strategies.", skillTags: ["ml-research", "optimizer", "regularization"] },
|
|
69
|
+
{ title: "Batch size and gradient accumulation", description: "Test different effective batch sizes via gradient accumulation within 5-minute budget.", skillTags: ["ml-research", "optimizer", "batch-size"] },
|
|
70
|
+
],
|
|
71
|
+
},
|
|
72
|
+
full_sweep: {
|
|
73
|
+
title: "Full Parameter Sweep",
|
|
74
|
+
description: "Comprehensive sweep across all optimization dimensions.",
|
|
75
|
+
subtasks: [
|
|
76
|
+
{ title: "Architecture innovations", description: "Focus on model architecture: attention, layers, dims, activations, embeddings.", skillTags: ["ml-research", "architecture"] },
|
|
77
|
+
{ title: "Training dynamics", description: "Focus on training: optimizer, LR, batch size, warmup, weight decay.", skillTags: ["ml-research", "training"] },
|
|
78
|
+
{ title: "Efficiency optimization", description: "Reduce VRAM while maintaining val_bpb. Explore quantization-friendly architectures, memory-efficient attention.", skillTags: ["ml-research", "efficiency"] },
|
|
79
|
+
],
|
|
80
|
+
},
|
|
81
|
+
};
|
|
82
|
+
function classifyAutoresearchCategory(description) {
|
|
83
|
+
const desc = description.toLowerCase();
|
|
84
|
+
if (["attention", "flash", "sliding", "causal", "head"].some((w) => desc.includes(w)))
|
|
85
|
+
return "attention";
|
|
86
|
+
if (["lr", "learning rate", "warmup", "cooldown", "schedule"].some((w) => desc.includes(w)))
|
|
87
|
+
return "learning_rate";
|
|
88
|
+
if (["muon", "adamw", "optimizer", "momentum", "weight decay"].some((w) => desc.includes(w)))
|
|
89
|
+
return "optimizer";
|
|
90
|
+
if (["layer", "depth", "dim", "hidden", "embed", "width"].some((w) => desc.includes(w)))
|
|
91
|
+
return "architecture";
|
|
92
|
+
if (["batch", "gradient", "accumulation"].some((w) => desc.includes(w)))
|
|
93
|
+
return "batch_size";
|
|
94
|
+
if (["norm", "rmsnorm", "layernorm"].some((w) => desc.includes(w)))
|
|
95
|
+
return "normalization";
|
|
96
|
+
if (["dropout", "regulariz", "weight tying"].some((w) => desc.includes(w)))
|
|
97
|
+
return "regularization";
|
|
98
|
+
if (["activation", "gelu", "swiglu", "relu"].some((w) => desc.includes(w)))
|
|
99
|
+
return "activation";
|
|
100
|
+
if (["positional", "rotary", "rope", "alibi"].some((w) => desc.includes(w)))
|
|
101
|
+
return "positional_encoding";
|
|
102
|
+
return "other";
|
|
103
|
+
}
|
|
104
|
+
function parseAutoresearchTsv(tsvContent, sinceCommit) {
|
|
105
|
+
const lines = tsvContent.trim().split("\n");
|
|
106
|
+
if (lines.length < 2)
|
|
107
|
+
return { totalExperiments: 0, improvements: 0, successRate: "0%", bestBpb: null, categories: {}, experiments: [], topImprovements: [] };
|
|
108
|
+
let prevBest = Infinity;
|
|
109
|
+
const experiments = [];
|
|
110
|
+
const categories = {};
|
|
111
|
+
let bestBpb = Infinity;
|
|
112
|
+
let improvementCount = 0;
|
|
113
|
+
for (let i = 1; i < lines.length; i++) {
|
|
114
|
+
const cols = lines[i].split("\t");
|
|
115
|
+
if (cols.length < 5)
|
|
116
|
+
continue;
|
|
117
|
+
const commitHash = cols[0].trim();
|
|
118
|
+
const valBpb = parseFloat(cols[1].trim());
|
|
119
|
+
if (isNaN(valBpb))
|
|
120
|
+
continue;
|
|
121
|
+
const peakVramMb = parseFloat(cols[2].trim()) || 0;
|
|
122
|
+
const status = cols[3].trim();
|
|
123
|
+
const description = cols[4].trim();
|
|
124
|
+
const improvement = prevBest < Infinity ? valBpb - prevBest : null;
|
|
125
|
+
const isImprovement = improvement !== null && improvement < 0;
|
|
126
|
+
const category = classifyAutoresearchCategory(description);
|
|
127
|
+
experiments.push({ commit: commitHash.slice(0, 8), valBpb, peakVramMb, status, description, category, improvement, isImprovement });
|
|
128
|
+
if (isImprovement) {
|
|
129
|
+
improvementCount++;
|
|
130
|
+
prevBest = valBpb;
|
|
131
|
+
}
|
|
132
|
+
else if (prevBest === Infinity && status === "baseline") {
|
|
133
|
+
prevBest = valBpb;
|
|
134
|
+
}
|
|
135
|
+
if (valBpb < bestBpb)
|
|
136
|
+
bestBpb = valBpb;
|
|
137
|
+
categories[category] = (categories[category] || 0) + 1;
|
|
138
|
+
}
|
|
139
|
+
let filtered = experiments;
|
|
140
|
+
if (sinceCommit) {
|
|
141
|
+
const idx = filtered.findIndex((e) => e.commit.startsWith(sinceCommit));
|
|
142
|
+
if (idx >= 0)
|
|
143
|
+
filtered = filtered.slice(idx + 1);
|
|
144
|
+
}
|
|
145
|
+
const improvements = filtered.filter((e) => e.isImprovement);
|
|
146
|
+
return {
|
|
147
|
+
totalExperiments: experiments.length,
|
|
148
|
+
improvements: improvementCount,
|
|
149
|
+
successRate: `${(experiments.length > 0 ? (improvementCount / experiments.length) * 100 : 0).toFixed(1)}%`,
|
|
150
|
+
bestBpb: bestBpb === Infinity ? null : bestBpb,
|
|
151
|
+
categories,
|
|
152
|
+
experiments: filtered,
|
|
153
|
+
topImprovements: improvements.sort((a, b) => a.valBpb - b.valBpb).slice(0, 5).map((e) => ({
|
|
154
|
+
commit: e.commit, valBpb: e.valBpb, delta: e.improvement, description: e.description, category: e.category,
|
|
155
|
+
})),
|
|
156
|
+
};
|
|
157
|
+
}
|
|
48
158
|
/**
|
|
49
159
|
* Register the `nookplot listen` command.
|
|
50
160
|
*/
|
|
@@ -401,6 +511,7 @@ function _getAvailableActionsRaw(signalType) {
|
|
|
401
511
|
"list_project_files", "read_project_file", "list_commits", "get_commit_detail",
|
|
402
512
|
"gpu_search", "gpu_heartbeat", "gpu_challenge", "gpu_submit_challenge",
|
|
403
513
|
"gpu_submit_attestation", "gpu_update_attestation", "gpu_revoke_attestation",
|
|
514
|
+
"gpu_rent",
|
|
404
515
|
"ignore",
|
|
405
516
|
];
|
|
406
517
|
case "collab_request":
|
|
@@ -554,6 +665,7 @@ async function executeAgentAction(runtime, action, signal, json) {
|
|
|
554
665
|
const content = action.content || "";
|
|
555
666
|
const channelId = action.channelId || signal.channelId || "";
|
|
556
667
|
try {
|
|
668
|
+
let result; // eslint-disable-line @typescript-eslint/no-unused-vars
|
|
557
669
|
switch (action.action) {
|
|
558
670
|
case "reply":
|
|
559
671
|
if (channelId) {
|
|
@@ -2138,27 +2250,1119 @@ async function executeAgentAction(runtime, action, signal, json) {
|
|
|
2138
2250
|
console.log(chalk.dim(` [reactive] GPU attestation revoked (tx: ${result.txHash})`));
|
|
2139
2251
|
break;
|
|
2140
2252
|
}
|
|
2141
|
-
case "
|
|
2253
|
+
case "gpu_rent": {
|
|
2254
|
+
const listingId = Number(action.listingId);
|
|
2255
|
+
if (!listingId)
|
|
2256
|
+
throw new Error("gpu_rent requires listingId");
|
|
2257
|
+
const result = await runtime.gpu.rentGpu({
|
|
2258
|
+
listingId,
|
|
2259
|
+
terms: action.terms,
|
|
2260
|
+
durationHours: action.durationHours,
|
|
2261
|
+
tokenAmount: action.tokenAmount,
|
|
2262
|
+
tokenAddress: action.tokenAddress,
|
|
2263
|
+
});
|
|
2264
|
+
if (!json)
|
|
2265
|
+
console.log(chalk.dim(` [reactive] GPU rented: listing ${listingId} (tx: ${result.txHash})`));
|
|
2142
2266
|
break;
|
|
2143
|
-
|
|
2144
|
-
|
|
2145
|
-
|
|
2146
|
-
|
|
2147
|
-
|
|
2148
|
-
|
|
2149
|
-
|
|
2150
|
-
|
|
2151
|
-
|
|
2267
|
+
}
|
|
2268
|
+
// ── Autoresearch tools ─────────────────────────────────────
|
|
2269
|
+
case "autoresearch_strategies": {
|
|
2270
|
+
const strategy = action.strategy;
|
|
2271
|
+
result = strategy
|
|
2272
|
+
? { name: strategy, ...(AUTORESEARCH_STRATEGIES[strategy] ?? { error: `Unknown strategy '${strategy}'` }) }
|
|
2273
|
+
: { strategies: Object.entries(AUTORESEARCH_STRATEGIES).map(([n, s]) => ({ name: n, title: s.title, description: s.description, subtaskCount: s.subtasks.length })) };
|
|
2274
|
+
if (!json)
|
|
2275
|
+
console.log(chalk.dim(` [reactive] Autoresearch strategies listed`));
|
|
2276
|
+
break;
|
|
2277
|
+
}
|
|
2278
|
+
case "autoresearch_parse": {
|
|
2279
|
+
const tsv = action.tsvContent;
|
|
2280
|
+
if (!tsv)
|
|
2281
|
+
throw new Error("autoresearch_parse requires tsvContent");
|
|
2282
|
+
result = parseAutoresearchTsv(tsv, action.sinceCommit);
|
|
2283
|
+
if (!json)
|
|
2284
|
+
console.log(chalk.dim(` [reactive] Parsed autoresearch results`));
|
|
2285
|
+
break;
|
|
2286
|
+
}
|
|
2287
|
+
case "autoresearch_launch_swarm": {
|
|
2288
|
+
const strategyName = action.strategy || "full_sweep";
|
|
2289
|
+
const config = AUTORESEARCH_STRATEGIES[strategyName];
|
|
2290
|
+
if (!config)
|
|
2291
|
+
throw new Error(`Unknown strategy '${strategyName}'. Available: ${Object.keys(AUTORESEARCH_STRATEGIES).join(", ")}`);
|
|
2292
|
+
const swarmTitle = action.customTitle || `Autoresearch: ${config.title}`;
|
|
2293
|
+
result = await runtime.connection.request("POST", "/v1/swarms", {
|
|
2294
|
+
title: swarmTitle,
|
|
2295
|
+
description: config.description,
|
|
2296
|
+
workspaceId: action.workspaceId,
|
|
2297
|
+
subtasks: config.subtasks,
|
|
2298
|
+
});
|
|
2299
|
+
if (!json)
|
|
2300
|
+
console.log(chalk.dim(` [reactive] Launched autoresearch swarm: ${swarmTitle}`));
|
|
2301
|
+
break;
|
|
2302
|
+
}
|
|
2303
|
+
case "autoresearch_report": {
|
|
2304
|
+
const experiments = action.experiments;
|
|
2305
|
+
if (!experiments?.length)
|
|
2306
|
+
throw new Error("autoresearch_report requires experiments array");
|
|
2307
|
+
const improvementsOnly = action.improvementsOnly !== false;
|
|
2308
|
+
const reportResult = { memoriesStored: 0, postsCreated: 0, errors: [] };
|
|
2309
|
+
for (const exp of experiments) {
|
|
2310
|
+
const memContent = `Experiment [${exp.commit}]: ${exp.description}. Result: val_bpb=${exp.valBpb}` +
|
|
2311
|
+
(exp.improvement != null ? ` (${exp.improvement > 0 ? "+" : ""}${exp.improvement.toFixed(6)} bpb)` : "") +
|
|
2312
|
+
` — ${exp.isImprovement ? "improved" : "no improvement"}. Category: ${exp.category}. VRAM: ${exp.peakVramMb}MB.`;
|
|
2313
|
+
try {
|
|
2314
|
+
await runtime.connection.request("POST", "/v1/agent-memory/store", {
|
|
2315
|
+
type: "episodic", content: memContent,
|
|
2316
|
+
importance: exp.isImprovement ? 0.8 : 0.3,
|
|
2317
|
+
tags: ["autoresearch", exp.category, exp.isImprovement ? "improvement" : "no-improvement"],
|
|
2318
|
+
source: "autoresearch",
|
|
2319
|
+
});
|
|
2320
|
+
reportResult.memoriesStored++;
|
|
2321
|
+
}
|
|
2322
|
+
catch (e) {
|
|
2323
|
+
reportResult.errors.push(`memory:${exp.commit}: ${e.message || e}`);
|
|
2324
|
+
}
|
|
2325
|
+
if (exp.isImprovement) {
|
|
2326
|
+
try {
|
|
2327
|
+
await prepareSignRelay(runtime.connection, "/v1/prepare/post", {
|
|
2328
|
+
title: `Autoresearch: ${exp.description}`,
|
|
2329
|
+
body: `## Autoresearch Finding: ${exp.description}\n\n**val_bpb:** ${exp.valBpb} (improvement: ${Math.abs(exp.improvement || 0).toFixed(6)})\n**Category:** ${exp.category}\n**VRAM:** ${exp.peakVramMb} MB\n**Commit:** \`${exp.commit}\`\n\nThis experiment was run autonomously using Karpathy's autoresearch framework.`,
|
|
2330
|
+
tags: ["autoresearch", exp.category, "ml-research"],
|
|
2331
|
+
community: action.communityId || "general",
|
|
2332
|
+
});
|
|
2333
|
+
reportResult.postsCreated++;
|
|
2334
|
+
}
|
|
2335
|
+
catch (e) {
|
|
2336
|
+
reportResult.errors.push(`post:${exp.commit}: ${e.message || e}`);
|
|
2337
|
+
}
|
|
2338
|
+
}
|
|
2152
2339
|
}
|
|
2340
|
+
result = reportResult;
|
|
2341
|
+
if (!json)
|
|
2342
|
+
console.log(chalk.dim(` [reactive] Autoresearch report: ${reportResult.memoriesStored} memories, ${reportResult.postsCreated} posts`));
|
|
2343
|
+
break;
|
|
2344
|
+
}
|
|
2345
|
+
case "autoresearch_submit": {
|
|
2346
|
+
const subtaskId = action.subtaskId;
|
|
2347
|
+
if (!subtaskId)
|
|
2348
|
+
throw new Error("autoresearch_submit requires subtaskId");
|
|
2349
|
+
const exps = action.experiments || [];
|
|
2350
|
+
const improvementExps = exps.filter((e) => e.isImprovement);
|
|
2351
|
+
const best = improvementExps.length ? improvementExps.reduce((a, b) => (a.valBpb < b.valBpb ? a : b)) : null;
|
|
2352
|
+
const submitContent = {
|
|
2353
|
+
total_experiments: action.totalExperiments || exps.length,
|
|
2354
|
+
improvements_found: action.improvements || improvementExps.length,
|
|
2355
|
+
success_rate: exps.length ? `${((improvementExps.length / exps.length) * 100).toFixed(1)}%` : "0%",
|
|
2356
|
+
best_bpb: action.bestBpb || (best ? best.valBpb : null),
|
|
2357
|
+
categories_explored: action.categories || {},
|
|
2358
|
+
...(best && { best_experiment: { commit: best.commit, val_bpb: best.valBpb, description: best.description, category: best.category } }),
|
|
2359
|
+
...(improvementExps.length > 0 && { all_improvements: improvementExps.sort((a, b) => a.valBpb - b.valBpb).map((e) => ({ commit: e.commit, val_bpb: e.valBpb, delta: e.improvement, description: e.description })) }),
|
|
2360
|
+
};
|
|
2361
|
+
result = await runtime.connection.request("POST", `/v1/swarms/subtasks/${encodeURIComponent(subtaskId)}/submit`, { content: submitContent, resultType: "output" });
|
|
2362
|
+
if (!json)
|
|
2363
|
+
console.log(chalk.dim(` [reactive] Submitted autoresearch results to subtask ${subtaskId}`));
|
|
2364
|
+
break;
|
|
2365
|
+
}
|
|
2366
|
+
case "autoresearch_bundle": {
|
|
2367
|
+
const bundleTitle = action.title;
|
|
2368
|
+
let bundleExps = action.experiments || [];
|
|
2369
|
+
if (!bundleTitle || !bundleExps.length)
|
|
2370
|
+
throw new Error("autoresearch_bundle requires title and experiments");
|
|
2371
|
+
if (action.improvementsOnly !== false)
|
|
2372
|
+
bundleExps = bundleExps.filter((e) => e.isImprovement);
|
|
2373
|
+
if (!bundleExps.length) {
|
|
2374
|
+
result = { published: false, reason: "no experiments to bundle" };
|
|
2375
|
+
break;
|
|
2376
|
+
}
|
|
2377
|
+
const bestBpb = Math.min(...bundleExps.map((e) => e.valBpb));
|
|
2378
|
+
const payload = {
|
|
2379
|
+
type: "autoresearch_bundle", version: "1.0", title: bundleTitle,
|
|
2380
|
+
description: `Collection of ${bundleExps.length} ML training experiments. Best val_bpb: ${bestBpb.toFixed(6)}.`,
|
|
2381
|
+
domain: "machine-learning", tags: ["autoresearch", "ml-training", "llm", ...(action.tags || [])],
|
|
2382
|
+
experiment_count: bundleExps.length, best_bpb: bestBpb,
|
|
2383
|
+
experiments: bundleExps.map((e) => ({ commit: e.commit || e.commitHash, val_bpb: e.valBpb, peak_vram_mb: e.peakVramMb, status: e.status, description: e.description, category: e.category, improvement: e.improvement })),
|
|
2384
|
+
};
|
|
2385
|
+
const resource = await runtime.connection.request("POST", "/v1/knowledge/resources", {
|
|
2386
|
+
source_type: "custom", title: bundleTitle, description: payload.description, content: JSON.stringify(payload), tags: payload.tags,
|
|
2387
|
+
});
|
|
2388
|
+
const resourceId = resource?.resourceId || resource?.resource_id || "unknown";
|
|
2153
2389
|
try {
|
|
2154
|
-
const
|
|
2155
|
-
|
|
2156
|
-
console.log(chalk.dim(` [reactive] MCP fallback: ${mcpName} → ok`));
|
|
2390
|
+
const bundle = await prepareSignRelay(runtime.connection, "/v1/prepare/bundle", { name: bundleTitle, description: payload.description, cids: [String(resourceId)], tags: payload.tags, domain: "machine-learning" });
|
|
2391
|
+
result = { published: true, title: bundleTitle, experiments: bundleExps.length, resourceId, bundle };
|
|
2157
2392
|
}
|
|
2158
|
-
catch (
|
|
2159
|
-
|
|
2160
|
-
|
|
2393
|
+
catch (e) {
|
|
2394
|
+
result = { published: false, reason: e.message || String(e), resourceId, contentUploaded: true };
|
|
2395
|
+
}
|
|
2396
|
+
if (!json)
|
|
2397
|
+
console.log(chalk.dim(` [reactive] Autoresearch bundle: ${bundleTitle}`));
|
|
2398
|
+
break;
|
|
2399
|
+
}
|
|
2400
|
+
case "autoresearch_session_summary": {
|
|
2401
|
+
const totalExp = action.totalExperiments;
|
|
2402
|
+
const bestBpbVal = action.bestBpb;
|
|
2403
|
+
if (totalExp == null || bestBpbVal == null)
|
|
2404
|
+
throw new Error("autoresearch_session_summary requires totalExperiments and bestBpb");
|
|
2405
|
+
const successRate = totalExp > 0 ? ((action.improvements || 0) / totalExp * 100).toFixed(1) : "0";
|
|
2406
|
+
const summaryContent = `Autoresearch session summary: ${totalExp} experiments, ${action.improvements || 0} improvements (${successRate}% success rate). Best val_bpb: ${bestBpbVal.toFixed(6)}. ` +
|
|
2407
|
+
(action.categories ? `Categories: ${Object.entries(action.categories).map(([k, v]) => `${k}(${v})`).join(", ")}. ` : "") +
|
|
2408
|
+
(action.topFindings?.length ? `Key findings: ${action.topFindings.join("; ")}. ` : "") +
|
|
2409
|
+
(action.sessionNotes ? `Notes: ${action.sessionNotes}` : "");
|
|
2410
|
+
result = await runtime.connection.request("POST", "/v1/agent-memory/store", {
|
|
2411
|
+
type: "semantic", content: summaryContent, importance: 0.9,
|
|
2412
|
+
tags: ["autoresearch", "session-summary", "ml-research"], source: "autoresearch",
|
|
2413
|
+
});
|
|
2414
|
+
if (!json)
|
|
2415
|
+
console.log(chalk.dim(` [reactive] Stored autoresearch session summary`));
|
|
2416
|
+
break;
|
|
2417
|
+
}
|
|
2418
|
+
// ── Read-only / discovery tools ────────────────────────────
|
|
2419
|
+
case "read_feed": {
|
|
2420
|
+
const qs = new URLSearchParams();
|
|
2421
|
+
if (action.community)
|
|
2422
|
+
qs.set("community", action.community);
|
|
2423
|
+
if (action.sort)
|
|
2424
|
+
qs.set("sort", action.sort);
|
|
2425
|
+
if (action.limit)
|
|
2426
|
+
qs.set("limit", String(action.limit));
|
|
2427
|
+
if (action.skip)
|
|
2428
|
+
qs.set("skip", String(action.skip));
|
|
2429
|
+
if (action.minScore)
|
|
2430
|
+
qs.set("minScore", String(action.minScore));
|
|
2431
|
+
if (action.followingOnly)
|
|
2432
|
+
qs.set("followingOnly", "true");
|
|
2433
|
+
result = await runtime.connection.request("GET", `/v1/index/feed?${qs}`);
|
|
2434
|
+
if (!json)
|
|
2435
|
+
console.log(chalk.dim(` [reactive] Read feed`));
|
|
2436
|
+
break;
|
|
2437
|
+
}
|
|
2438
|
+
case "check_balance": {
|
|
2439
|
+
result = await runtime.connection.request("GET", "/v1/credits/balance");
|
|
2440
|
+
if (!json)
|
|
2441
|
+
console.log(chalk.dim(` [reactive] Checked balance`));
|
|
2442
|
+
break;
|
|
2443
|
+
}
|
|
2444
|
+
case "check_reputation": {
|
|
2445
|
+
const addr = (action.address || target);
|
|
2446
|
+
if (!addr)
|
|
2447
|
+
throw new Error("check_reputation requires address");
|
|
2448
|
+
result = await runtime.connection.request("GET", `/v1/contributions/${encodeURIComponent(addr)}`);
|
|
2449
|
+
if (!json)
|
|
2450
|
+
console.log(chalk.dim(` [reactive] Checked reputation for ${addr.slice(0, 10)}...`));
|
|
2451
|
+
break;
|
|
2452
|
+
}
|
|
2453
|
+
case "check_token_balance": {
|
|
2454
|
+
result = await runtime.connection.request("GET", "/v1/token/balance");
|
|
2455
|
+
if (!json)
|
|
2456
|
+
console.log(chalk.dim(` [reactive] Checked token balance`));
|
|
2457
|
+
break;
|
|
2458
|
+
}
|
|
2459
|
+
case "check_token_allowance": {
|
|
2460
|
+
const tokenAddr = action.tokenAddress;
|
|
2461
|
+
const spenderAddr = action.spenderAddress;
|
|
2462
|
+
if (!tokenAddr || !spenderAddr)
|
|
2463
|
+
throw new Error("check_token_allowance requires tokenAddress and spenderAddress");
|
|
2464
|
+
result = await runtime.connection.request("GET", `/v1/token/allowance?tokenAddress=${encodeURIComponent(tokenAddr)}&spenderAddress=${encodeURIComponent(spenderAddr)}`);
|
|
2465
|
+
if (!json)
|
|
2466
|
+
console.log(chalk.dim(` [reactive] Checked token allowance`));
|
|
2467
|
+
break;
|
|
2468
|
+
}
|
|
2469
|
+
case "discover": {
|
|
2470
|
+
const dq = new URLSearchParams();
|
|
2471
|
+
if (action.query)
|
|
2472
|
+
dq.set("q", action.query);
|
|
2473
|
+
if (action.types)
|
|
2474
|
+
dq.set("types", action.types);
|
|
2475
|
+
if (action.limit)
|
|
2476
|
+
dq.set("limit", String(action.limit));
|
|
2477
|
+
result = await runtime.connection.request("GET", `/v1/search?${dq}`);
|
|
2478
|
+
if (!json)
|
|
2479
|
+
console.log(chalk.dim(` [reactive] Discovered content`));
|
|
2480
|
+
break;
|
|
2481
|
+
}
|
|
2482
|
+
case "get_bounty": {
|
|
2483
|
+
const bId = (action.id || action.bountyId);
|
|
2484
|
+
if (!bId)
|
|
2485
|
+
throw new Error("get_bounty requires id");
|
|
2486
|
+
result = await runtime.connection.request("GET", `/v1/bounties/${encodeURIComponent(bId)}`);
|
|
2487
|
+
if (!json)
|
|
2488
|
+
console.log(chalk.dim(` [reactive] Got bounty ${bId}`));
|
|
2489
|
+
break;
|
|
2490
|
+
}
|
|
2491
|
+
case "get_comments": {
|
|
2492
|
+
const cid = action.cid;
|
|
2493
|
+
if (!cid)
|
|
2494
|
+
throw new Error("get_comments requires cid");
|
|
2495
|
+
const cqs = new URLSearchParams();
|
|
2496
|
+
if (action.limit)
|
|
2497
|
+
cqs.set("limit", String(action.limit));
|
|
2498
|
+
result = await runtime.connection.request("GET", `/v1/index/content/${encodeURIComponent(cid)}/comments?${cqs}`);
|
|
2499
|
+
if (!json)
|
|
2500
|
+
console.log(chalk.dim(` [reactive] Got comments for ${cid.slice(0, 10)}...`));
|
|
2501
|
+
break;
|
|
2502
|
+
}
|
|
2503
|
+
case "get_content": {
|
|
2504
|
+
const contentCid = action.cid;
|
|
2505
|
+
if (!contentCid)
|
|
2506
|
+
throw new Error("get_content requires cid");
|
|
2507
|
+
result = await runtime.connection.request("GET", `/v1/index/content/${encodeURIComponent(contentCid)}`);
|
|
2508
|
+
if (!json)
|
|
2509
|
+
console.log(chalk.dim(` [reactive] Got content ${contentCid.slice(0, 10)}...`));
|
|
2510
|
+
break;
|
|
2511
|
+
}
|
|
2512
|
+
case "get_credentials": {
|
|
2513
|
+
result = { apiKey: runtime.connection.apiKey, address: runtime.connection.address, gatewayUrl: runtime.connection.gatewayUrl };
|
|
2514
|
+
if (!json)
|
|
2515
|
+
console.log(chalk.dim(` [reactive] Got credentials`));
|
|
2516
|
+
break;
|
|
2517
|
+
}
|
|
2518
|
+
case "get_email_inbox": {
|
|
2519
|
+
result = await runtime.connection.request("GET", "/v1/email/inbox");
|
|
2520
|
+
if (!json)
|
|
2521
|
+
console.log(chalk.dim(` [reactive] Got email inbox`));
|
|
2522
|
+
break;
|
|
2523
|
+
}
|
|
2524
|
+
case "get_pending_signals": {
|
|
2525
|
+
result = await runtime.connection.request("GET", "/v1/proactive/approvals");
|
|
2526
|
+
if (!json)
|
|
2527
|
+
console.log(chalk.dim(` [reactive] Got pending signals`));
|
|
2528
|
+
break;
|
|
2529
|
+
}
|
|
2530
|
+
case "get_project_commit": {
|
|
2531
|
+
const projId = action.projectId;
|
|
2532
|
+
const commitId = action.commitId;
|
|
2533
|
+
if (!projId || !commitId)
|
|
2534
|
+
throw new Error("get_project_commit requires projectId and commitId");
|
|
2535
|
+
result = await runtime.connection.request("GET", `/v1/projects/${encodeURIComponent(projId)}/commits/${encodeURIComponent(commitId)}`);
|
|
2536
|
+
if (!json)
|
|
2537
|
+
console.log(chalk.dim(` [reactive] Got commit ${commitId.slice(0, 8)}`));
|
|
2538
|
+
break;
|
|
2539
|
+
}
|
|
2540
|
+
case "get_second_opinion": {
|
|
2541
|
+
const question = action.question;
|
|
2542
|
+
if (!question)
|
|
2543
|
+
throw new Error("get_second_opinion requires question");
|
|
2544
|
+
result = await runtime.connection.request("POST", "/v1/insights", { title: `Question: ${question.slice(0, 80)}`, body: question, strategyType: "question", tags: ["second-opinion"] });
|
|
2545
|
+
if (!json)
|
|
2546
|
+
console.log(chalk.dim(` [reactive] Posted question for second opinion`));
|
|
2547
|
+
break;
|
|
2548
|
+
}
|
|
2549
|
+
case "get_swarm": {
|
|
2550
|
+
const swarmId = action.swarmId;
|
|
2551
|
+
if (!swarmId)
|
|
2552
|
+
throw new Error("get_swarm requires swarmId");
|
|
2553
|
+
result = await runtime.connection.request("GET", `/v1/swarms/${encodeURIComponent(swarmId)}`);
|
|
2554
|
+
if (!json)
|
|
2555
|
+
console.log(chalk.dim(` [reactive] Got swarm ${swarmId}`));
|
|
2556
|
+
break;
|
|
2557
|
+
}
|
|
2558
|
+
case "get_workspace": {
|
|
2559
|
+
const wsId = action.workspaceId;
|
|
2560
|
+
if (!wsId)
|
|
2561
|
+
throw new Error("get_workspace requires workspaceId");
|
|
2562
|
+
result = await runtime.connection.request("GET", `/v1/workspaces/${encodeURIComponent(wsId)}`);
|
|
2563
|
+
if (!json)
|
|
2564
|
+
console.log(chalk.dim(` [reactive] Got workspace ${wsId}`));
|
|
2565
|
+
break;
|
|
2566
|
+
}
|
|
2567
|
+
case "leaderboard": {
|
|
2568
|
+
const lqs = new URLSearchParams();
|
|
2569
|
+
if (action.limit)
|
|
2570
|
+
lqs.set("limit", String(action.limit));
|
|
2571
|
+
result = await runtime.connection.request("GET", `/v1/contributions/leaderboard?${lqs}`);
|
|
2572
|
+
if (!json)
|
|
2573
|
+
console.log(chalk.dim(` [reactive] Got leaderboard`));
|
|
2574
|
+
break;
|
|
2575
|
+
}
|
|
2576
|
+
case "lookup_agent": {
|
|
2577
|
+
const lookupAddr = (action.address || target);
|
|
2578
|
+
if (!lookupAddr)
|
|
2579
|
+
throw new Error("lookup_agent requires address");
|
|
2580
|
+
result = await runtime.connection.request("GET", `/v1/agents/${encodeURIComponent(lookupAddr)}/profile`);
|
|
2581
|
+
if (!json)
|
|
2582
|
+
console.log(chalk.dim(` [reactive] Looked up agent ${lookupAddr.slice(0, 10)}...`));
|
|
2583
|
+
break;
|
|
2584
|
+
}
|
|
2585
|
+
case "my_profile": {
|
|
2586
|
+
const me = await runtime.connection.request("GET", "/v1/agents/me");
|
|
2587
|
+
const addr2 = me?.address || runtime.connection.address;
|
|
2588
|
+
let contribs = {};
|
|
2589
|
+
let balance = {};
|
|
2590
|
+
try {
|
|
2591
|
+
contribs = await runtime.connection.request("GET", `/v1/contributions/${addr2}`);
|
|
2592
|
+
}
|
|
2593
|
+
catch { }
|
|
2594
|
+
try {
|
|
2595
|
+
balance = await runtime.connection.request("GET", "/v1/credits/balance");
|
|
2596
|
+
}
|
|
2597
|
+
catch { }
|
|
2598
|
+
result = { ...me, contributions: contribs, credits: balance };
|
|
2599
|
+
if (!json)
|
|
2600
|
+
console.log(chalk.dim(` [reactive] Got my profile`));
|
|
2601
|
+
break;
|
|
2602
|
+
}
|
|
2603
|
+
case "search_knowledge": {
|
|
2604
|
+
const skqs = new URLSearchParams();
|
|
2605
|
+
if (action.query)
|
|
2606
|
+
skqs.set("q", action.query);
|
|
2607
|
+
if (action.types)
|
|
2608
|
+
skqs.set("types", action.types);
|
|
2609
|
+
if (action.limit)
|
|
2610
|
+
skqs.set("limit", String(action.limit));
|
|
2611
|
+
result = await runtime.connection.request("GET", `/v1/search?${skqs}`);
|
|
2612
|
+
if (!json)
|
|
2613
|
+
console.log(chalk.dim(` [reactive] Searched knowledge`));
|
|
2614
|
+
break;
|
|
2615
|
+
}
|
|
2616
|
+
case "weekly_reward_info": {
|
|
2617
|
+
result = await runtime.connection.request("GET", "/v1/rewards/weekly/current");
|
|
2618
|
+
if (!json)
|
|
2619
|
+
console.log(chalk.dim(` [reactive] Got weekly reward info`));
|
|
2620
|
+
break;
|
|
2621
|
+
}
|
|
2622
|
+
case "check_my_rewards": {
|
|
2623
|
+
const rwqs = new URLSearchParams();
|
|
2624
|
+
if (action.limit)
|
|
2625
|
+
rwqs.set("limit", String(action.limit));
|
|
2626
|
+
result = await runtime.connection.request("GET", `/v1/rewards/weekly/me?${rwqs}`);
|
|
2627
|
+
if (!json)
|
|
2628
|
+
console.log(chalk.dim(` [reactive] Checked my rewards`));
|
|
2629
|
+
break;
|
|
2630
|
+
}
|
|
2631
|
+
// ── List/browse tools ──────────────────────────────────────
|
|
2632
|
+
case "list_bounties": {
|
|
2633
|
+
const lbqs = new URLSearchParams();
|
|
2634
|
+
if (action.community)
|
|
2635
|
+
lbqs.set("community", action.community);
|
|
2636
|
+
if (action.status != null)
|
|
2637
|
+
lbqs.set("status", String(action.status));
|
|
2638
|
+
if (action.limit)
|
|
2639
|
+
lbqs.set("limit", String(action.limit));
|
|
2640
|
+
result = await runtime.connection.request("GET", `/v1/index/bounties?${lbqs}`);
|
|
2641
|
+
if (!json)
|
|
2642
|
+
console.log(chalk.dim(` [reactive] Listed bounties`));
|
|
2643
|
+
break;
|
|
2644
|
+
}
|
|
2645
|
+
case "list_channels": {
|
|
2646
|
+
const lcqs = new URLSearchParams();
|
|
2647
|
+
if (action.channelType)
|
|
2648
|
+
lcqs.set("channelType", action.channelType);
|
|
2649
|
+
if (action.limit)
|
|
2650
|
+
lcqs.set("limit", String(action.limit));
|
|
2651
|
+
result = await runtime.connection.request("GET", `/v1/channels?${lcqs}`);
|
|
2652
|
+
if (!json)
|
|
2653
|
+
console.log(chalk.dim(` [reactive] Listed channels`));
|
|
2654
|
+
break;
|
|
2655
|
+
}
|
|
2656
|
+
case "list_communities": {
|
|
2657
|
+
const lcmqs = new URLSearchParams();
|
|
2658
|
+
if (action.limit)
|
|
2659
|
+
lcmqs.set("limit", String(action.limit));
|
|
2660
|
+
result = await runtime.connection.request("GET", `/v1/index/communities?${lcmqs}`);
|
|
2661
|
+
if (!json)
|
|
2662
|
+
console.log(chalk.dim(` [reactive] Listed communities`));
|
|
2663
|
+
break;
|
|
2664
|
+
}
|
|
2665
|
+
case "list_credit_agreements": {
|
|
2666
|
+
const lcaqs = new URLSearchParams();
|
|
2667
|
+
if (action.role)
|
|
2668
|
+
lcaqs.set("role", action.role);
|
|
2669
|
+
if (action.status)
|
|
2670
|
+
lcaqs.set("status", action.status);
|
|
2671
|
+
if (action.limit)
|
|
2672
|
+
lcaqs.set("limit", String(action.limit));
|
|
2673
|
+
result = await runtime.connection.request("GET", `/v1/marketplace/credit-agreements?${lcaqs}`);
|
|
2674
|
+
if (!json)
|
|
2675
|
+
console.log(chalk.dim(` [reactive] Listed credit agreements`));
|
|
2676
|
+
break;
|
|
2677
|
+
}
|
|
2678
|
+
case "list_guilds": {
|
|
2679
|
+
const lgqs = new URLSearchParams();
|
|
2680
|
+
if (action.limit)
|
|
2681
|
+
lgqs.set("limit", String(action.limit));
|
|
2682
|
+
result = await runtime.connection.request("GET", `/v1/index/guilds?${lgqs}`);
|
|
2683
|
+
if (!json)
|
|
2684
|
+
console.log(chalk.dim(` [reactive] Listed guilds`));
|
|
2685
|
+
break;
|
|
2686
|
+
}
|
|
2687
|
+
case "list_intents": {
|
|
2688
|
+
const liqs = new URLSearchParams();
|
|
2689
|
+
if (action.query)
|
|
2690
|
+
liqs.set("query", action.query);
|
|
2691
|
+
if (action.category)
|
|
2692
|
+
liqs.set("category", action.category);
|
|
2693
|
+
if (action.status)
|
|
2694
|
+
liqs.set("status", action.status);
|
|
2695
|
+
if (action.limit)
|
|
2696
|
+
liqs.set("limit", String(action.limit));
|
|
2697
|
+
result = await runtime.connection.request("GET", `/v1/intents?${liqs}`);
|
|
2698
|
+
if (!json)
|
|
2699
|
+
console.log(chalk.dim(` [reactive] Listed intents`));
|
|
2700
|
+
break;
|
|
2701
|
+
}
|
|
2702
|
+
case "list_muted": {
|
|
2703
|
+
result = await runtime.connection.request("GET", "/v1/agents/muted");
|
|
2704
|
+
if (!json)
|
|
2705
|
+
console.log(chalk.dim(` [reactive] Listed muted agents`));
|
|
2706
|
+
break;
|
|
2707
|
+
}
|
|
2708
|
+
case "list_project_commits": {
|
|
2709
|
+
const pId = action.projectId;
|
|
2710
|
+
if (!pId)
|
|
2711
|
+
throw new Error("list_project_commits requires projectId");
|
|
2712
|
+
const lpcqs = new URLSearchParams();
|
|
2713
|
+
if (action.limit)
|
|
2714
|
+
lpcqs.set("limit", String(action.limit));
|
|
2715
|
+
if (action.offset)
|
|
2716
|
+
lpcqs.set("offset", String(action.offset));
|
|
2717
|
+
result = await runtime.connection.request("GET", `/v1/projects/${encodeURIComponent(pId)}/commits?${lpcqs}`);
|
|
2718
|
+
if (!json)
|
|
2719
|
+
console.log(chalk.dim(` [reactive] Listed commits for ${pId}`));
|
|
2720
|
+
break;
|
|
2721
|
+
}
|
|
2722
|
+
case "list_projects": {
|
|
2723
|
+
const lpqs = new URLSearchParams();
|
|
2724
|
+
if (action.query)
|
|
2725
|
+
lpqs.set("q", action.query);
|
|
2726
|
+
if (action.limit)
|
|
2727
|
+
lpqs.set("limit", String(action.limit));
|
|
2728
|
+
result = await runtime.connection.request("GET", `/v1/search/projects?${lpqs}`);
|
|
2729
|
+
if (!json)
|
|
2730
|
+
console.log(chalk.dim(` [reactive] Listed projects`));
|
|
2731
|
+
break;
|
|
2732
|
+
}
|
|
2733
|
+
case "list_proposals": {
|
|
2734
|
+
const wId = action.workspaceId;
|
|
2735
|
+
if (!wId)
|
|
2736
|
+
throw new Error("list_proposals requires workspaceId");
|
|
2737
|
+
const lppqs = new URLSearchParams();
|
|
2738
|
+
if (action.status)
|
|
2739
|
+
lppqs.set("status", action.status);
|
|
2740
|
+
if (action.limit)
|
|
2741
|
+
lppqs.set("limit", String(action.limit));
|
|
2742
|
+
result = await runtime.connection.request("GET", `/v1/workspaces/${encodeURIComponent(wId)}/proposals?${lppqs}`);
|
|
2743
|
+
if (!json)
|
|
2744
|
+
console.log(chalk.dim(` [reactive] Listed proposals`));
|
|
2745
|
+
break;
|
|
2746
|
+
}
|
|
2747
|
+
case "list_services": {
|
|
2748
|
+
const lsqs = new URLSearchParams();
|
|
2749
|
+
if (action.category)
|
|
2750
|
+
lsqs.set("category", action.category);
|
|
2751
|
+
if (action.limit)
|
|
2752
|
+
lsqs.set("limit", String(action.limit));
|
|
2753
|
+
result = await runtime.connection.request("GET", `/v1/index/services?${lsqs}`);
|
|
2754
|
+
if (!json)
|
|
2755
|
+
console.log(chalk.dim(` [reactive] Listed services`));
|
|
2756
|
+
break;
|
|
2757
|
+
}
|
|
2758
|
+
case "list_swarms": {
|
|
2759
|
+
const lswqs = new URLSearchParams();
|
|
2760
|
+
if (action.mine)
|
|
2761
|
+
lswqs.set("mine", "true");
|
|
2762
|
+
if (action.status)
|
|
2763
|
+
lswqs.set("status", action.status);
|
|
2764
|
+
if (action.limit)
|
|
2765
|
+
lswqs.set("limit", String(action.limit));
|
|
2766
|
+
result = await runtime.connection.request("GET", `/v1/swarms?${lswqs}`);
|
|
2767
|
+
if (!json)
|
|
2768
|
+
console.log(chalk.dim(` [reactive] Listed swarms`));
|
|
2769
|
+
break;
|
|
2770
|
+
}
|
|
2771
|
+
case "list_teaching_exchanges": {
|
|
2772
|
+
const lteqs = new URLSearchParams();
|
|
2773
|
+
if (action.role)
|
|
2774
|
+
lteqs.set("role", action.role);
|
|
2775
|
+
if (action.status)
|
|
2776
|
+
lteqs.set("status", action.status);
|
|
2777
|
+
if (action.limit)
|
|
2778
|
+
lteqs.set("limit", String(action.limit));
|
|
2779
|
+
result = await runtime.connection.request("GET", `/v1/teaching/exchanges?${lteqs}`);
|
|
2780
|
+
if (!json)
|
|
2781
|
+
console.log(chalk.dim(` [reactive] Listed teaching exchanges`));
|
|
2782
|
+
break;
|
|
2783
|
+
}
|
|
2784
|
+
case "list_token_launches": {
|
|
2785
|
+
const ltlqs = new URLSearchParams();
|
|
2786
|
+
if (action.limit)
|
|
2787
|
+
ltlqs.set("limit", String(action.limit));
|
|
2788
|
+
if (action.offset)
|
|
2789
|
+
ltlqs.set("offset", String(action.offset));
|
|
2790
|
+
result = await runtime.connection.request("GET", `/v1/clawnch/launches?${ltlqs}`);
|
|
2791
|
+
if (!json)
|
|
2792
|
+
console.log(chalk.dim(` [reactive] Listed token launches`));
|
|
2793
|
+
break;
|
|
2794
|
+
}
|
|
2795
|
+
case "list_workspaces": {
|
|
2796
|
+
const lwqs = new URLSearchParams();
|
|
2797
|
+
if (action.limit)
|
|
2798
|
+
lwqs.set("limit", String(action.limit));
|
|
2799
|
+
result = await runtime.connection.request("GET", `/v1/workspaces?${lwqs}`);
|
|
2800
|
+
if (!json)
|
|
2801
|
+
console.log(chalk.dim(` [reactive] Listed workspaces`));
|
|
2802
|
+
break;
|
|
2803
|
+
}
|
|
2804
|
+
case "my_agreements": {
|
|
2805
|
+
const maqs = new URLSearchParams();
|
|
2806
|
+
if (action.role)
|
|
2807
|
+
maqs.set("role", action.role);
|
|
2808
|
+
if (action.status)
|
|
2809
|
+
maqs.set("status", action.status);
|
|
2810
|
+
if (action.limit)
|
|
2811
|
+
maqs.set("limit", String(action.limit));
|
|
2812
|
+
result = await runtime.connection.request("GET", `/v1/marketplace/agreements?${maqs}`);
|
|
2813
|
+
if (!json)
|
|
2814
|
+
console.log(chalk.dim(` [reactive] Got my agreements`));
|
|
2815
|
+
break;
|
|
2816
|
+
}
|
|
2817
|
+
case "my_bounties": {
|
|
2818
|
+
result = await runtime.connection.request("GET", "/v1/index/bounties?mine=true");
|
|
2819
|
+
if (!json)
|
|
2820
|
+
console.log(chalk.dim(` [reactive] Got my bounties`));
|
|
2821
|
+
break;
|
|
2822
|
+
}
|
|
2823
|
+
case "my_skills": {
|
|
2824
|
+
const addr3 = runtime.connection.address || "";
|
|
2825
|
+
result = await runtime.connection.request("GET", `/v1/skills/registry?publisherId=${encodeURIComponent(addr3)}`);
|
|
2826
|
+
if (!json)
|
|
2827
|
+
console.log(chalk.dim(` [reactive] Got my skills`));
|
|
2828
|
+
break;
|
|
2829
|
+
}
|
|
2830
|
+
case "my_tasks": {
|
|
2831
|
+
result = await runtime.connection.request("GET", "/v1/swarms/subtasks?mine=true");
|
|
2832
|
+
if (!json)
|
|
2833
|
+
console.log(chalk.dim(` [reactive] Got my tasks`));
|
|
2834
|
+
break;
|
|
2835
|
+
}
|
|
2836
|
+
case "available_subtasks": {
|
|
2837
|
+
const asqs = new URLSearchParams();
|
|
2838
|
+
if (action.skills)
|
|
2839
|
+
asqs.set("skills", action.skills);
|
|
2840
|
+
if (action.swarmId)
|
|
2841
|
+
asqs.set("swarmId", action.swarmId);
|
|
2842
|
+
if (action.limit)
|
|
2843
|
+
asqs.set("limit", String(action.limit));
|
|
2844
|
+
result = await runtime.connection.request("GET", `/v1/swarms/subtasks?${asqs}`);
|
|
2845
|
+
if (!json)
|
|
2846
|
+
console.log(chalk.dim(` [reactive] Listed available subtasks`));
|
|
2847
|
+
break;
|
|
2848
|
+
}
|
|
2849
|
+
// ── Agent-first tools ──────────────────────────────────────
|
|
2850
|
+
case "delegate_task": {
|
|
2851
|
+
const dtTitle = action.title;
|
|
2852
|
+
const dtDesc = action.description;
|
|
2853
|
+
if (!dtTitle || !dtDesc)
|
|
2854
|
+
throw new Error("delegate_task requires title and description");
|
|
2855
|
+
result = await runtime.connection.request("POST", "/v1/swarms", {
|
|
2856
|
+
title: dtTitle, description: dtDesc,
|
|
2857
|
+
subtasks: [{ title: dtTitle, description: dtDesc, skillTags: action.skills || [] }],
|
|
2858
|
+
});
|
|
2859
|
+
if (!json)
|
|
2860
|
+
console.log(chalk.dim(` [reactive] Delegated task: ${dtTitle}`));
|
|
2861
|
+
break;
|
|
2862
|
+
}
|
|
2863
|
+
case "save_learning": {
|
|
2864
|
+
const slTitle = action.title;
|
|
2865
|
+
const slBody = action.body;
|
|
2866
|
+
if (!slTitle || !slBody)
|
|
2867
|
+
throw new Error("save_learning requires title and body");
|
|
2868
|
+
result = await runtime.connection.request("POST", "/v1/agent-memory/store", {
|
|
2869
|
+
type: "semantic", content: `${slTitle}: ${slBody}`,
|
|
2870
|
+
importance: 0.7, tags: ["learning", ...(action.tags || [])],
|
|
2871
|
+
source: "self",
|
|
2872
|
+
});
|
|
2873
|
+
if (!json)
|
|
2874
|
+
console.log(chalk.dim(` [reactive] Saved learning: ${slTitle}`));
|
|
2875
|
+
break;
|
|
2876
|
+
}
|
|
2877
|
+
case "recall": {
|
|
2878
|
+
const recallQuery = action.query;
|
|
2879
|
+
if (!recallQuery)
|
|
2880
|
+
throw new Error("recall requires query");
|
|
2881
|
+
result = await runtime.connection.request("POST", "/v1/agent-memory/recall", {
|
|
2882
|
+
query: recallQuery, limit: action.limit || 10,
|
|
2883
|
+
});
|
|
2884
|
+
if (!json)
|
|
2885
|
+
console.log(chalk.dim(` [reactive] Recalled memories`));
|
|
2886
|
+
break;
|
|
2887
|
+
}
|
|
2888
|
+
case "save_checkpoint": {
|
|
2889
|
+
const cpTask = action.task;
|
|
2890
|
+
if (!cpTask)
|
|
2891
|
+
throw new Error("save_checkpoint requires task");
|
|
2892
|
+
const cpContent = `CHECKPOINT: ${cpTask} | Progress: ${action.progress || 0}% | Remaining: ${action.remaining || "unknown"} | Blockers: ${action.blockers || "none"} | Context: ${action.context || ""}`;
|
|
2893
|
+
result = await runtime.connection.request("POST", "/v1/agent-memory/store", {
|
|
2894
|
+
type: "episodic", content: cpContent, importance: 0.85,
|
|
2895
|
+
tags: ["checkpoint", "work-state"], source: "self",
|
|
2896
|
+
});
|
|
2897
|
+
if (!json)
|
|
2898
|
+
console.log(chalk.dim(` [reactive] Saved checkpoint: ${cpTask}`));
|
|
2899
|
+
break;
|
|
2900
|
+
}
|
|
2901
|
+
case "resume_checkpoint": {
|
|
2902
|
+
result = await runtime.connection.request("POST", "/v1/agent-memory/recall", {
|
|
2903
|
+
query: "CHECKPOINT work state progress", type: "episodic", limit: 1,
|
|
2904
|
+
});
|
|
2905
|
+
if (!json)
|
|
2906
|
+
console.log(chalk.dim(` [reactive] Resumed checkpoint`));
|
|
2907
|
+
break;
|
|
2908
|
+
}
|
|
2909
|
+
case "request_review": {
|
|
2910
|
+
const rvTitle = action.title;
|
|
2911
|
+
const rvContent = action.content;
|
|
2912
|
+
if (!rvTitle || !rvContent)
|
|
2913
|
+
throw new Error("request_review requires title and content");
|
|
2914
|
+
result = await runtime.connection.request("POST", "/v1/insights", {
|
|
2915
|
+
title: rvTitle, body: rvContent,
|
|
2916
|
+
strategyType: action.reviewType || "code",
|
|
2917
|
+
tags: ["review-request", action.reviewType || "code"],
|
|
2918
|
+
});
|
|
2919
|
+
if (!json)
|
|
2920
|
+
console.log(chalk.dim(` [reactive] Requested review: ${rvTitle}`));
|
|
2921
|
+
break;
|
|
2922
|
+
}
|
|
2923
|
+
case "ask_network": {
|
|
2924
|
+
const askQ = action.question;
|
|
2925
|
+
if (!askQ)
|
|
2926
|
+
throw new Error("ask_network requires question");
|
|
2927
|
+
result = await runtime.connection.request("POST", "/v1/insights", {
|
|
2928
|
+
title: `Question: ${askQ.slice(0, 80)}`, body: askQ,
|
|
2929
|
+
strategyType: "question", tags: ["network-question"],
|
|
2930
|
+
});
|
|
2931
|
+
if (!json)
|
|
2932
|
+
console.log(chalk.dim(` [reactive] Asked network`));
|
|
2933
|
+
break;
|
|
2934
|
+
}
|
|
2935
|
+
case "check_delegation": {
|
|
2936
|
+
const delBountyId = action.bountyId;
|
|
2937
|
+
if (!delBountyId)
|
|
2938
|
+
throw new Error("check_delegation requires bountyId");
|
|
2939
|
+
result = await runtime.connection.request("GET", `/v1/swarms/${encodeURIComponent(delBountyId)}`);
|
|
2940
|
+
if (!json)
|
|
2941
|
+
console.log(chalk.dim(` [reactive] Checked delegation ${delBountyId}`));
|
|
2942
|
+
break;
|
|
2943
|
+
}
|
|
2944
|
+
// ── On-chain tools missing from CLI ────────────────────────
|
|
2945
|
+
case "post_content":
|
|
2946
|
+
case "create_post": {
|
|
2947
|
+
const postTitle = action.title;
|
|
2948
|
+
const postBody = action.body;
|
|
2949
|
+
if (!postTitle || !postBody)
|
|
2950
|
+
throw new Error("post_content requires title and body");
|
|
2951
|
+
result = await prepareSignRelay(runtime.connection, "/v1/prepare/post", {
|
|
2952
|
+
title: postTitle, body: postBody,
|
|
2953
|
+
tags: action.tags, community: action.community || "general",
|
|
2954
|
+
});
|
|
2955
|
+
if (!json)
|
|
2956
|
+
console.log(chalk.dim(` [reactive] Published post: ${postTitle}`));
|
|
2957
|
+
break;
|
|
2958
|
+
}
|
|
2959
|
+
case "comment_on_content": {
|
|
2960
|
+
const parentCid = action.parentCid;
|
|
2961
|
+
const commentBody = action.body;
|
|
2962
|
+
if (!parentCid || !commentBody)
|
|
2963
|
+
throw new Error("comment_on_content requires parentCid and body");
|
|
2964
|
+
result = await prepareSignRelay(runtime.connection, "/v1/prepare/comment", {
|
|
2965
|
+
parentCid, body: commentBody, community: action.community,
|
|
2966
|
+
});
|
|
2967
|
+
if (!json)
|
|
2968
|
+
console.log(chalk.dim(` [reactive] Commented on ${parentCid.slice(0, 10)}...`));
|
|
2969
|
+
break;
|
|
2970
|
+
}
|
|
2971
|
+
case "unfollow_agent": {
|
|
2972
|
+
const unfAddr = (action.targetAddress || target);
|
|
2973
|
+
if (!unfAddr)
|
|
2974
|
+
throw new Error("unfollow_agent requires targetAddress");
|
|
2975
|
+
result = await prepareSignRelay(runtime.connection, "/v1/prepare/unfollow", { address: unfAddr });
|
|
2976
|
+
if (!json)
|
|
2977
|
+
console.log(chalk.dim(` [reactive] Unfollowed ${unfAddr.slice(0, 10)}...`));
|
|
2978
|
+
break;
|
|
2979
|
+
}
|
|
2980
|
+
case "approve_bounty_applicant": {
|
|
2981
|
+
const abId = (action.bountyId || action.id);
|
|
2982
|
+
const applicantAddr = action.applicantAddress;
|
|
2983
|
+
if (!abId || !applicantAddr)
|
|
2984
|
+
throw new Error("approve_bounty_applicant requires bountyId and applicantAddress");
|
|
2985
|
+
result = await prepareSignRelay(runtime.connection, `/v1/prepare/bounty/${encodeURIComponent(abId)}/approve-claimer`, { applicantAddress: applicantAddr });
|
|
2986
|
+
if (!json)
|
|
2987
|
+
console.log(chalk.dim(` [reactive] Approved bounty applicant ${applicantAddr.slice(0, 10)}...`));
|
|
2988
|
+
break;
|
|
2989
|
+
}
|
|
2990
|
+
case "create_service_listing": {
|
|
2991
|
+
const slsTitle = action.title;
|
|
2992
|
+
const slsDesc = action.description;
|
|
2993
|
+
const slsCat = action.category;
|
|
2994
|
+
if (!slsTitle || !slsDesc || !slsCat)
|
|
2995
|
+
throw new Error("create_service_listing requires title, description, category");
|
|
2996
|
+
result = await prepareSignRelay(runtime.connection, "/v1/prepare/service/list", {
|
|
2997
|
+
title: slsTitle, description: slsDesc, category: slsCat,
|
|
2998
|
+
priceAmount: action.priceAmount, pricingModel: action.pricingModel,
|
|
2999
|
+
tags: action.tags, tokenAddress: action.tokenAddress,
|
|
3000
|
+
});
|
|
3001
|
+
if (!json)
|
|
3002
|
+
console.log(chalk.dim(` [reactive] Created service listing: ${slsTitle}`));
|
|
3003
|
+
break;
|
|
3004
|
+
}
|
|
3005
|
+
case "hire_agent": {
|
|
3006
|
+
const listingId2 = action.listingId;
|
|
3007
|
+
const requirements = action.requirements;
|
|
3008
|
+
if (!listingId2 || !requirements)
|
|
3009
|
+
throw new Error("hire_agent requires listingId and requirements");
|
|
3010
|
+
result = await prepareSignRelay(runtime.connection, "/v1/prepare/service/agree", {
|
|
3011
|
+
listingId: listingId2, requirements, budget: action.budget,
|
|
3012
|
+
tokenAddress: action.tokenAddress,
|
|
3013
|
+
});
|
|
3014
|
+
if (!json)
|
|
3015
|
+
console.log(chalk.dim(` [reactive] Hired agent via listing ${listingId2}`));
|
|
3016
|
+
break;
|
|
3017
|
+
}
|
|
3018
|
+
case "accept_service": {
|
|
3019
|
+
const agreeId = action.agreementId;
|
|
3020
|
+
if (!agreeId)
|
|
3021
|
+
throw new Error("accept_service requires agreementId");
|
|
3022
|
+
result = await runtime.connection.request("POST", `/v1/marketplace/agreements/${encodeURIComponent(agreeId)}/accept`, {});
|
|
3023
|
+
if (!json)
|
|
3024
|
+
console.log(chalk.dim(` [reactive] Accepted service agreement ${agreeId}`));
|
|
3025
|
+
break;
|
|
3026
|
+
}
|
|
3027
|
+
case "dispute_service": {
|
|
3028
|
+
const dAgreeId = action.agreementId;
|
|
3029
|
+
if (!dAgreeId)
|
|
3030
|
+
throw new Error("dispute_service requires agreementId");
|
|
3031
|
+
result = await prepareSignRelay(runtime.connection, "/v1/prepare/service/dispute", {
|
|
3032
|
+
agreementId: dAgreeId, reason: action.reason,
|
|
3033
|
+
});
|
|
3034
|
+
if (!json)
|
|
3035
|
+
console.log(chalk.dim(` [reactive] Disputed service ${dAgreeId}`));
|
|
3036
|
+
break;
|
|
3037
|
+
}
|
|
3038
|
+
case "cancel_service": {
|
|
3039
|
+
const cAgreeId = action.agreementId;
|
|
3040
|
+
if (!cAgreeId)
|
|
3041
|
+
throw new Error("cancel_service requires agreementId");
|
|
3042
|
+
result = await prepareSignRelay(runtime.connection, "/v1/prepare/service/cancel", { agreementId: cAgreeId });
|
|
3043
|
+
if (!json)
|
|
3044
|
+
console.log(chalk.dim(` [reactive] Cancelled service ${cAgreeId}`));
|
|
3045
|
+
break;
|
|
3046
|
+
}
|
|
3047
|
+
case "approve_token": {
|
|
3048
|
+
const tokenAddr2 = action.tokenAddress;
|
|
3049
|
+
const spenderAddr2 = action.spenderAddress;
|
|
3050
|
+
const amount = action.amount || "max";
|
|
3051
|
+
if (!tokenAddr2 || !spenderAddr2)
|
|
3052
|
+
throw new Error("approve_token requires tokenAddress and spenderAddress");
|
|
3053
|
+
result = await runtime.connection.request("POST", "/v1/token/approve", {
|
|
3054
|
+
tokenAddress: tokenAddr2, spenderAddress: spenderAddr2, amount,
|
|
3055
|
+
});
|
|
3056
|
+
if (!json)
|
|
3057
|
+
console.log(chalk.dim(` [reactive] Approved token spending`));
|
|
3058
|
+
break;
|
|
3059
|
+
}
|
|
3060
|
+
// ── Proactive/signal tools ─────────────────────────────────
|
|
3061
|
+
case "poll_signals": {
|
|
3062
|
+
const psqs = new URLSearchParams();
|
|
3063
|
+
if (action.limit)
|
|
3064
|
+
psqs.set("limit", String(action.limit));
|
|
3065
|
+
result = await runtime.connection.request("GET", `/v1/proactive/pending-signals?${psqs}`);
|
|
3066
|
+
if (!json)
|
|
3067
|
+
console.log(chalk.dim(` [reactive] Polled signals`));
|
|
3068
|
+
break;
|
|
3069
|
+
}
|
|
3070
|
+
case "ack_signal": {
|
|
3071
|
+
const sigId = action.signalId;
|
|
3072
|
+
if (!sigId)
|
|
3073
|
+
throw new Error("ack_signal requires signalId");
|
|
3074
|
+
result = await runtime.connection.request("POST", `/v1/proactive/signals/${encodeURIComponent(sigId)}/ack`, {});
|
|
3075
|
+
if (!json)
|
|
3076
|
+
console.log(chalk.dim(` [reactive] Acknowledged signal ${sigId}`));
|
|
3077
|
+
break;
|
|
3078
|
+
}
|
|
3079
|
+
case "approve_action": {
|
|
3080
|
+
const actId = action.actionId;
|
|
3081
|
+
if (!actId)
|
|
3082
|
+
throw new Error("approve_action requires actionId");
|
|
3083
|
+
result = await runtime.connection.request("POST", `/v1/proactive/approvals/${encodeURIComponent(actId)}/approve`, {});
|
|
3084
|
+
if (!json)
|
|
3085
|
+
console.log(chalk.dim(` [reactive] Approved action ${actId}`));
|
|
3086
|
+
break;
|
|
3087
|
+
}
|
|
3088
|
+
case "reject_action": {
|
|
3089
|
+
const rejActId = action.actionId;
|
|
3090
|
+
if (!rejActId)
|
|
3091
|
+
throw new Error("reject_action requires actionId");
|
|
3092
|
+
result = await runtime.connection.request("POST", `/v1/proactive/approvals/${encodeURIComponent(rejActId)}/reject`, { reason: action.reason });
|
|
3093
|
+
if (!json)
|
|
3094
|
+
console.log(chalk.dim(` [reactive] Rejected action ${rejActId}`));
|
|
3095
|
+
break;
|
|
3096
|
+
}
|
|
3097
|
+
case "configure_proactive": {
|
|
3098
|
+
result = await runtime.connection.request("PUT", "/v1/proactive/settings", {
|
|
3099
|
+
enabled: action.enabled, scanIntervalMinutes: action.scanIntervalMinutes,
|
|
3100
|
+
maxActionsPerDay: action.maxActionsPerDay, callbackFormat: action.callbackFormat,
|
|
3101
|
+
});
|
|
3102
|
+
if (!json)
|
|
3103
|
+
console.log(chalk.dim(` [reactive] Configured proactive settings`));
|
|
3104
|
+
break;
|
|
3105
|
+
}
|
|
3106
|
+
// ── Content/write tools ────────────────────────────────────
|
|
3107
|
+
case "send_channel_message": {
|
|
3108
|
+
const chId = action.channelId;
|
|
3109
|
+
const chContent = action.content;
|
|
3110
|
+
if (!chId || !chContent)
|
|
3111
|
+
throw new Error("send_channel_message requires channelId and content");
|
|
3112
|
+
try {
|
|
3113
|
+
await runtime.connection.request("POST", `/v1/channels/${encodeURIComponent(chId)}/join`, {});
|
|
3114
|
+
}
|
|
3115
|
+
catch { }
|
|
3116
|
+
result = await runtime.connection.request("POST", `/v1/channels/${encodeURIComponent(chId)}/messages`, { content: chContent });
|
|
3117
|
+
if (!json)
|
|
3118
|
+
console.log(chalk.dim(` [reactive] Sent channel message`));
|
|
3119
|
+
break;
|
|
3120
|
+
}
|
|
3121
|
+
case "read_channel_messages": {
|
|
3122
|
+
const rcmChId = action.channelId;
|
|
3123
|
+
if (!rcmChId)
|
|
3124
|
+
throw new Error("read_channel_messages requires channelId");
|
|
3125
|
+
const rcmqs = new URLSearchParams();
|
|
3126
|
+
if (action.limit)
|
|
3127
|
+
rcmqs.set("limit", String(action.limit));
|
|
3128
|
+
if (action.before)
|
|
3129
|
+
rcmqs.set("before", action.before);
|
|
3130
|
+
result = await runtime.connection.request("GET", `/v1/channels/${encodeURIComponent(rcmChId)}/messages?${rcmqs}`);
|
|
3131
|
+
if (!json)
|
|
3132
|
+
console.log(chalk.dim(` [reactive] Read channel messages`));
|
|
3133
|
+
break;
|
|
3134
|
+
}
|
|
3135
|
+
case "subscribe":
|
|
3136
|
+
case "create_search_subscription": {
|
|
3137
|
+
const subLabel = action.label;
|
|
3138
|
+
const subQuery = action.query;
|
|
3139
|
+
if (!subLabel || !subQuery)
|
|
3140
|
+
throw new Error("subscribe requires label and query");
|
|
3141
|
+
result = await runtime.connection.request("POST", "/v1/search/subscriptions", {
|
|
3142
|
+
label: subLabel, query: subQuery,
|
|
3143
|
+
types: action.types, frequencyMinutes: action.frequencyMinutes,
|
|
3144
|
+
});
|
|
3145
|
+
if (!json)
|
|
3146
|
+
console.log(chalk.dim(` [reactive] Created subscription: ${subLabel}`));
|
|
3147
|
+
break;
|
|
3148
|
+
}
|
|
3149
|
+
case "mute_agent": {
|
|
3150
|
+
const muteAddr = (action.address || target);
|
|
3151
|
+
if (!muteAddr)
|
|
3152
|
+
throw new Error("mute_agent requires address");
|
|
3153
|
+
result = await runtime.connection.request("POST", `/v1/agents/${encodeURIComponent(muteAddr)}/mute`, {});
|
|
3154
|
+
if (!json)
|
|
3155
|
+
console.log(chalk.dim(` [reactive] Muted ${muteAddr.slice(0, 10)}...`));
|
|
3156
|
+
break;
|
|
3157
|
+
}
|
|
3158
|
+
case "unmute_agent": {
|
|
3159
|
+
const unmuteAddr = (action.address || target);
|
|
3160
|
+
if (!unmuteAddr)
|
|
3161
|
+
throw new Error("unmute_agent requires address");
|
|
3162
|
+
result = await runtime.connection.request("DELETE", `/v1/agents/${encodeURIComponent(unmuteAddr)}/mute`);
|
|
3163
|
+
if (!json)
|
|
3164
|
+
console.log(chalk.dim(` [reactive] Unmuted ${unmuteAddr.slice(0, 10)}...`));
|
|
3165
|
+
break;
|
|
3166
|
+
}
|
|
3167
|
+
case "report_spam":
|
|
3168
|
+
case "report_content": {
|
|
3169
|
+
const reportCid = (action.contentCid || action.cid);
|
|
3170
|
+
const reportReason = action.reason;
|
|
3171
|
+
if (!reportCid || !reportReason)
|
|
3172
|
+
throw new Error("report_content requires cid and reason");
|
|
3173
|
+
result = await runtime.connection.request("POST", `/v1/content/${encodeURIComponent(reportCid)}/report`, { reason: reportReason, details: action.details });
|
|
3174
|
+
if (!json)
|
|
3175
|
+
console.log(chalk.dim(` [reactive] Reported content ${reportCid.slice(0, 10)}...`));
|
|
3176
|
+
break;
|
|
3177
|
+
}
|
|
3178
|
+
case "import_project_url": {
|
|
3179
|
+
const impProjId = action.projectId;
|
|
3180
|
+
const impUrl = action.url;
|
|
3181
|
+
if (!impProjId || !impUrl)
|
|
3182
|
+
throw new Error("import_project_url requires projectId and url");
|
|
3183
|
+
result = await runtime.connection.request("POST", `/v1/projects/${encodeURIComponent(impProjId)}/import-url`, {
|
|
3184
|
+
url: impUrl, branch: action.branch, subdir: action.subdir,
|
|
3185
|
+
});
|
|
3186
|
+
if (!json)
|
|
3187
|
+
console.log(chalk.dim(` [reactive] Imported from ${impUrl}`));
|
|
3188
|
+
break;
|
|
3189
|
+
}
|
|
3190
|
+
case "match_submission_spec": {
|
|
3191
|
+
const msBountyId = action.bountyId;
|
|
3192
|
+
const msSubId = action.subId;
|
|
3193
|
+
if (!msBountyId || !msSubId)
|
|
3194
|
+
throw new Error("match_submission_spec requires bountyId and subId");
|
|
3195
|
+
result = await runtime.connection.request("POST", `/v1/bounties/${encodeURIComponent(msBountyId)}/submissions/${encodeURIComponent(msSubId)}/match-spec`, {});
|
|
3196
|
+
if (!json)
|
|
3197
|
+
console.log(chalk.dim(` [reactive] Matched submission spec`));
|
|
3198
|
+
break;
|
|
3199
|
+
}
|
|
3200
|
+
case "verify_submission": {
|
|
3201
|
+
const vsBountyId = action.bountyId;
|
|
3202
|
+
const vsSubId = action.subId;
|
|
3203
|
+
if (!vsBountyId || !vsSubId)
|
|
3204
|
+
throw new Error("verify_submission requires bountyId and subId");
|
|
3205
|
+
result = await runtime.connection.request("POST", `/v1/bounties/${encodeURIComponent(vsBountyId)}/submissions/${encodeURIComponent(vsSubId)}/verify`, { testCommand: action.testCommand });
|
|
3206
|
+
if (!json)
|
|
3207
|
+
console.log(chalk.dim(` [reactive] Verified submission`));
|
|
3208
|
+
break;
|
|
3209
|
+
}
|
|
3210
|
+
case "review_submission": {
|
|
3211
|
+
const rsBountyId = action.bountyId;
|
|
3212
|
+
const rsSubId = action.subId;
|
|
3213
|
+
if (!rsBountyId || !rsSubId)
|
|
3214
|
+
throw new Error("review_submission requires bountyId and subId");
|
|
3215
|
+
result = await runtime.connection.request("POST", `/v1/bounties/${encodeURIComponent(rsBountyId)}/submissions/${encodeURIComponent(rsSubId)}/review`, {});
|
|
3216
|
+
if (!json)
|
|
3217
|
+
console.log(chalk.dim(` [reactive] Reviewed submission`));
|
|
3218
|
+
break;
|
|
3219
|
+
}
|
|
3220
|
+
case "review_merge_request": {
|
|
3221
|
+
const rmrProjId = action.projectId;
|
|
3222
|
+
const rmrMrId = action.mrId;
|
|
3223
|
+
if (!rmrProjId || !rmrMrId)
|
|
3224
|
+
throw new Error("review_merge_request requires projectId and mrId");
|
|
3225
|
+
const mr = await runtime.connection.request("GET", `/v1/projects/${encodeURIComponent(rmrProjId)}/merge-requests/${encodeURIComponent(rmrMrId)}`);
|
|
3226
|
+
const commits = (mr?.commits || []);
|
|
3227
|
+
const reviews = [];
|
|
3228
|
+
for (const c of commits) {
|
|
3229
|
+
try {
|
|
3230
|
+
const rv = await runtime.connection.request("POST", `/v1/projects/${encodeURIComponent(rmrProjId)}/commits/${encodeURIComponent(c.id || c.commitId)}/ai-review`, {});
|
|
3231
|
+
reviews.push(rv);
|
|
3232
|
+
}
|
|
3233
|
+
catch { }
|
|
2161
3234
|
}
|
|
3235
|
+
result = { mergeRequest: mr, reviews };
|
|
3236
|
+
if (!json)
|
|
3237
|
+
console.log(chalk.dim(` [reactive] Reviewed MR ${rmrMrId} (${reviews.length} commits)`));
|
|
3238
|
+
break;
|
|
3239
|
+
}
|
|
3240
|
+
case "update_profile": {
|
|
3241
|
+
result = await runtime.connection.request("PATCH", "/v1/agents/me", {
|
|
3242
|
+
displayName: action.displayName, description: action.description,
|
|
3243
|
+
capabilities: action.capabilities,
|
|
3244
|
+
});
|
|
3245
|
+
if (!json)
|
|
3246
|
+
console.log(chalk.dim(` [reactive] Updated profile`));
|
|
3247
|
+
break;
|
|
3248
|
+
}
|
|
3249
|
+
case "register": {
|
|
3250
|
+
result = await runtime.connection.request("POST", "/v1/agents/register", {
|
|
3251
|
+
name: action.name, description: action.description,
|
|
3252
|
+
});
|
|
3253
|
+
if (!json)
|
|
3254
|
+
console.log(chalk.dim(` [reactive] Registered agent`));
|
|
3255
|
+
break;
|
|
3256
|
+
}
|
|
3257
|
+
// ── Workspace tools ────────────────────────────────────────
|
|
3258
|
+
case "create_workspace": {
|
|
3259
|
+
const cwName = action.name;
|
|
3260
|
+
if (!cwName)
|
|
3261
|
+
throw new Error("create_workspace requires name");
|
|
3262
|
+
result = await runtime.connection.request("POST", "/v1/workspaces", { name: cwName, description: action.description });
|
|
3263
|
+
if (!json)
|
|
3264
|
+
console.log(chalk.dim(` [reactive] Created workspace: ${cwName}`));
|
|
3265
|
+
break;
|
|
3266
|
+
}
|
|
3267
|
+
case "workspace_add_member": {
|
|
3268
|
+
const wamWsId = action.workspaceId;
|
|
3269
|
+
const wamAgentId = action.agentId;
|
|
3270
|
+
if (!wamWsId || !wamAgentId)
|
|
3271
|
+
throw new Error("workspace_add_member requires workspaceId and agentId");
|
|
3272
|
+
result = await runtime.connection.request("POST", `/v1/workspaces/${encodeURIComponent(wamWsId)}/members`, { agentId: wamAgentId, role: action.role || "editor" });
|
|
3273
|
+
if (!json)
|
|
3274
|
+
console.log(chalk.dim(` [reactive] Added member to workspace`));
|
|
3275
|
+
break;
|
|
3276
|
+
}
|
|
3277
|
+
case "workspace_set_entry": {
|
|
3278
|
+
const wseWsId = action.workspaceId;
|
|
3279
|
+
const wseKey = action.key;
|
|
3280
|
+
if (!wseWsId || !wseKey)
|
|
3281
|
+
throw new Error("workspace_set_entry requires workspaceId and key");
|
|
3282
|
+
result = await runtime.connection.request("PUT", `/v1/workspaces/${encodeURIComponent(wseWsId)}/state`, { key: wseKey, value: action.value });
|
|
3283
|
+
if (!json)
|
|
3284
|
+
console.log(chalk.dim(` [reactive] Set workspace entry: ${wseKey}`));
|
|
3285
|
+
break;
|
|
3286
|
+
}
|
|
3287
|
+
case "workspace_get_entries": {
|
|
3288
|
+
const wgeWsId = action.workspaceId;
|
|
3289
|
+
if (!wgeWsId)
|
|
3290
|
+
throw new Error("workspace_get_entries requires workspaceId");
|
|
3291
|
+
result = await runtime.connection.request("GET", `/v1/workspaces/${encodeURIComponent(wgeWsId)}/state`);
|
|
3292
|
+
if (!json)
|
|
3293
|
+
console.log(chalk.dim(` [reactive] Got workspace entries`));
|
|
3294
|
+
break;
|
|
3295
|
+
}
|
|
3296
|
+
case "create_proposal": {
|
|
3297
|
+
const cpWsId = action.workspaceId;
|
|
3298
|
+
const cpTitle = action.title;
|
|
3299
|
+
if (!cpWsId || !cpTitle)
|
|
3300
|
+
throw new Error("create_proposal requires workspaceId and title");
|
|
3301
|
+
result = await runtime.connection.request("POST", `/v1/workspaces/${encodeURIComponent(cpWsId)}/proposals`, {
|
|
3302
|
+
title: cpTitle, description: action.description,
|
|
3303
|
+
actionType: action.actionType, actionPayload: action.actionPayload,
|
|
3304
|
+
});
|
|
3305
|
+
if (!json)
|
|
3306
|
+
console.log(chalk.dim(` [reactive] Created proposal: ${cpTitle}`));
|
|
3307
|
+
break;
|
|
3308
|
+
}
|
|
3309
|
+
// ── Skill/rating tools ─────────────────────────────────────
|
|
3310
|
+
case "rate_skill":
|
|
3311
|
+
case "review_skill": {
|
|
3312
|
+
const rsSkillId = action.skillId;
|
|
3313
|
+
const rsRating = action.rating;
|
|
3314
|
+
if (!rsSkillId || !rsRating)
|
|
3315
|
+
throw new Error("rate_skill requires skillId and rating");
|
|
3316
|
+
result = await runtime.connection.request("POST", `/v1/skills/registry/${encodeURIComponent(rsSkillId)}/review`, {
|
|
3317
|
+
rating: rsRating, review: action.review,
|
|
3318
|
+
});
|
|
3319
|
+
if (!json)
|
|
3320
|
+
console.log(chalk.dim(` [reactive] Rated skill ${rsSkillId}`));
|
|
3321
|
+
break;
|
|
3322
|
+
}
|
|
3323
|
+
case "teaching_stats": {
|
|
3324
|
+
result = await runtime.connection.request("GET", "/v1/teaching/stats");
|
|
3325
|
+
if (!json)
|
|
3326
|
+
console.log(chalk.dim(` [reactive] Got teaching stats`));
|
|
3327
|
+
break;
|
|
3328
|
+
}
|
|
3329
|
+
case "search_teachers": {
|
|
3330
|
+
const stGoal = action.goal;
|
|
3331
|
+
if (!stGoal)
|
|
3332
|
+
throw new Error("search_teachers requires goal");
|
|
3333
|
+
const stqs = new URLSearchParams();
|
|
3334
|
+
stqs.set("goal", stGoal);
|
|
3335
|
+
if (action.limit)
|
|
3336
|
+
stqs.set("limit", String(action.limit));
|
|
3337
|
+
result = await runtime.connection.request("GET", `/v1/teaching/search-teachers?${stqs}`);
|
|
3338
|
+
if (!json)
|
|
3339
|
+
console.log(chalk.dim(` [reactive] Searched teachers`));
|
|
3340
|
+
break;
|
|
3341
|
+
}
|
|
3342
|
+
// ── Token launch tools ─────────────────────────────────────
|
|
3343
|
+
case "report_token_launch": {
|
|
3344
|
+
const tokenName = action.tokenName;
|
|
3345
|
+
const tokenTicker = action.tokenTicker;
|
|
3346
|
+
const tokenAddress2 = action.tokenAddress;
|
|
3347
|
+
if (!tokenName || !tokenTicker || !tokenAddress2)
|
|
3348
|
+
throw new Error("report_token_launch requires tokenName, tokenTicker, tokenAddress");
|
|
3349
|
+
result = await runtime.connection.request("POST", "/v1/clawnch/report-launch", {
|
|
3350
|
+
tokenName, tokenTicker, tokenAddress: tokenAddress2,
|
|
3351
|
+
description: action.description, imageUrl: action.imageUrl,
|
|
3352
|
+
poolAddress: action.poolAddress, protocolFeeSharePct: action.protocolFeeSharePct,
|
|
3353
|
+
});
|
|
3354
|
+
if (!json)
|
|
3355
|
+
console.log(chalk.dim(` [reactive] Reported token launch: ${tokenName}`));
|
|
3356
|
+
break;
|
|
3357
|
+
}
|
|
3358
|
+
case "ignore":
|
|
3359
|
+
break;
|
|
3360
|
+
default: {
|
|
3361
|
+
// ── Unhandled action ─────────────────────────────────────
|
|
3362
|
+
// All known tools should have explicit cases above.
|
|
3363
|
+
// Log unhandled for debugging — DO NOT route through MCP.
|
|
3364
|
+
if (!json)
|
|
3365
|
+
console.log(chalk.dim(` [reactive] Unhandled action: ${action.action}`));
|
|
2162
3366
|
break;
|
|
2163
3367
|
}
|
|
2164
3368
|
}
|