@yivan-lab/pretty-please 1.0.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 (86) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +380 -0
  3. package/bin/pls.js +681 -0
  4. package/bin/pls.tsx +541 -0
  5. package/dist/bin/pls.d.ts +2 -0
  6. package/dist/bin/pls.js +429 -0
  7. package/dist/src/ai.d.ts +48 -0
  8. package/dist/src/ai.js +295 -0
  9. package/dist/src/builtin-detector.d.ts +15 -0
  10. package/dist/src/builtin-detector.js +83 -0
  11. package/dist/src/chat-history.d.ts +26 -0
  12. package/dist/src/chat-history.js +81 -0
  13. package/dist/src/components/Chat.d.ts +13 -0
  14. package/dist/src/components/Chat.js +80 -0
  15. package/dist/src/components/ChatStatus.d.ts +9 -0
  16. package/dist/src/components/ChatStatus.js +34 -0
  17. package/dist/src/components/CodeColorizer.d.ts +12 -0
  18. package/dist/src/components/CodeColorizer.js +82 -0
  19. package/dist/src/components/CommandBox.d.ts +10 -0
  20. package/dist/src/components/CommandBox.js +45 -0
  21. package/dist/src/components/CommandGenerator.d.ts +20 -0
  22. package/dist/src/components/CommandGenerator.js +116 -0
  23. package/dist/src/components/ConfigDisplay.d.ts +9 -0
  24. package/dist/src/components/ConfigDisplay.js +42 -0
  25. package/dist/src/components/ConfigWizard.d.ts +9 -0
  26. package/dist/src/components/ConfigWizard.js +72 -0
  27. package/dist/src/components/ConfirmationPrompt.d.ts +12 -0
  28. package/dist/src/components/ConfirmationPrompt.js +26 -0
  29. package/dist/src/components/Duration.d.ts +9 -0
  30. package/dist/src/components/Duration.js +21 -0
  31. package/dist/src/components/HistoryDisplay.d.ts +9 -0
  32. package/dist/src/components/HistoryDisplay.js +51 -0
  33. package/dist/src/components/HookManager.d.ts +10 -0
  34. package/dist/src/components/HookManager.js +88 -0
  35. package/dist/src/components/InlineRenderer.d.ts +12 -0
  36. package/dist/src/components/InlineRenderer.js +75 -0
  37. package/dist/src/components/MarkdownDisplay.d.ts +13 -0
  38. package/dist/src/components/MarkdownDisplay.js +197 -0
  39. package/dist/src/components/MultiStepCommandGenerator.d.ts +25 -0
  40. package/dist/src/components/MultiStepCommandGenerator.js +142 -0
  41. package/dist/src/components/TableRenderer.d.ts +12 -0
  42. package/dist/src/components/TableRenderer.js +66 -0
  43. package/dist/src/config.d.ts +29 -0
  44. package/dist/src/config.js +203 -0
  45. package/dist/src/history.d.ts +20 -0
  46. package/dist/src/history.js +113 -0
  47. package/dist/src/mastra-agent.d.ts +7 -0
  48. package/dist/src/mastra-agent.js +31 -0
  49. package/dist/src/multi-step.d.ts +41 -0
  50. package/dist/src/multi-step.js +67 -0
  51. package/dist/src/shell-hook.d.ts +35 -0
  52. package/dist/src/shell-hook.js +348 -0
  53. package/dist/src/sysinfo.d.ts +15 -0
  54. package/dist/src/sysinfo.js +52 -0
  55. package/dist/src/ui/theme.d.ts +26 -0
  56. package/dist/src/ui/theme.js +31 -0
  57. package/dist/src/utils/console.d.ts +44 -0
  58. package/dist/src/utils/console.js +114 -0
  59. package/package.json +78 -0
  60. package/src/ai.js +324 -0
  61. package/src/builtin-detector.js +98 -0
  62. package/src/chat-history.js +94 -0
  63. package/src/components/Chat.tsx +122 -0
  64. package/src/components/ChatStatus.tsx +53 -0
  65. package/src/components/CodeColorizer.tsx +128 -0
  66. package/src/components/CommandBox.tsx +60 -0
  67. package/src/components/CommandGenerator.tsx +184 -0
  68. package/src/components/ConfigDisplay.tsx +64 -0
  69. package/src/components/ConfigWizard.tsx +101 -0
  70. package/src/components/ConfirmationPrompt.tsx +41 -0
  71. package/src/components/Duration.tsx +24 -0
  72. package/src/components/HistoryDisplay.tsx +69 -0
  73. package/src/components/HookManager.tsx +150 -0
  74. package/src/components/InlineRenderer.tsx +123 -0
  75. package/src/components/MarkdownDisplay.tsx +288 -0
  76. package/src/components/MultiStepCommandGenerator.tsx +229 -0
  77. package/src/components/TableRenderer.tsx +110 -0
  78. package/src/config.js +221 -0
  79. package/src/history.js +131 -0
  80. package/src/mastra-agent.ts +35 -0
  81. package/src/multi-step.ts +93 -0
  82. package/src/shell-hook.js +393 -0
  83. package/src/sysinfo.js +57 -0
  84. package/src/ui/theme.ts +37 -0
  85. package/src/utils/console.js +130 -0
  86. package/tsconfig.json +23 -0
package/bin/pls.tsx ADDED
@@ -0,0 +1,541 @@
1
+ #!/usr/bin/env node
2
+ import React from 'react'
3
+ import { render } from 'ink'
4
+ import { Command } from 'commander'
5
+ import { fileURLToPath } from 'url'
6
+ import { dirname, join } from 'path'
7
+ import { exec } from 'child_process'
8
+ import fs from 'fs'
9
+ import os from 'os'
10
+ import chalk from 'chalk'
11
+ import { CommandGenerator } from '../src/components/CommandGenerator.js'
12
+ import { MultiStepCommandGenerator } from '../src/components/MultiStepCommandGenerator.js'
13
+ import { Chat } from '../src/components/Chat.js'
14
+ import { isConfigValid, setConfigValue, getConfig, maskApiKey } from '../src/config.js'
15
+ import { clearHistory, addHistory, getHistory, getHistoryFilePath } from '../src/history.js'
16
+ import { clearChatHistory, getChatRoundCount, getChatHistoryFilePath } from '../src/chat-history.js'
17
+ import { type ExecutedStep } from '../src/multi-step.js'
18
+ import {
19
+ installShellHook,
20
+ uninstallShellHook,
21
+ getHookStatus,
22
+ detectShell,
23
+ getShellConfigPath,
24
+ } from '../src/shell-hook.js'
25
+ import * as console2 from '../src/utils/console.js'
26
+
27
+ // 获取 package.json 版本
28
+ const __filename = fileURLToPath(import.meta.url)
29
+ const __dirname = dirname(__filename)
30
+ const packageJson = JSON.parse(fs.readFileSync(join(__dirname, '../package.json'), 'utf-8'))
31
+
32
+ const program = new Command()
33
+
34
+ /**
35
+ * 执行命令(原生版本)
36
+ */
37
+ function executeCommand(command: string, prompt: string): Promise<{ exitCode: number; output: string }> {
38
+ return new Promise((resolve) => {
39
+ let output = ''
40
+ let hasOutput = false
41
+
42
+ console.log('') // 空行
43
+ console2.printSeparator('输出')
44
+
45
+ const child = exec(command)
46
+
47
+ child.stdout?.on('data', (data) => {
48
+ output += data
49
+ hasOutput = true
50
+ process.stdout.write(data)
51
+ })
52
+
53
+ child.stderr?.on('data', (data) => {
54
+ output += data
55
+ hasOutput = true
56
+ process.stderr.write(data)
57
+ })
58
+
59
+ child.on('close', (code) => {
60
+ if (hasOutput) {
61
+ console2.printSeparator('')
62
+ }
63
+ resolve({ exitCode: code || 0, output })
64
+ })
65
+
66
+ child.on('error', (err) => {
67
+ if (!hasOutput) {
68
+ console2.printSeparator('')
69
+ }
70
+ console2.error(err.message)
71
+ console2.printSeparator('')
72
+ resolve({ exitCode: 1, output: err.message })
73
+ })
74
+ })
75
+ }
76
+
77
+ // 设置程序
78
+ program
79
+ .name('pls')
80
+ .description('AI 驱动的命令行工具,将自然语言转换为可执行的 Shell 命令')
81
+ .version(packageJson.version, '-v, --version', '显示版本号')
82
+ .helpOption('-h, --help', '显示帮助信息')
83
+
84
+ // config 子命令
85
+ const configCmd = program.command('config').description('管理配置')
86
+
87
+ configCmd
88
+ .command('list')
89
+ .alias('show')
90
+ .description('查看当前配置')
91
+ .action(() => {
92
+ const config = getConfig()
93
+ const CONFIG_FILE = join(os.homedir(), '.please', 'config.json')
94
+
95
+ console.log('')
96
+ console2.title('当前配置:')
97
+ console2.muted('━'.repeat(40))
98
+ console.log(` ${chalk.hex('#00D9FF')('apiKey')}: ${maskApiKey(config.apiKey)}`)
99
+ console.log(` ${chalk.hex('#00D9FF')('baseUrl')}: ${config.baseUrl}`)
100
+ console.log(` ${chalk.hex('#00D9FF')('provider')}: ${config.provider}`)
101
+ console.log(` ${chalk.hex('#00D9FF')('model')}: ${config.model}`)
102
+ console.log(
103
+ ` ${chalk.hex('#00D9FF')('shellHook')}: ${
104
+ config.shellHook ? chalk.hex('#10B981')('已启用') : chalk.gray('未启用')
105
+ }`
106
+ )
107
+ console.log(` ${chalk.hex('#00D9FF')('chatHistoryLimit')}: ${config.chatHistoryLimit} 轮`)
108
+ console2.muted('━'.repeat(40))
109
+ console2.muted(`配置文件: ${CONFIG_FILE}`)
110
+ console.log('')
111
+ })
112
+
113
+ configCmd
114
+ .command('set <key> <value>')
115
+ .description('设置配置项 (apiKey, baseUrl, provider, model, shellHook, chatHistoryLimit)')
116
+ .action((key, value) => {
117
+ try {
118
+ setConfigValue(key, value)
119
+ console.log('')
120
+ console2.success(`已设置 ${key}`)
121
+ console.log('')
122
+ } catch (error: any) {
123
+ console.log('')
124
+ console2.error(error.message)
125
+ console.log('')
126
+ process.exit(1)
127
+ }
128
+ })
129
+
130
+ // 默认 config 命令(交互式配置)
131
+ configCmd.action(async () => {
132
+ const { runConfigWizard } = await import('../src/config.js')
133
+ await runConfigWizard()
134
+ })
135
+
136
+ // history 子命令
137
+ const historyCmd = program.command('history').description('查看或管理命令历史')
138
+
139
+ historyCmd
140
+ .command('show')
141
+ .description('显示历史记录')
142
+ .action(() => {
143
+ const history = getHistory()
144
+
145
+ if (history.length === 0) {
146
+ console.log('')
147
+ console2.muted('暂无历史记录')
148
+ console.log('')
149
+ return
150
+ }
151
+
152
+ console.log('')
153
+ console2.title('📜 命令历史:')
154
+ console2.muted('━'.repeat(50))
155
+
156
+ history.forEach((item: any, index: number) => {
157
+ const status = item.executed
158
+ ? item.exitCode === 0
159
+ ? chalk.hex('#10B981')('✓')
160
+ : chalk.hex('#EF4444')(`✗ 退出码:${item.exitCode}`)
161
+ : chalk.gray('(未执行)')
162
+
163
+ console.log(`\n${chalk.gray(`${index + 1}.`)} ${chalk.hex('#00D9FF')(item.userPrompt)}`)
164
+ console.log(` ${chalk.dim('→')} ${item.command} ${status}`)
165
+ console.log(` ${chalk.gray(item.timestamp)}`)
166
+ })
167
+
168
+ console.log('')
169
+ console2.muted(`历史文件: ${getHistoryFilePath()}`)
170
+ console.log('')
171
+ })
172
+
173
+ historyCmd
174
+ .command('clear')
175
+ .description('清空历史记录')
176
+ .action(() => {
177
+ clearHistory()
178
+ console.log('')
179
+ console2.success('历史记录已清空')
180
+ console.log('')
181
+ })
182
+
183
+ // 默认 history 命令(显示历史)
184
+ historyCmd.action(() => {
185
+ const history = getHistory()
186
+
187
+ if (history.length === 0) {
188
+ console.log('')
189
+ console2.muted('暂无历史记录')
190
+ console.log('')
191
+ return
192
+ }
193
+
194
+ console.log('')
195
+ console2.title('📜 命令历史:')
196
+ console2.muted('━'.repeat(50))
197
+
198
+ history.forEach((item: any, index: number) => {
199
+ const status = item.executed
200
+ ? item.exitCode === 0
201
+ ? chalk.hex('#10B981')('✓')
202
+ : chalk.hex('#EF4444')(`✗ 退出码:${item.exitCode}`)
203
+ : chalk.gray('(未执行)')
204
+
205
+ console.log(`\n${chalk.gray(`${index + 1}.`)} ${chalk.hex('#00D9FF')(item.userPrompt)}`)
206
+ console.log(` ${chalk.dim('→')} ${item.command} ${status}`)
207
+ console.log(` ${chalk.gray(item.timestamp)}`)
208
+ })
209
+
210
+ console.log('')
211
+ console2.muted(`历史文件: ${getHistoryFilePath()}`)
212
+ console.log('')
213
+ })
214
+
215
+ // hook 子命令
216
+ const hookCmd = program.command('hook').description('管理 shell hook(增强功能:记录终端命令历史)')
217
+
218
+ hookCmd
219
+ .command('install')
220
+ .description('安装 shell hook')
221
+ .action(async () => {
222
+ const shellType = detectShell()
223
+ const configPath = getShellConfigPath(shellType)
224
+
225
+ console.log('')
226
+ console2.title('🔧 Shell Hook 安装向导')
227
+ console2.muted('━'.repeat(40))
228
+ console2.muted(`检测到 Shell: ${shellType}`)
229
+ console2.muted(`配置文件: ${configPath || '未知'}`)
230
+ console.log('')
231
+
232
+ if (shellType === 'unknown') {
233
+ console2.error('不支持的 shell 类型')
234
+ console2.muted('支持的 shell: zsh, bash, powershell')
235
+ console.log('')
236
+ return
237
+ }
238
+
239
+ console2.warning('此功能会在你的 shell 配置文件中添加 hook,')
240
+ console2.warning('用于记录你在终端执行的每条命令,让 AI 更智能。')
241
+ console.log('')
242
+
243
+ const result = await installShellHook()
244
+ if (result) {
245
+ console2.success(`Shell hook 已安装`)
246
+ console2.warning(`⚠️ 请重启终端或执行: source ${configPath}`)
247
+ }
248
+ console.log('')
249
+ })
250
+
251
+ hookCmd
252
+ .command('uninstall')
253
+ .description('卸载 shell hook')
254
+ .action(() => {
255
+ console.log('')
256
+ uninstallShellHook()
257
+ console2.success('Shell hook 已卸载')
258
+ console2.warning('⚠️ 请重启终端使其生效')
259
+ console.log('')
260
+ })
261
+
262
+ hookCmd
263
+ .command('status')
264
+ .description('查看 shell hook 状态')
265
+ .action(() => {
266
+ const status = getHookStatus()
267
+
268
+ console.log('')
269
+ console2.title('📊 Shell Hook 状态')
270
+ console2.muted('━'.repeat(40))
271
+ console.log(` ${chalk.hex('#00D9FF')('Shell 类型')}: ${status.shellType}`)
272
+ console.log(` ${chalk.hex('#00D9FF')('配置文件')}: ${status.configPath || '未知'}`)
273
+ console.log(
274
+ ` ${chalk.hex('#00D9FF')('已安装')}: ${
275
+ status.installed ? chalk.hex('#10B981')('是') : chalk.gray('否')
276
+ }`
277
+ )
278
+ console.log(
279
+ ` ${chalk.hex('#00D9FF')('已启用')}: ${
280
+ status.enabled ? chalk.hex('#10B981')('是') : chalk.gray('否')
281
+ }`
282
+ )
283
+ console.log(` ${chalk.hex('#00D9FF')('历史文件')}: ${status.historyFile}`)
284
+ console2.muted('━'.repeat(40))
285
+
286
+ if (!status.installed) {
287
+ console.log('')
288
+ console2.muted('提示: 运行 pls hook install 安装 shell hook')
289
+ }
290
+ console.log('')
291
+ })
292
+
293
+ // 默认 hook 命令(显示状态)
294
+ hookCmd.action(() => {
295
+ const status = getHookStatus()
296
+
297
+ console.log('')
298
+ console2.title('📊 Shell Hook 状态')
299
+ console2.muted('━'.repeat(40))
300
+ console.log(` ${chalk.hex('#00D9FF')('Shell 类型')}: ${status.shellType}`)
301
+ console.log(` ${chalk.hex('#00D9FF')('配置文件')}: ${status.configPath || '未知'}`)
302
+ console.log(
303
+ ` ${chalk.hex('#00D9FF')('已安装')}: ${
304
+ status.installed ? chalk.hex('#10B981')('是') : chalk.gray('否')
305
+ }`
306
+ )
307
+ console.log(
308
+ ` ${chalk.hex('#00D9FF')('已启用')}: ${
309
+ status.enabled ? chalk.hex('#10B981')('是') : chalk.gray('否')
310
+ }`
311
+ )
312
+ console.log(` ${chalk.hex('#00D9FF')('历史文件')}: ${status.historyFile}`)
313
+ console2.muted('━'.repeat(40))
314
+
315
+ if (!status.installed) {
316
+ console.log('')
317
+ console2.muted('提示: 运行 pls hook install 安装 shell hook')
318
+ }
319
+ console.log('')
320
+ })
321
+
322
+ // chat 子命令
323
+ const chatCmd = program.command('chat').description('AI 对话模式,问答、讲解命令')
324
+
325
+ chatCmd
326
+ .command('clear')
327
+ .description('清空对话历史')
328
+ .action(() => {
329
+ clearChatHistory()
330
+ console.log('')
331
+ console2.success('对话历史已清空')
332
+ console.log('')
333
+ })
334
+
335
+ // 默认 chat 命令(进行对话)
336
+ chatCmd
337
+ .argument('[prompt...]', '你的问题')
338
+ .option('-d, --debug', '显示调试信息')
339
+ .action((promptArgs, options) => {
340
+ const prompt = promptArgs.join(' ')
341
+
342
+ if (!prompt.trim()) {
343
+ // 没有输入,显示对话状态
344
+ const roundCount = getChatRoundCount()
345
+ const historyFile = getChatHistoryFilePath()
346
+
347
+ console.log('')
348
+ console2.title('💬 AI 对话模式')
349
+ console2.muted('━'.repeat(40))
350
+ console.log(` ${chalk.hex('#00D9FF')('当前对话轮数')}: ${roundCount}`)
351
+ console.log(` ${chalk.hex('#00D9FF')('历史文件')}: ${historyFile}`)
352
+ console2.muted('━'.repeat(40))
353
+ console.log('')
354
+ console2.muted('用法:')
355
+ console2.info(' pls chat <问题> 与 AI 对话')
356
+ console2.info(' pls chat clear 清空对话历史')
357
+ console.log('')
358
+ return
359
+ }
360
+
361
+ // 检查配置
362
+ if (!isConfigValid()) {
363
+ console.log('')
364
+ console2.warning('⚠️ 检测到尚未配置 API Key')
365
+ console2.info('请运行 pls config 启动交互式配置向导')
366
+ console.log('')
367
+ process.exit(1)
368
+ }
369
+
370
+ // 使用 Ink 渲染对话(Chat 适合用 Ink 流式输出)
371
+ render(
372
+ <Chat
373
+ prompt={prompt}
374
+ debug={options.debug}
375
+ showRoundCount={true}
376
+ onComplete={() => process.exit(0)}
377
+ />
378
+ )
379
+ })
380
+
381
+ // 默认命令(执行 prompt)
382
+ program
383
+ .argument('[prompt...]', '自然语言描述你想执行的操作')
384
+ .option('-d, --debug', '显示调试信息(系统信息、完整 prompt 等)')
385
+ .action((promptArgs, options) => {
386
+ if (promptArgs.length === 0) {
387
+ program.help()
388
+ return
389
+ }
390
+
391
+ const prompt = promptArgs.join(' ')
392
+
393
+ if (!prompt.trim()) {
394
+ console.log('')
395
+ console2.error('请提供你想执行的操作描述')
396
+ console2.muted('示例: pls 安装 git')
397
+ console.log('')
398
+ process.exit(1)
399
+ }
400
+
401
+ // 检查配置
402
+ if (!isConfigValid()) {
403
+ console.log('')
404
+ console2.warning('⚠️ 检测到尚未配置 API Key')
405
+ console2.info('请运行 pls config 启动交互式配置向导')
406
+ console.log('')
407
+ process.exit(1)
408
+ }
409
+
410
+ // 使用多步骤命令生成器(统一处理单步和多步)
411
+ ;(async () => {
412
+ const executedSteps: ExecutedStep[] = []
413
+ let currentStepNumber = 1
414
+
415
+ while (true) {
416
+ let stepResult: any = null
417
+
418
+ // 使用 Ink 渲染命令生成
419
+ const { waitUntilExit, unmount } = render(
420
+ <MultiStepCommandGenerator
421
+ prompt={prompt}
422
+ debug={options.debug}
423
+ previousSteps={executedSteps}
424
+ currentStepNumber={currentStepNumber}
425
+ onStepComplete={(res) => {
426
+ stepResult = res
427
+ unmount()
428
+ }}
429
+ />
430
+ )
431
+
432
+ await waitUntilExit()
433
+ await new Promise((resolve) => setTimeout(resolve, 10))
434
+
435
+ // 处理步骤结果
436
+ if (!stepResult || stepResult.cancelled) {
437
+ console.log('')
438
+ console2.muted('已取消执行')
439
+ console.log('')
440
+ process.exit(0)
441
+ }
442
+
443
+ if (stepResult.hasBuiltin) {
444
+ addHistory({
445
+ userPrompt: currentStepNumber === 1 ? prompt : `[步骤${currentStepNumber}] ${prompt}`,
446
+ command: stepResult.command,
447
+ executed: false,
448
+ exitCode: null,
449
+ output: '',
450
+ reason: 'builtin',
451
+ })
452
+ process.exit(0)
453
+ }
454
+
455
+ if (stepResult.confirmed) {
456
+ // 执行命令
457
+ const execStart = Date.now()
458
+ const { exitCode, output } = await executeCommand(stepResult.command, prompt)
459
+ const execDuration = Date.now() - execStart
460
+
461
+ // 保存到执行历史
462
+ const executedStep: ExecutedStep = {
463
+ command: stepResult.command,
464
+ continue: stepResult.needsContinue || false,
465
+ reasoning: stepResult.reasoning,
466
+ nextStepHint: stepResult.nextStepHint,
467
+ exitCode,
468
+ output,
469
+ }
470
+ executedSteps.push(executedStep)
471
+
472
+ // 记录到 pls 历史
473
+ addHistory({
474
+ userPrompt:
475
+ currentStepNumber === 1 ? prompt : `[步骤${currentStepNumber}] ${stepResult.reasoning || prompt}`,
476
+ command: stepResult.command,
477
+ executed: true,
478
+ exitCode,
479
+ output,
480
+ })
481
+
482
+ // 显示结果
483
+ console.log('')
484
+ if (exitCode === 0) {
485
+ if (currentStepNumber === 1 && stepResult.needsContinue !== true) {
486
+ // 单步命令
487
+ console2.success(`执行完成 ${console2.formatDuration(execDuration)}`)
488
+ } else {
489
+ // 多步命令
490
+ console2.success(`步骤 ${currentStepNumber} 执行完成 ${console2.formatDuration(execDuration)}`)
491
+ }
492
+ } else {
493
+ // 执行失败,但不立即退出,让 AI 分析错误并调整策略
494
+ console2.error(
495
+ `步骤 ${currentStepNumber} 执行失败,退出码: ${exitCode} ${console2.formatDuration(execDuration)}`
496
+ )
497
+ console.log('')
498
+ console2.warning('正在请 AI 分析错误并调整策略...')
499
+ // 不退出,继续循环,AI 会收到错误信息
500
+ }
501
+
502
+ // 判断是否继续
503
+ if (stepResult.needsContinue !== true) {
504
+ if (currentStepNumber > 1) {
505
+ console.log('')
506
+ console2.success('✓ 所有步骤执行完成')
507
+ }
508
+ console.log('')
509
+ process.exit(0)
510
+ }
511
+
512
+ console.log('')
513
+ currentStepNumber++
514
+ }
515
+ }
516
+ })()
517
+ })
518
+
519
+ // 自定义帮助信息
520
+ program.addHelpText(
521
+ 'after',
522
+ `
523
+ ${chalk.bold('示例:')}
524
+ ${chalk.hex('#00D9FF')('pls 安装 git')} 让 AI 生成安装 git 的命令
525
+ ${chalk.hex('#00D9FF')('pls 查找大于 100MB 的文件')} 查找大文件
526
+ ${chalk.hex('#00D9FF')('pls 删除刚才创建的文件')} AI 会参考历史记录
527
+ ${chalk.hex('#00D9FF')('pls --debug 压缩 logs 目录')} 显示调试信息
528
+ ${chalk.hex('#00D9FF')('pls -m 删除当前目录的空文件夹')} 多步骤模式(AI 自动规划)
529
+ ${chalk.hex('#00D9FF')('pls chat tar 命令怎么用')} AI 对话模式
530
+ ${chalk.hex('#00D9FF')('pls chat clear')} 清空对话历史
531
+ ${chalk.hex('#00D9FF')('pls history')} 查看 pls 命令历史
532
+ ${chalk.hex('#00D9FF')('pls history clear')} 清空历史记录
533
+ ${chalk.hex('#00D9FF')('pls hook')} 查看 shell hook 状态
534
+ ${chalk.hex('#00D9FF')('pls hook install')} 安装 shell hook(增强功能)
535
+ ${chalk.hex('#00D9FF')('pls hook uninstall')} 卸载 shell hook
536
+ ${chalk.hex('#00D9FF')('pls config')} 交互式配置
537
+ ${chalk.hex('#00D9FF')('pls config list')} 查看当前配置
538
+ `
539
+ )
540
+
541
+ program.parse()
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};