shawnxixi-cli 0.3.1 → 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 +279 -41
  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 +309 -53
  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,6 +4,11 @@
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';
@@ -13,37 +18,96 @@ import { recordCommands } from './commands/biz/record';
13
18
  import { financeCommands } from './commands/biz/finance';
14
19
  import { itemCommands } from './commands/biz/item';
15
20
  import { calendarCommands } from './commands/biz/calendar';
16
- 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));
17
38
 
18
39
  const program = new Command();
19
40
 
20
41
  program
21
42
  .name('shawnxixi')
22
- .description('肖嘻 CLI 工具')
43
+ .description('肖嘻 CLI 工具 - 日常业务与系统管理')
23
44
  .version(version);
24
45
 
25
46
  // ============ biz ============
26
47
 
27
48
  const biz = program.command('biz').description('日常业务命令');
28
49
 
29
- // biz todo
30
- 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('待办管理(对标滴答清单)');
31
60
 
32
61
  todo
33
62
  .command('create <title>')
34
63
  .description('创建待办')
35
64
  .option('--due <date>', '截止日期 YYYY-MM-DD')
36
65
  .option('--priority <level>', '优先级 low|medium|high', 'medium')
37
- .action(async (title: string, options: { due?: string; priority?: string }) => {
38
- 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
+ });
39
79
  });
40
80
 
41
81
  todo
42
82
  .command('list')
43
83
  .description('列出待办')
44
- .option('--status <status>', '状态过滤')
45
- .action(async (options: { status?: string }) => {
46
- 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
+ });
47
111
  });
48
112
 
49
113
  todo
@@ -60,8 +124,81 @@ todo
60
124
  await todoCommands.delete(parseInt(id, 10));
61
125
  });
62
126
 
63
- // biz record
64
- 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('记录管理(日记/宠物/笔记/想法)');
65
202
 
66
203
  record
67
204
  .command('create <title>')
@@ -69,29 +206,47 @@ record
69
206
  .option('--content <text>', '内容')
70
207
  .option('--type <type>', '类型 diary|pet|note|idea', 'diary')
71
208
  .option('--tags <tags>', '标签,逗号分隔')
72
- .action(async (title: string, options: { content?: string; type?: string; tags?: string }) => {
73
- 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
+ });
74
214
  });
75
215
 
76
216
  record
77
217
  .command('list')
78
218
  .description('列出记录')
79
- .option('--type <type>', '类型过滤')
80
- .action(async (options: { type?: string }) => {
81
- 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 });
82
223
  });
83
224
 
84
- // biz finance
85
- 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)');
86
231
 
87
232
  finance
88
233
  .command('create <amount>')
89
234
  .description('记一笔账')
90
235
  .option('--type <type>', '类型 income|expense', 'expense')
91
- .option('--category <cat>', '分类', 'other')
92
- .option('--desc <text>', '备注')
93
- .action(async (amount: string, options: { type?: string; category?: string; desc?: string }) => {
94
- 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
+ });
95
250
  });
96
251
 
97
252
  finance
@@ -99,12 +254,37 @@ finance
99
254
  .description('列出账单')
100
255
  .option('--type <type>', '类型过滤 income|expense')
101
256
  .option('--category <cat>', '分类过滤')
102
- .action(async (options: { type?: string; category?: string }) => {
103
- 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
+ });
104
264
  });
105
265
 
106
- // biz item
107
- 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)');
108
288
 
109
289
  item
110
290
  .command('create <name>')
@@ -112,63 +292,139 @@ item
112
292
  .option('--location <loc>', '存放位置')
113
293
  .option('--expire <date>', '过期日期 YYYY-MM-DD')
114
294
  .option('--category <cat>', '分类')
115
- .action(async (name: string, options: { location?: string; expire?: string; category?: string }) => {
116
- 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
+ });
117
315
  });
118
316
 
119
317
  item
120
318
  .command('list')
121
319
  .description('列出物品')
122
320
  .option('--category <cat>', '分类过滤')
123
- .action(async (options: { category?: string }) => {
124
- 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();
125
338
  });
126
339
 
127
- // biz calendar
128
- 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)');
129
344
 
130
345
  calendar
131
346
  .command('create <title>')
132
347
  .description('创建日程')
133
- .requiredOption('--start <datetime>', '开始时间')
134
- .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')
135
352
  .option('--desc <text>', '描述')
136
- .action(async (title: string, options: { start: string; end: string; desc?: string }) => {
137
- 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
+ });
138
361
  });
139
362
 
140
363
  calendar
141
364
  .command('list')
142
365
  .description('列出日程')
143
- .option('--from <datetime>', '开始时间')
144
- .option('--to <datetime>', '结束时间')
145
- .action(async (options: { from?: string; to?: string }) => {
146
- 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 });
147
370
  });
148
371
 
149
- // ============ sys ============
150
-
151
- const sys = program.command('sys').description('系统命令');
152
-
153
- 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)');
154
377
 
155
378
  health
156
- .command('sync')
157
- .description('同步健康数据')
158
- .action(async () => {
159
- 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
+ });
160
392
  });
161
393
 
162
394
  health
163
- .command('query [dataType]')
395
+ .command('list')
164
396
  .description('查询健康数据')
397
+ .option('--type <type>', '数据类型过滤')
165
398
  .option('--from <date>', '开始日期 YYYY-MM-DD')
166
399
  .option('--to <date>', '结束日期 YYYY-MM-DD')
167
- .action(async (dataType: string | undefined, options: { from?: string; to?: string }) => {
168
- 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() });
169
424
  });
170
425
 
171
- program.parseAsync(process.argv).catch((error) => {
426
+ // 解析过滤后的参数
427
+ program.parseAsync(['node', 'shawnxixi', ...filteredArgs]).catch((error) => {
172
428
  console.error('Command failed:', error);
173
429
  process.exit(1);
174
430
  });