feat: assistant reads, lists and writes files and runs commands on any of the user's machines; agent mode does the steps itself, asking before each command and write
This commit is contained in:
1 parent
d9c7c2dd42
commit
a7e43ab700
5 files changed
+207
-31
No files matched your search
+18
-6
@@ -348,11 +348,18 @@ func gradioAnswer(raw json.RawMessage, cur string) string {
|
||||
}
|
||||
|
||||
const aiSystem = `Ты - ассистент панели LPRA (удалённый доступ к машинам: терминалы, файлы, порты). Отвечай по-русски, коротко и по делу.
|
||||
Ниже - что пользователь сейчас видит в панели: вкладки, активная панель, текст терминала или список файлов.
|
||||
Если нужно выполнить команду, дай её отдельным блоком
|
||||
` + "```run\nкоманда\n```" + `
|
||||
Пользователь сам нажмёт «Выполнить» - команда уйдёт в активный терминал с его правами. Одна команда на блок, без пояснений внутри блока.
|
||||
Не выдумывай вывод команд: после выполнения ты увидишь его в следующем сообщении. Опасные команды (удаление, перезапуск, изменение системы) - только с предупреждением.`
|
||||
Ниже - что пользователь сейчас видит в панели: его машины, вкладки, активная панель, текст терминала или список файлов.
|
||||
Действия - отдельными блоками, панель выполнит их с правами пользователя:
|
||||
` + "```run машина\nкоманда\n```" + ` - команда в терминале этой машины (машину можно не указывать - тогда активная);
|
||||
` + "```read машина:/путь\n```" + ` - прочитать файл;
|
||||
` + "```ls машина:/путь\n```" + ` - список папки;
|
||||
` + "```write машина:/путь\nполное новое содержимое файла\n```" + ` - записать файл целиком.
|
||||
Имя машины - как в списке машин. Одна команда на блок, без пояснений внутри блока. Результат действия придёт следующим сообщением - не выдумывай его.
|
||||
Опасные команды (удаление, перезапуск, изменение системы) - только с предупреждением. Перед правкой файла сначала прочитай его.`
|
||||
|
||||
const aiAgent = `
|
||||
Режим агента: ты сам ведёшь задачу шаг за шагом. В каждом ответе - коротко, что делаешь, и ровно одно действие. Получив результат, решай следующий шаг.
|
||||
Когда задача решена (или решить нельзя) - ответь итогом без блоков действий.`
|
||||
|
||||
// POST /api/panel/ai/chat - {messages, context}: the answer, streamed as
|
||||
// plain text. A failure after the start ends the text with "[ошибка: …]".
|
||||
@@ -365,6 +372,7 @@ func (s *Server) handleAIChat(w http.ResponseWriter, r *http.Request) {
|
||||
var in struct {
|
||||
Messages []aiMsg `json:"messages"`
|
||||
Context string `json:"context"`
|
||||
Agent bool `json:"agent"`
|
||||
}
|
||||
if err := json.NewDecoder(http.MaxBytesReader(w, r.Body, 1<<20)).Decode(&in); err != nil || len(in.Messages) == 0 {
|
||||
http.Error(w, "плохой запрос", http.StatusBadRequest)
|
||||
@@ -400,7 +408,11 @@ func (s *Server) handleAIChat(w http.ResponseWriter, r *http.Request) {
|
||||
fl.Flush()
|
||||
}
|
||||
}
|
||||
err := aiStream(r.Context(), s.aiConfig(), aiSystem+"\n\n--- Панель сейчас ---\n"+in.Context, in.Messages, emit)
|
||||
system := aiSystem
|
||||
if in.Agent {
|
||||
system += aiAgent
|
||||
}
|
||||
err := aiStream(r.Context(), s.aiConfig(), system+"\n\n--- Панель сейчас ---\n"+in.Context, in.Messages, emit)
|
||||
if err != nil && r.Context().Err() == nil {
|
||||
if !wrote {
|
||||
w.WriteHeader(http.StatusBadGateway)
|
||||
|
||||
Reference in new issue
Block a user