Skip to content

Commit be81135

Browse files
committed
Process @mentions in systemprompts
1 parent 66ea6a5 commit be81135

2 files changed

Lines changed: 33 additions & 4 deletions

File tree

src/repl/main.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -819,7 +819,7 @@ func showHelp() {
819819
.mai/rc (project or ~/.mai/rc) : script to be loaded before the repl is shown
820820
.mai/history.json (project or ~/.mai) : REPL command history file (JSON array)
821821
.mai/chat (project or ~/.mai) : storage for chat session files
822-
.mai/systemprompt.md (project or ~/.mai) : system prompt file
822+
.mai/systemprompt.md (project or ~/.mai) : system prompt file (supports '@' include directives)
823823
./prompts : directory containing custom prompts
824824
`)
825825
}

src/repl/repl.go

Lines changed: 32 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -168,11 +168,13 @@ func NewREPL(config *Config) (*REPL, error) {
168168
}
169169
}
170170

171-
// Load system prompt from promptfile if set
171+
// Load system prompt from promptfile if set, processing include directives
172172
if promptFile := repl.config.options.Get("promptfile"); promptFile != "" {
173173
content, err := os.ReadFile(promptFile)
174174
if err == nil {
175-
repl.systemPrompt = string(content)
175+
promptText := string(content)
176+
promptText = repl.processIncludeStatements(promptText, filepath.Dir(promptFile))
177+
repl.systemPrompt = promptText
176178
}
177179
} else if systemPrompt := repl.config.options.Get("systemprompt"); systemPrompt != "" {
178180
// Or use systemprompt text if set
@@ -1595,7 +1597,9 @@ func (r *REPL) sendToAI(input string) error {
15951597
if content, err := os.ReadFile(spFile); err != nil {
15961598
fmt.Fprintf(os.Stderr, "Error loading system prompt file %s: %v\r\n", spFile, err)
15971599
} else {
1598-
finalSystemPrompt = string(content)
1600+
text := string(content)
1601+
text = r.processIncludeStatements(text, filepath.Dir(spFile))
1602+
finalSystemPrompt = text
15991603
}
16001604
}
16011605
}
@@ -3238,6 +3242,31 @@ func (r *REPL) processAtMentions(input string) string {
32383242
return enhancedInput
32393243
}
32403244

3245+
// processIncludeStatements processes include directives in prompt content.
3246+
// Lines starting with '@' are treated as file paths to include.
3247+
func (r *REPL) processIncludeStatements(content, baseDir string) string {
3248+
var out []string
3249+
for _, line := range strings.Split(content, "\n") {
3250+
trimmed := strings.TrimSpace(line)
3251+
if strings.HasPrefix(trimmed, "@") {
3252+
incPath := strings.TrimSpace(trimmed[1:])
3253+
target := incPath
3254+
if !filepath.IsAbs(incPath) && baseDir != "" {
3255+
target = filepath.Join(baseDir, incPath)
3256+
}
3257+
if data, err := os.ReadFile(target); err != nil {
3258+
fmt.Fprintf(os.Stderr, "Error including file %s: %v\n", target, err)
3259+
out = append(out, line)
3260+
} else {
3261+
out = append(out, string(data))
3262+
}
3263+
} else {
3264+
out = append(out, line)
3265+
}
3266+
}
3267+
return strings.Join(out, "\n")
3268+
}
3269+
32413270
// autoDetectPromptDir attempts to find a prompts directory relative to the executable path
32423271
// and sets the promptdir config variable if found
32433272
func (r *REPL) autoDetectPromptDir() {

0 commit comments

Comments
 (0)