diff --git a/.gitea/workflows/release.yml b/.gitea/workflows/release.yml new file mode 100644 index 0000000..1c6ee5d --- /dev/null +++ b/.gitea/workflows/release.yml @@ -0,0 +1,105 @@ +name: release-tools + +# På varje push till master/main: bygg de tools som fått ändringar +# (linux x64 + arm64) och lägg binärerna på en rullande +# "-latest"-release på släppsidan i Gitea. +on: + push: + branches: [master, main] + workflow_dispatch: {} # manuell körning bygger ALLA tools + +jobs: + build-release: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + fetch-depth: 0 # hela historiken behövs för diffen mot 'before' + + - name: Detektera ändrade tools + id: changed + run: | + TOOLS="pixel-sprite-maker mesh-tool" + BEFORE="${{ github.event.before }}" + CHANGED="" + if [ "${{ github.event_name }}" = "workflow_dispatch" ] \ + || [ -z "$BEFORE" ] \ + || echo "$BEFORE" | grep -Eq '^0+$' \ + || ! git cat-file -e "$BEFORE" 2>/dev/null; then + echo "första push / manuell körning -> bygger alla tools" + CHANGED="$TOOLS" + else + for t in $TOOLS; do + if ! git diff --quiet "$BEFORE" "${{ github.sha }}" -- "$t/"; then + CHANGED="$CHANGED $t" + fi + done + fi + CHANGED="$(echo $CHANGED)" # trimma whitespace + echo "tools=$CHANGED" >> "$GITHUB_OUTPUT" + echo "bygger: ${CHANGED:-inget}" + + - name: Installera Go + if: steps.changed.outputs.tools != '' + uses: actions/setup-go@v5 + with: + go-version: "1.24" + cache: false + + - name: Testa + bygg (x64 + arm64) + if: steps.changed.outputs.tools != '' + run: | + set -e + VERSION="latest-$(git rev-parse --short HEAD)" + for t in ${{ steps.changed.outputs.tools }}; do + case "$t" in + pixel-sprite-maker) BIN=spritec ;; + mesh-tool) BIN=mesht ;; + *) echo "okänt tool $t"; exit 1 ;; + esac + echo "=== $t ($BIN) ===" + cd "$t" + go test ./... + mkdir -p build + GOOS=linux GOARCH=amd64 go build -trimpath \ + -ldflags "-s -w -X main.version=$VERSION" -o "build/$BIN-linux-x64" . + GOOS=linux GOARCH=arm64 go build -trimpath \ + -ldflags "-s -w -X main.version=$VERSION" -o "build/$BIN-linux-arm64" . + (cd build && sha256sum "$BIN"-linux-* > checksums.txt && ls -la) + cd .. + done + + - name: Skapa/uppdatera releaser + ladda upp binärer + if: steps.changed.outputs.tools != '' + env: + API: http://gitea-d:3000/api/v1 + REPO: ${{ github.repository }} + TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + set -e + for t in ${{ steps.changed.outputs.tools }}; do + case "$t" in + pixel-sprite-maker) BIN=spritec ;; + mesh-tool) BIN=mesht ;; + esac + TAG="$t-latest" + BODY="$t (binär: $BIN) - rullande bygge från senaste master. Commit: ${{ github.sha }}. Arkitekturer: linux x64 + arm64 (Pi5)." + rid=$(curl -s -X POST "$API/repos/$REPO/releases" \ + -H "Authorization: token $TOKEN" -H 'Content-Type: application/json' \ + -d "{\"tag_name\":\"$TAG\",\"name\":\"$TAG\",\"body\":\"$BODY\"}" | jq -r '.id // empty') + [ -z "$rid" ] && rid=$(curl -s "$API/repos/$REPO/releases/tags/$TAG" \ + -H "Authorization: token $TOKEN" | jq -r '.id') + echo "$t -> release id $rid" + for f in "$BIN-linux-x64" "$BIN-linux-arm64" checksums.txt; do + aid=$(curl -s "$API/repos/$REPO/releases/$rid/assets" \ + -H "Authorization: token $TOKEN" | jq -r ".[] | select(.name==\"$f\") | .id") + if [ -n "$aid" ] && [ "$aid" != "null" ]; then + curl -s -X DELETE "$API/repos/$REPO/releases/$rid/assets/$aid" \ + -H "Authorization: token $TOKEN" -o /dev/null + fi + curl -s -X POST "$API/repos/$REPO/releases/$rid/assets?name=$f" \ + -H "Authorization: token $TOKEN" \ + -F "attachment=@$t/build/$f" -o /dev/null -w " $f -> HTTP %{http_code}\n" + done + done diff --git a/.vscode/tasks.json b/.vscode/tasks.json new file mode 100644 index 0000000..3f12199 --- /dev/null +++ b/.vscode/tasks.json @@ -0,0 +1,44 @@ +{ + "version": "2.0.0", + "tasks": [ + { + "label": "build pixel-sprite-maker", + "type": "shell", + "command": "go build -trimpath -ldflags '-s -w' -o build/spritec .", + "options": { "cwd": "${workspaceFolder}/pixel-sprite-maker" }, + "group": "build", + "problemMatcher": ["$go"] + }, + { + "label": "build mesh-tool", + "type": "shell", + "command": "go build -trimpath -ldflags '-s -w' -o build/mesht .", + "options": { "cwd": "${workspaceFolder}/mesh-tool" }, + "group": "build", + "problemMatcher": ["$go"] + }, + { + "label": "test pixel-sprite-maker", + "type": "shell", + "command": "go test ./...", + "options": { "cwd": "${workspaceFolder}/pixel-sprite-maker" }, + "group": "test", + "problemMatcher": ["$go"] + }, + { + "label": "test mesh-tool", + "type": "shell", + "command": "go test ./...", + "options": { "cwd": "${workspaceFolder}/mesh-tool" }, + "group": "test", + "problemMatcher": ["$go"] + }, + { + "label": "build", + "dependsOn": ["build pixel-sprite-maker", "build mesh-tool"], + "dependsOrder": "parallel", + "group": { "kind": "build", "isDefault": true }, + "problemMatcher": [] + } + ] +} diff --git a/README.md b/README.md index e9b9467..b86b874 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,46 @@ # agent-tools -smal tools for ai agents \ No newline at end of file +Small, self-contained CLI tools built for **AI agents** to use during +development work. Every tool is a single static Go binary with a +text-first interface: input formats an agent can read and write +directly, and output (names, errors, previews) explicit enough that the +agent understands the result without opening an image viewer. + +| Tool | Binary | What it does | +|------|--------|--------------| +| [`pixel-sprite-maker/`](pixel-sprite-maker/) | `spritec` | Turns `.sprite` text files (palette + character grid) into PNG/JPG/SVG pixel art, up to 256x256 px per sprite. Combines several sprites into sprite sheets / animation strips whose **file names document the layout** (`walk_8x8_4x1.png` = 8x8 px frames, 4 columns, 1 row). | +| [`mesh-tool/`](mesh-tool/) | `mesht` | Creates, inspects and edits 3D models (OBJ + STL). ASCII multi-view rendering + measurements (bbox, volume, watertightness) let an agent *see* a model, edit it (scale/rotate/mirror/merge/primitives) and verify the result. | + +Each tool has its own folder, its own README with the full format/CLI +reference, its own tests and its own dev branch (`dev/`). + +## Building + +```bash +# Arch/Garuda prerequisite: +sudo pacman -S go + +cd / && go build -o build/ . # per tool +go test ./... # per tool +``` + +VS Code: **Terminal → Run Build Task** — `build` builds every tool into +its own `/build/` folder; per-tool `build ` and +`test ` tasks also exist. + +## CI / releases + +`.gitea/workflows/release.yml` runs on every push to `master`/`main` on +the self-hosted runner: tools whose folders changed are tested, built +for **linux x64 + arm64** (the Pi5), and published to a rolling +release per tool on the repo's release page: + +- tag `pixel-sprite-maker-latest` → assets `spritec-linux-x64`, `spritec-linux-arm64`, `checksums.txt` +- tag `mesh-tool-latest` → assets `mesht-linux-x64`, `mesht-linux-arm64`, `checksums.txt` + +A manual `workflow_dispatch` run builds all tools regardless of diffs. + +## Branch layout + +- `main` — stable, releases are built from here +- `dev/pixel-sprite-maker`, `dev/mesh-tool` — per-tool development branches diff --git a/doc/plan.md b/doc/plan.md new file mode 100644 index 0000000..1657977 --- /dev/null +++ b/doc/plan.md @@ -0,0 +1,43 @@ +# agent-tools — plan + +## Goal + +A collection of small, agent-friendly CLI tools. The common thread: +**text in, verifiable artifacts out**. An agent should be able to author +the input format directly, predict what the output will look like, and +verify results without a GUI. + +## Stack + +- Go (single static binaries, zero deps, trivial cross-compile to the + Pi5's arm64 runner), one Go module per tool. +- Targets: linux x64 + linux arm64. + +## Deploy target + +Pattern A (distributable binaries): rolling `-latest` release per +tool on Gitea, built by `.gitea/workflows/release.yml` on push to +master/main. Only tools whose folders changed get rebuilt. + +## Milestones + +1. ✅ `pixel-sprite-maker` (`spritec`): .sprite text format → PNG/JPG/SVG, + sprite sheets with self-documenting file names, terminal preview. +2. ✅ `mesh-tool` (`mesht`): OBJ/STL create/inspect/edit with ASCII + multi-view rendering, measurements and watertightness checks. +3. ✅ Per-tool VS Code build tasks → `/build/`. +4. ✅ CI: changed-tool detection + per-tool rolling releases. + +## Roadmap / expansion ideas (not agreed yet) + +- spritec: palette import from image files, GIF export for animations, + tile-map composer (map file referencing sprite tiles). +- mesht: OBJ vertex-color support, simple boolean ops (union via + voxelization), PNG snapshot rendering, glTF export. +- New tools: bitmap-font maker, sound-effect generator (sfxr-style text + presets), tiled-map (.tmx) writer. + +## Open questions + +- Versioned releases (`vX.Y.Z` tags per tool) on top of the rolling + `latest` — add when something depends on a pinned version.