plugin-undesirables 2.0.0 → 2.0.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 +123 -70
- package/dist/index.d.ts +7 -6
- package/dist/index.js +440 -394
- package/dist/index.js.map +1 -1
- package/images/banner.jpg +0 -0
- package/images/logo.jpg +0 -0
- package/package.json +13 -5
- package/dist/index.d.ts.map +0 -1
- package/og_preview.png +0 -0
- package/src/index.ts +0 -558
- package/tsconfig.json +0 -20
package/dist/index.js
CHANGED
|
@@ -1,110 +1,132 @@
|
|
|
1
|
-
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
* Features:
|
|
8
|
-
* - Load any of 4,444 unique soul personalities
|
|
9
|
-
* - 23 unique skills across the collection (10 universal + 13 strategy-specific)
|
|
10
|
-
* - Market analysis with personality-driven perspective
|
|
11
|
-
* - Business Pilot — 23 AI-powered business modules
|
|
12
|
-
* - Meme Machine — content creation & marketing
|
|
13
|
-
* - Portfolio analysis with risk guardrails
|
|
14
|
-
* - Persistent memory across sessions
|
|
15
|
-
* - Multi-agent safe (workspaces keyed by agentId)
|
|
16
|
-
*
|
|
17
|
-
* @see https://the-undesirables.com
|
|
18
|
-
* @see https://gitlab.com/meme-merchants/undesirables-mcp-server
|
|
19
|
-
*/
|
|
1
|
+
// src/index.ts
|
|
2
|
+
import * as fs2 from "fs";
|
|
3
|
+
import * as path2 from "path";
|
|
4
|
+
import * as yaml from "js-yaml";
|
|
5
|
+
|
|
6
|
+
// src/environment.ts
|
|
20
7
|
import * as fs from "fs";
|
|
21
8
|
import * as path from "path";
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
9
|
+
function validateUndesirableConfig(runtime) {
|
|
10
|
+
const workspacePath = runtime.getSetting?.("UNDESIRABLES_WORKSPACE") || process.env.UNDESIRABLES_WORKSPACE || "";
|
|
11
|
+
if (!workspacePath) {
|
|
12
|
+
return {
|
|
13
|
+
valid: false,
|
|
14
|
+
error: "UNDESIRABLES_WORKSPACE is required. Set it in your character.json settings or as an environment variable. Point it to the absolute path of your downloaded soul workspace folder."
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
if (!fs.existsSync(workspacePath)) {
|
|
18
|
+
return {
|
|
19
|
+
valid: false,
|
|
20
|
+
error: `UNDESIRABLES_WORKSPACE path does not exist: "${workspacePath}". Make sure you've downloaded and unzipped your soul workspace.`
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
const soulPath = path.join(workspacePath, "SOUL.md");
|
|
24
|
+
if (!fs.existsSync(soulPath)) {
|
|
25
|
+
return {
|
|
26
|
+
valid: false,
|
|
27
|
+
error: `No SOUL.md found in workspace: "${workspacePath}". This doesn't look like a valid soul workspace. Download one from the-undesirables.com/soul`
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
return { valid: true, workspacePath };
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// src/services.ts
|
|
34
|
+
import { Service } from "@elizaos/core";
|
|
35
|
+
var MemeTrendService = class _MemeTrendService extends Service {
|
|
36
|
+
static serviceType = "MEME_TREND_MONITOR";
|
|
37
|
+
get capabilityDescription() {
|
|
38
|
+
return "Monitors meme trends and content patterns for The Undesirables";
|
|
39
|
+
}
|
|
40
|
+
static async start(runtime) {
|
|
41
|
+
const service = new _MemeTrendService();
|
|
42
|
+
await service.initialize(runtime);
|
|
43
|
+
return service;
|
|
44
|
+
}
|
|
45
|
+
monitorInterval = null;
|
|
46
|
+
async initialize(_runtime) {
|
|
47
|
+
console.log("[Undesirables Service] Meme Trend Service initialized.");
|
|
48
|
+
}
|
|
49
|
+
async stop() {
|
|
50
|
+
if (this.monitorInterval) {
|
|
51
|
+
clearInterval(this.monitorInterval);
|
|
36
52
|
}
|
|
37
|
-
|
|
53
|
+
console.log("[Undesirables Service] Meme Trend Service stopped.");
|
|
54
|
+
}
|
|
55
|
+
pollTrends() {
|
|
56
|
+
console.log("[Undesirables Service] Background task: Fetching latest meme templates...");
|
|
57
|
+
}
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
// src/index.ts
|
|
61
|
+
var workspaces = /* @__PURE__ */ new Map();
|
|
62
|
+
function getSafePath(workspacePath, requestedFile) {
|
|
63
|
+
const baseDir = path2.resolve(workspacePath);
|
|
64
|
+
const targetPath = path2.resolve(baseDir, requestedFile);
|
|
65
|
+
if (!targetPath.startsWith(baseDir + path2.sep) && targetPath !== baseDir) {
|
|
66
|
+
throw new Error(`Security Error: Path traversal attempt detected on ${requestedFile}`);
|
|
67
|
+
}
|
|
68
|
+
return targetPath;
|
|
38
69
|
}
|
|
39
70
|
async function loadWorkspace(workspacePath) {
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
continue;
|
|
61
|
-
workspace.meta[key] = parsed[key];
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
catch {
|
|
66
|
-
// Silently skip malformed YAML frontmatter
|
|
67
|
-
}
|
|
71
|
+
const workspace = {
|
|
72
|
+
soulMd: "",
|
|
73
|
+
systemPrompt: "",
|
|
74
|
+
memory: "",
|
|
75
|
+
predictions: [],
|
|
76
|
+
skills: {},
|
|
77
|
+
meta: {}
|
|
78
|
+
};
|
|
79
|
+
const soulPath = getSafePath(workspacePath, "SOUL.md");
|
|
80
|
+
if (fs2.existsSync(soulPath)) {
|
|
81
|
+
workspace.soulMd = await fs2.promises.readFile(soulPath, "utf-8");
|
|
82
|
+
const fmMatch = workspace.soulMd.match(/^---\n([\s\S]*?)\n---/);
|
|
83
|
+
if (fmMatch) {
|
|
84
|
+
try {
|
|
85
|
+
const parsed = yaml.load(fmMatch[1], { schema: yaml.JSON_SCHEMA });
|
|
86
|
+
if (parsed && typeof parsed === "object") {
|
|
87
|
+
for (const key of Object.keys(parsed)) {
|
|
88
|
+
if (key === "__proto__" || key === "constructor" || key === "prototype") continue;
|
|
89
|
+
workspace.meta[key] = parsed[key];
|
|
90
|
+
}
|
|
68
91
|
}
|
|
92
|
+
} catch {
|
|
93
|
+
}
|
|
69
94
|
}
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
95
|
+
}
|
|
96
|
+
const systemPath = getSafePath(workspacePath, "SYSTEM_PROMPT.txt");
|
|
97
|
+
if (fs2.existsSync(systemPath)) {
|
|
98
|
+
workspace.systemPrompt = await fs2.promises.readFile(systemPath, "utf-8");
|
|
99
|
+
}
|
|
100
|
+
const memoryPath = getSafePath(workspacePath, "MEMORY.md");
|
|
101
|
+
if (fs2.existsSync(memoryPath)) {
|
|
102
|
+
workspace.memory = await fs2.promises.readFile(memoryPath, "utf-8");
|
|
103
|
+
}
|
|
104
|
+
const predictionsPath = getSafePath(workspacePath, "PREDICTIONS_LEDGER.json");
|
|
105
|
+
if (fs2.existsSync(predictionsPath)) {
|
|
106
|
+
try {
|
|
107
|
+
const raw = await fs2.promises.readFile(predictionsPath, "utf-8");
|
|
108
|
+
workspace.predictions = JSON.parse(raw);
|
|
109
|
+
} catch {
|
|
110
|
+
workspace.predictions = [];
|
|
73
111
|
}
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
112
|
+
}
|
|
113
|
+
const skillsDir = getSafePath(workspacePath, "skills");
|
|
114
|
+
if (fs2.existsSync(skillsDir)) {
|
|
115
|
+
const files = await fs2.promises.readdir(skillsDir);
|
|
116
|
+
for (const file of files.filter((f) => f.endsWith(".md"))) {
|
|
117
|
+
workspace.skills[file.replace(".md", "")] = await fs2.promises.readFile(
|
|
118
|
+
path2.join(skillsDir, file),
|
|
119
|
+
"utf-8"
|
|
120
|
+
);
|
|
77
121
|
}
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
try {
|
|
81
|
-
const raw = await fs.promises.readFile(predictionsPath, "utf-8");
|
|
82
|
-
workspace.predictions = JSON.parse(raw);
|
|
83
|
-
}
|
|
84
|
-
catch {
|
|
85
|
-
workspace.predictions = [];
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
const skillsDir = getSafePath(workspacePath, "skills");
|
|
89
|
-
if (fs.existsSync(skillsDir)) {
|
|
90
|
-
const files = await fs.promises.readdir(skillsDir);
|
|
91
|
-
for (const file of files.filter((f) => f.endsWith(".md"))) {
|
|
92
|
-
workspace.skills[file.replace(".md", "")] = await fs.promises.readFile(path.join(skillsDir, file), "utf-8");
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
return workspace;
|
|
122
|
+
}
|
|
123
|
+
return workspace;
|
|
96
124
|
}
|
|
97
|
-
// ============================================================
|
|
98
|
-
// Helper: Get workspace for current agent (multi-agent safe)
|
|
99
|
-
// ============================================================
|
|
100
125
|
function getWorkspace(runtime) {
|
|
101
|
-
|
|
126
|
+
return workspaces.get(runtime.agentId) || null;
|
|
102
127
|
}
|
|
103
|
-
// ============================================================
|
|
104
|
-
// Helper: Build context for LLM generation
|
|
105
|
-
// ============================================================
|
|
106
128
|
function buildSkillContext(skillContent, workspace, userMessage, instructions) {
|
|
107
|
-
|
|
129
|
+
return `You are an Undesirable AI agent with a unique personality.
|
|
108
130
|
|
|
109
131
|
Your personality context:
|
|
110
132
|
${workspace.soulMd.slice(0, 1500)}
|
|
@@ -124,296 +146,307 @@ ${instructions}
|
|
|
124
146
|
|
|
125
147
|
Respond in character using your archetype, risk tolerance, and guardrails.`;
|
|
126
148
|
}
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
const
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
149
|
+
async function generateResponse(runtime, context, callback, actionName) {
|
|
150
|
+
try {
|
|
151
|
+
const result = await runtime.generateText(context);
|
|
152
|
+
const text = typeof result === "string" ? result : result?.text || context;
|
|
153
|
+
if (callback) {
|
|
154
|
+
await callback({ text, source: "plugin-undesirables" }, actionName);
|
|
155
|
+
}
|
|
156
|
+
return { success: true, text };
|
|
157
|
+
} catch {
|
|
158
|
+
if (callback) {
|
|
159
|
+
await callback({ text: context, source: "plugin-undesirables" }, actionName);
|
|
160
|
+
}
|
|
161
|
+
return { success: true, text: context };
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
var marketAnalysisAction = {
|
|
165
|
+
name: "UNDESIRABLE_MARKET_ANALYSIS",
|
|
166
|
+
description: "Analyze a market, token, or trading pair using the Undesirable agent's unique personality-driven perspective and risk guardrails.",
|
|
167
|
+
similes: [
|
|
168
|
+
"ANALYZE_MARKET",
|
|
169
|
+
"MARKET_OUTLOOK",
|
|
170
|
+
"PRICE_ANALYSIS",
|
|
171
|
+
"TRADING_VIEW",
|
|
172
|
+
"WHAT_DO_YOU_THINK_ABOUT"
|
|
173
|
+
],
|
|
174
|
+
parameters: [
|
|
175
|
+
{
|
|
176
|
+
name: "asset",
|
|
177
|
+
description: "The token, coin, or market to analyze (e.g., 'ETH', 'BTC', 'SOL', 'DOGE')",
|
|
178
|
+
required: true,
|
|
179
|
+
schema: { type: "string" }
|
|
180
|
+
}
|
|
181
|
+
],
|
|
182
|
+
examples: [
|
|
183
|
+
[
|
|
184
|
+
{ name: "{{user1}}", content: { text: "What do you think about ETH right now?" } },
|
|
185
|
+
{ name: "{{agentName}}", content: { text: "Let me run my market analysis on ETH...", action: "UNDESIRABLE_MARKET_ANALYSIS" } }
|
|
139
186
|
],
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
user: "{{user1}}",
|
|
144
|
-
content: { text: "What do you think about ETH right now?" },
|
|
145
|
-
},
|
|
146
|
-
{
|
|
147
|
-
user: "{{agentName}}",
|
|
148
|
-
content: {
|
|
149
|
-
text: "Let me run my market analysis on ETH...",
|
|
150
|
-
action: "UNDESIRABLE_MARKET_ANALYSIS",
|
|
151
|
-
},
|
|
152
|
-
},
|
|
153
|
-
],
|
|
187
|
+
[
|
|
188
|
+
{ name: "{{user1}}", content: { text: "Give me your take on Bitcoin" } },
|
|
189
|
+
{ name: "{{agentName}}", content: { text: "Analyzing BTC through my lens...", action: "UNDESIRABLE_MARKET_ANALYSIS" } }
|
|
154
190
|
],
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
catch {
|
|
179
|
-
// Fallback for environments where generateText isn't available
|
|
180
|
-
if (callback)
|
|
181
|
-
callback({ text: `[Market Analysis]\n\n${context}` });
|
|
182
|
-
}
|
|
183
|
-
return true;
|
|
184
|
-
},
|
|
191
|
+
[
|
|
192
|
+
{ name: "{{user1}}", content: { text: "Is SOL a good buy here?" } },
|
|
193
|
+
{ name: "{{agentName}}", content: { text: "Running personality-driven analysis on SOL...", action: "UNDESIRABLE_MARKET_ANALYSIS" } }
|
|
194
|
+
]
|
|
195
|
+
],
|
|
196
|
+
validate: async (runtime, _message) => {
|
|
197
|
+
return getWorkspace(runtime) !== null;
|
|
198
|
+
},
|
|
199
|
+
handler: async (runtime, message, _state, _options, callback) => {
|
|
200
|
+
const workspace = getWorkspace(runtime);
|
|
201
|
+
if (!workspace) {
|
|
202
|
+
if (callback) await callback({ text: "No soul workspace loaded. Set UNDESIRABLES_WORKSPACE in your character.json settings." });
|
|
203
|
+
return { success: false, text: "No soul workspace loaded", data: { resolution: "Set UNDESIRABLES_WORKSPACE env var to your downloaded workspace path" } };
|
|
204
|
+
}
|
|
205
|
+
const skill = workspace.skills["market_analysis"] || "";
|
|
206
|
+
const context = buildSkillContext(
|
|
207
|
+
skill,
|
|
208
|
+
workspace,
|
|
209
|
+
message.content.text || "",
|
|
210
|
+
"Provide a detailed market analysis with conviction score, risk assessment, and actionable levels."
|
|
211
|
+
);
|
|
212
|
+
return generateResponse(runtime, context, callback, "UNDESIRABLE_MARKET_ANALYSIS");
|
|
213
|
+
}
|
|
185
214
|
};
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
215
|
+
var businessPilotAction = {
|
|
216
|
+
name: "UNDESIRABLE_BUSINESS_PILOT",
|
|
217
|
+
description: "Use the Business Pilot skill to recommend and set up AI-powered business tools \u2014 phone answering, SMS, invoicing, scheduling, and 23+ modules.",
|
|
218
|
+
similes: [
|
|
219
|
+
"SETUP_BUSINESS",
|
|
220
|
+
"PHONE_ANSWERING",
|
|
221
|
+
"BUSINESS_AUTOMATION",
|
|
222
|
+
"SMS_AUTORESPONDER",
|
|
223
|
+
"INVOICE_CHASER"
|
|
224
|
+
],
|
|
225
|
+
parameters: [
|
|
226
|
+
{
|
|
227
|
+
name: "business_type",
|
|
228
|
+
description: "The type of business to set up automation for (e.g., 'barbershop', 'restaurant', 'consulting')",
|
|
229
|
+
required: true,
|
|
230
|
+
schema: { type: "string" }
|
|
231
|
+
},
|
|
232
|
+
{
|
|
233
|
+
name: "module",
|
|
234
|
+
description: "Specific module to set up (e.g., 'phone answering', 'SMS', 'invoicing')",
|
|
235
|
+
required: false,
|
|
236
|
+
schema: { type: "string" }
|
|
237
|
+
}
|
|
238
|
+
],
|
|
239
|
+
examples: [
|
|
240
|
+
[
|
|
241
|
+
{ name: "{{user1}}", content: { text: "I run a barbershop. Help me set up phone answering." } },
|
|
242
|
+
{ name: "{{agentName}}", content: { text: "Loading Business Pilot skill for your barbershop...", action: "UNDESIRABLE_BUSINESS_PILOT" } }
|
|
195
243
|
],
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
user: "{{user1}}",
|
|
200
|
-
content: {
|
|
201
|
-
text: "I run a barbershop. Help me set up phone answering.",
|
|
202
|
-
},
|
|
203
|
-
},
|
|
204
|
-
{
|
|
205
|
-
user: "{{agentName}}",
|
|
206
|
-
content: {
|
|
207
|
-
text: "Loading Business Pilot skill for your barbershop...",
|
|
208
|
-
action: "UNDESIRABLE_BUSINESS_PILOT",
|
|
209
|
-
},
|
|
210
|
-
},
|
|
211
|
-
],
|
|
244
|
+
[
|
|
245
|
+
{ name: "{{user1}}", content: { text: "Set up automated SMS for my restaurant" } },
|
|
246
|
+
{ name: "{{agentName}}", content: { text: "Configuring SMS autoresponder for your restaurant...", action: "UNDESIRABLE_BUSINESS_PILOT" } }
|
|
212
247
|
],
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
},
|
|
248
|
+
[
|
|
249
|
+
{ name: "{{user1}}", content: { text: "I need invoice automation for my freelance business" } },
|
|
250
|
+
{ name: "{{agentName}}", content: { text: "Setting up invoice chaser module...", action: "UNDESIRABLE_BUSINESS_PILOT" } }
|
|
251
|
+
]
|
|
252
|
+
],
|
|
253
|
+
validate: async (runtime, _message) => {
|
|
254
|
+
const ws = getWorkspace(runtime);
|
|
255
|
+
return ws !== null && "business_pilot" in (ws?.skills || {});
|
|
256
|
+
},
|
|
257
|
+
handler: async (runtime, message, _state, _options, callback) => {
|
|
258
|
+
const workspace = getWorkspace(runtime);
|
|
259
|
+
if (!workspace) {
|
|
260
|
+
if (callback) await callback({ text: "No soul workspace loaded." });
|
|
261
|
+
return { success: false, error: "No soul workspace loaded" };
|
|
262
|
+
}
|
|
263
|
+
const skill = workspace.skills["business_pilot"] || "";
|
|
264
|
+
const context = buildSkillContext(
|
|
265
|
+
skill,
|
|
266
|
+
workspace,
|
|
267
|
+
message.content.text || "",
|
|
268
|
+
"Recommend the top 3-5 modules they should set up first with exact steps."
|
|
269
|
+
);
|
|
270
|
+
return generateResponse(runtime, context, callback, "UNDESIRABLE_BUSINESS_PILOT");
|
|
271
|
+
}
|
|
238
272
|
};
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
273
|
+
var memeMachineAction = {
|
|
274
|
+
name: "UNDESIRABLE_MEME_MACHINE",
|
|
275
|
+
description: "Generate memes, marketing content, content calendars, and viral social media assets using the Meme Machine skill.",
|
|
276
|
+
similes: [
|
|
277
|
+
"CREATE_MEME",
|
|
278
|
+
"MEME_MARKETING",
|
|
279
|
+
"CONTENT_CALENDAR",
|
|
280
|
+
"VIRAL_CONTENT",
|
|
281
|
+
"BRAND_VOICE"
|
|
282
|
+
],
|
|
283
|
+
parameters: [
|
|
284
|
+
{
|
|
285
|
+
name: "business_or_topic",
|
|
286
|
+
description: "The business, brand, or topic to create meme content for (e.g., 'barbershop', 'crypto', 'coffee shop')",
|
|
287
|
+
required: true,
|
|
288
|
+
schema: { type: "string" }
|
|
289
|
+
},
|
|
290
|
+
{
|
|
291
|
+
name: "platform",
|
|
292
|
+
description: "Target platform for the content (e.g., 'twitter', 'instagram', 'tiktok')",
|
|
293
|
+
required: false,
|
|
294
|
+
schema: { type: "string" }
|
|
295
|
+
}
|
|
296
|
+
],
|
|
297
|
+
examples: [
|
|
298
|
+
[
|
|
299
|
+
{ name: "{{user1}}", content: { text: "Create some memes for my barbershop" } },
|
|
300
|
+
{ name: "{{agentName}}", content: { text: "Firing up the Meme Machine for barbershop content...", action: "UNDESIRABLE_MEME_MACHINE" } }
|
|
248
301
|
],
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
user: "{{user1}}",
|
|
253
|
-
content: { text: "Create some memes for my barbershop" },
|
|
254
|
-
},
|
|
255
|
-
{
|
|
256
|
-
user: "{{agentName}}",
|
|
257
|
-
content: {
|
|
258
|
-
text: "Firing up the Meme Machine for barbershop content...",
|
|
259
|
-
action: "UNDESIRABLE_MEME_MACHINE",
|
|
260
|
-
},
|
|
261
|
-
},
|
|
262
|
-
],
|
|
302
|
+
[
|
|
303
|
+
{ name: "{{user1}}", content: { text: "I need viral Twitter content for my coffee brand" } },
|
|
304
|
+
{ name: "{{agentName}}", content: { text: "Generating viral coffee brand content...", action: "UNDESIRABLE_MEME_MACHINE" } }
|
|
263
305
|
],
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
},
|
|
306
|
+
[
|
|
307
|
+
{ name: "{{user1}}", content: { text: "Make me a content calendar for this week" } },
|
|
308
|
+
{ name: "{{agentName}}", content: { text: "Building your weekly content calendar...", action: "UNDESIRABLE_MEME_MACHINE" } }
|
|
309
|
+
]
|
|
310
|
+
],
|
|
311
|
+
validate: async (runtime, _message) => {
|
|
312
|
+
const ws = getWorkspace(runtime);
|
|
313
|
+
return ws !== null && "meme_machine" in (ws?.skills || {});
|
|
314
|
+
},
|
|
315
|
+
handler: async (runtime, message, _state, _options, callback) => {
|
|
316
|
+
const workspace = getWorkspace(runtime);
|
|
317
|
+
if (!workspace) {
|
|
318
|
+
if (callback) await callback({ text: "No soul workspace loaded." });
|
|
319
|
+
return { success: false, error: "No soul workspace loaded" };
|
|
320
|
+
}
|
|
321
|
+
const skill = workspace.skills["meme_machine"] || "";
|
|
322
|
+
const context = buildSkillContext(
|
|
323
|
+
skill,
|
|
324
|
+
workspace,
|
|
325
|
+
message.content.text || "",
|
|
326
|
+
"Create 3 meme concepts with template, text, caption, and export size."
|
|
327
|
+
);
|
|
328
|
+
return generateResponse(runtime, context, callback, "UNDESIRABLE_MEME_MACHINE");
|
|
329
|
+
}
|
|
289
330
|
};
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
331
|
+
var loadSkillAction = {
|
|
332
|
+
name: "UNDESIRABLE_LOAD_SKILL",
|
|
333
|
+
description: "Load and execute any of the 34 tools from the Undesirable soul workspace \u2014 market analysis, content creation, portfolio check, entry signals, exit strategy, whale tracking, snipe evaluation, and more.",
|
|
334
|
+
similes: [
|
|
335
|
+
"USE_SKILL",
|
|
336
|
+
"RUN_SKILL",
|
|
337
|
+
"EXECUTE_SKILL",
|
|
338
|
+
"CHECK_PORTFOLIO",
|
|
339
|
+
"CONTENT_CREATION",
|
|
340
|
+
"ENTRY_SIGNAL",
|
|
341
|
+
"EXIT_STRATEGY"
|
|
342
|
+
],
|
|
343
|
+
parameters: [
|
|
344
|
+
{
|
|
345
|
+
name: "skill_name",
|
|
346
|
+
description: "Name of the skill to load (e.g., 'check_portfolio', 'entry_signal', 'whale_tracker')",
|
|
347
|
+
required: false,
|
|
348
|
+
schema: { type: "string" }
|
|
349
|
+
}
|
|
350
|
+
],
|
|
351
|
+
examples: [
|
|
352
|
+
[
|
|
353
|
+
{ name: "{{user1}}", content: { text: "Check my portfolio" } },
|
|
354
|
+
{ name: "{{agentName}}", content: { text: "Loading portfolio check skill...", action: "UNDESIRABLE_LOAD_SKILL" } }
|
|
301
355
|
],
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
user: "{{user1}}",
|
|
306
|
-
content: { text: "Check my portfolio" },
|
|
307
|
-
},
|
|
308
|
-
{
|
|
309
|
-
user: "{{agentName}}",
|
|
310
|
-
content: {
|
|
311
|
-
text: "Loading portfolio check skill...",
|
|
312
|
-
action: "UNDESIRABLE_LOAD_SKILL",
|
|
313
|
-
},
|
|
314
|
-
},
|
|
315
|
-
],
|
|
356
|
+
[
|
|
357
|
+
{ name: "{{user1}}", content: { text: "Should I ape into this token?" } },
|
|
358
|
+
{ name: "{{agentName}}", content: { text: "Running ape checklist analysis...", action: "UNDESIRABLE_LOAD_SKILL" } }
|
|
316
359
|
],
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
const { generateText, ModelClass } = await import("@elizaos/core");
|
|
385
|
-
const responseText = await generateText({ runtime, context, modelClass: ModelClass.LARGE });
|
|
386
|
-
if (callback)
|
|
387
|
-
callback({ text: responseText, action: "UNDESIRABLE_LOAD_SKILL" });
|
|
388
|
-
}
|
|
389
|
-
catch {
|
|
390
|
-
if (callback)
|
|
391
|
-
callback({ text: `[${matchedName}]\n\n${context}` });
|
|
392
|
-
}
|
|
393
|
-
return true;
|
|
394
|
-
},
|
|
360
|
+
[
|
|
361
|
+
{ name: "{{user1}}", content: { text: "What are whales buying right now?" } },
|
|
362
|
+
{ name: "{{agentName}}", content: { text: "Activating whale tracker skill...", action: "UNDESIRABLE_LOAD_SKILL" } }
|
|
363
|
+
]
|
|
364
|
+
],
|
|
365
|
+
validate: async (runtime, _message) => {
|
|
366
|
+
return getWorkspace(runtime) !== null;
|
|
367
|
+
},
|
|
368
|
+
handler: async (runtime, message, _state, _options, callback) => {
|
|
369
|
+
const workspace = getWorkspace(runtime);
|
|
370
|
+
if (!workspace) {
|
|
371
|
+
if (callback) await callback({ text: "No soul workspace loaded." });
|
|
372
|
+
return { success: false, error: "No soul workspace loaded" };
|
|
373
|
+
}
|
|
374
|
+
const text = message.content.text?.toLowerCase() || "";
|
|
375
|
+
let matchedSkill = "";
|
|
376
|
+
let matchedName = "";
|
|
377
|
+
const skillMatches = {
|
|
378
|
+
check_portfolio: ["portfolio", "balance", "holdings", "how am i doing"],
|
|
379
|
+
content_creation: ["tweet", "write", "promote", "content", "thread"],
|
|
380
|
+
conviction_score: ["conviction", "confidence", "how sure"],
|
|
381
|
+
image_generation: ["image", "picture", "generate art"],
|
|
382
|
+
music_generation: ["music", "song", "beat", "audio"],
|
|
383
|
+
prediction_log: ["predict", "forecast", "call"],
|
|
384
|
+
video_production: ["video", "promo", "cinematic", "render video", "edit video"],
|
|
385
|
+
farm_yield: ["farm", "yield farming", "liquidity", "lp", "best yield"],
|
|
386
|
+
compound_strategy: ["compound", "auto-compound", "compounding", "apy", "harvest"],
|
|
387
|
+
risk_assessment: ["risk", "downside", "worst case", "is this safe"],
|
|
388
|
+
snipe_launch: ["snipe", "new launch", "token launching", "just launched"],
|
|
389
|
+
memecoin_scanner: ["memecoin", "find me a gem", "degen scan", "what memecoins"],
|
|
390
|
+
ape_checklist: ["should i ape", "ape check", "is this a good ape"],
|
|
391
|
+
whale_tracker: ["whale", "smart money", "whale watch", "what are whales buying"],
|
|
392
|
+
copy_trade: ["copy trade", "mirror this", "follow this wallet"],
|
|
393
|
+
position_sizing: ["position size", "how much should i buy", "how big"],
|
|
394
|
+
volatility_scan: ["volatile", "volatility", "what's moving", "find volatile"],
|
|
395
|
+
liquidation_watch: ["liquidation", "liquidation levels", "longs", "shorts"],
|
|
396
|
+
mev_detect: ["mev", "sandwich", "front-running", "front run"],
|
|
397
|
+
entry_signal: ["entry", "should i buy", "good time to buy", "buy signal"],
|
|
398
|
+
exit_strategy: ["exit", "sell", "take profit", "stop loss", "when should i sell"],
|
|
399
|
+
rebalance_check: ["rebalance", "allocation", "portfolio drift"],
|
|
400
|
+
diversify_check: ["diversify", "diversification", "spread", "concentrate"],
|
|
401
|
+
sector_rotation: ["sector", "rotation", "rotate", "cycle"]
|
|
402
|
+
};
|
|
403
|
+
for (const [skillName, triggers] of Object.entries(skillMatches)) {
|
|
404
|
+
if (triggers.some((t) => text.includes(t)) && workspace.skills[skillName]) {
|
|
405
|
+
matchedSkill = workspace.skills[skillName];
|
|
406
|
+
matchedName = skillName;
|
|
407
|
+
break;
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
if (!matchedSkill) {
|
|
411
|
+
const available = Object.keys(workspace.skills).filter((k) => k !== "_index").join(", ");
|
|
412
|
+
if (callback) {
|
|
413
|
+
await callback({
|
|
414
|
+
text: `Available skills: ${available}. Tell me what you need and I'll load the right one.`
|
|
415
|
+
});
|
|
416
|
+
}
|
|
417
|
+
return { success: true, text: `Listed ${available.split(", ").length} available skills` };
|
|
418
|
+
}
|
|
419
|
+
const context = buildSkillContext(
|
|
420
|
+
matchedSkill,
|
|
421
|
+
workspace,
|
|
422
|
+
message.content.text || "",
|
|
423
|
+
`Execute the ${matchedName.replace(/_/g, " ")} skill thoroughly.`
|
|
424
|
+
);
|
|
425
|
+
return generateResponse(runtime, context, callback, "UNDESIRABLE_LOAD_SKILL");
|
|
426
|
+
}
|
|
395
427
|
};
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
428
|
+
var soulProvider = {
|
|
429
|
+
name: "undesirables-soul",
|
|
430
|
+
description: "Injects Undesirable soul personality context into every agent response",
|
|
431
|
+
get: async (runtime, _message, _state) => {
|
|
432
|
+
if (!workspaces.has(runtime.agentId)) {
|
|
433
|
+
const workspacePath = runtime.getSetting?.("UNDESIRABLES_WORKSPACE") || process.env.UNDESIRABLES_WORKSPACE || "";
|
|
434
|
+
if (workspacePath && fs2.existsSync(workspacePath)) {
|
|
435
|
+
const loaded = await loadWorkspace(workspacePath);
|
|
436
|
+
workspaces.set(runtime.agentId, loaded);
|
|
437
|
+
console.log(
|
|
438
|
+
`\u{1F438} Loaded Undesirable soul: ${loaded.meta.name || "Unknown"} (agent: ${runtime.agentId})`
|
|
439
|
+
);
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
const workspace = getWorkspace(runtime);
|
|
443
|
+
if (!workspace) {
|
|
444
|
+
return {
|
|
445
|
+
text: "No Undesirable soul workspace loaded. Set UNDESIRABLES_WORKSPACE env var to your downloaded workspace path."
|
|
446
|
+
};
|
|
447
|
+
}
|
|
448
|
+
return {
|
|
449
|
+
text: `[SOUL CONTEXT]
|
|
417
450
|
Name: ${workspace.meta.name || "Unknown Undesirable"}
|
|
418
451
|
Archetype: ${workspace.meta.archetype || "Unknown"}
|
|
419
452
|
Strategy: ${workspace.meta.strategy || "Unknown"}
|
|
@@ -425,28 +458,41 @@ Predictions: ${workspace.predictions.length}
|
|
|
425
458
|
Personality: ${(workspace.meta.adjectives || []).join(", ")}
|
|
426
459
|
|
|
427
460
|
The agent should respond using the personality and style defined in its soul.
|
|
428
|
-
Collection: The Undesirables
|
|
429
|
-
Website: https://the-undesirables.com
|
|
430
|
-
|
|
461
|
+
Collection: The Undesirables \u2014 4,444 autonomous AI agents on Ethereum.
|
|
462
|
+
Website: https://the-undesirables.com`,
|
|
463
|
+
values: {
|
|
464
|
+
soulName: workspace.meta.name || "Unknown",
|
|
465
|
+
archetype: workspace.meta.archetype || "Unknown",
|
|
466
|
+
strategy: workspace.meta.strategy || "Unknown",
|
|
467
|
+
tokenId: workspace.meta.token_id || "?"
|
|
468
|
+
}
|
|
469
|
+
};
|
|
470
|
+
}
|
|
431
471
|
};
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
472
|
+
var undesirablePlugin = {
|
|
473
|
+
name: "plugin-undesirables",
|
|
474
|
+
description: "The Undesirables \u2014 4,444 autonomous AI agents on Ethereum. Pioneers 'Personality-as-Code' via verifiable soul workspaces. Adds soul personality, market analysis, Business Pilot (23 modules), Meme Machine, and 34 tools to any ElizaOS agent.",
|
|
475
|
+
init: async (config, runtime) => {
|
|
476
|
+
const validation = validateUndesirableConfig(runtime);
|
|
477
|
+
if (!validation.valid) {
|
|
478
|
+
console.warn(`\u26A0\uFE0F Undesirables: ${validation.error}`);
|
|
479
|
+
} else {
|
|
480
|
+
console.log(`\u{1F438} Undesirable soul workspace loaded: ${validation.workspacePath}`);
|
|
481
|
+
}
|
|
482
|
+
},
|
|
483
|
+
actions: [
|
|
484
|
+
marketAnalysisAction,
|
|
485
|
+
businessPilotAction,
|
|
486
|
+
memeMachineAction,
|
|
487
|
+
loadSkillAction
|
|
488
|
+
],
|
|
489
|
+
providers: [soulProvider],
|
|
490
|
+
evaluators: [],
|
|
491
|
+
services: [MemeTrendService]
|
|
492
|
+
};
|
|
493
|
+
var index_default = undesirablePlugin;
|
|
494
|
+
export {
|
|
495
|
+
index_default as default,
|
|
496
|
+
loadWorkspace
|
|
449
497
|
};
|
|
450
|
-
export default undesirablePlugin;
|
|
451
|
-
export { loadWorkspace };
|
|
452
498
|
//# sourceMappingURL=index.js.map
|