lovarch-cli 0.2.1__tar.gz → 0.3.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (138) hide show
  1. {lovarch_cli-0.2.1 → lovarch_cli-0.3.0}/CHANGELOG.md +35 -1
  2. {lovarch_cli-0.2.1 → lovarch_cli-0.3.0}/PKG-INFO +45 -5
  3. {lovarch_cli-0.2.1 → lovarch_cli-0.3.0}/README.md +44 -4
  4. lovarch_cli-0.3.0/lovarch_cli/agents/__init__.py +5 -0
  5. lovarch_cli-0.3.0/lovarch_cli/agents/prompts.py +85 -0
  6. lovarch_cli-0.3.0/lovarch_cli/agents/runner.py +66 -0
  7. {lovarch_cli-0.2.1 → lovarch_cli-0.3.0}/lovarch_cli/cli.py +16 -0
  8. lovarch_cli-0.3.0/lovarch_cli/commands/agent_cmd.py +80 -0
  9. {lovarch_cli-0.2.1 → lovarch_cli-0.3.0}/lovarch_cli/commands/context_cmd.py +7 -0
  10. {lovarch_cli-0.2.1 → lovarch_cli-0.3.0}/lovarch_cli/commands/do_cmd.py +36 -0
  11. lovarch_cli-0.3.0/lovarch_cli/commands/mcp_cmd.py +83 -0
  12. {lovarch_cli-0.2.1 → lovarch_cli-0.3.0}/lovarch_cli/commands/run.py +71 -0
  13. lovarch_cli-0.3.0/lovarch_cli/commands/skills_cmd.py +88 -0
  14. {lovarch_cli-0.2.1 → lovarch_cli-0.3.0}/lovarch_cli/mcp/server.py +22 -0
  15. {lovarch_cli-0.2.1 → lovarch_cli-0.3.0}/lovarch_cli/mcp/tools.py +63 -0
  16. lovarch_cli-0.3.0/lovarch_cli/skills/lovarch-capitolato/SKILL.md +37 -0
  17. lovarch_cli-0.3.0/lovarch_cli/skills/lovarch-direzione-lavori/SKILL.md +29 -0
  18. lovarch_cli-0.3.0/lovarch_cli/skills/lovarch-interior-designer/SKILL.md +47 -0
  19. lovarch_cli-0.3.0/lovarch_cli/skills/lovarch-preventivi/SKILL.md +34 -0
  20. lovarch_cli-0.3.0/lovarch_cli/skills/lovarch-render/SKILL.md +36 -0
  21. lovarch_cli-0.3.0/lovarch_cli/skills/lovarch-verifica-normativa/SKILL.md +40 -0
  22. lovarch_cli-0.3.0/lovarch_cli/squad/scripts/input_parser.py +225 -0
  23. {lovarch_cli-0.2.1 → lovarch_cli-0.3.0}/lovarch_cli/squad/scripts/pipeline_runner.py +494 -306
  24. {lovarch_cli-0.2.1 → lovarch_cli-0.3.0}/lovarch_cli/version.py +1 -1
  25. {lovarch_cli-0.2.1 → lovarch_cli-0.3.0}/lovarch_cli/workflows/platform.py +47 -0
  26. lovarch_cli-0.2.1/lovarch_cli/commands/mcp_cmd.py +0 -26
  27. {lovarch_cli-0.2.1 → lovarch_cli-0.3.0}/.gitignore +0 -0
  28. {lovarch_cli-0.2.1 → lovarch_cli-0.3.0}/LICENSE +0 -0
  29. {lovarch_cli-0.2.1 → lovarch_cli-0.3.0}/lovarch_cli/__init__.py +0 -0
  30. {lovarch_cli-0.2.1 → lovarch_cli-0.3.0}/lovarch_cli/__main__.py +0 -0
  31. {lovarch_cli-0.2.1 → lovarch_cli-0.3.0}/lovarch_cli/ai/__init__.py +0 -0
  32. {lovarch_cli-0.2.1 → lovarch_cli-0.3.0}/lovarch_cli/ai/gateway.py +0 -0
  33. {lovarch_cli-0.2.1 → lovarch_cli-0.3.0}/lovarch_cli/api.py +0 -0
  34. {lovarch_cli-0.2.1 → lovarch_cli-0.3.0}/lovarch_cli/auth/__init__.py +0 -0
  35. {lovarch_cli-0.2.1 → lovarch_cli-0.3.0}/lovarch_cli/auth/keyring_store.py +0 -0
  36. {lovarch_cli-0.2.1 → lovarch_cli-0.3.0}/lovarch_cli/auth/local_server.py +0 -0
  37. {lovarch_cli-0.2.1 → lovarch_cli-0.3.0}/lovarch_cli/auth/pkce.py +0 -0
  38. {lovarch_cli-0.2.1 → lovarch_cli-0.3.0}/lovarch_cli/auth/session.py +0 -0
  39. {lovarch_cli-0.2.1 → lovarch_cli-0.3.0}/lovarch_cli/clients/__init__.py +0 -0
  40. {lovarch_cli-0.2.1 → lovarch_cli-0.3.0}/lovarch_cli/clients/factory.py +0 -0
  41. {lovarch_cli-0.2.1 → lovarch_cli-0.3.0}/lovarch_cli/clients/local_client.py +0 -0
  42. {lovarch_cli-0.2.1 → lovarch_cli-0.3.0}/lovarch_cli/clients/lovarch_storage.py +0 -0
  43. {lovarch_cli-0.2.1 → lovarch_cli-0.3.0}/lovarch_cli/clients/lovarch_supabase.py +0 -0
  44. {lovarch_cli-0.2.1 → lovarch_cli-0.3.0}/lovarch_cli/clients/persistence.py +0 -0
  45. {lovarch_cli-0.2.1 → lovarch_cli-0.3.0}/lovarch_cli/clients/storage.py +0 -0
  46. {lovarch_cli-0.2.1 → lovarch_cli-0.3.0}/lovarch_cli/commands/__init__.py +0 -0
  47. {lovarch_cli-0.2.1 → lovarch_cli-0.3.0}/lovarch_cli/commands/account.py +0 -0
  48. {lovarch_cli-0.2.1 → lovarch_cli-0.3.0}/lovarch_cli/commands/audit.py +0 -0
  49. {lovarch_cli-0.2.1 → lovarch_cli-0.3.0}/lovarch_cli/commands/config_cmd.py +0 -0
  50. {lovarch_cli-0.2.1 → lovarch_cli-0.3.0}/lovarch_cli/commands/consolidate.py +0 -0
  51. {lovarch_cli-0.2.1 → lovarch_cli-0.3.0}/lovarch_cli/commands/dev.py +0 -0
  52. {lovarch_cli-0.2.1 → lovarch_cli-0.3.0}/lovarch_cli/commands/init.py +0 -0
  53. {lovarch_cli-0.2.1 → lovarch_cli-0.3.0}/lovarch_cli/commands/jobs_cmd.py +0 -0
  54. {lovarch_cli-0.2.1 → lovarch_cli-0.3.0}/lovarch_cli/commands/login.py +0 -0
  55. {lovarch_cli-0.2.1 → lovarch_cli-0.3.0}/lovarch_cli/commands/signup.py +0 -0
  56. {lovarch_cli-0.2.1 → lovarch_cli-0.3.0}/lovarch_cli/commands/status.py +0 -0
  57. {lovarch_cli-0.2.1 → lovarch_cli-0.3.0}/lovarch_cli/commands/upgrade.py +0 -0
  58. {lovarch_cli-0.2.1 → lovarch_cli-0.3.0}/lovarch_cli/commands/verifica_cmd.py +0 -0
  59. {lovarch_cli-0.2.1 → lovarch_cli-0.3.0}/lovarch_cli/config.py +0 -0
  60. {lovarch_cli-0.2.1 → lovarch_cli-0.3.0}/lovarch_cli/config_store.py +0 -0
  61. {lovarch_cli-0.2.1 → lovarch_cli-0.3.0}/lovarch_cli/credits/__init__.py +0 -0
  62. {lovarch_cli-0.2.1 → lovarch_cli-0.3.0}/lovarch_cli/credits/base.py +0 -0
  63. {lovarch_cli-0.2.1 → lovarch_cli-0.3.0}/lovarch_cli/credits/factory.py +0 -0
  64. {lovarch_cli-0.2.1 → lovarch_cli-0.3.0}/lovarch_cli/credits/local.py +0 -0
  65. {lovarch_cli-0.2.1 → lovarch_cli-0.3.0}/lovarch_cli/credits/lovarch.py +0 -0
  66. {lovarch_cli-0.2.1 → lovarch_cli-0.3.0}/lovarch_cli/i18n/__init__.py +0 -0
  67. {lovarch_cli-0.2.1 → lovarch_cli-0.3.0}/lovarch_cli/i18n/loader.py +0 -0
  68. {lovarch_cli-0.2.1 → lovarch_cli-0.3.0}/lovarch_cli/i18n/translations/en.json +0 -0
  69. {lovarch_cli-0.2.1 → lovarch_cli-0.3.0}/lovarch_cli/i18n/translations/es.json +0 -0
  70. {lovarch_cli-0.2.1 → lovarch_cli-0.3.0}/lovarch_cli/i18n/translations/it.json +0 -0
  71. {lovarch_cli-0.2.1 → lovarch_cli-0.3.0}/lovarch_cli/i18n/translations/pt.json +0 -0
  72. {lovarch_cli-0.2.1 → lovarch_cli-0.3.0}/lovarch_cli/mcp/__init__.py +0 -0
  73. {lovarch_cli-0.2.1 → lovarch_cli-0.3.0}/lovarch_cli/sample_downloader.py +0 -0
  74. {lovarch_cli-0.2.1 → lovarch_cli-0.3.0}/lovarch_cli/squad/README.md +0 -0
  75. {lovarch_cli-0.2.1 → lovarch_cli-0.3.0}/lovarch_cli/squad/agents/auditor-input.md +0 -0
  76. {lovarch_cli-0.2.1 → lovarch_cli-0.3.0}/lovarch_cli/squad/agents/bim-engineer.md +0 -0
  77. {lovarch_cli-0.2.1 → lovarch_cli-0.3.0}/lovarch_cli/squad/agents/briefing-architect.md +0 -0
  78. {lovarch_cli-0.2.1 → lovarch_cli-0.3.0}/lovarch_cli/squad/agents/cad-engineer.md +0 -0
  79. {lovarch_cli-0.2.1 → lovarch_cli-0.3.0}/lovarch_cli/squad/agents/capitolato-writer.md +0 -0
  80. {lovarch_cli-0.2.1 → lovarch_cli-0.3.0}/lovarch_cli/squad/agents/computo-engineer.md +0 -0
  81. {lovarch_cli-0.2.1 → lovarch_cli-0.3.0}/lovarch_cli/squad/agents/concept-designer.md +0 -0
  82. {lovarch_cli-0.2.1 → lovarch_cli-0.3.0}/lovarch_cli/squad/agents/contratto-architect.md +0 -0
  83. {lovarch_cli-0.2.1 → lovarch_cli-0.3.0}/lovarch_cli/squad/agents/deliverable-builder.md +0 -0
  84. {lovarch_cli-0.2.1 → lovarch_cli-0.3.0}/lovarch_cli/squad/agents/energy-prelim.md +0 -0
  85. {lovarch_cli-0.2.1 → lovarch_cli-0.3.0}/lovarch_cli/squad/agents/pratiche-it.md +0 -0
  86. {lovarch_cli-0.2.1 → lovarch_cli-0.3.0}/lovarch_cli/squad/agents/progetto-chief.md +0 -0
  87. {lovarch_cli-0.2.1 → lovarch_cli-0.3.0}/lovarch_cli/squad/agents/quality-dati.md +0 -0
  88. {lovarch_cli-0.2.1 → lovarch_cli-0.3.0}/lovarch_cli/squad/agents/quality-misure.md +0 -0
  89. {lovarch_cli-0.2.1 → lovarch_cli-0.3.0}/lovarch_cli/squad/agents/quality-normativa.md +0 -0
  90. {lovarch_cli-0.2.1 → lovarch_cli-0.3.0}/lovarch_cli/squad/agents/quality-output.md +0 -0
  91. {lovarch_cli-0.2.1 → lovarch_cli-0.3.0}/lovarch_cli/squad/agents/regolatorio-it.md +0 -0
  92. {lovarch_cli-0.2.1 → lovarch_cli-0.3.0}/lovarch_cli/squad/checklists/handoff-quality-gate.md +0 -0
  93. {lovarch_cli-0.2.1 → lovarch_cli-0.3.0}/lovarch_cli/squad/checklists/quality-dati-checklist.md +0 -0
  94. {lovarch_cli-0.2.1 → lovarch_cli-0.3.0}/lovarch_cli/squad/checklists/quality-misure-checklist.md +0 -0
  95. {lovarch_cli-0.2.1 → lovarch_cli-0.3.0}/lovarch_cli/squad/checklists/quality-normativa-checklist.md +0 -0
  96. {lovarch_cli-0.2.1 → lovarch_cli-0.3.0}/lovarch_cli/squad/checklists/quality-output-checklist.md +0 -0
  97. {lovarch_cli-0.2.1 → lovarch_cli-0.3.0}/lovarch_cli/squad/config.yaml +0 -0
  98. {lovarch_cli-0.2.1 → lovarch_cli-0.3.0}/lovarch_cli/squad/data/CHANGELOG.md +0 -0
  99. {lovarch_cli-0.2.1 → lovarch_cli-0.3.0}/lovarch_cli/squad/data/agents-prd.md +0 -0
  100. {lovarch_cli-0.2.1 → lovarch_cli-0.3.0}/lovarch_cli/squad/data/architettura-progetto-rules.md +0 -0
  101. {lovarch_cli-0.2.1 → lovarch_cli-0.3.0}/lovarch_cli/squad/data/handoff-card-template.md +0 -0
  102. {lovarch_cli-0.2.1 → lovarch_cli-0.3.0}/lovarch_cli/squad/data/mocks/catasto-visura.json +0 -0
  103. {lovarch_cli-0.2.1 → lovarch_cli-0.3.0}/lovarch_cli/squad/data/mocks/firma-envelope.json +0 -0
  104. {lovarch_cli-0.2.1 → lovarch_cli-0.3.0}/lovarch_cli/squad/data/prezzario-lombardia-sample.json +0 -0
  105. {lovarch_cli-0.2.1 → lovarch_cli-0.3.0}/lovarch_cli/squad/scripts/api_clients.py +0 -0
  106. {lovarch_cli-0.2.1 → lovarch_cli-0.3.0}/lovarch_cli/squad/scripts/architect_profile.py +0 -0
  107. {lovarch_cli-0.2.1 → lovarch_cli-0.3.0}/lovarch_cli/squad/scripts/deliverable_generators.py +0 -0
  108. {lovarch_cli-0.2.1 → lovarch_cli-0.3.0}/lovarch_cli/squad/scripts/generate_attico_brera_dwg.py +0 -0
  109. {lovarch_cli-0.2.1 → lovarch_cli-0.3.0}/lovarch_cli/squad/scripts/generate_chianti_dxf.py +0 -0
  110. {lovarch_cli-0.2.1 → lovarch_cli-0.3.0}/lovarch_cli/squad/scripts/generate_chianti_images.py +0 -0
  111. {lovarch_cli-0.2.1 → lovarch_cli-0.3.0}/lovarch_cli/squad/scripts/generate_real_sample_images.py +0 -0
  112. {lovarch_cli-0.2.1 → lovarch_cli-0.3.0}/lovarch_cli/squad/scripts/generate_sample_assets.py +0 -0
  113. {lovarch_cli-0.2.1 → lovarch_cli-0.3.0}/lovarch_cli/squad/scripts/lovarch_client.py +0 -0
  114. {lovarch_cli-0.2.1 → lovarch_cli-0.3.0}/lovarch_cli/squad/scripts/render_dxf_to_png.py +0 -0
  115. {lovarch_cli-0.2.1 → lovarch_cli-0.3.0}/lovarch_cli/squad/scripts/run_palestra_demo.sh +0 -0
  116. {lovarch_cli-0.2.1 → lovarch_cli-0.3.0}/lovarch_cli/squad/scripts/simulate_squad_execution.py +0 -0
  117. {lovarch_cli-0.2.1 → lovarch_cli-0.3.0}/lovarch_cli/squad/scripts/validate-squad.py +0 -0
  118. {lovarch_cli-0.2.1 → lovarch_cli-0.3.0}/lovarch_cli/squad/tasks/audit-input.md +0 -0
  119. {lovarch_cli-0.2.1 → lovarch_cli-0.3.0}/lovarch_cli/squad/tasks/compute-metric.md +0 -0
  120. {lovarch_cli-0.2.1 → lovarch_cli-0.3.0}/lovarch_cli/squad/tasks/consolidate-dossier.md +0 -0
  121. {lovarch_cli-0.2.1 → lovarch_cli-0.3.0}/lovarch_cli/squad/tasks/generate-cad-plan.md +0 -0
  122. {lovarch_cli-0.2.1 → lovarch_cli-0.3.0}/lovarch_cli/squad/tasks/generate-ifc-model.md +0 -0
  123. {lovarch_cli-0.2.1 → lovarch_cli-0.3.0}/lovarch_cli/squad/tasks/write-capitolato.md +0 -0
  124. {lovarch_cli-0.2.1 → lovarch_cli-0.3.0}/lovarch_cli/squad/templates/asseverazione-tecnica.md +0 -0
  125. {lovarch_cli-0.2.1 → lovarch_cli-0.3.0}/lovarch_cli/squad/templates/capitolato-uni-11337.md +0 -0
  126. {lovarch_cli-0.2.1 → lovarch_cli-0.3.0}/lovarch_cli/squad/templates/cila-comune-milano.md +0 -0
  127. {lovarch_cli-0.2.1 → lovarch_cli-0.3.0}/lovarch_cli/squad/templates/contratto-cnappc.md +0 -0
  128. {lovarch_cli-0.2.1 → lovarch_cli-0.3.0}/lovarch_cli/squad/workflows/dal-brief-al-cantiere.yaml +0 -0
  129. {lovarch_cli-0.2.1 → lovarch_cli-0.3.0}/lovarch_cli/squad_loader.py +0 -0
  130. {lovarch_cli-0.2.1 → lovarch_cli-0.3.0}/lovarch_cli/verify/__init__.py +0 -0
  131. {lovarch_cli-0.2.1 → lovarch_cli-0.3.0}/lovarch_cli/verify/contratto.py +0 -0
  132. {lovarch_cli-0.2.1 → lovarch_cli-0.3.0}/lovarch_cli/verify/dossier.py +0 -0
  133. {lovarch_cli-0.2.1 → lovarch_cli-0.3.0}/lovarch_cli/verify/misure.py +0 -0
  134. {lovarch_cli-0.2.1 → lovarch_cli-0.3.0}/lovarch_cli/verify/normativa.py +0 -0
  135. {lovarch_cli-0.2.1 → lovarch_cli-0.3.0}/lovarch_cli/workflows/__init__.py +0 -0
  136. {lovarch_cli-0.2.1 → lovarch_cli-0.3.0}/pyproject.toml +0 -0
  137. {lovarch_cli-0.2.1 → lovarch_cli-0.3.0}/scripts/refresh_squad_vendor.py +0 -0
  138. {lovarch_cli-0.2.1 → lovarch_cli-0.3.0}/scripts/sync_squad.py +0 -0
@@ -7,7 +7,41 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
- (No unreleased changes yet — last release was v0.2.1.)
10
+ (No unreleased changes yet — last release was v0.3.0.)
11
+
12
+ ## [0.3.0] — 2026-07-04
13
+
14
+ ### Added — MCP remoto, Skills, agenti, verifica, workflows
15
+
16
+ Il rilascio che porta agli utenti tutto ciò che è stato costruito dopo v0.2.1:
17
+
18
+ - **Skills** (`lovarch skills install`) — 6 skill (interior-designer, capitolato,
19
+ preventivi, direzione-lavori, verifica-normativa, render) che il TUO agente
20
+ (Claude Code) esegue col PROPRIO modello: il testo non consuma crediti Lovarch,
21
+ la piattaforma addebita solo immagini/dati/deliverable/verifica. Regola
22
+ architetturale: "il cervello è dell'utente, la piattaforma fa ciò che solo lei fa".
23
+ - **MCP remoto** `https://mcp.lovarch.com/mcp` (Streamable HTTP) + chiavi `lvk_`
24
+ (`lovarch mcp key`) — connetti Lovarch a qualsiasi client MCP con URL + header,
25
+ come le altre piattaforme.
26
+ - **Agenti** (`lovarch agent`) — interior-designer, direzione-lavori, preventivi,
27
+ geometra-catasto, personalizzati col brand dell'utente (executor=Sonnet 5,
28
+ verifier=Opus 4.8).
29
+ - **verifica** (`lovarch verifica`) — misure (DXF, gratis), normativa, contratto
30
+ (regola QN_007), dossier: controllo adversariale a 2 modelli.
31
+ - **do** (`lovarch do`) — render, colors, copy, logo, site: workflow della
32
+ piattaforma dal terminale.
33
+ - **context** (`lovarch context show [--json]`) — il bundle di personalizzazione.
34
+ - **jobs** (`lovarch jobs`) — job asincroni (video/export/upscale).
35
+ - **config** (`lovarch config`) — preferenze + API keys BYO per il Free.
36
+ - Runner v5: input reale dal progetto (fine del demo hardcoded), run faseadas
37
+ (`--deliverables`), 3 agenti redigono via LLM, chief Opus sul REJECT,
38
+ retry-loop reale del QA.
39
+
40
+ ### Rules
41
+
42
+ - Costo sempre in crediti (mai USD). Lingua dell'utente sempre. Modello
43
+ scegliibile dal catalogo. Il testo, con un agente proprio, gira in locale.
44
+
11
45
 
12
46
  ## [0.2.1] — 2026-07-03
13
47
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: lovarch-cli
3
- Version: 0.2.1
3
+ Version: 0.3.0
4
4
  Summary: AI-powered architectural project execution CLI by Lovarch
5
5
  Project-URL: Homepage, https://archprime.io
6
6
  Project-URL: Documentation, https://lovarch.com/cli-docs
@@ -135,7 +135,7 @@ WSL, o se hai già pipx configurato):
135
135
 
136
136
  ```bash
137
137
  # Ultima release (anche pre-release):
138
- pipx install git+https://github.com/ArchPrime-official/lovarch-cli.git@v0.1.2
138
+ pipx install git+https://github.com/ArchPrime-official/lovarch-cli.git@v0.3.0
139
139
 
140
140
  # Oppure dal branch main (rolling):
141
141
  pipx install git+https://github.com/ArchPrime-official/lovarch-cli.git
@@ -150,7 +150,7 @@ git clone https://github.com/ArchPrime-official/lovarch-cli.git
150
150
  cd lovarch-cli
151
151
  python3.12 -m venv .venv && source .venv/bin/activate
152
152
  pip install -e ".[dev]"
153
- pytest tests/ # → 142 passing
153
+ pytest tests/ # → 198 passing
154
154
  lovarch --version
155
155
  ```
156
156
 
@@ -164,7 +164,7 @@ Vedi [CONTRIBUTING.md](./CONTRIBUTING.md) per il workflow di sviluppo.
164
164
 
165
165
  ```bash
166
166
  # Verifica installazione
167
- lovarch --version # → lovarch-cli 0.1.2
167
+ lovarch --version # → lovarch-cli 0.3.0
168
168
 
169
169
  # Primo login (interattivo: Free o Premium)
170
170
  lovarch login
@@ -191,7 +191,7 @@ lovarch status
191
191
  |---------|-------------|
192
192
  | `arch login` | Login Free o Premium |
193
193
  | `arch signup` | Cadastro Free interattivo |
194
- | `arch config` | Configurazione (API keys, lingua, storage path) — _in arrivo (v0.2)_ |
194
+ | `arch config` | Configurazione (API keys, lingua, storage path) |
195
195
  | `arch init <progetto>` | Crea nuovo progetto con struttura sample-input |
196
196
  | `arch audit <progetto>` | Esegue audit input (gate di ingresso) |
197
197
  | `arch run <workflow>` | Esegue workflow completo |
@@ -199,9 +199,49 @@ lovarch status
199
199
  | `arch status <id>` | Stato di una esecuzione |
200
200
  | `arch upgrade` | CTA per passare da Free a Premium |
201
201
  | `arch account delete` | Right-to-erasure GDPR |
202
+ | `arch context show` | Contesto di personalizzazione usato dagli agenti AI (premium) |
203
+ | `arch do render\|colors\|copy` | Workflow della piattaforma dal terminale (premium) |
204
+ | `arch verifica misure <dxf>` | Verifica DXF: layer ISO, ambienti, cartiglio (gratis) |
205
+ | `arch verifica normativa\|contratto <doc>` | Verifica adversariale 2 modelli (premium) |
206
+ | `arch verifica dossier <cartella>` | QA completo standalone su una cartella (premium) |
207
+ | `arch jobs list\|status` | Job asincroni (video, export, upscale) |
208
+ | `arch mcp serve` | Server MCP per Claude Code / IDE |
202
209
 
203
210
  Vedi `arch --help` per dettagli completi.
204
211
 
212
+ ## Skills — usa il TUO agente (Claude Code, Codex...)
213
+
214
+ Se usi già un agente con un suo modello, il TESTO lo genera lui (zero crediti
215
+ Lovarch); la piattaforma addebita solo immagini, dati e verifiche di piattaforma.
216
+
217
+ ```bash
218
+ lovarch skills install # → ~/.claude/skills
219
+ # poi, nel tuo agente: "progetto di interni per un attico 90mq..." → parte lovarch-interior-designer
220
+ ```
221
+
222
+ Skill disponibili: `interior-designer`, `capitolato`, `preventivi`,
223
+ `direzione-lavori`, `verifica-normativa`, `render`.
224
+
225
+ ## Server MCP (Claude Code / Claude / IDE)
226
+
227
+ Il CLI espone le sue capacità come server **MCP** — 15 tools (render, verifica,
228
+ crediti, contesto, testo multi-modello...). Registrazione in Claude Code:
229
+
230
+ ```bash
231
+ claude mcp add lovarch -- lovarch mcp serve
232
+ ```
233
+
234
+ Oppure il **server MCP remoto** (nessuna installazione — una URL + una chiave):
235
+
236
+ ```bash
237
+ lovarch mcp key # crea una chiave lvk_...
238
+ claude mcp add lovarch --transport http https://mcp.lovarch.com/mcp \\
239
+ --header "Authorization: Bearer lvk_..."
240
+ ```
241
+
242
+ Ogni tool-call addebita i crediti Lovarch dell'utente esattamente come il CLI
243
+ (i costi sono SEMPRE espressi in crediti).
244
+
205
245
  ## Limiti dichiarati
206
246
 
207
247
  `lovarch-cli` **NON** sostituisce:
@@ -76,7 +76,7 @@ WSL, o se hai già pipx configurato):
76
76
 
77
77
  ```bash
78
78
  # Ultima release (anche pre-release):
79
- pipx install git+https://github.com/ArchPrime-official/lovarch-cli.git@v0.1.2
79
+ pipx install git+https://github.com/ArchPrime-official/lovarch-cli.git@v0.3.0
80
80
 
81
81
  # Oppure dal branch main (rolling):
82
82
  pipx install git+https://github.com/ArchPrime-official/lovarch-cli.git
@@ -91,7 +91,7 @@ git clone https://github.com/ArchPrime-official/lovarch-cli.git
91
91
  cd lovarch-cli
92
92
  python3.12 -m venv .venv && source .venv/bin/activate
93
93
  pip install -e ".[dev]"
94
- pytest tests/ # → 142 passing
94
+ pytest tests/ # → 198 passing
95
95
  lovarch --version
96
96
  ```
97
97
 
@@ -105,7 +105,7 @@ Vedi [CONTRIBUTING.md](./CONTRIBUTING.md) per il workflow di sviluppo.
105
105
 
106
106
  ```bash
107
107
  # Verifica installazione
108
- lovarch --version # → lovarch-cli 0.1.2
108
+ lovarch --version # → lovarch-cli 0.3.0
109
109
 
110
110
  # Primo login (interattivo: Free o Premium)
111
111
  lovarch login
@@ -132,7 +132,7 @@ lovarch status
132
132
  |---------|-------------|
133
133
  | `arch login` | Login Free o Premium |
134
134
  | `arch signup` | Cadastro Free interattivo |
135
- | `arch config` | Configurazione (API keys, lingua, storage path) — _in arrivo (v0.2)_ |
135
+ | `arch config` | Configurazione (API keys, lingua, storage path) |
136
136
  | `arch init <progetto>` | Crea nuovo progetto con struttura sample-input |
137
137
  | `arch audit <progetto>` | Esegue audit input (gate di ingresso) |
138
138
  | `arch run <workflow>` | Esegue workflow completo |
@@ -140,9 +140,49 @@ lovarch status
140
140
  | `arch status <id>` | Stato di una esecuzione |
141
141
  | `arch upgrade` | CTA per passare da Free a Premium |
142
142
  | `arch account delete` | Right-to-erasure GDPR |
143
+ | `arch context show` | Contesto di personalizzazione usato dagli agenti AI (premium) |
144
+ | `arch do render\|colors\|copy` | Workflow della piattaforma dal terminale (premium) |
145
+ | `arch verifica misure <dxf>` | Verifica DXF: layer ISO, ambienti, cartiglio (gratis) |
146
+ | `arch verifica normativa\|contratto <doc>` | Verifica adversariale 2 modelli (premium) |
147
+ | `arch verifica dossier <cartella>` | QA completo standalone su una cartella (premium) |
148
+ | `arch jobs list\|status` | Job asincroni (video, export, upscale) |
149
+ | `arch mcp serve` | Server MCP per Claude Code / IDE |
143
150
 
144
151
  Vedi `arch --help` per dettagli completi.
145
152
 
153
+ ## Skills — usa il TUO agente (Claude Code, Codex...)
154
+
155
+ Se usi già un agente con un suo modello, il TESTO lo genera lui (zero crediti
156
+ Lovarch); la piattaforma addebita solo immagini, dati e verifiche di piattaforma.
157
+
158
+ ```bash
159
+ lovarch skills install # → ~/.claude/skills
160
+ # poi, nel tuo agente: "progetto di interni per un attico 90mq..." → parte lovarch-interior-designer
161
+ ```
162
+
163
+ Skill disponibili: `interior-designer`, `capitolato`, `preventivi`,
164
+ `direzione-lavori`, `verifica-normativa`, `render`.
165
+
166
+ ## Server MCP (Claude Code / Claude / IDE)
167
+
168
+ Il CLI espone le sue capacità come server **MCP** — 15 tools (render, verifica,
169
+ crediti, contesto, testo multi-modello...). Registrazione in Claude Code:
170
+
171
+ ```bash
172
+ claude mcp add lovarch -- lovarch mcp serve
173
+ ```
174
+
175
+ Oppure il **server MCP remoto** (nessuna installazione — una URL + una chiave):
176
+
177
+ ```bash
178
+ lovarch mcp key # crea una chiave lvk_...
179
+ claude mcp add lovarch --transport http https://mcp.lovarch.com/mcp \\
180
+ --header "Authorization: Bearer lvk_..."
181
+ ```
182
+
183
+ Ogni tool-call addebita i crediti Lovarch dell'utente esattamente come il CLI
184
+ (i costi sono SEMPRE espressi in crediti).
185
+
146
186
  ## Limiti dichiarati
147
187
 
148
188
  `lovarch-cli` **NON** sostituisce:
@@ -0,0 +1,5 @@
1
+ """Architecture/interior/construction agents runnable from CLI/MCP."""
2
+ from lovarch_cli.agents.prompts import AGENTS, AgentPersona
3
+ from lovarch_cli.agents.runner import AgentResult, run_agent
4
+
5
+ __all__ = ["AGENTS", "AgentPersona", "AgentResult", "run_agent"]
@@ -0,0 +1,85 @@
1
+ """Curated architecture/interior/construction agent personas.
2
+
3
+ Each agent runs through the platform text gateway (cli-ai-text) with the user's
4
+ personalization context prepended, so the output speaks in the user's brand and
5
+ language and debits the user's credits. These extend the squad
6
+ (architettura-progetto) with roles focused on interior design and construction —
7
+ usable standalone from the CLI/MCP, the way each professional prefers.
8
+ """
9
+ from __future__ import annotations
10
+
11
+ from dataclasses import dataclass
12
+
13
+
14
+ @dataclass
15
+ class AgentPersona:
16
+ id: str
17
+ label: str
18
+ role: str # executor (Sonnet) | verifier/chief (Opus)
19
+ system: str
20
+ default_max_tokens: int = 3500
21
+
22
+
23
+ AGENTS: dict[str, AgentPersona] = {
24
+ "interior-designer": AgentPersona(
25
+ id="interior-designer",
26
+ label="Interior Designer",
27
+ role="executor",
28
+ system=(
29
+ "Sei @interior-designer, interior designer esperto (metodo ispirato a "
30
+ "Patricia Urquiola: materia, colore, comfort, dettaglio artigianale). "
31
+ "Dato un brief di progetto, produci in markdown un PROGETTO DI INTERNI "
32
+ "concreto e realizzabile con: (1) concept e atmosfera; (2) layout per "
33
+ "ambiente con mq e flussi; (3) palette materiali e finiture (pavimenti, "
34
+ "pareti, superfici) con motivazione; (4) FF&E — arredi e illuminazione "
35
+ "chiave con criteri di scelta; (5) palette cromatica; (6) note di "
36
+ "comfort e sostenibilità. Coerente con lo stile e i vincoli del cliente. "
37
+ "Concreto, niente riempitivi."
38
+ ),
39
+ ),
40
+ "direzione-lavori": AgentPersona(
41
+ id="direzione-lavori",
42
+ label="Direzione Lavori",
43
+ role="executor",
44
+ system=(
45
+ "Sei @direzione-lavori, direttore dei lavori esperto di cantieri edili "
46
+ "italiani. Dato un progetto, produci in markdown: (1) CRONOPROGRAMMA "
47
+ "realistico per fasi (demolizioni, impianti, opere edili, finiture, "
48
+ "collaudo) con durate e dipendenze; (2) SAL (stati di avanzamento) con "
49
+ "milestone; (3) checklist VISITE DI CANTIERE per fase; (4) verbale-tipo "
50
+ "di sopralluogo; (5) punti di controllo qualità e sicurezza (D.Lgs "
51
+ "81/2008 — CSP/CSE dove necessario). Segnala sempre che firme e "
52
+ "responsabilità sono del professionista abilitato (banner BOZZA)."
53
+ ),
54
+ ),
55
+ "preventivi": AgentPersona(
56
+ id="preventivi",
57
+ label="Preventivi / Proposta",
58
+ role="executor",
59
+ system=(
60
+ "Sei @preventivi, esperto di preventivi e proposte commerciali per "
61
+ "studi di architettura italiani. Dato un progetto e (se disponibili) i "
62
+ "dati fiscali del professionista, produci in markdown una PROPOSTA "
63
+ "professionale con: (1) oggetto e perimetro dell'incarico; (2) fasi e "
64
+ "deliverable; (3) onorario e articolazione in SAL; (4) tempi; (5) note "
65
+ "su oneri (cassa, IVA) e condizioni. Per un cliente PRIVATO i parametri "
66
+ "DM 17/06/2016 sono ORIENTATIVI: un eventuale scostamento va motivato, "
67
+ "MAI presentato come obbligo di legge (la L.49/2023 vincola solo "
68
+ "contraenti forti). Tono professionale ma caldo."
69
+ ),
70
+ ),
71
+ "geometra-catasto": AgentPersona(
72
+ id="geometra-catasto",
73
+ label="Geometra / Catasto",
74
+ role="verifier",
75
+ system=(
76
+ "Sei @geometra-catasto, esperto di dati catastali e pratiche DOCFA. "
77
+ "Dato un input (dati immobile / visura), verifica la COERENZA dei dati "
78
+ "catastali e produci in markdown: (1) riepilogo identificativi (foglio, "
79
+ "mappale, subalterno, categoria, classe) segnalando incongruenze; (2) "
80
+ "check di preparazione per DOCFA/visura; (3) rilievi mancanti o dubbi. "
81
+ "Sei un supporto di CONTROLLO: firma, rilievo metrico e responsabilità "
82
+ "restano del geometra/tecnico abilitato (banner BOZZA)."
83
+ ),
84
+ ),
85
+ }
@@ -0,0 +1,66 @@
1
+ """Run a curated agent persona via the platform text gateway.
2
+
3
+ Prepends the user's personalization bundle (brand, style, signature, language)
4
+ to the agent's system prompt, so every agent speaks in the user's brand and
5
+ language, and debits the user's credits by real tokens.
6
+ """
7
+ from __future__ import annotations
8
+
9
+ from dataclasses import dataclass
10
+
11
+ from lovarch_cli.agents.prompts import AGENTS
12
+ from lovarch_cli.ai import AiGatewayError, LovarchAiGateway
13
+
14
+
15
+ @dataclass
16
+ class AgentResult:
17
+ agent_id: str
18
+ text: str
19
+ model: str
20
+ credits_charged: int
21
+ balance: int | None
22
+
23
+
24
+ async def run_agent(
25
+ gateway: LovarchAiGateway,
26
+ agent_id: str,
27
+ brief: str,
28
+ *,
29
+ language: str = "it",
30
+ lead_id: str | None = None,
31
+ ) -> AgentResult:
32
+ """Run the agent on a brief, personalized with the user's context bundle."""
33
+ persona = AGENTS.get(agent_id)
34
+ if persona is None:
35
+ raise AiGatewayError(
36
+ f"Agente sconosciuto: {agent_id}. Disponibili: {', '.join(AGENTS)}"
37
+ )
38
+
39
+ system = persona.system
40
+ # Best-effort personalization: prepend the user's context prompt_block.
41
+ try:
42
+ bundle = await gateway.get_user_context(lead_id=lead_id)
43
+ block = bundle.get("prompt_block") if isinstance(bundle, dict) else None
44
+ if block:
45
+ system = f"{block}\n\n{system}"
46
+ lang = ((bundle or {}).get("preferences") or {}).get("preferred_language") if isinstance(bundle, dict) else None
47
+ if lang:
48
+ language = lang
49
+ except AiGatewayError:
50
+ pass # personalization is optional; the agent still runs
51
+
52
+ result = await gateway.generate_text(
53
+ brief,
54
+ role=persona.role, # type: ignore[arg-type]
55
+ system=system,
56
+ max_tokens=persona.default_max_tokens,
57
+ language=language,
58
+ operation_type=f"agent:{agent_id}",
59
+ )
60
+ return AgentResult(
61
+ agent_id=agent_id,
62
+ text=result.text,
63
+ model=result.model,
64
+ credits_charged=result.credits_charged,
65
+ balance=result.balance,
66
+ )
@@ -249,6 +249,22 @@ app.add_typer(
249
249
  help="Job asincroni (video, export, upscale) — stato e output.",
250
250
  )
251
251
 
252
+ from lovarch_cli.commands.agent_cmd import agent_app # noqa: E402
253
+
254
+ app.add_typer(
255
+ agent_app,
256
+ name="agent",
257
+ help="Agenti architetto/interior/cantiere (interior-designer, direzione-lavori...).",
258
+ )
259
+
260
+ from lovarch_cli.commands.skills_cmd import skills_app # noqa: E402
261
+
262
+ app.add_typer(
263
+ skills_app,
264
+ name="skills",
265
+ help="Skills per il tuo agente (Claude Code): testo col TUO modello, zero crediti.",
266
+ )
267
+
252
268
  from lovarch_cli.commands.config_cmd import config_app # noqa: E402
253
269
 
254
270
  app.add_typer(
@@ -0,0 +1,80 @@
1
+ """`lovarch agent` — run architecture/interior/construction agents.
2
+
3
+ lovarch agent list
4
+ lovarch agent interior-designer "attico 90mq, stile caldo minimale, cliente ama il legno"
5
+ lovarch agent direzione-lavori "ristrutturazione 120mq, consegna 90 giorni"
6
+
7
+ Each agent runs via the platform (debits credits), personalized with your brand
8
+ and language.
9
+ """
10
+ from __future__ import annotations
11
+
12
+ import asyncio
13
+
14
+ import typer
15
+ from rich.console import Console
16
+ from rich.markdown import Markdown
17
+
18
+ from lovarch_cli.agents import AGENTS
19
+
20
+ console = Console()
21
+ err_console = Console(stderr=True)
22
+
23
+ agent_app = typer.Typer(
24
+ help="Agenti per architetti, interior designer e cantiere (premium).",
25
+ no_args_is_help=True,
26
+ )
27
+
28
+
29
+ @agent_app.command("list")
30
+ def list_command() -> None:
31
+ """Elenca gli agenti disponibili."""
32
+ for a in AGENTS.values():
33
+ model = "Opus 4.8" if a.role in ("verifier", "chief") else "Sonnet 5"
34
+ console.print(f" [cyan]{a.id}[/cyan] — {a.label} [dim]({model})[/dim]")
35
+
36
+
37
+ @agent_app.command("run")
38
+ def run_command(
39
+ agent_id: str = typer.Argument(..., help="ID agente (vedi `lovarch agent list`)."),
40
+ brief: str = typer.Argument(..., help="Brief / richiesta per l'agente."),
41
+ lead: str = typer.Option(None, "--lead", help="ID di un cliente CRM da usare come contesto."),
42
+ language: str = typer.Option(None, "--language", help="Lingua dell'output."),
43
+ output: str = typer.Option(None, "--output", "-o", help="Salva il markdown su file."),
44
+ ) -> None:
45
+ """Esegui un agente su un brief (personalizzato + addebita crediti)."""
46
+ from lovarch_cli.agents import run_agent
47
+ from lovarch_cli.ai import AiGatewayError, InsufficientCreditsError, LovarchAiGateway
48
+ from lovarch_cli.auth.session import LovarchSession
49
+ from lovarch_cli.i18n import current_lang
50
+
51
+ if agent_id not in AGENTS:
52
+ err_console.print(
53
+ f"[red]✗ Agente sconosciuto: {agent_id}. Disponibili: {', '.join(AGENTS)}[/red]"
54
+ )
55
+ raise typer.Exit(2)
56
+
57
+ session = LovarchSession.load()
58
+ if session is None:
59
+ err_console.print("[red]✗ Non autenticato. Esegui `lovarch login --premium`.[/red]")
60
+ raise typer.Exit(1)
61
+
62
+ try:
63
+ result = asyncio.run(run_agent(
64
+ LovarchAiGateway(session), agent_id, brief,
65
+ language=language or current_lang(), lead_id=lead,
66
+ ))
67
+ except InsufficientCreditsError as exc:
68
+ err_console.print(f"[red]✗ Crediti insufficienti: disponibili {exc.available}, richiesti {exc.needed}.[/red]")
69
+ raise typer.Exit(1)
70
+ except AiGatewayError as exc:
71
+ err_console.print(f"[red]✗ {exc}[/red]")
72
+ raise typer.Exit(1)
73
+
74
+ console.print(Markdown(result.text))
75
+ console.print(f"\n[dim]— @{result.agent_id} · crediti addebitati: {result.credits_charged}[/dim]")
76
+ if output:
77
+ from pathlib import Path
78
+
79
+ Path(output).expanduser().write_text(result.text, encoding="utf-8")
80
+ console.print(f"[green]✓[/green] salvato: {output}")
@@ -35,6 +35,7 @@ _CHIP_LABELS = {
35
35
  @context_app.command("show")
36
36
  def show_command(
37
37
  lead_id: str = typer.Option(None, "--lead", help="ID di un lead CRM da includere."),
38
+ as_json: bool = typer.Option(False, "--json", help="Output JSON completo (per skills/agenti)."),
38
39
  ) -> None:
39
40
  """Mostra il bundle di personalizzazione (richiede login premium)."""
40
41
  from lovarch_cli.ai import AiGatewayError, LovarchAiGateway
@@ -51,6 +52,12 @@ def show_command(
51
52
  err_console.print(f"[red]✗ {exc}[/red]")
52
53
  raise typer.Exit(1)
53
54
 
55
+ if as_json:
56
+ import json as _json
57
+
58
+ print(_json.dumps(bundle, ensure_ascii=False, indent=2))
59
+ return
60
+
54
61
  summary = bundle.get("context_summary", {})
55
62
  table = Table(title="Contesto AI — cosa viene usato per personalizzare",
56
63
  show_header=True, header_style="bold gold1")
@@ -118,3 +118,39 @@ def copy_command(
118
118
  rest = {k: v for k, v in out.items() if k not in ("caption", "hashtags")}
119
119
  if rest:
120
120
  console.print_json(json.dumps(rest, ensure_ascii=False))
121
+
122
+
123
+ @do_app.command("logo")
124
+ def logo_command(
125
+ prompt: str = typer.Argument(..., help="Descrizione del logo / brand."),
126
+ output: Path = typer.Option(Path("logo.png"), "--output", "-o"),
127
+ ref: Path = typer.Option(None, "--ref", help="Immagine di riferimento."),
128
+ language: str = typer.Option(None, "--language"),
129
+ ) -> None:
130
+ """Logo pack del brand via piattaforma."""
131
+ from lovarch_cli.mcp.tools import tool_logo
132
+
133
+ out = asyncio.run(tool_logo(_workflows(), prompt=prompt, output_path=str(output),
134
+ reference_image_path=str(ref) if ref else None, language=_lang(language)))
135
+ if not out.get("ok"):
136
+ err_console.print(f"[red]✗ {out.get('error')}[/red]"); raise typer.Exit(1)
137
+ if out.get("saved_to"):
138
+ console.print(f"[green]✓[/green] Logo: [bold]{out['saved_to']}[/bold]")
139
+ if out.get("image_url"):
140
+ console.print(f"[dim]Nel tuo account: {out['image_url']}[/dim]")
141
+
142
+
143
+ @do_app.command("site")
144
+ def site_command(
145
+ prompt: str = typer.Argument(..., help="Descrizione del sito web."),
146
+ output: Path = typer.Option(Path("site.html"), "--output", "-o"),
147
+ language: str = typer.Option(None, "--language"),
148
+ ) -> None:
149
+ """Genera un sito web (HTML) via piattaforma."""
150
+ from lovarch_cli.mcp.tools import tool_site
151
+
152
+ out = asyncio.run(tool_site(_workflows(), prompt=prompt, output_path=str(output), language=_lang(language)))
153
+ if not out.get("ok"):
154
+ err_console.print(f"[red]✗ {out.get('error')}[/red]"); raise typer.Exit(1)
155
+ console.print(f"[green]✓[/green] Sito: [bold]{out['saved_to']}[/bold] ({out.get('bytes', 0)} bytes)")
156
+
@@ -0,0 +1,83 @@
1
+ """`lovarch mcp` — run the Lovarch MCP server.
2
+
3
+ The heavy ``mcp`` SDK import is lazy (inside the command) so that
4
+ ``lovarch --help`` and every other command keep working even when the optional
5
+ ``[mcp]`` extra is not installed.
6
+ """
7
+ from __future__ import annotations
8
+
9
+ import typer
10
+
11
+ mcp_app = typer.Typer(
12
+ help="Server MCP di Lovarch (per Claude Code / IDE). Richiede l'extra [mcp].",
13
+ no_args_is_help=True,
14
+ )
15
+
16
+
17
+ @mcp_app.command("serve")
18
+ def serve_command() -> None:
19
+ """Avvia il server MCP su stdio.
20
+
21
+ Registra in Claude Code con:
22
+ claude mcp add lovarch -- lovarch mcp serve
23
+ """
24
+ from lovarch_cli.mcp.server import serve
25
+
26
+ serve()
27
+
28
+
29
+ @mcp_app.command("key")
30
+ def key_command(
31
+ label: str = typer.Option(None, "--label", "-l", help="Etichetta della chiave (es. 'claude-code macbook')."),
32
+ revoke: str = typer.Option(None, "--revoke", help="ID di una chiave da revocare."),
33
+ list_keys: bool = typer.Option(False, "--list", help="Elenca le chiavi esistenti."),
34
+ ) -> None:
35
+ """Crea (o gestisce) una chiave di connessione per il MCP REMOTO
36
+ (https://mcp.lovarch.com/mcp). La chiave è mostrata UNA sola volta."""
37
+ import asyncio
38
+
39
+ from rich.console import Console
40
+
41
+ from lovarch_cli.auth.session import LovarchSession
42
+
43
+ console = Console()
44
+ err_console = Console(stderr=True)
45
+
46
+ session = LovarchSession.load()
47
+ if session is None:
48
+ err_console.print("[red]✗ Non autenticato. Esegui `lovarch login --premium`.[/red]")
49
+ raise typer.Exit(1)
50
+
51
+ async def _call(body: dict) -> dict:
52
+ resp = await session.request("POST", "/functions/v1/mcp-key-create", json=body)
53
+ try:
54
+ return resp.json()
55
+ except ValueError:
56
+ return {"ok": False, "error": f"HTTP {resp.status_code}"}
57
+
58
+ if list_keys:
59
+ data = asyncio.run(_call({"action": "list"}))
60
+ for k in data.get("keys", []):
61
+ state = "revocata" if k.get("revoked_at") else "attiva"
62
+ console.print(f" {k['id'][:8]} · {k.get('label') or '—'} · {state} · creata {str(k.get('created_at'))[:10]}")
63
+ if not data.get("keys"):
64
+ console.print("[dim]Nessuna chiave.[/dim]")
65
+ return
66
+
67
+ if revoke:
68
+ data = asyncio.run(_call({"action": "revoke", "key_id": revoke}))
69
+ if data.get("ok"):
70
+ console.print(f"[green]✓[/green] chiave revocata: {revoke}")
71
+ else:
72
+ err_console.print(f"[red]✗ {data.get('error')}[/red]")
73
+ raise typer.Exit(1)
74
+ return
75
+
76
+ data = asyncio.run(_call({"action": "create", "label": label}))
77
+ if not data.get("ok"):
78
+ err_console.print(f"[red]✗ {data.get('error')}[/red]")
79
+ raise typer.Exit(1)
80
+ console.print("\n[bold gold1]Chiave MCP creata[/bold gold1] [dim](mostrata solo ORA — salvala)[/dim]\n")
81
+ console.print(f" [bold]{data['key']}[/bold]\n")
82
+ console.print("Collega a Claude Code:\n")
83
+ console.print(f" [cyan]claude mcp add lovarch --transport http {data.get('mcp_url', 'https://mcp.lovarch.com/mcp')} --header \"Authorization: Bearer {data['key']}\"[/cyan]\n")