diff options
Diffstat (limited to 'internal/hexaiaction/prompts.go')
| -rw-r--r-- | internal/hexaiaction/prompts.go | 91 |
1 files changed, 91 insertions, 0 deletions
diff --git a/internal/hexaiaction/prompts.go b/internal/hexaiaction/prompts.go new file mode 100644 index 0000000..2e0e4e2 --- /dev/null +++ b/internal/hexaiaction/prompts.go @@ -0,0 +1,91 @@ +package hexaiaction + +import ( + "context" + "strings" + "time" + + "codeberg.org/snonux/hexai/internal/appconfig" + "codeberg.org/snonux/hexai/internal/llm" + "codeberg.org/snonux/hexai/internal/textutil" +) + +// Render performs simple {{var}} replacement like LSP. +func Render(t string, vars map[string]string) string { return textutil.RenderTemplate(t, vars) } + +// StripFences removes surrounding markdown code fences. +func StripFences(s string) string { return textutil.StripCodeFences(s) } + +type chatDoer interface { + Chat(ctx context.Context, msgs []llm.Message, opts ...llm.RequestOption) (string, error) +} + +func runRewrite(ctx context.Context, cfg appconfig.App, client chatDoer, instruction, selection string) (string, error) { + sys := cfg.PromptCodeActionRewriteSystem + user := Render(cfg.PromptCodeActionRewriteUser, map[string]string{"instruction": instruction, "selection": selection}) + return runOnceWithOpts(ctx, client, sys, user, reqOptsFrom(cfg)) +} + +func runDiagnostics(ctx context.Context, cfg appconfig.App, client chatDoer, diags []string, selection string) (string, error) { + var b strings.Builder + for i, d := range diags { + if strings.TrimSpace(d) == "" { + continue + } + b.WriteString(strings.TrimSpace(d)) + if i < len(diags)-1 { + b.WriteString("\n") + } + } + sys := cfg.PromptCodeActionDiagnosticsSystem + user := Render(cfg.PromptCodeActionDiagnosticsUser, map[string]string{"diagnostics": b.String(), "selection": selection}) + return runOnceWithOpts(ctx, client, sys, user, reqOptsFrom(cfg)) +} + +func runDocument(ctx context.Context, cfg appconfig.App, client chatDoer, selection string) (string, error) { + sys := cfg.PromptCodeActionDocumentSystem + user := Render(cfg.PromptCodeActionDocumentUser, map[string]string{"selection": selection}) + return runOnceWithOpts(ctx, client, sys, user, reqOptsFrom(cfg)) +} + +func runGoTest(ctx context.Context, cfg appconfig.App, client chatDoer, funcCode string) (string, error) { + sys := cfg.PromptCodeActionGoTestSystem + user := Render(cfg.PromptCodeActionGoTestUser, map[string]string{"function": funcCode}) + return runOnceWithOpts(ctx, client, sys, user, reqOptsFrom(cfg)) +} + +func runOnce(ctx context.Context, client chatDoer, sys, user string) (string, error) { + msgs := []llm.Message{{Role: "system", Content: sys}, {Role: "user", Content: user}} + txt, err := client.Chat(ctx, msgs) + if err != nil { + return "", err + } + return strings.TrimSpace(StripFences(txt)), nil +} + +func runOnceWithOpts(ctx context.Context, client chatDoer, sys, user string, opts []llm.RequestOption) (string, error) { + msgs := []llm.Message{{Role: "system", Content: sys}, {Role: "user", Content: user}} + txt, err := client.Chat(ctx, msgs, opts...) + if err != nil { + return "", err + } + return strings.TrimSpace(StripFences(txt)), nil +} + +// reqOptsFrom builds LLM request options similar to LSP behavior. +func reqOptsFrom(cfg appconfig.App) []llm.RequestOption { + opts := []llm.RequestOption{llm.WithMaxTokens(cfg.MaxTokens)} + if cfg.CodingTemperature != nil { + opts = append(opts, llm.WithTemperature(*cfg.CodingTemperature)) + } + return opts +} + +// Timeout helpers to mirror LSP behavior. +func timeout10s(parent context.Context) (context.Context, context.CancelFunc) { + return context.WithTimeout(parent, 10*time.Second) +} + +func timeout8s(parent context.Context) (context.Context, context.CancelFunc) { + return context.WithTimeout(parent, 8*time.Second) +} |
