// Package session holds what the two front ends — the terminal REPL // (internal/agent) and the editor front end (internal/acp) — agree a // conversation starts from, and how it is reset by the /new command. // // A session, for both of them, is a plain []*ai.Message whose first element is // the system prompt. "Starting a new session" means going back to exactly that: // the system prompt alone, every question, answer and tool turn forgotten. // The package knows nothing about the screen or the protocol: printing the // report line, or sending the session/update, stays each front end's job. package session import ( "strings" "github.com/firebase/genkit/go/ai" ) // NewCommand is the slash command that clears the history and starts a new // session. The same spelling is used at the terminal prompt and in an ACP // prompt; ACP advertises it without the slash (see NewCommandName). const NewCommand = "/new" // NewCommandName is NewCommand as ACP names it: clients list commands by bare // name and send them back as prompt text with the leading slash. const NewCommandName = "new" // IsNewCommand reports whether the user's input is the /new command. The // input is trimmed first: an editor sends the line as typed, spaces and // trailing newline included, and "/new " must not be mistaken for a question. // // session.IsNewCommand("/new") // true // session.IsNewCommand(" /new\n") // true // session.IsNewCommand("/new one") // false — not the command func IsNewCommand(input string) bool { return strings.TrimSpace(input) == NewCommand } // Fresh returns the history of a brand-new session: the system prompt and // nothing else. Both front ends start from it, and /new returns to it. // // messages := session.Fresh(config.Cfg.System) // // len(messages) == 1, messages[0].Role == ai.RoleSystem func Fresh(system string) []*ai.Message { return []*ai.Message{ai.NewSystemTextMessage(system)} } // Forgotten counts the messages a reset throws away: everything except the // system prompt. It is the figure the report line shows ("12 message(s) // forgotten"), so the user sees that the command did something — or that // there was nothing to forget. // // session.Forgotten(session.Fresh("you are bob")) // 0 func Forgotten(msgs []*ai.Message) int { n := 0 for _, m := range msgs { if m.Role != ai.RoleSystem { n++ } } return n }