497 lines
16 KiB
YAML
497 lines
16 KiB
YAML
---
|
|
# Move the plays related to AGENTS.md to its own file since it is now so large.
|
|
|
|
- name: Workstation | Linux | Software | AI | Sandbox | Dir
|
|
ansible.builtin.file:
|
|
dest: "{{ user_user.home }}/AI-Sandbox"
|
|
state: directory
|
|
owner: "{{ user }}"
|
|
group: "{{ user }}"
|
|
mode: "0755"
|
|
|
|
- name: Workstation | Linux | Software | AI | Sandbox | Env
|
|
ansible.builtin.blockinfile:
|
|
path: "{{ user_user.home }}/AI-Sandbox/{{ item }}"
|
|
marker: "# {mark} | MANAGE BY ANSIBLE | Env Vars"
|
|
content: |
|
|
if [[ -d "$HOME/bin" ]]; then
|
|
export PATH="$HOME/bin:$PATH"
|
|
fi
|
|
|
|
export ANDROID_HOME="{{ user_user.home }}/SDKs/Android/Sdk"
|
|
export GRADLE_USER_HOME={{ user_user.home }}/.gradle
|
|
export PATH="$ANDROID_HOME/platform-tools:$PATH"
|
|
export PATH="$ANDROID_HOME/cmdline-tools/latest/bin:$PATH"
|
|
|
|
export FLUTTER_HOME="{{ user_user.home }}/SDKs/Flutter/flutter"
|
|
export PUB_CACHE={{ user_user.home }}/.pub-cache
|
|
export PATH="$FLUTTER_HOME/bin:$PATH"
|
|
|
|
export JAVA_HOME="{{ user_user.home }}/SDKs/Java"
|
|
export PATH="$JAVA_HOME/bin:$PATH"
|
|
create: true
|
|
backup: false
|
|
owner: "{{ user }}"
|
|
group: "{{ user }}"
|
|
mode: "0755"
|
|
loop:
|
|
- ".bashrc"
|
|
|
|
- name: Workstation | Linux | Software | AI | Sandbox | AGENTS.md
|
|
ansible.builtin.copy:
|
|
dest: "{{ user_user.home }}/AI-Sandbox/AGENTS.md"
|
|
content: |
|
|
# Environment
|
|
|
|
You are running in a Docker container called Open Terminal. We are
|
|
communicating via Open WebUI, also being run in a Docker
|
|
container. You are the user `user` and have been granted access to
|
|
the designer's Code and SDKs via mount at `{{ user_user.home }}`.
|
|
|
|
Host system is typically (but not always) a systemd-free distro
|
|
such as Artix or Devuan. User likes the `runit` service manager.
|
|
`elogind` is used rather than systemd's logind. Desktop is i3 and
|
|
display manager is lightdm. Servers are run on Debian and Docker
|
|
containers are typically debian:trixie-slim with a Dockerfile
|
|
called by compose.yml which adds the necessary packages, sometimes
|
|
building from source if the Debian executable is too old.
|
|
|
|
If the `$GOT_EM` environment variable is `true` then all the
|
|
necessary packages for compiling Android and Flutter were
|
|
installed. If it is `false` then they were not installed, and
|
|
compiling will fail. Please check this before trying and alert me
|
|
if they need added. If we don't have Internet, then ask me to
|
|
compile or run whatever command is needed on the host system.
|
|
|
|
# Rules
|
|
|
|
Never use any `git` subcommands that change the repo, including
|
|
but not limited to `add`, `commit`, `pull`, `push`, `branch`,
|
|
`switch`, etc. The user is who controls the respository changes.
|
|
You may use informational git subcommands such as `git status`,
|
|
and may occasionally be asked to run `git clone` type commands.
|
|
|
|
If any programs need installed in order to work on a project, we
|
|
need to document that in an `install.sh` script, as well as add it
|
|
to `~/PACKAGES.txt` so that we can ensure they stay installed.
|
|
`install.sh` scripts should be for both `apt` systems (Debian,
|
|
Ubuntu) and pacman system (Arch, Artix). using distribution
|
|
package managers is preferable over `pip` and `npm` when
|
|
possible, unless the project is actually Python or Node.js.
|
|
|
|
The user manages the `{{ user_user.home }}/SDKs` directory. Do not
|
|
modify it. Instead, ask if anything needs updated or added.
|
|
|
|
Never manually edit, modify, delete, alter, replace, etc any
|
|
files under system folders such as `/usr`. Anything under `/` is
|
|
managed by the system. If you need assistance changing anything
|
|
such as `/usr/lib/jvm`, please ask the user and halt all further
|
|
operations until you have received feedback.
|
|
|
|
# Effort
|
|
|
|
It is never okay to brute force a solution if something is not
|
|
working well. it is better to ask the user for assistance or alert
|
|
them that you've encountered blockers and then cease the process
|
|
until you've received feedback. This especially relates to when
|
|
system errors occur which are not related to the source code, such
|
|
as a compiler failing to be found or an SDK version mismatch. If
|
|
the error is with the source code though, troubleshooting and code
|
|
changes should continue until the program is compiling properly.
|
|
|
|
For CLI projects such as script languages, the final result should
|
|
always be tested both to run successfully and have the proper
|
|
output. All test cases should be analyzed and walked through,
|
|
which will help ensure all the requirements have been met.
|
|
|
|
For GUI programs (such as Android, Flutter, Kotlin Multiplatform,
|
|
Kivy, etc), the project should be tested to both compile & build
|
|
successfully and also generate the proper installation file (APK,
|
|
Linux Bundle). Once that is confirmed, the user/desginer will test
|
|
that the application meets the proper requirements.
|
|
|
|
# Preferences
|
|
|
|
You have free reign over your home directory. Feel free to
|
|
create memory files or anything else which would benefit you.
|
|
|
|
Everything we create should have both Desktop Linux and Android
|
|
in mind. Windows, MacOS, and iOS will never be compiled for, but
|
|
if we can do things in a way which makes it easy for others to
|
|
fork the project and add the support themselves, then that's best.
|
|
|
|
# Versions
|
|
|
|
These are the versions of plugins and languages we need to use.
|
|
If you know of an important upgrade from them, please let me know.
|
|
|
|
If you find that an application is already a newer version than
|
|
those listed here, that is acceptable, never attempt to downgrade
|
|
without explicitly asking the user first and having a good reason.
|
|
|
|
## Android / Flutter
|
|
|
|
- Gradle 9.8.2
|
|
- AGP 9.5.0
|
|
- Kotlin 2.4.21
|
|
- Java JDK 17
|
|
- Flutter Plugin Loader 1.0.0
|
|
- compileSdk 37
|
|
- targetSDK 37
|
|
|
|
Regardless of whether AGP bundles Kotlin, we need to specify it to
|
|
avoid things like "Your project's Kotlin version (2.2.10) is lower
|
|
than Flutter's minimum supported version of 2.2.20. Please upgrade
|
|
your Kotlin version." This is exactly why we use these versions,
|
|
plus it helps document what's actually being used over guessing.
|
|
|
|
Only the arm-v8a architecture needs included in the release
|
|
builds. x86 and others should continue to exist in the debug run.
|
|
This will help save space on local servers like Gitea and F-Droid.
|
|
If code for this does not exist, please add splitting or filtering
|
|
so that when the designer generates a signed APK it's only v8a.
|
|
|
|
Android : paths are from the project root.
|
|
Flutter : paths are under the folder `android`.
|
|
|
|
### All Android Project Types
|
|
|
|
#### ./gradle/wrapper/grade-wrapper.properties
|
|
|
|
```
|
|
distributionUrl=https\://services.gradle.org/distributions/gradle-9.8.2-bin.zip
|
|
```
|
|
|
|
#### ./settings.gradle.kts
|
|
|
|
```
|
|
id("com.android.application") version "9.5.0" apply false
|
|
id("org.jetbrains.kotlin.android") version "2.4.21" apply false
|
|
```
|
|
|
|
#### ./app/build.gradle.kts
|
|
|
|
```
|
|
compileOptions {
|
|
sourceCompatibility = JavaVersion.VERSION_17
|
|
targetCompatibility = JavaVersion.VERSION_17
|
|
}
|
|
kotlin {
|
|
compilerOptions {
|
|
jvmTarget.set(JvmTarget.JVM_17)
|
|
}
|
|
}
|
|
```
|
|
|
|
Also enable minify and shrink while in there.
|
|
|
|
```
|
|
buildTypes {
|
|
getByName("release") {
|
|
...
|
|
isMinifyEnabled = true
|
|
isShrinkResources = true
|
|
proguardFiles(
|
|
getDefaultProguardFile("proguard-android-optimize.txt"),
|
|
"proguard-rules.pro"
|
|
)
|
|
}
|
|
}
|
|
```
|
|
|
|
### Flutter Projects
|
|
|
|
#### ./settings.gradle.kts
|
|
|
|
```
|
|
id("dev.flutter.flutter-plugin-loader") version "1.0.0"
|
|
```
|
|
|
|
### Native Kotlin Apps
|
|
|
|
These only apply to Android apps which are not Flutter, Kivy, etc.
|
|
|
|
#### Plugin Versions
|
|
|
|
##### ./gradle/libs.versions.toml
|
|
|
|
```
|
|
[versions]
|
|
agp = "9.5.0"
|
|
kotlin = "2.4.21"
|
|
coreKtx = "1.19.1"
|
|
junit = "4.13.2"
|
|
junitVersion = "1.3.0"
|
|
espressoCore = "3.7.0"
|
|
lifecycleRuntimeKtx = "2.11.0"
|
|
activityCompose = "1.13.0"
|
|
composeBom = "2026.09.00"
|
|
```
|
|
|
|
#### Kotlin Compose Fix
|
|
|
|
Also ensure Kotlin is coming from Compose and not Jetbrains.
|
|
|
|
##### ./gradle/libs.versions.toml
|
|
|
|
```
|
|
[plugins]
|
|
androidApplication = { id = "com.android.application", version.ref = "agp" }
|
|
#jetbrainsKotlinAndroid = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" }
|
|
kotlinCompose = { id = "org.jetbrains.kotlin.plugin.compose", version.ref = "kotlin" }
|
|
```
|
|
|
|
##### ./build.gradle.kts
|
|
|
|
```
|
|
plugins {
|
|
alias(libs.plugins.androidApplication) apply false
|
|
//alias(libs.plugins.jetbrainsKotlinAndroid) apply false
|
|
alias(libs.plugins.kotlinCompose) apply false
|
|
}
|
|
```
|
|
|
|
##### ./app/build.gradle.kts
|
|
|
|
```
|
|
plugins {
|
|
alias(libs.plugins.androidApplication)
|
|
//alias(libs.plugins.jetbrainsKotlinAndroid)
|
|
alias(libs.plugins.kotlinCompose)
|
|
}
|
|
```
|
|
|
|
# Build Processes
|
|
|
|
How to compile certain projects. Tools to prefer. If a language
|
|
or framework is not mentioned, then use the typical commands.
|
|
|
|
## Kotlin Multiplatform (KMP)
|
|
|
|
Used to create small native Android apps with the ability to also
|
|
run against Desktop Linux. APK size is the greatest benefit for
|
|
using KMP over something like Flutter or KivyMD.
|
|
|
|
### Kotlin Toolchain
|
|
|
|
This is the preferred build type when setting up new projects.
|
|
|
|
Please use `kotlin` rather than any `amper` commands. `amper` has
|
|
been deprecated and is intentionally not present on the system.
|
|
Examples:
|
|
|
|
```
|
|
# 1. Compile + link ALL targets (JVM, iOS, Android, native, etc.)
|
|
./kotlin build
|
|
|
|
# 2. (Optional) Run tests across all targets
|
|
./kotlin test
|
|
|
|
# 3. (Optional) Run all quality checks (tests + registered linters)
|
|
./kotlin check
|
|
```
|
|
|
|
### Gradle KMP
|
|
|
|
This is a legacy method, new projects will not be set up with it.
|
|
Examples:
|
|
|
|
```
|
|
# Compile all targets
|
|
./gradlew assemble
|
|
|
|
# Or more explicitly (if you want to be sure nothing is skipped):
|
|
./gradlew jvmJar assembleDebug assembleIosSimulatorArm64 # etc. per target
|
|
|
|
# Run all tests
|
|
./gradlew allTests
|
|
```
|
|
|
|
# Coding Conventions
|
|
|
|
Preferences related to how code should be written.
|
|
|
|
## All languages
|
|
|
|
If a value is going to be used more than once, even a small path or file
|
|
name, it should exist in a variable.
|
|
|
|
Relative shebangs such as `#!/usr/bin/env bash` and `#!/usr/bin/env node`
|
|
are always preferred over static shebangs such as `#!/bin/bash`, since
|
|
scripts are run across a multitude of different systems.
|
|
|
|
### Layout
|
|
|
|
Programs should be laid out in 5 sections.
|
|
|
|
- Variables
|
|
- Instantiate global variables and defaults used for parameters which
|
|
do not get passed an explicit value by the user.
|
|
- Functions
|
|
- Functions to be used throughout the program, including the Usage.
|
|
- Parameters / Validation
|
|
- Parse the parameters, validate the input, and assign any defaults.
|
|
- Main
|
|
- The primary logic of the program, completes the task at hand.
|
|
- Finish / Cleanup
|
|
- Typically just `exit 0`, but sometimes a summary of what was done.
|
|
|
|
All sections may not always apply, such as with Hugo websites. With
|
|
projects like Android apps this would apply to each individual function,
|
|
method, and class. If a section does not need anything, it can be blank.
|
|
|
|
```
|
|
public static void doThing(String thingName) {
|
|
// Variables //
|
|
String thingPrefix = "/place/for/thing/"
|
|
|
|
// Functions //
|
|
|
|
// Parameters //
|
|
if (thingName.isEmpty) {
|
|
Exception e = new Exception("No name passed!");
|
|
throw e;
|
|
}
|
|
|
|
// Main //
|
|
runStuff(thingPrefix + thingName);
|
|
|
|
// Finish //
|
|
}
|
|
```
|
|
|
|
The comments do not need to be included, this example is just as valid,
|
|
what maytters most is that the 5 section are done in order rather than
|
|
instantiating variable mid-scope.
|
|
|
|
```
|
|
public static void doThing(String thingName) {
|
|
String thingPrefix = "/place/for/thing/"
|
|
|
|
if (thingName.isEmpty) {
|
|
Exception e = new Exception("No name passed!");
|
|
throw e;
|
|
}
|
|
|
|
runStuff(thingPrefix + thingName);
|
|
}
|
|
```
|
|
|
|
`if` statements and loops start new scope, so they also need the layout
|
|
applied to them. Loops may sometimes require a variable assignment before
|
|
it begins which is completely okay and does not break the layout rule.
|
|
This example has a Variables, Validation, Main, and Finish section without
|
|
the use of labels or comments since the code itself is simple and small.
|
|
|
|
```
|
|
count=0
|
|
array="cats dogs giraffes rhinos horses"
|
|
last_animal=""
|
|
for animal in $array; do
|
|
if (( count >= 3 )); then
|
|
echo "That's enough! We finished at the ${last_animal}."
|
|
break;
|
|
fi
|
|
|
|
echo "We're looking at ${animal}."
|
|
|
|
last_animal=$animal
|
|
(( count++ ))
|
|
done
|
|
```
|
|
|
|
Providing the user's input in error messages is really helpful and can aid
|
|
their troubleshooting if things are not going according to expectations.
|
|
|
|
Example using Bash:
|
|
|
|
```
|
|
#!/usr/bin/env bash
|
|
|
|
### Variables ###
|
|
|
|
declare A B
|
|
typeset -i a b
|
|
|
|
### Functions ###
|
|
|
|
function usage() {
|
|
status="$1"
|
|
cat << EOF
|
|
Usage: add.sh -a NUM -b NUM [-h]
|
|
|
|
Adds two numbers and prints out the full equation.
|
|
|
|
Example:
|
|
|
|
$ add.sh -a 5 -b 25
|
|
5 + 25 = 30
|
|
EOF
|
|
exit $status
|
|
}
|
|
function add() {
|
|
num1="$1"
|
|
num2="$2"
|
|
sum=""
|
|
|
|
if [[ -z $num1 || -z $num2 ]]; then
|
|
echo "ERROR: Two numnbers must be passed."
|
|
fi
|
|
|
|
sum=$(( num1 + num2 ))
|
|
echo "${num1} + ${num2} = ${sum}"
|
|
}
|
|
|
|
### Parameters ###
|
|
|
|
while getopts ':a:b:h' opt; do
|
|
case $opt in
|
|
a) A="$OPTARG" ;;
|
|
b) B="$OPTARG" ;;
|
|
h) usage 0 ;;
|
|
*) echo "ERROR: Option $OPTARG not recognized." >&2 && usage 1 ;;
|
|
esac
|
|
done
|
|
|
|
if [[ -z "$A" || -z "$B" ]]; then
|
|
echo "ERROR: Both numbers need to be passed. A=${A} B=${B}" >&2
|
|
usage 2
|
|
fi
|
|
a="$A" b="$B"
|
|
if [[ "$a" != "$A" || "$b" != "$B" ]]; then
|
|
echo "ERROR: Values contain non-numeric data, please try again." >&2
|
|
echo "A=${A} B=${B}" >&2
|
|
usage 3
|
|
fi
|
|
|
|
### Main ###
|
|
|
|
add "$a" "$b"
|
|
|
|
### Finish ###
|
|
|
|
unset A B usage add
|
|
exit 0
|
|
```
|
|
|
|
## Bash
|
|
|
|
`[[ ]]` are preferred over `[ ]`, `test`, etc. `(( ))` are always fine.
|
|
|
|
When defining a function please use both the keyword `function` as well as
|
|
the `()`, such as `function myfunc() {}`.
|
|
|
|
When instantiating global variables, please use `typeset` or `declare`
|
|
rather than just `VAR1=""; VAR2=""`, such as:
|
|
|
|
```
|
|
declare VAR1="" VAR2="" BOOL="true" BOOL2="false"
|
|
typeset -i INT1=0 INT2=99
|
|
```
|
|
|
|
When doing colored output, `tput` is always preferred over literal values.
|
|
backup: false
|
|
owner: "{{ user }}"
|
|
group: "{{ user }}"
|
|
mode: "0755"
|