@yivan-lab/pretty-please 1.1.0 → 1.2.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 (52) hide show
  1. package/README.md +283 -1
  2. package/bin/pls.tsx +1022 -104
  3. package/dist/bin/pls.js +894 -84
  4. package/dist/package.json +4 -4
  5. package/dist/src/alias.d.ts +41 -0
  6. package/dist/src/alias.js +240 -0
  7. package/dist/src/chat-history.js +10 -1
  8. package/dist/src/components/Chat.js +2 -1
  9. package/dist/src/components/CodeColorizer.js +26 -20
  10. package/dist/src/components/CommandBox.js +2 -1
  11. package/dist/src/components/ConfirmationPrompt.js +2 -1
  12. package/dist/src/components/Duration.js +2 -1
  13. package/dist/src/components/InlineRenderer.js +2 -1
  14. package/dist/src/components/MarkdownDisplay.js +2 -1
  15. package/dist/src/components/MultiStepCommandGenerator.d.ts +3 -1
  16. package/dist/src/components/MultiStepCommandGenerator.js +20 -10
  17. package/dist/src/components/TableRenderer.js +2 -1
  18. package/dist/src/config.d.ts +34 -3
  19. package/dist/src/config.js +71 -31
  20. package/dist/src/multi-step.d.ts +22 -6
  21. package/dist/src/multi-step.js +27 -4
  22. package/dist/src/remote-history.d.ts +63 -0
  23. package/dist/src/remote-history.js +315 -0
  24. package/dist/src/remote.d.ts +113 -0
  25. package/dist/src/remote.js +634 -0
  26. package/dist/src/shell-hook.d.ts +53 -0
  27. package/dist/src/shell-hook.js +242 -19
  28. package/dist/src/ui/theme.d.ts +27 -24
  29. package/dist/src/ui/theme.js +71 -21
  30. package/dist/src/upgrade.d.ts +41 -0
  31. package/dist/src/upgrade.js +348 -0
  32. package/dist/src/utils/console.js +22 -11
  33. package/package.json +4 -4
  34. package/src/alias.ts +301 -0
  35. package/src/chat-history.ts +11 -1
  36. package/src/components/Chat.tsx +2 -1
  37. package/src/components/CodeColorizer.tsx +27 -19
  38. package/src/components/CommandBox.tsx +2 -1
  39. package/src/components/ConfirmationPrompt.tsx +2 -1
  40. package/src/components/Duration.tsx +2 -1
  41. package/src/components/InlineRenderer.tsx +2 -1
  42. package/src/components/MarkdownDisplay.tsx +2 -1
  43. package/src/components/MultiStepCommandGenerator.tsx +25 -11
  44. package/src/components/TableRenderer.tsx +2 -1
  45. package/src/config.ts +117 -32
  46. package/src/multi-step.ts +43 -6
  47. package/src/remote-history.ts +390 -0
  48. package/src/remote.ts +800 -0
  49. package/src/shell-hook.ts +271 -19
  50. package/src/ui/theme.ts +101 -24
  51. package/src/upgrade.ts +397 -0
  52. package/src/utils/console.ts +22 -11
package/src/config.ts CHANGED
@@ -3,6 +3,18 @@ import path from 'path'
3
3
  import os from 'os'
4
4
  import readline from 'readline'
5
5
  import chalk from 'chalk'
6
+ import { getCurrentTheme } from './ui/theme.js'
7
+
8
+ // 获取主题颜色
9
+ function getColors() {
10
+ const theme = getCurrentTheme()
11
+ return {
12
+ primary: theme.primary,
13
+ secondary: theme.secondary,
14
+ success: theme.success,
15
+ error: theme.error
16
+ }
17
+ }
6
18
 
7
19
  // 配置文件路径
8
20
  export const CONFIG_DIR = path.join(os.homedir(), '.please')
@@ -27,6 +39,41 @@ type Provider = (typeof VALID_PROVIDERS)[number]
27
39
  const VALID_EDIT_MODES = ['manual', 'auto'] as const
28
40
  type EditMode = (typeof VALID_EDIT_MODES)[number]
29
41
 
42
+ // 主题
43
+ const VALID_THEMES = ['dark', 'light'] as const
44
+ export type ThemeName = (typeof VALID_THEMES)[number]
45
+
46
+ /**
47
+ * 别名配置接口
48
+ */
49
+ export interface AliasConfig {
50
+ prompt: string
51
+ description?: string
52
+ }
53
+
54
+ /**
55
+ * 远程服务器配置接口
56
+ */
57
+ export interface RemoteConfig {
58
+ host: string
59
+ user: string
60
+ port: number
61
+ key?: string // SSH 私钥路径
62
+ password?: boolean // 是否使用密码认证(密码不存储,每次交互输入)
63
+ workDir?: string // 默认工作目录
64
+ }
65
+
66
+ /**
67
+ * 远程服务器系统信息缓存
68
+ */
69
+ export interface RemoteSysInfo {
70
+ os: string // 操作系统 (linux, darwin, etc.)
71
+ osVersion: string // 系统版本
72
+ shell: string // 默认 shell (bash, zsh, etc.)
73
+ hostname: string // 主机名
74
+ cachedAt: string // 缓存时间
75
+ }
76
+
30
77
  /**
31
78
  * 配置接口
32
79
  */
@@ -40,6 +87,10 @@ export interface Config {
40
87
  commandHistoryLimit: number
41
88
  shellHistoryLimit: number
42
89
  editMode: EditMode
90
+ theme: ThemeName
91
+ aliases: Record<string, AliasConfig>
92
+ remotes: Record<string, RemoteConfig> // 远程服务器配置
93
+ defaultRemote?: string // 默认远程服务器名称
43
94
  }
44
95
 
45
96
  /**
@@ -55,6 +106,10 @@ const DEFAULT_CONFIG: Config = {
55
106
  commandHistoryLimit: 10,
56
107
  shellHistoryLimit: 15,
57
108
  editMode: 'manual',
109
+ theme: 'dark',
110
+ aliases: {},
111
+ remotes: {},
112
+ defaultRemote: '',
58
113
  }
59
114
 
60
115
  /**
@@ -68,20 +123,33 @@ function ensureConfigDir(): void {
68
123
 
69
124
  /**
70
125
  * 读取配置
126
+ * 优化:添加缓存,避免重复读取文件
71
127
  */
128
+ let cachedConfig: Config | null = null
129
+
72
130
  export function getConfig(): Config {
131
+ // 如果已有缓存,直接返回
132
+ if (cachedConfig !== null) {
133
+ return cachedConfig
134
+ }
135
+
73
136
  ensureConfigDir()
74
137
 
138
+ let config: Config
139
+
75
140
  if (!fs.existsSync(CONFIG_FILE)) {
76
- return { ...DEFAULT_CONFIG }
141
+ config = { ...DEFAULT_CONFIG }
142
+ } else {
143
+ try {
144
+ const content = fs.readFileSync(CONFIG_FILE, 'utf-8')
145
+ config = { ...DEFAULT_CONFIG, ...JSON.parse(content) }
146
+ } catch {
147
+ config = { ...DEFAULT_CONFIG }
148
+ }
77
149
  }
78
150
 
79
- try {
80
- const content = fs.readFileSync(CONFIG_FILE, 'utf-8')
81
- return { ...DEFAULT_CONFIG, ...JSON.parse(content) }
82
- } catch {
83
- return { ...DEFAULT_CONFIG }
84
- }
151
+ cachedConfig = config
152
+ return config
85
153
  }
86
154
 
87
155
  /**
@@ -123,11 +191,21 @@ export function setConfigValue(key: string, value: string | boolean | number): C
123
191
  throw new Error(`editMode 必须是以下之一: ${VALID_EDIT_MODES.join(', ')}`)
124
192
  }
125
193
  config.editMode = strValue as EditMode
126
- } else if (key === 'apiKey' || key === 'baseUrl' || key === 'model') {
194
+ } else if (key === 'theme') {
195
+ const strValue = String(value)
196
+ if (!VALID_THEMES.includes(strValue as ThemeName)) {
197
+ throw new Error(`theme 必须是以下之一: ${VALID_THEMES.join(', ')}`)
198
+ }
199
+ config.theme = strValue as ThemeName
200
+ } else if (key === 'apiKey' || key === 'baseUrl' || key === 'model' || key === 'defaultRemote') {
127
201
  config[key] = String(value)
128
202
  }
129
203
 
130
204
  saveConfig(config)
205
+
206
+ // 清除缓存,下次读取时会重新加载
207
+ cachedConfig = null
208
+
131
209
  return config
132
210
  }
133
211
 
@@ -152,23 +230,29 @@ export function maskApiKey(apiKey: string): string {
152
230
  */
153
231
  export function displayConfig(): void {
154
232
  const config = getConfig()
233
+ const colors = getColors()
155
234
  console.log(chalk.bold('\n当前配置:'))
156
235
  console.log(chalk.gray('━'.repeat(50)))
157
- console.log(` ${chalk.cyan('apiKey')}: ${maskApiKey(config.apiKey)}`)
158
- console.log(` ${chalk.cyan('baseUrl')}: ${config.baseUrl}`)
159
- console.log(` ${chalk.cyan('provider')}: ${config.provider}`)
160
- console.log(` ${chalk.cyan('model')}: ${config.model}`)
236
+ console.log(` ${chalk.hex(colors.primary)('apiKey')}: ${maskApiKey(config.apiKey)}`)
237
+ console.log(` ${chalk.hex(colors.primary)('baseUrl')}: ${config.baseUrl}`)
238
+ console.log(` ${chalk.hex(colors.primary)('provider')}: ${config.provider}`)
239
+ console.log(` ${chalk.hex(colors.primary)('model')}: ${config.model}`)
161
240
  console.log(
162
- ` ${chalk.cyan('shellHook')}: ${config.shellHook ? chalk.green('已启用') : chalk.gray('未启用')}`
241
+ ` ${chalk.hex(colors.primary)('shellHook')}: ${config.shellHook ? chalk.hex(colors.success)('已启用') : chalk.gray('未启用')}`
242
+ )
243
+ console.log(
244
+ ` ${chalk.hex(colors.primary)('editMode')}: ${
245
+ config.editMode === 'auto' ? chalk.hex(colors.primary)('auto (自动编辑)') : chalk.gray('manual (按E编辑)')
246
+ }`
163
247
  )
248
+ console.log(` ${chalk.hex(colors.primary)('chatHistoryLimit')}: ${config.chatHistoryLimit} 轮`)
249
+ console.log(` ${chalk.hex(colors.primary)('commandHistoryLimit')}: ${config.commandHistoryLimit} 条`)
250
+ console.log(` ${chalk.hex(colors.primary)('shellHistoryLimit')}: ${config.shellHistoryLimit} 条`)
164
251
  console.log(
165
- ` ${chalk.cyan('editMode')}: ${
166
- config.editMode === 'auto' ? chalk.hex('#00D9FF')('auto (自动编辑)') : chalk.gray('manual (按E编辑)')
252
+ ` ${chalk.hex(colors.primary)('theme')}: ${
253
+ config.theme === 'dark' ? chalk.hex(colors.primary)('dark (深色)') : chalk.hex(colors.primary)('light (浅色)')
167
254
  }`
168
255
  )
169
- console.log(` ${chalk.cyan('chatHistoryLimit')}: ${config.chatHistoryLimit} 轮`)
170
- console.log(` ${chalk.cyan('commandHistoryLimit')}: ${config.commandHistoryLimit} 条`)
171
- console.log(` ${chalk.cyan('shellHistoryLimit')}: ${config.shellHistoryLimit} 条`)
172
256
  console.log(chalk.gray('━'.repeat(50)))
173
257
  console.log(chalk.gray(`配置文件: ${CONFIG_FILE}\n`))
174
258
  }
@@ -200,19 +284,20 @@ function question(rl: readline.Interface, prompt: string): Promise<string> {
200
284
  export async function runConfigWizard(): Promise<void> {
201
285
  const rl = createReadlineInterface()
202
286
  const config = getConfig()
287
+ const colors = getColors()
203
288
 
204
- console.log(chalk.bold.hex('#00D9FF')('\n🔧 Pretty Please 配置向导'))
289
+ console.log(chalk.bold.hex(colors.primary)('\n🔧 Pretty Please 配置向导'))
205
290
  console.log(chalk.gray('━'.repeat(50)))
206
291
  console.log(chalk.gray('直接回车使用默认值,输入值后回车确认\n'))
207
292
 
208
293
  try {
209
294
  // 1. Provider
210
295
  const providerHint = chalk.gray(`(可选: ${VALID_PROVIDERS.join(', ')})`)
211
- const providerPrompt = `${chalk.cyan('Provider')} ${providerHint}\n${chalk.gray('默认:')} ${chalk.yellow(config.provider)} ${chalk.gray('→')} `
296
+ const providerPrompt = `${chalk.hex(colors.primary)('Provider')} ${providerHint}\n${chalk.gray('默认:')} ${chalk.hex(colors.secondary)(config.provider)} ${chalk.gray('→')} `
212
297
  const provider = await question(rl, providerPrompt)
213
298
  if (provider.trim()) {
214
299
  if (!VALID_PROVIDERS.includes(provider.trim() as Provider)) {
215
- console.log(chalk.hex('#EF4444')(`\n✗ 无效的 provider,必须是以下之一: ${VALID_PROVIDERS.join(', ')}`))
300
+ console.log(chalk.hex(colors.error)(`\n✗ 无效的 provider,必须是以下之一: ${VALID_PROVIDERS.join(', ')}`))
216
301
  console.log()
217
302
  rl.close()
218
303
  return
@@ -221,7 +306,7 @@ export async function runConfigWizard(): Promise<void> {
221
306
  }
222
307
 
223
308
  // 2. Base URL
224
- const baseUrlPrompt = `${chalk.cyan('API Base URL')}\n${chalk.gray('默认:')} ${chalk.yellow(config.baseUrl)} ${chalk.gray('→')} `
309
+ const baseUrlPrompt = `${chalk.hex(colors.primary)('API Base URL')}\n${chalk.gray('默认:')} ${chalk.hex(colors.secondary)(config.baseUrl)} ${chalk.gray('→')} `
225
310
  const baseUrl = await question(rl, baseUrlPrompt)
226
311
  if (baseUrl.trim()) {
227
312
  config.baseUrl = baseUrl.trim()
@@ -229,21 +314,21 @@ export async function runConfigWizard(): Promise<void> {
229
314
 
230
315
  // 3. API Key
231
316
  const currentKeyDisplay = config.apiKey ? maskApiKey(config.apiKey) : '(未设置)'
232
- const apiKeyPrompt = `${chalk.cyan('API Key')} ${chalk.gray(`(当前: ${currentKeyDisplay})`)}\n${chalk.gray('→')} `
317
+ const apiKeyPrompt = `${chalk.hex(colors.primary)('API Key')} ${chalk.gray(`(当前: ${currentKeyDisplay})`)}\n${chalk.gray('→')} `
233
318
  const apiKey = await question(rl, apiKeyPrompt)
234
319
  if (apiKey.trim()) {
235
320
  config.apiKey = apiKey.trim()
236
321
  }
237
322
 
238
323
  // 4. Model
239
- const modelPrompt = `${chalk.cyan('Model')}\n${chalk.gray('默认:')} ${chalk.yellow(config.model)} ${chalk.gray('→')} `
324
+ const modelPrompt = `${chalk.hex(colors.primary)('Model')}\n${chalk.gray('默认:')} ${chalk.hex(colors.secondary)(config.model)} ${chalk.gray('→')} `
240
325
  const model = await question(rl, modelPrompt)
241
326
  if (model.trim()) {
242
327
  config.model = model.trim()
243
328
  }
244
329
 
245
330
  // 5. Shell Hook
246
- const shellHookPrompt = `${chalk.cyan('启用 Shell Hook')} ${chalk.gray('(记录终端命令历史)')}\n${chalk.gray('默认:')} ${chalk.yellow(config.shellHook ? 'true' : 'false')} ${chalk.gray('→')} `
331
+ const shellHookPrompt = `${chalk.hex(colors.primary)('启用 Shell Hook')} ${chalk.gray('(记录终端命令历史)')}\n${chalk.gray('默认:')} ${chalk.hex(colors.secondary)(config.shellHook ? 'true' : 'false')} ${chalk.gray('→')} `
247
332
  const shellHook = await question(rl, shellHookPrompt)
248
333
  if (shellHook.trim()) {
249
334
  config.shellHook = shellHook.trim() === 'true'
@@ -251,11 +336,11 @@ export async function runConfigWizard(): Promise<void> {
251
336
 
252
337
  // 6. Edit Mode
253
338
  const editModeHint = chalk.gray('(manual=按E编辑, auto=自动编辑)')
254
- const editModePrompt = `${chalk.cyan('编辑模式')} ${editModeHint}\n${chalk.gray('默认:')} ${chalk.yellow(config.editMode)} ${chalk.gray('→')} `
339
+ const editModePrompt = `${chalk.hex(colors.primary)('编辑模式')} ${editModeHint}\n${chalk.gray('默认:')} ${chalk.hex(colors.secondary)(config.editMode)} ${chalk.gray('→')} `
255
340
  const editMode = await question(rl, editModePrompt)
256
341
  if (editMode.trim()) {
257
342
  if (!VALID_EDIT_MODES.includes(editMode.trim() as EditMode)) {
258
- console.log(chalk.hex('#EF4444')(`\n✗ 无效的 editMode,必须是: manual 或 auto`))
343
+ console.log(chalk.hex(colors.error)(`\n✗ 无效的 editMode,必须是: manual 或 auto`))
259
344
  console.log()
260
345
  rl.close()
261
346
  return
@@ -264,7 +349,7 @@ export async function runConfigWizard(): Promise<void> {
264
349
  }
265
350
 
266
351
  // 7. Chat History Limit
267
- const chatHistoryPrompt = `${chalk.cyan('Chat 历史保留轮数')}\n${chalk.gray('默认:')} ${chalk.yellow(config.chatHistoryLimit)} ${chalk.gray('→')} `
352
+ const chatHistoryPrompt = `${chalk.hex(colors.primary)('Chat 历史保留轮数')}\n${chalk.gray('默认:')} ${chalk.hex(colors.secondary)(config.chatHistoryLimit)} ${chalk.gray('→')} `
268
353
  const chatHistoryLimit = await question(rl, chatHistoryPrompt)
269
354
  if (chatHistoryLimit.trim()) {
270
355
  const num = parseInt(chatHistoryLimit.trim(), 10)
@@ -274,7 +359,7 @@ export async function runConfigWizard(): Promise<void> {
274
359
  }
275
360
 
276
361
  // 8. Command History Limit
277
- const commandHistoryPrompt = `${chalk.cyan('命令历史保留条数')}\n${chalk.gray('默认:')} ${chalk.yellow(config.commandHistoryLimit)} ${chalk.gray('→')} `
362
+ const commandHistoryPrompt = `${chalk.hex(colors.primary)('命令历史保留条数')}\n${chalk.gray('默认:')} ${chalk.hex(colors.secondary)(config.commandHistoryLimit)} ${chalk.gray('→')} `
278
363
  const commandHistoryLimit = await question(rl, commandHistoryPrompt)
279
364
  if (commandHistoryLimit.trim()) {
280
365
  const num = parseInt(commandHistoryLimit.trim(), 10)
@@ -284,7 +369,7 @@ export async function runConfigWizard(): Promise<void> {
284
369
  }
285
370
 
286
371
  // 9. Shell History Limit
287
- const shellHistoryPrompt = `${chalk.cyan('Shell 历史保留条数')}\n${chalk.gray('默认:')} ${chalk.yellow(config.shellHistoryLimit)} ${chalk.gray('→')} `
372
+ const shellHistoryPrompt = `${chalk.hex(colors.primary)('Shell 历史保留条数')}\n${chalk.gray('默认:')} ${chalk.hex(colors.secondary)(config.shellHistoryLimit)} ${chalk.gray('→')} `
288
373
  const shellHistoryLimit = await question(rl, shellHistoryPrompt)
289
374
  if (shellHistoryLimit.trim()) {
290
375
  const num = parseInt(shellHistoryLimit.trim(), 10)
@@ -296,12 +381,12 @@ export async function runConfigWizard(): Promise<void> {
296
381
  saveConfig(config)
297
382
 
298
383
  console.log('\n' + chalk.gray('━'.repeat(50)))
299
- console.log(chalk.hex('#10B981')('✅ 配置已保存'))
384
+ console.log(chalk.hex(getColors().success)('✅ 配置已保存'))
300
385
  console.log(chalk.gray(` ${CONFIG_FILE}`))
301
386
  console.log()
302
387
  } catch (error) {
303
388
  const message = error instanceof Error ? error.message : String(error)
304
- console.log(chalk.hex('#EF4444')(`\n✗ 配置失败: ${message}`))
389
+ console.log(chalk.hex(getColors().error)(`\n✗ 配置失败: ${message}`))
305
390
  console.log()
306
391
  } finally {
307
392
  rl.close()
package/src/multi-step.ts CHANGED
@@ -4,16 +4,19 @@ import { buildCommandSystemPrompt } from './prompts.js'
4
4
  import { formatSystemInfo } from './sysinfo.js'
5
5
  import { formatHistoryForAI } from './history.js'
6
6
  import { formatShellHistoryForAI, getShellHistory } from './shell-hook.js'
7
- import { getConfig } from './config.js'
7
+ import { getConfig, type RemoteSysInfo } from './config.js'
8
+ import { formatRemoteHistoryForAI, formatRemoteShellHistoryForAI, type RemoteShellHistoryItem } from './remote-history.js'
9
+ import { formatRemoteSysInfoForAI } from './remote.js'
8
10
 
9
11
  /**
10
12
  * 多步骤命令的 Zod Schema
13
+ * 注意:optional 字段使用 .default() 是为了绕过 Mastra 0.24.8 对 optional 字段的验证 bug
11
14
  */
12
15
  export const CommandStepSchema = z.object({
13
16
  command: z.string(),
14
- continue: z.boolean().optional(), // 可选!没有 continue = 单步模式
15
- reasoning: z.string().optional(),
16
- nextStepHint: z.string().optional(),
17
+ continue: z.boolean().optional().default(false),
18
+ reasoning: z.string().optional().default(''),
19
+ nextStepHint: z.string().optional().default(''),
17
20
  })
18
21
 
19
22
  export type CommandStep = z.infer<typeof CommandStepSchema>
@@ -26,6 +29,15 @@ export interface ExecutedStep extends CommandStep {
26
29
  output: string
27
30
  }
28
31
 
32
+ /**
33
+ * 远程执行上下文
34
+ */
35
+ export interface RemoteContext {
36
+ name: string
37
+ sysInfo: RemoteSysInfo
38
+ shellHistory: RemoteShellHistoryItem[]
39
+ }
40
+
29
41
  /**
30
42
  * 生成系统上下文信息(供 Mastra 使用)
31
43
  */
@@ -39,16 +51,37 @@ export function getFullSystemPrompt() {
39
51
  return buildCommandSystemPrompt(sysinfo, plsHistory, shellHistory, shellHookEnabled)
40
52
  }
41
53
 
54
+ /**
55
+ * 生成远程系统上下文信息
56
+ */
57
+ export function getRemoteFullSystemPrompt(remoteContext: RemoteContext) {
58
+ // 格式化远程系统信息
59
+ const sysinfo = formatRemoteSysInfoForAI(remoteContext.name, remoteContext.sysInfo)
60
+
61
+ // 格式化远程 pls 命令历史
62
+ const plsHistory = formatRemoteHistoryForAI(remoteContext.name)
63
+
64
+ // 格式化远程 shell 历史
65
+ const shellHistory = formatRemoteShellHistoryForAI(remoteContext.shellHistory)
66
+ const shellHookEnabled = remoteContext.shellHistory.length > 0
67
+
68
+ return buildCommandSystemPrompt(sysinfo, plsHistory, shellHistory, shellHookEnabled)
69
+ }
70
+
42
71
  /**
43
72
  * 使用 Mastra 生成多步骤命令
44
73
  */
45
74
  export async function generateMultiStepCommand(
46
75
  userPrompt: string,
47
76
  previousSteps: ExecutedStep[] = [],
48
- options: { debug?: boolean } = {}
77
+ options: { debug?: boolean; remoteContext?: RemoteContext } = {}
49
78
  ): Promise<{ stepData: CommandStep; debugInfo?: any }> {
50
79
  const agent = createShellAgent()
51
- const fullSystemPrompt = getFullSystemPrompt()
80
+
81
+ // 根据是否有远程上下文选择不同的系统提示词
82
+ const fullSystemPrompt = options.remoteContext
83
+ ? getRemoteFullSystemPrompt(options.remoteContext)
84
+ : getFullSystemPrompt()
52
85
 
53
86
  // 构建消息数组(string[] 格式)
54
87
  const messages: string[] = [userPrompt]
@@ -85,6 +118,10 @@ export async function generateMultiStepCommand(
85
118
  userPrompt,
86
119
  previousStepsCount: previousSteps.length,
87
120
  response: stepData,
121
+ remoteContext: options.remoteContext ? {
122
+ name: options.remoteContext.name,
123
+ sysInfo: options.remoteContext.sysInfo,
124
+ } : undefined,
88
125
  },
89
126
  }
90
127
  }