Files
ratatoskr-go/internal/analyst/prompt.go
ki.sagidullin 6c0b903794
Some checks failed
CI / test (push) Failing after 1m52s
CI / build-and-package (amd64, linux) (push) Failing after 1m3s
CI / build-and-package (amd64, windows) (push) Successful in 30s
feat(analyst): этапы задачи — аналитик раскладывает на steps с критериями готовности, dev идёт по ним
2026-08-24 18:05:06 +05:00

99 lines
4.7 KiB
Go
Raw Permalink 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"
"github.com/kamelion/ratatoskr-go/internal/storage"
)
// 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 — конкретный результат, что считается готовым |
| steps | (опционально) разбиение задачи на этапы: список {title, ac} с критерием готовности каждого этапа |
Изменяй в JSON только те поля, которые надо поменять; что менять не надо — пустой строкой.
**Фаза ответа (phase):**
- ask — данных не хватает: задай вопросы (до 3), черновик не меняешь.
- propose — черновик ДОСТАТОЧЕН и ты ВНОСИШЬ правки: заполни изменяемые поля (title/goal/repos/why/ac), в chat_reply — краткое резюме.
- ready — черновик уже ПОЛНЫЙ и готов как есть, менять НЕЧЕГО: phase="ready", все поля изменений оставь пустыми, в chat_reply — резюме и подтверждение готовности. Задачу можно отправлять агенту-кодеру.
- abort — тема не про код / не подходит: phase="abort" с abort_reason.
{{- 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}}
{{if .Steps}}
steps:
{{- range .Steps}}
- {{.Title}}{{if .AC}}{{.AC}}{{end}}
{{- end}}
{{- else}} steps: (не задано){{end}}
**Ответь строго JSON-объектом, без лишнего текста:**
{
"phase": "ask|propose|ready|abort",
"title": "название (только если меняешь)",
"goal": "цель (только если меняешь)",
"repos": ["имя_репо_1", "имя_репо_2"],
"why": "зачем (только если меняешь)",
"ac": "критерии (только если меняешь)",
"steps": [{"title": "этап 1", "ac": "критерий этапа 1"}],
"questions": ["вопрос 1", "вопрос 2"],
"chat_reply": "твой ответ пользователю (на русском, естественно)",
"abort_reason": "если phase=abort — причина"
}
`))
// TemplateData — данные для рендера шаблона промпта.
type TemplateData struct {
Title string
Goal string
Repos []string
Why string
AC string
Steps []storage.Step
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
}