@hedgehog-finance/hedgehog-plugin 1.0.20 → 1.0.21
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/index.d.ts +1 -1
- package/dist/src/channel.js +124 -0
- package/dist/src/channel.js.map +1 -1
- package/dist/src/core/database.js +113 -0
- package/dist/src/core/database.js.map +1 -1
- package/dist/src/features/index.js +5 -1
- package/dist/src/features/index.js.map +1 -1
- package/dist/src/features/pluginInfo/tools.d.ts +11 -0
- package/dist/src/features/pluginInfo/tools.js +49 -0
- package/dist/src/features/pluginInfo/tools.js.map +1 -0
- package/dist/src/features/stockAnalysis/schema.d.ts +61 -0
- package/dist/src/features/stockAnalysis/schema.js +30 -0
- package/dist/src/features/stockAnalysis/schema.js.map +1 -0
- package/dist/src/features/stockAnalysis/tools.d.ts +20 -0
- package/dist/src/features/stockAnalysis/tools.js +138 -0
- package/dist/src/features/stockAnalysis/tools.js.map +1 -0
- package/dist/src/types.d.ts +1 -1
- package/package.json +1 -1
- package/src/channel.ts +128 -0
- package/src/core/database.ts +111 -0
- package/src/features/index.ts +5 -1
- package/src/features/pluginInfo/tools.ts +63 -0
- package/src/features/stockAnalysis/schema.ts +60 -0
- package/src/features/stockAnalysis/tools.ts +192 -0
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
import { randomUUID } from "node:crypto";
|
|
2
|
+
import { getDB } from "../../core/database.js";
|
|
3
|
+
import {
|
|
4
|
+
ArticleAiAnalysis,
|
|
5
|
+
GetArticleAiAnalysisParamsSchema,
|
|
6
|
+
GetStockAiAnalysisParamsSchema,
|
|
7
|
+
QueryStockAiAnalysisHistoryParamsSchema,
|
|
8
|
+
SaveArticleAiAnalysisParamsSchema,
|
|
9
|
+
SaveStockAiAnalysisParamsSchema,
|
|
10
|
+
StockAiAnalysis
|
|
11
|
+
} from "./schema.js";
|
|
12
|
+
|
|
13
|
+
interface RuntimeTool {
|
|
14
|
+
name: string;
|
|
15
|
+
description: string;
|
|
16
|
+
parameters: unknown;
|
|
17
|
+
registerTool?: boolean;
|
|
18
|
+
execute(params: unknown, ctx: { userId: string }): Promise<string>;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export function normalizeStockCode(stockCode: string): string {
|
|
22
|
+
return stockCode.trim().toUpperCase().replace(/\.SS$/i, ".SH");
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function selectLatestStockAnalysis(
|
|
26
|
+
db: ReturnType<typeof getDB>,
|
|
27
|
+
userId: string,
|
|
28
|
+
stockCode: string
|
|
29
|
+
): StockAiAnalysis | undefined {
|
|
30
|
+
return db.prepare(`
|
|
31
|
+
SELECT id, stockCode, stockName, market, content, createdAt, updatedAt
|
|
32
|
+
FROM stock_ai_analysis
|
|
33
|
+
WHERE userId = ? AND stockCode = ?
|
|
34
|
+
ORDER BY updatedAt DESC, createdAt DESC
|
|
35
|
+
LIMIT 1
|
|
36
|
+
`).get(userId, stockCode) as StockAiAnalysis | undefined;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export function saveStockAiAnalysisRecord(
|
|
40
|
+
db: ReturnType<typeof getDB>,
|
|
41
|
+
userId: string,
|
|
42
|
+
args: {
|
|
43
|
+
stockCode: string;
|
|
44
|
+
stockName: string;
|
|
45
|
+
market: string;
|
|
46
|
+
content: string;
|
|
47
|
+
}
|
|
48
|
+
): StockAiAnalysis {
|
|
49
|
+
const stockCode = normalizeStockCode(args.stockCode);
|
|
50
|
+
const id = randomUUID();
|
|
51
|
+
|
|
52
|
+
db.prepare(`
|
|
53
|
+
INSERT INTO stock_ai_analysis (id, userId, stockCode, stockName, market, content)
|
|
54
|
+
VALUES (?, ?, ?, ?, ?, ?)
|
|
55
|
+
`).run(id, userId, stockCode, args.stockName, args.market, args.content);
|
|
56
|
+
|
|
57
|
+
return db.prepare(`
|
|
58
|
+
SELECT id, stockCode, stockName, market, content, createdAt, updatedAt
|
|
59
|
+
FROM stock_ai_analysis
|
|
60
|
+
WHERE userId = ? AND id = ?
|
|
61
|
+
`).get(userId, id) as StockAiAnalysis;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function selectLatestArticleAnalysis(
|
|
65
|
+
db: ReturnType<typeof getDB>,
|
|
66
|
+
userId: string,
|
|
67
|
+
sourceId: string,
|
|
68
|
+
analysisType: ArticleAiAnalysis["analysisType"],
|
|
69
|
+
market: string
|
|
70
|
+
): ArticleAiAnalysis | undefined {
|
|
71
|
+
return db.prepare(`
|
|
72
|
+
SELECT id, sourceId, analysisType, market, content, createdAt, updatedAt
|
|
73
|
+
FROM article_ai_analysis
|
|
74
|
+
WHERE userId = ? AND sourceId = ? AND analysisType = ? AND market = ?
|
|
75
|
+
ORDER BY updatedAt DESC, createdAt DESC
|
|
76
|
+
LIMIT 1
|
|
77
|
+
`).get(userId, sourceId, analysisType, market) as ArticleAiAnalysis | undefined;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
function saveArticleAiAnalysisRecord(
|
|
81
|
+
db: ReturnType<typeof getDB>,
|
|
82
|
+
userId: string,
|
|
83
|
+
args: {
|
|
84
|
+
sourceId: string;
|
|
85
|
+
analysisType: ArticleAiAnalysis["analysisType"];
|
|
86
|
+
market: string;
|
|
87
|
+
content: string;
|
|
88
|
+
}
|
|
89
|
+
): ArticleAiAnalysis {
|
|
90
|
+
const id = randomUUID();
|
|
91
|
+
|
|
92
|
+
db.prepare(`
|
|
93
|
+
INSERT INTO article_ai_analysis (id, sourceId, userId, analysisType, market, content)
|
|
94
|
+
VALUES (?, ?, ?, ?, ?, ?)
|
|
95
|
+
ON CONFLICT(sourceId, userId, analysisType, market) DO UPDATE SET
|
|
96
|
+
content = excluded.content,
|
|
97
|
+
updatedAt = STRFTIME('%Y-%m-%dT%H:%M:%fZ', 'NOW')
|
|
98
|
+
`).run(id, args.sourceId, userId, args.analysisType, args.market, args.content);
|
|
99
|
+
|
|
100
|
+
return db.prepare(`
|
|
101
|
+
SELECT id, sourceId, analysisType, market, content, createdAt, updatedAt
|
|
102
|
+
FROM article_ai_analysis
|
|
103
|
+
WHERE userId = ? AND sourceId = ? AND analysisType = ? AND market = ?
|
|
104
|
+
`).get(userId, args.sourceId, args.analysisType, args.market) as ArticleAiAnalysis;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
export const stockAnalysisTools: Record<string, RuntimeTool> = {
|
|
108
|
+
get_stock_ai_analysis: {
|
|
109
|
+
name: "get_stock_ai_analysis",
|
|
110
|
+
description: "读取股票 AI 分析的最新一条历史记录;不触发模型分析。",
|
|
111
|
+
parameters: GetStockAiAnalysisParamsSchema,
|
|
112
|
+
registerTool: false,
|
|
113
|
+
async execute(params, ctx) {
|
|
114
|
+
const args = GetStockAiAnalysisParamsSchema.parse(params);
|
|
115
|
+
const db = getDB();
|
|
116
|
+
const data = selectLatestStockAnalysis(db, ctx.userId, normalizeStockCode(args.stockCode));
|
|
117
|
+
return JSON.stringify({ success: true, data: data || null });
|
|
118
|
+
}
|
|
119
|
+
},
|
|
120
|
+
query_stock_ai_analysis_history: {
|
|
121
|
+
name: "query_stock_ai_analysis_history",
|
|
122
|
+
description: "分页读取股票 AI 分析历史记录;不触发模型分析。",
|
|
123
|
+
parameters: QueryStockAiAnalysisHistoryParamsSchema,
|
|
124
|
+
registerTool: false,
|
|
125
|
+
async execute(params, ctx) {
|
|
126
|
+
const args = QueryStockAiAnalysisHistoryParamsSchema.parse(params);
|
|
127
|
+
const db = getDB();
|
|
128
|
+
const stockCode = normalizeStockCode(args.stockCode);
|
|
129
|
+
const offset = (args.page - 1) * args.pageSize;
|
|
130
|
+
const rows = db.prepare(`
|
|
131
|
+
SELECT id, stockCode, stockName, market, content, createdAt, updatedAt
|
|
132
|
+
FROM stock_ai_analysis
|
|
133
|
+
WHERE userId = ? AND stockCode = ? AND market = ?
|
|
134
|
+
ORDER BY updatedAt DESC, createdAt DESC
|
|
135
|
+
LIMIT ? OFFSET ?
|
|
136
|
+
`).all(ctx.userId, stockCode, args.market, args.pageSize, offset) as StockAiAnalysis[];
|
|
137
|
+
const countRow = db.prepare(`
|
|
138
|
+
SELECT COUNT(*) AS total
|
|
139
|
+
FROM stock_ai_analysis
|
|
140
|
+
WHERE userId = ? AND stockCode = ? AND market = ?
|
|
141
|
+
`).get(ctx.userId, stockCode, args.market) as { total: number };
|
|
142
|
+
const total = countRow.total || 0;
|
|
143
|
+
|
|
144
|
+
return JSON.stringify({
|
|
145
|
+
success: true,
|
|
146
|
+
data: rows,
|
|
147
|
+
pagination: {
|
|
148
|
+
page: args.page,
|
|
149
|
+
pageSize: args.pageSize,
|
|
150
|
+
total,
|
|
151
|
+
totalPages: Math.ceil(total / args.pageSize)
|
|
152
|
+
}
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
},
|
|
156
|
+
save_stock_ai_analysis: {
|
|
157
|
+
name: "save_stock_ai_analysis",
|
|
158
|
+
description: "追加保存一条股票 AI 分析历史记录。",
|
|
159
|
+
parameters: SaveStockAiAnalysisParamsSchema,
|
|
160
|
+
registerTool: false,
|
|
161
|
+
async execute(params, ctx) {
|
|
162
|
+
const args = SaveStockAiAnalysisParamsSchema.parse(params);
|
|
163
|
+
const db = getDB();
|
|
164
|
+
const data = saveStockAiAnalysisRecord(db, ctx.userId, args);
|
|
165
|
+
return JSON.stringify({ success: true, data });
|
|
166
|
+
}
|
|
167
|
+
},
|
|
168
|
+
get_article_ai_analysis: {
|
|
169
|
+
name: "get_article_ai_analysis",
|
|
170
|
+
description: "读取文章 AI 分析结果;支持信息求证与深度推演,不触发模型分析。",
|
|
171
|
+
parameters: GetArticleAiAnalysisParamsSchema,
|
|
172
|
+
registerTool: false,
|
|
173
|
+
async execute(params, ctx) {
|
|
174
|
+
const args = GetArticleAiAnalysisParamsSchema.parse(params);
|
|
175
|
+
const db = getDB();
|
|
176
|
+
const data = selectLatestArticleAnalysis(db, ctx.userId, args.id, args.analysisType, args.market);
|
|
177
|
+
return JSON.stringify({ success: true, data: data || null });
|
|
178
|
+
}
|
|
179
|
+
},
|
|
180
|
+
save_article_ai_analysis: {
|
|
181
|
+
name: "save_article_ai_analysis",
|
|
182
|
+
description: "保存文章 AI 分析结果;支持信息求证与深度推演。",
|
|
183
|
+
parameters: SaveArticleAiAnalysisParamsSchema,
|
|
184
|
+
registerTool: false,
|
|
185
|
+
async execute(params, ctx) {
|
|
186
|
+
const args = SaveArticleAiAnalysisParamsSchema.parse(params);
|
|
187
|
+
const db = getDB();
|
|
188
|
+
const data = saveArticleAiAnalysisRecord(db, ctx.userId, { ...args, sourceId: args.id });
|
|
189
|
+
return JSON.stringify({ success: true, data });
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
};
|