tickflow-assist 0.2.11 → 0.2.12

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/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  基于 [OpenClaw](https://openclaw.ai) 的 A 股监控与分析插件。它使用 [TickFlow](https://tickflow.org/auth/register?ref=BUJ54JEDGE) 获取行情与财务数据,结合 LLM 生成技术面、基本面、资讯面的综合判断,并把结果持久化到本地 LanceDB。
4
4
 
5
- 最近更新:`v0.2.11` 优化复盘/告警文本样式,接入 PNG 告警卡发送与临时文件清理,并按 A 股习惯调整涨跌主色。
5
+ 最近更新:`v0.2.12` 调整社区安装清单,允许先安装插件再执行 `configure-openclaw` 写入密钥配置;同时将 `test_alert` 升级为文本 + PNG 告警卡链路测试。
6
6
 
7
7
  ## 安装
8
8
 
@@ -13,6 +13,8 @@ openclaw plugins install tickflow-assist
13
13
  npx -y tickflow-assist configure-openclaw
14
14
  ```
15
15
 
16
+ 安装阶段允许先落插件,再通过第二条命令写入 `tickflowApiKey`、`llmApiKey` 等正式配置。
17
+
16
18
  第二条命令会写入 `~/.openclaw/openclaw.json` 中的 `plugins.entries["tickflow-assist"].config`,并默认执行:
17
19
 
18
20
  - `openclaw plugins enable tickflow-assist`
package/dist/bootstrap.js CHANGED
@@ -152,7 +152,7 @@ export function createAppContext(config, options = {}) {
152
152
  startMonitorTool(monitorService, runtime),
153
153
  stopDailyUpdateTool(dailyUpdateWorker, runtime),
154
154
  stopMonitorTool(monitorService, runtime),
155
- testAlertTool(alertService),
155
+ testAlertTool(alertService, alertMediaService),
156
156
  updateAllTool(dailyUpdateWorker),
157
157
  viewAnalysisTool(analysisViewService),
158
158
  ],
@@ -208,7 +208,7 @@ export function registerPluginCommands(api, tools, app) {
208
208
  },
209
209
  {
210
210
  name: "ta_testalert",
211
- description: "发送一条测试告警,不经过 AI 对话。",
211
+ description: "发送一条文本 + PNG 测试告警,不经过 AI 对话。",
212
212
  requireAuth: true,
213
213
  handler: async () => ({
214
214
  text: await runToolText(testAlert),
@@ -1,5 +1,6 @@
1
1
  import { AlertService } from "../services/alert-service.js";
2
- export declare function testAlertTool(alertService: AlertService): {
2
+ import { AlertMediaService } from "../services/alert-media-service.js";
3
+ export declare function testAlertTool(alertService: AlertService, alertMediaService: AlertMediaService): {
3
4
  name: string;
4
5
  description: string;
5
6
  optional: boolean;
@@ -1,21 +1,101 @@
1
1
  import { formatChinaDateTime } from "../utils/china-time.js";
2
- export function testAlertTool(alertService) {
2
+ export function testAlertTool(alertService, alertMediaService) {
3
3
  return {
4
4
  name: "test_alert",
5
- description: "Send a test alert through the configured OpenClaw alert delivery path.",
5
+ description: "Send a text plus PNG test alert through the configured OpenClaw alert delivery path.",
6
6
  optional: true,
7
7
  async run() {
8
- const ok = await alertService.send(alertService.formatSystemNotification("🧪 TickFlow 测试告警", [
9
- `时间: ${formatChinaDateTime()}`,
10
- "说明: 这是一条手动触发的测试消息,用于验证 channel 投递链路正常。",
11
- ]));
12
- if (ok) {
13
- return "✅ 测试告警发送成功";
8
+ const now = formatChinaDateTime();
9
+ const message = alertService.formatSystemNotification("🧪 TickFlow 测试告警", [
10
+ `时间: ${now}`,
11
+ "说明: 这是一条手动触发的测试消息,用于验证文本与 PNG 告警卡投递链路正常。",
12
+ ]);
13
+ let mediaFile = null;
14
+ try {
15
+ mediaFile = await alertMediaService.writeAlertCard({
16
+ symbol: "000001.SZ",
17
+ ruleName: "test_alert",
18
+ image: buildTestAlertImage(now),
19
+ });
14
20
  }
15
- const detail = alertService.getLastError();
16
- return detail
17
- ? `❌ 测试告警发送失败\n原因: ${detail}`
18
- : "❌ 测试告警发送失败";
21
+ catch (error) {
22
+ const textOnlyResult = await alertService.sendWithResult({ message });
23
+ if (textOnlyResult.ok) {
24
+ return [
25
+ "⚠️ 测试告警文本已发送,但 PNG 生成失败",
26
+ `原因: ${formatErrorMessage(error)}`,
27
+ ].join("\n");
28
+ }
29
+ const detail = textOnlyResult.error ?? alertService.getLastError() ?? "未知错误";
30
+ return [
31
+ "❌ 测试告警发送失败",
32
+ `PNG 生成失败: ${formatErrorMessage(error)}`,
33
+ `文本发送失败: ${detail}`,
34
+ ].join("\n");
35
+ }
36
+ try {
37
+ const result = await alertService.sendWithResult({
38
+ message,
39
+ mediaPath: mediaFile.filePath,
40
+ mediaLocalRoots: mediaFile.mediaLocalRoots,
41
+ filename: mediaFile.filename,
42
+ });
43
+ if (result.ok && result.mediaDelivered) {
44
+ return "✅ 测试告警发送成功(文本 + PNG)";
45
+ }
46
+ if (result.ok) {
47
+ return "⚠️ 测试告警文本已发送,但 PNG 未送达,已回退为纯文本";
48
+ }
49
+ const detail = result.error ?? alertService.getLastError();
50
+ return detail
51
+ ? `❌ 测试告警发送失败\n原因: ${detail}`
52
+ : "❌ 测试告警发送失败";
53
+ }
54
+ finally {
55
+ if (mediaFile) {
56
+ await alertMediaService.removeFile(mediaFile.filePath).catch(() => { });
57
+ }
58
+ }
59
+ },
60
+ };
61
+ }
62
+ function buildTestAlertImage(now) {
63
+ const triggerPrice = 12.18;
64
+ const currentPrice = 12.36;
65
+ return {
66
+ tone: "breakthrough",
67
+ alertLabel: "测试告警",
68
+ name: "平安银行",
69
+ symbol: "000001.SZ",
70
+ timestampLabel: `测试告警 | ${now.slice(0, 16)}`,
71
+ currentPrice,
72
+ triggerPrice,
73
+ changePct: 2.15,
74
+ distancePct: ((currentPrice - triggerPrice) / triggerPrice) * 100,
75
+ costPrice: 11.92,
76
+ profitPct: ((currentPrice - 11.92) / 11.92) * 100,
77
+ note: "用于验证 PNG 告警卡发送、媒体上传与纯文本回退链路。",
78
+ points: [
79
+ { time: "09:30", price: 12.02 },
80
+ { time: "10:00", price: 12.08 },
81
+ { time: "10:30", price: 12.12 },
82
+ { time: "11:30", price: 12.15 },
83
+ { time: "13:00", price: 12.19 },
84
+ { time: "14:00", price: 12.27 },
85
+ { time: "15:00", price: currentPrice },
86
+ ],
87
+ levels: {
88
+ stopLoss: 11.86,
89
+ support: 12.08,
90
+ resistance: 12.30,
91
+ breakthrough: triggerPrice,
92
+ takeProfit: 12.68,
19
93
  },
20
94
  };
21
95
  }
96
+ function formatErrorMessage(error) {
97
+ if (error instanceof Error) {
98
+ return error.message;
99
+ }
100
+ return String(error);
101
+ }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "id": "tickflow-assist",
3
3
  "name": "TickFlow Assist",
4
- "version": "0.2.11",
4
+ "version": "0.2.12",
5
5
  "description": "A-share watchlist analysis, monitoring, and alert delivery powered by TickFlow and OpenClaw.",
6
6
  "skills": [
7
7
  "skills"
@@ -9,7 +9,6 @@
9
9
  "configSchema": {
10
10
  "type": "object",
11
11
  "additionalProperties": false,
12
- "required": ["tickflowApiKey", "llmApiKey"],
13
12
  "properties": {
14
13
  "tickflowApiUrl": {
15
14
  "type": "string",
@@ -19,7 +18,7 @@
19
18
  "tickflowApiKey": {
20
19
  "type": "string",
21
20
  "minLength": 1,
22
- "description": "Required. TickFlow API key used for market and financial data."
21
+ "description": "TickFlow API key used for market and financial data. Required before using the plugin."
23
22
  },
24
23
  "tickflowApiKeyLevel": {
25
24
  "type": "string",
@@ -45,7 +44,7 @@
45
44
  "llmApiKey": {
46
45
  "type": "string",
47
46
  "minLength": 1,
48
- "description": "Required. API key for the analysis model endpoint configured in llmBaseUrl."
47
+ "description": "API key for the analysis model endpoint configured in llmBaseUrl. Required before using analysis features."
49
48
  },
50
49
  "llmModel": {
51
50
  "type": "string",
@@ -114,7 +113,7 @@
114
113
  "uiHints": {
115
114
  "tickflowApiKey": {
116
115
  "label": "TickFlow API Key",
117
- "help": "Required for TickFlow market and financial data.",
116
+ "help": "Required before using TickFlow market and financial data.",
118
117
  "sensitive": true
119
118
  },
120
119
  "tickflowApiKeyLevel": {
@@ -132,7 +131,7 @@
132
131
  },
133
132
  "llmApiKey": {
134
133
  "label": "LLM API Key",
135
- "help": "Required for analysis model requests.",
134
+ "help": "Required before using analysis model requests.",
136
135
  "sensitive": true
137
136
  },
138
137
  "llmModel": {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tickflow-assist",
3
- "version": "0.2.11",
3
+ "version": "0.2.12",
4
4
  "description": "OpenClaw plugin for TickFlow-based A-share analysis, monitoring, and alerting.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -29,7 +29,7 @@
29
29
  "dev": "tsc -p tsconfig.json --watch",
30
30
  "prepack": "npm run build && node ./scripts/prepare-package-assets.mjs",
31
31
  "postpack": "node ./scripts/restore-package-assets.mjs",
32
- "test": "npm run build && node --test dist/plugin-registration.test.js",
32
+ "test": "npm run build && node --test dist/plugin-registration.test.js dist/tools/test-alert.tool.test.js",
33
33
  "community-setup": "node dist/dev/tickflow-assist-cli.js configure-openclaw",
34
34
  "tool": "node dist/dev/run-tool.js",
35
35
  "monitor-loop": "node dist/dev/run-monitor-loop.js",
@@ -83,6 +83,7 @@ TickFlow Assist 常用指令:
83
83
 
84
84
  14. 测试告警
85
85
  `测试告警`
86
+ 会发送一条文本 + PNG 告警卡测试消息
86
87
 
87
88
  15. 查看数据库表
88
89
  `数据库里有哪些表`