1
0

documentation and configuration for the AI coding assistant aider AI (#174)

Co-authored-by: Michael Hoennig <michael@hoennig.de>
Reviewed-on: https://dev.hostsharing.net/hostsharing/hs.hsadmin.ng/pulls/174
Reviewed-by: Timotheus Pokorra <timotheus.pokorra@hostsharing.net>
This commit is contained in:
Michael Hoennig
2025-04-11 15:27:54 +02:00
parent 77ace7d794
commit 50541266b4
5 changed files with 723 additions and 1 deletions

462
.aider.conf.yml Normal file
View File

@@ -0,0 +1,462 @@
##########################################################
# Sample .aider.conf.yml
# This file lists *all* the valid configuration entries.
# Place in your home dir, or at the root of your git repo.
##########################################################
# Note: You can only put OpenAI and Anthropic API keys in the yaml
# config file. Keys for all APIs can be stored in a .env file
# https://aider.chat/docs/config/dotenv.html
##########
# options:
## show this help message and exit
#help: xxx
#############
# Main model:
## Specify the model to use for the main chat
model: gemini-2.5-pro
########################
# API Keys and settings:
## Specify the OpenAI API key
#openai-api-key: xxx
## Specify the Anthropic API key
#anthropic-api-key: xxx
## Specify the api base url
#openai-api-base: xxx
## (deprecated, use --set-env OPENAI_API_TYPE=<value>)
#openai-api-type: xxx
## (deprecated, use --set-env OPENAI_API_VERSION=<value>)
#openai-api-version: xxx
## (deprecated, use --set-env OPENAI_API_DEPLOYMENT_ID=<value>)
#openai-api-deployment-id: xxx
## (deprecated, use --set-env OPENAI_ORGANIZATION=<value>)
#openai-organization-id: xxx
## Set an environment variable (to control API settings, can be used multiple times)
#set-env: xxx
## Specify multiple values like this:
#set-env:
# - xxx
# - yyy
# - zzz
## Set an API key for a provider (eg: --api-key provider=<key> sets PROVIDER_API_KEY=<key>)
#api-key: xxx
## Specify multiple values like this:
#api-key:
# - xxx
# - yyy
# - zzz
#################
# Model settings:
## List known models which match the (partial) MODEL name
#list-models: xxx
## Specify a file with aider model settings for unknown models
#model-settings-file: .aider.model.settings.yml
## Specify a file with context window and costs for unknown models
#model-metadata-file: .aider.model.metadata.json
## Add a model alias (can be used multiple times)
#alias: xxx
## Specify multiple values like this:
#alias:
# - xxx
# - yyy
# - zzz
## Set the reasoning_effort API parameter (default: not set)
## depends on the concrete model if and how this is supported
reasoning-effort: high
## Set the thinking token budget for models that support it (default: not set)
## depends on the concrete model if and how this is supported
#thinking-tokens: xxx
## Verify the SSL cert when connecting to models (default: True)
#verify-ssl: true
## Timeout in seconds for API calls (default: None)
#timeout: xxx
## Specify what edit format the LLM should use (default depends on model)
#edit-format: xxx
## Use architect edit format for the main chat
#architect: false
## Enable/disable automatic acceptance of architect changes (default: True)
#auto-accept-architect: true
## Specify the model to use for commit messages and chat history summarization (default depends on --model)
#weak-model: xxx
## Specify the model to use for editor tasks (default depends on --model)
#editor-model: xxx
## Specify the edit format for the editor model (default: depends on editor model)
#editor-edit-format: xxx
## Only work with models that have meta-data available (default: True)
#show-model-warnings: true
## Check if model accepts settings like reasoning_effort/thinking_tokens (default: True)
#check-model-accepts-settings: true
## Soft limit on tokens for chat history, after which summarization begins. If unspecified, defaults to the model's max_chat_history_tokens.
#max-chat-history-tokens: xxx
#################
# Cache settings:
## Enable caching of prompts (default: False)
#cache-prompts: false
## Number of times to ping at 5min intervals to keep prompt cache warm (default: 0)
#cache-keepalive-pings: false
###################
# Repomap settings:
## Suggested number of tokens to use for repo map, use 0 to disable
#map-tokens: xxx
## Control how often the repo map is refreshed. Options: auto, always, files, manual (default: auto)
#map-refresh: auto
## Multiplier for map tokens when no files are specified (default: 2)
#map-multiplier-no-files: true
################
# History Files:
## Specify the chat input history file (default: .aider.input.history)
#input-history-file: .aider.input.history
## Specify the chat history file (default: .aider.chat.history.md)
#chat-history-file: .aider.chat.history.md
## Restore the previous chat history messages (default: False)
#restore-chat-history: false
## Log the conversation with the LLM to this file (for example, .aider.llm.history)
#llm-history-file: xxx
##################
# Output settings:
## Use colors suitable for a dark terminal background (default: False)
#dark-mode: false
## Use colors suitable for a light terminal background (default: False)
#light-mode: false
## Enable/disable pretty, colorized output (default: True)
#pretty: true
## Enable/disable streaming responses (default: True)
#stream: true
## Set the color for user input (default: #00cc00)
#user-input-color: "#00cc00"
## Set the color for tool output (default: None)
#tool-output-color: "xxx"
## Set the color for tool error messages (default: #FF2222)
#tool-error-color: "#FF2222"
## Set the color for tool warning messages (default: #FFA500)
#tool-warning-color: "#FFA500"
## Set the color for assistant output (default: #0088ff)
#assistant-output-color: "#0088ff"
## Set the color for the completion menu (default: terminal's default text color)
#completion-menu-color: "xxx"
## Set the background color for the completion menu (default: terminal's default background color)
#completion-menu-bg-color: "xxx"
## Set the color for the current item in the completion menu (default: terminal's default background color)
#completion-menu-current-color: "xxx"
## Set the background color for the current item in the completion menu (default: terminal's default text color)
#completion-menu-current-bg-color: "xxx"
## Set the markdown code theme (default: default, other options include monokai, solarized-dark, solarized-light, or a Pygments builtin style, see https://pygments.org/styles for available themes)
#code-theme: default
## Show diffs when committing changes (default: False)
#show-diffs: false
###############
# Git settings:
## Enable/disable looking for a git repo (default: True)
#git: true
## Enable/disable adding .aider* to .gitignore (default: True)
#gitignore: true
## Specify the aider ignore file (default: .aiderignore in git root)
#aiderignore: .aiderignore
## Only consider files in the current subtree of the git repository
#subtree-only: false
## Enable/disable auto commit of LLM changes (default: True)
auto-commits: false
## Enable/disable commits when repo is found dirty (default: True)
#dirty-commits: true
## Attribute aider code changes in the git author name (default: True)
#attribute-author: true
## Attribute aider commits in the git committer name (default: True)
#attribute-committer: true
## Prefix commit messages with 'aider: ' if aider authored the changes (default: False)
#attribute-commit-message-author: false
## Prefix all commit messages with 'aider: ' (default: False)
#attribute-commit-message-committer: false
## Enable/disable git pre-commit hooks with --no-verify (default: False)
#git-commit-verify: false
## Commit all pending changes with a suitable commit message, then exit
#commit: false
## Specify a custom prompt for generating commit messages
#commit-prompt: xxx
## Perform a dry run without modifying files (default: False)
#dry-run: false
## Skip the sanity check for the git repository (default: False)
#skip-sanity-check-repo: false
## Enable/disable watching files for ai coding comments (default: False)
#watch-files: false
########################
# Fixing and committing:
## Lint and fix provided files, or dirty files if none provided
lint: false
## Specify lint commands to run for different languages, eg: "python: flake8 --select=..." (can be used multiple times)
# lint-cmd: gw-spotless # won't work because aider does not support bash aliases
## Specify multiple values like this:
#lint-cmd:
# - xxx
# - yyy
# - zzz
## Enable/disable automatic linting after changes (default: True)
#auto-lint: true
## Specify command to run tests
#test-cmd: xxx
## Enable/disable automatic testing after changes (default: False)
#auto-test: false
## Run tests, fix problems found and then exit
#test: false
############
# Analytics:
## Enable/disable analytics for current session (default: random)
#analytics: xxx
## Specify a file to log analytics events
#analytics-log: xxx
## Permanently disable analytics
#analytics-disable: false
############
# Upgrading:
## Check for updates and return status in the exit code
#just-check-update: false
## Check for new aider versions on launch
#check-update: true
## Show release notes on first run of new version (default: None, ask user)
#show-release-notes: xxx
## Install the latest version from the main branch
#install-main-branch: false
## Upgrade aider to the latest version from PyPI
#upgrade: false
## Show the version number and exit
#version: xxx
########
# Modes:
## Specify a single message to send the LLM, process reply then exit (disables chat mode)
#message: xxx
## Specify a file containing the message to send the LLM, process reply, then exit (disables chat mode)
#message-file: xxx
## Run aider in your browser (default: False)
#gui: false
## Enable automatic copy/paste of chat between aider and web UI (default: False)
#copy-paste: false
## Apply the changes from the given file instead of running the chat (debug)
#apply: xxx
## Apply clipboard contents as edits using the main model's editor format
#apply-clipboard-edits: false
## Do all startup activities then exit before accepting user input (debug)
#exit: false
## Print the repo map and exit (debug)
#show-repo-map: false
## Print the system prompts and exit (debug)
#show-prompts: false
#################
# Voice settings:
## Audio format for voice recording (default: wav). webm and mp3 require ffmpeg
#voice-format: wav
## Specify the language for voice using ISO 639-1 code (default: auto)
#voice-language: en
## Specify the input device name for voice recording
#voice-input-device: xxx
#################
# Other settings:
## specify a file to edit (can be used multiple times)
#file: xxx
## Specify multiple values like this:
#file:
# - xxx
# - yyy
# - zzz
## specify a read-only file (can be used multiple times)
read: CONVENTIONS.md
## Specify multiple values like this:
# read:
# - CONVENTIONS.md
# - ...
# - ...
## Use VI editing mode in the terminal (default: False)
#vim: false
## Specify the language to use in the chat (default: None, uses system settings)
#chat-language: xxx
## Always say yes to every confirmation
#yes-always: false
## Enable verbose output
#verbose: false
## Load and execute /commands from a file on launch
#load: xxx
## Specify the encoding for input and output (default: utf-8)
#encoding: utf-8
## Line endings to use when writing files (default: platform)
#line-endings: platform
## Specify the config file (default: search for .aider.conf.yml in git root, cwd or home directory)
#config: xxx
## Specify the .env file to load (default: .env in git root)
#env-file: .env
## Enable/disable suggesting shell commands (default: True)
#suggest-shell-commands: true
## Enable/disable fancy input with history and completion (default: True)
#fancy-input: true
## Enable/disable multi-line input mode with Meta-Enter to submit (default: False)
#multiline: false
## Enable/disable terminal bell notifications when LLM responses are ready (default: False)
#notifications: false
## Specify a command to run for notifications instead of the terminal bell. If not specified, a default command for your OS may be used.
#notifications-command: xxx
## Enable/disable detection and offering to add URLs to chat (default: True)
#detect-urls: true
## Specify which editor to use for the /editor command
#editor: xxx
############################
# Deprecated model settings:
## Use claude-3-opus-20240229 model for the main chat (deprecated, use --model)
#opus: false
## Use anthropic/claude-3-7-sonnet-20250219 model for the main chat (deprecated, use --model)
#sonnet: false
## Use claude-3-5-haiku-20241022 model for the main chat (deprecated, use --model)
#haiku: false
## Use gpt-4-0613 model for the main chat (deprecated, use --model)
#4: false
## Use gpt-4o model for the main chat (deprecated, use --model)
#4o: false
## Use gpt-4o-mini model for the main chat (deprecated, use --model)
#mini: false
## Use gpt-4-1106-preview model for the main chat (deprecated, use --model)
#4-turbo: false
## Use gpt-3.5-turbo model for the main chat (deprecated, use --model)
#35turbo: false
## Use deepseek/deepseek-chat model for the main chat (deprecated, use --model)
#deepseek: false
## Use o1-mini model for the main chat (deprecated, use --model)
#o1-mini: false
## Use o1-preview model for the main chat (deprecated, use --model)
#o1-preview: false

5
.gitignore vendored
View File

@@ -142,3 +142,8 @@ Desktop.ini
######################
/.environment*
/src/test/resources/migration-prod/*
.aider/
.aider.tags.cache.*
.aider.chat.history.md
.aider.input.history
.cache

111
CONVENTIONS.md Normal file
View File

@@ -0,0 +1,111 @@
# Code Generting Conventions
This document outlines the coding conventions for this project to be used by any AI agent.
Ask the user to add these files to the AI agent before generating anything.
## Initially
At the beginning of each code generation session, determine all files which are not yet added, but might need to be changed and new files which might need to be created.
Consider:
- related Java-classes (*.java), including test classes
- also Java-classes files in the same package as the mainly related class, e.g. patcher
- related liquibase changesets (*.sql)
- related openapi specs (*.yaml)
- related i18n files (*.properties)
Make sure production code and test code stay in sync,
a change in one usually means the other has also to be changed.
## Java Conventions (`*.java` files)
### General Rules for Java Files
These rules apply to all `.java` files in `src/**/*.java` but not those located in `**/generated/**`, `build/**`, or `.gradle/**` directories.
1. **Imports**: No wildcard imports. Unused imports must be removed.
2. **Indentation**: Use 4 spaces for indentation. Do not use tabs.
3. **End of File**: All files must end with a newline character.
4. **Formatting Control**: Spotless formatting can be temporarily disabled for specific code blocks using comments:
```java
// spotless:off
// ... code that should not be formatted ...
// spotless:on
```
* Follow existing code style and patterns within the project.
- Avoid reassigning variables and use `final var` where possible.
- Use `final` for method parameters.
* Use meaningful names for variables, methods, and classes.
* Write clear and concise comments where necessary to explain complex logic or intent.
### toString via Stringify
For assertions, keep in mind, that the Stringify implementation of the toString method skips null values. Thus, do not add null values in assertions if a Stringify-based toString implementation is tested!
## PostgreSQL Conventions (`*.sql` files)
Do only Liquibase changesets if they got created in the same branch.
If they already exist in the master branch, generate a new Liquibase changeset.
Add new Liquibase changesets to existing files where they belong,
e.g. add a changeset with an ALTER TABLE directly after the related CREATE TABLE changeset.
If creating a new Liquibase changeset, there is no need to check if the change already exists, Liquibase will check that.
## i18n Conventions (`*.properties` files)
Use the English translation as the key in the `messages_*.properties` file,
'=' and ' ' need to be quoted.
## YAML Conventions (*.yaml files)
Always use exactly 4 spaces for indentation.
## General Conventions
### general strategy
At the beginning of each task, always determine all files which might need to be changed and new files which might need to be created.
### adding/deleting/amending fields/properties
If a field in a database table is added, deleted or amended, the following steps must be taken:
- The property must be added to the Java class on which the entity/entities are based; it must also be included in the toString method. Also amend the related unit test.
- If the related entity has a patcher class, also add the new property to the patcher (usually ending with EntityPatcher) and its unit test (usually ending with EntityPatcherUnitTest).
- The property must be included in (potentially 3) JSON resources (POST, GET, PATCH) in the OpenAPI specification.
- The property must be added to the SQL table, so either enforce it via Liquibase or create a new Liquibase changeset.
- The property must be included in the restricted view, which must be dropped and recreated due to the structural change; this view is generated by a stored procedure from the RBAC system.
- The property must be added to the RBAC update trigger; for this, the RBAC DSL, the static method rbac() in the entity class(es), must be adjusted. The generator should automatically force Liquibase to reapply the changeset.
- The tests may need to be adjusted; the new field should also be tested in an integration test for POST, GET, and PATCH.
## While Generating CHanges
Check all added files, if they need to be changed for the new feature.
Most likely, all added files need some sort of change.
Make sure production code and test code stay in sync,
a change in one usually means the other has also to be changed.
## Executing Commands
### Generating from OpenAPI
If OpenAPI specs (*.yaml) got changed, `gw openApiGenerate` needs to be executed.
### Generating from RBAC DSL
If any RBAC spec of an entity has changed, the static rbac() method in an entity class, `gw rbacGenerate` has to be executed before any test can run.
### Test Execution
Use the alias `gw-test` to run the tests with a proper environment.
Do not suggest to run `./gradlew test`, it won't work without a correect environment.

128
README.md
View File

@@ -1,5 +1,7 @@
# hsadminNg Development
(The origin repository for this project can be found at [Hostsharing eG](https://git.hostsharing.net/hostsharing/hs.hsadmin.ng).)
This documents gives an overview of the development environment and tools.
For architecture consider the files in the `doc` and `adr` folder.
@@ -361,6 +363,9 @@ You can explore the prototype as follows:
### Directory and Package Structure
#### General Directory Structure
`.aider.conf.yml`
Configuration for the _aider AI_ coding agent.
`.aliases`
Shell-aliases for common tasks.
@@ -371,6 +376,9 @@ You can explore the prototype as follows:
`build.gradle.kts`
Gradle build-file (Kotlin-Script). Contains dependencies and build configurations.
`CONVENTIONS.md`
Coding conventions for use by an AI agent.
`doc/`
Contains project documentation.
@@ -932,6 +940,126 @@ BEGIN
END $$;
```
### How to Use _aider AI_ - Pair Programming in Your Terminal
[aider](https://aider.chat/) is an [open source](https://github.com/Aider-AI/aider) AI agent in the shape of a command-line tool that lets you code with large language models (LLMs) OpenAI GPT, Claude Sonnet or Google Gemini.
It allows you to easily analyze and edit files by chatting with the AI.
*BEWARE*: aider is going to send your source code to the LLM!
_hsadmin-NG_ is open source, so this is not a big problem.
For more information about security regarding aider, please have a look at the end of this chapter and check out [the aider privacy policy](https://aider.chat/docs/legal/privacy.html).
#### Installation
Assuming you have Python 3 and `pipx` installed (a tool to install and run Python applications in isolated environments), you can install `aider-chat` like this:
```shell
pipx install aider-chat
```
If you want to use specific features like OpenAI's vision capabilities, you might need to add the following dependencies:
```shell
pipx inject aider-chat openai --include-apps
```
To add support for Google's Gemini AI, you can add the `google-generativeai` package:
```shell
pipx inject aider-chat google-generativeai --include-apps
```
#### Configuration
`aider` requires an API key for the AI model you want to use.
E.g. for _OpenAI GPT_, set the `OPENAI_API_KEY` environment variable:
```shell
export OPENAI_API_KEY="your-api-key-here"
```
And e.g. for _Google Gemini_, set the `GEMINI_API_KEY` environment variable:
```shell
export GEMINI_API_KEY="your-api-key-here"
```
You might want to add this to your shell's startup file (e.g., `.bashrc`, `.zshrc`).
#### Usage
1. Navigate to your project's root directory in the terminal.
2. Start `aider` by simply typing:
```shell
aider # see also .aider.conf.yml
```
3. Add the files you want the AI to work with:
```
/add path/to/your/file.java path/to/another/file.py
```
4. Start chatting! Describe the changes you want, ask questions, or request code generation. `aider` will propose changes and apply them directly to your files after your confirmation.
5. Use `/quit` to exit `aider`.
Refer to the [official aider documentation](https://aider.chat/docs/usage.html) for more commands and advanced features.
#### Example Session
Aider is not yet very good at figuring out which files to amend in a large code base.
I tried giving hints with `/ask`, but it was always missing too many files.
With some of my approaches, it even wanted to create new files, which is not necessary for this task.
I even tried with other language models, like gpt-o4 or r1 (deepseek-reasoning), no success.
Maybe somebody else can figure it out, or it gets better with time?
For now, I just determined the files myself.
As I knew that the new filed needs to be supported everywhere,
where the existing field `registrationOffice` occurs, I could simply use grep:
```shell
aider `grep -rl registrationOffice src/main/java/ src/test/java/ src/main/resources/api-definition src/main/resources/db/`
```
Then I requested my change to the _aider AI_ chat:
> I want to add a text field `notes` to the database table `hs_office.partner_details` and related files.
Files to amend have already been added to aider AI.
Please apply all required changes for Java production+test-code,
add the Liquibase changeset and amend the OpenAPI-Spec.
I ran the tests and found that patching the partner details did not work.
So, I told the _aider AI_ about it:
> Please doublecheck if you followed all conventions.
Any other amendments necessary to support the new field `notes` in the partner details?
Then I saw, that _aider AI_ did add some notes to the test data, but not to the assertions.
I decided that the changes in the test-data are not necessary and reverted thos files using git.
Now, all tests passed.
Try it yourself, but keep in mind that LLMs use a concept called _temperature_ which specifies a level of randomness.
This means, you might get different results.
#### Security
To reassure myself which files _aider AI_ accesses, I checked this with `strace`:
```
# run aider under strace:
strace -f -t -e trace=file -o build/aider.strace aider ...
# and in another terminal check the strace log:
tail -f build/aider.strace | grep -oP '"\K[^\n"]+(?=")'
```
At the time I've checked it, all accessed files made sense.
Of course, as with any locally installed application, there is no guarantee.
There is a _Docker_ image for _aider AI_, but it's pretty restriced
and to be able to use some features, you'd need to rebuild the image.
## Further Documentation

View File

@@ -71,9 +71,11 @@ repositories {
maven { url = uri("https://repo.spring.io/milestone") }
}
val JAVA_VERSION = 21
java {
toolchain {
languageVersion.set(JavaLanguageVersion.of(21))
languageVersion.set(JavaLanguageVersion.of(JAVA_VERSION))
vendor.set(JvmVendorSpec.ADOPTIUM)
implementation.set(JvmImplementation.VENDOR_SPECIFIC)
}
@@ -623,6 +625,20 @@ tasks.register("convertMarkdownToHtml") {
dependsOn(tasks.named("scenarioTest"))
}
// HOWTO re-generate the RBAC rules (PostgreSQL code) from the RBAC specs in the entities rbac()-method
// in a shell run `gw rbacGenerate`
tasks.register<JavaExec>("rbacGenerate") {
group = "application"
mainClass.set("net.hostsharing.hsadminng.rbac.generator.RbacSpec")
classpath = sourceSets["main"].runtimeClasspath
// This ensures the task uses the Java version from the defined toolchain.
javaLauncher.set(javaToolchains.launcherFor {
languageVersion.set(JavaLanguageVersion.of(JAVA_VERSION))
vendor.set(JvmVendorSpec.ADOPTIUM)
implementation.set(JvmImplementation.VENDOR_SPECIFIC)
})
}
// shortcut for compiling all files
tasks.register("compile") {