opencode-wyvern 0.1.1 → 0.2.1
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.
- package/README.md +45 -11
- package/bin/oc-setup.js +36 -8
- package/package.json +8 -4
- package/src/client.js +7 -3
- package/src/i18n.js +19 -0
- package/src/prompts.js +238 -26
- package/src/sections.js +130 -28
- package/src/server.js +127 -19
- package/src/setup.js +248 -69
- package/src/shell.js +6 -1
- package/src/uninstall.js +62 -23
- package/templates/command-commit.md +18 -0
- package/templates/command-explain.md +16 -0
- package/templates/command-omniroute-restart.md +19 -0
- package/templates/command-refactor.md +18 -0
- package/templates/command-review.md +17 -0
- package/templates/command-tests.md +16 -0
package/src/uninstall.js
CHANGED
|
@@ -4,6 +4,7 @@ import crypto from "node:crypto"
|
|
|
4
4
|
import { homedir } from "node:os"
|
|
5
5
|
import { spawnSync } from "node:child_process"
|
|
6
6
|
import { c, confirm, closePrompts } from "./prompts.js"
|
|
7
|
+
import { ui } from "./i18n.js"
|
|
7
8
|
import { loadConfig } from "./config.js"
|
|
8
9
|
import { stripClientBlock, LEGACY_MARKERS } from "./client.js"
|
|
9
10
|
import { pwshProfilePath, bashRcPath, sshConfigPath, configDir } from "./shell.js"
|
|
@@ -37,21 +38,26 @@ function rmDir(p, label) {
|
|
|
37
38
|
|
|
38
39
|
/**
|
|
39
40
|
* Disinstallazione completa: rimuove blocchi client (PowerShell + bash),
|
|
40
|
-
*
|
|
41
|
-
* viene
|
|
42
|
-
*
|
|
41
|
+
* cache locali e alias SSH dal config. La config locale (entry/providers/...)
|
|
42
|
+
* viene PRESERVATA di default per poterla riusare in una reinstallazione; la
|
|
43
|
+
* chiave SSH locale NON viene cancellata (potrebbe servire per altri accessi).
|
|
44
|
+
* La pulizia del server è opzionale e va confermata esplicitamente.
|
|
43
45
|
*/
|
|
44
46
|
export async function runUninstall() {
|
|
45
47
|
const cfg = loadConfig()
|
|
46
48
|
const alias = (cfg.entry && cfg.entry.server) || "remote-server"
|
|
47
49
|
|
|
48
|
-
console.log(c.bold(c.cyan("oc-setup — disinstallazione completa")))
|
|
49
|
-
console.log(c.dim(" rimuovo: blocchi client (PowerShell+bash),
|
|
50
|
-
|
|
50
|
+
console.log(c.bold(c.cyan(ui("oc-setup — disinstallazione completa", "oc-setup — complete uninstall"))))
|
|
51
|
+
console.log(c.dim(ui(" rimuovo: blocchi client (PowerShell+bash), cache locali e alias SSH.",
|
|
52
|
+
" removing: client blocks (PowerShell+bash), local caches and SSH alias.")))
|
|
53
|
+
console.log(c.dim(ui(" la config locale (~/.config/opencode-wyvern) viene preservata per la reinstallazione.",
|
|
54
|
+
" the local config (~/.config/opencode-wyvern) is kept, ready for the new install.")))
|
|
55
|
+
console.log(c.dim(ui(" NON cancello la chiave ~/.ssh/id_ed25519 (potrebbe servire altrove).",
|
|
56
|
+
" I will NOT delete the ~/.ssh/id_ed25519 key (it may be needed elsewhere).")))
|
|
51
57
|
|
|
52
|
-
const ok = await confirm("Procedo con la disinstallazione?", false)
|
|
58
|
+
const ok = await confirm(ui("Procedo con la disinstallazione?", "Proceed with the uninstall?"), false)
|
|
53
59
|
if (!ok) {
|
|
54
|
-
console.log(c.yellow("
|
|
60
|
+
console.log(c.yellow(` ${ui("annullato.", "cancelled.")}`))
|
|
55
61
|
closePrompts()
|
|
56
62
|
return
|
|
57
63
|
}
|
|
@@ -62,10 +68,13 @@ export async function runUninstall() {
|
|
|
62
68
|
const r = stripClientBlock(f)
|
|
63
69
|
if (r.changed) {
|
|
64
70
|
changed = true
|
|
65
|
-
console.log(
|
|
71
|
+
console.log(ui(
|
|
72
|
+
` - blocco client rimosso: ${r.filePath} (backup: ${r.backup})`,
|
|
73
|
+
` - client block removed: ${r.filePath} (backup: ${r.backup})`,
|
|
74
|
+
))
|
|
66
75
|
}
|
|
67
76
|
}
|
|
68
|
-
if (!changed) console.log(c.dim(" nessun blocco client trovato nei profili."))
|
|
77
|
+
if (!changed) console.log(c.dim(ui(" nessun blocco client trovato nei profili.", " no client block found in the profiles.")))
|
|
69
78
|
|
|
70
79
|
const sp = sshConfigPath()
|
|
71
80
|
if (fs.existsSync(sp)) {
|
|
@@ -75,35 +84,65 @@ export async function runUninstall() {
|
|
|
75
84
|
const backup = `${sp}.bak-${crypto.randomBytes(3).toString("hex")}`
|
|
76
85
|
fs.writeFileSync(backup, orig, "utf8")
|
|
77
86
|
fs.writeFileSync(sp, next ? next + "\n" : "", "utf8")
|
|
78
|
-
console.log(
|
|
87
|
+
console.log(ui(
|
|
88
|
+
` - alias SSH '${alias}' rimosso da ${sp} (backup: ${backup})`,
|
|
89
|
+
` - SSH alias '${alias}' removed from ${sp} (backup: ${backup})`,
|
|
90
|
+
))
|
|
79
91
|
} else {
|
|
80
|
-
console.log(c.dim(
|
|
92
|
+
console.log(c.dim(ui(
|
|
93
|
+
` nessun alias '${alias}' trovato in ${sp}.`,
|
|
94
|
+
` no alias '${alias}' found in ${sp}.`,
|
|
95
|
+
)))
|
|
81
96
|
}
|
|
82
97
|
}
|
|
83
98
|
|
|
84
|
-
|
|
85
|
-
|
|
99
|
+
// La config locale serve spesso per la reinstallazione: default = conserva.
|
|
100
|
+
const keepConfig = await confirm(ui(
|
|
101
|
+
`Conservo la config locale (${configDir()}) per la reinstallazione?`,
|
|
102
|
+
`Keep the local config (${configDir()}) for a new install?`,
|
|
103
|
+
), true)
|
|
104
|
+
if (!keepConfig) {
|
|
105
|
+
const r = rmDir(configDir(), "config locale")
|
|
106
|
+
if (r) console.log(ui(` - rimosso: ${configDir()}`, ` - removed: ${configDir()}`))
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
for (const d of CACHE_DIRS) {
|
|
110
|
+
if (rmDir(d)) console.log(ui(` - rimosso: ${d}`, ` - removed: ${d}`))
|
|
86
111
|
}
|
|
87
112
|
|
|
88
113
|
if (cfg.entry && cfg.entry.host && cfg.entry.user) {
|
|
89
|
-
const clean = await confirm(
|
|
114
|
+
const clean = await confirm(ui(
|
|
90
115
|
`Rimuovere anche la config opencode dal server (ssh ${cfg.entry.user}@${cfg.entry.host} → rm -rf ~/.config/opencode)?`,
|
|
91
|
-
|
|
92
|
-
)
|
|
116
|
+
`Also remove the opencode config from the server (ssh ${cfg.entry.user}@${cfg.entry.host} → rm -rf ~/.config/opencode)?`,
|
|
117
|
+
), false)
|
|
93
118
|
if (clean) {
|
|
94
|
-
console.log(c.cyan("[..] Rimuovo ~/.config/opencode sul server..."))
|
|
119
|
+
console.log(c.cyan(ui("[..] Rimuovo ~/.config/opencode sul server...", "[..] Removing ~/.config/opencode on the server...")))
|
|
95
120
|
const res = spawnSync("ssh", [...sshTargetArgs(cfg.entry), "rm -rf ~/.config/opencode && echo DISINSTALL_OK"], {
|
|
96
121
|
encoding: "utf8",
|
|
97
122
|
stdio: ["ignore", "inherit", "inherit"],
|
|
98
123
|
timeout: 120000,
|
|
99
124
|
})
|
|
100
|
-
if (res.status === 0) console.log(c.green(" config opencode rimossa dal server."))
|
|
101
|
-
else console.log(c.yellow(" server non raggiungibile o rm fallito (da rifare a mano)."))
|
|
125
|
+
if (res.status === 0) console.log(c.green(ui(" config opencode rimossa dal server.", " opencode config removed from the server.")))
|
|
126
|
+
else console.log(c.yellow(ui(" server non raggiungibile o rm fallito (da rifare a mano).", " server unreachable or rm failed (to be done manually).")))
|
|
102
127
|
}
|
|
103
128
|
}
|
|
104
129
|
|
|
105
|
-
console.log(c.green("
|
|
106
|
-
|
|
107
|
-
|
|
130
|
+
console.log(c.green(`\n${ui("Disinstallazione completata.", "Uninstall completed.")}`))
|
|
131
|
+
if (keepConfig) {
|
|
132
|
+
console.log(c.dim(ui(
|
|
133
|
+
` config locale preservata: ${configDir()} (per una reinstallazione indolore)`,
|
|
134
|
+
` local config kept: ${configDir()} (for a painless reinstall)`,
|
|
135
|
+
)))
|
|
136
|
+
} else {
|
|
137
|
+
console.log(c.dim(ui(
|
|
138
|
+
` config locale rimossa: ${configDir()}`,
|
|
139
|
+
` local config removed: ${configDir()}`,
|
|
140
|
+
)))
|
|
141
|
+
}
|
|
142
|
+
console.log(c.dim(ui(
|
|
143
|
+
` chiave SSH conservata: ${path.join(homedir(), ".ssh", "id_ed25519")}`,
|
|
144
|
+
` SSH key kept: ${path.join(homedir(), ".ssh", "id_ed25519")}`,
|
|
145
|
+
)))
|
|
146
|
+
console.log(c.dim(ui(" Per una nuova installazione: oc-setup", " For a new install: oc-setup")))
|
|
108
147
|
closePrompts()
|
|
109
148
|
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Genera un messaggio di commit convenzionale (Conventional Commits)
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
# Commit message
|
|
6
|
+
|
|
7
|
+
Analizza le modifiche staged (`git diff --cached`) o le modifiche non committate
|
|
8
|
+
se non è ancora nulla staged (`git diff`).
|
|
9
|
+
|
|
10
|
+
Procedi:
|
|
11
|
+
1. Scegli il **tipo** corretto: `feat`/`fix`/`refactor`/`chore`/`docs`/`test`/`perf`/`ci`.
|
|
12
|
+
2. Scrivi un **oggetto** (imperativo, ≤72 caratteri, senza punto finale).
|
|
13
|
+
3. Aggiungi un **corpo** solo se serve per giustificare il *perché* (non ripetere
|
|
14
|
+
cosa fa il diff). Massimo 72 caratteri per riga.
|
|
15
|
+
4. Se pertinente, aggiungi **breaking change** trailer: `BREAKING CHANGE: <descrizione>`.
|
|
16
|
+
|
|
17
|
+
Output finale: solo il messaggio di commit, senza backtick né output aggiuntivo,
|
|
18
|
+
così che possa essere usato direttamente con `git commit -m "<messaggio>"`.
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Spiega il codice indicato (flusso, scopo, punti chiave)
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
# Spiega il codice
|
|
6
|
+
|
|
7
|
+
Spiega il codice indicato in modo comprensibile ma tecnicamente preciso.
|
|
8
|
+
|
|
9
|
+
1. **Scopo**: cosa fa e perché esiste (contestualizza nel progetto).
|
|
10
|
+
2. **Flusso**: percorso di esecuzione principale, dall'ingresso all'output.
|
|
11
|
+
3. **Punti chiave**: funzioni/rami critici, assunzioni implicite, stati.
|
|
12
|
+
4. **Punti d'attenzione**: dove è facile introdurre bug, cosa qui è fragile.
|
|
13
|
+
|
|
14
|
+
Usa brevi riferimenti `file:riga` per i punti chiave. Se chiedono di un simbolo
|
|
15
|
+
specifico, concentrati su quello anziché spiegare tutto il file. Non aggiungere
|
|
16
|
+
consigli di refactoring a meno che non vengano richiesti.
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Riavvia il container Docker omniroute e verifica che torni healthy
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
# Riavvio OmniRoute
|
|
6
|
+
|
|
7
|
+
Usa questo comando quando il server OmniRoute va in blocco, risponde con errori
|
|
8
|
+
di rete/gateway oppure risulta in stato non healthy. Rimuovi ogni stato bloccato
|
|
9
|
+
e attendi che il gateway sia di nuovo pronto fino a conferma.
|
|
10
|
+
|
|
11
|
+
Esegui esattamente (senza modifiche al container, un solo comando):
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
docker restart omniroute && until [ "$(docker inspect --format='{{.State.Health.Status}}' omniroute 2>/dev/null)" = "healthy" ]; do sleep 2; done && docker inspect --format='{{.State.Status}} / {{.State.Health.Status}}' omniroute
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
Riporta il risultato finale rispecchiando l'output (es. `running / healthy`).
|
|
18
|
+
Se dopo un numero elevato di tentativi il container resta `starting` o
|
|
19
|
+
`unhealthy`, segnalalo all'utente senza nascondere lo stato.
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Piano di refactoring per il codice indicato
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
# Refactoring
|
|
6
|
+
|
|
7
|
+
Analizza il codice indicato e proponi un piano di refactoring incrementale,
|
|
8
|
+
con piccoli passi compilabili e verificabili in modo indipendente.
|
|
9
|
+
|
|
10
|
+
Prima di scrivere codice:
|
|
11
|
+
1. Identifica le **code smell** concrete (duplicazione, accoppiamento, lunghezza,
|
|
12
|
+
responsabilità confuse, abuso di selector/flag).
|
|
13
|
+
2. Proponi la **struttura target** (moduli, funzioni, nomi) motivando ogni scelta.
|
|
14
|
+
3. Elenca i **passi** ordinati: dal più sicuro (meccanico) al più rischioso
|
|
15
|
+
(cambio di comportamento), ciascuno con quali test/correttezza lo verificano.
|
|
16
|
+
|
|
17
|
+
Esegui poi i passi uno alla volta, fermandoti per conferma prima di cambiamenti
|
|
18
|
+
di comportamento o modifiche di API pubbliche. Mantieni invariata la semantica.
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Checklist di code review sul codice selezionato
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
# Code Review
|
|
6
|
+
|
|
7
|
+
Esegui una review del codice indicato (selezione o file). Procedi per priorità
|
|
8
|
+
e riporta solo problemi concreti, non preferenze stilistiche.
|
|
9
|
+
|
|
10
|
+
1. **Correttezza**: bug, race condition, errori di off-by-one, gestione edge case.
|
|
11
|
+
2. **Sicurezza**: injection (SQL, shell, XSS), segreti hardcoded, autenticazione/autorizzazione.
|
|
12
|
+
3. **Robustezza**: errori non gestiti, risorse non rilasciate, timeout.
|
|
13
|
+
4. **Manutenibilità**: duplicazione, funzioni troppo lunghe, naming ambiguo.
|
|
14
|
+
5. **Performance evidenti**: loop N+1, query senza indice, uso eccessivo di memoria.
|
|
15
|
+
|
|
16
|
+
Formato: per ogni problema un blocco `[GRAVITÀ] file:riga — problema` seguita da
|
|
17
|
+
una proposta di fix. Chiudi con un riepilogo numerato per gravità (critico/alto/medio/basso).
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Genera casi di test per il codice indicato
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
# Test
|
|
6
|
+
|
|
7
|
+
Scrivi casi di test per il codice indicato. Prima individua il framework di test
|
|
8
|
+
già usato dal progetto (package.json, config esistente) e seguine le convenzioni;
|
|
9
|
+
se non è determinabile, chiedi all'utente.
|
|
10
|
+
|
|
11
|
+
Copri in ordine: casi felici, edge case (limiti, input vuoti/null, valori limite),
|
|
12
|
+
e casi d'errore (input invalidi, eccezioni). Per ogni test indica cosa verifica
|
|
13
|
+
("behaviour"), non come è implementato. Non aggiungere test puramente decorativi.
|
|
14
|
+
|
|
15
|
+
Dopo aver scritto i test: esegui la suite relativa, correggi gli errori introdotti
|
|
16
|
+
e riporta il comando usato e il risultato.
|