chaimi-keep-mcp 3.3.0-beta.8 → 3.3.1-beta.1
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 +10 -0
- package/SKILL.md +66 -50
- package/bin/cli.js +7 -7
- package/package.json +1 -1
- package/server.js +205 -156
package/README.md
CHANGED
|
@@ -89,6 +89,16 @@ export MCP_PROMPT_URL="你的Prompt服务地址"
|
|
|
89
89
|
|
|
90
90
|
## Changelog
|
|
91
91
|
|
|
92
|
+
### v3.3.1-beta.0 (2026-04-27)
|
|
93
|
+
- **优化** 简化工具描述 - save_expense/save_receipt/save_income 描述更简洁,不暴露业务逻辑
|
|
94
|
+
- **优化** 参数类型自动转换 - 支持 CLI 工具的字符串传参自动转为数字
|
|
95
|
+
- **优化** 改进错误提示 - 添加 `hint` 和 `debug` 字段,帮助 Agent 自查参数问题
|
|
96
|
+
- **新增** 参数查看指南 - SKILL.md 添加"六.5 如何查看工具参数"章节
|
|
97
|
+
- **优化** 更新记账流程 - 简化为"4步记账法",更易于 Agent 执行
|
|
98
|
+
|
|
99
|
+
### v3.3.0-beta.8 (2026-04-27)
|
|
100
|
+
- **重要变更** Server 只返回原始数据 - 不再构建 userMessage,由 Agent 使用模板渲染
|
|
101
|
+
|
|
92
102
|
### v3.1.47-beta.5 (2026-04-22)
|
|
93
103
|
- **修复** 输入长度限制 - 添加硬性长度检查,防止超大字符串攻击
|
|
94
104
|
- **修复** 错误信息泄露 - 生产环境只显示友好提示,不暴露内部错误
|
package/SKILL.md
CHANGED
|
@@ -4,8 +4,7 @@ description: >-
|
|
|
4
4
|
柴米AI记账MCP Server,连接微信小程序记账功能。
|
|
5
5
|
TRIGGER: 用户提及"记账/记录/保存"并涉及金额或商品信息。
|
|
6
6
|
DO NOT TRIGGER: 非记账操作,或明确使用其他记账工具时。
|
|
7
|
-
|
|
8
|
-
updated: "2026-04-25"
|
|
7
|
+
updated: "2026-04-27"
|
|
9
8
|
---
|
|
10
9
|
|
|
11
10
|
# 柴米AI记账 Skill
|
|
@@ -122,29 +121,71 @@ chaimi-keep-mcp ⭐ 本Skill
|
|
|
122
121
|
|
|
123
122
|
## 六、快速开始
|
|
124
123
|
|
|
125
|
-
###
|
|
124
|
+
### 4步记账法
|
|
126
125
|
|
|
127
126
|
```
|
|
128
|
-
第1
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
第
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
```
|
|
127
|
+
第1步:读文档
|
|
128
|
+
└─ get_skill() 获取 SKILL.md 规范
|
|
129
|
+
└─ references/response-templates.md 了解回复模板
|
|
130
|
+
|
|
131
|
+
第2步:拿Token
|
|
132
|
+
└─ 文字记账:get_text_parse_prompt() 获取 Token 和解析模板
|
|
133
|
+
└─ 小票记账:get_parse_prompt() 获取 Token 和解析模板
|
|
136
134
|
|
|
137
|
-
|
|
135
|
+
第3步:AI解析
|
|
136
|
+
└─ 按模板解析用户输入,生成结构化数据 + _requestToken
|
|
138
137
|
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
138
|
+
第4步:执行记账
|
|
139
|
+
└─ 调用工具(save_expense/income/receipt,带上 _requestToken)
|
|
140
|
+
└─ 根据 _templateLocation 使用模板渲染美学回复
|
|
141
|
+
```
|
|
142
142
|
|
|
143
143
|
---
|
|
144
144
|
|
|
145
145
|
## 七、回复规范
|
|
146
146
|
|
|
147
|
-
### 7.1
|
|
147
|
+
### 7.1 核心原则
|
|
148
|
+
|
|
149
|
+
**Server 只返回原始数据,Agent 必须使用模板自行渲染回复。**
|
|
150
|
+
|
|
151
|
+
所有工具调用成功后:
|
|
152
|
+
- ❌ 不再返回 `userMessage` 字段
|
|
153
|
+
- ✅ 返回 `_templateLocation` 指向模板文件位置
|
|
154
|
+
- ✅ 返回 `_templateHint` 提示使用哪个模板
|
|
155
|
+
- ✅ 返回 `_templateVariables` 提供模板变量数据
|
|
156
|
+
|
|
157
|
+
### 7.2 模板文件位置
|
|
158
|
+
|
|
159
|
+
**主模板文件**: `references/response-templates.md`
|
|
160
|
+
|
|
161
|
+
**模板文件结构**:
|
|
162
|
+
```
|
|
163
|
+
references/
|
|
164
|
+
└── response-templates.md # 完整回复模板库(包含所有工具的回复模板)
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
### 7.3 各工具对应的回复模板
|
|
168
|
+
|
|
169
|
+
| 工具 | 模板位置 | 模板章节 | 说明 |
|
|
170
|
+
|------|---------|---------|------|
|
|
171
|
+
| `save_expense` | `references/response-templates.md` | 2.1 标准成功模板 | 文字记账成功 |
|
|
172
|
+
| `save_income` | `references/response-templates.md` | 2.1 标准成功模板 | 收入记账成功 |
|
|
173
|
+
| `save_receipt` | `references/response-templates.md` | 2.3 小票记账模板 | 小票记账成功 |
|
|
174
|
+
| `get_expenses` | `references/response-templates.md` | 2.5 查询结果模板 | 消费记录查询 |
|
|
175
|
+
| `get_receipt_list` | `references/response-templates.md` | 2.5 查询结果模板 | 小票列表查询 |
|
|
176
|
+
| `get_statistics` | `references/response-templates.md` | 2.6 统计结果模板 | 消费统计分析 |
|
|
177
|
+
|
|
178
|
+
### 7.4 回复模板使用流程
|
|
179
|
+
|
|
180
|
+
```
|
|
181
|
+
1. 调用工具 → 返回原始数据 + _templateLocation + _templateHint + _templateVariables
|
|
182
|
+
2. 读取 _templateLocation 指定的模板文件
|
|
183
|
+
3. 根据 _templateHint 选择对应模板章节
|
|
184
|
+
4. 使用 _templateVariables 填充模板变量
|
|
185
|
+
5. 渲染最终回复给用户
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
### 7.5 5层视觉结构
|
|
148
189
|
|
|
149
190
|
```
|
|
150
191
|
【第1层:成功标识】✅ 「Agent名称」已帮您记账成功
|
|
@@ -164,7 +205,7 @@ chaimi-keep-mcp ⭐ 本Skill
|
|
|
164
205
|
───────────────
|
|
165
206
|
```
|
|
166
207
|
|
|
167
|
-
### 7.
|
|
208
|
+
### 7.6 标准成功模板
|
|
168
209
|
|
|
169
210
|
```markdown
|
|
170
211
|
✅ 「{agentName}」已帮您记账成功
|
|
@@ -180,40 +221,13 @@ chaimi-keep-mcp ⭐ 本Skill
|
|
|
180
221
|
💡 消费洞察:{洞察内容}(可选)
|
|
181
222
|
|
|
182
223
|
───────────────
|
|
183
|
-
🎉 {
|
|
184
|
-
柴米AI记账
|
|
185
|
-
chaimi-keep-mcp v{版本号}
|
|
186
|
-
───────────────
|
|
187
|
-
```
|
|
188
|
-
|
|
189
|
-
### 7.3 极简模板(连续记账)
|
|
190
|
-
|
|
191
|
-
```markdown
|
|
192
|
-
✅ 已记录:{商品名} ¥{金额} · {分类}
|
|
193
|
-
{正能量祝福语}
|
|
194
|
-
```
|
|
195
|
-
|
|
196
|
-
### 7.4 高金额模板(>1000元)
|
|
197
|
-
|
|
198
|
-
```markdown
|
|
199
|
-
⚠️ 大额消费确认
|
|
200
|
-
═══════════════
|
|
201
|
-
💰 金额:¥{金额}
|
|
202
|
-
📦 商品:{商品名}
|
|
203
|
-
🕐 时间:{日期}
|
|
204
|
-
|
|
205
|
-
✅ 已确认录入「柴米AI记账」
|
|
206
|
-
|
|
207
|
-
💡 消费洞察:{洞察内容}(可选)
|
|
208
|
-
|
|
209
|
-
───────────────
|
|
210
|
-
💡 {消费建议}
|
|
224
|
+
🎉 {正能量情绪词}!
|
|
211
225
|
柴米AI记账
|
|
212
226
|
chaimi-keep-mcp v{版本号}
|
|
213
227
|
───────────────
|
|
214
228
|
```
|
|
215
229
|
|
|
216
|
-
### 7.
|
|
230
|
+
### 7.7 模板变量说明
|
|
217
231
|
|
|
218
232
|
| 变量 | 说明 | 示例 |
|
|
219
233
|
|:-----|:-----|:-----|
|
|
@@ -224,10 +238,12 @@ chaimi-keep-mcp ⭐ 本Skill
|
|
|
224
238
|
| {商家} | 商家名称(可选) | 麦当劳 |
|
|
225
239
|
| {日期时间} | 格式化时间 | 2026-04-24 12:30 |
|
|
226
240
|
| {洞察内容} | 消费洞察建议(可选) | 本月餐饮支出占比30%,建议控制 |
|
|
227
|
-
| {
|
|
241
|
+
| {正能量情绪词} | 分类对应正能量祝福语 | 美食为梦想充电,继续向前冲!🍚 |
|
|
228
242
|
| {版本号} | MCP版本 | 3.2.0 |
|
|
229
243
|
|
|
230
|
-
|
|
244
|
+
**详细正能量情绪词库和完整模板** → 见 references/response-templates.md
|
|
245
|
+
|
|
246
|
+
**历史变更记录** → 见 CHANGELOG.md
|
|
231
247
|
|
|
232
248
|
---
|
|
233
249
|
|
|
@@ -269,6 +285,6 @@ chaimi-keep-mcp ⭐ 本Skill
|
|
|
269
285
|
|
|
270
286
|
---
|
|
271
287
|
|
|
272
|
-
|
|
273
|
-
**最后更新:2026-04-
|
|
288
|
+
|
|
289
|
+
**最后更新:2026-04-27**
|
|
274
290
|
**Status:生产就绪**
|
package/bin/cli.js
CHANGED
|
@@ -293,13 +293,13 @@ function configureAllAgents() {
|
|
|
293
293
|
* 注意:使用 console.error,避免污染 stdout(MCP 协议通信使用 stdout)
|
|
294
294
|
*/
|
|
295
295
|
function showWelcome() {
|
|
296
|
-
console.error('
|
|
297
|
-
console.error('║
|
|
298
|
-
console.error(`║
|
|
299
|
-
console.error('║
|
|
300
|
-
console.error('║ 支持: OpenClaw | WorkBuddy | Claude | Cursor
|
|
301
|
-
console.error('║
|
|
302
|
-
console.error('
|
|
296
|
+
console.error('╔══════════════════════════════════════════════════════════════════════════════════╗');
|
|
297
|
+
console.error('║ ║');
|
|
298
|
+
console.error(`║ 柴米记账 MCP Server v${CURRENT_VERSION} ║`);
|
|
299
|
+
console.error('║ ║');
|
|
300
|
+
console.error('║ 支持: OpenClaw|hermes | WorkBuddy等国产小龙虾 | Claude | Cursor等支持 mcp的agent ║');
|
|
301
|
+
console.error('║ ║');
|
|
302
|
+
console.error('╚══════════════════════════════════════════════════════════════════════════════════╝');
|
|
303
303
|
console.error('');
|
|
304
304
|
}
|
|
305
305
|
|
package/package.json
CHANGED
package/server.js
CHANGED
|
@@ -23,9 +23,18 @@ const os = require('os');
|
|
|
23
23
|
const fs = require('fs');
|
|
24
24
|
const crypto = require('crypto');
|
|
25
25
|
|
|
26
|
-
//
|
|
27
|
-
|
|
28
|
-
|
|
26
|
+
// 读取版本文件获取版本号
|
|
27
|
+
function getVersion() {
|
|
28
|
+
try {
|
|
29
|
+
const verFilePath = path.join(__dirname, 'VERSION');
|
|
30
|
+
return fs.readFileSync(verFilePath, 'utf8').trim();
|
|
31
|
+
} catch (e) {
|
|
32
|
+
// 如果版本文件不存在,从 package.json 兜底
|
|
33
|
+
const pkgJson = JSON.parse(fs.readFileSync(path.join(__dirname, 'package.json'), 'utf8'));
|
|
34
|
+
return pkgJson.version;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
const MCP_VERSION = getVersion();
|
|
29
38
|
|
|
30
39
|
// 导入 OAuth 模块
|
|
31
40
|
const { OAuthManager, FileTokenStorage } = require('./oauth.js');
|
|
@@ -244,7 +253,7 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
|
244
253
|
},
|
|
245
254
|
{
|
|
246
255
|
name: 'save_expense',
|
|
247
|
-
description: '
|
|
256
|
+
description: '【强制验证Token】保存单商品消费记录。前置要求:先调用 get_skill 和 get_text_parse_prompt。字段列表见 get_text_parse_prompt 返回的模板。',
|
|
248
257
|
inputSchema: {
|
|
249
258
|
type: 'object',
|
|
250
259
|
properties: {
|
|
@@ -266,7 +275,7 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
|
266
275
|
},
|
|
267
276
|
{
|
|
268
277
|
name: 'save_receipt',
|
|
269
|
-
description: '
|
|
278
|
+
description: '【强制验证Token】【必须上传图片】保存购物小票/发票/收据图片。⚠️ 注意:必须是图片才能使用此工具记账,文字描述请用 save_expense。前置要求:先调用 get_skill 和 get_parse_prompt。items为商品数组,字段列表见 get_parse_prompt 返回的模板.',
|
|
270
279
|
inputSchema: {
|
|
271
280
|
type: 'object',
|
|
272
281
|
properties: {
|
|
@@ -309,7 +318,7 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
|
309
318
|
},
|
|
310
319
|
{
|
|
311
320
|
name: 'get_expenses',
|
|
312
|
-
description: '查询消费记录(支持周/月周期)。支持按周/月或日期范围筛选,可查看分类、商家、来源等多维度数据。新功能:新增 period
|
|
321
|
+
description: '查询消费记录(支持周/月周期)。支持按周/月或日期范围筛选,可查看分类、商家、来源等多维度数据。新功能:新增 period 参数,以及消费模式分析(高频商家、消费时间等)。返回格式:本工具只返回原始数据,不返回格式化消息。Agent必须使用get_skill获取SKILL.md中的"七、回复规范",再读取references/response-templates.md中的模板自行渲染回复。',
|
|
313
322
|
inputSchema: {
|
|
314
323
|
type: 'object',
|
|
315
324
|
properties: {
|
|
@@ -330,7 +339,7 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
|
330
339
|
},
|
|
331
340
|
{
|
|
332
341
|
name: 'get_receipt_list',
|
|
333
|
-
description: '
|
|
342
|
+
description: '获取小票列表。支持按日期范围、商家、金额等多维度筛选。返回格式:本工具只返回原始数据,不返回格式化消息。Agent必须使用get_skill获取SKILL.md中的"七、回复规范",再读取references/response-templates.md中的模板自行渲染回复。',
|
|
334
343
|
inputSchema: {
|
|
335
344
|
type: 'object',
|
|
336
345
|
properties: {
|
|
@@ -347,7 +356,7 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
|
347
356
|
},
|
|
348
357
|
{
|
|
349
358
|
name: 'get_statistics',
|
|
350
|
-
description: '获取消费统计(支持周/月周期)。支持按周/月或日期范围统计,可查看分类占比、消费趋势等。新功能:新增 period 参数(this_week、last_week、this_month、last_month),以及 insights
|
|
359
|
+
description: '获取消费统计(支持周/月周期)。支持按周/月或日期范围统计,可查看分类占比、消费趋势等。新功能:新增 period 参数(this_week、last_week、this_month、last_month),以及 insights 洞察数据。返回格式:本工具只返回原始数据,不返回格式化消息。Agent必须使用get_skill获取SKILL.md中的"七、回复规范",再读取references/response-templates.md中的模板自行渲染回复。',
|
|
351
360
|
inputSchema: {
|
|
352
361
|
type: 'object',
|
|
353
362
|
properties: {
|
|
@@ -365,7 +374,7 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
|
365
374
|
},
|
|
366
375
|
{
|
|
367
376
|
name: 'get_insights',
|
|
368
|
-
description: '【新功能】获取消费洞察线索(包含趋势、模式、健康、优化建议)。纯云端计算,零AI成本!返回洞察线索,供 Agent
|
|
377
|
+
description: '【新功能】获取消费洞察线索(包含趋势、模式、健康、优化建议)。纯云端计算,零AI成本!返回洞察线索,供 Agent 结合用户大模型进行深度分析。返回格式:本工具只返回原始数据,不返回格式化消息。Agent必须使用get_skill获取SKILL.md中的"七、回复规范",再读取references/response-templates.md中的模板自行渲染回复。',
|
|
369
378
|
inputSchema: {
|
|
370
379
|
type: 'object',
|
|
371
380
|
properties: {
|
|
@@ -376,7 +385,7 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
|
376
385
|
},
|
|
377
386
|
{
|
|
378
387
|
name: 'export_data',
|
|
379
|
-
description: '【新功能】导出完整的消费数据,供 Agent 深度分析(零AI
|
|
388
|
+
description: '【新功能】导出完整的消费数据,供 Agent 深度分析(零AI成本!)。支持导出完整的消费记录和小票数据,然后在用户侧使用大模型进行深度分析。返回格式:本工具只返回原始数据,不返回格式化消息。Agent必须使用get_skill获取SKILL.md中的"七、回复规范",再读取references/response-templates.md中的模板自行渲染回复。',
|
|
380
389
|
inputSchema: {
|
|
381
390
|
type: 'object',
|
|
382
391
|
properties: {
|
|
@@ -390,7 +399,7 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
|
390
399
|
},
|
|
391
400
|
{
|
|
392
401
|
name: 'save_income',
|
|
393
|
-
description: '
|
|
402
|
+
description: '【强制验证Token】保存收入记录。前置要求:先调用 get_skill 和 get_text_parse_prompt。字段列表见 get_text_parse_prompt 返回的模板.',
|
|
394
403
|
inputSchema: {
|
|
395
404
|
type: 'object',
|
|
396
405
|
properties: {
|
|
@@ -409,7 +418,7 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
|
409
418
|
},
|
|
410
419
|
{
|
|
411
420
|
name: 'get_text_parse_prompt',
|
|
412
|
-
description: '
|
|
421
|
+
description: '【不调用100%失败】获取文字记账解析的Prompt模板和requestToken。⚠️ 文字/语音记账必须先调用此工具获取Token,AI解析时必须返回_requestToken字段,否则save_expense/save_income会报MISSING_TOKEN错误!',
|
|
413
422
|
inputSchema: {
|
|
414
423
|
type: 'object',
|
|
415
424
|
properties: {
|
|
@@ -420,7 +429,7 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
|
420
429
|
},
|
|
421
430
|
{
|
|
422
431
|
name: 'get_parse_prompt',
|
|
423
|
-
description: '
|
|
432
|
+
description: '【不调用100%失败】获取小票图片解析的Prompt模板和requestToken。⚠️ 小票记账必须先调用此工具获取Token,AI解析时必须返回_requestToken字段,否则save_receipt会报MISSING_TOKEN错误!',
|
|
424
433
|
inputSchema: {
|
|
425
434
|
type: 'object',
|
|
426
435
|
properties: {
|
|
@@ -430,7 +439,7 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
|
430
439
|
},
|
|
431
440
|
{
|
|
432
441
|
name: 'submit_feedback',
|
|
433
|
-
description: '提交反馈、建议或问题报告。当用户遇到记账问题、有功能建议或发现异常时,可使用此工具提交反馈。反馈类型包括:bug(问题报告)、feature(功能建议)、improvement(优化建议)、other(其他)。提交成功后会返回反馈编号,可用于查询处理进度。注意:反馈内容不要超过150
|
|
442
|
+
description: '提交反馈、建议或问题报告。当用户遇到记账问题、有功能建议或发现异常时,可使用此工具提交反馈。反馈类型包括:bug(问题报告)、feature(功能建议)、improvement(优化建议)、other(其他)。提交成功后会返回反馈编号,可用于查询处理进度。注意:反馈内容不要超过150个字符,超过部分会被截断。返回格式:本工具只返回原始数据,不返回格式化消息。Agent必须使用get_skill获取SKILL.md中的"七、回复规范",再读取references/response-templates.md中的模板自行渲染回复。',
|
|
434
443
|
inputSchema: {
|
|
435
444
|
type: 'object',
|
|
436
445
|
properties: {
|
|
@@ -478,9 +487,7 @@ async function getToken() {
|
|
|
478
487
|
const existingToken = await oauthManager.tokenStorage.load();
|
|
479
488
|
if (existingToken && existingToken.accessToken && existingToken.expiresAt) {
|
|
480
489
|
const expiresAt = new Date(existingToken.expiresAt).getTime();
|
|
481
|
-
|
|
482
|
-
const threshold = now + 5 * 60 * 1000;
|
|
483
|
-
if (expiresAt > threshold) {
|
|
490
|
+
if (expiresAt > Date.now() + 5 * 60 * 1000) {
|
|
484
491
|
// Token 有效,直接使用
|
|
485
492
|
cachedToken = existingToken.accessToken;
|
|
486
493
|
tokenExpireTime = expiresAt;
|
|
@@ -886,8 +893,41 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
886
893
|
}
|
|
887
894
|
}
|
|
888
895
|
|
|
896
|
+
// 【新增】参数类型自动转换(兼容 CLI 工具的字符串传参)
|
|
897
|
+
function autoConvertTypes(toolName, args) {
|
|
898
|
+
const numberFields = {
|
|
899
|
+
'save_expense': ['amount', 'date'],
|
|
900
|
+
'save_receipt': ['totalAmount', 'actualAmount', 'originalAmount', 'discountAmount', 'date'],
|
|
901
|
+
'save_income': ['amount', 'date'],
|
|
902
|
+
};
|
|
903
|
+
|
|
904
|
+
const fields = numberFields[toolName] || [];
|
|
905
|
+
for (const field of fields) {
|
|
906
|
+
if (field in args && typeof args[field] !== 'number') {
|
|
907
|
+
const parsed = parseFloat(args[field]);
|
|
908
|
+
if (!isNaN(parsed)) {
|
|
909
|
+
console.error(`[TypeConvert] ${field}: "${args[field]}" → ${parsed}`);
|
|
910
|
+
args[field] = parsed;
|
|
911
|
+
}
|
|
912
|
+
}
|
|
913
|
+
}
|
|
914
|
+
|
|
915
|
+
// 转换 items 数组中的数字字段
|
|
916
|
+
if (args.items && Array.isArray(args.items)) {
|
|
917
|
+
args.items.forEach(item => {
|
|
918
|
+
['amount', 'price', 'quantity'].forEach(field => {
|
|
919
|
+
if (field in item && typeof item[field] !== 'number') {
|
|
920
|
+
const parsed = parseFloat(item[field]);
|
|
921
|
+
if (!isNaN(parsed)) item[field] = parsed;
|
|
922
|
+
}
|
|
923
|
+
});
|
|
924
|
+
});
|
|
925
|
+
}
|
|
926
|
+
}
|
|
927
|
+
|
|
928
|
+
autoConvertTypes(name, processedArgs);
|
|
929
|
+
|
|
889
930
|
let result;
|
|
890
|
-
let userMessage;
|
|
891
931
|
|
|
892
932
|
switch (name) {
|
|
893
933
|
case 'get_skill': {
|
|
@@ -931,8 +971,14 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
931
971
|
if (missingFields.length > 0) {
|
|
932
972
|
result = {
|
|
933
973
|
success: false,
|
|
934
|
-
error: `必填字段缺失:${missingFields.join(', ')}
|
|
935
|
-
code: 400
|
|
974
|
+
error: `必填字段缺失:${missingFields.join(', ')}`,
|
|
975
|
+
code: 400,
|
|
976
|
+
hint: '解决方法:1.查看 SKILL.md 中"六.5 如何查看工具参数" 2.运行 mcporter list 柴米记账 --schema 查看完整参数结构',
|
|
977
|
+
debug: {
|
|
978
|
+
missing: missingFields,
|
|
979
|
+
received: Object.keys(processedArgs),
|
|
980
|
+
docs: '调用 get_skill() 获取详细使用指南'
|
|
981
|
+
}
|
|
936
982
|
};
|
|
937
983
|
userMessage = `❌ 记账失败\n\n错误:缺少必填字段:${missingFields.join(', ')}\n\n💡 解决方案:\n1. 请检查是否从用户输入中提取了所有信息\n2. 确保传递以下字段:name(商品名)、amount(金额)、category(分类)、rawInput(原始输入)\n3. 参考 SKILL.md 中的"调用前检查清单"`;
|
|
938
984
|
break;
|
|
@@ -995,17 +1041,20 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
995
1041
|
achievementsText = '\n\n🎉 成就解锁:' + result.newlyUnlocked.map(a => `${a.icon} ${a.title}(+${a.points}分)`).join(';');
|
|
996
1042
|
}
|
|
997
1043
|
|
|
998
|
-
//
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1044
|
+
// 【新增】返回模板位置信息(Server只返回原始数据,Agent使用模板渲染)
|
|
1045
|
+
result._templateLocation = 'references/response-templates.md';
|
|
1046
|
+
result._templateHint = '请使用references/response-templates.md中的2.1标准成功模板渲染回复';
|
|
1047
|
+
result._templateVariables = {
|
|
1048
|
+
agentName: await getAgentName(),
|
|
1049
|
+
商品名: displayName,
|
|
1050
|
+
商家: displayStore || '',
|
|
1051
|
+
金额: displayAmount,
|
|
1052
|
+
分类: result.data?.categoryName || displayCategory,
|
|
1053
|
+
日期: result.data?.date ? new Date(result.data.date).toLocaleDateString('zh-CN') : new Date().toLocaleDateString('zh-CN'),
|
|
1054
|
+
正能量祝福语: friendlyEnding,
|
|
1055
|
+
insightsText,
|
|
1056
|
+
achievementsText
|
|
1057
|
+
};
|
|
1009
1058
|
}
|
|
1010
1059
|
break;
|
|
1011
1060
|
}
|
|
@@ -1024,13 +1073,19 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
1024
1073
|
if (missingFields.length > 0) {
|
|
1025
1074
|
result = {
|
|
1026
1075
|
success: false,
|
|
1027
|
-
error: `必填字段缺失:${missingFields.join(', ')}
|
|
1028
|
-
code: 400
|
|
1076
|
+
error: `必填字段缺失:${missingFields.join(', ')}`,
|
|
1077
|
+
code: 400,
|
|
1078
|
+
hint: '解决方法:1.查看 SKILL.md 中"六.5 如何查看工具参数" 2.运行 mcporter list 柴米记账 --schema 查看完整参数结构',
|
|
1079
|
+
debug: {
|
|
1080
|
+
missing: missingFields,
|
|
1081
|
+
received: Object.keys(processedArgs),
|
|
1082
|
+
docs: '调用 get_skill() 获取详细使用指南'
|
|
1083
|
+
}
|
|
1029
1084
|
};
|
|
1030
|
-
userMessage = `❌ 保存失败\n\n错误:缺少必填字段:${missingFields.join(', ')}\n\n💡 解决方案:\n1. 请检查是否从 get_parse_prompt 的解析结果中提取了所有信息\n2. 确保传递以下字段:store、totalAmount、actualAmount、originalAmount、discountAmount、storeCategory、storeSubCategory\n3. 参考 SKILL.md
|
|
1085
|
+
userMessage = `❌ 保存失败\n\n错误:缺少必填字段:${missingFields.join(', ')}\n\n💡 解决方案:\n1. 请检查是否从 get_parse_prompt 的解析结果中提取了所有信息\n2. 确保传递以下字段:store、totalAmount、actualAmount、originalAmount、discountAmount、storeCategory、storeSubCategory\n3. 参考 SKILL.md 中的小票字段核对清单`;
|
|
1031
1086
|
break;
|
|
1032
1087
|
}
|
|
1033
|
-
|
|
1088
|
+
|
|
1034
1089
|
// 数值校验
|
|
1035
1090
|
const amountFields = ['totalAmount', 'actualAmount', 'originalAmount'];
|
|
1036
1091
|
for (const field of amountFields) {
|
|
@@ -1240,16 +1295,21 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
1240
1295
|
achievementsText = '\n\n🎉 成就解锁:' + result.newlyUnlocked.map(a => `${a.icon} ${a.title}(+${a.points}分)`).join(';');
|
|
1241
1296
|
}
|
|
1242
1297
|
|
|
1243
|
-
//
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1298
|
+
// 【新增】返回模板位置信息(Server只返回原始数据,Agent使用模板渲染)
|
|
1299
|
+
result._templateLocation = 'references/response-templates.md';
|
|
1300
|
+
result._templateHint = '请使用references/response-templates.md中的2.3小票记账模板渲染回复';
|
|
1301
|
+
result._templateVariables = {
|
|
1302
|
+
agentName: await getAgentName(),
|
|
1303
|
+
store: storeName,
|
|
1304
|
+
totalAmount: totalAmount,
|
|
1305
|
+
category: result.data?.storeCategory || category,
|
|
1306
|
+
itemCount: itemCount,
|
|
1307
|
+
date: result.data?.date ? new Date(result.data.date).toLocaleDateString('zh-CN') : new Date().toLocaleDateString('zh-CN'),
|
|
1308
|
+
正能量祝福语: friendlyEnding,
|
|
1309
|
+
insightsText,
|
|
1310
|
+
achievementsText,
|
|
1311
|
+
items: processedArgs.items
|
|
1312
|
+
};
|
|
1253
1313
|
}
|
|
1254
1314
|
break;
|
|
1255
1315
|
}
|
|
@@ -1265,33 +1325,14 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
1265
1325
|
const items = result.data?.items || [];
|
|
1266
1326
|
const patterns = result.data?.patterns || {};
|
|
1267
1327
|
|
|
1268
|
-
//
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
|
|
1276
|
-
}
|
|
1277
|
-
|
|
1278
|
-
// 消费时间模式
|
|
1279
|
-
if (patterns.timePattern) {
|
|
1280
|
-
summary += `⏰ 消费高峰:${patterns.timePattern.peakTime}\n`;
|
|
1281
|
-
if (patterns.timePattern.lateNightCount > 0) {
|
|
1282
|
-
summary += `🌙 深夜消费:${patterns.timePattern.lateNightCount}次\n`;
|
|
1283
|
-
}
|
|
1284
|
-
}
|
|
1285
|
-
|
|
1286
|
-
// 异常消费
|
|
1287
|
-
if (patterns.unusualItems && patterns.unusualItems.length > 0) {
|
|
1288
|
-
const topUnusual = patterns.unusualItems[0];
|
|
1289
|
-
summary += `💡 大额消费:${topUnusual.name} ¥${topUnusual.amount}\n`;
|
|
1290
|
-
}
|
|
1291
|
-
|
|
1292
|
-
summary += `\n💡 提示:完整数据(含每笔明细、flags标记)请查看下方 JSON 数据`;
|
|
1293
|
-
|
|
1294
|
-
userMessage = summary;
|
|
1328
|
+
// 【新增】返回模板位置信息(Server只返回原始数据,Agent使用模板渲染)
|
|
1329
|
+
result._templateLocation = 'references/response-templates.md';
|
|
1330
|
+
result._templateHint = '请使用references/response-templates.md中的2.5查询结果模板渲染回复';
|
|
1331
|
+
result._templateVariables = {
|
|
1332
|
+
total: total,
|
|
1333
|
+
items: items,
|
|
1334
|
+
patterns: patterns
|
|
1335
|
+
};
|
|
1295
1336
|
}
|
|
1296
1337
|
break;
|
|
1297
1338
|
}
|
|
@@ -1304,42 +1345,18 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
1304
1345
|
if (result.success) {
|
|
1305
1346
|
const data = result.data || {};
|
|
1306
1347
|
|
|
1307
|
-
//
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
// 预算进度
|
|
1320
|
-
if (data.budget) {
|
|
1321
|
-
summary += `🎯 预算:已用¥${data.budget.used}/¥${data.budget.total}(${data.budget.progress}%)\n`;
|
|
1322
|
-
}
|
|
1323
|
-
|
|
1324
|
-
// Top 3 分类
|
|
1325
|
-
if (data.categories && data.categories.length > 0) {
|
|
1326
|
-
summary += `\n📂 消费分类 Top3:\n`;
|
|
1327
|
-
data.categories.slice(0, 3).forEach((cat, idx) => {
|
|
1328
|
-
summary += ` ${idx + 1}. ${cat.category}:¥${cat.amount}(${cat.percentage}%)\n`;
|
|
1329
|
-
});
|
|
1330
|
-
}
|
|
1331
|
-
|
|
1332
|
-
// 洞察摘要
|
|
1333
|
-
if (data.insights && data.insights.length > 0) {
|
|
1334
|
-
summary += `\n💡 洞察线索(${data.insights.length}条):\n`;
|
|
1335
|
-
data.insights.slice(0, 3).forEach(insight => {
|
|
1336
|
-
summary += ` ${insight.emoji || '•'} ${insight.title}:${insight.message}\n`;
|
|
1337
|
-
});
|
|
1338
|
-
}
|
|
1339
|
-
|
|
1340
|
-
summary += `\n💡 提示:完整数据(含每日统计、所有洞察)请查看下方 JSON 数据`;
|
|
1341
|
-
|
|
1342
|
-
userMessage = summary;
|
|
1348
|
+
// 【新增】返回模板位置信息(Server只返回原始数据,Agent使用模板渲染)
|
|
1349
|
+
result._templateLocation = 'references/response-templates.md';
|
|
1350
|
+
result._templateHint = '请使用references/response-templates.md中的2.6统计结果模板渲染回复';
|
|
1351
|
+
result._templateVariables = {
|
|
1352
|
+
period: data.periodDisplay || data.period || '未知',
|
|
1353
|
+
totalAmount: data.totalAmount || 0,
|
|
1354
|
+
totalCount: data.totalCount || 0,
|
|
1355
|
+
compare: data.compare,
|
|
1356
|
+
budget: data.budget,
|
|
1357
|
+
categories: data.categories,
|
|
1358
|
+
insights: data.insights
|
|
1359
|
+
};
|
|
1343
1360
|
}
|
|
1344
1361
|
break;
|
|
1345
1362
|
}
|
|
@@ -1383,9 +1400,12 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
1383
1400
|
}
|
|
1384
1401
|
}
|
|
1385
1402
|
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
1403
|
+
// 【新增】返回模板位置信息(Server只返回原始数据,Agent使用模板渲染)
|
|
1404
|
+
result._templateLocation = 'references/response-templates.md';
|
|
1405
|
+
result._templateHint = '请使用references/response-templates.md中的2.6智能洞察模板渲染回复';
|
|
1406
|
+
result._templateVariables = {
|
|
1407
|
+
insights: insights
|
|
1408
|
+
};
|
|
1389
1409
|
}
|
|
1390
1410
|
break;
|
|
1391
1411
|
}
|
|
@@ -1401,15 +1421,14 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
1401
1421
|
const totalAmount = summary.totalAmount || 0;
|
|
1402
1422
|
const periodDisplay = result.data?.periodDisplay || '';
|
|
1403
1423
|
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
|
|
1410
|
-
|
|
1411
|
-
|
|
1412
|
-
userMessage = summaryText;
|
|
1424
|
+
// 【新增】返回模板位置信息(Server只返回原始数据,Agent使用模板渲染)
|
|
1425
|
+
result._templateLocation = 'references/response-templates.md';
|
|
1426
|
+
result._templateHint = '请使用references/response-templates.md中的模板渲染回复';
|
|
1427
|
+
result._templateVariables = {
|
|
1428
|
+
period: periodDisplay,
|
|
1429
|
+
totalRecords: totalRecords,
|
|
1430
|
+
totalAmount: totalAmount
|
|
1431
|
+
};
|
|
1413
1432
|
}
|
|
1414
1433
|
break;
|
|
1415
1434
|
}
|
|
@@ -1428,8 +1447,14 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
1428
1447
|
if (missingFields.length > 0) {
|
|
1429
1448
|
result = {
|
|
1430
1449
|
success: false,
|
|
1431
|
-
error: `必填字段缺失:${missingFields.join(', ')}
|
|
1432
|
-
code: 400
|
|
1450
|
+
error: `必填字段缺失:${missingFields.join(', ')}`,
|
|
1451
|
+
code: 400,
|
|
1452
|
+
hint: '解决方法:1.查看 SKILL.md 中"六.5 如何查看工具参数" 2.运行 mcporter list 柴米记账 --schema 查看完整参数结构',
|
|
1453
|
+
debug: {
|
|
1454
|
+
missing: missingFields,
|
|
1455
|
+
received: Object.keys(processedArgs),
|
|
1456
|
+
docs: '调用 get_skill() 获取详细使用指南'
|
|
1457
|
+
}
|
|
1433
1458
|
};
|
|
1434
1459
|
userMessage = `❌ 收入记录失败\n\n错误:缺少必填字段:${missingFields.join(', ')}\n\n💡 解决方案:\n1. 请检查是否从用户输入中提取了所有信息\n2. 确保传递以下字段:name(收入来源)、amount(金额)、category(分类)、date(日期)、rawInput(原始输入)\n3. 参考 SKILL.md 中的"调用前检查清单"`;
|
|
1435
1460
|
break;
|
|
@@ -1468,14 +1493,19 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
1468
1493
|
const displayAmount = processedArgs.amount || 0;
|
|
1469
1494
|
const displayCategory = processedArgs.category || '其他';
|
|
1470
1495
|
const displayStore = processedArgs.store || '';
|
|
1471
|
-
const displayStoreText = displayStore ? `【${displayStore}】` : '';
|
|
1472
1496
|
|
|
1473
|
-
//
|
|
1474
|
-
|
|
1475
|
-
|
|
1476
|
-
|
|
1477
|
-
|
|
1478
|
-
|
|
1497
|
+
// 【新增】返回模板位置信息(Server只返回原始数据,Agent使用模板渲染)
|
|
1498
|
+
result._templateLocation = 'references/response-templates.md';
|
|
1499
|
+
result._templateHint = '请使用references/response-templates.md中的2.1标准成功模板渲染回复';
|
|
1500
|
+
result._templateVariables = {
|
|
1501
|
+
agentName: await getAgentName(),
|
|
1502
|
+
商品名: displayName,
|
|
1503
|
+
商家: displayStore,
|
|
1504
|
+
金额: displayAmount,
|
|
1505
|
+
分类: result.data?.categoryName || displayCategory,
|
|
1506
|
+
日期: result.data?.date ? new Date(result.data.date).toLocaleDateString('zh-CN') : new Date().toLocaleDateString('zh-CN'),
|
|
1507
|
+
正能量祝福语: '入账顺利!💰'
|
|
1508
|
+
};
|
|
1479
1509
|
}
|
|
1480
1510
|
break;
|
|
1481
1511
|
}
|
|
@@ -1493,13 +1523,19 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
1493
1523
|
systemPrompt: promptResult.data.systemPrompt,
|
|
1494
1524
|
userPromptTemplate: promptResult.data.userPromptTemplate,
|
|
1495
1525
|
examples: promptResult.data.examples,
|
|
1496
|
-
|
|
1526
|
+
requestToken: promptResult.data.requestToken,
|
|
1527
|
+
instructions: '请将 systemPrompt 作为 system message,把小票图片作为 user message,调用你的大模型进行解析。解析完成后,调用 save_receipt 工具保存结果。⚠️ 注意:AI解析结果必须包含 _requestToken 字段!'
|
|
1497
1528
|
}
|
|
1498
1529
|
};
|
|
1499
|
-
|
|
1530
|
+
// 【新增】返回模板位置信息(Server只返回原始数据,Agent使用模板渲染)
|
|
1531
|
+
result._templateLocation = 'references/response-templates.md';
|
|
1532
|
+
result._templateHint = '请使用references/response-templates.md中的2.1标准成功模板渲染回复';
|
|
1533
|
+
result._templateVariables = {
|
|
1534
|
+
version: promptResult.data.version,
|
|
1535
|
+
examples: promptResult.data.examples
|
|
1536
|
+
};
|
|
1500
1537
|
} else {
|
|
1501
1538
|
result = { success: false, error: promptResult.error };
|
|
1502
|
-
userMessage = `❌ 获取Prompt失败:${promptResult.error}`;
|
|
1503
1539
|
}
|
|
1504
1540
|
break;
|
|
1505
1541
|
}
|
|
@@ -1515,13 +1551,19 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
1515
1551
|
prompt: promptResult.data.prompt,
|
|
1516
1552
|
currentDate: promptResult.data.currentDate,
|
|
1517
1553
|
currentTime: promptResult.data.currentTime,
|
|
1554
|
+
requestToken: promptResult.data.requestToken,
|
|
1518
1555
|
instructions: promptResult.data.instructions
|
|
1519
1556
|
}
|
|
1520
1557
|
};
|
|
1521
|
-
|
|
1558
|
+
// 【新增】返回模板位置信息(Server只返回原始数据,Agent使用模板渲染)
|
|
1559
|
+
result._templateLocation = 'references/response-templates.md';
|
|
1560
|
+
result._templateHint = '请使用references/response-templates.md中的2.1标准成功模板渲染回复';
|
|
1561
|
+
result._templateVariables = {
|
|
1562
|
+
currentDate: promptResult.data.currentDate,
|
|
1563
|
+
currentTime: promptResult.data.currentTime
|
|
1564
|
+
};
|
|
1522
1565
|
} else {
|
|
1523
1566
|
result = { success: false, error: promptResult.error };
|
|
1524
|
-
userMessage = `❌ 获取文字记账解析 Prompt 失败:${promptResult.error}`;
|
|
1525
1567
|
}
|
|
1526
1568
|
break;
|
|
1527
1569
|
}
|
|
@@ -1548,9 +1590,20 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
1548
1590
|
other: '其他反馈'
|
|
1549
1591
|
}[feedbackData.feedType] || '其他反馈';
|
|
1550
1592
|
|
|
1551
|
-
|
|
1593
|
+
// 【新增】返回模板位置信息(Server只返回原始数据,Agent使用模板渲染)
|
|
1594
|
+
result._templateLocation = 'references/response-templates.md';
|
|
1595
|
+
result._templateHint = '请使用references/response-templates.md中的模板渲染回复';
|
|
1596
|
+
result._templateVariables = {
|
|
1597
|
+
feedbackId: result.data.feedbackId,
|
|
1598
|
+
type: typeText,
|
|
1599
|
+
time: new Date().toLocaleString('zh-CN')
|
|
1600
|
+
};
|
|
1552
1601
|
} else {
|
|
1553
|
-
|
|
1602
|
+
result._templateLocation = 'references/response-templates.md';
|
|
1603
|
+
result._templateHint = '请使用references/response-templates.md中的模板渲染回复';
|
|
1604
|
+
result._templateVariables = {
|
|
1605
|
+
error: result.error || '未知错误'
|
|
1606
|
+
};
|
|
1554
1607
|
}
|
|
1555
1608
|
break;
|
|
1556
1609
|
}
|
|
@@ -1559,21 +1612,29 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
1559
1612
|
throw new Error(`未知工具: ${name}`);
|
|
1560
1613
|
}
|
|
1561
1614
|
|
|
1562
|
-
if (!result.success) {
|
|
1563
|
-
userMessage = `❌ 操作失败:${result.error || '未知错误'}`;
|
|
1564
|
-
}
|
|
1565
|
-
|
|
1566
1615
|
// 【新增】在结果中添加 agentName,让 Agent 可以使用
|
|
1567
1616
|
const agentName = await getAgentName();
|
|
1568
1617
|
if (result && typeof result === 'object') {
|
|
1569
1618
|
result.agentName = agentName;
|
|
1570
1619
|
}
|
|
1571
1620
|
|
|
1621
|
+
// 【修改】Server 只返回原始数据,不再构建格式化消息
|
|
1622
|
+
// Agent 必须使用 references/response-templates.md 中的模板自行渲染回复
|
|
1623
|
+
const responseData = {
|
|
1624
|
+
success: result.success,
|
|
1625
|
+
data: result.data,
|
|
1626
|
+
error: result.error,
|
|
1627
|
+
_templateLocation: result._templateLocation,
|
|
1628
|
+
_templateHint: result._templateHint,
|
|
1629
|
+
_templateVariables: result._templateVariables,
|
|
1630
|
+
agentName: agentName
|
|
1631
|
+
};
|
|
1632
|
+
|
|
1572
1633
|
return {
|
|
1573
1634
|
content: [
|
|
1574
1635
|
{
|
|
1575
1636
|
type: 'text',
|
|
1576
|
-
text:
|
|
1637
|
+
text: `⚠️ 【注意】Server 只返回原始数据,不返回格式化消息。\n请使用 _templateLocation 指定的模板自行渲染回复。\n\n---\n📦 柴米记账 MCP v${MCP_VERSION}\n\n## 完整数据\n\`\`\`json\n${safeStringify(responseData)}\n\`\`\``,
|
|
1577
1638
|
},
|
|
1578
1639
|
],
|
|
1579
1640
|
};
|
|
@@ -2185,23 +2246,11 @@ async function pollForAuthInBackground(deviceCode, interval) {
|
|
|
2185
2246
|
authState.isWaiting = false;
|
|
2186
2247
|
|
|
2187
2248
|
// 保存token到文件
|
|
2188
|
-
|
|
2189
|
-
await oauthManager.tokenStorage.save(token);
|
|
2190
|
-
console.error('🔍 [DEBUG] Token 保存完成');
|
|
2191
|
-
} catch (error) {
|
|
2192
|
-
console.error('❌ Token 保存失败:', error.message);
|
|
2193
|
-
throw error;
|
|
2194
|
-
}
|
|
2249
|
+
await oauthManager.tokenStorage.save(token);
|
|
2195
2250
|
|
|
2196
2251
|
// 【新增】保存默认 Agent 名称和 deviceCode(首次记账时会获取真实名称)
|
|
2197
|
-
|
|
2198
|
-
|
|
2199
|
-
await oauthManager.tokenStorage.saveDeviceCode(authState.deviceCode);
|
|
2200
|
-
console.error('🔍 [DEBUG] Agent 名称和 deviceCode 保存完成');
|
|
2201
|
-
} catch (error) {
|
|
2202
|
-
console.error('❌ Agent 信息保存失败:', error.message);
|
|
2203
|
-
// 这个失败不影响授权,只记录日志
|
|
2204
|
-
}
|
|
2252
|
+
await oauthManager.tokenStorage.saveAgentName('柴米AI助手');
|
|
2253
|
+
await oauthManager.tokenStorage.saveDeviceCode(authState.deviceCode);
|
|
2205
2254
|
|
|
2206
2255
|
// 清除授权状态
|
|
2207
2256
|
await oauthManager.clearAuthState();
|