@hedgehog-finance/hedgehog-plugin 1.0.21 → 1.0.22
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 +4 -3
- package/dist/index.js +49 -6
- package/dist/index.js.map +1 -1
- package/dist/setup-api.d.ts +2 -0
- package/dist/setup-api.js +8 -0
- package/dist/setup-api.js.map +1 -0
- package/dist/src/channel.js +25 -23
- package/dist/src/channel.js.map +1 -1
- package/dist/src/core/database.js +449 -39
- package/dist/src/core/database.js.map +1 -1
- package/dist/src/dailyMorningBriefingCron.d.ts +46 -0
- package/dist/src/dailyMorningBriefingCron.js +82 -0
- package/dist/src/dailyMorningBriefingCron.js.map +1 -0
- package/dist/src/features/chartOutput.d.ts +2 -0
- package/dist/src/features/chartOutput.js +35 -0
- package/dist/src/features/chartOutput.js.map +1 -0
- package/dist/src/features/dailyMorningBriefing/schema.d.ts +56 -0
- package/dist/src/features/dailyMorningBriefing/schema.js +22 -0
- package/dist/src/features/dailyMorningBriefing/schema.js.map +1 -0
- package/dist/src/features/dailyMorningBriefing/tools.d.ts +12 -0
- package/dist/src/features/dailyMorningBriefing/tools.js +204 -0
- package/dist/src/features/dailyMorningBriefing/tools.js.map +1 -0
- package/dist/src/features/deepReasoning/schema.d.ts +43 -0
- package/dist/src/features/deepReasoning/schema.js +17 -0
- package/dist/src/features/deepReasoning/schema.js.map +1 -0
- package/dist/src/features/deepReasoning/tools.d.ts +12 -0
- package/dist/src/features/deepReasoning/tools.js +163 -0
- package/dist/src/features/deepReasoning/tools.js.map +1 -0
- package/dist/src/features/index.d.ts +2 -1
- package/dist/src/features/index.js +9 -1
- package/dist/src/features/index.js.map +1 -1
- package/dist/src/features/informationVerification/schema.d.ts +43 -0
- package/dist/src/features/informationVerification/schema.js +17 -0
- package/dist/src/features/informationVerification/schema.js.map +1 -0
- package/dist/src/features/informationVerification/tools.d.ts +12 -0
- package/dist/src/features/informationVerification/tools.js +162 -0
- package/dist/src/features/informationVerification/tools.js.map +1 -0
- package/dist/src/features/notes/schema.d.ts +136 -39
- package/dist/src/features/notes/schema.js +13 -10
- package/dist/src/features/notes/schema.js.map +1 -1
- package/dist/src/features/notes/tools.d.ts +1 -0
- package/dist/src/features/notes/tools.js +47 -14
- package/dist/src/features/notes/tools.js.map +1 -1
- package/dist/src/features/pluginInfo/schema.d.ts +79 -0
- package/dist/src/features/pluginInfo/schema.js +14 -0
- package/dist/src/features/pluginInfo/schema.js.map +1 -0
- package/dist/src/features/pluginInfo/tools.d.ts +1 -0
- package/dist/src/features/pluginInfo/tools.js +157 -2
- package/dist/src/features/pluginInfo/tools.js.map +1 -1
- package/dist/src/features/profileLibrary/schema.d.ts +34 -6
- package/dist/src/features/profileLibrary/schema.js +1 -1
- package/dist/src/features/profileLibrary/schema.js.map +1 -1
- package/dist/src/features/stockAnalysis/schema.d.ts +224 -31
- package/dist/src/features/stockAnalysis/schema.js +76 -12
- package/dist/src/features/stockAnalysis/schema.js.map +1 -1
- package/dist/src/features/stockAnalysis/tools.d.ts +6 -4
- package/dist/src/features/stockAnalysis/tools.js +389 -44
- package/dist/src/features/stockAnalysis/tools.js.map +1 -1
- package/dist/src/features/stockBasic/schema.d.ts +149 -0
- package/dist/src/features/stockBasic/schema.js +26 -0
- package/dist/src/features/stockBasic/schema.js.map +1 -0
- package/dist/src/features/stockBasic/tools.d.ts +12 -0
- package/dist/src/features/stockBasic/tools.js +124 -0
- package/dist/src/features/stockBasic/tools.js.map +1 -0
- package/dist/src/features/watchlist/logic.d.ts +3 -3
- package/dist/src/features/watchlist/logic.js +47 -46
- package/dist/src/features/watchlist/logic.js.map +1 -1
- package/dist/src/features/watchlist/schema.d.ts +89 -54
- package/dist/src/features/watchlist/schema.js +7 -4
- package/dist/src/features/watchlist/schema.js.map +1 -1
- package/dist/src/features/watchlist/tools.d.ts +106 -59
- package/dist/src/features/watchlist/tools.js +182 -104
- package/dist/src/features/watchlist/tools.js.map +1 -1
- package/dist/src/openclawConfig.d.ts +6 -0
- package/dist/src/openclawConfig.js +74 -0
- package/dist/src/openclawConfig.js.map +1 -0
- package/dist/src/openclawConstants.d.ts +4 -0
- package/dist/src/openclawConstants.js +10 -0
- package/dist/src/openclawConstants.js.map +1 -0
- package/dist/src/runtime.js +20 -0
- package/dist/src/runtime.js.map +1 -1
- package/index.ts +52 -5
- package/openclaw.plugin.json +24 -0
- package/package.json +21 -6
- package/setup-api.ts +10 -0
- package/src/channel.ts +26 -25
- package/src/core/database.ts +447 -40
- package/src/dailyMorningBriefingCron.ts +129 -0
- package/src/features/chartOutput.ts +35 -0
- package/src/features/dailyMorningBriefing/schema.ts +38 -0
- package/src/features/dailyMorningBriefing/tools.ts +246 -0
- package/src/features/deepReasoning/schema.ts +22 -0
- package/src/features/deepReasoning/tools.ts +182 -0
- package/src/features/index.ts +11 -2
- package/src/features/informationVerification/schema.ts +22 -0
- package/src/features/informationVerification/tools.ts +181 -0
- package/src/features/notes/schema.ts +17 -12
- package/src/features/notes/tools.ts +54 -17
- package/src/features/pluginInfo/schema.ts +19 -0
- package/src/features/pluginInfo/tools.ts +173 -2
- package/src/features/profileLibrary/schema.ts +1 -1
- package/src/features/stockAnalysis/schema.ts +99 -17
- package/src/features/stockAnalysis/tools.ts +447 -49
- package/src/features/stockBasic/schema.ts +33 -0
- package/src/features/stockBasic/tools.ts +157 -0
- package/src/features/watchlist/logic.ts +56 -53
- package/src/features/watchlist/schema.ts +11 -6
- package/src/features/watchlist/tools.ts +191 -106
- package/src/openclawConfig.ts +101 -0
- package/src/openclawConstants.ts +11 -0
- package/src/runtime.ts +19 -0
package/src/core/database.ts
CHANGED
|
@@ -55,8 +55,8 @@ function startDailyBackupJob() {
|
|
|
55
55
|
scheduleNextBackup();
|
|
56
56
|
}
|
|
57
57
|
|
|
58
|
-
function normalizeMetadataStockCode(
|
|
59
|
-
const code = String(
|
|
58
|
+
function normalizeMetadataStockCode(stock_code: string, exchange: string): string {
|
|
59
|
+
const code = String(stock_code || "").trim().toUpperCase();
|
|
60
60
|
if (/\.(SH|SS|SZ|HK|US)$/i.test(code)) {
|
|
61
61
|
return code.replace(/\.SS$/i, ".SH");
|
|
62
62
|
}
|
|
@@ -72,35 +72,52 @@ function normalizeMetadataStockCode(stockCode: string, exchange: string): string
|
|
|
72
72
|
}
|
|
73
73
|
}
|
|
74
74
|
|
|
75
|
+
function runStockColumnNameMigrations(db: DatabaseSync) {
|
|
76
|
+
const legacyCodeColumn = "stock" + "Code";
|
|
77
|
+
const legacyNameColumn = "stock" + "Name";
|
|
78
|
+
const tables = ["watchlist", "global_stock_metadata", "stock_classification_cache", "stock_ai_analysis"];
|
|
79
|
+
|
|
80
|
+
for (const table of tables) {
|
|
81
|
+
const columns = db.prepare(`PRAGMA table_info(${table})`).all() as { name: string }[];
|
|
82
|
+
const columnNames = new Set(columns.map(column => column.name));
|
|
83
|
+
if (columnNames.has(legacyCodeColumn) && !columnNames.has("stock_code")) {
|
|
84
|
+
db.prepare(`ALTER TABLE ${table} RENAME COLUMN ${legacyCodeColumn} TO stock_code`).run();
|
|
85
|
+
}
|
|
86
|
+
if (columnNames.has(legacyNameColumn) && !columnNames.has("stock_name")) {
|
|
87
|
+
db.prepare(`ALTER TABLE ${table} RENAME COLUMN ${legacyNameColumn} TO stock_name`).run();
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
75
92
|
function runWatchlistDedupMigrations(db: DatabaseSync) {
|
|
76
93
|
db.exec("BEGIN TRANSACTION");
|
|
77
94
|
try {
|
|
78
95
|
const metadataRows = db.prepare(`
|
|
79
|
-
SELECT
|
|
80
|
-
`).all() as {
|
|
96
|
+
SELECT stock_code, exchange FROM stock_classification_cache
|
|
97
|
+
`).all() as { stock_code: string; exchange: string }[];
|
|
81
98
|
const metadataDeleteStmt = db.prepare(`
|
|
82
|
-
DELETE FROM
|
|
99
|
+
DELETE FROM stock_classification_cache WHERE stock_code = ? AND exchange = ?
|
|
83
100
|
`);
|
|
84
101
|
const metadataUpdateStmt = db.prepare(`
|
|
85
|
-
UPDATE
|
|
102
|
+
UPDATE stock_classification_cache SET stock_code = ? WHERE stock_code = ? AND exchange = ?
|
|
86
103
|
`);
|
|
87
104
|
const metadataExistsStmt = db.prepare(`
|
|
88
|
-
SELECT 1 FROM
|
|
105
|
+
SELECT 1 FROM stock_classification_cache WHERE stock_code = ? AND exchange = ?
|
|
89
106
|
`);
|
|
90
107
|
for (const row of metadataRows) {
|
|
91
|
-
const normalizedCode = normalizeMetadataStockCode(row.
|
|
92
|
-
if (!normalizedCode || normalizedCode === row.
|
|
108
|
+
const normalizedCode = normalizeMetadataStockCode(row.stock_code, row.exchange);
|
|
109
|
+
if (!normalizedCode || normalizedCode === row.stock_code) continue;
|
|
93
110
|
const existing = metadataExistsStmt.get(normalizedCode, row.exchange);
|
|
94
111
|
if (existing) {
|
|
95
|
-
metadataDeleteStmt.run(row.
|
|
112
|
+
metadataDeleteStmt.run(row.stock_code, row.exchange);
|
|
96
113
|
} else {
|
|
97
|
-
metadataUpdateStmt.run(normalizedCode, row.
|
|
114
|
+
metadataUpdateStmt.run(normalizedCode, row.stock_code, row.exchange);
|
|
98
115
|
}
|
|
99
116
|
}
|
|
100
117
|
|
|
101
118
|
const duplicateCategories = db.prepare(`
|
|
102
119
|
SELECT userId, name, type, MIN(id) AS keepId, GROUP_CONCAT(id) AS ids
|
|
103
|
-
FROM
|
|
120
|
+
FROM industry_theme_categories
|
|
104
121
|
GROUP BY userId, name, type
|
|
105
122
|
HAVING COUNT(*) > 1
|
|
106
123
|
`).all() as { userId: string; name: string; type: 'industry' | 'theme'; keepId: string; ids: string }[];
|
|
@@ -109,7 +126,7 @@ function runWatchlistDedupMigrations(db: DatabaseSync) {
|
|
|
109
126
|
const ids = dup.ids.split(",").filter(id => id && id !== dup.keepId);
|
|
110
127
|
for (const oldId of ids) {
|
|
111
128
|
db.prepare(`UPDATE ${table} SET categoryId = ? WHERE userId = ? AND categoryId = ?`).run(dup.keepId, dup.userId, oldId);
|
|
112
|
-
db.prepare("DELETE FROM
|
|
129
|
+
db.prepare("DELETE FROM industry_theme_categories WHERE id = ?").run(oldId);
|
|
113
130
|
}
|
|
114
131
|
}
|
|
115
132
|
|
|
@@ -132,8 +149,8 @@ function runWatchlistDedupMigrations(db: DatabaseSync) {
|
|
|
132
149
|
}
|
|
133
150
|
|
|
134
151
|
db.exec(`
|
|
135
|
-
CREATE UNIQUE INDEX IF NOT EXISTS
|
|
136
|
-
ON
|
|
152
|
+
CREATE UNIQUE INDEX IF NOT EXISTS idx_industry_theme_categories_user_name_type
|
|
153
|
+
ON industry_theme_categories(userId, name, type);
|
|
137
154
|
CREATE UNIQUE INDEX IF NOT EXISTS idx_watchlist_industry_items_watchlist_category
|
|
138
155
|
ON watchlist_industry_items(watchlistId, categoryId);
|
|
139
156
|
CREATE UNIQUE INDEX IF NOT EXISTS idx_watchlist_theme_items_watchlist_category
|
|
@@ -141,6 +158,98 @@ function runWatchlistDedupMigrations(db: DatabaseSync) {
|
|
|
141
158
|
`);
|
|
142
159
|
}
|
|
143
160
|
|
|
161
|
+
function runClassificationCacheMigrations(db: DatabaseSync) {
|
|
162
|
+
const oldColumns = db.prepare("PRAGMA table_info(global_stock_metadata)").all() as { name: string }[];
|
|
163
|
+
if (oldColumns.length === 0) return;
|
|
164
|
+
|
|
165
|
+
const oldColumnNames = new Set(oldColumns.map(column => column.name));
|
|
166
|
+
const industryColumn = oldColumnNames.has("industry_classification") ? "industry_classification" : "industryJson";
|
|
167
|
+
const themeColumn = oldColumnNames.has("theme_classification") ? "theme_classification" : oldColumnNames.has("theme") ? "theme" : "themeJson";
|
|
168
|
+
const updatedColumn = oldColumnNames.has("last_updated") ? "last_updated" : "lastUpdated";
|
|
169
|
+
if (!oldColumnNames.has(industryColumn) || !oldColumnNames.has(themeColumn)) return;
|
|
170
|
+
|
|
171
|
+
db.exec("BEGIN");
|
|
172
|
+
try {
|
|
173
|
+
db.exec(`
|
|
174
|
+
INSERT OR REPLACE INTO stock_classification_cache (
|
|
175
|
+
stock_code,
|
|
176
|
+
exchange,
|
|
177
|
+
stock_name,
|
|
178
|
+
industry_classification,
|
|
179
|
+
theme_classification,
|
|
180
|
+
last_updated
|
|
181
|
+
)
|
|
182
|
+
SELECT
|
|
183
|
+
stock_code,
|
|
184
|
+
exchange,
|
|
185
|
+
stock_name,
|
|
186
|
+
${industryColumn},
|
|
187
|
+
${themeColumn},
|
|
188
|
+
${updatedColumn}
|
|
189
|
+
FROM global_stock_metadata;
|
|
190
|
+
|
|
191
|
+
DROP TABLE global_stock_metadata;
|
|
192
|
+
`);
|
|
193
|
+
db.exec("COMMIT");
|
|
194
|
+
} catch (e) {
|
|
195
|
+
if (db.inTransaction) db.exec("ROLLBACK");
|
|
196
|
+
throw e;
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
function runClassificationCacheSchemaMigrations(db: DatabaseSync) {
|
|
201
|
+
const columns = db.prepare("PRAGMA table_info(stock_classification_cache)").all() as { name: string }[];
|
|
202
|
+
if (columns.length === 0) return;
|
|
203
|
+
const columnNames = new Set(columns.map(column => column.name));
|
|
204
|
+
if (columnNames.has("theme") && !columnNames.has("theme_classification")) {
|
|
205
|
+
db.prepare("ALTER TABLE stock_classification_cache RENAME COLUMN theme TO theme_classification").run();
|
|
206
|
+
columnNames.delete("theme");
|
|
207
|
+
columnNames.add("theme_classification");
|
|
208
|
+
}
|
|
209
|
+
if (columnNames.has("lastUpdated") && !columnNames.has("last_updated")) {
|
|
210
|
+
db.prepare("ALTER TABLE stock_classification_cache RENAME COLUMN lastUpdated TO last_updated").run();
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
function runIndustryThemeCategoryMigrations(db: DatabaseSync) {
|
|
215
|
+
const oldColumns = db.prepare("PRAGMA table_info(watchlist_categories)").all() as { name: string }[];
|
|
216
|
+
if (oldColumns.length === 0) return;
|
|
217
|
+
|
|
218
|
+
db.exec("BEGIN");
|
|
219
|
+
try {
|
|
220
|
+
db.exec(`
|
|
221
|
+
INSERT OR IGNORE INTO industry_theme_categories (
|
|
222
|
+
id,
|
|
223
|
+
remoteId,
|
|
224
|
+
userId,
|
|
225
|
+
name,
|
|
226
|
+
type,
|
|
227
|
+
weight,
|
|
228
|
+
sortOrder,
|
|
229
|
+
createdAt,
|
|
230
|
+
updatedAt
|
|
231
|
+
)
|
|
232
|
+
SELECT
|
|
233
|
+
id,
|
|
234
|
+
remoteId,
|
|
235
|
+
userId,
|
|
236
|
+
name,
|
|
237
|
+
type,
|
|
238
|
+
weight,
|
|
239
|
+
sortOrder,
|
|
240
|
+
createdAt,
|
|
241
|
+
updatedAt
|
|
242
|
+
FROM watchlist_categories;
|
|
243
|
+
|
|
244
|
+
DROP TABLE watchlist_categories;
|
|
245
|
+
`);
|
|
246
|
+
db.exec("COMMIT");
|
|
247
|
+
} catch (e) {
|
|
248
|
+
if (db.inTransaction) db.exec("ROLLBACK");
|
|
249
|
+
throw e;
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
|
|
144
253
|
function runStockNotesMigrations(db: DatabaseSync) {
|
|
145
254
|
const columns = db.prepare("PRAGMA table_info(stock_notes)").all() as { name: string }[];
|
|
146
255
|
if (columns.length > 0 && !columns.some(column => column.name === "watchlistId")) {
|
|
@@ -153,13 +262,72 @@ function runStockNotesMigrations(db: DatabaseSync) {
|
|
|
153
262
|
db.exec("CREATE INDEX IF NOT EXISTS idx_stock_notes_user_stock ON stock_notes(userId, watchlistId, updatedAt DESC)");
|
|
154
263
|
}
|
|
155
264
|
|
|
265
|
+
function runDailyMorningBriefingMigrations(db: DatabaseSync) {
|
|
266
|
+
const tableColumns = db.prepare("PRAGMA table_info(daily_morning_briefings)").all() as { name: string }[];
|
|
267
|
+
const tableColumnNames = new Set(tableColumns.map(column => column.name));
|
|
268
|
+
const indexes = db.prepare("PRAGMA index_list(daily_morning_briefings)").all() as { name: string; unique: number }[];
|
|
269
|
+
const hasUniqueDateMarketIndex = indexes.some(index => {
|
|
270
|
+
if (index.unique !== 1) return false;
|
|
271
|
+
const columns = db.prepare(`PRAGMA index_info(${index.name})`).all() as { name: string }[];
|
|
272
|
+
const columnNames = columns.map(column => column.name);
|
|
273
|
+
return columnNames.length === 2 && columnNames.includes("briefingDate") && columnNames.includes("market");
|
|
274
|
+
});
|
|
275
|
+
if (!hasUniqueDateMarketIndex) return;
|
|
276
|
+
|
|
277
|
+
const snapshotColumn = tableColumnNames.has("watchlistSnapshot") ? "watchlistSnapshot" : "watchlistSnapshotJson";
|
|
278
|
+
const statusColumn = tableColumnNames.has("status") ? "status" : "'completed'";
|
|
279
|
+
db.exec("BEGIN");
|
|
280
|
+
try {
|
|
281
|
+
db.exec(`
|
|
282
|
+
DROP TABLE IF EXISTS daily_morning_briefings_history;
|
|
283
|
+
|
|
284
|
+
CREATE TABLE daily_morning_briefings_history (
|
|
285
|
+
id TEXT PRIMARY KEY,
|
|
286
|
+
market TEXT NOT NULL DEFAULT 'CN',
|
|
287
|
+
briefingDate TEXT NOT NULL,
|
|
288
|
+
content TEXT NOT NULL,
|
|
289
|
+
status TEXT NOT NULL DEFAULT 'completed',
|
|
290
|
+
watchlistSnapshot TEXT NOT NULL DEFAULT '[]',
|
|
291
|
+
createdAt DATETIME DEFAULT (STRFTIME('%Y-%m-%dT%H:%M:%fZ', 'NOW')),
|
|
292
|
+
updatedAt DATETIME DEFAULT (STRFTIME('%Y-%m-%dT%H:%M:%fZ', 'NOW'))
|
|
293
|
+
);
|
|
294
|
+
|
|
295
|
+
INSERT INTO daily_morning_briefings_history (id, market, briefingDate, content, status, watchlistSnapshot, createdAt, updatedAt)
|
|
296
|
+
SELECT id, market, briefingDate, content, ${statusColumn}, ${snapshotColumn}, createdAt, updatedAt
|
|
297
|
+
FROM daily_morning_briefings;
|
|
298
|
+
|
|
299
|
+
DROP TABLE daily_morning_briefings;
|
|
300
|
+
ALTER TABLE daily_morning_briefings_history RENAME TO daily_morning_briefings;
|
|
301
|
+
CREATE INDEX IF NOT EXISTS idx_daily_morning_briefings_date ON daily_morning_briefings(briefingDate DESC);
|
|
302
|
+
`);
|
|
303
|
+
db.exec("COMMIT");
|
|
304
|
+
} catch (e) {
|
|
305
|
+
if (db.inTransaction) db.exec("ROLLBACK");
|
|
306
|
+
throw e;
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
function runDailyMorningBriefingSchemaMigrations(db: DatabaseSync) {
|
|
311
|
+
const columns = db.prepare("PRAGMA table_info(daily_morning_briefings)").all() as { name: string }[];
|
|
312
|
+
if (columns.length === 0) return;
|
|
313
|
+
const columnNames = new Set(columns.map(column => column.name));
|
|
314
|
+
if (columnNames.has("watchlistSnapshotJson") && !columnNames.has("watchlistSnapshot")) {
|
|
315
|
+
db.prepare("ALTER TABLE daily_morning_briefings RENAME COLUMN watchlistSnapshotJson TO watchlistSnapshot").run();
|
|
316
|
+
columnNames.delete("watchlistSnapshotJson");
|
|
317
|
+
columnNames.add("watchlistSnapshot");
|
|
318
|
+
}
|
|
319
|
+
if (!columnNames.has("status")) {
|
|
320
|
+
db.prepare("ALTER TABLE daily_morning_briefings ADD COLUMN status TEXT NOT NULL DEFAULT 'completed'").run();
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
|
|
156
324
|
function runStockAiAnalysisMigrations(db: DatabaseSync) {
|
|
157
325
|
const indexes = db.prepare("PRAGMA index_list(stock_ai_analysis)").all() as { name: string; unique: number }[];
|
|
158
326
|
const hasUniqueStockIndex = indexes.some(index => {
|
|
159
327
|
if (index.unique !== 1) return false;
|
|
160
328
|
const columns = db.prepare(`PRAGMA index_info(${index.name})`).all() as { name: string }[];
|
|
161
329
|
const columnNames = columns.map(column => column.name);
|
|
162
|
-
return columnNames.includes("userId") && columnNames.includes("
|
|
330
|
+
return columnNames.includes("userId") && columnNames.includes("stock_code");
|
|
163
331
|
});
|
|
164
332
|
if (!hasUniqueStockIndex) return;
|
|
165
333
|
|
|
@@ -171,8 +339,8 @@ function runStockAiAnalysisMigrations(db: DatabaseSync) {
|
|
|
171
339
|
CREATE TABLE stock_ai_analysis_history (
|
|
172
340
|
id TEXT NOT NULL,
|
|
173
341
|
userId TEXT NOT NULL,
|
|
174
|
-
|
|
175
|
-
|
|
342
|
+
stock_code TEXT NOT NULL,
|
|
343
|
+
stock_name TEXT NOT NULL,
|
|
176
344
|
market TEXT NOT NULL DEFAULT 'CN',
|
|
177
345
|
content TEXT NOT NULL,
|
|
178
346
|
createdAt DATETIME DEFAULT (STRFTIME('%Y-%m-%dT%H:%M:%fZ', 'NOW')),
|
|
@@ -180,13 +348,13 @@ function runStockAiAnalysisMigrations(db: DatabaseSync) {
|
|
|
180
348
|
PRIMARY KEY(id, userId)
|
|
181
349
|
);
|
|
182
350
|
|
|
183
|
-
INSERT INTO stock_ai_analysis_history (id, userId,
|
|
184
|
-
SELECT id, userId,
|
|
351
|
+
INSERT INTO stock_ai_analysis_history (id, userId, stock_code, stock_name, market, content, createdAt, updatedAt)
|
|
352
|
+
SELECT id, userId, stock_code, stock_name, market, content, createdAt, updatedAt
|
|
185
353
|
FROM stock_ai_analysis;
|
|
186
354
|
|
|
187
355
|
DROP TABLE stock_ai_analysis;
|
|
188
356
|
ALTER TABLE stock_ai_analysis_history RENAME TO stock_ai_analysis;
|
|
189
|
-
CREATE INDEX IF NOT EXISTS idx_stock_ai_analysis_user_stock_updated ON stock_ai_analysis(userId,
|
|
357
|
+
CREATE INDEX IF NOT EXISTS idx_stock_ai_analysis_user_stock_updated ON stock_ai_analysis(userId, stock_code, updatedAt DESC);
|
|
190
358
|
`);
|
|
191
359
|
db.exec("COMMIT");
|
|
192
360
|
} catch (e) {
|
|
@@ -195,6 +363,13 @@ function runStockAiAnalysisMigrations(db: DatabaseSync) {
|
|
|
195
363
|
}
|
|
196
364
|
}
|
|
197
365
|
|
|
366
|
+
function runStockAiAnalysisSchemaMigrations(db: DatabaseSync) {
|
|
367
|
+
const columns = db.prepare("PRAGMA table_info(stock_ai_analysis)").all() as { name: string }[];
|
|
368
|
+
if (columns.length > 0 && !columns.some(column => column.name === "status")) {
|
|
369
|
+
db.prepare("ALTER TABLE stock_ai_analysis ADD COLUMN status TEXT NOT NULL DEFAULT 'completed'").run();
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
|
|
198
373
|
function runArticleAiAnalysisMigrations(db: DatabaseSync) {
|
|
199
374
|
const columns = db.prepare("PRAGMA table_info(article_ai_analysis)").all() as { name: string }[];
|
|
200
375
|
if (columns.length === 0 || columns.some(column => column.name === "sourceId")) {
|
|
@@ -235,6 +410,160 @@ function runArticleAiAnalysisMigrations(db: DatabaseSync) {
|
|
|
235
410
|
}
|
|
236
411
|
}
|
|
237
412
|
|
|
413
|
+
function runNewsAnalysisMigrations(db: DatabaseSync) {
|
|
414
|
+
const columns = db.prepare("PRAGMA table_info(article_ai_analysis)").all() as { name: string }[];
|
|
415
|
+
if (columns.length === 0 || !columns.some(column => column.name === "sourceId")) {
|
|
416
|
+
return;
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
db.exec("BEGIN");
|
|
420
|
+
try {
|
|
421
|
+
db.exec(`
|
|
422
|
+
INSERT OR REPLACE INTO news_fact_check_analysis (id, sourceId, sourceTitle, userId, status, content, createdAt, updatedAt)
|
|
423
|
+
SELECT id, sourceId, '', userId, 'completed', content, createdAt, updatedAt
|
|
424
|
+
FROM article_ai_analysis
|
|
425
|
+
WHERE analysisType = 'verification';
|
|
426
|
+
|
|
427
|
+
INSERT OR REPLACE INTO news_deep_reasoning_analysis (id, sourceId, sourceTitle, userId, market, status, content, createdAt, updatedAt)
|
|
428
|
+
SELECT id, sourceId, '', userId, market, 'completed', content, createdAt, updatedAt
|
|
429
|
+
FROM article_ai_analysis
|
|
430
|
+
WHERE analysisType = 'deduction';
|
|
431
|
+
|
|
432
|
+
DROP TABLE article_ai_analysis;
|
|
433
|
+
`);
|
|
434
|
+
db.exec("COMMIT");
|
|
435
|
+
} catch (e) {
|
|
436
|
+
if (db.inTransaction) db.exec("ROLLBACK");
|
|
437
|
+
throw e;
|
|
438
|
+
}
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
function runNewsFactCheckAnalysisSchemaMigrations(db: DatabaseSync) {
|
|
442
|
+
const columns = db.prepare("PRAGMA table_info(news_fact_check_analysis)").all() as { name: string }[];
|
|
443
|
+
if (columns.length === 0) return;
|
|
444
|
+
const columnNames = new Set(columns.map(column => column.name));
|
|
445
|
+
if (
|
|
446
|
+
!columnNames.has("market") &&
|
|
447
|
+
columnNames.has("sourceTitle")
|
|
448
|
+
) return;
|
|
449
|
+
|
|
450
|
+
const sourceTitleExpr = columnNames.has("sourceTitle") ? "sourceTitle" : "''";
|
|
451
|
+
const statusExpr = columnNames.has("status") ? "status" : "'completed'";
|
|
452
|
+
|
|
453
|
+
db.exec("BEGIN");
|
|
454
|
+
try {
|
|
455
|
+
db.exec(`
|
|
456
|
+
DROP TABLE IF EXISTS news_fact_check_analysis_v2;
|
|
457
|
+
|
|
458
|
+
CREATE TABLE news_fact_check_analysis_v2 (
|
|
459
|
+
id TEXT NOT NULL,
|
|
460
|
+
sourceId TEXT NOT NULL,
|
|
461
|
+
sourceTitle TEXT NOT NULL DEFAULT '',
|
|
462
|
+
userId TEXT NOT NULL,
|
|
463
|
+
status TEXT NOT NULL DEFAULT 'completed',
|
|
464
|
+
content TEXT NOT NULL,
|
|
465
|
+
createdAt DATETIME DEFAULT (STRFTIME('%Y-%m-%dT%H:%M:%fZ', 'NOW')),
|
|
466
|
+
updatedAt DATETIME DEFAULT (STRFTIME('%Y-%m-%dT%H:%M:%fZ', 'NOW')),
|
|
467
|
+
PRIMARY KEY(id, userId),
|
|
468
|
+
UNIQUE(sourceId, userId)
|
|
469
|
+
);
|
|
470
|
+
|
|
471
|
+
INSERT OR REPLACE INTO news_fact_check_analysis_v2 (id, sourceId, sourceTitle, userId, status, content, createdAt, updatedAt)
|
|
472
|
+
SELECT id, sourceId, ${sourceTitleExpr}, userId, ${statusExpr}, content, createdAt, updatedAt
|
|
473
|
+
FROM news_fact_check_analysis;
|
|
474
|
+
|
|
475
|
+
DROP TABLE news_fact_check_analysis;
|
|
476
|
+
ALTER TABLE news_fact_check_analysis_v2 RENAME TO news_fact_check_analysis;
|
|
477
|
+
CREATE INDEX IF NOT EXISTS idx_news_fact_check_analysis_user_source_updated
|
|
478
|
+
ON news_fact_check_analysis(userId, sourceId, updatedAt DESC);
|
|
479
|
+
`);
|
|
480
|
+
db.exec("COMMIT");
|
|
481
|
+
} catch (e) {
|
|
482
|
+
if (db.inTransaction) db.exec("ROLLBACK");
|
|
483
|
+
throw e;
|
|
484
|
+
}
|
|
485
|
+
}
|
|
486
|
+
|
|
487
|
+
function runNewsDeepReasoningAnalysisSchemaMigrations(db: DatabaseSync) {
|
|
488
|
+
const columns = db.prepare("PRAGMA table_info(news_deep_reasoning_analysis)").all() as { name: string }[];
|
|
489
|
+
if (columns.length === 0) return;
|
|
490
|
+
const columnNames = new Set(columns.map(column => column.name));
|
|
491
|
+
if (columnNames.has("market") && columnNames.has("sourceTitle")) return;
|
|
492
|
+
|
|
493
|
+
const sourceTitleExpr = columnNames.has("sourceTitle") ? "sourceTitle" : "''";
|
|
494
|
+
const marketExpr = columnNames.has("market") ? "market" : "'CN'";
|
|
495
|
+
const statusExpr = columnNames.has("status") ? "status" : "'completed'";
|
|
496
|
+
|
|
497
|
+
db.exec("BEGIN");
|
|
498
|
+
try {
|
|
499
|
+
db.exec(`
|
|
500
|
+
DROP TABLE IF EXISTS news_deep_reasoning_analysis_v2;
|
|
501
|
+
|
|
502
|
+
CREATE TABLE news_deep_reasoning_analysis_v2 (
|
|
503
|
+
id TEXT NOT NULL,
|
|
504
|
+
sourceId TEXT NOT NULL,
|
|
505
|
+
sourceTitle TEXT NOT NULL DEFAULT '',
|
|
506
|
+
userId TEXT NOT NULL,
|
|
507
|
+
market TEXT NOT NULL DEFAULT 'CN',
|
|
508
|
+
status TEXT NOT NULL DEFAULT 'completed',
|
|
509
|
+
content TEXT NOT NULL,
|
|
510
|
+
createdAt DATETIME DEFAULT (STRFTIME('%Y-%m-%dT%H:%M:%fZ', 'NOW')),
|
|
511
|
+
updatedAt DATETIME DEFAULT (STRFTIME('%Y-%m-%dT%H:%M:%fZ', 'NOW')),
|
|
512
|
+
PRIMARY KEY(id, userId),
|
|
513
|
+
UNIQUE(sourceId, userId, market)
|
|
514
|
+
);
|
|
515
|
+
|
|
516
|
+
INSERT OR REPLACE INTO news_deep_reasoning_analysis_v2 (id, sourceId, sourceTitle, userId, market, status, content, createdAt, updatedAt)
|
|
517
|
+
SELECT id, sourceId, ${sourceTitleExpr}, userId, ${marketExpr}, ${statusExpr}, content, createdAt, updatedAt
|
|
518
|
+
FROM news_deep_reasoning_analysis;
|
|
519
|
+
|
|
520
|
+
DROP TABLE news_deep_reasoning_analysis;
|
|
521
|
+
ALTER TABLE news_deep_reasoning_analysis_v2 RENAME TO news_deep_reasoning_analysis;
|
|
522
|
+
CREATE INDEX IF NOT EXISTS idx_news_deep_reasoning_analysis_user_source_updated
|
|
523
|
+
ON news_deep_reasoning_analysis(userId, sourceId, updatedAt DESC);
|
|
524
|
+
`);
|
|
525
|
+
db.exec("COMMIT");
|
|
526
|
+
} catch (e) {
|
|
527
|
+
if (db.inTransaction) db.exec("ROLLBACK");
|
|
528
|
+
throw e;
|
|
529
|
+
}
|
|
530
|
+
}
|
|
531
|
+
|
|
532
|
+
function runNewsFactCheckDropSourceContentMigration(db: DatabaseSync) {
|
|
533
|
+
const columns = db.prepare("PRAGMA table_info(news_fact_check_analysis)").all() as { name: string }[];
|
|
534
|
+
if (columns.length === 0) return;
|
|
535
|
+
if (!columns.some(column => column.name === "sourceContent")) return;
|
|
536
|
+
db.prepare("ALTER TABLE news_fact_check_analysis DROP COLUMN sourceContent").run();
|
|
537
|
+
}
|
|
538
|
+
|
|
539
|
+
function runNewsDeepReasoningDropSourceContentMigration(db: DatabaseSync) {
|
|
540
|
+
const columns = db.prepare("PRAGMA table_info(news_deep_reasoning_analysis)").all() as { name: string }[];
|
|
541
|
+
if (columns.length === 0) return;
|
|
542
|
+
if (!columns.some(column => column.name === "sourceContent")) return;
|
|
543
|
+
db.prepare("ALTER TABLE news_deep_reasoning_analysis DROP COLUMN sourceContent").run();
|
|
544
|
+
}
|
|
545
|
+
|
|
546
|
+
function runProfileLibrariesSchemaMigrations(db: DatabaseSync) {
|
|
547
|
+
const columns = db.prepare("PRAGMA table_info(profile_libraries)").all() as { name: string }[];
|
|
548
|
+
if (columns.length === 0) return;
|
|
549
|
+
const columnNames = new Set(columns.map(column => column.name));
|
|
550
|
+
if (!columnNames.has("knowType")) {
|
|
551
|
+
db.prepare("ALTER TABLE profile_libraries ADD COLUMN knowType TEXT").run();
|
|
552
|
+
}
|
|
553
|
+
if (!columnNames.has("recordDate")) {
|
|
554
|
+
db.prepare("ALTER TABLE profile_libraries ADD COLUMN recordDate DATETIME DEFAULT (STRFTIME('%Y-%m-%dT%H:%M:%fZ', 'NOW'))").run();
|
|
555
|
+
}
|
|
556
|
+
if (!columnNames.has("content")) {
|
|
557
|
+
db.prepare("ALTER TABLE profile_libraries ADD COLUMN content TEXT").run();
|
|
558
|
+
}
|
|
559
|
+
if (!columnNames.has("vectorValue")) {
|
|
560
|
+
db.prepare("ALTER TABLE profile_libraries ADD COLUMN vectorValue BLOB").run();
|
|
561
|
+
}
|
|
562
|
+
if (!columnNames.has("source")) {
|
|
563
|
+
db.prepare("ALTER TABLE profile_libraries ADD COLUMN source TEXT").run();
|
|
564
|
+
}
|
|
565
|
+
}
|
|
566
|
+
|
|
238
567
|
export function getDB(): DatabaseSync {
|
|
239
568
|
if (!_db) {
|
|
240
569
|
const dbPath = getDbPath();
|
|
@@ -251,35 +580,58 @@ export function getDB(): DatabaseSync {
|
|
|
251
580
|
_db = new DatabaseSync(dbPath);
|
|
252
581
|
_db.exec("PRAGMA journal_mode = WAL");
|
|
253
582
|
_db.exec("PRAGMA synchronous = NORMAL");
|
|
583
|
+
runStockColumnNameMigrations(_db);
|
|
254
584
|
|
|
255
585
|
_db.exec(`
|
|
256
586
|
CREATE TABLE IF NOT EXISTS watchlist (
|
|
257
587
|
id TEXT PRIMARY KEY,
|
|
258
588
|
userId TEXT NOT NULL,
|
|
259
|
-
|
|
589
|
+
stock_code TEXT NOT NULL,
|
|
260
590
|
exchange TEXT NOT NULL,
|
|
261
591
|
market TEXT NOT NULL,
|
|
262
|
-
|
|
592
|
+
stock_name TEXT NOT NULL,
|
|
263
593
|
sortOrder REAL DEFAULT 0,
|
|
264
594
|
isDeleted INTEGER DEFAULT 0 CHECK (isDeleted IN (0, 1)),
|
|
265
595
|
createdAt DATETIME DEFAULT (STRFTIME('%Y-%m-%dT%H:%M:%fZ', 'NOW')),
|
|
266
596
|
updatedAt DATETIME DEFAULT (STRFTIME('%Y-%m-%dT%H:%M:%fZ', 'NOW')),
|
|
267
|
-
UNIQUE(userId,
|
|
597
|
+
UNIQUE(userId, stock_code, exchange)
|
|
268
598
|
);
|
|
269
599
|
|
|
270
|
-
CREATE TABLE IF NOT EXISTS
|
|
271
|
-
|
|
272
|
-
exchange
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
PRIMARY KEY(
|
|
600
|
+
CREATE TABLE IF NOT EXISTS stock_classification_cache (
|
|
601
|
+
stock_code TEXT NOT NULL,
|
|
602
|
+
exchange TEXT NOT NULL,
|
|
603
|
+
stock_name TEXT NOT NULL,
|
|
604
|
+
industry_classification TEXT,
|
|
605
|
+
theme_classification TEXT,
|
|
606
|
+
last_updated DATETIME DEFAULT (STRFTIME('%Y-%m-%dT%H:%M:%fZ', 'NOW')),
|
|
607
|
+
PRIMARY KEY(stock_code, exchange)
|
|
278
608
|
);
|
|
279
609
|
|
|
280
610
|
CREATE INDEX IF NOT EXISTS idx_watchlist_main ON watchlist(userId, isDeleted, sortOrder ASC);
|
|
281
611
|
|
|
282
|
-
CREATE TABLE IF NOT EXISTS
|
|
612
|
+
CREATE TABLE IF NOT EXISTS stock_basic (
|
|
613
|
+
stock_code TEXT PRIMARY KEY,
|
|
614
|
+
symbol TEXT NOT NULL,
|
|
615
|
+
name TEXT NOT NULL,
|
|
616
|
+
fullname TEXT,
|
|
617
|
+
enname TEXT,
|
|
618
|
+
cnspell TEXT,
|
|
619
|
+
exchange TEXT NOT NULL,
|
|
620
|
+
market TEXT,
|
|
621
|
+
industry TEXT,
|
|
622
|
+
area TEXT,
|
|
623
|
+
curr_type TEXT,
|
|
624
|
+
list_date TEXT,
|
|
625
|
+
is_hs TEXT,
|
|
626
|
+
act_name TEXT,
|
|
627
|
+
act_ent_type TEXT,
|
|
628
|
+
createdAt DATETIME DEFAULT (STRFTIME('%Y-%m-%dT%H:%M:%fZ', 'NOW')),
|
|
629
|
+
updatedAt DATETIME DEFAULT (STRFTIME('%Y-%m-%dT%H:%M:%fZ', 'NOW'))
|
|
630
|
+
);
|
|
631
|
+
CREATE INDEX IF NOT EXISTS idx_stock_basic_exchange_symbol ON stock_basic(exchange, symbol);
|
|
632
|
+
CREATE INDEX IF NOT EXISTS idx_stock_basic_name ON stock_basic(name);
|
|
633
|
+
|
|
634
|
+
CREATE TABLE IF NOT EXISTS industry_theme_categories (
|
|
283
635
|
id TEXT PRIMARY KEY,
|
|
284
636
|
remoteId TEXT,
|
|
285
637
|
userId TEXT NOT NULL,
|
|
@@ -318,7 +670,12 @@ export function getDB(): DatabaseSync {
|
|
|
318
670
|
CREATE TABLE IF NOT EXISTS profile_libraries (
|
|
319
671
|
id TEXT NOT NULL,
|
|
320
672
|
userId TEXT NOT NULL,
|
|
673
|
+
knowType TEXT,
|
|
321
674
|
title TEXT NOT NULL,
|
|
675
|
+
recordDate DATETIME DEFAULT (STRFTIME('%Y-%m-%dT%H:%M:%fZ', 'NOW')),
|
|
676
|
+
content TEXT,
|
|
677
|
+
vectorValue BLOB,
|
|
678
|
+
source TEXT,
|
|
322
679
|
createdAt DATETIME DEFAULT (STRFTIME('%Y-%m-%dT%H:%M:%fZ', 'NOW')),
|
|
323
680
|
updatedAt DATETIME DEFAULT (STRFTIME('%Y-%m-%dT%H:%M:%fZ', 'NOW')),
|
|
324
681
|
PRIMARY KEY(id, userId)
|
|
@@ -349,35 +706,85 @@ export function getDB(): DatabaseSync {
|
|
|
349
706
|
CREATE TABLE IF NOT EXISTS stock_ai_analysis (
|
|
350
707
|
id TEXT NOT NULL,
|
|
351
708
|
userId TEXT NOT NULL,
|
|
352
|
-
|
|
353
|
-
|
|
709
|
+
stock_code TEXT NOT NULL,
|
|
710
|
+
stock_name TEXT NOT NULL,
|
|
354
711
|
market TEXT NOT NULL DEFAULT 'CN',
|
|
712
|
+
status TEXT NOT NULL DEFAULT 'completed',
|
|
355
713
|
content TEXT NOT NULL,
|
|
356
714
|
createdAt DATETIME DEFAULT (STRFTIME('%Y-%m-%dT%H:%M:%fZ', 'NOW')),
|
|
357
715
|
updatedAt DATETIME DEFAULT (STRFTIME('%Y-%m-%dT%H:%M:%fZ', 'NOW')),
|
|
358
716
|
PRIMARY KEY(id, userId)
|
|
359
717
|
);
|
|
360
|
-
CREATE INDEX IF NOT EXISTS idx_stock_ai_analysis_user_stock_updated ON stock_ai_analysis(userId,
|
|
718
|
+
CREATE INDEX IF NOT EXISTS idx_stock_ai_analysis_user_stock_updated ON stock_ai_analysis(userId, stock_code, updatedAt DESC);
|
|
361
719
|
|
|
362
|
-
CREATE TABLE IF NOT EXISTS
|
|
720
|
+
CREATE TABLE IF NOT EXISTS news_fact_check_analysis (
|
|
363
721
|
id TEXT NOT NULL,
|
|
364
722
|
sourceId TEXT NOT NULL,
|
|
723
|
+
sourceTitle TEXT NOT NULL DEFAULT '',
|
|
724
|
+
userId TEXT NOT NULL,
|
|
725
|
+
status TEXT NOT NULL DEFAULT 'completed',
|
|
726
|
+
content TEXT NOT NULL,
|
|
727
|
+
createdAt DATETIME DEFAULT (STRFTIME('%Y-%m-%dT%H:%M:%fZ', 'NOW')),
|
|
728
|
+
updatedAt DATETIME DEFAULT (STRFTIME('%Y-%m-%dT%H:%M:%fZ', 'NOW')),
|
|
729
|
+
PRIMARY KEY(id, userId),
|
|
730
|
+
UNIQUE(sourceId, userId)
|
|
731
|
+
);
|
|
732
|
+
CREATE INDEX IF NOT EXISTS idx_news_fact_check_analysis_user_source_updated
|
|
733
|
+
ON news_fact_check_analysis(userId, sourceId, updatedAt DESC);
|
|
734
|
+
|
|
735
|
+
CREATE TABLE IF NOT EXISTS news_deep_reasoning_analysis (
|
|
736
|
+
id TEXT NOT NULL,
|
|
737
|
+
sourceId TEXT NOT NULL,
|
|
738
|
+
sourceTitle TEXT NOT NULL DEFAULT '',
|
|
365
739
|
userId TEXT NOT NULL,
|
|
366
|
-
analysisType TEXT NOT NULL,
|
|
367
740
|
market TEXT NOT NULL DEFAULT 'CN',
|
|
741
|
+
status TEXT NOT NULL DEFAULT 'completed',
|
|
368
742
|
content TEXT NOT NULL,
|
|
369
743
|
createdAt DATETIME DEFAULT (STRFTIME('%Y-%m-%dT%H:%M:%fZ', 'NOW')),
|
|
370
744
|
updatedAt DATETIME DEFAULT (STRFTIME('%Y-%m-%dT%H:%M:%fZ', 'NOW')),
|
|
371
745
|
PRIMARY KEY(id, userId),
|
|
372
|
-
UNIQUE(sourceId, userId,
|
|
746
|
+
UNIQUE(sourceId, userId, market)
|
|
747
|
+
);
|
|
748
|
+
CREATE INDEX IF NOT EXISTS idx_news_deep_reasoning_analysis_user_source_updated
|
|
749
|
+
ON news_deep_reasoning_analysis(userId, sourceId, updatedAt DESC);
|
|
750
|
+
|
|
751
|
+
CREATE TABLE IF NOT EXISTS daily_morning_briefings (
|
|
752
|
+
id TEXT PRIMARY KEY,
|
|
753
|
+
market TEXT NOT NULL DEFAULT 'CN',
|
|
754
|
+
briefingDate TEXT NOT NULL,
|
|
755
|
+
content TEXT NOT NULL,
|
|
756
|
+
status TEXT NOT NULL DEFAULT 'completed',
|
|
757
|
+
watchlistSnapshot TEXT NOT NULL DEFAULT '[]',
|
|
758
|
+
createdAt DATETIME DEFAULT (STRFTIME('%Y-%m-%dT%H:%M:%fZ', 'NOW')),
|
|
759
|
+
updatedAt DATETIME DEFAULT (STRFTIME('%Y-%m-%dT%H:%M:%fZ', 'NOW'))
|
|
760
|
+
);
|
|
761
|
+
CREATE INDEX IF NOT EXISTS idx_daily_morning_briefings_date ON daily_morning_briefings(briefingDate DESC);
|
|
762
|
+
|
|
763
|
+
CREATE TABLE IF NOT EXISTS skill_versions (
|
|
764
|
+
skillName TEXT PRIMARY KEY,
|
|
765
|
+
version TEXT NOT NULL,
|
|
766
|
+
createdAt DATETIME DEFAULT (STRFTIME('%Y-%m-%dT%H:%M:%fZ', 'NOW')),
|
|
767
|
+
updatedAt DATETIME DEFAULT (STRFTIME('%Y-%m-%dT%H:%M:%fZ', 'NOW'))
|
|
373
768
|
);
|
|
374
|
-
CREATE INDEX IF NOT EXISTS idx_article_ai_analysis_user_source_type_updated ON article_ai_analysis(userId, sourceId, analysisType, updatedAt DESC);
|
|
375
769
|
`);
|
|
376
770
|
|
|
771
|
+
runClassificationCacheSchemaMigrations(_db);
|
|
772
|
+
runClassificationCacheMigrations(_db);
|
|
773
|
+
runClassificationCacheSchemaMigrations(_db);
|
|
774
|
+
runIndustryThemeCategoryMigrations(_db);
|
|
377
775
|
runWatchlistDedupMigrations(_db);
|
|
378
776
|
runStockNotesMigrations(_db);
|
|
379
777
|
runStockAiAnalysisMigrations(_db);
|
|
778
|
+
runStockAiAnalysisSchemaMigrations(_db);
|
|
380
779
|
runArticleAiAnalysisMigrations(_db);
|
|
780
|
+
runNewsFactCheckAnalysisSchemaMigrations(_db);
|
|
781
|
+
runNewsDeepReasoningAnalysisSchemaMigrations(_db);
|
|
782
|
+
runNewsAnalysisMigrations(_db);
|
|
783
|
+
runDailyMorningBriefingMigrations(_db);
|
|
784
|
+
runDailyMorningBriefingSchemaMigrations(_db);
|
|
785
|
+
runNewsFactCheckDropSourceContentMigration(_db);
|
|
786
|
+
runNewsDeepReasoningDropSourceContentMigration(_db);
|
|
787
|
+
runProfileLibrariesSchemaMigrations(_db);
|
|
381
788
|
}
|
|
382
789
|
return _db;
|
|
383
790
|
}
|