@hedgehog-finance/hedgehog-plugin 1.0.12 → 1.0.13
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 +10 -0
- package/dist/index.js +24 -0
- package/dist/index.js.map +1 -0
- package/dist/src/channel.d.ts +6 -0
- package/dist/src/channel.js +620 -0
- package/dist/src/channel.js.map +1 -0
- package/dist/src/core/database.d.ts +2 -0
- package/dist/src/core/database.js +220 -0
- package/dist/src/core/database.js.map +1 -0
- package/dist/src/core/logger.d.ts +3 -0
- package/dist/src/core/logger.js +20 -0
- package/dist/src/core/logger.js.map +1 -0
- package/dist/src/features/index.d.ts +22 -0
- package/dist/src/features/index.js +8 -0
- package/dist/src/features/index.js.map +1 -0
- package/dist/src/features/watchlist/logic.d.ts +48 -0
- package/dist/src/features/watchlist/logic.js +607 -0
- package/dist/src/features/watchlist/logic.js.map +1 -0
- package/dist/src/features/watchlist/schema.d.ts +85 -0
- package/dist/src/features/watchlist/schema.js +29 -0
- package/dist/src/features/watchlist/schema.js.map +1 -0
- package/dist/src/features/watchlist/store.d.ts +1 -0
- package/dist/src/features/watchlist/store.js +2 -0
- package/dist/src/features/watchlist/store.js.map +1 -0
- package/dist/src/features/watchlist/tools.d.ts +135 -0
- package/dist/src/features/watchlist/tools.js +572 -0
- package/dist/src/features/watchlist/tools.js.map +1 -0
- package/dist/src/runtime.d.ts +5 -0
- package/dist/src/runtime.js +40 -0
- package/dist/src/runtime.js.map +1 -0
- package/dist/src/types.d.ts +99 -0
- package/dist/src/types.js +16 -0
- package/dist/src/types.js.map +1 -0
- package/index.ts +4 -4
- package/package.json +23 -6
- package/src/channel.ts +26 -4
- package/src/core/database.ts +90 -3
- package/src/features/index.ts +2 -1
- package/src/features/watchlist/logic.ts +503 -128
- package/src/features/watchlist/schema.ts +1 -6
- package/src/features/watchlist/tools.ts +248 -103
- package/src/runtime.ts +3 -3
- package/src/types.ts +1 -1
- package/tsconfig.json +0 -16
|
@@ -0,0 +1,572 @@
|
|
|
1
|
+
import { randomUUID } from "node:crypto";
|
|
2
|
+
import { z } from "openclaw/plugin-sdk/zod";
|
|
3
|
+
import { getDB } from "../../core/database.js";
|
|
4
|
+
import { logger } from "../../core/logger.js";
|
|
5
|
+
import { watchlistLogic } from "./logic.js";
|
|
6
|
+
import { AddToWatchlistParamsSchema, GetWatchlistParamsSchema, SyncCategoriesParamsSchema, BatchUpdateSortOrdersParamsSchema } from "./schema.js";
|
|
7
|
+
let watchlistMutationQueue = Promise.resolve();
|
|
8
|
+
function enqueueWatchlistMutation(task) {
|
|
9
|
+
const previous = watchlistMutationQueue;
|
|
10
|
+
let release;
|
|
11
|
+
watchlistMutationQueue = new Promise((resolve) => {
|
|
12
|
+
release = resolve;
|
|
13
|
+
});
|
|
14
|
+
return previous
|
|
15
|
+
.catch(() => undefined)
|
|
16
|
+
.then(task)
|
|
17
|
+
.finally(release);
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* 辅助函数:统一处理归一化分类项
|
|
21
|
+
*/
|
|
22
|
+
function normalizeTags(input) {
|
|
23
|
+
if (!input)
|
|
24
|
+
return [];
|
|
25
|
+
const items = Array.isArray(input) ? input : [input];
|
|
26
|
+
return items
|
|
27
|
+
.filter((item) => typeof item?.name === 'string' && item.name.trim().length > 0)
|
|
28
|
+
.map(item => ({ name: item.name, weight: item.weight ?? 0 }));
|
|
29
|
+
}
|
|
30
|
+
function normalizeWatchlistStock(stock) {
|
|
31
|
+
return {
|
|
32
|
+
...stock,
|
|
33
|
+
stockCode: watchlistLogic._normalizeStockCodeForCache(stock.stockCode, stock.exchange)
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
function watchlistStockKey(stock) {
|
|
37
|
+
return `${watchlistLogic._normalizeStockCodeForCache(stock.stockCode, stock.exchange)}:${stock.exchange}`;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* 辅助函数:更新股票的分类标签
|
|
41
|
+
*/
|
|
42
|
+
function updateWatchlistTags(db, watchlistId, userId, industry, theme) {
|
|
43
|
+
db.prepare("DELETE FROM watchlist_industry_items WHERE watchlistId = ? AND userId = ?").run(watchlistId, userId);
|
|
44
|
+
db.prepare("DELETE FROM watchlist_theme_items WHERE watchlistId = ? AND userId = ?").run(watchlistId, userId);
|
|
45
|
+
const normIndustries = normalizeTags(industry);
|
|
46
|
+
for (const item of normIndustries) {
|
|
47
|
+
const categoryId = watchlistLogic._ensureCategory(db, item.name, 'industry', userId);
|
|
48
|
+
if (categoryId) {
|
|
49
|
+
db.prepare(`
|
|
50
|
+
INSERT OR IGNORE INTO watchlist_industry_items (id, watchlistId, userId, categoryId, weight)
|
|
51
|
+
VALUES (?, ?, ?, ?, ?)
|
|
52
|
+
`).run(randomUUID(), watchlistId, userId, categoryId, item.weight);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
const normThemes = normalizeTags(theme);
|
|
56
|
+
for (const item of normThemes) {
|
|
57
|
+
const categoryId = watchlistLogic._ensureCategory(db, item.name, 'theme', userId);
|
|
58
|
+
if (categoryId) {
|
|
59
|
+
db.prepare(`
|
|
60
|
+
INSERT OR IGNORE INTO watchlist_theme_items (id, watchlistId, userId, categoryId, weight)
|
|
61
|
+
VALUES (?, ?, ?, ?, ?)
|
|
62
|
+
`).run(randomUUID(), watchlistId, userId, categoryId, item.weight);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
function upsertStockClassificationCache(db, stock, classification) {
|
|
67
|
+
const cacheCode = watchlistLogic._normalizeStockCodeForCache(stock.stockCode, stock.exchange);
|
|
68
|
+
const legacyCode = stock.stockCode.trim().toUpperCase().replace(/\.(SH|SS|SZ|HK|US)$/i, "");
|
|
69
|
+
db.prepare(`
|
|
70
|
+
INSERT OR REPLACE INTO global_stock_metadata (stockCode, exchange, stockName, industryJson, themeJson)
|
|
71
|
+
VALUES (?, ?, ?, ?, ?)
|
|
72
|
+
`).run(cacheCode, stock.exchange, stock.stockName, JSON.stringify(classification.industry), JSON.stringify(classification.theme || []));
|
|
73
|
+
if (legacyCode && legacyCode !== cacheCode) {
|
|
74
|
+
db.prepare(`
|
|
75
|
+
DELETE FROM global_stock_metadata WHERE stockCode = ? AND exchange = ?
|
|
76
|
+
`).run(legacyCode, stock.exchange);
|
|
77
|
+
}
|
|
78
|
+
logger.info({
|
|
79
|
+
stockCode: stock.stockCode,
|
|
80
|
+
cacheCode,
|
|
81
|
+
exchange: stock.exchange,
|
|
82
|
+
industry: classification.industry.name,
|
|
83
|
+
themeCount: classification.theme?.length || 0
|
|
84
|
+
}, "[Watchlist] classification cache upserted");
|
|
85
|
+
}
|
|
86
|
+
export const watchlistTools = {
|
|
87
|
+
add_to_watchlist: {
|
|
88
|
+
name: "add_to_watchlist",
|
|
89
|
+
description: "添加股票到自选列表",
|
|
90
|
+
parameters: AddToWatchlistParamsSchema,
|
|
91
|
+
registerTool: false,
|
|
92
|
+
execute: async (args, ctx) => {
|
|
93
|
+
return enqueueWatchlistMutation(async () => {
|
|
94
|
+
const uId = String(ctx.userId);
|
|
95
|
+
if (!ctx.runtime) {
|
|
96
|
+
return JSON.stringify({ success: false, error: "无法分析行业/主题关系:runtime 不可用" });
|
|
97
|
+
}
|
|
98
|
+
const db = getDB();
|
|
99
|
+
const stock = normalizeWatchlistStock(args);
|
|
100
|
+
const existingBeforeClassify = db.prepare("SELECT id, isDeleted FROM watchlist WHERE userId = ? AND stockCode = ? AND exchange = ?")
|
|
101
|
+
.get(uId, stock.stockCode, stock.exchange);
|
|
102
|
+
if (existingBeforeClassify?.isDeleted === 0) {
|
|
103
|
+
return JSON.stringify({ success: true, skipped: true, reason: "duplicate", id: existingBeforeClassify.id });
|
|
104
|
+
}
|
|
105
|
+
let classification;
|
|
106
|
+
try {
|
|
107
|
+
classification = await watchlistLogic.getStockClassification(ctx.runtime, stock.stockName, stock.stockCode, stock.exchange, uId);
|
|
108
|
+
}
|
|
109
|
+
catch (e) {
|
|
110
|
+
return JSON.stringify({ success: false, error: e.message });
|
|
111
|
+
}
|
|
112
|
+
if (!classification) {
|
|
113
|
+
return JSON.stringify({ success: false, error: "行业/主题关系分析失败" });
|
|
114
|
+
}
|
|
115
|
+
if (db.inTransaction)
|
|
116
|
+
db.exec("ROLLBACK");
|
|
117
|
+
db.exec("BEGIN TRANSACTION");
|
|
118
|
+
try {
|
|
119
|
+
const sortRow = db.prepare("SELECT MAX(sortOrder) as max FROM watchlist WHERE userId=? AND isDeleted=0").get(uId);
|
|
120
|
+
const nextOrder = (sortRow?.max ?? 0) + 1024;
|
|
121
|
+
let watchlistId;
|
|
122
|
+
const existingItem = db.prepare("SELECT id, isDeleted FROM watchlist WHERE userId = ? AND stockCode = ? AND exchange = ?").get(uId, stock.stockCode, stock.exchange);
|
|
123
|
+
if (existingItem) {
|
|
124
|
+
watchlistId = existingItem.id;
|
|
125
|
+
if (existingItem.isDeleted === 1) {
|
|
126
|
+
db.prepare(`
|
|
127
|
+
UPDATE watchlist SET isDeleted = 0, stockName = ?, sortOrder = ?, updatedAt = STRFTIME('%Y-%m-%dT%H:%M:%fZ', 'NOW') WHERE id = ?
|
|
128
|
+
`).run(stock.stockName, nextOrder, watchlistId);
|
|
129
|
+
}
|
|
130
|
+
else {
|
|
131
|
+
db.exec("ROLLBACK");
|
|
132
|
+
return JSON.stringify({ success: true, skipped: true, reason: "duplicate", id: watchlistId });
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
else {
|
|
136
|
+
watchlistId = randomUUID();
|
|
137
|
+
db.prepare(`
|
|
138
|
+
INSERT INTO watchlist (id, userId, stockCode, stockName, exchange, market, sortOrder)
|
|
139
|
+
VALUES (?, ?, ?, ?, ?, ?, ?)
|
|
140
|
+
`).run(watchlistId, uId, stock.stockCode, stock.stockName, stock.exchange, stock.market, nextOrder);
|
|
141
|
+
}
|
|
142
|
+
upsertStockClassificationCache(db, stock, classification);
|
|
143
|
+
updateWatchlistTags(db, watchlistId, uId, classification.industry, classification.theme);
|
|
144
|
+
db.exec("COMMIT");
|
|
145
|
+
return JSON.stringify({ success: true, id: watchlistId });
|
|
146
|
+
}
|
|
147
|
+
catch (e) {
|
|
148
|
+
if (db.inTransaction)
|
|
149
|
+
db.exec("ROLLBACK");
|
|
150
|
+
return JSON.stringify({ success: false, error: e.message });
|
|
151
|
+
}
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
},
|
|
155
|
+
batch_add_to_watchlist: {
|
|
156
|
+
name: "batch_add_to_watchlist",
|
|
157
|
+
description: "批量添加股票到自选列表。添加多只股票时必须使用这个工具,不要循环调用 add_to_watchlist。",
|
|
158
|
+
parameters: z.object({ stocks: z.array(AddToWatchlistParamsSchema) }),
|
|
159
|
+
execute: async (args, ctx) => {
|
|
160
|
+
return enqueueWatchlistMutation(async () => {
|
|
161
|
+
if (!Array.isArray(args.stocks) || args.stocks.length === 0) {
|
|
162
|
+
return JSON.stringify({ success: false, error: "批量添加失败:stocks 不能为空" });
|
|
163
|
+
}
|
|
164
|
+
if (!ctx.runtime) {
|
|
165
|
+
return JSON.stringify({ success: false, error: "无法分析行业/主题关系:runtime 不可用" });
|
|
166
|
+
}
|
|
167
|
+
const db = getDB();
|
|
168
|
+
const uId = String(ctx.userId);
|
|
169
|
+
const uniqueStocks = [];
|
|
170
|
+
const inputSeen = new Set();
|
|
171
|
+
const skipped = [];
|
|
172
|
+
for (const rawStock of args.stocks) {
|
|
173
|
+
const stock = normalizeWatchlistStock(rawStock);
|
|
174
|
+
const key = watchlistStockKey(stock);
|
|
175
|
+
if (inputSeen.has(key)) {
|
|
176
|
+
skipped.push({ stockCode: stock.stockCode, exchange: stock.exchange, reason: "input_duplicate" });
|
|
177
|
+
continue;
|
|
178
|
+
}
|
|
179
|
+
inputSeen.add(key);
|
|
180
|
+
uniqueStocks.push(stock);
|
|
181
|
+
}
|
|
182
|
+
const stocksToAdd = [];
|
|
183
|
+
for (const stock of uniqueStocks) {
|
|
184
|
+
const existing = db.prepare("SELECT id, isDeleted FROM watchlist WHERE userId = ? AND stockCode = ? AND exchange = ?")
|
|
185
|
+
.get(uId, stock.stockCode, stock.exchange);
|
|
186
|
+
if (existing?.isDeleted === 0) {
|
|
187
|
+
skipped.push({ stockCode: stock.stockCode, exchange: stock.exchange, reason: "duplicate", id: existing.id });
|
|
188
|
+
}
|
|
189
|
+
else {
|
|
190
|
+
stocksToAdd.push(stock);
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
logger.info({
|
|
194
|
+
count: args.stocks?.length ?? 0,
|
|
195
|
+
addCount: stocksToAdd.length,
|
|
196
|
+
skippedCount: skipped.length,
|
|
197
|
+
codes: args.stocks?.map(stock => stock.stockCode)
|
|
198
|
+
}, "[Watchlist] batch_add_to_watchlist received");
|
|
199
|
+
if (stocksToAdd.length === 0) {
|
|
200
|
+
return JSON.stringify({ success: true, ids: [], skipped });
|
|
201
|
+
}
|
|
202
|
+
let batchResults;
|
|
203
|
+
try {
|
|
204
|
+
batchResults = await watchlistLogic.classifyStocksTogether(ctx.runtime, stocksToAdd, uId);
|
|
205
|
+
}
|
|
206
|
+
catch (e) {
|
|
207
|
+
logger.warn({
|
|
208
|
+
count: stocksToAdd.length,
|
|
209
|
+
codes: stocksToAdd.map(stock => stock.stockCode),
|
|
210
|
+
error: e.message || String(e)
|
|
211
|
+
}, "[Watchlist] batch_add_to_watchlist classification failed");
|
|
212
|
+
return JSON.stringify({
|
|
213
|
+
success: false,
|
|
214
|
+
failedStage: "classification",
|
|
215
|
+
error: e.message || "批量添加失败:行业/主题关系分析失败"
|
|
216
|
+
});
|
|
217
|
+
}
|
|
218
|
+
if (db.inTransaction)
|
|
219
|
+
db.exec("ROLLBACK");
|
|
220
|
+
db.exec("BEGIN TRANSACTION");
|
|
221
|
+
try {
|
|
222
|
+
const results = [];
|
|
223
|
+
const writtenItems = [];
|
|
224
|
+
const sortRow = db.prepare("SELECT MAX(sortOrder) as max FROM watchlist WHERE userId=? AND isDeleted=0").get(uId);
|
|
225
|
+
let currentMaxOrder = sortRow?.max ?? 0;
|
|
226
|
+
stocksToAdd.forEach((stock, i) => {
|
|
227
|
+
const nextOrder = currentMaxOrder + 1024;
|
|
228
|
+
currentMaxOrder = nextOrder;
|
|
229
|
+
const classification = batchResults[i];
|
|
230
|
+
if (!classification) {
|
|
231
|
+
throw new Error(`行业/主题关系分析失败: ${stock.stockName}`);
|
|
232
|
+
}
|
|
233
|
+
let watchlistId;
|
|
234
|
+
const existingItem = db.prepare("SELECT id, isDeleted FROM watchlist WHERE userId = ? AND stockCode = ? AND exchange = ?").get(uId, stock.stockCode, stock.exchange);
|
|
235
|
+
if (existingItem) {
|
|
236
|
+
watchlistId = existingItem.id;
|
|
237
|
+
if (existingItem.isDeleted === 1) {
|
|
238
|
+
db.prepare(`
|
|
239
|
+
UPDATE watchlist SET isDeleted = 0, stockName = ?, sortOrder = ?, updatedAt = STRFTIME('%Y-%m-%dT%H:%M:%fZ', 'NOW') WHERE id = ?
|
|
240
|
+
`).run(stock.stockName, nextOrder, watchlistId);
|
|
241
|
+
}
|
|
242
|
+
else {
|
|
243
|
+
skipped.push({ stockCode: stock.stockCode, exchange: stock.exchange, reason: "duplicate", id: watchlistId });
|
|
244
|
+
return;
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
else {
|
|
248
|
+
watchlistId = randomUUID();
|
|
249
|
+
db.prepare(`
|
|
250
|
+
INSERT INTO watchlist (id, userId, stockCode, stockName, exchange, market, sortOrder)
|
|
251
|
+
VALUES (?, ?, ?, ?, ?, ?, ?)
|
|
252
|
+
`).run(watchlistId, uId, stock.stockCode, stock.stockName, stock.exchange, stock.market, nextOrder);
|
|
253
|
+
}
|
|
254
|
+
results.push(watchlistId);
|
|
255
|
+
writtenItems.push({ id: watchlistId, stock, classification });
|
|
256
|
+
});
|
|
257
|
+
if (writtenItems.length > 0) {
|
|
258
|
+
writtenItems.forEach(({ id, stock, classification }) => {
|
|
259
|
+
upsertStockClassificationCache(db, stock, classification);
|
|
260
|
+
updateWatchlistTags(db, id, uId, classification.industry, classification.theme);
|
|
261
|
+
});
|
|
262
|
+
}
|
|
263
|
+
if (results.length !== stocksToAdd.length) {
|
|
264
|
+
logger.info({
|
|
265
|
+
input: args.stocks.length,
|
|
266
|
+
addRequested: stocksToAdd.length,
|
|
267
|
+
written: results.length,
|
|
268
|
+
skipped: skipped.length
|
|
269
|
+
}, "[Watchlist] batch_add_to_watchlist skipped duplicates");
|
|
270
|
+
}
|
|
271
|
+
db.exec("COMMIT");
|
|
272
|
+
return JSON.stringify({ success: true, ids: results, skipped });
|
|
273
|
+
}
|
|
274
|
+
catch (e) {
|
|
275
|
+
if (db.inTransaction)
|
|
276
|
+
db.exec("ROLLBACK");
|
|
277
|
+
return JSON.stringify({ success: false, error: e.message });
|
|
278
|
+
}
|
|
279
|
+
});
|
|
280
|
+
}
|
|
281
|
+
},
|
|
282
|
+
get_watchlist: {
|
|
283
|
+
name: "get_watchlist",
|
|
284
|
+
description: "获取自选股列表",
|
|
285
|
+
parameters: GetWatchlistParamsSchema,
|
|
286
|
+
execute: async (args, ctx) => {
|
|
287
|
+
try {
|
|
288
|
+
const db = getDB();
|
|
289
|
+
const uId = String(ctx.userId);
|
|
290
|
+
let query;
|
|
291
|
+
let params = [uId];
|
|
292
|
+
if (args.categoryId && args.categoryType) {
|
|
293
|
+
const table = args.categoryType === "industry" ? "watchlist_industry_items" : "watchlist_theme_items";
|
|
294
|
+
query = `
|
|
295
|
+
SELECT w.*, ci.weight as relWeight
|
|
296
|
+
FROM watchlist w
|
|
297
|
+
JOIN ${table} ci ON w.id = ci.watchlistId
|
|
298
|
+
WHERE w.userId = ? AND w.isDeleted = 0 AND ci.categoryId = ?
|
|
299
|
+
ORDER BY ci.weight DESC, w.sortOrder ASC
|
|
300
|
+
`;
|
|
301
|
+
params.push(args.categoryId);
|
|
302
|
+
}
|
|
303
|
+
else {
|
|
304
|
+
query = `
|
|
305
|
+
SELECT w.*, (
|
|
306
|
+
SELECT MAX(total.weight) FROM (
|
|
307
|
+
SELECT weight FROM watchlist_industry_items WHERE watchlistId = w.id
|
|
308
|
+
UNION ALL
|
|
309
|
+
SELECT weight FROM watchlist_theme_items WHERE watchlistId = w.id
|
|
310
|
+
UNION ALL
|
|
311
|
+
SELECT 0 as weight
|
|
312
|
+
) total
|
|
313
|
+
) as globalWeight
|
|
314
|
+
FROM watchlist w
|
|
315
|
+
WHERE w.userId = ? AND w.isDeleted = 0
|
|
316
|
+
ORDER BY globalWeight DESC, w.sortOrder ASC
|
|
317
|
+
`;
|
|
318
|
+
}
|
|
319
|
+
const stocks = db.prepare(query).all(...params);
|
|
320
|
+
const fullList = stocks.map(stock => {
|
|
321
|
+
const industries = db.prepare(`
|
|
322
|
+
SELECT c.name FROM watchlist_categories c
|
|
323
|
+
JOIN watchlist_industry_items i ON c.id = i.categoryId
|
|
324
|
+
WHERE i.watchlistId = ? ORDER BY i.weight DESC
|
|
325
|
+
`).all(stock.id);
|
|
326
|
+
const themes = db.prepare(`
|
|
327
|
+
SELECT c.name FROM watchlist_categories c
|
|
328
|
+
JOIN watchlist_theme_items t ON c.id = t.categoryId
|
|
329
|
+
WHERE t.watchlistId = ? ORDER BY t.weight DESC
|
|
330
|
+
`).all(stock.id);
|
|
331
|
+
return {
|
|
332
|
+
...stock,
|
|
333
|
+
industries: industries.map(i => i.name),
|
|
334
|
+
themes: themes.map(t => t.name)
|
|
335
|
+
};
|
|
336
|
+
});
|
|
337
|
+
return JSON.stringify({ success: true, data: fullList });
|
|
338
|
+
}
|
|
339
|
+
catch (e) {
|
|
340
|
+
return JSON.stringify({ success: false, error: e.message });
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
},
|
|
344
|
+
get_thematic_dashboard: {
|
|
345
|
+
name: "get_thematic_dashboard",
|
|
346
|
+
description: "获取聚合后的主题/行业看板数据",
|
|
347
|
+
parameters: z.object({}),
|
|
348
|
+
execute: async (_args, ctx) => {
|
|
349
|
+
try {
|
|
350
|
+
const db = getDB();
|
|
351
|
+
const uId = String(ctx.userId);
|
|
352
|
+
const industryData = db.prepare(`
|
|
353
|
+
SELECT c.name as category_name, i.weight, w.stockCode
|
|
354
|
+
FROM watchlist_categories c
|
|
355
|
+
JOIN watchlist_industry_items i ON c.id = i.categoryId
|
|
356
|
+
JOIN watchlist w ON i.watchlistId = w.id
|
|
357
|
+
WHERE i.userId = ? AND w.isDeleted = 0
|
|
358
|
+
`).all(uId);
|
|
359
|
+
const themeData = db.prepare(`
|
|
360
|
+
SELECT c.name as category_name, t.weight, w.stockCode
|
|
361
|
+
FROM watchlist_categories c
|
|
362
|
+
JOIN watchlist_theme_items t ON c.id = t.categoryId
|
|
363
|
+
JOIN watchlist w ON t.watchlistId = w.id
|
|
364
|
+
WHERE t.userId = ? AND w.isDeleted = 0
|
|
365
|
+
`).all(uId);
|
|
366
|
+
const combined = [...industryData, ...themeData];
|
|
367
|
+
const aggMap = new Map();
|
|
368
|
+
combined.forEach(item => {
|
|
369
|
+
const name = item.category_name;
|
|
370
|
+
const existing = aggMap.get(name) || { category_name: name, weight_total: 0, stocks: [] };
|
|
371
|
+
existing.weight_total += (item.weight || 0);
|
|
372
|
+
if (!existing.stocks.includes(item.stockCode)) {
|
|
373
|
+
existing.stocks.push(item.stockCode);
|
|
374
|
+
}
|
|
375
|
+
aggMap.set(name, existing);
|
|
376
|
+
});
|
|
377
|
+
const result = Array.from(aggMap.values()).sort((a, b) => b.weight_total - a.weight_total);
|
|
378
|
+
return JSON.stringify({ success: true, data: result });
|
|
379
|
+
}
|
|
380
|
+
catch (e) {
|
|
381
|
+
return JSON.stringify({ success: false, error: e.message });
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
},
|
|
385
|
+
get_watchlist_tabs: {
|
|
386
|
+
name: "get_watchlist_tabs",
|
|
387
|
+
description: "获取分类页签",
|
|
388
|
+
parameters: z.object({}),
|
|
389
|
+
execute: async (_args, ctx) => {
|
|
390
|
+
try {
|
|
391
|
+
const db = getDB();
|
|
392
|
+
const uId = String(ctx.userId);
|
|
393
|
+
const industries = db.prepare(`
|
|
394
|
+
SELECT DISTINCT c.id, c.name, c.type, c.sortOrder
|
|
395
|
+
FROM watchlist_categories c
|
|
396
|
+
JOIN watchlist_industry_items i ON c.id = i.categoryId
|
|
397
|
+
WHERE i.userId = ?
|
|
398
|
+
ORDER BY c.sortOrder ASC, c.name ASC
|
|
399
|
+
`).all(uId);
|
|
400
|
+
const themes = db.prepare(`
|
|
401
|
+
SELECT DISTINCT c.id, c.name, c.type, c.sortOrder
|
|
402
|
+
FROM watchlist_categories c
|
|
403
|
+
JOIN watchlist_theme_items t ON c.id = t.categoryId
|
|
404
|
+
WHERE t.userId = ?
|
|
405
|
+
ORDER BY c.sortOrder ASC, c.name ASC
|
|
406
|
+
`).all(uId);
|
|
407
|
+
const tabs = [
|
|
408
|
+
{ id: "all", name: "全部", type: "all" },
|
|
409
|
+
...industries.map(i => ({ id: i.id, name: i.name, type: "industry" })),
|
|
410
|
+
...themes.map(t => ({ id: t.id, name: t.name, type: "theme" }))
|
|
411
|
+
];
|
|
412
|
+
return JSON.stringify({ success: true, data: tabs });
|
|
413
|
+
}
|
|
414
|
+
catch (e) {
|
|
415
|
+
return JSON.stringify({ success: false, error: e.message });
|
|
416
|
+
}
|
|
417
|
+
}
|
|
418
|
+
},
|
|
419
|
+
smart_reorder_watchlist: {
|
|
420
|
+
name: "smart_reorder_watchlist",
|
|
421
|
+
description: "触发 AI 智能排序",
|
|
422
|
+
parameters: z.object({}),
|
|
423
|
+
execute: async (_args, ctx) => {
|
|
424
|
+
if (!ctx.runtime)
|
|
425
|
+
return JSON.stringify({ success: false, error: "Runtime not available" });
|
|
426
|
+
const db = getDB();
|
|
427
|
+
const uId = String(ctx.userId);
|
|
428
|
+
try {
|
|
429
|
+
const stocks = db.prepare("SELECT stockCode as code, stockName as name FROM watchlist WHERE userId = ? AND isDeleted = 0").all(uId);
|
|
430
|
+
if (stocks.length === 0)
|
|
431
|
+
return JSON.stringify({ success: true, message: "没有可排序的股票" });
|
|
432
|
+
const sortedResults = await watchlistLogic.applySmartSort(ctx.runtime, `sort-${uId}`, stocks);
|
|
433
|
+
if (sortedResults.length > 0) {
|
|
434
|
+
db.exec("BEGIN TRANSACTION");
|
|
435
|
+
const stmt = db.prepare(`
|
|
436
|
+
UPDATE watchlist SET sortOrder = ?, updatedAt = STRFTIME('%Y-%m-%dT%H:%M:%fZ', 'NOW')
|
|
437
|
+
WHERE userId = ? AND stockCode = ? AND isDeleted = 0
|
|
438
|
+
`);
|
|
439
|
+
sortedResults.forEach((item, i) => {
|
|
440
|
+
const currentOrder = i * 10;
|
|
441
|
+
stmt.run(currentOrder, uId, item.code);
|
|
442
|
+
});
|
|
443
|
+
db.exec("COMMIT");
|
|
444
|
+
return JSON.stringify({ success: true, message: "智能排序已完成" });
|
|
445
|
+
}
|
|
446
|
+
return JSON.stringify({ success: false, error: "AI 未能返回有效的排序结果" });
|
|
447
|
+
}
|
|
448
|
+
catch (e) {
|
|
449
|
+
if (db.inTransaction)
|
|
450
|
+
db.exec("ROLLBACK");
|
|
451
|
+
return JSON.stringify({ success: false, error: e.message });
|
|
452
|
+
}
|
|
453
|
+
}
|
|
454
|
+
},
|
|
455
|
+
sync_watchlist_categories: {
|
|
456
|
+
name: "sync_watchlist_categories",
|
|
457
|
+
description: "同步分类字典",
|
|
458
|
+
parameters: SyncCategoriesParamsSchema,
|
|
459
|
+
execute: async (args, ctx) => {
|
|
460
|
+
const db = getDB();
|
|
461
|
+
const uId = String(ctx.userId);
|
|
462
|
+
db.exec("BEGIN TRANSACTION");
|
|
463
|
+
try {
|
|
464
|
+
if (args.industries) {
|
|
465
|
+
for (const name of args.industries) {
|
|
466
|
+
db.prepare(`
|
|
467
|
+
INSERT INTO watchlist_categories (id, remoteId, userId, name, type, weight, sortOrder)
|
|
468
|
+
VALUES (?, ?, ?, ?, 'industry', 0, 0)
|
|
469
|
+
ON CONFLICT(userId, remoteId) DO UPDATE SET name = excluded.name, updatedAt = STRFTIME('%Y-%m-%dT%H:%M:%fZ', 'NOW')
|
|
470
|
+
ON CONFLICT(userId, name, type) DO UPDATE SET remoteId = excluded.remoteId, updatedAt = STRFTIME('%Y-%m-%dT%H:%M:%fZ', 'NOW')
|
|
471
|
+
`).run(randomUUID(), name, uId, name);
|
|
472
|
+
}
|
|
473
|
+
}
|
|
474
|
+
if (args.themes) {
|
|
475
|
+
for (const name of args.themes) {
|
|
476
|
+
db.prepare(`
|
|
477
|
+
INSERT INTO watchlist_categories (id, remoteId, userId, name, type, weight, sortOrder)
|
|
478
|
+
VALUES (?, ?, ?, ?, 'theme', 0, 0)
|
|
479
|
+
ON CONFLICT(userId, remoteId) DO UPDATE SET name = excluded.name, updatedAt = STRFTIME('%Y-%m-%dT%H:%M:%fZ', 'NOW')
|
|
480
|
+
ON CONFLICT(userId, name, type) DO UPDATE SET remoteId = excluded.remoteId, updatedAt = STRFTIME('%Y-%m-%dT%H:%M:%fZ', 'NOW')
|
|
481
|
+
`).run(randomUUID(), name, uId, name);
|
|
482
|
+
}
|
|
483
|
+
}
|
|
484
|
+
db.exec("COMMIT");
|
|
485
|
+
return JSON.stringify({ success: true });
|
|
486
|
+
}
|
|
487
|
+
catch (e) {
|
|
488
|
+
db.exec("ROLLBACK");
|
|
489
|
+
return JSON.stringify({ success: false, error: e.message });
|
|
490
|
+
}
|
|
491
|
+
}
|
|
492
|
+
},
|
|
493
|
+
batch_update_sort_orders: {
|
|
494
|
+
name: "batch_update_sort_orders",
|
|
495
|
+
description: "批量更新排序",
|
|
496
|
+
parameters: BatchUpdateSortOrdersParamsSchema,
|
|
497
|
+
execute: async (args, ctx) => {
|
|
498
|
+
const db = getDB();
|
|
499
|
+
const uId = String(ctx.userId);
|
|
500
|
+
db.exec("BEGIN TRANSACTION");
|
|
501
|
+
try {
|
|
502
|
+
const stmt = db.prepare(`UPDATE watchlist SET sortOrder = ?, updatedAt = STRFTIME('%Y-%m-%dT%H:%M:%fZ', 'NOW') WHERE id = ? AND userId = ? AND isDeleted = 0`);
|
|
503
|
+
args.orderedIds.forEach((id, i) => {
|
|
504
|
+
const weight = i * 1024;
|
|
505
|
+
stmt.run(weight, id, uId);
|
|
506
|
+
});
|
|
507
|
+
db.exec("COMMIT");
|
|
508
|
+
return JSON.stringify({ success: true });
|
|
509
|
+
}
|
|
510
|
+
catch (e) {
|
|
511
|
+
db.exec("ROLLBACK");
|
|
512
|
+
return JSON.stringify({ success: false, error: e.message });
|
|
513
|
+
}
|
|
514
|
+
}
|
|
515
|
+
},
|
|
516
|
+
reset_watchlist_classification: {
|
|
517
|
+
name: "reset_watchlist_classification",
|
|
518
|
+
description: "清除并重新进行智能分类",
|
|
519
|
+
parameters: z.object({}),
|
|
520
|
+
execute: async (_args, ctx) => {
|
|
521
|
+
if (!ctx.runtime)
|
|
522
|
+
return JSON.stringify({ success: false, error: "Runtime not available" });
|
|
523
|
+
const db = getDB();
|
|
524
|
+
const uId = String(ctx.userId);
|
|
525
|
+
db.exec("BEGIN TRANSACTION");
|
|
526
|
+
try {
|
|
527
|
+
db.prepare("DELETE FROM watchlist_industry_items WHERE userId = ?").run(uId);
|
|
528
|
+
db.prepare("DELETE FROM watchlist_theme_items WHERE userId = ?").run(uId);
|
|
529
|
+
const stocks = db.prepare("SELECT stockName, stockCode, exchange, market FROM watchlist WHERE userId = ? AND isDeleted = 0").all(uId);
|
|
530
|
+
if (stocks.length > 0) {
|
|
531
|
+
watchlistLogic.getBatchStockClassification(ctx.runtime, stocks, uId, { forceRefresh: true })
|
|
532
|
+
.then(batchResults => {
|
|
533
|
+
const db2 = getDB();
|
|
534
|
+
const userStocks = db2.prepare("SELECT id, stockCode, exchange FROM watchlist WHERE userId = ? AND isDeleted = 0").all(uId);
|
|
535
|
+
batchResults.forEach((res, i) => {
|
|
536
|
+
if (res) {
|
|
537
|
+
const s = stocks[i];
|
|
538
|
+
const match = userStocks.find(us => us.stockCode === s.stockCode && us.exchange === s.exchange);
|
|
539
|
+
if (match) {
|
|
540
|
+
upsertStockClassificationCache(db2, {
|
|
541
|
+
stockName: s.stockName,
|
|
542
|
+
stockCode: s.stockCode,
|
|
543
|
+
exchange: s.exchange,
|
|
544
|
+
market: s.market
|
|
545
|
+
}, res);
|
|
546
|
+
const cats = [
|
|
547
|
+
...(res.industry ? [{ name: res.industry.name, type: 'industry', weight: res.industry.weight }] : []),
|
|
548
|
+
...res.theme.map((t) => ({ name: t.name, type: 'theme', weight: t.weight }))
|
|
549
|
+
];
|
|
550
|
+
cats.forEach(c => {
|
|
551
|
+
const catId = watchlistLogic._ensureCategory(db2, c.name, c.type, uId);
|
|
552
|
+
if (catId) {
|
|
553
|
+
const table = c.type === 'industry' ? 'watchlist_industry_items' : 'watchlist_theme_items';
|
|
554
|
+
db2.prepare(`INSERT OR IGNORE INTO ${table} (id, watchlistId, userId, categoryId, weight) VALUES (?, ?, ?, ?, ?)`).run(randomUUID(), match.id, uId, catId, c.weight);
|
|
555
|
+
}
|
|
556
|
+
});
|
|
557
|
+
}
|
|
558
|
+
}
|
|
559
|
+
});
|
|
560
|
+
}).catch(err => console.error("[Watchlist] 重置分类失败:", err));
|
|
561
|
+
}
|
|
562
|
+
db.exec("COMMIT");
|
|
563
|
+
return JSON.stringify({ success: true, message: "重置分类请求已提交" });
|
|
564
|
+
}
|
|
565
|
+
catch (e) {
|
|
566
|
+
db.exec("ROLLBACK");
|
|
567
|
+
return JSON.stringify({ success: false, error: e.message });
|
|
568
|
+
}
|
|
569
|
+
}
|
|
570
|
+
}
|
|
571
|
+
};
|
|
572
|
+
//# sourceMappingURL=tools.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tools.js","sourceRoot":"","sources":["../../../../src/features/watchlist/tools.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { PluginRuntime } from "openclaw/plugin-sdk/channel-core";
|
|
2
|
+
export declare function setHedgehogRuntime(next: PluginRuntime): void;
|
|
3
|
+
export declare function getDbPath(): string;
|
|
4
|
+
export declare function getBackupDir(): string;
|
|
5
|
+
export declare function getHedgehogRuntime(): PluginRuntime;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import path from "path";
|
|
2
|
+
import * as os from "node:os";
|
|
3
|
+
import { logger } from "./core/logger.js";
|
|
4
|
+
let runtime = null;
|
|
5
|
+
let dbPath = "";
|
|
6
|
+
let backupDir = "";
|
|
7
|
+
export function setHedgehogRuntime(next) {
|
|
8
|
+
runtime = next;
|
|
9
|
+
try {
|
|
10
|
+
// 从配置里读取 hedgehog-finance 的 workspace
|
|
11
|
+
const cfg = next.config.loadConfig();
|
|
12
|
+
const agentList = (cfg.agents?.list || []);
|
|
13
|
+
const hedgehogAgent = agentList.find((a) => a.id === "hedgehog-finance");
|
|
14
|
+
const workspaceDir = hedgehogAgent?.workspace ||
|
|
15
|
+
cfg.agents?.defaults?.workspace ||
|
|
16
|
+
path.join(os.homedir(), ".openclaw", "hedgehog-workspace");
|
|
17
|
+
dbPath = path.join(workspaceDir, "data", "business.db");
|
|
18
|
+
backupDir = path.join(workspaceDir, "backups");
|
|
19
|
+
logger.info({ workspaceDir, dbPath }, "resolved workspace");
|
|
20
|
+
}
|
|
21
|
+
catch (e) {
|
|
22
|
+
logger.error({ err: e }, "Failed to resolve workspace");
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
export function getDbPath() {
|
|
26
|
+
if (!dbPath)
|
|
27
|
+
throw new Error("[hedgehog-app] dbPath not initialized");
|
|
28
|
+
return dbPath;
|
|
29
|
+
}
|
|
30
|
+
export function getBackupDir() {
|
|
31
|
+
if (!backupDir)
|
|
32
|
+
throw new Error("[hedgehog-app] backupDir not initialized");
|
|
33
|
+
return backupDir;
|
|
34
|
+
}
|
|
35
|
+
export function getHedgehogRuntime() {
|
|
36
|
+
if (!runtime)
|
|
37
|
+
throw new Error("[hedgehog-app] runtime not initialized");
|
|
38
|
+
return runtime;
|
|
39
|
+
}
|
|
40
|
+
//# sourceMappingURL=runtime.js.map
|