koishi-plugin-aka-sa-caller 0.0.1 → 0.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/lib/index.d.ts +4 -1
- package/lib/index.js +164 -2
- package/package.json +4 -4
package/lib/index.d.ts
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import { Context, Schema } from 'koishi';
|
|
2
2
|
export declare const name = "aka-sa-caller";
|
|
3
3
|
export interface Config {
|
|
4
|
+
apiUrl: string;
|
|
5
|
+
pollInterval: number;
|
|
6
|
+
maxPollAttempts: number;
|
|
4
7
|
}
|
|
5
8
|
export declare const Config: Schema<Config>;
|
|
6
|
-
export declare function apply(ctx: Context): void;
|
|
9
|
+
export declare function apply(ctx: Context, config: Config): void;
|
package/lib/index.js
CHANGED
|
@@ -27,8 +27,170 @@ __export(src_exports, {
|
|
|
27
27
|
module.exports = __toCommonJS(src_exports);
|
|
28
28
|
var import_koishi = require("koishi");
|
|
29
29
|
var name = "aka-sa-caller";
|
|
30
|
-
var Config = import_koishi.Schema.object({
|
|
31
|
-
|
|
30
|
+
var Config = import_koishi.Schema.object({
|
|
31
|
+
apiUrl: import_koishi.Schema.string().default("http://localhost:2380").description("Stock Advisor API地址"),
|
|
32
|
+
pollInterval: import_koishi.Schema.number().default(2e3).description("轮询间隔(毫秒)"),
|
|
33
|
+
maxPollAttempts: import_koishi.Schema.number().default(60).description("最大轮询次数(约2分钟)")
|
|
34
|
+
});
|
|
35
|
+
function apply(ctx, config) {
|
|
36
|
+
let stockCache = [];
|
|
37
|
+
async function fetchStocks() {
|
|
38
|
+
try {
|
|
39
|
+
const response = await ctx.http.get(
|
|
40
|
+
`${config.apiUrl}/api/stocks`
|
|
41
|
+
);
|
|
42
|
+
if (response.success) {
|
|
43
|
+
return response.stocks;
|
|
44
|
+
}
|
|
45
|
+
return [];
|
|
46
|
+
} catch (error) {
|
|
47
|
+
ctx.logger.error(`获取股票列表失败: ${error}`);
|
|
48
|
+
return [];
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
__name(fetchStocks, "fetchStocks");
|
|
52
|
+
async function submitAnalysis(symbol) {
|
|
53
|
+
try {
|
|
54
|
+
const response = await ctx.http.post(
|
|
55
|
+
`${config.apiUrl}/api/analysis/submit`,
|
|
56
|
+
{ symbol }
|
|
57
|
+
);
|
|
58
|
+
if (response.success) {
|
|
59
|
+
return response.task_id;
|
|
60
|
+
}
|
|
61
|
+
return null;
|
|
62
|
+
} catch (error) {
|
|
63
|
+
ctx.logger.error(`提交分析任务失败: ${error}`);
|
|
64
|
+
return null;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
__name(submitAnalysis, "submitAnalysis");
|
|
68
|
+
async function pollTaskStatus(taskId) {
|
|
69
|
+
for (let i = 0; i < config.maxPollAttempts; i++) {
|
|
70
|
+
try {
|
|
71
|
+
const response = await ctx.http.get(`${config.apiUrl}/api/analysis/task/${taskId}`);
|
|
72
|
+
if (response.success) {
|
|
73
|
+
const task = response.task;
|
|
74
|
+
if (task.status === "completed" && task.result) {
|
|
75
|
+
return task.result;
|
|
76
|
+
} else if (task.status === "failed") {
|
|
77
|
+
ctx.logger.error(`任务失败: ${task.error}`);
|
|
78
|
+
return null;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
} catch (error) {
|
|
82
|
+
ctx.logger.error(`查询任务状态失败: ${error}`);
|
|
83
|
+
}
|
|
84
|
+
await new Promise((resolve) => setTimeout(resolve, config.pollInterval));
|
|
85
|
+
}
|
|
86
|
+
ctx.logger.warn(`任务 ${taskId} 超时`);
|
|
87
|
+
return null;
|
|
88
|
+
}
|
|
89
|
+
__name(pollTaskStatus, "pollTaskStatus");
|
|
90
|
+
function formatAnalysis(analysis) {
|
|
91
|
+
const parts = [];
|
|
92
|
+
parts.push(`📊 ${analysis.symbol} 分析报告`);
|
|
93
|
+
parts.push(`⏰ ${new Date(analysis.timestamp).toLocaleString("zh-CN")}`);
|
|
94
|
+
parts.push("");
|
|
95
|
+
const sentimentEmoji = {
|
|
96
|
+
positive: "✅ 积极",
|
|
97
|
+
negative: "❌ 消极",
|
|
98
|
+
neutral: "⚪ 中性"
|
|
99
|
+
};
|
|
100
|
+
parts.push(`📈 市场情绪: ${sentimentEmoji[analysis.sentiment] || "未知"}`);
|
|
101
|
+
parts.push("");
|
|
102
|
+
if (analysis.action) {
|
|
103
|
+
const actionEmoji = {
|
|
104
|
+
"加仓": "🟢",
|
|
105
|
+
"减仓": "🔴",
|
|
106
|
+
"持有": "🟡",
|
|
107
|
+
"观望": "⚪"
|
|
108
|
+
};
|
|
109
|
+
parts.push(`🎯 操作建议: ${actionEmoji[analysis.action] || ""} ${analysis.action}`);
|
|
110
|
+
if (analysis.action_reason) {
|
|
111
|
+
parts.push(`理由: ${analysis.action_reason}`);
|
|
112
|
+
}
|
|
113
|
+
parts.push("");
|
|
114
|
+
}
|
|
115
|
+
if (analysis.news_summary) {
|
|
116
|
+
parts.push("📝 新闻摘要:");
|
|
117
|
+
parts.push(analysis.news_summary);
|
|
118
|
+
parts.push("");
|
|
119
|
+
}
|
|
120
|
+
if (analysis.fundamental_analysis && analysis.fundamental_analysis !== "数据解析失败" && analysis.fundamental_analysis !== "基本面分析数据不足") {
|
|
121
|
+
parts.push("🏢 基本面分析:");
|
|
122
|
+
parts.push(analysis.fundamental_analysis);
|
|
123
|
+
parts.push("");
|
|
124
|
+
}
|
|
125
|
+
if (analysis.market_sentiment && analysis.market_sentiment !== "市场情绪分析数据不足") {
|
|
126
|
+
parts.push("💹 市场情绪:");
|
|
127
|
+
parts.push(analysis.market_sentiment);
|
|
128
|
+
parts.push("");
|
|
129
|
+
}
|
|
130
|
+
if (analysis.conclusion) {
|
|
131
|
+
parts.push("📌 投资总结:");
|
|
132
|
+
parts.push(analysis.conclusion);
|
|
133
|
+
}
|
|
134
|
+
return parts.join("\n");
|
|
135
|
+
}
|
|
136
|
+
__name(formatAnalysis, "formatAnalysis");
|
|
137
|
+
ctx.on("ready", async () => {
|
|
138
|
+
stockCache = await fetchStocks();
|
|
139
|
+
ctx.logger.info(`已加载 ${stockCache.length} 只股票`);
|
|
140
|
+
for (const stock of stockCache) {
|
|
141
|
+
ctx.command(`${stock.symbol}`, `分析 ${stock.name}`).action(async ({ session }) => {
|
|
142
|
+
await session.send(`正在分析 ${stock.symbol}...`);
|
|
143
|
+
const taskId = await submitAnalysis(stock.symbol);
|
|
144
|
+
if (!taskId) {
|
|
145
|
+
return "❌ 提交分析任务失败,请稍后重试";
|
|
146
|
+
}
|
|
147
|
+
const result = await pollTaskStatus(taskId);
|
|
148
|
+
if (!result) {
|
|
149
|
+
return "❌ 分析失败或超时,请稍后重试";
|
|
150
|
+
}
|
|
151
|
+
return formatAnalysis(result);
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
});
|
|
155
|
+
ctx.command("代码", "查看所有可用的股票代码").action(async () => {
|
|
156
|
+
if (stockCache.length === 0) {
|
|
157
|
+
return "⚠️ 暂无股票,请在 Stock Advisor 中添加";
|
|
158
|
+
}
|
|
159
|
+
const lines = ["📋 可用股票代码:"];
|
|
160
|
+
for (const stock of stockCache) {
|
|
161
|
+
lines.push(`• ${stock.symbol} - ${stock.name}`);
|
|
162
|
+
}
|
|
163
|
+
lines.push("");
|
|
164
|
+
lines.push("💡 直接输入股票代码即可查询分析");
|
|
165
|
+
return lines.join("\n");
|
|
166
|
+
});
|
|
167
|
+
ctx.command("更新股票代码", "从 Stock Advisor 刷新股票列表").action(async ({ session }) => {
|
|
168
|
+
await session.send("正在更新...");
|
|
169
|
+
const oldCount = stockCache.length;
|
|
170
|
+
stockCache = await fetchStocks();
|
|
171
|
+
const newCount = stockCache.length;
|
|
172
|
+
for (const stock of stockCache) {
|
|
173
|
+
ctx.command(`${stock.symbol}`, `分析 ${stock.name}`).action(async ({ session: session2 }) => {
|
|
174
|
+
await session2.send(`正在分析 ${stock.symbol}...`);
|
|
175
|
+
const taskId = await submitAnalysis(stock.symbol);
|
|
176
|
+
if (!taskId) {
|
|
177
|
+
return "❌ 提交分析任务失败,请稍后重试";
|
|
178
|
+
}
|
|
179
|
+
const result = await pollTaskStatus(taskId);
|
|
180
|
+
if (!result) {
|
|
181
|
+
return "❌ 分析失败或超时,请稍后重试";
|
|
182
|
+
}
|
|
183
|
+
return formatAnalysis(result);
|
|
184
|
+
});
|
|
185
|
+
}
|
|
186
|
+
if (newCount > oldCount) {
|
|
187
|
+
return `✅ 更新成功!新增 ${newCount - oldCount} 只股票,当前共 ${newCount} 只`;
|
|
188
|
+
} else if (newCount < oldCount) {
|
|
189
|
+
return `✅ 更新成功!减少 ${oldCount - newCount} 只股票,当前共 ${newCount} 只`;
|
|
190
|
+
} else {
|
|
191
|
+
return `✅ 更新成功!当前共 ${newCount} 只股票`;
|
|
192
|
+
}
|
|
193
|
+
});
|
|
32
194
|
}
|
|
33
195
|
__name(apply, "apply");
|
|
34
196
|
// Annotate the CommonJS export names for ESM import in node:
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "koishi-plugin-aka-sa-caller",
|
|
3
|
-
"description": "",
|
|
4
|
-
"version": "0.0.
|
|
3
|
+
"description": "集成 Stock Advisor 的 Koishi 插件,提供股票分析功能",
|
|
4
|
+
"version": "0.0.2",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"typings": "lib/index.d.ts",
|
|
7
7
|
"files": [
|
|
@@ -36,8 +36,8 @@
|
|
|
36
36
|
},
|
|
37
37
|
"koishi": {
|
|
38
38
|
"description": {
|
|
39
|
-
"en": "",
|
|
40
|
-
"zh": ""
|
|
39
|
+
"en": "Koishi plugin for Stock Advisor integration - Analyze stocks with AI-powered insights",
|
|
40
|
+
"zh": "集成 Stock Advisor 的 Koishi 插件 - 使用 AI 分析股票"
|
|
41
41
|
},
|
|
42
42
|
"service": {
|
|
43
43
|
"required": [],
|