@yivan-lab/pretty-please 1.0.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 +381 -28
- package/bin/pls.tsx +1138 -109
- package/dist/bin/pls.d.ts +1 -1
- package/dist/bin/pls.js +994 -91
- package/dist/package.json +80 -0
- package/dist/src/ai.d.ts +1 -41
- package/dist/src/ai.js +9 -190
- package/dist/src/alias.d.ts +41 -0
- package/dist/src/alias.js +240 -0
- package/dist/src/builtin-detector.d.ts +14 -8
- package/dist/src/builtin-detector.js +36 -16
- package/dist/src/chat-history.d.ts +16 -11
- package/dist/src/chat-history.js +35 -4
- package/dist/src/components/Chat.js +5 -4
- package/dist/src/components/CodeColorizer.js +26 -20
- package/dist/src/components/CommandBox.js +3 -17
- package/dist/src/components/ConfirmationPrompt.d.ts +2 -1
- package/dist/src/components/ConfirmationPrompt.js +9 -4
- 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 +5 -1
- package/dist/src/components/MultiStepCommandGenerator.js +127 -14
- package/dist/src/components/TableRenderer.js +2 -1
- package/dist/src/config.d.ts +59 -9
- package/dist/src/config.js +147 -48
- package/dist/src/history.d.ts +19 -5
- package/dist/src/history.js +26 -11
- package/dist/src/mastra-agent.d.ts +0 -1
- package/dist/src/mastra-agent.js +3 -4
- package/dist/src/mastra-chat.d.ts +28 -0
- package/dist/src/mastra-chat.js +93 -0
- package/dist/src/multi-step.d.ts +23 -7
- package/dist/src/multi-step.js +29 -6
- package/dist/src/prompts.d.ts +11 -0
- package/dist/src/prompts.js +140 -0
- 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 +87 -12
- package/dist/src/shell-hook.js +315 -17
- package/dist/src/sysinfo.d.ts +9 -5
- package/dist/src/sysinfo.js +2 -2
- 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.d.ts +11 -11
- package/dist/src/utils/console.js +26 -17
- package/package.json +11 -9
- package/src/alias.ts +301 -0
- package/src/builtin-detector.ts +126 -0
- package/src/chat-history.ts +140 -0
- package/src/components/Chat.tsx +6 -5
- package/src/components/CodeColorizer.tsx +27 -19
- package/src/components/CommandBox.tsx +3 -17
- package/src/components/ConfirmationPrompt.tsx +11 -3
- 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 +167 -16
- package/src/components/TableRenderer.tsx +2 -1
- package/src/config.ts +394 -0
- package/src/history.ts +160 -0
- package/src/mastra-agent.ts +3 -4
- package/src/mastra-chat.ts +124 -0
- package/src/multi-step.ts +45 -8
- package/src/prompts.ts +154 -0
- package/src/remote-history.ts +390 -0
- package/src/remote.ts +800 -0
- package/src/shell-hook.ts +754 -0
- package/src/{sysinfo.js → sysinfo.ts} +28 -16
- package/src/ui/theme.ts +101 -24
- package/src/upgrade.ts +397 -0
- package/src/utils/{console.js → console.ts} +36 -27
- package/bin/pls.js +0 -681
- package/src/ai.js +0 -324
- package/src/builtin-detector.js +0 -98
- package/src/chat-history.js +0 -94
- package/src/components/ChatStatus.tsx +0 -53
- package/src/components/CommandGenerator.tsx +0 -184
- package/src/components/ConfigDisplay.tsx +0 -64
- package/src/components/ConfigWizard.tsx +0 -101
- package/src/components/HistoryDisplay.tsx +0 -69
- package/src/components/HookManager.tsx +0 -150
- package/src/config.js +0 -221
- package/src/history.js +0 -131
- package/src/shell-hook.js +0 -393
|
@@ -0,0 +1,315 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 远程服务器历史管理模块
|
|
3
|
+
* 管理每个远程服务器的命令历史
|
|
4
|
+
*/
|
|
5
|
+
import fs from 'fs';
|
|
6
|
+
import path from 'path';
|
|
7
|
+
import chalk from 'chalk';
|
|
8
|
+
import { CONFIG_DIR, getConfig } from './config.js';
|
|
9
|
+
import { getCurrentTheme } from './ui/theme.js';
|
|
10
|
+
import { sshExec, getRemote } from './remote.js';
|
|
11
|
+
// 获取主题颜色
|
|
12
|
+
function getColors() {
|
|
13
|
+
const theme = getCurrentTheme();
|
|
14
|
+
return {
|
|
15
|
+
primary: theme.primary,
|
|
16
|
+
secondary: theme.secondary,
|
|
17
|
+
success: theme.success,
|
|
18
|
+
error: theme.error,
|
|
19
|
+
warning: theme.warning,
|
|
20
|
+
muted: theme.text.muted,
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
// 远程服务器数据目录
|
|
24
|
+
const REMOTES_DIR = path.join(CONFIG_DIR, 'remotes');
|
|
25
|
+
// ================== 命令历史管理 ==================
|
|
26
|
+
/**
|
|
27
|
+
* 获取远程服务器历史文件路径
|
|
28
|
+
*/
|
|
29
|
+
function getRemoteHistoryPath(name) {
|
|
30
|
+
return path.join(REMOTES_DIR, name, 'history.json');
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* 获取远程服务器命令历史
|
|
34
|
+
*/
|
|
35
|
+
export function getRemoteHistory(name) {
|
|
36
|
+
const historyPath = getRemoteHistoryPath(name);
|
|
37
|
+
if (!fs.existsSync(historyPath)) {
|
|
38
|
+
return [];
|
|
39
|
+
}
|
|
40
|
+
try {
|
|
41
|
+
const content = fs.readFileSync(historyPath, 'utf-8');
|
|
42
|
+
return JSON.parse(content);
|
|
43
|
+
}
|
|
44
|
+
catch {
|
|
45
|
+
return [];
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* 添加远程命令历史记录
|
|
50
|
+
*/
|
|
51
|
+
export function addRemoteHistory(name, record) {
|
|
52
|
+
const config = getConfig();
|
|
53
|
+
const historyPath = getRemoteHistoryPath(name);
|
|
54
|
+
// 确保目录存在
|
|
55
|
+
const dir = path.dirname(historyPath);
|
|
56
|
+
if (!fs.existsSync(dir)) {
|
|
57
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
58
|
+
}
|
|
59
|
+
let history = getRemoteHistory(name);
|
|
60
|
+
// 添加新记录
|
|
61
|
+
history.push({
|
|
62
|
+
...record,
|
|
63
|
+
timestamp: new Date().toISOString(),
|
|
64
|
+
});
|
|
65
|
+
// 限制历史数量
|
|
66
|
+
const limit = config.commandHistoryLimit || 10;
|
|
67
|
+
if (history.length > limit) {
|
|
68
|
+
history = history.slice(-limit);
|
|
69
|
+
}
|
|
70
|
+
fs.writeFileSync(historyPath, JSON.stringify(history, null, 2));
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* 清空远程命令历史
|
|
74
|
+
*/
|
|
75
|
+
export function clearRemoteHistory(name) {
|
|
76
|
+
const historyPath = getRemoteHistoryPath(name);
|
|
77
|
+
if (fs.existsSync(historyPath)) {
|
|
78
|
+
fs.unlinkSync(historyPath);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* 格式化远程命令历史供 AI 使用
|
|
83
|
+
*/
|
|
84
|
+
export function formatRemoteHistoryForAI(name) {
|
|
85
|
+
const history = getRemoteHistory(name);
|
|
86
|
+
if (history.length === 0) {
|
|
87
|
+
return '';
|
|
88
|
+
}
|
|
89
|
+
const lines = history.map((record, index) => {
|
|
90
|
+
let status = '';
|
|
91
|
+
if (record.reason === 'builtin') {
|
|
92
|
+
status = '(包含 builtin,未执行)';
|
|
93
|
+
}
|
|
94
|
+
else if (record.executed) {
|
|
95
|
+
status = record.exitCode === 0 ? '✓' : `✗ 退出码:${record.exitCode}`;
|
|
96
|
+
}
|
|
97
|
+
else {
|
|
98
|
+
status = '(用户取消执行)';
|
|
99
|
+
}
|
|
100
|
+
// 显示用户修改信息
|
|
101
|
+
if (record.userModified && record.aiGeneratedCommand) {
|
|
102
|
+
return `${index + 1}. "${record.userPrompt}" → AI 生成: ${record.aiGeneratedCommand} / 用户修改为: ${record.command} ${status}`;
|
|
103
|
+
}
|
|
104
|
+
else {
|
|
105
|
+
return `${index + 1}. "${record.userPrompt}" → ${record.command} ${status}`;
|
|
106
|
+
}
|
|
107
|
+
});
|
|
108
|
+
return `【该服务器最近通过 pls 执行的命令】\n${lines.join('\n')}`;
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* 显示远程命令历史
|
|
112
|
+
*/
|
|
113
|
+
export function displayRemoteHistory(name) {
|
|
114
|
+
const remote = getRemote(name);
|
|
115
|
+
const history = getRemoteHistory(name);
|
|
116
|
+
const colors = getColors();
|
|
117
|
+
if (!remote) {
|
|
118
|
+
console.log('');
|
|
119
|
+
console.log(chalk.hex(colors.error)(`✗ 服务器 "${name}" 不存在`));
|
|
120
|
+
console.log('');
|
|
121
|
+
return;
|
|
122
|
+
}
|
|
123
|
+
console.log('');
|
|
124
|
+
if (history.length === 0) {
|
|
125
|
+
console.log(chalk.gray(` 服务器 "${name}" 暂无命令历史`));
|
|
126
|
+
console.log('');
|
|
127
|
+
return;
|
|
128
|
+
}
|
|
129
|
+
console.log(chalk.bold(`📜 服务器 "${name}" 命令历史:`));
|
|
130
|
+
console.log(chalk.gray('━'.repeat(50)));
|
|
131
|
+
history.forEach((item, index) => {
|
|
132
|
+
const status = item.executed
|
|
133
|
+
? item.exitCode === 0
|
|
134
|
+
? chalk.hex(colors.success)('✓')
|
|
135
|
+
: chalk.hex(colors.error)(`✗ 退出码:${item.exitCode}`)
|
|
136
|
+
: chalk.gray('(未执行)');
|
|
137
|
+
console.log(`\n${chalk.gray(`${index + 1}.`)} ${chalk.hex(colors.primary)(item.userPrompt)}`);
|
|
138
|
+
// 显示用户修改信息
|
|
139
|
+
if (item.userModified && item.aiGeneratedCommand) {
|
|
140
|
+
console.log(` ${chalk.dim('AI 生成:')} ${chalk.gray(item.aiGeneratedCommand)}`);
|
|
141
|
+
console.log(` ${chalk.dim('用户修改为:')} ${item.command} ${status} ${chalk.hex(colors.warning)('(已修改)')}`);
|
|
142
|
+
}
|
|
143
|
+
else {
|
|
144
|
+
console.log(` ${chalk.dim('→')} ${item.command} ${status}`);
|
|
145
|
+
}
|
|
146
|
+
console.log(` ${chalk.gray(item.timestamp)}`);
|
|
147
|
+
});
|
|
148
|
+
console.log('');
|
|
149
|
+
console.log(chalk.gray('━'.repeat(50)));
|
|
150
|
+
console.log(chalk.gray(`历史文件: ${getRemoteHistoryPath(name)}`));
|
|
151
|
+
console.log('');
|
|
152
|
+
}
|
|
153
|
+
// ================== Shell 历史管理 ==================
|
|
154
|
+
// 远程 shell 历史的本地缓存文件
|
|
155
|
+
function getRemoteShellHistoryPath(name) {
|
|
156
|
+
return path.join(REMOTES_DIR, name, 'shell_history.jsonl');
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* 从远程服务器读取 shell 历史
|
|
160
|
+
* 读取远程 ~/.please/shell_history.jsonl
|
|
161
|
+
*/
|
|
162
|
+
export async function fetchRemoteShellHistory(name) {
|
|
163
|
+
const config = getConfig();
|
|
164
|
+
const limit = config.shellHistoryLimit || 15;
|
|
165
|
+
try {
|
|
166
|
+
// 读取远程 shell 历史文件
|
|
167
|
+
const result = await sshExec(name, `tail -n ${limit} ~/.please/shell_history.jsonl 2>/dev/null || echo ""`, {
|
|
168
|
+
timeout: 10000,
|
|
169
|
+
});
|
|
170
|
+
if (result.exitCode !== 0 || !result.stdout.trim()) {
|
|
171
|
+
return [];
|
|
172
|
+
}
|
|
173
|
+
const lines = result.stdout.trim().split('\n').filter(line => line.trim());
|
|
174
|
+
const items = [];
|
|
175
|
+
for (const line of lines) {
|
|
176
|
+
try {
|
|
177
|
+
const item = JSON.parse(line);
|
|
178
|
+
items.push(item);
|
|
179
|
+
}
|
|
180
|
+
catch {
|
|
181
|
+
// 跳过无效行
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
// 缓存到本地
|
|
185
|
+
saveRemoteShellHistoryCache(name, items);
|
|
186
|
+
return items;
|
|
187
|
+
}
|
|
188
|
+
catch {
|
|
189
|
+
// 如果无法连接,尝试返回缓存
|
|
190
|
+
return getRemoteShellHistoryCache(name);
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
/**
|
|
194
|
+
* 保存远程 shell 历史缓存到本地
|
|
195
|
+
*/
|
|
196
|
+
function saveRemoteShellHistoryCache(name, items) {
|
|
197
|
+
const cachePath = getRemoteShellHistoryPath(name);
|
|
198
|
+
// 确保目录存在
|
|
199
|
+
const dir = path.dirname(cachePath);
|
|
200
|
+
if (!fs.existsSync(dir)) {
|
|
201
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
202
|
+
}
|
|
203
|
+
const content = items.map(item => JSON.stringify(item)).join('\n');
|
|
204
|
+
fs.writeFileSync(cachePath, content);
|
|
205
|
+
}
|
|
206
|
+
/**
|
|
207
|
+
* 获取本地缓存的远程 shell 历史
|
|
208
|
+
*/
|
|
209
|
+
function getRemoteShellHistoryCache(name) {
|
|
210
|
+
const cachePath = getRemoteShellHistoryPath(name);
|
|
211
|
+
if (!fs.existsSync(cachePath)) {
|
|
212
|
+
return [];
|
|
213
|
+
}
|
|
214
|
+
try {
|
|
215
|
+
const content = fs.readFileSync(cachePath, 'utf-8');
|
|
216
|
+
const lines = content.trim().split('\n').filter(line => line.trim());
|
|
217
|
+
return lines.map(line => {
|
|
218
|
+
try {
|
|
219
|
+
return JSON.parse(line);
|
|
220
|
+
}
|
|
221
|
+
catch {
|
|
222
|
+
return null;
|
|
223
|
+
}
|
|
224
|
+
}).filter((item) => item !== null);
|
|
225
|
+
}
|
|
226
|
+
catch {
|
|
227
|
+
return [];
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
/**
|
|
231
|
+
* 格式化远程 shell 历史供 AI 使用
|
|
232
|
+
*/
|
|
233
|
+
export function formatRemoteShellHistoryForAI(items) {
|
|
234
|
+
if (items.length === 0) {
|
|
235
|
+
return '';
|
|
236
|
+
}
|
|
237
|
+
const lines = items.map((item, index) => {
|
|
238
|
+
const status = item.exit === 0 ? '✓' : `✗ 退出码:${item.exit}`;
|
|
239
|
+
return `${index + 1}. ${item.cmd} ${status}`;
|
|
240
|
+
});
|
|
241
|
+
return `【该服务器终端最近执行的命令】\n${lines.join('\n')}`;
|
|
242
|
+
}
|
|
243
|
+
/**
|
|
244
|
+
* 显示远程 shell 历史
|
|
245
|
+
*/
|
|
246
|
+
export async function displayRemoteShellHistory(name) {
|
|
247
|
+
const remote = getRemote(name);
|
|
248
|
+
const colors = getColors();
|
|
249
|
+
if (!remote) {
|
|
250
|
+
console.log('');
|
|
251
|
+
console.log(chalk.hex(colors.error)(`✗ 服务器 "${name}" 不存在`));
|
|
252
|
+
console.log('');
|
|
253
|
+
return;
|
|
254
|
+
}
|
|
255
|
+
console.log('');
|
|
256
|
+
console.log(chalk.gray(`正在从 ${name} 读取 shell 历史...`));
|
|
257
|
+
try {
|
|
258
|
+
const history = await fetchRemoteShellHistory(name);
|
|
259
|
+
if (history.length === 0) {
|
|
260
|
+
console.log('');
|
|
261
|
+
console.log(chalk.gray(` 服务器 "${name}" 暂无 shell 历史`));
|
|
262
|
+
console.log(chalk.gray(' 请先安装远程 hook: pls remote hook install ' + name));
|
|
263
|
+
console.log('');
|
|
264
|
+
return;
|
|
265
|
+
}
|
|
266
|
+
console.log('');
|
|
267
|
+
console.log(chalk.bold(`终端历史 - ${name}(最近 ${history.length} 条):`));
|
|
268
|
+
console.log(chalk.gray('━'.repeat(50)));
|
|
269
|
+
history.forEach((item, index) => {
|
|
270
|
+
const num = index + 1;
|
|
271
|
+
const status = item.exit === 0 ? chalk.hex(colors.success)('✓') : chalk.hex(colors.error)(`✗ (${item.exit})`);
|
|
272
|
+
console.log(` ${chalk.hex(colors.primary)(num.toString().padStart(2, ' '))}. ${item.cmd} ${status}`);
|
|
273
|
+
});
|
|
274
|
+
console.log(chalk.gray('━'.repeat(50)));
|
|
275
|
+
console.log(chalk.gray(`远程文件: ~/.please/shell_history.jsonl`));
|
|
276
|
+
console.log('');
|
|
277
|
+
}
|
|
278
|
+
catch (error) {
|
|
279
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
280
|
+
console.log('');
|
|
281
|
+
console.log(chalk.hex(colors.error)(`✗ 无法读取远程 shell 历史: ${message}`));
|
|
282
|
+
console.log('');
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
/**
|
|
286
|
+
* 清空远程 shell 历史
|
|
287
|
+
*/
|
|
288
|
+
export async function clearRemoteShellHistory(name) {
|
|
289
|
+
const remote = getRemote(name);
|
|
290
|
+
const colors = getColors();
|
|
291
|
+
if (!remote) {
|
|
292
|
+
console.log('');
|
|
293
|
+
console.log(chalk.hex(colors.error)(`✗ 服务器 "${name}" 不存在`));
|
|
294
|
+
console.log('');
|
|
295
|
+
return;
|
|
296
|
+
}
|
|
297
|
+
try {
|
|
298
|
+
// 清空远程文件
|
|
299
|
+
await sshExec(name, 'rm -f ~/.please/shell_history.jsonl', { timeout: 10000 });
|
|
300
|
+
// 清空本地缓存
|
|
301
|
+
const cachePath = getRemoteShellHistoryPath(name);
|
|
302
|
+
if (fs.existsSync(cachePath)) {
|
|
303
|
+
fs.unlinkSync(cachePath);
|
|
304
|
+
}
|
|
305
|
+
console.log('');
|
|
306
|
+
console.log(chalk.hex(colors.success)(`✓ 服务器 "${name}" 的 shell 历史已清空`));
|
|
307
|
+
console.log('');
|
|
308
|
+
}
|
|
309
|
+
catch (error) {
|
|
310
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
311
|
+
console.log('');
|
|
312
|
+
console.log(chalk.hex(colors.error)(`✗ 无法清空远程 shell 历史: ${message}`));
|
|
313
|
+
console.log('');
|
|
314
|
+
}
|
|
315
|
+
}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 远程执行器模块
|
|
3
|
+
* 通过 SSH 在远程服务器上执行命令
|
|
4
|
+
*/
|
|
5
|
+
import { type RemoteConfig, type RemoteSysInfo } from './config.js';
|
|
6
|
+
/**
|
|
7
|
+
* 关闭 ControlMaster 连接
|
|
8
|
+
*/
|
|
9
|
+
export declare function closeControlMaster(name: string): Promise<void>;
|
|
10
|
+
/**
|
|
11
|
+
* 获取所有远程服务器配置
|
|
12
|
+
*/
|
|
13
|
+
export declare function getRemotes(): Record<string, RemoteConfig>;
|
|
14
|
+
/**
|
|
15
|
+
* 获取单个远程服务器配置
|
|
16
|
+
*/
|
|
17
|
+
export declare function getRemote(name: string): RemoteConfig | null;
|
|
18
|
+
/**
|
|
19
|
+
* 添加远程服务器
|
|
20
|
+
*/
|
|
21
|
+
export declare function addRemote(name: string, hostStr: string, options?: {
|
|
22
|
+
key?: string;
|
|
23
|
+
password?: boolean;
|
|
24
|
+
}): void;
|
|
25
|
+
/**
|
|
26
|
+
* 删除远程服务器
|
|
27
|
+
*/
|
|
28
|
+
export declare function removeRemote(name: string): boolean;
|
|
29
|
+
/**
|
|
30
|
+
* 显示所有远程服务器
|
|
31
|
+
*/
|
|
32
|
+
export declare function displayRemotes(): void;
|
|
33
|
+
/**
|
|
34
|
+
* 设置远程服务器工作目录
|
|
35
|
+
*/
|
|
36
|
+
export declare function setRemoteWorkDir(name: string, workDir: string): void;
|
|
37
|
+
/**
|
|
38
|
+
* 获取远程服务器工作目录
|
|
39
|
+
*/
|
|
40
|
+
export declare function getRemoteWorkDir(name: string): string | undefined;
|
|
41
|
+
/**
|
|
42
|
+
* SSH 执行选项
|
|
43
|
+
*/
|
|
44
|
+
export interface SSHExecOptions {
|
|
45
|
+
timeout?: number;
|
|
46
|
+
stdin?: string;
|
|
47
|
+
onStdout?: (data: string) => void;
|
|
48
|
+
onStderr?: (data: string) => void;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* SSH 执行结果
|
|
52
|
+
*/
|
|
53
|
+
export interface SSHExecResult {
|
|
54
|
+
exitCode: number;
|
|
55
|
+
stdout: string;
|
|
56
|
+
stderr: string;
|
|
57
|
+
output: string;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* 通过 SSH 执行命令
|
|
61
|
+
* 使用 ControlMaster 实现连接复用,密码认证只需输入一次
|
|
62
|
+
*/
|
|
63
|
+
export declare function sshExec(name: string, command: string, options?: SSHExecOptions): Promise<SSHExecResult>;
|
|
64
|
+
/**
|
|
65
|
+
* 测试远程连接
|
|
66
|
+
*/
|
|
67
|
+
export declare function testRemoteConnection(name: string): Promise<{
|
|
68
|
+
success: boolean;
|
|
69
|
+
message: string;
|
|
70
|
+
}>;
|
|
71
|
+
/**
|
|
72
|
+
* 获取缓存的远程系统信息
|
|
73
|
+
*/
|
|
74
|
+
export declare function getRemoteSysInfo(name: string): RemoteSysInfo | null;
|
|
75
|
+
/**
|
|
76
|
+
* 采集远程系统信息
|
|
77
|
+
*/
|
|
78
|
+
export declare function collectRemoteSysInfo(name: string, force?: boolean): Promise<RemoteSysInfo>;
|
|
79
|
+
/**
|
|
80
|
+
* 格式化远程系统信息供 AI 使用
|
|
81
|
+
*/
|
|
82
|
+
export declare function formatRemoteSysInfoForAI(name: string, sysInfo: RemoteSysInfo): string;
|
|
83
|
+
/**
|
|
84
|
+
* 批量远程执行结果
|
|
85
|
+
*/
|
|
86
|
+
export interface BatchRemoteResult {
|
|
87
|
+
server: string;
|
|
88
|
+
command: string;
|
|
89
|
+
exitCode: number;
|
|
90
|
+
stdout: string;
|
|
91
|
+
stderr: string;
|
|
92
|
+
output: string;
|
|
93
|
+
sysInfo: RemoteSysInfo;
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* 批量远程执行命令
|
|
97
|
+
* 每个服务器单独生成命令,支持异构环境
|
|
98
|
+
*/
|
|
99
|
+
export declare function generateBatchRemoteCommands(serverNames: string[], userPrompt: string, options?: {
|
|
100
|
+
debug?: boolean;
|
|
101
|
+
}): Promise<Array<{
|
|
102
|
+
server: string;
|
|
103
|
+
command: string;
|
|
104
|
+
sysInfo: RemoteSysInfo;
|
|
105
|
+
}>>;
|
|
106
|
+
/**
|
|
107
|
+
* 执行批量远程命令
|
|
108
|
+
*/
|
|
109
|
+
export declare function executeBatchRemoteCommands(commands: Array<{
|
|
110
|
+
server: string;
|
|
111
|
+
command: string;
|
|
112
|
+
sysInfo: RemoteSysInfo;
|
|
113
|
+
}>): Promise<BatchRemoteResult[]>;
|