fi-pool-server 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.
Files changed (93) hide show
  1. package/README.md +26 -0
  2. package/dist/db/index.d.ts +18 -0
  3. package/dist/db/index.d.ts.map +1 -0
  4. package/dist/db/index.js +58 -0
  5. package/dist/db/index.js.map +1 -0
  6. package/dist/db/migrate.d.ts +11 -0
  7. package/dist/db/migrate.d.ts.map +1 -0
  8. package/dist/db/migrate.js +42 -0
  9. package/dist/db/migrate.js.map +1 -0
  10. package/dist/db/schema.d.ts +1101 -0
  11. package/dist/db/schema.d.ts.map +1 -0
  12. package/dist/db/schema.js +149 -0
  13. package/dist/db/schema.js.map +1 -0
  14. package/dist/index.d.ts +50 -0
  15. package/dist/index.d.ts.map +1 -0
  16. package/dist/index.js +69 -0
  17. package/dist/index.js.map +1 -0
  18. package/dist/services/analysis.d.ts +62 -0
  19. package/dist/services/analysis.d.ts.map +1 -0
  20. package/dist/services/analysis.js +74 -0
  21. package/dist/services/analysis.js.map +1 -0
  22. package/dist/services/daily-info.d.ts +150 -0
  23. package/dist/services/daily-info.d.ts.map +1 -0
  24. package/dist/services/daily-info.js +293 -0
  25. package/dist/services/daily-info.js.map +1 -0
  26. package/dist/services/embedding.d.ts +89 -0
  27. package/dist/services/embedding.d.ts.map +1 -0
  28. package/dist/services/embedding.js +227 -0
  29. package/dist/services/embedding.js.map +1 -0
  30. package/dist/services/llm.d.ts +64 -0
  31. package/dist/services/llm.d.ts.map +1 -0
  32. package/dist/services/llm.js +109 -0
  33. package/dist/services/llm.js.map +1 -0
  34. package/dist/services/pipeline.d.ts +161 -0
  35. package/dist/services/pipeline.d.ts.map +1 -0
  36. package/dist/services/pipeline.js +844 -0
  37. package/dist/services/pipeline.js.map +1 -0
  38. package/dist/services/pool.d.ts +142 -0
  39. package/dist/services/pool.d.ts.map +1 -0
  40. package/dist/services/pool.js +208 -0
  41. package/dist/services/pool.js.map +1 -0
  42. package/dist/services/sentiment.d.ts +31 -0
  43. package/dist/services/sentiment.d.ts.map +1 -0
  44. package/dist/services/sentiment.js +76 -0
  45. package/dist/services/sentiment.js.map +1 -0
  46. package/dist/services/session.d.ts +117 -0
  47. package/dist/services/session.d.ts.map +1 -0
  48. package/dist/services/session.js +176 -0
  49. package/dist/services/session.js.map +1 -0
  50. package/dist/services/stock.d.ts +82 -0
  51. package/dist/services/stock.d.ts.map +1 -0
  52. package/dist/services/stock.js +99 -0
  53. package/dist/services/stock.js.map +1 -0
  54. package/dist/services/word-count.d.ts +61 -0
  55. package/dist/services/word-count.d.ts.map +1 -0
  56. package/dist/services/word-count.js +120 -0
  57. package/dist/services/word-count.js.map +1 -0
  58. package/dist/tools/auxiliary.d.ts +93 -0
  59. package/dist/tools/auxiliary.d.ts.map +1 -0
  60. package/dist/tools/auxiliary.js +204 -0
  61. package/dist/tools/auxiliary.js.map +1 -0
  62. package/dist/tools/command.d.ts +193 -0
  63. package/dist/tools/command.d.ts.map +1 -0
  64. package/dist/tools/command.js +263 -0
  65. package/dist/tools/command.js.map +1 -0
  66. package/dist/tools/execute.d.ts +109 -0
  67. package/dist/tools/execute.d.ts.map +1 -0
  68. package/dist/tools/execute.js +112 -0
  69. package/dist/tools/execute.js.map +1 -0
  70. package/dist/tools/manager.d.ts +150 -0
  71. package/dist/tools/manager.d.ts.map +1 -0
  72. package/dist/tools/manager.js +200 -0
  73. package/dist/tools/manager.js.map +1 -0
  74. package/dist/tools/query.d.ts +163 -0
  75. package/dist/tools/query.d.ts.map +1 -0
  76. package/dist/tools/query.js +190 -0
  77. package/dist/tools/query.js.map +1 -0
  78. package/dist/utils/http-client.d.ts +87 -0
  79. package/dist/utils/http-client.d.ts.map +1 -0
  80. package/dist/utils/http-client.js +211 -0
  81. package/dist/utils/http-client.js.map +1 -0
  82. package/dist/utils/indicators.d.ts +194 -0
  83. package/dist/utils/indicators.d.ts.map +1 -0
  84. package/dist/utils/indicators.js +395 -0
  85. package/dist/utils/indicators.js.map +1 -0
  86. package/dist/utils/signals.d.ts +65 -0
  87. package/dist/utils/signals.d.ts.map +1 -0
  88. package/dist/utils/signals.js +171 -0
  89. package/dist/utils/signals.js.map +1 -0
  90. package/drizzle/0000_equal_marvel_apes.sql +124 -0
  91. package/drizzle/meta/0000_snapshot.json +858 -0
  92. package/drizzle/meta/_journal.json +13 -0
  93. package/package.json +58 -0
@@ -0,0 +1,204 @@
1
+ /**
2
+ * 辅助类工具(Auxiliary)
3
+ *
4
+ * 提供帮助信息、资源列表、状态查询、版本信息、配置管理等功能。
5
+ * 返回值均为元信息,不涉及业务数据。
6
+ *
7
+ * @module tools/auxiliary
8
+ */
9
+ import { getDatabase } from '../db/index.js';
10
+ import { config as configTable } from '../db/schema.js';
11
+ import { eq } from 'drizzle-orm';
12
+ import { VERSION } from '../index.js';
13
+ import * as poolService from '../services/pool.js';
14
+ import * as stockService from '../services/stock.js';
15
+ /**
16
+ * 输出所有可用的命令和工具帮助信息。
17
+ *
18
+ * @param command - 可选命令名称,不指定则输出所有
19
+ * @returns 帮助文本
20
+ */
21
+ export async function help(command) {
22
+ const lines = [
23
+ 'Fi-Pool-Manager v' + VERSION,
24
+ '',
25
+ '可用管理命令:',
26
+ ' create_pool 创建新的股票池',
27
+ ' delete_pool 删除指定股池',
28
+ ' update_pool 修改股池信息',
29
+ ' add_stocks 向股池添加股票',
30
+ ' remove_stocks 从股池移除股票',
31
+ ' set_pool_signal 设置股池信号',
32
+ '',
33
+ '可用查询命令:',
34
+ ' list_pools 列出所有股池',
35
+ ' get_pool_stocks 查股池中的股票',
36
+ ' get_stock_info 查股票基本信息',
37
+ ' get_daily_info 查日行情数据',
38
+ ' get_analysis_report 查客观分析报告',
39
+ ' get_final_report 查最终报告',
40
+ ' get_system_status 查看系统状态',
41
+ '',
42
+ '可用执行命令:',
43
+ ' run_local_analysis 运行本地分析',
44
+ ' run_full_pipeline 运行完整流水线',
45
+ ' run_pool_analysis 运行股池本地分析',
46
+ ' run_pool_full_pipeline 运行股池完整流水线',
47
+ ' refresh_data 刷新行情数据',
48
+ '',
49
+ '可用辅助命令:',
50
+ ' help 显示帮助',
51
+ ' list_resources 列出可用资源',
52
+ ' show_state 查看系统简要状态',
53
+ ' show_version 输出版本信息',
54
+ ' get_config 查看配置',
55
+ ' set_config 设置配置',
56
+ '',
57
+ '报告输出命令:',
58
+ ' output_analysis_report 输出客观分析报告',
59
+ ' output_final_report 输出最终报告',
60
+ ' output_pool_report 输出股池报告',
61
+ ' semantic_search 语义搜索',
62
+ ' session_manage 管理 LLM 会话',
63
+ ];
64
+ if (command) {
65
+ const filtered = lines.filter((l) => l.toLowerCase().includes(command.toLowerCase()));
66
+ if (filtered.length > 0) {
67
+ return ['匹配 "' + command + '" 的帮助信息:', '', ...filtered].join('\n');
68
+ }
69
+ return `未找到命令: ${command}`;
70
+ }
71
+ return lines.join('\n');
72
+ }
73
+ /**
74
+ * 列出可用资源。
75
+ *
76
+ * @param type - 资源类型 "pools" | "stocks" | "tools"
77
+ * @returns 资源列表
78
+ */
79
+ export async function listResources(type) {
80
+ switch (type) {
81
+ case 'pools': {
82
+ const pools = await poolService.listPools();
83
+ return {
84
+ items: pools.map((p) => ({
85
+ id: String(p.id),
86
+ name: p.name,
87
+ })),
88
+ };
89
+ }
90
+ case 'stocks': {
91
+ const stocks = await stockService.listAllStocks();
92
+ return {
93
+ items: stocks.map((s) => ({
94
+ id: s.code,
95
+ name: s.name,
96
+ })),
97
+ };
98
+ }
99
+ case 'tools': {
100
+ const toolNames = [
101
+ 'create_pool', 'delete_pool', 'update_pool', 'add_stocks', 'remove_stocks', 'set_pool_signal',
102
+ 'list_pools', 'get_pool_stocks', 'get_stock_info', 'get_daily_info', 'get_analysis_report',
103
+ 'get_final_report', 'get_system_status', 'output_analysis_report', 'output_final_report',
104
+ 'output_pool_report', 'semantic_search', 'session_manage', 'run_local_analysis',
105
+ 'run_full_pipeline', 'run_pool_analysis', 'run_pool_full_pipeline', 'refresh_data',
106
+ 'help', 'list_resources', 'show_state', 'show_version', 'get_config', 'set_config',
107
+ ];
108
+ return {
109
+ items: toolNames.map((name) => ({ id: name, name })),
110
+ };
111
+ }
112
+ default:
113
+ return { items: [] };
114
+ }
115
+ }
116
+ /**
117
+ * 查看系统简要运行状态。
118
+ *
119
+ * @returns { status: 'running' | 'error', version: string, uptime: number }
120
+ */
121
+ export async function showState() {
122
+ return {
123
+ status: 'running',
124
+ version: VERSION,
125
+ uptime: Math.floor(process.uptime()),
126
+ };
127
+ }
128
+ /**
129
+ * 输出版本信息。
130
+ *
131
+ * @returns 版本字符串
132
+ */
133
+ export async function showVersion() {
134
+ return `Fi-Pool-Manager v${VERSION}`;
135
+ }
136
+ /**
137
+ * 查看指定配置项或所有配置。
138
+ *
139
+ * 查询优先级:DB → process.env → null。
140
+ * DB 中不存在的键会 fallback 到 .env 环境变量。
141
+ *
142
+ * @param key - 可选配置键名,不指定则返回所有配置
143
+ * @returns 配置键值对
144
+ */
145
+ export async function getConfig(key) {
146
+ const db = getDatabase();
147
+ if (key) {
148
+ // 先查 DB,再 fallback 到 process.env
149
+ const row = db
150
+ .select()
151
+ .from(configTable)
152
+ .where(eq(configTable.key, key))
153
+ .get();
154
+ if (row)
155
+ return { key: row.key, value: row.value };
156
+ const envVal = process.env[key];
157
+ return envVal !== undefined
158
+ ? { key, value: envVal, source: '.env' }
159
+ : { key, value: null };
160
+ }
161
+ // 返回全部:DB 值 + process.env 补充
162
+ const allRows = db.select().from(configTable).all();
163
+ const config = {};
164
+ for (const row of allRows) {
165
+ config[row.key] = row.value;
166
+ }
167
+ // 补充运行时环境变量中不在 DB 中的配置
168
+ const envKeys = ['LLM_BASE_URL', 'LLM_MODEL', 'DB_PATH', 'DASHSCOPE_API_KEY', 'DATA_FETCH_INTERVAL_MS'];
169
+ for (const ek of envKeys) {
170
+ if (!(ek in config) && process.env[ek]) {
171
+ config[ek] = process.env[ek];
172
+ }
173
+ }
174
+ return { config };
175
+ }
176
+ /**
177
+ * 修改配置项。
178
+ *
179
+ * 同时更新 DB 和运行时的 process.env,确保对同一进程后续读取生效。
180
+ *
181
+ * @param key - 配置键名
182
+ * @param value - 配置值
183
+ * @returns { success: true }
184
+ */
185
+ export async function setConfig(key, value) {
186
+ try {
187
+ const db = getDatabase();
188
+ db.insert(configTable)
189
+ .values({ key, value })
190
+ .onConflictDoUpdate({
191
+ target: configTable.key,
192
+ set: { value },
193
+ })
194
+ .run();
195
+ // 同步到运行时环境,确保同一进程后续读取一致
196
+ process.env[key] = value;
197
+ return { success: true };
198
+ }
199
+ catch (err) {
200
+ const message = err instanceof Error ? err.message : String(err);
201
+ return { success: false, error: { code: 'DB_ERROR', message } };
202
+ }
203
+ }
204
+ //# sourceMappingURL=auxiliary.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auxiliary.js","sourceRoot":"","sources":["../../src/tools/auxiliary.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,193 @@
1
+ /**
2
+ * 命令类工具(Command)
3
+ *
4
+ * 封装报告输出、语义搜索和会话管理等功能。
5
+ * 返回值均为复合结构,包含完整或摘要的内容。
6
+ *
7
+ * @module tools/command
8
+ */
9
+ import * as embeddingService from '../services/embedding.js';
10
+ /**
11
+ * 输出指定股票指定日期的客观分析报告。
12
+ *
13
+ * @param code - 股票代码
14
+ * @param date - 报告日期 'yyyy-MM-dd'
15
+ * @param mode - 输出模式:
16
+ * - 'overview':仅返回 code、date、summary 摘要字段
17
+ * - 'full'(默认):返回完整报告(含 indicators、signals JSON)
18
+ * @returns 包含 code、date、summary 的报告对象,不存在时返回 null
19
+ *
20
+ * @example
21
+ * const report = await outputAnalysisReport('600519', '2024-06-01', 'full');
22
+ * if (report) console.log(report.summary);
23
+ */
24
+ export declare function outputAnalysisReport(code: string, date: string, mode?: 'overview' | 'full'): Promise<{
25
+ code: string;
26
+ date: string;
27
+ summary: string;
28
+ createdAt: string;
29
+ } | {
30
+ id: number;
31
+ indicators: string;
32
+ signals: string;
33
+ code: string;
34
+ date: string;
35
+ summary: string;
36
+ createdAt: string;
37
+ } | null>;
38
+ /**
39
+ * 输出指定股票指定日期的最终报告。
40
+ *
41
+ * @param code - 股票代码
42
+ * @param date - 报告日期 'yyyy-MM-dd'
43
+ * @param mode - 输出模式:
44
+ * - 'overview':仅返回 code、date、summary、pipelineId 摘要字段
45
+ * - 'full'(默认):返回完整报告(含 fullReport、roleSummary)
46
+ * @returns 包含 code、date 的报告对象,不存在时返回 null
47
+ *
48
+ * @example
49
+ * const report = await outputFinalReport('600519', '2024-06-01', 'overview');
50
+ */
51
+ export declare function outputFinalReport(code: string, date: string, mode?: 'overview' | 'full'): Promise<{
52
+ code: string;
53
+ date: string;
54
+ summary: string;
55
+ pipelineId: string;
56
+ createdAt: string;
57
+ } | {
58
+ id: number;
59
+ fullReport: string;
60
+ roleSummary: string | {
61
+ role: string;
62
+ keyPoint: string;
63
+ }[];
64
+ code: string;
65
+ date: string;
66
+ summary: string;
67
+ pipelineId: string;
68
+ createdAt: string;
69
+ } | null>;
70
+ /**
71
+ * 输出指定股池的综合分析报告。
72
+ *
73
+ * @param poolId - 股池 ID
74
+ * @param mode - 输出模式:
75
+ * - 'overview':仅输出股池摘要信息和股票列表
76
+ * - 'full'(默认):输出完整报告(含每只股票的最新分析摘要)
77
+ * @returns 包含 poolId、name 的股池报告对象,股池不存在时返回 null
78
+ *
79
+ * @example
80
+ * const r = await outputPoolReport(1, 'overview');
81
+ */
82
+ export declare function outputPoolReport(poolId: number, mode?: 'overview' | 'full'): Promise<{
83
+ poolId: number;
84
+ poolName: string;
85
+ poolDesc: string;
86
+ poolSignal: number;
87
+ stockCount: number;
88
+ stocks: {
89
+ code: string;
90
+ name: string;
91
+ currentPrice: number;
92
+ signal: number;
93
+ latestAnalysisDate: string | null;
94
+ summary: string | null;
95
+ }[];
96
+ } | {
97
+ summary: string;
98
+ poolId: number;
99
+ poolName: string;
100
+ poolDesc: string;
101
+ poolSignal: number;
102
+ stockCount: number;
103
+ stocks: {
104
+ code: string;
105
+ name: string;
106
+ currentPrice: number;
107
+ signal: number;
108
+ latestAnalysisDate: string | null;
109
+ summary: string | null;
110
+ }[];
111
+ } | null>;
112
+ /**
113
+ * 基于语义相似度搜索历史分析报告。
114
+ *
115
+ * 通过向量嵌入技术,搜索与查询文本语义相似的分析报告或最终报告。
116
+ *
117
+ * @param query - 搜索查询文本
118
+ * @param limit - 最多返回结果数,默认 10
119
+ * @param type - 搜索范围:
120
+ * - 'analysis':仅搜索客观分析报告
121
+ * - 'final':仅搜索最终报告
122
+ * - 'all'(默认):搜索全部类型
123
+ * @returns 搜索结果数组,按相关性降序排列
124
+ *
125
+ * @example
126
+ * const results = await semanticSearch('贵州茅台', 5, 'final');
127
+ * results.forEach(r => console.log(r.code, r.date, r.relevance));
128
+ */
129
+ export declare function semanticSearch(query: string, limit?: number, type?: 'analysis' | 'final' | 'all'): Promise<embeddingService.SearchResult[]>;
130
+ /**
131
+ * 管理 LLM 会话。
132
+ *
133
+ * 支持新建、切换、列出全部和查看当前会话四种操作。
134
+ *
135
+ * @param action - 操作类型:
136
+ * - 'new':创建新会话
137
+ * - 'switch':切换到指定会话(不存在时自动创建)
138
+ * - 'list':列出所有会话
139
+ * - 'current':查看当前会话信息
140
+ * @param sessionId - 切换到指定会话时的 ID(action 为 'switch' 时必填)
141
+ * @returns 会话操作结果对象
142
+ *
143
+ * @example
144
+ * // 创建新会话
145
+ * const s1 = await sessionManage('new');
146
+ * // 切换到已有会话
147
+ * const s2 = await sessionManage('switch', 'a1b2c3d4');
148
+ * // 列出所有会话
149
+ * const list = await sessionManage('list');
150
+ * // 查看当前会话
151
+ * const cur = await sessionManage('current');
152
+ */
153
+ export declare function sessionManage(action: 'new' | 'switch' | 'list' | 'current', sessionId?: string): Promise<{
154
+ action: "new";
155
+ sessionId: string;
156
+ createdAt: string;
157
+ previousId?: undefined;
158
+ count?: undefined;
159
+ sessions?: undefined;
160
+ session?: undefined;
161
+ } | {
162
+ action: "switch";
163
+ sessionId: string;
164
+ previousId: string | undefined;
165
+ createdAt?: undefined;
166
+ count?: undefined;
167
+ sessions?: undefined;
168
+ session?: undefined;
169
+ } | {
170
+ action: "list";
171
+ count: number;
172
+ sessions: {
173
+ id: string;
174
+ createdAt: string;
175
+ }[];
176
+ sessionId?: undefined;
177
+ createdAt?: undefined;
178
+ previousId?: undefined;
179
+ session?: undefined;
180
+ } | {
181
+ action: "current";
182
+ session: {
183
+ id: string;
184
+ createdAt: string;
185
+ messageCount: number;
186
+ } | null;
187
+ sessionId?: undefined;
188
+ createdAt?: undefined;
189
+ previousId?: undefined;
190
+ count?: undefined;
191
+ sessions?: undefined;
192
+ }>;
193
+ //# sourceMappingURL=command.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"command.d.ts","sourceRoot":"","sources":["../../src/tools/command.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AASH,OAAO,KAAK,gBAAgB,MAAM,0BAA0B,CAAC;AAG7D;;;;;;;;;;;;;GAaG;AACH,wBAAsB,oBAAoB,CACxC,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,EACZ,IAAI,GAAE,UAAU,GAAG,MAAe;;;;;;;;;;;;;UA+BnC;AAED;;;;;;;;;;;;GAYG;AACH,wBAAsB,iBAAiB,CACrC,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,EACZ,IAAI,GAAE,UAAU,GAAG,MAAe;;;;;;;;;;cA2BA,MAAM;kBAAY,MAAM;;;;;;;UAa3D;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,gBAAgB,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,GAAE,UAAU,GAAG,MAAe;;;;;;;;;;;;;;;;;;;;;;;;;;;;;UA8DxF;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAsB,cAAc,CAClC,KAAK,EAAE,MAAM,EACb,KAAK,GAAE,MAAW,EAClB,IAAI,GAAE,UAAU,GAAG,OAAO,GAAG,KAAa,4CAQ3C;AAED;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAsB,aAAa,CACjC,MAAM,EAAE,KAAK,GAAG,QAAQ,GAAG,MAAM,GAAG,SAAS,EAC7C,SAAS,CAAC,EAAE,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkDnB"}
@@ -0,0 +1,263 @@
1
+ /**
2
+ * 命令类工具(Command)
3
+ *
4
+ * 封装报告输出、语义搜索和会话管理等功能。
5
+ * 返回值均为复合结构,包含完整或摘要的内容。
6
+ *
7
+ * @module tools/command
8
+ */
9
+ import { getDatabase } from '../db/index.js';
10
+ import { dailyAnalysisReport, finalReport, } from '../db/schema.js';
11
+ import { eq, and, desc } from 'drizzle-orm';
12
+ import * as poolService from '../services/pool.js';
13
+ import * as embeddingService from '../services/embedding.js';
14
+ import * as sessionService from '../services/session.js';
15
+ /**
16
+ * 输出指定股票指定日期的客观分析报告。
17
+ *
18
+ * @param code - 股票代码
19
+ * @param date - 报告日期 'yyyy-MM-dd'
20
+ * @param mode - 输出模式:
21
+ * - 'overview':仅返回 code、date、summary 摘要字段
22
+ * - 'full'(默认):返回完整报告(含 indicators、signals JSON)
23
+ * @returns 包含 code、date、summary 的报告对象,不存在时返回 null
24
+ *
25
+ * @example
26
+ * const report = await outputAnalysisReport('600519', '2024-06-01', 'full');
27
+ * if (report) console.log(report.summary);
28
+ */
29
+ export async function outputAnalysisReport(code, date, mode = 'full') {
30
+ const db = getDatabase();
31
+ const row = db
32
+ .select()
33
+ .from(dailyAnalysisReport)
34
+ .where(and(eq(dailyAnalysisReport.code, code), eq(dailyAnalysisReport.date, date)))
35
+ .get();
36
+ if (!row)
37
+ return null;
38
+ const base = {
39
+ code: row.code,
40
+ date: row.date,
41
+ summary: row.summary,
42
+ createdAt: row.createdAt,
43
+ };
44
+ if (mode === 'overview')
45
+ return base;
46
+ return {
47
+ ...base,
48
+ id: row.id,
49
+ indicators: row.indicators,
50
+ signals: row.signals,
51
+ };
52
+ }
53
+ /**
54
+ * 输出指定股票指定日期的最终报告。
55
+ *
56
+ * @param code - 股票代码
57
+ * @param date - 报告日期 'yyyy-MM-dd'
58
+ * @param mode - 输出模式:
59
+ * - 'overview':仅返回 code、date、summary、pipelineId 摘要字段
60
+ * - 'full'(默认):返回完整报告(含 fullReport、roleSummary)
61
+ * @returns 包含 code、date 的报告对象,不存在时返回 null
62
+ *
63
+ * @example
64
+ * const report = await outputFinalReport('600519', '2024-06-01', 'overview');
65
+ */
66
+ export async function outputFinalReport(code, date, mode = 'full') {
67
+ const db = getDatabase();
68
+ const row = db
69
+ .select()
70
+ .from(finalReport)
71
+ .where(and(eq(finalReport.code, code), eq(finalReport.date, date)))
72
+ .get();
73
+ if (!row)
74
+ return null;
75
+ const base = {
76
+ code: row.code,
77
+ date: row.date,
78
+ summary: row.summary,
79
+ pipelineId: row.pipelineId,
80
+ createdAt: row.createdAt,
81
+ };
82
+ if (mode === 'overview')
83
+ return base;
84
+ // 尝试解析 roleSummary JSON,失败则返回原始字符串
85
+ let roleSummary = row.roleSummary;
86
+ try {
87
+ roleSummary = JSON.parse(row.roleSummary);
88
+ }
89
+ catch {
90
+ // 保持原始字符串
91
+ }
92
+ return {
93
+ ...base,
94
+ id: row.id,
95
+ fullReport: row.fullReport,
96
+ roleSummary,
97
+ };
98
+ }
99
+ /**
100
+ * 输出指定股池的综合分析报告。
101
+ *
102
+ * @param poolId - 股池 ID
103
+ * @param mode - 输出模式:
104
+ * - 'overview':仅输出股池摘要信息和股票列表
105
+ * - 'full'(默认):输出完整报告(含每只股票的最新分析摘要)
106
+ * @returns 包含 poolId、name 的股池报告对象,股池不存在时返回 null
107
+ *
108
+ * @example
109
+ * const r = await outputPoolReport(1, 'overview');
110
+ */
111
+ export async function outputPoolReport(poolId, mode = 'full') {
112
+ const poolInfo = await poolService.getPoolById(poolId);
113
+ if (!poolInfo)
114
+ return null;
115
+ const stocksInPool = await poolService.getPoolStocks(poolId);
116
+ const db = getDatabase();
117
+ const stockSummaries = await Promise.all(stocksInPool.map(async (s) => {
118
+ const latestAnalysis = db
119
+ .select({
120
+ date: dailyAnalysisReport.date,
121
+ summary: dailyAnalysisReport.summary,
122
+ signals: dailyAnalysisReport.signals,
123
+ })
124
+ .from(dailyAnalysisReport)
125
+ .where(eq(dailyAnalysisReport.code, s.code))
126
+ .orderBy(desc(dailyAnalysisReport.date))
127
+ .limit(1)
128
+ .get();
129
+ let signal = 0;
130
+ if (latestAnalysis?.signals) {
131
+ try {
132
+ const parsed = JSON.parse(latestAnalysis.signals);
133
+ if (parsed.goldenCross)
134
+ signal = 1;
135
+ else if (parsed.deadCross)
136
+ signal = -1;
137
+ }
138
+ catch {
139
+ // ignore
140
+ }
141
+ }
142
+ return {
143
+ code: s.code,
144
+ name: s.name,
145
+ currentPrice: s.currentPrice,
146
+ signal,
147
+ latestAnalysisDate: latestAnalysis?.date || null,
148
+ summary: latestAnalysis?.summary?.slice(0, 200) || null,
149
+ };
150
+ }));
151
+ const base = {
152
+ poolId: poolInfo.id,
153
+ poolName: poolInfo.name,
154
+ poolDesc: poolInfo.desc,
155
+ poolSignal: poolInfo.poolSignal,
156
+ stockCount: stockSummaries.length,
157
+ stocks: stockSummaries,
158
+ };
159
+ if (mode === 'overview') {
160
+ const bullish = stockSummaries.filter((s) => s.signal === 1).length;
161
+ const bearish = stockSummaries.filter((s) => s.signal === -1).length;
162
+ return {
163
+ ...base,
164
+ summary: `股池共 ${base.stockCount} 只股票,看多 ${bullish} 只,看空 ${bearish} 只,中性 ${base.stockCount - bullish - bearish} 只。`,
165
+ };
166
+ }
167
+ return base;
168
+ }
169
+ /**
170
+ * 基于语义相似度搜索历史分析报告。
171
+ *
172
+ * 通过向量嵌入技术,搜索与查询文本语义相似的分析报告或最终报告。
173
+ *
174
+ * @param query - 搜索查询文本
175
+ * @param limit - 最多返回结果数,默认 10
176
+ * @param type - 搜索范围:
177
+ * - 'analysis':仅搜索客观分析报告
178
+ * - 'final':仅搜索最终报告
179
+ * - 'all'(默认):搜索全部类型
180
+ * @returns 搜索结果数组,按相关性降序排列
181
+ *
182
+ * @example
183
+ * const results = await semanticSearch('贵州茅台', 5, 'final');
184
+ * results.forEach(r => console.log(r.code, r.date, r.relevance));
185
+ */
186
+ export async function semanticSearch(query, limit = 10, type = 'all') {
187
+ const searchType = type === 'all' ? undefined : type;
188
+ return embeddingService.searchSimilar({
189
+ query,
190
+ type: searchType,
191
+ limit,
192
+ });
193
+ }
194
+ /**
195
+ * 管理 LLM 会话。
196
+ *
197
+ * 支持新建、切换、列出全部和查看当前会话四种操作。
198
+ *
199
+ * @param action - 操作类型:
200
+ * - 'new':创建新会话
201
+ * - 'switch':切换到指定会话(不存在时自动创建)
202
+ * - 'list':列出所有会话
203
+ * - 'current':查看当前会话信息
204
+ * @param sessionId - 切换到指定会话时的 ID(action 为 'switch' 时必填)
205
+ * @returns 会话操作结果对象
206
+ *
207
+ * @example
208
+ * // 创建新会话
209
+ * const s1 = await sessionManage('new');
210
+ * // 切换到已有会话
211
+ * const s2 = await sessionManage('switch', 'a1b2c3d4');
212
+ * // 列出所有会话
213
+ * const list = await sessionManage('list');
214
+ * // 查看当前会话
215
+ * const cur = await sessionManage('current');
216
+ */
217
+ export async function sessionManage(action, sessionId) {
218
+ switch (action) {
219
+ case 'new': {
220
+ const id = sessionService.createSession();
221
+ return {
222
+ action: 'new',
223
+ sessionId: id,
224
+ createdAt: new Date().toISOString(),
225
+ };
226
+ }
227
+ case 'switch': {
228
+ if (!sessionId) {
229
+ throw new Error('switch 操作需要提供 sessionId 参数');
230
+ }
231
+ const result = sessionService.switchSession(sessionId);
232
+ return {
233
+ action: 'switch',
234
+ sessionId: result.sessionId,
235
+ previousId: result.previousId,
236
+ };
237
+ }
238
+ case 'list': {
239
+ const sessions = sessionService.listSessions();
240
+ return {
241
+ action: 'list',
242
+ count: sessions.length,
243
+ sessions,
244
+ };
245
+ }
246
+ case 'current': {
247
+ const current = sessionService.getCurrentSession();
248
+ return {
249
+ action: 'current',
250
+ session: current
251
+ ? {
252
+ id: current.id,
253
+ createdAt: current.createdAt,
254
+ messageCount: current.messages.length,
255
+ }
256
+ : null,
257
+ };
258
+ }
259
+ default:
260
+ throw new Error(`未知的会话操作: ${action}`);
261
+ }
262
+ }
263
+ //# sourceMappingURL=command.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"command.js","sourceRoot":"","sources":["../../src/tools/command.ts"],"names":[],"mappings":"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"}