Files
ratatoskr-go/internal/analyst/prompt.go
Hermes bd3d825738
All checks were successful
CI / test (push) Successful in 46s
CI / build-and-package (amd64, darwin) (push) Successful in 36s
CI / build-and-package (amd64, linux) (push) Successful in 37s
CI / build-and-package (amd64, windows) (push) Successful in 44s
CI / build-and-package (arm64, darwin) (push) Successful in 35s
CI / build-and-package (arm64, linux) (push) Successful in 36s
feat: множественные репозитории (Repos) и клонирование в воркере
- Task.Repos []string (XML-колонка repos, обратная совместимость с repo)
- config: блок git {base_url, token}
- аналитик: ответ repos[], шаблон показывает список
- core: propose без repos → возврат в сбор (E1)
- worker вариант A: один dev из общего cwd, prepareRepos клонирует
  недостающие репо (git clone), validateRepoName (E3), ErrRepoNotGit (E4)
- ошибки E1-E4 в worker/errors.go
2026-08-16 09:18:15 +05:00

79 lines
3.3 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package analyst
import (
"strings"
"text/template"
)
// promptTemplate — шаблон промпта для аналитика (opencode analyst-agent).
// Выдаётся как stdin модели, ожидается JSON-ответ с phase, изменениями, вопросами.
var promptTemplate = template.Must(template.New("analyst").Parse(`Ты — аналитик, помогаешь сформулировать задачу для opencode (ИИ-агент для написания кода).
📋 **Твоя задача:**
Пока не все поля задачи прояснены — задавай уточняющие вопросы (одновременно до 3).
Когда достаточно данных — предложи готовый черновик задачи.
Если тема явно не про код или не подходит opencode — abort.
**Поля задачи:**
| Поле | Описание |
|------|----------|
| title | краткое название (14 слова) |
| goal | цель задачи: что именно нужно сделать |
| repos | список репозиториев (имена на git-хосте; для связанных — все сразу) |
| why | зачем это нужно, контекст |
| ac | acceptance criteria — конкретный результат, что считается готовым |
{{- if .Force}}
⚠️ **Режим принудительного предложения** — не задавай вопросы, сразу предложи черновик даже с тем, что есть.
{{- end}}
**Переписка с пользователем:**
{{.History}}
**Текущий черновик:**
{{if .Title}} title: {{.Title}}{{else}} title: (не задано){{end}}
{{if .Goal}} goal: {{.Goal}}{{else}} goal: (не задано){{end}}
{{if .Repos}}
repos:
{{- range .Repos}}
- {{.}}
{{- end}}
{{- else}} repos: (не задано){{end}}
{{if .Why}} why: {{.Why}}{{else}} why: (не задано){{end}}
{{if .AC}} ac: {{.AC}}{{else}} ac: (не задано){{end}}
**Ответь строго JSON-объектом, без лишнего текста:**
{
"phase": "ask|propose|abort",
"title": "название (только если меняешь)",
"goal": "цель (только если меняешь)",
"repos": ["имя_репо_1", "имя_репо_2"],
"why": "зачем (только если меняешь)",
"ac": "критерии (только если меняешь)",
"questions": ["вопрос 1", "вопрос 2"],
"chat_reply": "твой ответ пользователю (на русском, естественно)",
"abort_reason": "если phase=abort — причина"
}
`))
// TemplateData — данные для рендера шаблона промпта.
type TemplateData struct {
Title string
Goal string
Repos []string
Why string
AC string
History string // отформатированная переписка
Force bool
}
// RenderPrompt собирает промпт из истории и черновика.
func RenderPrompt(data TemplateData) (string, error) {
var buf strings.Builder
if err := promptTemplate.Execute(&buf, data); err != nil {
return "", err
}
return buf.String(), nil
}