(fs afero.Fs, coderPrompt, systemPrompt, claudeMDPath string)
| 898 | ) |
| 899 | |
| 900 | func injectClaudeMD(fs afero.Fs, coderPrompt, systemPrompt, claudeMDPath string) error { |
| 901 | _, err := fs.Stat(claudeMDPath) |
| 902 | if err != nil { |
| 903 | if !os.IsNotExist(err) { |
| 904 | return xerrors.Errorf("failed to stat claude config: %w", err) |
| 905 | } |
| 906 | // Write a new file with the system prompt. |
| 907 | if err = fs.MkdirAll(filepath.Dir(claudeMDPath), 0o700); err != nil { |
| 908 | return xerrors.Errorf("failed to create claude config directory: %w", err) |
| 909 | } |
| 910 | |
| 911 | return afero.WriteFile(fs, claudeMDPath, []byte(promptsBlock(coderPrompt, systemPrompt, "")), 0o600) |
| 912 | } |
| 913 | |
| 914 | bs, err := afero.ReadFile(fs, claudeMDPath) |
| 915 | if err != nil { |
| 916 | return xerrors.Errorf("failed to read claude config: %w", err) |
| 917 | } |
| 918 | |
| 919 | // Extract the content without the guarded sections |
| 920 | cleanContent := string(bs) |
| 921 | |
| 922 | // Remove existing coder prompt section if it exists |
| 923 | coderStartIdx := indexOf(cleanContent, coderPromptStartGuard) |
| 924 | coderEndIdx := indexOf(cleanContent, coderPromptEndGuard) |
| 925 | if coderStartIdx != -1 && coderEndIdx != -1 && coderStartIdx < coderEndIdx { |
| 926 | beforeCoderPrompt := cleanContent[:coderStartIdx] |
| 927 | afterCoderPrompt := cleanContent[coderEndIdx+len(coderPromptEndGuard):] |
| 928 | cleanContent = beforeCoderPrompt + afterCoderPrompt |
| 929 | } |
| 930 | |
| 931 | // Remove existing system prompt section if it exists |
| 932 | systemStartIdx := indexOf(cleanContent, systemPromptStartGuard) |
| 933 | systemEndIdx := indexOf(cleanContent, systemPromptEndGuard) |
| 934 | if systemStartIdx != -1 && systemEndIdx != -1 && systemStartIdx < systemEndIdx { |
| 935 | beforeSystemPrompt := cleanContent[:systemStartIdx] |
| 936 | afterSystemPrompt := cleanContent[systemEndIdx+len(systemPromptEndGuard):] |
| 937 | cleanContent = beforeSystemPrompt + afterSystemPrompt |
| 938 | } |
| 939 | |
| 940 | // Trim any leading whitespace from the clean content |
| 941 | cleanContent = strings.TrimSpace(cleanContent) |
| 942 | |
| 943 | // Create the new content with coder and system prompt prepended |
| 944 | newContent := promptsBlock(coderPrompt, systemPrompt, cleanContent) |
| 945 | |
| 946 | // Write the updated content back to the file |
| 947 | err = afero.WriteFile(fs, claudeMDPath, []byte(newContent), 0o600) |
| 948 | if err != nil { |
| 949 | return xerrors.Errorf("failed to write claude config: %w", err) |
| 950 | } |
| 951 | |
| 952 | return nil |
| 953 | } |
| 954 | |
| 955 | func promptsBlock(coderPrompt, systemPrompt, existingContent string) string { |
| 956 | var newContent strings.Builder |
no test coverage detected