@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.
- package/README.md +283 -1
- package/bin/pls.tsx +1022 -104
- package/dist/bin/pls.js +894 -84
- package/dist/package.json +4 -4
- package/dist/src/alias.d.ts +41 -0
- package/dist/src/alias.js +240 -0
- package/dist/src/chat-history.js +10 -1
- package/dist/src/components/Chat.js +2 -1
- package/dist/src/components/CodeColorizer.js +26 -20
- package/dist/src/components/CommandBox.js +2 -1
- package/dist/src/components/ConfirmationPrompt.js +2 -1
- package/dist/src/components/Duration.js +2 -1
- package/dist/src/components/InlineRenderer.js +2 -1
- package/dist/src/components/MarkdownDisplay.js +2 -1
- package/dist/src/components/MultiStepCommandGenerator.d.ts +3 -1
- package/dist/src/components/MultiStepCommandGenerator.js +20 -10
- package/dist/src/components/TableRenderer.js +2 -1
- package/dist/src/config.d.ts +34 -3
- package/dist/src/config.js +71 -31
- package/dist/src/multi-step.d.ts +22 -6
- package/dist/src/multi-step.js +27 -4
- package/dist/src/remote-history.d.ts +63 -0
- package/dist/src/remote-history.js +315 -0
- package/dist/src/remote.d.ts +113 -0
- package/dist/src/remote.js +634 -0
- package/dist/src/shell-hook.d.ts +53 -0
- package/dist/src/shell-hook.js +242 -19
- package/dist/src/ui/theme.d.ts +27 -24
- package/dist/src/ui/theme.js +71 -21
- package/dist/src/upgrade.d.ts +41 -0
- package/dist/src/upgrade.js +348 -0
- package/dist/src/utils/console.js +22 -11
- package/package.json +4 -4
- package/src/alias.ts +301 -0
- package/src/chat-history.ts +11 -1
- package/src/components/Chat.tsx +2 -1
- package/src/components/CodeColorizer.tsx +27 -19
- package/src/components/CommandBox.tsx +2 -1
- package/src/components/ConfirmationPrompt.tsx +2 -1
- package/src/components/Duration.tsx +2 -1
- package/src/components/InlineRenderer.tsx +2 -1
- package/src/components/MarkdownDisplay.tsx +2 -1
- package/src/components/MultiStepCommandGenerator.tsx +25 -11
- package/src/components/TableRenderer.tsx +2 -1
- package/src/config.ts +117 -32
- package/src/multi-step.ts +43 -6
- package/src/remote-history.ts +390 -0
- package/src/remote.ts +800 -0
- package/src/shell-hook.ts +271 -19
- package/src/ui/theme.ts +101 -24
- package/src/upgrade.ts +397 -0
- package/src/utils/console.ts +22 -11
package/dist/src/config.d.ts
CHANGED
|
@@ -3,6 +3,36 @@ declare const VALID_PROVIDERS: readonly ["openai", "anthropic", "deepseek", "goo
|
|
|
3
3
|
type Provider = (typeof VALID_PROVIDERS)[number];
|
|
4
4
|
declare const VALID_EDIT_MODES: readonly ["manual", "auto"];
|
|
5
5
|
type EditMode = (typeof VALID_EDIT_MODES)[number];
|
|
6
|
+
declare const VALID_THEMES: readonly ["dark", "light"];
|
|
7
|
+
export type ThemeName = (typeof VALID_THEMES)[number];
|
|
8
|
+
/**
|
|
9
|
+
* 别名配置接口
|
|
10
|
+
*/
|
|
11
|
+
export interface AliasConfig {
|
|
12
|
+
prompt: string;
|
|
13
|
+
description?: string;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* 远程服务器配置接口
|
|
17
|
+
*/
|
|
18
|
+
export interface RemoteConfig {
|
|
19
|
+
host: string;
|
|
20
|
+
user: string;
|
|
21
|
+
port: number;
|
|
22
|
+
key?: string;
|
|
23
|
+
password?: boolean;
|
|
24
|
+
workDir?: string;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* 远程服务器系统信息缓存
|
|
28
|
+
*/
|
|
29
|
+
export interface RemoteSysInfo {
|
|
30
|
+
os: string;
|
|
31
|
+
osVersion: string;
|
|
32
|
+
shell: string;
|
|
33
|
+
hostname: string;
|
|
34
|
+
cachedAt: string;
|
|
35
|
+
}
|
|
6
36
|
/**
|
|
7
37
|
* 配置接口
|
|
8
38
|
*/
|
|
@@ -16,10 +46,11 @@ export interface Config {
|
|
|
16
46
|
commandHistoryLimit: number;
|
|
17
47
|
shellHistoryLimit: number;
|
|
18
48
|
editMode: EditMode;
|
|
49
|
+
theme: ThemeName;
|
|
50
|
+
aliases: Record<string, AliasConfig>;
|
|
51
|
+
remotes: Record<string, RemoteConfig>;
|
|
52
|
+
defaultRemote?: string;
|
|
19
53
|
}
|
|
20
|
-
/**
|
|
21
|
-
* 读取配置
|
|
22
|
-
*/
|
|
23
54
|
export declare function getConfig(): Config;
|
|
24
55
|
/**
|
|
25
56
|
* 保存配置
|
package/dist/src/config.js
CHANGED
|
@@ -3,6 +3,17 @@ 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
|
+
function getColors() {
|
|
9
|
+
const theme = getCurrentTheme();
|
|
10
|
+
return {
|
|
11
|
+
primary: theme.primary,
|
|
12
|
+
secondary: theme.secondary,
|
|
13
|
+
success: theme.success,
|
|
14
|
+
error: theme.error
|
|
15
|
+
};
|
|
16
|
+
}
|
|
6
17
|
// 配置文件路径
|
|
7
18
|
export const CONFIG_DIR = path.join(os.homedir(), '.please');
|
|
8
19
|
const CONFIG_FILE = path.join(CONFIG_DIR, 'config.json');
|
|
@@ -20,6 +31,8 @@ const VALID_PROVIDERS = [
|
|
|
20
31
|
];
|
|
21
32
|
// 编辑模式
|
|
22
33
|
const VALID_EDIT_MODES = ['manual', 'auto'];
|
|
34
|
+
// 主题
|
|
35
|
+
const VALID_THEMES = ['dark', 'light'];
|
|
23
36
|
/**
|
|
24
37
|
* 默认配置
|
|
25
38
|
*/
|
|
@@ -33,6 +46,10 @@ const DEFAULT_CONFIG = {
|
|
|
33
46
|
commandHistoryLimit: 10,
|
|
34
47
|
shellHistoryLimit: 15,
|
|
35
48
|
editMode: 'manual',
|
|
49
|
+
theme: 'dark',
|
|
50
|
+
aliases: {},
|
|
51
|
+
remotes: {},
|
|
52
|
+
defaultRemote: '',
|
|
36
53
|
};
|
|
37
54
|
/**
|
|
38
55
|
* 确保配置目录存在
|
|
@@ -44,19 +61,30 @@ function ensureConfigDir() {
|
|
|
44
61
|
}
|
|
45
62
|
/**
|
|
46
63
|
* 读取配置
|
|
64
|
+
* 优化:添加缓存,避免重复读取文件
|
|
47
65
|
*/
|
|
66
|
+
let cachedConfig = null;
|
|
48
67
|
export function getConfig() {
|
|
68
|
+
// 如果已有缓存,直接返回
|
|
69
|
+
if (cachedConfig !== null) {
|
|
70
|
+
return cachedConfig;
|
|
71
|
+
}
|
|
49
72
|
ensureConfigDir();
|
|
73
|
+
let config;
|
|
50
74
|
if (!fs.existsSync(CONFIG_FILE)) {
|
|
51
|
-
|
|
75
|
+
config = { ...DEFAULT_CONFIG };
|
|
52
76
|
}
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
77
|
+
else {
|
|
78
|
+
try {
|
|
79
|
+
const content = fs.readFileSync(CONFIG_FILE, 'utf-8');
|
|
80
|
+
config = { ...DEFAULT_CONFIG, ...JSON.parse(content) };
|
|
81
|
+
}
|
|
82
|
+
catch {
|
|
83
|
+
config = { ...DEFAULT_CONFIG };
|
|
84
|
+
}
|
|
59
85
|
}
|
|
86
|
+
cachedConfig = config;
|
|
87
|
+
return config;
|
|
60
88
|
}
|
|
61
89
|
/**
|
|
62
90
|
* 保存配置
|
|
@@ -98,10 +126,19 @@ export function setConfigValue(key, value) {
|
|
|
98
126
|
}
|
|
99
127
|
config.editMode = strValue;
|
|
100
128
|
}
|
|
101
|
-
else if (key === '
|
|
129
|
+
else if (key === 'theme') {
|
|
130
|
+
const strValue = String(value);
|
|
131
|
+
if (!VALID_THEMES.includes(strValue)) {
|
|
132
|
+
throw new Error(`theme 必须是以下之一: ${VALID_THEMES.join(', ')}`);
|
|
133
|
+
}
|
|
134
|
+
config.theme = strValue;
|
|
135
|
+
}
|
|
136
|
+
else if (key === 'apiKey' || key === 'baseUrl' || key === 'model' || key === 'defaultRemote') {
|
|
102
137
|
config[key] = String(value);
|
|
103
138
|
}
|
|
104
139
|
saveConfig(config);
|
|
140
|
+
// 清除缓存,下次读取时会重新加载
|
|
141
|
+
cachedConfig = null;
|
|
105
142
|
return config;
|
|
106
143
|
}
|
|
107
144
|
/**
|
|
@@ -124,17 +161,19 @@ export function maskApiKey(apiKey) {
|
|
|
124
161
|
*/
|
|
125
162
|
export function displayConfig() {
|
|
126
163
|
const config = getConfig();
|
|
164
|
+
const colors = getColors();
|
|
127
165
|
console.log(chalk.bold('\n当前配置:'));
|
|
128
166
|
console.log(chalk.gray('━'.repeat(50)));
|
|
129
|
-
console.log(` ${chalk.
|
|
130
|
-
console.log(` ${chalk.
|
|
131
|
-
console.log(` ${chalk.
|
|
132
|
-
console.log(` ${chalk.
|
|
133
|
-
console.log(` ${chalk.
|
|
134
|
-
console.log(` ${chalk.
|
|
135
|
-
console.log(` ${chalk.
|
|
136
|
-
console.log(` ${chalk.
|
|
137
|
-
console.log(` ${chalk.
|
|
167
|
+
console.log(` ${chalk.hex(colors.primary)('apiKey')}: ${maskApiKey(config.apiKey)}`);
|
|
168
|
+
console.log(` ${chalk.hex(colors.primary)('baseUrl')}: ${config.baseUrl}`);
|
|
169
|
+
console.log(` ${chalk.hex(colors.primary)('provider')}: ${config.provider}`);
|
|
170
|
+
console.log(` ${chalk.hex(colors.primary)('model')}: ${config.model}`);
|
|
171
|
+
console.log(` ${chalk.hex(colors.primary)('shellHook')}: ${config.shellHook ? chalk.hex(colors.success)('已启用') : chalk.gray('未启用')}`);
|
|
172
|
+
console.log(` ${chalk.hex(colors.primary)('editMode')}: ${config.editMode === 'auto' ? chalk.hex(colors.primary)('auto (自动编辑)') : chalk.gray('manual (按E编辑)')}`);
|
|
173
|
+
console.log(` ${chalk.hex(colors.primary)('chatHistoryLimit')}: ${config.chatHistoryLimit} 轮`);
|
|
174
|
+
console.log(` ${chalk.hex(colors.primary)('commandHistoryLimit')}: ${config.commandHistoryLimit} 条`);
|
|
175
|
+
console.log(` ${chalk.hex(colors.primary)('shellHistoryLimit')}: ${config.shellHistoryLimit} 条`);
|
|
176
|
+
console.log(` ${chalk.hex(colors.primary)('theme')}: ${config.theme === 'dark' ? chalk.hex(colors.primary)('dark (深色)') : chalk.hex(colors.primary)('light (浅色)')}`);
|
|
138
177
|
console.log(chalk.gray('━'.repeat(50)));
|
|
139
178
|
console.log(chalk.gray(`配置文件: ${CONFIG_FILE}\n`));
|
|
140
179
|
}
|
|
@@ -163,17 +202,18 @@ function question(rl, prompt) {
|
|
|
163
202
|
export async function runConfigWizard() {
|
|
164
203
|
const rl = createReadlineInterface();
|
|
165
204
|
const config = getConfig();
|
|
166
|
-
|
|
205
|
+
const colors = getColors();
|
|
206
|
+
console.log(chalk.bold.hex(colors.primary)('\n🔧 Pretty Please 配置向导'));
|
|
167
207
|
console.log(chalk.gray('━'.repeat(50)));
|
|
168
208
|
console.log(chalk.gray('直接回车使用默认值,输入值后回车确认\n'));
|
|
169
209
|
try {
|
|
170
210
|
// 1. Provider
|
|
171
211
|
const providerHint = chalk.gray(`(可选: ${VALID_PROVIDERS.join(', ')})`);
|
|
172
|
-
const providerPrompt = `${chalk.
|
|
212
|
+
const providerPrompt = `${chalk.hex(colors.primary)('Provider')} ${providerHint}\n${chalk.gray('默认:')} ${chalk.hex(colors.secondary)(config.provider)} ${chalk.gray('→')} `;
|
|
173
213
|
const provider = await question(rl, providerPrompt);
|
|
174
214
|
if (provider.trim()) {
|
|
175
215
|
if (!VALID_PROVIDERS.includes(provider.trim())) {
|
|
176
|
-
console.log(chalk.hex(
|
|
216
|
+
console.log(chalk.hex(colors.error)(`\n✗ 无效的 provider,必须是以下之一: ${VALID_PROVIDERS.join(', ')}`));
|
|
177
217
|
console.log();
|
|
178
218
|
rl.close();
|
|
179
219
|
return;
|
|
@@ -181,37 +221,37 @@ export async function runConfigWizard() {
|
|
|
181
221
|
config.provider = provider.trim();
|
|
182
222
|
}
|
|
183
223
|
// 2. Base URL
|
|
184
|
-
const baseUrlPrompt = `${chalk.
|
|
224
|
+
const baseUrlPrompt = `${chalk.hex(colors.primary)('API Base URL')}\n${chalk.gray('默认:')} ${chalk.hex(colors.secondary)(config.baseUrl)} ${chalk.gray('→')} `;
|
|
185
225
|
const baseUrl = await question(rl, baseUrlPrompt);
|
|
186
226
|
if (baseUrl.trim()) {
|
|
187
227
|
config.baseUrl = baseUrl.trim();
|
|
188
228
|
}
|
|
189
229
|
// 3. API Key
|
|
190
230
|
const currentKeyDisplay = config.apiKey ? maskApiKey(config.apiKey) : '(未设置)';
|
|
191
|
-
const apiKeyPrompt = `${chalk.
|
|
231
|
+
const apiKeyPrompt = `${chalk.hex(colors.primary)('API Key')} ${chalk.gray(`(当前: ${currentKeyDisplay})`)}\n${chalk.gray('→')} `;
|
|
192
232
|
const apiKey = await question(rl, apiKeyPrompt);
|
|
193
233
|
if (apiKey.trim()) {
|
|
194
234
|
config.apiKey = apiKey.trim();
|
|
195
235
|
}
|
|
196
236
|
// 4. Model
|
|
197
|
-
const modelPrompt = `${chalk.
|
|
237
|
+
const modelPrompt = `${chalk.hex(colors.primary)('Model')}\n${chalk.gray('默认:')} ${chalk.hex(colors.secondary)(config.model)} ${chalk.gray('→')} `;
|
|
198
238
|
const model = await question(rl, modelPrompt);
|
|
199
239
|
if (model.trim()) {
|
|
200
240
|
config.model = model.trim();
|
|
201
241
|
}
|
|
202
242
|
// 5. Shell Hook
|
|
203
|
-
const shellHookPrompt = `${chalk.
|
|
243
|
+
const shellHookPrompt = `${chalk.hex(colors.primary)('启用 Shell Hook')} ${chalk.gray('(记录终端命令历史)')}\n${chalk.gray('默认:')} ${chalk.hex(colors.secondary)(config.shellHook ? 'true' : 'false')} ${chalk.gray('→')} `;
|
|
204
244
|
const shellHook = await question(rl, shellHookPrompt);
|
|
205
245
|
if (shellHook.trim()) {
|
|
206
246
|
config.shellHook = shellHook.trim() === 'true';
|
|
207
247
|
}
|
|
208
248
|
// 6. Edit Mode
|
|
209
249
|
const editModeHint = chalk.gray('(manual=按E编辑, auto=自动编辑)');
|
|
210
|
-
const editModePrompt = `${chalk.
|
|
250
|
+
const editModePrompt = `${chalk.hex(colors.primary)('编辑模式')} ${editModeHint}\n${chalk.gray('默认:')} ${chalk.hex(colors.secondary)(config.editMode)} ${chalk.gray('→')} `;
|
|
211
251
|
const editMode = await question(rl, editModePrompt);
|
|
212
252
|
if (editMode.trim()) {
|
|
213
253
|
if (!VALID_EDIT_MODES.includes(editMode.trim())) {
|
|
214
|
-
console.log(chalk.hex(
|
|
254
|
+
console.log(chalk.hex(colors.error)(`\n✗ 无效的 editMode,必须是: manual 或 auto`));
|
|
215
255
|
console.log();
|
|
216
256
|
rl.close();
|
|
217
257
|
return;
|
|
@@ -219,7 +259,7 @@ export async function runConfigWizard() {
|
|
|
219
259
|
config.editMode = editMode.trim();
|
|
220
260
|
}
|
|
221
261
|
// 7. Chat History Limit
|
|
222
|
-
const chatHistoryPrompt = `${chalk.
|
|
262
|
+
const chatHistoryPrompt = `${chalk.hex(colors.primary)('Chat 历史保留轮数')}\n${chalk.gray('默认:')} ${chalk.hex(colors.secondary)(config.chatHistoryLimit)} ${chalk.gray('→')} `;
|
|
223
263
|
const chatHistoryLimit = await question(rl, chatHistoryPrompt);
|
|
224
264
|
if (chatHistoryLimit.trim()) {
|
|
225
265
|
const num = parseInt(chatHistoryLimit.trim(), 10);
|
|
@@ -228,7 +268,7 @@ export async function runConfigWizard() {
|
|
|
228
268
|
}
|
|
229
269
|
}
|
|
230
270
|
// 8. Command History Limit
|
|
231
|
-
const commandHistoryPrompt = `${chalk.
|
|
271
|
+
const commandHistoryPrompt = `${chalk.hex(colors.primary)('命令历史保留条数')}\n${chalk.gray('默认:')} ${chalk.hex(colors.secondary)(config.commandHistoryLimit)} ${chalk.gray('→')} `;
|
|
232
272
|
const commandHistoryLimit = await question(rl, commandHistoryPrompt);
|
|
233
273
|
if (commandHistoryLimit.trim()) {
|
|
234
274
|
const num = parseInt(commandHistoryLimit.trim(), 10);
|
|
@@ -237,7 +277,7 @@ export async function runConfigWizard() {
|
|
|
237
277
|
}
|
|
238
278
|
}
|
|
239
279
|
// 9. Shell History Limit
|
|
240
|
-
const shellHistoryPrompt = `${chalk.
|
|
280
|
+
const shellHistoryPrompt = `${chalk.hex(colors.primary)('Shell 历史保留条数')}\n${chalk.gray('默认:')} ${chalk.hex(colors.secondary)(config.shellHistoryLimit)} ${chalk.gray('→')} `;
|
|
241
281
|
const shellHistoryLimit = await question(rl, shellHistoryPrompt);
|
|
242
282
|
if (shellHistoryLimit.trim()) {
|
|
243
283
|
const num = parseInt(shellHistoryLimit.trim(), 10);
|
|
@@ -247,13 +287,13 @@ export async function runConfigWizard() {
|
|
|
247
287
|
}
|
|
248
288
|
saveConfig(config);
|
|
249
289
|
console.log('\n' + chalk.gray('━'.repeat(50)));
|
|
250
|
-
console.log(chalk.hex(
|
|
290
|
+
console.log(chalk.hex(getColors().success)('✅ 配置已保存'));
|
|
251
291
|
console.log(chalk.gray(` ${CONFIG_FILE}`));
|
|
252
292
|
console.log();
|
|
253
293
|
}
|
|
254
294
|
catch (error) {
|
|
255
295
|
const message = error instanceof Error ? error.message : String(error);
|
|
256
|
-
console.log(chalk.hex(
|
|
296
|
+
console.log(chalk.hex(getColors().error)(`\n✗ 配置失败: ${message}`));
|
|
257
297
|
console.log();
|
|
258
298
|
}
|
|
259
299
|
finally {
|
package/dist/src/multi-step.d.ts
CHANGED
|
@@ -1,17 +1,20 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
|
+
import { type RemoteSysInfo } from './config.js';
|
|
3
|
+
import { type RemoteShellHistoryItem } from './remote-history.js';
|
|
2
4
|
/**
|
|
3
5
|
* 多步骤命令的 Zod Schema
|
|
6
|
+
* 注意:optional 字段使用 .default() 是为了绕过 Mastra 0.24.8 对 optional 字段的验证 bug
|
|
4
7
|
*/
|
|
5
8
|
export declare const CommandStepSchema: z.ZodObject<{
|
|
6
9
|
command: z.ZodString;
|
|
7
|
-
continue: z.ZodOptional<z.ZodBoolean
|
|
8
|
-
reasoning: z.ZodOptional<z.ZodString
|
|
9
|
-
nextStepHint: z.ZodOptional<z.ZodString
|
|
10
|
+
continue: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
|
|
11
|
+
reasoning: z.ZodDefault<z.ZodOptional<z.ZodString>>;
|
|
12
|
+
nextStepHint: z.ZodDefault<z.ZodOptional<z.ZodString>>;
|
|
10
13
|
}, "strip", z.ZodTypeAny, {
|
|
11
14
|
command: string;
|
|
12
|
-
reasoning
|
|
13
|
-
continue
|
|
14
|
-
nextStepHint
|
|
15
|
+
reasoning: string;
|
|
16
|
+
continue: boolean;
|
|
17
|
+
nextStepHint: string;
|
|
15
18
|
}, {
|
|
16
19
|
command: string;
|
|
17
20
|
reasoning?: string | undefined;
|
|
@@ -26,15 +29,28 @@ export interface ExecutedStep extends CommandStep {
|
|
|
26
29
|
exitCode: number;
|
|
27
30
|
output: string;
|
|
28
31
|
}
|
|
32
|
+
/**
|
|
33
|
+
* 远程执行上下文
|
|
34
|
+
*/
|
|
35
|
+
export interface RemoteContext {
|
|
36
|
+
name: string;
|
|
37
|
+
sysInfo: RemoteSysInfo;
|
|
38
|
+
shellHistory: RemoteShellHistoryItem[];
|
|
39
|
+
}
|
|
29
40
|
/**
|
|
30
41
|
* 生成系统上下文信息(供 Mastra 使用)
|
|
31
42
|
*/
|
|
32
43
|
export declare function getFullSystemPrompt(): string;
|
|
44
|
+
/**
|
|
45
|
+
* 生成远程系统上下文信息
|
|
46
|
+
*/
|
|
47
|
+
export declare function getRemoteFullSystemPrompt(remoteContext: RemoteContext): string;
|
|
33
48
|
/**
|
|
34
49
|
* 使用 Mastra 生成多步骤命令
|
|
35
50
|
*/
|
|
36
51
|
export declare function generateMultiStepCommand(userPrompt: string, previousSteps?: ExecutedStep[], options?: {
|
|
37
52
|
debug?: boolean;
|
|
53
|
+
remoteContext?: RemoteContext;
|
|
38
54
|
}): Promise<{
|
|
39
55
|
stepData: CommandStep;
|
|
40
56
|
debugInfo?: any;
|
package/dist/src/multi-step.js
CHANGED
|
@@ -5,14 +5,17 @@ import { formatSystemInfo } from './sysinfo.js';
|
|
|
5
5
|
import { formatHistoryForAI } from './history.js';
|
|
6
6
|
import { formatShellHistoryForAI, getShellHistory } from './shell-hook.js';
|
|
7
7
|
import { getConfig } from './config.js';
|
|
8
|
+
import { formatRemoteHistoryForAI, formatRemoteShellHistoryForAI } from './remote-history.js';
|
|
9
|
+
import { formatRemoteSysInfoForAI } from './remote.js';
|
|
8
10
|
/**
|
|
9
11
|
* 多步骤命令的 Zod Schema
|
|
12
|
+
* 注意:optional 字段使用 .default() 是为了绕过 Mastra 0.24.8 对 optional 字段的验证 bug
|
|
10
13
|
*/
|
|
11
14
|
export const CommandStepSchema = z.object({
|
|
12
15
|
command: z.string(),
|
|
13
|
-
continue: z.boolean().optional(),
|
|
14
|
-
reasoning: z.string().optional(),
|
|
15
|
-
nextStepHint: z.string().optional(),
|
|
16
|
+
continue: z.boolean().optional().default(false),
|
|
17
|
+
reasoning: z.string().optional().default(''),
|
|
18
|
+
nextStepHint: z.string().optional().default(''),
|
|
16
19
|
});
|
|
17
20
|
/**
|
|
18
21
|
* 生成系统上下文信息(供 Mastra 使用)
|
|
@@ -25,12 +28,28 @@ export function getFullSystemPrompt() {
|
|
|
25
28
|
const shellHookEnabled = config.shellHook && getShellHistory().length > 0;
|
|
26
29
|
return buildCommandSystemPrompt(sysinfo, plsHistory, shellHistory, shellHookEnabled);
|
|
27
30
|
}
|
|
31
|
+
/**
|
|
32
|
+
* 生成远程系统上下文信息
|
|
33
|
+
*/
|
|
34
|
+
export function getRemoteFullSystemPrompt(remoteContext) {
|
|
35
|
+
// 格式化远程系统信息
|
|
36
|
+
const sysinfo = formatRemoteSysInfoForAI(remoteContext.name, remoteContext.sysInfo);
|
|
37
|
+
// 格式化远程 pls 命令历史
|
|
38
|
+
const plsHistory = formatRemoteHistoryForAI(remoteContext.name);
|
|
39
|
+
// 格式化远程 shell 历史
|
|
40
|
+
const shellHistory = formatRemoteShellHistoryForAI(remoteContext.shellHistory);
|
|
41
|
+
const shellHookEnabled = remoteContext.shellHistory.length > 0;
|
|
42
|
+
return buildCommandSystemPrompt(sysinfo, plsHistory, shellHistory, shellHookEnabled);
|
|
43
|
+
}
|
|
28
44
|
/**
|
|
29
45
|
* 使用 Mastra 生成多步骤命令
|
|
30
46
|
*/
|
|
31
47
|
export async function generateMultiStepCommand(userPrompt, previousSteps = [], options = {}) {
|
|
32
48
|
const agent = createShellAgent();
|
|
33
|
-
|
|
49
|
+
// 根据是否有远程上下文选择不同的系统提示词
|
|
50
|
+
const fullSystemPrompt = options.remoteContext
|
|
51
|
+
? getRemoteFullSystemPrompt(options.remoteContext)
|
|
52
|
+
: getFullSystemPrompt();
|
|
34
53
|
// 构建消息数组(string[] 格式)
|
|
35
54
|
const messages = [userPrompt];
|
|
36
55
|
// 添加之前步骤的执行结果
|
|
@@ -60,6 +79,10 @@ export async function generateMultiStepCommand(userPrompt, previousSteps = [], o
|
|
|
60
79
|
userPrompt,
|
|
61
80
|
previousStepsCount: previousSteps.length,
|
|
62
81
|
response: stepData,
|
|
82
|
+
remoteContext: options.remoteContext ? {
|
|
83
|
+
name: options.remoteContext.name,
|
|
84
|
+
sysInfo: options.remoteContext.sysInfo,
|
|
85
|
+
} : undefined,
|
|
63
86
|
},
|
|
64
87
|
};
|
|
65
88
|
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 远程服务器历史管理模块
|
|
3
|
+
* 管理每个远程服务器的命令历史
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* 远程命令历史记录
|
|
7
|
+
*/
|
|
8
|
+
export interface RemoteHistoryRecord {
|
|
9
|
+
userPrompt: string;
|
|
10
|
+
command: string;
|
|
11
|
+
aiGeneratedCommand?: string;
|
|
12
|
+
userModified?: boolean;
|
|
13
|
+
executed: boolean;
|
|
14
|
+
exitCode: number | null;
|
|
15
|
+
output: string;
|
|
16
|
+
timestamp: string;
|
|
17
|
+
reason?: string;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Shell 历史记录项
|
|
21
|
+
*/
|
|
22
|
+
export interface RemoteShellHistoryItem {
|
|
23
|
+
cmd: string;
|
|
24
|
+
exit: number;
|
|
25
|
+
time: string;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* 获取远程服务器命令历史
|
|
29
|
+
*/
|
|
30
|
+
export declare function getRemoteHistory(name: string): RemoteHistoryRecord[];
|
|
31
|
+
/**
|
|
32
|
+
* 添加远程命令历史记录
|
|
33
|
+
*/
|
|
34
|
+
export declare function addRemoteHistory(name: string, record: Omit<RemoteHistoryRecord, 'timestamp'>): void;
|
|
35
|
+
/**
|
|
36
|
+
* 清空远程命令历史
|
|
37
|
+
*/
|
|
38
|
+
export declare function clearRemoteHistory(name: string): void;
|
|
39
|
+
/**
|
|
40
|
+
* 格式化远程命令历史供 AI 使用
|
|
41
|
+
*/
|
|
42
|
+
export declare function formatRemoteHistoryForAI(name: string): string;
|
|
43
|
+
/**
|
|
44
|
+
* 显示远程命令历史
|
|
45
|
+
*/
|
|
46
|
+
export declare function displayRemoteHistory(name: string): void;
|
|
47
|
+
/**
|
|
48
|
+
* 从远程服务器读取 shell 历史
|
|
49
|
+
* 读取远程 ~/.please/shell_history.jsonl
|
|
50
|
+
*/
|
|
51
|
+
export declare function fetchRemoteShellHistory(name: string): Promise<RemoteShellHistoryItem[]>;
|
|
52
|
+
/**
|
|
53
|
+
* 格式化远程 shell 历史供 AI 使用
|
|
54
|
+
*/
|
|
55
|
+
export declare function formatRemoteShellHistoryForAI(items: RemoteShellHistoryItem[]): string;
|
|
56
|
+
/**
|
|
57
|
+
* 显示远程 shell 历史
|
|
58
|
+
*/
|
|
59
|
+
export declare function displayRemoteShellHistory(name: string): Promise<void>;
|
|
60
|
+
/**
|
|
61
|
+
* 清空远程 shell 历史
|
|
62
|
+
*/
|
|
63
|
+
export declare function clearRemoteShellHistory(name: string): Promise<void>;
|