nub/internal/tool/builtin/question.go
Tom a97013d876 initial commit
- v 0.1.0 siehe CHANGELOG.md
2026-07-25 11:08:01 +02:00

74 lines
2.2 KiB
Go

package builtin
import (
"context"
"encoding/json"
"fmt"
"nub/internal/tool"
)
// QuestionTool stellt eine generische Rückfrage an den Nutzer — anders als
// Permissions (system-/config-entschieden, boolesch) entscheidet hier das
// Modell selbst, dass es etwas klären will, und bekommt eine Text-Antwort
// als normales Tool-Ergebnis zurück. Kein Permission-Gate: das Tool ist
// von sich aus interaktiv, eine Rückfrage auf die Rückfrage ergäbe keinen
// Sinn.
type QuestionTool struct{}
func (QuestionTool) Name() string { return "question" }
func (QuestionTool) Description() string {
return "Stellt dem Nutzer eine Rückfrage, wenn eine Aufgabe mehrdeutig ist oder eine Entscheidung nötig ist, bevor es weitergeht."
}
func (QuestionTool) Schema() json.RawMessage {
return json.RawMessage(`{
"type": "object",
"properties": {
"question": {"type": "string"},
"options": {
"type": "array",
"items": {"type": "string"},
"description": "Optionale Vorschläge, die dem Nutzer zusätzlich zur Frage angezeigt werden"
}
},
"required": ["question"]
}`)
}
type questionInput struct {
Question string `json:"question"`
Options []string `json:"options"`
}
func (QuestionTool) Run(ctx context.Context, input json.RawMessage, env tool.Env) (tool.Result, error) {
var in questionInput
if err := json.Unmarshal(input, &in); err != nil {
return tool.Result{ForModel: "invalid input: " + err.Error(), IsError: true}, nil
}
if in.Question == "" {
return tool.Result{ForModel: "question must not be empty", IsError: true}, nil
}
if env.Ask == nil {
return tool.Result{
ForModel: "interactive questions are not supported in this mode (e.g. print mode) — proceed with your best judgment, or state your assumption in your next reply instead of asking",
IsError: true,
}, nil
}
answer, err := env.Ask(ctx, in.Question, in.Options)
if err != nil {
return tool.Result{ForModel: fmt.Sprintf("question failed: %v", err), IsError: true}, nil
}
return tool.Result{
ForModel: answer,
ForUI: QuestionResult{Question: in.Question, Options: in.Options, Answer: answer},
}, nil
}
type QuestionResult struct {
Question string
Options []string
Answer string
}