shawnxixi-cli 0.3.0 → 1.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 (82) hide show
  1. package/.env.example +8 -2
  2. package/.github/workflows/ci.yml +9 -22
  3. package/.github/workflows/release.yml +30 -0
  4. package/CLAUDE.md +167 -63
  5. package/README.md +345 -65
  6. package/commitlint.config.js +10 -0
  7. package/dist/commands/biz/calendar.d.ts +17 -2
  8. package/dist/commands/biz/calendar.d.ts.map +1 -1
  9. package/dist/commands/biz/calendar.js +47 -9
  10. package/dist/commands/biz/calendar.js.map +1 -1
  11. package/dist/commands/biz/finance.d.ts +32 -1
  12. package/dist/commands/biz/finance.d.ts.map +1 -1
  13. package/dist/commands/biz/finance.js +99 -12
  14. package/dist/commands/biz/finance.js.map +1 -1
  15. package/dist/commands/biz/health.d.ts +32 -0
  16. package/dist/commands/biz/health.d.ts.map +1 -0
  17. package/dist/commands/biz/health.js +92 -0
  18. package/dist/commands/biz/health.js.map +1 -0
  19. package/dist/commands/biz/item.d.ts +41 -0
  20. package/dist/commands/biz/item.d.ts.map +1 -1
  21. package/dist/commands/biz/item.js +89 -5
  22. package/dist/commands/biz/item.js.map +1 -1
  23. package/dist/commands/biz/record.d.ts +0 -8
  24. package/dist/commands/biz/record.d.ts.map +1 -1
  25. package/dist/commands/biz/record.js +29 -8
  26. package/dist/commands/biz/record.js.map +1 -1
  27. package/dist/commands/biz/task.d.ts +38 -0
  28. package/dist/commands/biz/task.d.ts.map +1 -0
  29. package/dist/commands/biz/task.js +110 -0
  30. package/dist/commands/biz/task.js.map +1 -0
  31. package/dist/commands/biz/todo.d.ts +52 -8
  32. package/dist/commands/biz/todo.d.ts.map +1 -1
  33. package/dist/commands/biz/todo.js +167 -17
  34. package/dist/commands/biz/todo.js.map +1 -1
  35. package/dist/commands/sys/health.d.ts.map +1 -1
  36. package/dist/commands/sys/health.js +20 -3
  37. package/dist/commands/sys/health.js.map +1 -1
  38. package/dist/index.d.ts +5 -0
  39. package/dist/index.d.ts.map +1 -1
  40. package/dist/index.js +281 -42
  41. package/dist/index.js.map +1 -1
  42. package/dist/services/api.d.ts +22 -8
  43. package/dist/services/api.d.ts.map +1 -1
  44. package/dist/services/api.js +108 -28
  45. package/dist/services/api.js.map +1 -1
  46. package/dist/utils/env.d.ts +16 -0
  47. package/dist/utils/env.d.ts.map +1 -0
  48. package/dist/utils/env.js +78 -0
  49. package/dist/utils/env.js.map +1 -0
  50. package/dist/utils/finance.model.d.ts +80 -0
  51. package/dist/utils/finance.model.d.ts.map +1 -0
  52. package/dist/utils/finance.model.js +150 -0
  53. package/dist/utils/finance.model.js.map +1 -0
  54. package/dist/utils/output.d.ts +42 -0
  55. package/dist/utils/output.d.ts.map +1 -0
  56. package/dist/utils/output.js +124 -0
  57. package/dist/utils/output.js.map +1 -0
  58. package/dist/utils/todo.model.d.ts +55 -0
  59. package/dist/utils/todo.model.d.ts.map +1 -0
  60. package/dist/utils/todo.model.js +135 -0
  61. package/dist/utils/todo.model.js.map +1 -0
  62. package/package.json +18 -2
  63. package/src/commands/biz/calendar.ts +61 -10
  64. package/src/commands/biz/finance.ts +112 -13
  65. package/src/commands/biz/health.ts +96 -0
  66. package/src/commands/biz/item.ts +113 -6
  67. package/src/commands/biz/record.ts +32 -8
  68. package/src/commands/biz/task.ts +115 -0
  69. package/src/commands/biz/todo.ts +193 -21
  70. package/src/commands/sys/health.ts +23 -3
  71. package/src/index.ts +311 -54
  72. package/src/services/api.ts +111 -30
  73. package/src/utils/env.ts +85 -0
  74. package/src/utils/finance.model.ts +182 -0
  75. package/src/utils/output.ts +126 -0
  76. package/src/utils/todo.model.ts +167 -0
  77. package/tests/commands/finance.test.ts +281 -0
  78. package/tests/commands/item.test.ts +215 -0
  79. package/tests/commands/todo.test.ts +292 -9
  80. package/tests/services/api.test.ts +292 -20
  81. package/tests/utils/finance.model.test.ts +319 -0
  82. package/tests/utils/todo.model.test.ts +315 -0
@@ -4,20 +4,40 @@
4
4
  */
5
5
 
6
6
  import { apiService } from '../../services/api';
7
+ import { output, outputError, createLoading, isDryRun, dryRunLog } from '../../utils/output';
7
8
 
8
9
  export const syncHealth = async (dataType?: string, options: { startDate?: string; endDate?: string } = {}) => {
10
+ const loading = createLoading('处理健康数据...');
11
+
9
12
  try {
10
13
  if (dataType || options.startDate || options.endDate) {
11
14
  // 查询模式
15
+ if (isDryRun()) {
16
+ loading.stop();
17
+ dryRunLog('查询健康数据', { dataType, ...options });
18
+ return;
19
+ }
20
+
21
+ loading.start();
12
22
  const result = await apiService.queryHealthData(dataType, options.startDate, options.endDate);
13
- console.log(JSON.stringify(result, null, 2));
23
+ loading.succeed('健康数据加载成功');
24
+ output(result);
14
25
  } else {
15
26
  // 同步模式
27
+ if (isDryRun()) {
28
+ loading.stop();
29
+ dryRunLog('同步健康数据', {});
30
+ return;
31
+ }
32
+
33
+ loading.start();
16
34
  const result = await apiService.syncHealthData();
17
- console.log(JSON.stringify(result, null, 2));
35
+ loading.succeed('健康数据同步成功');
36
+ output(result);
18
37
  }
19
38
  } catch (error: any) {
20
- console.error('健康数据操作失败:', error.message);
39
+ loading.fail('健康数据操作失败');
40
+ outputError(error.message);
21
41
  process.exit(1);
22
42
  }
23
43
  };
package/src/index.ts CHANGED
@@ -4,45 +4,110 @@
4
4
  * shawnxixi-cli
5
5
  * 肖嘻 CLI 工具入口
6
6
  * 命令命名空间:biz:*(日常业务)、sys:*(系统操作)
7
+ *
8
+ * 全局参数:
9
+ * --json 输出 JSON 格式
10
+ * --quiet 静默模式(只输出关键信息)
11
+ * --dry-run 预览模式(不实际调用 API)
7
12
  */
8
13
 
9
14
  import { Command } from 'commander';
15
+ import { version } from '../package.json';
10
16
  import { todoCommands } from './commands/biz/todo';
11
17
  import { recordCommands } from './commands/biz/record';
12
18
  import { financeCommands } from './commands/biz/finance';
13
19
  import { itemCommands } from './commands/biz/item';
14
20
  import { calendarCommands } from './commands/biz/calendar';
15
- import { syncHealth } from './commands/sys/health';
21
+ import { taskCommands } from './commands/biz/task';
22
+ import { healthCommands } from './commands/biz/health';
23
+ import { setGlobalFlags, output } from './utils/output';
24
+
25
+ // 预解析全局参数(在 Commander 解析之前)
26
+ const rawArgs = process.argv.slice(2);
27
+ const globalFlags = {
28
+ json: rawArgs.includes('--json'),
29
+ quiet: rawArgs.includes('--quiet'),
30
+ dryRun: rawArgs.includes('--dry-run'),
31
+ };
32
+
33
+ // 设置全局标志
34
+ setGlobalFlags(globalFlags);
35
+
36
+ // 过滤掉全局参数,避免干扰 commander 解析
37
+ const filteredArgs = rawArgs.filter(arg => !['--json', '--quiet', '--dry-run'].includes(arg));
16
38
 
17
39
  const program = new Command();
18
40
 
19
41
  program
20
42
  .name('shawnxixi')
21
- .description('肖嘻 CLI 工具')
22
- .version('0.2.0');
43
+ .description('肖嘻 CLI 工具 - 日常业务与系统管理')
44
+ .version(version);
23
45
 
24
46
  // ============ biz ============
25
47
 
26
48
  const biz = program.command('biz').description('日常业务命令');
27
49
 
28
- // biz todo
29
- const todo = biz.command('todo').description('待办管理');
50
+ // -------- biz todo --------
51
+ // biz todo create 创建待办
52
+ // biz todo list 列出待办
53
+ // biz todo edit 编辑待办
54
+ // biz todo done 标记完成
55
+ // biz todo delete 删除待办
56
+ // biz todo repeat 完成并生成下次 occurrence
57
+ // biz todo subtask 创建子待办
58
+ // biz todo subtasks 列出子待办
59
+ const todo = biz.command('todo').description('待办管理(对标滴答清单)');
30
60
 
31
61
  todo
32
62
  .command('create <title>')
33
63
  .description('创建待办')
34
64
  .option('--due <date>', '截止日期 YYYY-MM-DD')
35
65
  .option('--priority <level>', '优先级 low|medium|high', 'medium')
36
- .action(async (title: string, options: { due?: string; priority?: string }) => {
37
- await todoCommands.create(title, options);
66
+ .option('--tags <tags>', '标签,逗号分隔')
67
+ .option('--repeat <rule>', '重复规则 daily|weekly|monthly')
68
+ .option('--end-date <date>', '重复结束日期 YYYY-MM-DD')
69
+ .option('--parent-id <id>', '父待办 ID(创建子待办)')
70
+ .action(async (title: string, options: Record<string, string>) => {
71
+ await todoCommands.create(title, {
72
+ due: options.due,
73
+ priority: options.priority,
74
+ tags: options.tags,
75
+ repeat: options.repeat,
76
+ endDate: options.endDate,
77
+ parentId: options.parentId,
78
+ });
38
79
  });
39
80
 
40
81
  todo
41
82
  .command('list')
42
83
  .description('列出待办')
43
- .option('--status <status>', '状态过滤')
44
- .action(async (options: { status?: string }) => {
45
- await todoCommands.list(options);
84
+ .option('--status <status>', '状态过滤 pending|done')
85
+ .option('--priority <level>', '优先级过滤 low|medium|high')
86
+ .option('--tags <tags>', '标签过滤,逗号分隔')
87
+ .action(async (options: Record<string, string>) => {
88
+ await todoCommands.list({
89
+ status: options.status,
90
+ priority: options.priority,
91
+ tags: options.tags,
92
+ });
93
+ });
94
+
95
+ todo
96
+ .command('edit <id>')
97
+ .description('编辑待办')
98
+ .option('--title <title>', '新标题')
99
+ .option('--status <status>', '新状态 pending|done')
100
+ .option('--priority <level>', '新优先级 low|medium|high')
101
+ .option('--due <date>', '新截止日期 YYYY-MM-DD')
102
+ .option('--tags <tags>', '新标签,逗号分隔')
103
+ .action(async (id: string, options: Record<string, string>) => {
104
+ await todoCommands.update(parseInt(id, 10), {
105
+ title: options.title,
106
+ status: options.status,
107
+ priority: options.priority,
108
+ due: options.due,
109
+ tags: options.tags,
110
+ });
46
111
  });
47
112
 
48
113
  todo
@@ -59,8 +124,81 @@ todo
59
124
  await todoCommands.delete(parseInt(id, 10));
60
125
  });
61
126
 
62
- // biz record
63
- const record = biz.command('record').description('记录管理');
127
+ todo
128
+ .command('repeat <id>')
129
+ .description('完成待办并生成下次 occurrence(适用于重复待办)')
130
+ .action(async (id: string) => {
131
+ await todoCommands.repeat(parseInt(id, 10));
132
+ });
133
+
134
+ todo
135
+ .command('subtask <parent-id>')
136
+ .description('创建子待办')
137
+ .requiredOption('--title <title>', '子待办标题(必需)')
138
+ .action(async (parentId: string, options: Record<string, string>) => {
139
+ await todoCommands.subtask(parseInt(parentId, 10), { title: options.title });
140
+ });
141
+
142
+ todo
143
+ .command('subtasks <parent-id>')
144
+ .description('列出子待办')
145
+ .action(async (parentId: string) => {
146
+ await todoCommands.subtasks(parseInt(parentId, 10));
147
+ });
148
+
149
+ // -------- biz task --------
150
+ // biz task create 创建任务
151
+ // biz task list 列出任务
152
+ // biz task update 更新任务
153
+ // biz task delete 删除任务
154
+ const task = biz.command('task').description('任务管理(对标系统任务)');
155
+
156
+ task
157
+ .command('list')
158
+ .description('列出任务')
159
+ .option('--status <status>', '状态过滤 pending|running|done')
160
+ .option('--source <source>', '来源过滤 openclaw|cli')
161
+ .action(async (options: Record<string, string>) => {
162
+ await taskCommands.list({ status: options.status, source: options.source });
163
+ });
164
+
165
+ task
166
+ .command('create <title>')
167
+ .description('创建任务')
168
+ .option('--source <source>', '来源 openclaw|cli', 'cli')
169
+ .option('--openclaw-id <id>', 'OpenClaw ID')
170
+ .option('--priority <level>', '优先级 low|medium|high', 'medium')
171
+ .action(async (title: string, options: Record<string, string>) => {
172
+ await taskCommands.create(title, {
173
+ source: options.source,
174
+ openclawId: options.openclawId,
175
+ priority: options.priority,
176
+ });
177
+ });
178
+
179
+ task
180
+ .command('update <id>')
181
+ .description('更新任务')
182
+ .option('--status <status>', '新状态 pending|running|done')
183
+ .option('--priority <level>', '新优先级 low|medium|high')
184
+ .action(async (id: string, options: Record<string, string>) => {
185
+ await taskCommands.update(parseInt(id, 10), {
186
+ status: options.status,
187
+ priority: options.priority,
188
+ });
189
+ });
190
+
191
+ task
192
+ .command('delete <id>')
193
+ .description('删除任务')
194
+ .action(async (id: string) => {
195
+ await taskCommands.delete(parseInt(id, 10));
196
+ });
197
+
198
+ // -------- biz record --------
199
+ // biz record create 创建记录
200
+ // biz record list 列出记录
201
+ const record = biz.command('record').description('记录管理(日记/宠物/笔记/想法)');
64
202
 
65
203
  record
66
204
  .command('create <title>')
@@ -68,29 +206,47 @@ record
68
206
  .option('--content <text>', '内容')
69
207
  .option('--type <type>', '类型 diary|pet|note|idea', 'diary')
70
208
  .option('--tags <tags>', '标签,逗号分隔')
71
- .action(async (title: string, options: { content?: string; type?: string; tags?: string }) => {
72
- await recordCommands.create(title, options.content || '', options);
209
+ .action(async (title: string, options: Record<string, string>) => {
210
+ await recordCommands.create(title, options.content || '', {
211
+ type: options.type,
212
+ tags: options.tags,
213
+ });
73
214
  });
74
215
 
75
216
  record
76
217
  .command('list')
77
218
  .description('列出记录')
78
- .option('--type <type>', '类型过滤')
79
- .action(async (options: { type?: string }) => {
80
- await recordCommands.list(options);
219
+ .option('--type <type>', '类型过滤 diary|pet|note|idea')
220
+ .option('--tags <tags>', '标签过滤,逗号分隔')
221
+ .action(async (options: Record<string, string>) => {
222
+ await recordCommands.list({ type: options.type, tags: options.tags });
81
223
  });
82
224
 
83
- // biz finance
84
- const finance = biz.command('finance').description('财务管理');
225
+ // -------- biz finance --------
226
+ // biz finance create 新增账单
227
+ // biz finance list 列出账单
228
+ // biz finance stats 账单统计
229
+ // biz finance report 月度报表
230
+ const finance = biz.command('finance').description('财务管理(对标记账类 App)');
85
231
 
86
232
  finance
87
233
  .command('create <amount>')
88
234
  .description('记一笔账')
89
235
  .option('--type <type>', '类型 income|expense', 'expense')
90
- .option('--category <cat>', '分类', 'other')
91
- .option('--desc <text>', '备注')
92
- .action(async (amount: string, options: { type?: string; category?: string; desc?: string }) => {
93
- await financeCommands.create(amount, options);
236
+ .option('--category <cat>', '分类')
237
+ .option('--note <text>', '备注')
238
+ .option('--account <account>', '账户 cash|card|alipay|wechat', 'cash')
239
+ .option('--date <date>', '日期 YYYY-MM-DD')
240
+ .option('--tags <tags>', '标签,逗号分隔')
241
+ .action(async (amount: string, options: Record<string, string>) => {
242
+ await financeCommands.create(amount, {
243
+ type: options.type,
244
+ category: options.category,
245
+ note: options.note,
246
+ account: options.account,
247
+ date: options.date,
248
+ tags: options.tags,
249
+ });
94
250
  });
95
251
 
96
252
  finance
@@ -98,12 +254,37 @@ finance
98
254
  .description('列出账单')
99
255
  .option('--type <type>', '类型过滤 income|expense')
100
256
  .option('--category <cat>', '分类过滤')
101
- .action(async (options: { type?: string; category?: string }) => {
102
- await financeCommands.list(options);
257
+ .option('--month <month>', '月份过滤 YYYY-MM')
258
+ .action(async (options: Record<string, string>) => {
259
+ await financeCommands.list({
260
+ type: options.type,
261
+ category: options.category,
262
+ month: options.month,
263
+ });
103
264
  });
104
265
 
105
- // biz item
106
- const item = biz.command('item').description('物品管理');
266
+ finance
267
+ .command('stats')
268
+ .description('账单统计')
269
+ .option('--month <month>', '月份 YYYY-MM', new Date().toISOString().slice(0, 7))
270
+ .action(async (options: Record<string, string>) => {
271
+ await financeCommands.stats({ month: options.month });
272
+ });
273
+
274
+ finance
275
+ .command('report')
276
+ .description('月度报表')
277
+ .option('--month <month>', '月份 YYYY-MM', new Date().toISOString().slice(0, 7))
278
+ .action(async (options: Record<string, string>) => {
279
+ await financeCommands.report({ month: options.month });
280
+ });
281
+
282
+ // -------- biz item --------
283
+ // biz item create 添加物品
284
+ // biz item list 列出物品
285
+ // biz item expiring 即将过期物品
286
+ // biz item stats 库存统计
287
+ const item = biz.command('item').description('物品管理(对标物品清单 App)');
107
288
 
108
289
  item
109
290
  .command('create <name>')
@@ -111,63 +292,139 @@ item
111
292
  .option('--location <loc>', '存放位置')
112
293
  .option('--expire <date>', '过期日期 YYYY-MM-DD')
113
294
  .option('--category <cat>', '分类')
114
- .action(async (name: string, options: { location?: string; expire?: string; category?: string }) => {
115
- await itemCommands.create(name, options);
295
+ .option('--quantity <n>', '数量', parseInt)
296
+ .option('--unit <unit>', '单位 个|瓶|盒|kg|g|ml|l')
297
+ .option('--brand <brand>', '品牌')
298
+ .option('--barcode <code>', '条码')
299
+ .option('--price <price>', '价格')
300
+ .option('--supplier <supplier>', '供应商')
301
+ .option('--purchase-date <date>', '购买日期 YYYY-MM-DD')
302
+ .action(async (name: string, options: Record<string, string>) => {
303
+ await itemCommands.create(name, {
304
+ location: options.location,
305
+ expire: options.expire,
306
+ category: options.category,
307
+ quantity: options.quantity ? parseInt(options.quantity) : undefined,
308
+ unit: options.unit,
309
+ brand: options.brand,
310
+ barcode: options.barcode,
311
+ price: options.price ? parseFloat(options.price) : undefined,
312
+ supplier: options.supplier,
313
+ purchaseDate: options.purchaseDate,
314
+ });
116
315
  });
117
316
 
118
317
  item
119
318
  .command('list')
120
319
  .description('列出物品')
121
320
  .option('--category <cat>', '分类过滤')
122
- .action(async (options: { category?: string }) => {
123
- await itemCommands.list(options);
321
+ .action(async (options: Record<string, string>) => {
322
+ await itemCommands.list({ category: options.category });
323
+ });
324
+
325
+ item
326
+ .command('expiring')
327
+ .description('即将过期的物品')
328
+ .option('--days <n>', '提前多少天提醒', '7')
329
+ .action(async (options: Record<string, string>) => {
330
+ await itemCommands.expiring({ days: options.days ? parseInt(options.days) : 7 });
331
+ });
332
+
333
+ item
334
+ .command('stats')
335
+ .description('物品库存统计')
336
+ .action(async () => {
337
+ await itemCommands.stats();
124
338
  });
125
339
 
126
- // biz calendar
127
- const calendar = biz.command('calendar').description('日程管理');
340
+ // -------- biz calendar --------
341
+ // biz calendar create 创建日程
342
+ // biz calendar list 列出日程
343
+ const calendar = biz.command('calendar').description('日程管理(对标日历 App)');
128
344
 
129
345
  calendar
130
346
  .command('create <title>')
131
347
  .description('创建日程')
132
- .requiredOption('--start <datetime>', '开始时间')
133
- .requiredOption('--end <datetime>', '结束时间')
348
+ .requiredOption('--from <datetime>', '开始时间 YYYY-MM-DD 或 YYYY-MM-DD HH:MM')
349
+ .requiredOption('--to <datetime>', '结束时间 YYYY-MM-DD 或 YYYY-MM-DD HH:MM')
350
+ .option('--location <loc>', '地点')
351
+ .option('--color <color>', '颜色 HEX 如 #ff0000')
134
352
  .option('--desc <text>', '描述')
135
- .action(async (title: string, options: { start: string; end: string; desc?: string }) => {
136
- await calendarCommands.create(title, options);
353
+ .action(async (title: string, options: Record<string, string>) => {
354
+ await calendarCommands.create(title, {
355
+ from: options.from,
356
+ to: options.to,
357
+ location: options.location,
358
+ color: options.color,
359
+ desc: options.desc,
360
+ });
137
361
  });
138
362
 
139
363
  calendar
140
364
  .command('list')
141
365
  .description('列出日程')
142
- .option('--from <datetime>', '开始时间')
143
- .option('--to <datetime>', '结束时间')
144
- .action(async (options: { from?: string; to?: string }) => {
145
- await calendarCommands.list(options);
366
+ .option('--from <datetime>', '开始时间 YYYY-MM-DD')
367
+ .option('--to <datetime>', '结束时间 YYYY-MM-DD')
368
+ .action(async (options: Record<string, string>) => {
369
+ await calendarCommands.list({ from: options.from, to: options.to });
146
370
  });
147
371
 
148
- // ============ sys ============
149
-
150
- const sys = program.command('sys').description('系统命令');
151
-
152
- const health = sys.command('health').description('健康数据');
372
+ // -------- biz health --------
373
+ // biz health log 记录健康数据
374
+ // biz health list 查询健康数据
375
+ // biz health sync 同步健康数据
376
+ const health = biz.command('health').description('健康数据管理(对标 Apple Health)');
153
377
 
154
378
  health
155
- .command('sync')
156
- .description('同步健康数据')
157
- .action(async () => {
158
- await syncHealth();
379
+ .command('log')
380
+ .description('记录健康数据')
381
+ .requiredOption('--type <type>', '数据类型 heart_rate|steps|weight|sleep|blood_pressure|oxygen|body_temp')
382
+ .requiredOption('--value <value>', '数值')
383
+ .option('--unit <unit>', '单位 bpm|kg|steps|hours|mmHg|%|°C')
384
+ .option('--date <date>', '日期 YYYY-MM-DD', new Date().toISOString().slice(0, 10))
385
+ .action(async (options: Record<string, string>) => {
386
+ await healthCommands.log({
387
+ type: options.type,
388
+ value: options.value,
389
+ unit: options.unit,
390
+ date: options.date,
391
+ });
159
392
  });
160
393
 
161
394
  health
162
- .command('query [dataType]')
395
+ .command('list')
163
396
  .description('查询健康数据')
397
+ .option('--type <type>', '数据类型过滤')
164
398
  .option('--from <date>', '开始日期 YYYY-MM-DD')
165
399
  .option('--to <date>', '结束日期 YYYY-MM-DD')
166
- .action(async (dataType: string | undefined, options: { from?: string; to?: string }) => {
167
- await syncHealth(dataType, { startDate: options.from, endDate: options.to });
400
+ .action(async (options: Record<string, string>) => {
401
+ await healthCommands.list({
402
+ type: options.type,
403
+ from: options.from,
404
+ to: options.to,
405
+ });
406
+ });
407
+
408
+ health
409
+ .command('sync')
410
+ .description('同步健康数据(保留兼容)')
411
+ .action(async () => {
412
+ await healthCommands.sync();
413
+ });
414
+
415
+ // ============ sys ============
416
+
417
+ const sys = program.command('sys').description('系统命令');
418
+
419
+ sys
420
+ .command('health')
421
+ .description('健康检查')
422
+ .action(async () => {
423
+ output({ status: 'ok', timestamp: new Date().toISOString() });
168
424
  });
169
425
 
170
- program.parseAsync(process.argv).catch((error) => {
426
+ // 解析过滤后的参数
427
+ program.parseAsync(['node', 'shawnxixi', ...filteredArgs]).catch((error) => {
171
428
  console.error('Command failed:', error);
172
429
  process.exit(1);
173
430
  });