@guanxing1/plugin-elizaos 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +168 -0
- package/dist/index.cjs +957 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +45 -0
- package/dist/index.d.ts +45 -0
- package/dist/index.js +919 -0
- package/dist/index.js.map +1 -0
- package/package.json +56 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,919 @@
|
|
|
1
|
+
// src/services/guanxingService.ts
|
|
2
|
+
import { Service } from "@elizaos/core";
|
|
3
|
+
var BASE_URL = "https://heartai.zeabur.app";
|
|
4
|
+
var GuanXingService = class _GuanXingService extends Service {
|
|
5
|
+
static serviceType = "guanxing";
|
|
6
|
+
capabilityDescription = "Chinese metaphysics API client (\u89C2\u661F GuanXing)";
|
|
7
|
+
async stop() {
|
|
8
|
+
}
|
|
9
|
+
static async start(_runtime) {
|
|
10
|
+
return new _GuanXingService();
|
|
11
|
+
}
|
|
12
|
+
static async callAPI(endpoint, body, apiKey) {
|
|
13
|
+
const res = await fetch(`${BASE_URL}/api/v1/${endpoint}`, {
|
|
14
|
+
method: "POST",
|
|
15
|
+
headers: {
|
|
16
|
+
"Content-Type": "application/json",
|
|
17
|
+
"Authorization": `Bearer ${apiKey}`
|
|
18
|
+
},
|
|
19
|
+
body: JSON.stringify(body)
|
|
20
|
+
});
|
|
21
|
+
const json = await res.json();
|
|
22
|
+
if (!res.ok || !json.success) {
|
|
23
|
+
throw new Error(json.error ?? `GuanXing API error: ${res.status}`);
|
|
24
|
+
}
|
|
25
|
+
return json;
|
|
26
|
+
}
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
// src/actions/bazi.ts
|
|
30
|
+
function extractDate(text) {
|
|
31
|
+
const isoMatch = text.match(/(\d{4})[-/](\d{1,2})[-/](\d{1,2})/);
|
|
32
|
+
if (isoMatch) {
|
|
33
|
+
const [, y, m, d] = isoMatch;
|
|
34
|
+
return `${y}-${m.padStart(2, "0")}-${d.padStart(2, "0")}`;
|
|
35
|
+
}
|
|
36
|
+
const months = {
|
|
37
|
+
january: "01",
|
|
38
|
+
february: "02",
|
|
39
|
+
march: "03",
|
|
40
|
+
april: "04",
|
|
41
|
+
may: "05",
|
|
42
|
+
june: "06",
|
|
43
|
+
july: "07",
|
|
44
|
+
august: "08",
|
|
45
|
+
september: "09",
|
|
46
|
+
october: "10",
|
|
47
|
+
november: "11",
|
|
48
|
+
december: "12",
|
|
49
|
+
jan: "01",
|
|
50
|
+
feb: "02",
|
|
51
|
+
mar: "03",
|
|
52
|
+
apr: "04",
|
|
53
|
+
jun: "06",
|
|
54
|
+
jul: "07",
|
|
55
|
+
aug: "08",
|
|
56
|
+
sep: "09",
|
|
57
|
+
oct: "10",
|
|
58
|
+
nov: "11",
|
|
59
|
+
dec: "12"
|
|
60
|
+
};
|
|
61
|
+
const monthPattern = Object.keys(months).join("|");
|
|
62
|
+
const mdyMatch = text.match(new RegExp(`(${monthPattern})\\s+(\\d{1,2}),?\\s+(\\d{4})`, "i"));
|
|
63
|
+
if (mdyMatch) {
|
|
64
|
+
const m = months[mdyMatch[1].toLowerCase()];
|
|
65
|
+
return `${mdyMatch[3]}-${m}-${mdyMatch[2].padStart(2, "0")}`;
|
|
66
|
+
}
|
|
67
|
+
const dmyMatch = text.match(new RegExp(`(\\d{1,2})\\s+(${monthPattern}),?\\s+(\\d{4})`, "i"));
|
|
68
|
+
if (dmyMatch) {
|
|
69
|
+
const m = months[dmyMatch[2].toLowerCase()];
|
|
70
|
+
return `${dmyMatch[3]}-${m}-${dmyMatch[1].padStart(2, "0")}`;
|
|
71
|
+
}
|
|
72
|
+
return null;
|
|
73
|
+
}
|
|
74
|
+
function extractHour(text) {
|
|
75
|
+
const pmMatch = text.match(/(\d{1,2})\s*pm/i);
|
|
76
|
+
if (pmMatch) {
|
|
77
|
+
const h = parseInt(pmMatch[1], 10);
|
|
78
|
+
return h === 12 ? 12 : h + 12;
|
|
79
|
+
}
|
|
80
|
+
const amMatch = text.match(/(\d{1,2})\s*am/i);
|
|
81
|
+
if (amMatch) {
|
|
82
|
+
const h = parseInt(amMatch[1], 10);
|
|
83
|
+
return h === 12 ? 0 : h;
|
|
84
|
+
}
|
|
85
|
+
const timeMatch = text.match(/(\d{1,2}):(\d{2})/);
|
|
86
|
+
if (timeMatch) return parseInt(timeMatch[1], 10);
|
|
87
|
+
const cnMatch = text.match(/(\d{1,2})\s*[时点]/);
|
|
88
|
+
if (cnMatch) return parseInt(cnMatch[1], 10);
|
|
89
|
+
return void 0;
|
|
90
|
+
}
|
|
91
|
+
var baziAction = {
|
|
92
|
+
name: "BAZI_ANALYSIS",
|
|
93
|
+
description: "Analyze Chinese Four Pillars of Destiny (BaZi/\u516B\u5B57) based on birth date and time. Returns heavenly stems, earthly branches, five elements balance, and life analysis.",
|
|
94
|
+
similes: [
|
|
95
|
+
"BAZI",
|
|
96
|
+
"FOUR_PILLARS",
|
|
97
|
+
"EIGHT_CHARACTERS",
|
|
98
|
+
"CHINESE_ASTROLOGY",
|
|
99
|
+
"BIRTH_CHART",
|
|
100
|
+
"BAZI_READING",
|
|
101
|
+
"FOUR_PILLARS_OF_DESTINY"
|
|
102
|
+
],
|
|
103
|
+
validate: async (runtime, _message, _state) => {
|
|
104
|
+
return !!runtime.getSetting("GUANXING_API_KEY");
|
|
105
|
+
},
|
|
106
|
+
handler: async (runtime, message, _state, _options, callback) => {
|
|
107
|
+
const apiKey = String(runtime.getSetting("GUANXING_API_KEY"));
|
|
108
|
+
const text = typeof message.content === "string" ? message.content : message.content.text ?? "";
|
|
109
|
+
const birthDate = extractDate(text);
|
|
110
|
+
if (!birthDate) {
|
|
111
|
+
const reply = "I need a birth date to perform BaZi analysis. Please provide a date like: **1990-06-15** or **June 15, 1990**.";
|
|
112
|
+
callback?.({ text: reply });
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
115
|
+
const birthHour = extractHour(text);
|
|
116
|
+
try {
|
|
117
|
+
const res = await GuanXingService.callAPI("bazi", {
|
|
118
|
+
birthDate,
|
|
119
|
+
...birthHour !== void 0 && { birthHour }
|
|
120
|
+
}, apiKey);
|
|
121
|
+
const d = res.data;
|
|
122
|
+
const wuxing = Object.entries(d.wuxing).map(([k, v]) => `${k}: ${v}`).join(" | ");
|
|
123
|
+
const reply = [
|
|
124
|
+
`**\u516B\u5B57 BaZi Analysis** for ${birthDate}${birthHour !== void 0 ? ` at ${birthHour}:00` : ""}`,
|
|
125
|
+
"",
|
|
126
|
+
`**Four Pillars:** ${d.bazi}`,
|
|
127
|
+
`**Day Master (\u65E5\u4E3B):** ${d.dayMaster}`,
|
|
128
|
+
`**Five Elements (\u4E94\u884C):** ${wuxing}`,
|
|
129
|
+
"",
|
|
130
|
+
d.analysis
|
|
131
|
+
].join("\n");
|
|
132
|
+
callback?.({ text: reply });
|
|
133
|
+
return;
|
|
134
|
+
} catch (err) {
|
|
135
|
+
const reply = `Sorry, I couldn't complete the BaZi analysis: ${err.message}`;
|
|
136
|
+
callback?.({ text: reply });
|
|
137
|
+
return;
|
|
138
|
+
}
|
|
139
|
+
},
|
|
140
|
+
examples: [
|
|
141
|
+
[
|
|
142
|
+
{ name: "user", content: { text: "Can you do a BaZi reading for someone born on 1990-06-15 at 2pm?" } },
|
|
143
|
+
{ name: "agent", content: { text: "**\u516B\u5B57 BaZi Analysis** for 1990-06-15 at 14:00\n\n**Four Pillars:** \u5E9A\u5348 \u58EC\u5348 \u4E01\u5DF3 \u4E01\u672A\n**Day Master (\u65E5\u4E3B):** \u4E01\u706B\n**Five Elements (\u4E94\u884C):** \u91D1: 1 | \u6728: 0 | \u6C34: 1 | \u706B: 4 | \u571F: 2\n\nYour chart shows strong Fire energy..." } }
|
|
144
|
+
],
|
|
145
|
+
[
|
|
146
|
+
{ name: "user", content: { text: "What are my eight characters? I was born March 3, 1985" } },
|
|
147
|
+
{ name: "agent", content: { text: "**\u516B\u5B57 BaZi Analysis** for 1985-03-03\n\n**Four Pillars:** \u4E59\u4E11 \u620A\u5BC5 \u8F9B\u4EA5 ..." } }
|
|
148
|
+
]
|
|
149
|
+
]
|
|
150
|
+
};
|
|
151
|
+
|
|
152
|
+
// src/actions/fortune.ts
|
|
153
|
+
var ZODIAC_MAP = {
|
|
154
|
+
// English -> Chinese
|
|
155
|
+
aries: "\u767D\u7F8A\u5EA7",
|
|
156
|
+
taurus: "\u91D1\u725B\u5EA7",
|
|
157
|
+
gemini: "\u53CC\u5B50\u5EA7",
|
|
158
|
+
cancer: "\u5DE8\u87F9\u5EA7",
|
|
159
|
+
leo: "\u72EE\u5B50\u5EA7",
|
|
160
|
+
virgo: "\u5904\u5973\u5EA7",
|
|
161
|
+
libra: "\u5929\u79E4\u5EA7",
|
|
162
|
+
scorpio: "\u5929\u874E\u5EA7",
|
|
163
|
+
sagittarius: "\u5C04\u624B\u5EA7",
|
|
164
|
+
capricorn: "\u6469\u7FAF\u5EA7",
|
|
165
|
+
aquarius: "\u6C34\u74F6\u5EA7",
|
|
166
|
+
pisces: "\u53CC\u9C7C\u5EA7",
|
|
167
|
+
// Chinese names pass through
|
|
168
|
+
\u767D\u7F8A\u5EA7: "\u767D\u7F8A\u5EA7",
|
|
169
|
+
\u91D1\u725B\u5EA7: "\u91D1\u725B\u5EA7",
|
|
170
|
+
\u53CC\u5B50\u5EA7: "\u53CC\u5B50\u5EA7",
|
|
171
|
+
\u5DE8\u87F9\u5EA7: "\u5DE8\u87F9\u5EA7",
|
|
172
|
+
\u72EE\u5B50\u5EA7: "\u72EE\u5B50\u5EA7",
|
|
173
|
+
\u5904\u5973\u5EA7: "\u5904\u5973\u5EA7",
|
|
174
|
+
\u5929\u79E4\u5EA7: "\u5929\u79E4\u5EA7",
|
|
175
|
+
\u5929\u874E\u5EA7: "\u5929\u874E\u5EA7",
|
|
176
|
+
\u5C04\u624B\u5EA7: "\u5C04\u624B\u5EA7",
|
|
177
|
+
\u6469\u7FAF\u5EA7: "\u6469\u7FAF\u5EA7",
|
|
178
|
+
\u6C34\u74F6\u5EA7: "\u6C34\u74F6\u5EA7",
|
|
179
|
+
\u53CC\u9C7C\u5EA7: "\u53CC\u9C7C\u5EA7"
|
|
180
|
+
};
|
|
181
|
+
function extractZodiac(text) {
|
|
182
|
+
const lower = text.toLowerCase();
|
|
183
|
+
for (const [key, val] of Object.entries(ZODIAC_MAP)) {
|
|
184
|
+
if (lower.includes(key.toLowerCase())) return val;
|
|
185
|
+
}
|
|
186
|
+
return null;
|
|
187
|
+
}
|
|
188
|
+
function stars(n) {
|
|
189
|
+
return "\u2605".repeat(n) + "\u2606".repeat(5 - n);
|
|
190
|
+
}
|
|
191
|
+
var fortuneAction = {
|
|
192
|
+
name: "DAILY_FORTUNE",
|
|
193
|
+
description: "Get today's fortune and luck forecast by zodiac sign (\u6BCF\u65E5\u8FD0\u52BF). Covers career, love, wealth, and health with lucky color/number.",
|
|
194
|
+
similes: [
|
|
195
|
+
"DAILY_LUCK",
|
|
196
|
+
"HOROSCOPE",
|
|
197
|
+
"TODAY_FORTUNE",
|
|
198
|
+
"LUCK_FORECAST",
|
|
199
|
+
"FORTUNE_TODAY",
|
|
200
|
+
"DAILY_HOROSCOPE"
|
|
201
|
+
],
|
|
202
|
+
validate: async (runtime) => {
|
|
203
|
+
return !!runtime.getSetting("GUANXING_API_KEY");
|
|
204
|
+
},
|
|
205
|
+
handler: async (runtime, message, _state, _options, callback) => {
|
|
206
|
+
const apiKey = String(runtime.getSetting("GUANXING_API_KEY"));
|
|
207
|
+
const text = typeof message.content === "string" ? message.content : message.content.text ?? "";
|
|
208
|
+
const zodiac = extractZodiac(text);
|
|
209
|
+
if (!zodiac) {
|
|
210
|
+
const reply = "Which zodiac sign should I check? Please mention a sign like **Aries**, **Leo**, or **\u5929\u79E4\u5EA7**.";
|
|
211
|
+
callback?.({ text: reply });
|
|
212
|
+
return;
|
|
213
|
+
}
|
|
214
|
+
try {
|
|
215
|
+
const res = await GuanXingService.callAPI("fortune", { zodiac }, apiKey);
|
|
216
|
+
const d = res.data;
|
|
217
|
+
const reply = [
|
|
218
|
+
`**${zodiac} \u2014 Today's Fortune \u6BCF\u65E5\u8FD0\u52BF**`,
|
|
219
|
+
"",
|
|
220
|
+
`Overall: ${stars(d.overall)}`,
|
|
221
|
+
`Career: ${stars(d.career)}`,
|
|
222
|
+
`Love: ${stars(d.love)}`,
|
|
223
|
+
`Wealth: ${stars(d.wealth)}`,
|
|
224
|
+
`Health: ${stars(d.health)}`,
|
|
225
|
+
"",
|
|
226
|
+
`\u{1F3A8} Lucky Color: ${d.luckyColor}`,
|
|
227
|
+
`\u{1F522} Lucky Number: ${d.luckyNumber}`,
|
|
228
|
+
`\u{1F3F7}\uFE0F Keywords: ${d.keywords.join(", ")}`,
|
|
229
|
+
"",
|
|
230
|
+
`\u{1F4A1} ${d.advice}`
|
|
231
|
+
].join("\n");
|
|
232
|
+
callback?.({ text: reply });
|
|
233
|
+
return;
|
|
234
|
+
} catch (err) {
|
|
235
|
+
const reply = `Sorry, I couldn't fetch the fortune: ${err.message}`;
|
|
236
|
+
callback?.({ text: reply });
|
|
237
|
+
return;
|
|
238
|
+
}
|
|
239
|
+
},
|
|
240
|
+
examples: [
|
|
241
|
+
[
|
|
242
|
+
{ name: "user", content: { text: "What's my daily fortune? I'm a Leo." } },
|
|
243
|
+
{ name: "agent", content: { text: "**\u72EE\u5B50\u5EA7 \u2014 Today's Fortune \u6BCF\u65E5\u8FD0\u52BF**\n\nOverall: \u2605\u2605\u2605\u2605\u2606\nCareer: \u2605\u2605\u2605\u2605\u2605\n..." } }
|
|
244
|
+
]
|
|
245
|
+
]
|
|
246
|
+
};
|
|
247
|
+
|
|
248
|
+
// src/actions/qiuqian.ts
|
|
249
|
+
function extractType(text) {
|
|
250
|
+
const lower = text.toLowerCase();
|
|
251
|
+
if (lower.includes("guandi") || lower.includes("\u5173\u5E1D") || lower.includes("\u5173\u516C")) return "guandi";
|
|
252
|
+
return "guanyin";
|
|
253
|
+
}
|
|
254
|
+
var qiuqianAction = {
|
|
255
|
+
name: "QIUQIAN",
|
|
256
|
+
description: "Draw a divine fortune stick (\u6C42\u7B7E) from Guanyin or Guandi temple. Ask a question and receive a numbered lot with poem and interpretation.",
|
|
257
|
+
similes: [
|
|
258
|
+
"FORTUNE_STICK",
|
|
259
|
+
"DIVINE_LOT",
|
|
260
|
+
"TEMPLE_FORTUNE",
|
|
261
|
+
"DRAW_LOT",
|
|
262
|
+
"KAUCIM",
|
|
263
|
+
"CHI_CHI_STICKS",
|
|
264
|
+
"ORACLE_STICKS"
|
|
265
|
+
],
|
|
266
|
+
validate: async (runtime) => {
|
|
267
|
+
return !!runtime.getSetting("GUANXING_API_KEY");
|
|
268
|
+
},
|
|
269
|
+
handler: async (runtime, message, _state, _options, callback) => {
|
|
270
|
+
const apiKey = String(runtime.getSetting("GUANXING_API_KEY"));
|
|
271
|
+
const text = typeof message.content === "string" ? message.content : message.content.text ?? "";
|
|
272
|
+
const question = text.replace(/^(draw|pull|get)\s+(a\s+)?(fortune\s+stick|lot|qiuqian|签)/i, "").replace(/^(求签|抽签|问签)\s*/i, "").trim() || "General guidance for my path ahead";
|
|
273
|
+
const type = extractType(text);
|
|
274
|
+
try {
|
|
275
|
+
const res = await GuanXingService.callAPI("qiuqian", { question, type }, apiKey);
|
|
276
|
+
const d = res.data;
|
|
277
|
+
const reply = [
|
|
278
|
+
`**\u{1F3EE} Fortune Stick #${d.qianNumber} \u2014 ${d.qianTitle}**`,
|
|
279
|
+
`Grade: **${d.qianType}**`,
|
|
280
|
+
"",
|
|
281
|
+
`> ${d.poem.replace(/\n/g, "\n> ")}`,
|
|
282
|
+
"",
|
|
283
|
+
`**Interpretation:** ${d.interpretation}`
|
|
284
|
+
].join("\n");
|
|
285
|
+
callback?.({ text: reply });
|
|
286
|
+
return;
|
|
287
|
+
} catch (err) {
|
|
288
|
+
const reply = `Sorry, I couldn't draw a fortune stick: ${err.message}`;
|
|
289
|
+
callback?.({ text: reply });
|
|
290
|
+
return;
|
|
291
|
+
}
|
|
292
|
+
},
|
|
293
|
+
examples: [
|
|
294
|
+
[
|
|
295
|
+
{ name: "user", content: { text: "Draw a fortune stick \u2014 should I change jobs this year?" } },
|
|
296
|
+
{ name: "agent", content: { text: "**\u{1F3EE} Fortune Stick #42 \u2014 \u65E7\u71D5\u8854\u6CE5**\nGrade: **\u4E2D\u4E0A**\n\n> \u65E7\u71D5\u91CD\u6765\u8FD4\u6545\u5DE2...\n\n**Interpretation:** This lot suggests returning to familiar ground..." } }
|
|
297
|
+
]
|
|
298
|
+
]
|
|
299
|
+
};
|
|
300
|
+
|
|
301
|
+
// src/actions/tarot.ts
|
|
302
|
+
function extractSpread(text) {
|
|
303
|
+
const lower = text.toLowerCase();
|
|
304
|
+
if (lower.includes("celtic") || lower.includes("\u51EF\u5C14\u7279")) return "celtic_cross";
|
|
305
|
+
if (lower.includes("three") || lower.includes("3") || lower.includes("\u4E09\u5F20") || lower.includes("past present future")) return "three";
|
|
306
|
+
return "single";
|
|
307
|
+
}
|
|
308
|
+
var tarotAction = {
|
|
309
|
+
name: "TAROT_READING",
|
|
310
|
+
description: "Perform a tarot card reading (\u5854\u7F57\u5360\u535C). Supports single card, three-card (past/present/future), and Celtic Cross spreads.",
|
|
311
|
+
similes: [
|
|
312
|
+
"TAROT",
|
|
313
|
+
"TAROT_CARD",
|
|
314
|
+
"CARD_READING",
|
|
315
|
+
"DRAW_TAROT",
|
|
316
|
+
"TAROT_SPREAD",
|
|
317
|
+
"PULL_A_CARD"
|
|
318
|
+
],
|
|
319
|
+
validate: async (runtime) => {
|
|
320
|
+
return !!runtime.getSetting("GUANXING_API_KEY");
|
|
321
|
+
},
|
|
322
|
+
handler: async (runtime, message, _state, _options, callback) => {
|
|
323
|
+
const apiKey = String(runtime.getSetting("GUANXING_API_KEY"));
|
|
324
|
+
const text = typeof message.content === "string" ? message.content : message.content.text ?? "";
|
|
325
|
+
const question = text.replace(/^(do\s+a\s+)?tarot\s+(reading|spread|card)/i, "").replace(/^(塔罗|占卜)\s*/i, "").trim() || "General guidance";
|
|
326
|
+
const spread = extractSpread(text);
|
|
327
|
+
try {
|
|
328
|
+
const res = await GuanXingService.callAPI("tarot", { question, spread }, apiKey);
|
|
329
|
+
const d = res.data;
|
|
330
|
+
const cardLines = d.cards.map((c, i) => {
|
|
331
|
+
const pos = d.cards.length > 1 ? `**Card ${i + 1}:** ` : "";
|
|
332
|
+
const rev = c.reversed ? " (Reversed)" : "";
|
|
333
|
+
return `${pos}${c.name}${rev} \u2014 ${c.meaning}`;
|
|
334
|
+
});
|
|
335
|
+
const reply = [
|
|
336
|
+
`**\u{1F0CF} Tarot Reading \u2014 ${d.spread}**`,
|
|
337
|
+
"",
|
|
338
|
+
...cardLines,
|
|
339
|
+
"",
|
|
340
|
+
`**Reading:** ${d.interpretation}`,
|
|
341
|
+
"",
|
|
342
|
+
`\u{1F4A1} ${d.advice}`
|
|
343
|
+
].join("\n");
|
|
344
|
+
callback?.({ text: reply });
|
|
345
|
+
return;
|
|
346
|
+
} catch (err) {
|
|
347
|
+
const reply = `Sorry, I couldn't complete the tarot reading: ${err.message}`;
|
|
348
|
+
callback?.({ text: reply });
|
|
349
|
+
return;
|
|
350
|
+
}
|
|
351
|
+
},
|
|
352
|
+
examples: [
|
|
353
|
+
[
|
|
354
|
+
{ name: "user", content: { text: "Do a three-card tarot reading about my career" } },
|
|
355
|
+
{ name: "agent", content: { text: "**\u{1F0CF} Tarot Reading \u2014 Past / Present / Future**\n\n**Card 1:** The Tower (Reversed) \u2014 Past upheaval is settling...\n**Card 2:** The Star \u2014 Current hope and inspiration...\n**Card 3:** The World \u2014 Completion and fulfillment ahead..." } }
|
|
356
|
+
]
|
|
357
|
+
]
|
|
358
|
+
};
|
|
359
|
+
|
|
360
|
+
// src/actions/dream.ts
|
|
361
|
+
function extractMood(text) {
|
|
362
|
+
const moods = [
|
|
363
|
+
"scared",
|
|
364
|
+
"happy",
|
|
365
|
+
"sad",
|
|
366
|
+
"confused",
|
|
367
|
+
"anxious",
|
|
368
|
+
"peaceful",
|
|
369
|
+
"excited",
|
|
370
|
+
"\u5BB3\u6015",
|
|
371
|
+
"\u5F00\u5FC3",
|
|
372
|
+
"\u96BE\u8FC7",
|
|
373
|
+
"\u56F0\u60D1",
|
|
374
|
+
"\u7126\u8651",
|
|
375
|
+
"\u5E73\u9759"
|
|
376
|
+
];
|
|
377
|
+
const lower = text.toLowerCase();
|
|
378
|
+
return moods.find((m) => lower.includes(m));
|
|
379
|
+
}
|
|
380
|
+
var dreamAction = {
|
|
381
|
+
name: "DREAM_INTERPRET",
|
|
382
|
+
description: "Interpret a dream using Chinese dream analysis (\u5468\u516C\u89E3\u68A6) combined with modern psychology. Describe your dream and receive symbol analysis, interpretation, and advice.",
|
|
383
|
+
similes: [
|
|
384
|
+
"DREAM_ANALYSIS",
|
|
385
|
+
"DREAM_MEANING",
|
|
386
|
+
"INTERPRET_DREAM",
|
|
387
|
+
"DREAM_DICTIONARY",
|
|
388
|
+
"DREAM_READING"
|
|
389
|
+
],
|
|
390
|
+
validate: async (runtime) => {
|
|
391
|
+
return !!runtime.getSetting("GUANXING_API_KEY");
|
|
392
|
+
},
|
|
393
|
+
handler: async (runtime, message, _state, _options, callback) => {
|
|
394
|
+
const apiKey = String(runtime.getSetting("GUANXING_API_KEY"));
|
|
395
|
+
const text = typeof message.content === "string" ? message.content : message.content.text ?? "";
|
|
396
|
+
const dream = text.replace(/^(interpret|analyze|what does)\s+(my\s+)?dream\s*(mean|about)?:?\s*/i, "").replace(/^(解梦|梦见)\s*/i, "").trim();
|
|
397
|
+
if (dream.length < 5) {
|
|
398
|
+
const reply = "Please describe your dream in more detail so I can interpret it.";
|
|
399
|
+
callback?.({ text: reply });
|
|
400
|
+
return;
|
|
401
|
+
}
|
|
402
|
+
const mood = extractMood(text);
|
|
403
|
+
try {
|
|
404
|
+
const res = await GuanXingService.callAPI("dream", {
|
|
405
|
+
dream,
|
|
406
|
+
...mood && { mood }
|
|
407
|
+
}, apiKey);
|
|
408
|
+
const d = res.data;
|
|
409
|
+
const reply = [
|
|
410
|
+
`**\u{1F319} Dream Interpretation \u5468\u516C\u89E3\u68A6**`,
|
|
411
|
+
"",
|
|
412
|
+
`**Symbols:** ${d.symbols.join(", ")}`,
|
|
413
|
+
"",
|
|
414
|
+
`**Interpretation:** ${d.interpretation}`,
|
|
415
|
+
"",
|
|
416
|
+
`**Psychological Insight:** ${d.psychAnalysis}`,
|
|
417
|
+
"",
|
|
418
|
+
`\u{1F4A1} ${d.advice}`
|
|
419
|
+
].join("\n");
|
|
420
|
+
callback?.({ text: reply });
|
|
421
|
+
return;
|
|
422
|
+
} catch (err) {
|
|
423
|
+
const reply = `Sorry, I couldn't interpret the dream: ${err.message}`;
|
|
424
|
+
callback?.({ text: reply });
|
|
425
|
+
return;
|
|
426
|
+
}
|
|
427
|
+
},
|
|
428
|
+
examples: [
|
|
429
|
+
[
|
|
430
|
+
{ name: "user", content: { text: "Interpret my dream: I was flying over a vast ocean and saw a golden dragon" } },
|
|
431
|
+
{ name: "agent", content: { text: "**\u{1F319} Dream Interpretation \u5468\u516C\u89E3\u68A6**\n\n**Symbols:** flying, ocean, golden dragon\n\n**Interpretation:** Flying over water represents emotional freedom..." } }
|
|
432
|
+
]
|
|
433
|
+
]
|
|
434
|
+
};
|
|
435
|
+
|
|
436
|
+
// src/actions/almanac.ts
|
|
437
|
+
function extractDate2(text) {
|
|
438
|
+
const match = text.match(/(\d{4})[-/](\d{1,2})[-/](\d{1,2})/);
|
|
439
|
+
if (match) {
|
|
440
|
+
const [, y, m, d] = match;
|
|
441
|
+
return `${y}-${m.padStart(2, "0")}-${d.padStart(2, "0")}`;
|
|
442
|
+
}
|
|
443
|
+
if (/tomorrow|明天/i.test(text)) {
|
|
444
|
+
const d = /* @__PURE__ */ new Date();
|
|
445
|
+
d.setDate(d.getDate() + 1);
|
|
446
|
+
return d.toISOString().slice(0, 10);
|
|
447
|
+
}
|
|
448
|
+
if (/yesterday|昨天/i.test(text)) {
|
|
449
|
+
const d = /* @__PURE__ */ new Date();
|
|
450
|
+
d.setDate(d.getDate() - 1);
|
|
451
|
+
return d.toISOString().slice(0, 10);
|
|
452
|
+
}
|
|
453
|
+
return void 0;
|
|
454
|
+
}
|
|
455
|
+
var almanacAction = {
|
|
456
|
+
name: "ALMANAC_LOOKUP",
|
|
457
|
+
description: "Look up the Chinese almanac / Huang Li (\u9EC4\u5386) for a date. Shows lunar date, auspicious/inauspicious activities, hourly fortunes, and daily summary.",
|
|
458
|
+
similes: [
|
|
459
|
+
"ALMANAC",
|
|
460
|
+
"HUANGLI",
|
|
461
|
+
"CHINESE_CALENDAR",
|
|
462
|
+
"AUSPICIOUS_DATE",
|
|
463
|
+
"LUCKY_DAY",
|
|
464
|
+
"TONG_SHING"
|
|
465
|
+
],
|
|
466
|
+
validate: async (runtime) => {
|
|
467
|
+
return !!runtime.getSetting("GUANXING_API_KEY");
|
|
468
|
+
},
|
|
469
|
+
handler: async (runtime, message, _state, _options, callback) => {
|
|
470
|
+
const apiKey = String(runtime.getSetting("GUANXING_API_KEY"));
|
|
471
|
+
const text = typeof message.content === "string" ? message.content : message.content.text ?? "";
|
|
472
|
+
const date = extractDate2(text);
|
|
473
|
+
try {
|
|
474
|
+
const res = await GuanXingService.callAPI("almanac", {
|
|
475
|
+
...date && { date }
|
|
476
|
+
}, apiKey);
|
|
477
|
+
const d = res.data;
|
|
478
|
+
const reply = [
|
|
479
|
+
`**\u{1F4C5} Chinese Almanac \u9EC4\u5386** \u2014 ${date ?? "Today"}`,
|
|
480
|
+
"",
|
|
481
|
+
`**Lunar Date:** ${d.lunarDate}`,
|
|
482
|
+
`**Gan-Zhi:** ${d.ganzhi}`,
|
|
483
|
+
"",
|
|
484
|
+
`\u2705 **Auspicious (\u5B9C):** ${d.yi.join(", ")}`,
|
|
485
|
+
`\u274C **Inauspicious (\u5FCC):** ${d.ji.join(", ")}`,
|
|
486
|
+
"",
|
|
487
|
+
`**Chong-Sha:** ${d.chongsha}`,
|
|
488
|
+
"",
|
|
489
|
+
d.summary
|
|
490
|
+
].join("\n");
|
|
491
|
+
callback?.({ text: reply });
|
|
492
|
+
return;
|
|
493
|
+
} catch (err) {
|
|
494
|
+
const reply = `Sorry, I couldn't look up the almanac: ${err.message}`;
|
|
495
|
+
callback?.({ text: reply });
|
|
496
|
+
return;
|
|
497
|
+
}
|
|
498
|
+
},
|
|
499
|
+
examples: [
|
|
500
|
+
[
|
|
501
|
+
{ name: "user", content: { text: "Check the Chinese almanac for today" } },
|
|
502
|
+
{ name: "agent", content: { text: "**\u{1F4C5} Chinese Almanac \u9EC4\u5386** \u2014 Today\n\n**Lunar Date:** \u4E8C\u6708\u5341\u4E5D\n**Gan-Zhi:** \u4E59\u5DF3\u5E74 \u5DF1\u536F\u6708 \u58EC\u7533\u65E5\n\n\u2705 **Auspicious (\u5B9C):** \u5F00\u4E1A, \u642C\u5BB6, \u7B7E\u7EA6..." } }
|
|
503
|
+
]
|
|
504
|
+
]
|
|
505
|
+
};
|
|
506
|
+
|
|
507
|
+
// src/actions/fengshui.ts
|
|
508
|
+
function extractSpaceType(text) {
|
|
509
|
+
const lower = text.toLowerCase();
|
|
510
|
+
if (lower.includes("office") || lower.includes("\u529E\u516C") || lower.includes("workplace")) return "office";
|
|
511
|
+
if (lower.includes("shop") || lower.includes("store") || lower.includes("\u5546\u94FA") || lower.includes("\u5E97")) return "shop";
|
|
512
|
+
return "home";
|
|
513
|
+
}
|
|
514
|
+
function extractDirection(text) {
|
|
515
|
+
const directions = [
|
|
516
|
+
"north",
|
|
517
|
+
"south",
|
|
518
|
+
"east",
|
|
519
|
+
"west",
|
|
520
|
+
"northeast",
|
|
521
|
+
"northwest",
|
|
522
|
+
"southeast",
|
|
523
|
+
"southwest",
|
|
524
|
+
"\u5317",
|
|
525
|
+
"\u5357",
|
|
526
|
+
"\u4E1C",
|
|
527
|
+
"\u897F",
|
|
528
|
+
"\u4E1C\u5317",
|
|
529
|
+
"\u897F\u5317",
|
|
530
|
+
"\u4E1C\u5357",
|
|
531
|
+
"\u897F\u5357"
|
|
532
|
+
];
|
|
533
|
+
const lower = text.toLowerCase();
|
|
534
|
+
return directions.find((d) => lower.includes(d));
|
|
535
|
+
}
|
|
536
|
+
var fengshuiAction = {
|
|
537
|
+
name: "FENGSHUI_ASSESSMENT",
|
|
538
|
+
description: "Assess Feng Shui (\u98CE\u6C34) for a home, office, or shop. Get score, analysis, improvement suggestions, and lucky/unlucky items.",
|
|
539
|
+
similes: [
|
|
540
|
+
"FENGSHUI",
|
|
541
|
+
"FENG_SHUI",
|
|
542
|
+
"GEOMANCY",
|
|
543
|
+
"SPACE_ENERGY",
|
|
544
|
+
"FENGSHUI_TIPS",
|
|
545
|
+
"FENGSHUI_ANALYSIS"
|
|
546
|
+
],
|
|
547
|
+
validate: async (runtime) => {
|
|
548
|
+
return !!runtime.getSetting("GUANXING_API_KEY");
|
|
549
|
+
},
|
|
550
|
+
handler: async (runtime, message, _state, _options, callback) => {
|
|
551
|
+
const apiKey = String(runtime.getSetting("GUANXING_API_KEY"));
|
|
552
|
+
const text = typeof message.content === "string" ? message.content : message.content.text ?? "";
|
|
553
|
+
const spaceType = extractSpaceType(text);
|
|
554
|
+
const direction = extractDirection(text);
|
|
555
|
+
const concerns = text.replace(/feng\s*shui|风水|assess(ment)?|check|analyze/gi, "").replace(/(home|office|shop|house|apartment)/gi, "").trim() || void 0;
|
|
556
|
+
try {
|
|
557
|
+
const res = await GuanXingService.callAPI("fengshui", {
|
|
558
|
+
spaceType,
|
|
559
|
+
...direction && { direction },
|
|
560
|
+
...concerns && { concerns }
|
|
561
|
+
}, apiKey);
|
|
562
|
+
const d = res.data;
|
|
563
|
+
const reply = [
|
|
564
|
+
`**\u{1F3E1} Feng Shui Assessment \u98CE\u6C34\u8BC4\u4F30** \u2014 ${spaceType}`,
|
|
565
|
+
"",
|
|
566
|
+
`**Score:** ${d.score}/100`,
|
|
567
|
+
"",
|
|
568
|
+
d.analysis,
|
|
569
|
+
"",
|
|
570
|
+
`**Suggestions:**`,
|
|
571
|
+
...d.suggestions.map((s) => `\u2022 ${s}`),
|
|
572
|
+
"",
|
|
573
|
+
`\u2705 **Lucky Items:** ${d.luckyItems.join(", ")}`,
|
|
574
|
+
`\u274C **Avoid:** ${d.avoidItems.join(", ")}`
|
|
575
|
+
].join("\n");
|
|
576
|
+
callback?.({ text: reply });
|
|
577
|
+
return;
|
|
578
|
+
} catch (err) {
|
|
579
|
+
const reply = `Sorry, I couldn't complete the Feng Shui assessment: ${err.message}`;
|
|
580
|
+
callback?.({ text: reply });
|
|
581
|
+
return;
|
|
582
|
+
}
|
|
583
|
+
},
|
|
584
|
+
examples: [
|
|
585
|
+
[
|
|
586
|
+
{ name: "user", content: { text: "Check the feng shui of my home office facing south" } },
|
|
587
|
+
{ name: "agent", content: { text: "**\u{1F3E1} Feng Shui Assessment \u98CE\u6C34\u8BC4\u4F30** \u2014 office\n\n**Score:** 72/100\n\nSouth-facing offices benefit from strong Fire energy..." } }
|
|
588
|
+
]
|
|
589
|
+
]
|
|
590
|
+
};
|
|
591
|
+
|
|
592
|
+
// src/actions/nameScore.ts
|
|
593
|
+
function extractName(text) {
|
|
594
|
+
const explicit = text.match(/(?:surname|last\s*name|姓)\s*[::]?\s*(\S+)\s+(?:given\s*name|first\s*name|名)\s*[::]?\s*(\S+)/i);
|
|
595
|
+
if (explicit) return { surname: explicit[1], givenName: explicit[2] };
|
|
596
|
+
const cnMatch = text.match(/([\u4e00-\u9fff]{2,4})/);
|
|
597
|
+
if (cnMatch) {
|
|
598
|
+
const name = cnMatch[1];
|
|
599
|
+
return { surname: name[0], givenName: name.slice(1) };
|
|
600
|
+
}
|
|
601
|
+
const cleaned = text.replace(/score|name|rate|analyze|check|姓名|打分/gi, "").trim();
|
|
602
|
+
const parts = cleaned.split(/\s+/).filter((p) => p.length > 0);
|
|
603
|
+
if (parts.length >= 2) {
|
|
604
|
+
return { surname: parts[0], givenName: parts.slice(1).join(" ") };
|
|
605
|
+
}
|
|
606
|
+
return null;
|
|
607
|
+
}
|
|
608
|
+
var nameScoreAction = {
|
|
609
|
+
name: "NAME_SCORE",
|
|
610
|
+
description: "Score and analyze a Chinese name using numerology and five-element theory (\u59D3\u540D\u6253\u5206). Returns Tian/Ren/Di/Wai/Zong grid scores and five-element analysis.",
|
|
611
|
+
similes: [
|
|
612
|
+
"NAME_ANALYSIS",
|
|
613
|
+
"NAME_NUMEROLOGY",
|
|
614
|
+
"NAME_SCORE",
|
|
615
|
+
"NAME_MEANING",
|
|
616
|
+
"SCORE_NAME",
|
|
617
|
+
"NAME_RATING"
|
|
618
|
+
],
|
|
619
|
+
validate: async (runtime) => {
|
|
620
|
+
return !!runtime.getSetting("GUANXING_API_KEY");
|
|
621
|
+
},
|
|
622
|
+
handler: async (runtime, message, _state, _options, callback) => {
|
|
623
|
+
const apiKey = String(runtime.getSetting("GUANXING_API_KEY"));
|
|
624
|
+
const text = typeof message.content === "string" ? message.content : message.content.text ?? "";
|
|
625
|
+
const name = extractName(text);
|
|
626
|
+
if (!name) {
|
|
627
|
+
const reply = "Please provide a name to score. Example: **\u5F20\u4F1F** or **surname: Zhang, given name: Wei**.";
|
|
628
|
+
callback?.({ text: reply });
|
|
629
|
+
return;
|
|
630
|
+
}
|
|
631
|
+
try {
|
|
632
|
+
const res = await GuanXingService.callAPI("name-score", {
|
|
633
|
+
surname: name.surname,
|
|
634
|
+
givenName: name.givenName
|
|
635
|
+
}, apiKey);
|
|
636
|
+
const d = res.data;
|
|
637
|
+
const b = d.breakdown;
|
|
638
|
+
const reply = [
|
|
639
|
+
`**\u{1F4DD} Name Score \u59D3\u540D\u6253\u5206** \u2014 ${name.surname}${name.givenName}`,
|
|
640
|
+
"",
|
|
641
|
+
`**Total Score: ${d.totalScore}/100**`,
|
|
642
|
+
"",
|
|
643
|
+
`| Grid | Score |`,
|
|
644
|
+
`|------|-------|`,
|
|
645
|
+
`| \u5929\u683C Tian | ${b.tianGe} |`,
|
|
646
|
+
`| \u4EBA\u683C Ren | ${b.renGe} |`,
|
|
647
|
+
`| \u5730\u683C Di | ${b.diGe} |`,
|
|
648
|
+
`| \u5916\u683C Wai | ${b.waiGe} |`,
|
|
649
|
+
`| \u603B\u683C Zong | ${b.zongGe} |`,
|
|
650
|
+
"",
|
|
651
|
+
`**Five Elements:** ${d.wuxingAnalysis}`,
|
|
652
|
+
"",
|
|
653
|
+
d.analysis
|
|
654
|
+
].join("\n");
|
|
655
|
+
callback?.({ text: reply });
|
|
656
|
+
return;
|
|
657
|
+
} catch (err) {
|
|
658
|
+
const reply = `Sorry, I couldn't score the name: ${err.message}`;
|
|
659
|
+
callback?.({ text: reply });
|
|
660
|
+
return;
|
|
661
|
+
}
|
|
662
|
+
},
|
|
663
|
+
examples: [
|
|
664
|
+
[
|
|
665
|
+
{ name: "user", content: { text: "Score the name \u5F20\u4F1F" } },
|
|
666
|
+
{ name: "agent", content: { text: "**\u{1F4DD} Name Score \u59D3\u540D\u6253\u5206** \u2014 \u5F20\u4F1F\n\n**Total Score: 85/100**\n\n| Grid | Score |\n|------|-------|\n| \u5929\u683C Tian | 12 |..." } }
|
|
667
|
+
]
|
|
668
|
+
]
|
|
669
|
+
};
|
|
670
|
+
|
|
671
|
+
// src/actions/compatibility.ts
|
|
672
|
+
var ZODIAC_MAP2 = {
|
|
673
|
+
aries: "\u767D\u7F8A\u5EA7",
|
|
674
|
+
taurus: "\u91D1\u725B\u5EA7",
|
|
675
|
+
gemini: "\u53CC\u5B50\u5EA7",
|
|
676
|
+
cancer: "\u5DE8\u87F9\u5EA7",
|
|
677
|
+
leo: "\u72EE\u5B50\u5EA7",
|
|
678
|
+
virgo: "\u5904\u5973\u5EA7",
|
|
679
|
+
libra: "\u5929\u79E4\u5EA7",
|
|
680
|
+
scorpio: "\u5929\u874E\u5EA7",
|
|
681
|
+
sagittarius: "\u5C04\u624B\u5EA7",
|
|
682
|
+
capricorn: "\u6469\u7FAF\u5EA7",
|
|
683
|
+
aquarius: "\u6C34\u74F6\u5EA7",
|
|
684
|
+
pisces: "\u53CC\u9C7C\u5EA7",
|
|
685
|
+
\u767D\u7F8A\u5EA7: "\u767D\u7F8A\u5EA7",
|
|
686
|
+
\u91D1\u725B\u5EA7: "\u91D1\u725B\u5EA7",
|
|
687
|
+
\u53CC\u5B50\u5EA7: "\u53CC\u5B50\u5EA7",
|
|
688
|
+
\u5DE8\u87F9\u5EA7: "\u5DE8\u87F9\u5EA7",
|
|
689
|
+
\u72EE\u5B50\u5EA7: "\u72EE\u5B50\u5EA7",
|
|
690
|
+
\u5904\u5973\u5EA7: "\u5904\u5973\u5EA7",
|
|
691
|
+
\u5929\u79E4\u5EA7: "\u5929\u79E4\u5EA7",
|
|
692
|
+
\u5929\u874E\u5EA7: "\u5929\u874E\u5EA7",
|
|
693
|
+
\u5C04\u624B\u5EA7: "\u5C04\u624B\u5EA7",
|
|
694
|
+
\u6469\u7FAF\u5EA7: "\u6469\u7FAF\u5EA7",
|
|
695
|
+
\u6C34\u74F6\u5EA7: "\u6C34\u74F6\u5EA7",
|
|
696
|
+
\u53CC\u9C7C\u5EA7: "\u53CC\u9C7C\u5EA7"
|
|
697
|
+
};
|
|
698
|
+
function findZodiacs(text) {
|
|
699
|
+
const found = [];
|
|
700
|
+
const lower = text.toLowerCase();
|
|
701
|
+
for (const [key, val] of Object.entries(ZODIAC_MAP2)) {
|
|
702
|
+
if (lower.includes(key.toLowerCase()) && !found.includes(val)) {
|
|
703
|
+
found.push(val);
|
|
704
|
+
}
|
|
705
|
+
}
|
|
706
|
+
return found;
|
|
707
|
+
}
|
|
708
|
+
function extractDates(text) {
|
|
709
|
+
const matches = [...text.matchAll(/(\d{4})[-/](\d{1,2})[-/](\d{1,2})/g)];
|
|
710
|
+
return matches.map((m) => `${m[1]}-${m[2].padStart(2, "0")}-${m[3].padStart(2, "0")}`);
|
|
711
|
+
}
|
|
712
|
+
var compatibilityAction = {
|
|
713
|
+
name: "COMPATIBILITY_CHECK",
|
|
714
|
+
description: "Check compatibility between two people using zodiac signs and/or birth dates (\u7F18\u5206\u914D\u5BF9). Returns love, career, and friendship compatibility scores.",
|
|
715
|
+
similes: [
|
|
716
|
+
"COMPATIBILITY",
|
|
717
|
+
"MATCH",
|
|
718
|
+
"LOVE_MATCH",
|
|
719
|
+
"RELATIONSHIP_CHECK",
|
|
720
|
+
"COUPLE_MATCH",
|
|
721
|
+
"ZODIAC_COMPATIBILITY"
|
|
722
|
+
],
|
|
723
|
+
validate: async (runtime) => {
|
|
724
|
+
return !!runtime.getSetting("GUANXING_API_KEY");
|
|
725
|
+
},
|
|
726
|
+
handler: async (runtime, message, _state, _options, callback) => {
|
|
727
|
+
const apiKey = String(runtime.getSetting("GUANXING_API_KEY"));
|
|
728
|
+
const text = typeof message.content === "string" ? message.content : message.content.text ?? "";
|
|
729
|
+
const zodiacs = findZodiacs(text);
|
|
730
|
+
const dates = extractDates(text);
|
|
731
|
+
if (zodiacs.length < 2 && dates.length < 2) {
|
|
732
|
+
const reply = "I need two zodiac signs or birth dates to check compatibility. Example: **Leo and Pisces** or **1990-06-15 and 1992-03-20**.";
|
|
733
|
+
callback?.({ text: reply });
|
|
734
|
+
return;
|
|
735
|
+
}
|
|
736
|
+
const person1 = { zodiac: zodiacs[0] ?? "" };
|
|
737
|
+
const person2 = { zodiac: zodiacs[1] ?? zodiacs[0] ?? "" };
|
|
738
|
+
if (dates[0]) person1.birthDate = dates[0];
|
|
739
|
+
if (dates[1]) person2.birthDate = dates[1];
|
|
740
|
+
try {
|
|
741
|
+
let bar2 = function(value) {
|
|
742
|
+
const filled = Math.round(value / 10);
|
|
743
|
+
return "\u2588".repeat(filled) + "\u2591".repeat(10 - filled) + ` ${value}%`;
|
|
744
|
+
};
|
|
745
|
+
var bar = bar2;
|
|
746
|
+
const res = await GuanXingService.callAPI("compatibility", {
|
|
747
|
+
person1,
|
|
748
|
+
person2
|
|
749
|
+
}, apiKey);
|
|
750
|
+
const d = res.data;
|
|
751
|
+
const dim = d.dimensions;
|
|
752
|
+
const reply = [
|
|
753
|
+
`**\u{1F495} Compatibility Check \u7F18\u5206\u914D\u5BF9**`,
|
|
754
|
+
`${zodiacs[0] || dates[0]} \xD7 ${zodiacs[1] || dates[1]}`,
|
|
755
|
+
"",
|
|
756
|
+
`**Overall Score: ${d.score}/100**`,
|
|
757
|
+
"",
|
|
758
|
+
`Love: ${bar2(dim.love)}`,
|
|
759
|
+
`Career: ${bar2(dim.career)}`,
|
|
760
|
+
`Friendship: ${bar2(dim.friendship)}`,
|
|
761
|
+
"",
|
|
762
|
+
d.analysis,
|
|
763
|
+
"",
|
|
764
|
+
`\u{1F4A1} ${d.advice}`
|
|
765
|
+
].join("\n");
|
|
766
|
+
callback?.({ text: reply });
|
|
767
|
+
return;
|
|
768
|
+
} catch (err) {
|
|
769
|
+
const reply = `Sorry, I couldn't check compatibility: ${err.message}`;
|
|
770
|
+
callback?.({ text: reply });
|
|
771
|
+
return;
|
|
772
|
+
}
|
|
773
|
+
},
|
|
774
|
+
examples: [
|
|
775
|
+
[
|
|
776
|
+
{ name: "user", content: { text: "Check compatibility between Leo and Pisces" } },
|
|
777
|
+
{ name: "agent", content: { text: "**\u{1F495} Compatibility Check \u7F18\u5206\u914D\u5BF9**\n\u72EE\u5B50\u5EA7 \xD7 \u53CC\u9C7C\u5EA7\n\n**Overall Score: 68/100**\n\nLove: \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2591\u2591 75%..." } }
|
|
778
|
+
]
|
|
779
|
+
]
|
|
780
|
+
};
|
|
781
|
+
|
|
782
|
+
// src/actions/zodiac.ts
|
|
783
|
+
var ZODIAC_MAP3 = {
|
|
784
|
+
aries: "\u767D\u7F8A\u5EA7",
|
|
785
|
+
taurus: "\u91D1\u725B\u5EA7",
|
|
786
|
+
gemini: "\u53CC\u5B50\u5EA7",
|
|
787
|
+
cancer: "\u5DE8\u87F9\u5EA7",
|
|
788
|
+
leo: "\u72EE\u5B50\u5EA7",
|
|
789
|
+
virgo: "\u5904\u5973\u5EA7",
|
|
790
|
+
libra: "\u5929\u79E4\u5EA7",
|
|
791
|
+
scorpio: "\u5929\u874E\u5EA7",
|
|
792
|
+
sagittarius: "\u5C04\u624B\u5EA7",
|
|
793
|
+
capricorn: "\u6469\u7FAF\u5EA7",
|
|
794
|
+
aquarius: "\u6C34\u74F6\u5EA7",
|
|
795
|
+
pisces: "\u53CC\u9C7C\u5EA7",
|
|
796
|
+
\u767D\u7F8A\u5EA7: "\u767D\u7F8A\u5EA7",
|
|
797
|
+
\u91D1\u725B\u5EA7: "\u91D1\u725B\u5EA7",
|
|
798
|
+
\u53CC\u5B50\u5EA7: "\u53CC\u5B50\u5EA7",
|
|
799
|
+
\u5DE8\u87F9\u5EA7: "\u5DE8\u87F9\u5EA7",
|
|
800
|
+
\u72EE\u5B50\u5EA7: "\u72EE\u5B50\u5EA7",
|
|
801
|
+
\u5904\u5973\u5EA7: "\u5904\u5973\u5EA7",
|
|
802
|
+
\u5929\u79E4\u5EA7: "\u5929\u79E4\u5EA7",
|
|
803
|
+
\u5929\u874E\u5EA7: "\u5929\u874E\u5EA7",
|
|
804
|
+
\u5C04\u624B\u5EA7: "\u5C04\u624B\u5EA7",
|
|
805
|
+
\u6469\u7FAF\u5EA7: "\u6469\u7FAF\u5EA7",
|
|
806
|
+
\u6C34\u74F6\u5EA7: "\u6C34\u74F6\u5EA7",
|
|
807
|
+
\u53CC\u9C7C\u5EA7: "\u53CC\u9C7C\u5EA7"
|
|
808
|
+
};
|
|
809
|
+
var ASPECTS = ["personality", "love", "career", "compatibility"];
|
|
810
|
+
function extractZodiac2(text) {
|
|
811
|
+
const lower = text.toLowerCase();
|
|
812
|
+
for (const [key, val] of Object.entries(ZODIAC_MAP3)) {
|
|
813
|
+
if (lower.includes(key.toLowerCase())) return val;
|
|
814
|
+
}
|
|
815
|
+
return null;
|
|
816
|
+
}
|
|
817
|
+
function extractAspect(text) {
|
|
818
|
+
const lower = text.toLowerCase();
|
|
819
|
+
return ASPECTS.find((a) => lower.includes(a));
|
|
820
|
+
}
|
|
821
|
+
var zodiacAction = {
|
|
822
|
+
name: "ZODIAC_READING",
|
|
823
|
+
description: "Get a detailed zodiac sign reading (\u661F\u5EA7\u89E3\u8BFB). Covers personality, love, career, and compatibility aspects with traits, element, and ruling planet.",
|
|
824
|
+
similes: [
|
|
825
|
+
"ZODIAC",
|
|
826
|
+
"STAR_SIGN",
|
|
827
|
+
"ZODIAC_READING",
|
|
828
|
+
"ZODIAC_ANALYSIS",
|
|
829
|
+
"ASTROLOGY",
|
|
830
|
+
"SIGN_READING"
|
|
831
|
+
],
|
|
832
|
+
validate: async (runtime) => {
|
|
833
|
+
return !!runtime.getSetting("GUANXING_API_KEY");
|
|
834
|
+
},
|
|
835
|
+
handler: async (runtime, message, _state, _options, callback) => {
|
|
836
|
+
const apiKey = String(runtime.getSetting("GUANXING_API_KEY"));
|
|
837
|
+
const text = typeof message.content === "string" ? message.content : message.content.text ?? "";
|
|
838
|
+
const zodiac = extractZodiac2(text);
|
|
839
|
+
if (!zodiac) {
|
|
840
|
+
const reply = "Which zodiac sign should I analyze? Please mention a sign like **Aries**, **Scorpio**, or **\u5929\u874E\u5EA7**.";
|
|
841
|
+
callback?.({ text: reply });
|
|
842
|
+
return;
|
|
843
|
+
}
|
|
844
|
+
const aspect = extractAspect(text);
|
|
845
|
+
try {
|
|
846
|
+
const res = await GuanXingService.callAPI("zodiac", {
|
|
847
|
+
zodiac,
|
|
848
|
+
...aspect && { aspect }
|
|
849
|
+
}, apiKey);
|
|
850
|
+
const d = res.data;
|
|
851
|
+
const reply = [
|
|
852
|
+
`**\u2B50 ${zodiac} Zodiac Reading \u661F\u5EA7\u89E3\u8BFB**${aspect ? ` \u2014 ${aspect}` : ""}`,
|
|
853
|
+
"",
|
|
854
|
+
`**Element:** ${d.element}`,
|
|
855
|
+
`**Ruling Planet:** ${d.rulingPlanet}`,
|
|
856
|
+
`**Key Traits:** ${d.traits.join(", ")}`,
|
|
857
|
+
`**Best Match:** ${d.compatibility.join(", ")}`,
|
|
858
|
+
"",
|
|
859
|
+
d.analysis
|
|
860
|
+
].join("\n");
|
|
861
|
+
callback?.({ text: reply });
|
|
862
|
+
return;
|
|
863
|
+
} catch (err) {
|
|
864
|
+
const reply = `Sorry, I couldn't complete the zodiac reading: ${err.message}`;
|
|
865
|
+
callback?.({ text: reply });
|
|
866
|
+
return;
|
|
867
|
+
}
|
|
868
|
+
},
|
|
869
|
+
examples: [
|
|
870
|
+
[
|
|
871
|
+
{ name: "user", content: { text: "Tell me about Scorpio's personality" } },
|
|
872
|
+
{ name: "agent", content: { text: "**\u2B50 \u5929\u874E\u5EA7 Zodiac Reading \u661F\u5EA7\u89E3\u8BFB** \u2014 personality\n\n**Element:** Water\n**Ruling Planet:** Pluto\n**Key Traits:** Passionate, Determined, Mysterious..." } }
|
|
873
|
+
]
|
|
874
|
+
]
|
|
875
|
+
};
|
|
876
|
+
|
|
877
|
+
// src/index.ts
|
|
878
|
+
var guanxingPlugin = {
|
|
879
|
+
name: "@guanxing/plugin-elizaos",
|
|
880
|
+
description: "Chinese metaphysics AI tools \u2014 BaZi (\u516B\u5B57), Tarot, I-Ching (\u6C42\u7B7E), Feng Shui, fortune telling, dream interpretation, and more. Powered by \u89C2\u661F GuanXing.",
|
|
881
|
+
actions: [
|
|
882
|
+
baziAction,
|
|
883
|
+
fortuneAction,
|
|
884
|
+
qiuqianAction,
|
|
885
|
+
tarotAction,
|
|
886
|
+
dreamAction,
|
|
887
|
+
almanacAction,
|
|
888
|
+
fengshuiAction,
|
|
889
|
+
nameScoreAction,
|
|
890
|
+
compatibilityAction,
|
|
891
|
+
zodiacAction
|
|
892
|
+
],
|
|
893
|
+
services: [GuanXingService],
|
|
894
|
+
init: async (_config, runtime) => {
|
|
895
|
+
const apiKey = runtime.getSetting("GUANXING_API_KEY");
|
|
896
|
+
if (!apiKey) {
|
|
897
|
+
console.warn(
|
|
898
|
+
"[guanxing] No GUANXING_API_KEY set. Get one at https://heartai.zeabur.app"
|
|
899
|
+
);
|
|
900
|
+
}
|
|
901
|
+
}
|
|
902
|
+
};
|
|
903
|
+
var index_default = guanxingPlugin;
|
|
904
|
+
export {
|
|
905
|
+
GuanXingService,
|
|
906
|
+
almanacAction,
|
|
907
|
+
baziAction,
|
|
908
|
+
compatibilityAction,
|
|
909
|
+
index_default as default,
|
|
910
|
+
dreamAction,
|
|
911
|
+
fengshuiAction,
|
|
912
|
+
fortuneAction,
|
|
913
|
+
guanxingPlugin,
|
|
914
|
+
nameScoreAction,
|
|
915
|
+
qiuqianAction,
|
|
916
|
+
tarotAction,
|
|
917
|
+
zodiacAction
|
|
918
|
+
};
|
|
919
|
+
//# sourceMappingURL=index.js.map
|