Metadata-Version: 2.4
Name: magicbox-dk
Version: 0.0.3
Summary: Magicbox for help DigitalKin developpers.
Author-email: Alexandre TRESALLET <a.tresall@digitalkin.ai>
License-Expression: MIT
License-File: LICENSE
Keywords: digitalkin,kin,magicbox,sdk
Requires-Python: >=3.10
Requires-Dist: jinja2>=3.1
Requires-Dist: pydantic>=2.13.4
Requires-Dist: pyyaml>=6.0.3
Requires-Dist: questionary>=2.0.0
Requires-Dist: rich>=13.0.0
Requires-Dist: typer>=0.25.1
Description-Content-Type: text/markdown

# Magicbox

> **`dk`** — orchestrateur d'environnement de développement pour les services et archétypes DigitalKin.

Magicbox pilote **Docker Compose** à partir d'un **profil YAML par scénario de dev**. Une seule CLI (`dk`), un profil
décrit *ce que* vous voulez faire tourner (front, services, infra, archétypes, kins) et *comment* (version distante,
clone git, ou dépôt local), et Magicbox génère les composes, résout l'environnement, alloue les ports et démarre la
stack — le tout stocké hors du repo, dans le dossier de config standard de votre OS.

[![PyPI](https://img.shields.io/pypi/v/magicbox-dk.svg)](https://pypi.org/project/magicbox-dk/)
[![Python](https://img.shields.io/pypi/pyversions/magicbox-dk.svg)](https://pypi.org/project/magicbox-dk/)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](#license)

---

## Sommaire

- [Installation](#installation)
- [Démarrage rapide](#démarrage-rapide)
- [Concepts](#concepts)
- [Commandes](#commandes)
- [Organisation des fichiers (`config_root`)](#organisation-des-fichiers-config_root)
- [Le profil](#le-profil)
- [Settings, globals & credentials](#settings-globals--credentials)
- [Multi-profils](#multi-profils)
- [Auth git](#auth-git)
- [Versioning & release](#versioning--release)
- [Dépannage](#dépannage)
- [License](#license)

---

## Installation

Magicbox est un **outil en ligne de commande** : installez-le dans un environnement isolé avec **`uv`** ou **`pipx`**
pour exposer la commande `dk` globalement (sans polluer votre Python système).

```bash
uv tool install magicbox-dk      # recommandé (uv)
# ou
pipx install magicbox-dk         # équivalent pipx
```

La CLI expose deux entrypoints équivalents : **`dk`** (court) et **`digitalkin`**. Python **≥ 3.10** requis, et un démon
**Docker** avec le plugin **Compose v2** en état de marche (`dk doctor` vérifie tout ça).

Mettre à jour ou désinstaller :

```bash
uv tool upgrade magicbox-dk      # ou: pipx upgrade magicbox-dk
uv tool uninstall magicbox-dk    # ou: pipx uninstall magicbox-dk
```

> Tester sans installer globalement : `uvx --from magicbox-dk dk --help`.
> Installer une pré-release (`.devN`) : `uv tool install "magicbox-dk==X.Y.Z.devN"` (ou
`pipx install --pip-args=--pre magicbox-dk`).

### Depuis les sources (dev)

Le projet est géré avec [`uv`](https://docs.astral.sh/uv/) :

```bash
uv sync                 # résout les dépendances depuis uv.lock
uv pip install -e .     # expose l'entrypoint `dk` en mode éditable
```

---

## Démarrage rapide

```bash
dk init                  # bootstrap : structure utilisateur + profil « Default »
dk edit                  # édite le profil (menus interactifs)
dk prepare               # clone les remotes, génère les composes, écrit network.yml
dk start                 # régénère les <entry>.env (live) + docker compose up -d
dk status                # état des conteneurs, section par section
dk stop                  # docker compose down + supprime les .env
```

Sans sous-commande, `dk` affiche le **tableau de bord** (profil actif, liste des profils, commandes clés).

---

## Commandes

Tous les alias sont interchangeables (`dk rm` == `dk delete`). Le nom de profil est toujours **optionnel** : sans lui,
la commande cible le **profil actif** (`dk status dev` cible ponctuellement `dev`).

### Cycle de vie

| Commande                       | Rôle                                                                                                   |
|--------------------------------|--------------------------------------------------------------------------------------------------------|
| `dk init`                      | Bootstrap : crée `<config_root>/profiles`, `settings.yaml`, un profil par défaut. **Idempotent**.      |
| `dk create [name]`             | Crée un nouveau profil à partir du template `profile.base.yaml`.                                       |
| `dk delete, rm <name>`         | Supprime un profil (et ses clones) définitivement.                                                     |
| `dk prepare [profile]`         | Valide le YAML, clone les remotes, alloue les ports, génère les composes, écrit `network.yml`.         |
| `dk start, run, up [profile]`  | Régénère les `<entry>.env` (live) + `docker compose up -d` + attend les healthchecks.                  |
| `dk stop, down [profile]`      | `docker compose down --remove-orphans` + supprime les `.env`. `--all` arrête toutes les stacks.        |
| `dk restart, reload [profile]` | `stop` puis `start`.                                                                                   |
| `dk clean [profile]`           | Tear-down Docker + purge images / clones / composes. `--all` pour tous, `--env` inclut le dossier env. |
| `dk switch <name>`             | Change le profil actif.                                                                                |
| `dk update [name...]`          | `git pull --ff-only` sur les clones du profil actif.                                                   |

### Édition

| Commande                | Rôle                                                                                        |
|-------------------------|---------------------------------------------------------------------------------------------|
| `dk edit [profile]`     | Éditeur interactif du profil (menus navigables) : front, services, infra, archétypes, kins. |
| `dk settings`           | Édite les settings globaux (env globales, start, ports, timeouts, docker, infra).           |
| `dk env`                | Raccourci vers l'éditeur des variables d'env globales (`settings.env`).                     |
| `dk credentials, creds` | Édite les credentials infra partagés (SurrealDB logins / S3 accounts).                      |

### Inspection & utilitaires

| Commande                   | Rôle                                                                             |
|----------------------------|----------------------------------------------------------------------------------|
| `dk dashboard`             | Tableau de bord : profil actif, liste des profils, commandes clés (défaut).      |
| `dk list, ls`              | Liste les profils avec marqueurs d'état. Supporte `--json`.                      |
| `dk show, info [profile]`  | Vue compacte de la config d'un profil. Supporte `--json`.                        |
| `dk status, stats, ps`     | État des conteneurs, section par section.                                        |
| `dk logs [service]`        | `docker compose logs`.                                                           |
| `dk shell, exec <service>` | Ouvre un shell dans un conteneur du profil actif (`/bin/bash`, sinon `/bin/sh`). |
| `dk validate [profile]`    | Valide le YAML (Pydantic), sans effet de bord.                                   |
| `dk doctor`                | Vérifie Docker, Compose, git et la structure utilisateur.                        |
| `dk version`               | Affiche la version de Magicbox.                                                  |

> Toutes les commandes (sauf `init` et `doctor`) s'arrêtent si la structure utilisateur n'existe pas — un message invite
> à lancer `dk init`.
>
> Ajoutez **`-d`** (ou `--debug`) à n'importe quelle commande pour voir les étapes internes et les commandes docker/git
> exécutées (secrets masqués).

---

## Organisation des fichiers (`config_root`)

Tout l'état côté utilisateur vit dans le dossier de config standard de l'OS :

| OS      | `config_root`                               |
|---------|---------------------------------------------|
| macOS   | `~/Library/Application Support/digitalkin/` |
| Linux   | `~/.config/digitalkin/`                     |
| Windows | `%APPDATA%\digitalkin\`                     |

```
<config_root>/
├── profiles/<profile_id>/     ← un dossier par profil (profile_id = id court 6 hex)
│   ├── profile.yaml           ← la spec du profil (source de vérité)
│   ├── composes/              ← overrides docker-compose générés par `dk prepare`
│   ├── env/                   ← env par entrée : <entry>.yml (source) + <entry>.env (aplati)
│   ├── repos/                 ← clones git du profil (un dossier par entrée git)
│   └── network.yml            ← host/port/url résolus de chaque service (généré par `dk prepare`)
├── settings.yaml              ← settings core (profil actif, ports, timeouts, docker, start)
├── globals.yaml               ← variables d'env globales, partagées entre profils
└── credentials.yaml           ← credentials infra partagés (surrealdb_logins + s3_accounts)
```

Points clés :

- **Les clones vivent *dans* chaque profil** (`<profile>/repos/`) — deux profils qui pointent le même dépôt ne se
  partagent pas un clone potentiellement checkout sur des refs incompatibles. Supprimer un profil emporte ses clones.
- **L'env par entrée est scindé en deux fichiers** :
  - `<profile>/env/<entry>.yml` — **source de vérité**, éditée via `dk edit → Edit env`. Catégorisée (secret /
    connection / other) + un bloc `network:` en lecture seule reflétant les adresses des autres services.
  - `<profile>/env/<entry>.env` — **artefact transitoire** régénéré par `dk start` (merge source + template +
    `network.yml` + globals + credentials + résolution Jinja), consommé comme `env_file:` par Compose, **supprimé par
    `dk stop`**.
- **Conséquence pratique** : tout changement dans `dk settings` / `dk edit` est pris en compte au prochain `dk start`,
  sans re-lancer `dk prepare`.
- **`dk clean`** purge `composes/`, `repos/` et les `.env` aplatis ; il **préserve** les sources `.yml` (les secrets
  saisis survivent à un `clean` → `prepare`). Seuls `dk clean --env` ou `dk delete` suppriment tout le dossier `env/`.

> Aucun secret irremplaçable ne vit ici : c'est de la config régénérable. Un `rm -rf <config_root>` suivi de `dk init`
> repart de zéro proprement.

---

## Le profil

Un profil déclare un bloc méta (`profile:` — nom, description) puis les clés racine :
`frontend`, `node-service-provider`, `back`, `infra`, `archetypes`, `tools`, `kins`.

### Mode unifié — `remote` / `git` / `dev`

Chaque élément exécutable (frontend Horizon, services, archétypes, tools) porte un seul `mode` :

- **`remote`** — utilise une version en prod / managée ; seul `endpoint` est requis (référence à une variable de
  connexion globale).
- **`git`** — clone le dépôt et le build/run en local ; `ref` (branche). L'`url` est éditable pour les
  archétypes/tools ;
  pour les services et Horizon, le dépôt est prédéfini.
- **`dev`** — version locale ; `path` (chemin vers le dépôt local).

Les entrées d'infra (redis, surrealdb, s3) utilisent `local` / `remote` : `local` lance le conteneur préfabriqué,
`remote` résout son adresse depuis `settings.env.connection.<endpoint>`.

> Les services / infra / frontend sont **toujours actifs** dans un profil — pas de flag `enabled`, c'est le `mode` qui
> décide local vs externe. Seuls les **kins** gardent un `enabled` (activer/désactiver une session de chat sans la
> supprimer).

### Exemple

```yaml
profile:
  name: Default
  description: Profil full-local (sauf DB)

frontend:
  type: chainlit          # ou horizon (avec mode/ref)

node-service-provider:
  mode: remote
  endpoint: node-service-provider

back:
  mode: dev
  path: ~/dev/digitalkin/back

infra:
  redis:     { mode: local }
  surrealdb: { mode: remote, endpoint: surrealdb-prod }
  s3:        { mode: local }

archetypes:
  Template:
    mode: git
    url: git@github.com:DigitalKin-ai/template-archetype.git
    ref: dev
    endpoint: template
    module_id: modules:template
    sdk:
      source: pypi
      version: stable

tools: {}

kins:
  Template:
    enabled: true
    archetype: Template          # référence une clé de `archetypes`
    description: Kin de démarrage minimal tournant sur l'archetype Template.
    has_config_setup: false
```

La validation est **stricte** (`extra: forbid`) — toute clé inconnue fait échouer `dk prepare` / `dk validate`. La façon
recommandée d'éditer un profil reste `dk edit`.

---

## Settings, globals & credentials

Trois fichiers, chargés ensemble en un seul modèle Pydantic `Settings`, réécrits par `dk settings` :

- **`settings.yaml`** — settings core, éditables via `dk settings` :
  - **Env globals** — `secret` / `connection` / `other` partagés entre profils, consommables depuis n'importe quelle
    entrée via des références Jinja `{{ globals.NOM }}`.
  - **Start** — `attach` (est-ce que `dk start` suit les logs par défaut).
  - **Ports** — port hôte unique du front (`frontend_host`, défaut `8080`, partagé Chainlit/Horizon) + plage
    d'allocation
    des archétypes (`archetype_pool_start`/`_end`, défaut `50050-50070`).
  - **Timeouts** — poll/timeout des healthchecks, limite de restart, passes de résolution Jinja, timeout fetch git.
  - **Docker** — préfixes de nom conteneur/projet, montages de volumes.
- **`globals.yaml`** — le bloc d'env globales (`settings.env`), partagé entre profils. Éditable via `dk env`.
- **`credentials.yaml`** — credentials infra partagés (`surrealdb_logins` + `s3_accounts`), référencés par les services
  par leur nom de profil. Éditable via `dk credentials`.

Les défauts sont codés en dur : les fichiers YAML n'ont besoin que de surcharger ce qui diffère.

---

## Multi-profils

```bash
dk create dev            # crée un profil « dev » depuis le template
dk edit dev              # personnalise-le
dk prepare dev
dk switch dev            # en fait le profil actif
```

Surcharger le profil actif pour une seule commande : `dk status dev`, `dk start dev`, etc.

---

## Auth git

Magicbox délègue l'authentification au système : configurez votre credential helper (`osxkeychain`, `gh`, clé SSH dans
`~/.ssh/config`, …) **avant** de lancer `dk prepare`. Les URLs des profils ne contiennent jamais de secret.

---

## Versioning & release

Le versionnage suit **PEP 440** : `major.minor.patch` avec un pré-release `.devN` optionnel,
piloté par [`bump-my-version`](https://github.com/callowayproject/bump-my-version) (config dans
`.bumpversion.toml`). Chaque `bump` met à jour `pyproject.toml` **et** `uv.lock`, puis **commit +
tag** automatiquement (`commit = true`, `tag = true`).

> Le binaire Homebrew de `bump-my-version` peut être cassé (interpréteur Python obsolète) —
> préfixe les commandes par `uv run` pour utiliser celui du venv.

**Règle d'or** : un `.devN` est toujours un pré-release de la **prochaine** version pas encore
sortie (`0.0.2.dev1 < 0.0.2`). La base `major.minor.patch` ne fait que **monter** — on ne colle
jamais un `.dev` sur une version déjà publiée.

### Les cas

| Cas                                           | Commande                           | Exemple                     |
|-----------------------------------------------|------------------------------------|-----------------------------|
| **Ouvrir un cycle dev** (depuis une finale)   | `bump patch` \| `minor` \| `major` | `0.0.1` → `0.0.2.dev1`      |
| **Itérer en dev**                             | `bump dev`                         | `0.0.2.dev1` → `0.0.2.dev2` |
| **Passer d'une dev à la release** (finaliser) | `bump --new-version X.Y.Z`         | `0.0.2.dev2` → `0.0.2`      |

> `bump dev` depuis une **finale** échoue (`value 0 is lower than the first value 1`) : c'est voulu
> (`first_value = 1`). Depuis une finale, on ouvre le cycle avec `patch`/`minor`/`major`, jamais `dev`.
> Et « finaliser » (retirer le `.dev`) se fait avec `--new-version`, car un compteur `.dev` ne peut
> pas redescendre à 0 tout seul.

### Procédure complète (pour chaque version)

```bash
# 1. bump : édite pyproject.toml + uv.lock, commit + tag automatiques
uv run bump-my-version bump patch          # 0.0.1 → 0.0.2.dev1

# 2. pousse le commit ET son tag
git push --follow-tags origin main

# 3. crée la GitHub Release → déclenche la publication (.github/workflows/release.yml)
gh release create v0.0.2.dev1 --prerelease --generate-notes   # --prerelease pour un .dev
```

Exemple d'un cycle complet `0.0.1 → 0.0.2` :

```bash
uv run bump-my-version bump patch            # 0.0.1 → 0.0.2.dev1
git push --follow-tags origin main
gh release create v0.0.2.dev1 --prerelease --generate-notes

uv run bump-my-version bump dev              # 0.0.2.dev1 → 0.0.2.dev2
git push --follow-tags origin main
gh release create v0.0.2.dev2 --prerelease --generate-notes

uv run bump-my-version bump --new-version 0.0.2   # finalise : 0.0.2.dev2 → 0.0.2
git push --follow-tags origin main
gh release create v0.0.2 --generate-notes    # release finale (sans --prerelease)
```

`bump-my-version show-bump` affiche à tout moment les transitions possibles depuis la version courante.

---

## Dépannage

| Symptôme                      | Remède                                                                       |
|-------------------------------|------------------------------------------------------------------------------|
| Dépendances / structure KO    | `dk doctor` — diagnostique Docker, Compose, git et la structure utilisateur. |
| Profil corrompu               | `dk delete <profil>` puis `dk create`.                                       |
| Clones pollués                | `dk clean <profil>` puis `dk prepare`.                                       |
| Reset complet                 | `rm -rf <config_root>` puis `dk init` (aucun secret irremplaçable n'y vit).  |
| Comprendre ce qui se passe    | Ajouter `-d` / `--debug` : étapes internes + commandes docker/git échoées.   |
| Build BuildKit `EOF` (Colima) | Souvent un OOM de la VM Colima — augmenter sa RAM.                           |

---

## License

MIT — © DigitalKin.
