16c0e7b61042e70e368b1ac58bc685d052d1da59

Author
TheEdgeOfRage <git@theedgeofrage.com>
Committer
TheEdgeOfRage <git@theedgeofrage.com>
Date

Message

remove: drop persona generation

Diff

  1diff --git a/cmd/jp/main.go b/cmd/jp/main.go
  2index f4280f829ac62bc6c814b5c3742b343ee2ff3b58..79166aef5fa4dba67eff0717fff29fbf5dd4ae79 100644
  3--- a/cmd/jp/main.go
  4+++ b/cmd/jp/main.go
  5@@ -2,8 +2,6 @@
  6 package main
  7 
  8 import (
  9-	"context"
 10-	"encoding/json"
 11 	"fmt"
 12 	"io"
 13 	"net/http"
 14@@ -32,8 +30,6 @@ func main() {
 15 	switch os.Args[1] {
 16 	case "run":
 17 		runCmd(os.Args[2:])
 18-	case "persona":
 19-		personaCmd(os.Args[2:])
 20 	case "help", "-h", "--help":
 21 		usage(os.Stdout)
 22 	default:
 23@@ -149,51 +145,13 @@ func fatalf(format string, args ...any) {
 24 	os.Exit(1)
 25 }
 26 
 27-func personaCmd(args []string) {
 28-	if len(args) == 0 || args[0] != "gen" {
 29-		fmt.Fprintln(os.Stderr, "jp persona: expected subcommand 'gen'")
 30-		os.Exit(1)
 31-	}
 32-	genPersonaCmd(args[1:])
 33-}
 34-
 35-type genOptions struct {
 36-	config.Config
 37-	Role string `long:"role" required:"true" description:"role to author a persona for"`
 38-}
 39-
 40-func genPersonaCmd(args []string) {
 41-	opts := parseOpts[genOptions]("persona gen", args)
 42-
 43-	ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second)
 44-	defer cancel()
 45-	client := llm.NewClient(opts.LLMBaseURL, nil)
 46-	draft, err := persona.GenerateDraft(ctx, client, opts.Role)
 47-	if err != nil {
 48-		fmt.Fprintf(os.Stderr, "persona gen: LLM service at %s unavailable: %v\n", opts.LLMBaseURL, err)
 49-		os.Exit(1)
 50-	}
 51-
 52-	out, merr := json.MarshalIndent(draft, "", "  ")
 53-	if merr != nil {
 54-		fmt.Fprintf(os.Stderr, "persona gen: encode draft: %v\n", merr)
 55-		os.Exit(1)
 56-	}
 57-	if _, werr := fmt.Fprintln(os.Stdout, string(out)); werr != nil {
 58-		os.Exit(1)
 59-	}
 60-	fmt.Fprintln(os.Stderr, "DRAFT persona. Requires human review before use.")
 61-	fmt.Fprintln(os.Stderr, "Nothing was written to assets/personas/. Review it and save it yourself.")
 62-}
 63-
 64 func usage(w io.Writer) {
 65 	_, _ = fmt.Fprint(w, `jp - Japanese learning RPG
 66 
 67 Usage:
 68-  jp run [flags]           Run the game
 69-  jp persona gen --role R  Author a persona draft
 70-  jp help                  Show this help
 71+  jp run [flags]   Run the game
 72+  jp help          Show this help
 73 
 74-Run "jp run -help" or "jp persona gen -help" for flag details.
 75+Run "jp run -help" for flag details.
 76 `)
 77 }
 78diff --git a/internal/llm/contract.go b/internal/llm/contract.go
 79index ffb93543c4f8445aea93c09907b8c96f43fe7c52..15c8dd648885abc5a1a7ef45dabe717bb0323dbb 100644
 80--- a/internal/llm/contract.go
 81+++ b/internal/llm/contract.go
 82@@ -92,13 +92,6 @@ func requireFields(vals map[string]string, names []string) error {
 83 	return nil
 84 }
 85 
 86-// ParseFields is the shared strict FIELD|value parser for model output
 87-// contracts. It tolerates surrounding whitespace and returns a recoverable
 88-// *ContractError on malformed lines, unknown fields, or duplicate fields.
 89-func ParseFields(raw string, names ...string) (map[string]string, error) {
 90-	return parseFields(raw, names)
 91-}
 92-
 93 type NPCReply struct {
 94 	Romaji  string
 95 	Kana    string
 96diff --git a/internal/persona/draft.go b/internal/persona/draft.go
 97deleted file mode 100644
 98index fc9783a52b2189da3bf7967584024c878b8d3295..0000000000000000000000000000000000000000
 99--- a/internal/persona/draft.go
100+++ /dev/null
101@@ -1,71 +0,0 @@
102-package persona
103-
104-import (
105-	"context"
106-
107-	"japanese/internal/llm"
108-)
109-
110-// PersonaDraft is an LLM-authored, not-yet-reviewed persona. It carries only
111-// the fields the model can author; location, situation, and ambiguity are
112-// filled in by a human during review before it becomes a stored Persona.
113-type PersonaDraft struct {
114-	Name        string `json:"name"`
115-	Personality string `json:"personality"`
116-	SpeechStyle string `json:"speech_style"`
117-}
118-
119-const draftSystem = `You write one person's profile for use in a realistic everyday conversation.
120-Return exactly three lines and nothing else, in this order:
121-NAME|<a natural name for the person>
122-PERSONALITY|<two to four personality traits separated by commas>
123-SPEECH_STYLE|<one sentence describing how they speak>`
124-
125-// DraftSystemPrompt returns the game-free system prompt for persona authoring.
126-// It names no game, player, NPC, quest, or scenario.
127-func DraftSystemPrompt() string { return draftSystem }
128-
129-// DraftUserPrompt returns the user prompt that supplies the role to author.
130-func DraftUserPrompt(role string) string {
131-	return "Write the profile of a real person whose role is: " + role + ". They are in an ordinary, real-world situation."
132-}
133-
134-var draftFieldNames = []string{"NAME", "PERSONALITY", "SPEECH_STYLE"}
135-
136-// GenerateDraft asks the configured LLM client for a persona draft for the
137-// given role and parses the strict three-field result. It issues exactly one
138-// chat request; it never starts, probes, or manages any service.
139-func GenerateDraft(ctx context.Context, client *llm.Client, role string) (PersonaDraft, error) {
140-	msgs := []llm.Message{
141-		{Role: llm.RoleSystem, Content: DraftSystemPrompt()},
142-		{Role: llm.RoleUser, Content: DraftUserPrompt(role)},
143-	}
144-	raw, err := client.Generate(ctx, msgs, llm.Qwen3Options())
145-	if err != nil {
146-		return PersonaDraft{}, err
147-	}
148-	return ParseDraft(raw)
149-}
150-
151-// ParseDraft parses the strict three-field persona draft contract. Missing or
152-// empty fields and malformed lines are recoverable *llm.ContractError values.
153-func ParseDraft(raw string) (PersonaDraft, error) {
154-	vals, err := llm.ParseFields(raw, draftFieldNames...)
155-	if err != nil {
156-		return PersonaDraft{}, err
157-	}
158-	for _, name := range draftFieldNames {
159-		v, ok := vals[name]
160-		if !ok {
161-			return PersonaDraft{}, &llm.ContractError{Kind: llm.MissingField, Field: name}
162-		}
163-		if v == "" {
164-			return PersonaDraft{}, &llm.ContractError{Kind: llm.EmptyValue, Field: name}
165-		}
166-	}
167-	return PersonaDraft{
168-		Name:        vals["NAME"],
169-		Personality: vals["PERSONALITY"],
170-		SpeechStyle: vals["SPEECH_STYLE"],
171-	}, nil
172-}