opencode-wyvern 0.2.2 → 0.2.4
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 +6 -7
- package/package.json +1 -1
- package/src/sections.js +3 -3
- package/src/server.js +50 -18
- package/src/setup.js +11 -2
- package/templates/client-bash.sh +26 -8
- package/templates/client-pwsh.ps1 +22 -9
package/README.md
CHANGED
|
@@ -20,7 +20,7 @@ npm install -g opencode-wyvern
|
|
|
20
20
|
Il comando si chiama **`oc-setup`** (non `oc-help`, non `oc`). Verifica:
|
|
21
21
|
|
|
22
22
|
```bash
|
|
23
|
-
oc-setup --version # → 0.2.
|
|
23
|
+
oc-setup --version # → 0.2.4
|
|
24
24
|
```
|
|
25
25
|
|
|
26
26
|
Se compare `oc-setup: command not found` subito dopo l'installazione, il
|
|
@@ -96,7 +96,7 @@ accodata al valore precedente.
|
|
|
96
96
|
| `client-bash` | locale | stesso blocco in `~/.bashrc` |
|
|
97
97
|
| `server` | remoto | controlla node/npm, installa opencode se manca, crea `~/.config/opencode` + `AGENTS.md` |
|
|
98
98
|
| `commands` | remoto | comandi custom in `command/*.md` (`/baseline-ui`, `/omniroute-restart`, `/review`, ...) |
|
|
99
|
-
| `mcp` | remoto | server MCP preset (Figma
|
|
99
|
+
| `mcp` | remoto | server MCP preset (Figma Developer MCP); token in `.env` |
|
|
100
100
|
| `providers` | remoto | provider opencode in `opencode.json`; chiavi in `.env` |
|
|
101
101
|
| `plugins` | remoto | plugin npm installati nella dir config e listati in `opencode.json` |
|
|
102
102
|
| `claude-mem` | remoto | memoria: wrapper `plugins/claude-mem-plugin.js` |
|
|
@@ -125,10 +125,9 @@ Docker OmniRoute e attende che sia `healthy`), `/review`, `/refactor`, `/tests`,
|
|
|
125
125
|
|
|
126
126
|
## MCP
|
|
127
127
|
|
|
128
|
-
La sezione `mcp`
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
token finisce in `.env` sul server, mai in `config.json`).
|
|
128
|
+
La sezione `mcp` configura **Figma Developer MCP** (stdio via
|
|
129
|
+
`npx figma-developer-mcp`). Il Figma personal access token finisce in `.env`
|
|
130
|
+
sul server, mai in `config.json`.
|
|
132
131
|
|
|
133
132
|
## Client
|
|
134
133
|
|
|
@@ -149,4 +148,4 @@ node bin/oc-setup.js --help
|
|
|
149
148
|
- Nessuna chiave/token/password nel pacchetto o in `config.json` locale.
|
|
150
149
|
- Le API key sono scritte dal bootstrap remoto in `~/.config/opencode/.env` (`chmod 600`).
|
|
151
150
|
- I file remoti viaggiano come base64 dentro lo script; con server non raggiungibile
|
|
152
|
-
lo script non viene stampato a video (evita leak delle chiavi).
|
|
151
|
+
lo script non viene stampato a video (evita leak delle chiavi).
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "opencode-wyvern",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.4",
|
|
4
4
|
"description": "Setup modulare per OpenCode: SSH, client PowerShell/bash (comandi oc-*), configurazione server opencode, provider, plugin e comandi custom. Installi tutto, attivi quello che vuoi.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
package/src/sections.js
CHANGED
|
@@ -155,7 +155,6 @@ export const COMMAND_CHOICES = [
|
|
|
155
155
|
]
|
|
156
156
|
|
|
157
157
|
export const MCP_CHOICES = [
|
|
158
|
-
{ label: "Figma Desktop — Dev Mode (localhost, " + ui("nessun segreto", "no secret") + ")", value: "figma-desktop" },
|
|
159
158
|
{ label: "Figma Developer MCP — npx + " + ui("token personale Figma", "personal Figma token"), value: "figma-developer" },
|
|
160
159
|
]
|
|
161
160
|
|
|
@@ -196,7 +195,8 @@ export function serverState(cfg) {
|
|
|
196
195
|
omnirouteUrl,
|
|
197
196
|
baseUrls: cfg.baseUrls || {},
|
|
198
197
|
customCommands: cfg.customCommands || [],
|
|
199
|
-
|
|
198
|
+
// Ignora preset rimossi: `oc-setup generate` pulisce anche le vecchie config.
|
|
199
|
+
mcpList: (cfg.mcpList || []).filter((id) => MCP_PRESETS[id]),
|
|
200
200
|
defaultModel,
|
|
201
201
|
smallModel,
|
|
202
202
|
tuning: cfg.tuning,
|
|
@@ -259,4 +259,4 @@ export function applyRemoteSections(cfg, { dryRun = false, envKeys, applyMode }
|
|
|
259
259
|
}
|
|
260
260
|
runRemote(cfg.entry || cfg, script)
|
|
261
261
|
return { applied: true, script }
|
|
262
|
-
}
|
|
262
|
+
}
|
package/src/server.js
CHANGED
|
@@ -158,16 +158,14 @@ function providerBlock(id, models, baseUrls = {}, omnirouteUrl = "") {
|
|
|
158
158
|
* `envKey` = chiave d'ambiente da chiedere al setup (finisce in .env sul server).
|
|
159
159
|
*/
|
|
160
160
|
export const MCP_PRESETS = {
|
|
161
|
-
"figma-desktop": {
|
|
162
|
-
label: "Figma Desktop — Dev Mode (localhost, nessun segreto)",
|
|
163
|
-
type: "remote",
|
|
164
|
-
url: "http://127.0.0.1:3845/mcp",
|
|
165
|
-
},
|
|
166
161
|
"figma-developer": {
|
|
167
162
|
label: "Figma Developer MCP — npx + Figma personal token",
|
|
168
163
|
type: "local",
|
|
169
|
-
command: ["npx", "-y", "figma-developer-mcp", "--stdio"],
|
|
170
|
-
environment: {
|
|
164
|
+
command: ["npx", "-y", "figma-developer-mcp", "--stdio", "--no-telemetry"],
|
|
165
|
+
environment: {
|
|
166
|
+
FIGMA_API_KEY: "{env:FIGMA_API_KEY}",
|
|
167
|
+
PATH: "{env:PATH}",
|
|
168
|
+
},
|
|
171
169
|
timeout: 15000,
|
|
172
170
|
envKey: "FIGMA_API_KEY",
|
|
173
171
|
},
|
|
@@ -175,14 +173,14 @@ export const MCP_PRESETS = {
|
|
|
175
173
|
|
|
176
174
|
/** Raggruppa i preset MCP scelti nel blocco `mcp` di opencode.json. */
|
|
177
175
|
export function buildMcpBlock(mcpList = []) {
|
|
178
|
-
const
|
|
176
|
+
const servers = {}
|
|
179
177
|
for (const id of mcpList) {
|
|
180
178
|
const p = MCP_PRESETS[id]
|
|
181
179
|
if (!p) continue
|
|
182
180
|
const { label, envKey, ...serv } = p
|
|
183
|
-
|
|
181
|
+
servers[id] = serv
|
|
184
182
|
}
|
|
185
|
-
return
|
|
183
|
+
return Object.keys(servers).length ? { servers } : {}
|
|
186
184
|
}
|
|
187
185
|
|
|
188
186
|
/** Modello default (inner ID) per un preset MCP che richiede un token. */
|
|
@@ -244,11 +242,12 @@ export function ensureLocalKey() {
|
|
|
244
242
|
export function installKeyOnServer(cfg) {
|
|
245
243
|
const { pub } = keyPaths()
|
|
246
244
|
const pubContent = fs.readFileSync(pub, "utf8").trim()
|
|
245
|
+
const pubB64 = Buffer.from(pubContent, "utf8").toString("base64")
|
|
247
246
|
const target = sshTargetArgs(cfg)
|
|
248
247
|
const remoteCmd =
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
"
|
|
248
|
+
`umask 077; mkdir -p ~/.ssh; touch ~/.ssh/authorized_keys; ` +
|
|
249
|
+
`PUB="$(printf '%s' '${pubB64}' | base64 -d)"; ` +
|
|
250
|
+
`grep -qxF "$PUB" ~/.ssh/authorized_keys 2>/dev/null || printf '%s\\n' "$PUB" >> ~/.ssh/authorized_keys; ` +
|
|
252
251
|
"chmod 700 ~/.ssh; chmod 600 ~/.ssh/authorized_keys; echo OK"
|
|
253
252
|
|
|
254
253
|
console.log(c.cyan(ui(
|
|
@@ -278,6 +277,8 @@ export function hostAliasBlock(cfg) {
|
|
|
278
277
|
if (cfg.host) parts.push(` HostName ${cfg.host}`)
|
|
279
278
|
if (cfg.user) parts.push(` User ${cfg.user}`)
|
|
280
279
|
if (cfg.port && String(cfg.port) !== "22") parts.push(` Port ${cfg.port}`)
|
|
280
|
+
parts.push(" IdentityFile ~/.ssh/id_ed25519")
|
|
281
|
+
parts.push(" IdentitiesOnly yes")
|
|
281
282
|
parts.push(" ServerAliveInterval 30")
|
|
282
283
|
parts.push(" ServerAliveCountMax 5")
|
|
283
284
|
parts.push(" StrictHostKeyChecking accept-new")
|
|
@@ -289,19 +290,37 @@ export function ensureSshConfigAlias(cfg) {
|
|
|
289
290
|
const p = sshConfigPath()
|
|
290
291
|
const target = `Host ${cfg.server}`
|
|
291
292
|
let content = ""
|
|
293
|
+
const nextBlock = hostAliasBlock(cfg)
|
|
292
294
|
if (fs.existsSync(p)) {
|
|
293
295
|
content = fs.readFileSync(p, "utf8")
|
|
294
|
-
|
|
296
|
+
const re = new RegExp(`(^|\\n)Host\\s+${cfg.server.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}\\n(?:[ \\t].*(?:\\n|$))*`, "m")
|
|
297
|
+
if (re.test(content)) {
|
|
298
|
+
const updated = content.replace(re, (m, lead = "") => `${lead}${nextBlock}\n`)
|
|
299
|
+
if (updated === content) return false
|
|
300
|
+
fs.writeFileSync(p, updated, "utf8")
|
|
301
|
+
return true
|
|
302
|
+
}
|
|
295
303
|
if (content && !content.endsWith("\n")) content += "\n"
|
|
296
304
|
}
|
|
297
305
|
ensureDir(path.dirname(p))
|
|
298
|
-
fs.writeFileSync(p, content +
|
|
306
|
+
fs.writeFileSync(p, content + nextBlock + "\n", "utf8")
|
|
299
307
|
return true
|
|
300
308
|
}
|
|
301
309
|
|
|
302
310
|
/** Verifica la connessione SSH senza password (BatchMode). */
|
|
303
311
|
export function verifyConnection(cfg) {
|
|
304
|
-
const
|
|
312
|
+
const { key } = keyPaths()
|
|
313
|
+
const target = cfg.server || sshTargetArgs(cfg).at(-1)
|
|
314
|
+
const targetArgs = cfg.server ? [] : sshTargetArgs(cfg).slice(0, -1)
|
|
315
|
+
const keyArgs = fs.existsSync(key) ? ["-i", key, "-o", "IdentitiesOnly=yes"] : []
|
|
316
|
+
const res = run("ssh", [
|
|
317
|
+
...targetArgs,
|
|
318
|
+
...keyArgs,
|
|
319
|
+
"-o", "BatchMode=yes",
|
|
320
|
+
"-o", "ConnectTimeout=8",
|
|
321
|
+
target,
|
|
322
|
+
"echo CONN_OK",
|
|
323
|
+
], {
|
|
305
324
|
silent: true,
|
|
306
325
|
timeout: 20000,
|
|
307
326
|
})
|
|
@@ -335,7 +354,7 @@ export function buildRemoteScript({ sections = new Set(), providers = new Set(),
|
|
|
335
354
|
"if [ -z \"$OPENCODE_BIN\" ]; then",
|
|
336
355
|
" log 'opencode mancante: lo installo (npm i -g opencode-ai)'",
|
|
337
356
|
" npm install -g opencode-ai >/dev/null 2>&1 || true",
|
|
338
|
-
" OPENCODE_BIN=\"$(command -v opencode 2>/dev/null)\"",
|
|
357
|
+
" OPENCODE_BIN=\"$(command -v opencode 2>/dev/null || ls -t $HOME/.nvm/versions/node/*/bin/opencode 2>/dev/null | head -n1)\"",
|
|
339
358
|
"fi",
|
|
340
359
|
'[ -f package.json ] || printf \'{\\n "private": true,\\n "dependencies": {}\\n}\\n\' > package.json',
|
|
341
360
|
"[ -f .gitignore ] || printf 'node_modules\\n.env\\n' > .gitignore",
|
|
@@ -392,6 +411,19 @@ export function buildRemoteScript({ sections = new Set(), providers = new Set(),
|
|
|
392
411
|
lines.push("umask 077; [ -f \"$CFG_DIR/.env\" ] || : > \"$CFG_DIR/.env\"")
|
|
393
412
|
}
|
|
394
413
|
|
|
414
|
+
if (mcpList.includes("figma-developer")) {
|
|
415
|
+
lines.push(
|
|
416
|
+
'NVM_NODE_BIN="$(ls -dt \"$HOME\"/.nvm/versions/node/*/bin 2>/dev/null | head -n1)"',
|
|
417
|
+
'if [ -n "$NVM_NODE_BIN" ] && [ -x "$NVM_NODE_BIN/node" ]; then',
|
|
418
|
+
' touch "$CFG_DIR/.env"',
|
|
419
|
+
' grep -v "^PATH=" "$CFG_DIR/.env" > "$CFG_DIR/.env.tmp" || true',
|
|
420
|
+
' printf \'PATH="%s:%s"\\n\' "$NVM_NODE_BIN" "$PATH" >> "$CFG_DIR/.env.tmp"',
|
|
421
|
+
' mv "$CFG_DIR/.env.tmp" "$CFG_DIR/.env"',
|
|
422
|
+
' chmod 600 "$CFG_DIR/.env"',
|
|
423
|
+
'fi',
|
|
424
|
+
)
|
|
425
|
+
}
|
|
426
|
+
|
|
395
427
|
lines.push('log "config opencode scritta in: $CFG_DIR"')
|
|
396
428
|
lines.push("[ -n \"$OPENCODE_BIN\" ] && \"$OPENCODE_BIN\" --version && echo REMOTE_OK || echo REMOTE_NO_OPENCODE")
|
|
397
429
|
return lines.join("\n")
|
|
@@ -448,4 +480,4 @@ export function runScriptLocal(script) {
|
|
|
448
480
|
|
|
449
481
|
export function isPortValid(v) {
|
|
450
482
|
return v === "" || (/^\d+$/.test(v) && Number(v) >= 1 && Number(v) <= 65535)
|
|
451
|
-
}
|
|
483
|
+
}
|
package/src/setup.js
CHANGED
|
@@ -323,6 +323,14 @@ if (!localOnly) {
|
|
|
323
323
|
if (doInstall) {
|
|
324
324
|
try {
|
|
325
325
|
installKeyOnServer(entry)
|
|
326
|
+
if (verifyConnection(entry)) {
|
|
327
|
+
console.log(c.green(ui(" autenticazione SSH a chiave verificata.", " SSH key authentication verified.")))
|
|
328
|
+
} else {
|
|
329
|
+
console.log(c.yellow(ui(
|
|
330
|
+
" attenzione: la chiave e' stata copiata, ma l'accesso senza password non e' stato verificato. Controlla sshd e ~/.ssh/authorized_keys sul server.",
|
|
331
|
+
" warning: the key was copied, but passwordless login could not be verified. Check sshd and ~/.ssh/authorized_keys on the server.",
|
|
332
|
+
)))
|
|
333
|
+
}
|
|
326
334
|
} catch (err) {
|
|
327
335
|
console.log(c.yellow(` ${ui("attenzione:", "warning:")} ${err.message}`))
|
|
328
336
|
}
|
|
@@ -385,7 +393,8 @@ export async function cmdStatus() {
|
|
|
385
393
|
console.log(` server: provider ${providers.join(", ")}${urls.length ? ` · ${urls.join(" · ")}` : ""}${cfg.tuning ? ui(" · tuning on", " · tuning on") : ""}`)
|
|
386
394
|
}
|
|
387
395
|
if (cfg.customCommands?.length) console.log(` cmds : ${cfg.customCommands.map((x) => "/" + x).join(", ")}`)
|
|
388
|
-
|
|
396
|
+
const mcpList = (cfg.mcpList || []).filter((id) => MCP_PRESETS[id])
|
|
397
|
+
if (mcpList.length) console.log(` mcp : ${mcpList.join(", ")}`)
|
|
389
398
|
console.log("")
|
|
390
399
|
console.log(ui(" moduli:", " modules:"))
|
|
391
400
|
for (const s of SECTIONS) {
|
|
@@ -447,4 +456,4 @@ function fail(msg) {
|
|
|
447
456
|
export async function runPrintClient(kind) {
|
|
448
457
|
const id = kind === "bash" ? "client-bash" : "client-pwsh"
|
|
449
458
|
await cmdPrint(id)
|
|
450
|
-
}
|
|
459
|
+
}
|
package/templates/client-bash.sh
CHANGED
|
@@ -28,11 +28,10 @@ oc-sync-env
|
|
|
28
28
|
|
|
29
29
|
oc-path() {
|
|
30
30
|
oc-sync-env
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
fi
|
|
35
|
-
echo "$OC_OPENCODE"
|
|
31
|
+
# Risolve opencode SUL SERVER al momento dell'esecuzione: funziona anche
|
|
32
|
+
# senza chiave SSH configurata (BatchMode non tenuto) e senza opencode nel
|
|
33
|
+
# PATH del server (cade sulle installazioni nvm `~/.nvm/versions/node/*/bin`).
|
|
34
|
+
printf '%s' '__oc_wyvern(){ OPENCODE_BIN="$(command -v opencode 2>/dev/null || ls -t $HOME/.nvm/versions/node/*/bin/opencode 2>/dev/null | head -n1)"; if [ -z "$OPENCODE_BIN" ]; then echo "[oc] ERRORE: opencode non trovato sul server. Esegui oc-setup scegliendo Client + Server, oppure installa sul server: npm install -g opencode-ai" >&2; return 127; fi; "$OPENCODE_BIN" "$@"; }; __oc_wyvern'
|
|
36
35
|
}
|
|
37
36
|
|
|
38
37
|
oc-connect() {
|
|
@@ -201,10 +200,23 @@ oc-delete() {
|
|
|
201
200
|
|
|
202
201
|
oc-go() {
|
|
203
202
|
oc-sync-env
|
|
204
|
-
local id="$1" dir="${2
|
|
203
|
+
local id="$1" dir="${2:-}" norecap=0 oc exit_code session_dir
|
|
205
204
|
[ "$3" = "--no-recap" ] && norecap=1
|
|
205
|
+
if [ -z "$id" ]; then
|
|
206
|
+
echo -e "${RED}[FAIL] Specifica l'ID della sessione.${NC}"
|
|
207
|
+
return 2
|
|
208
|
+
fi
|
|
209
|
+
case "$id" in
|
|
210
|
+
*[![:alnum:]_-]*) echo -e "${RED}[FAIL] ID sessione non valido.${NC}"; return 2 ;;
|
|
211
|
+
esac
|
|
206
212
|
oc="$(oc-path)"
|
|
207
|
-
|
|
213
|
+
if [ -z "$dir" ]; then
|
|
214
|
+
session_dir="$(oc-cache-load | awk -F '\t' -v wanted="$id" '$2 == wanted { print $4; exit }')"
|
|
215
|
+
if [ -z "$session_dir" ]; then
|
|
216
|
+
session_dir="$(oc-sessions-all | awk -F '\t' -v wanted="$id" '$2 == wanted { print $4; exit }')"
|
|
217
|
+
fi
|
|
218
|
+
dir="${session_dir:-~}"
|
|
219
|
+
fi
|
|
208
220
|
mkdir -p "${XDG_CACHE_HOME:-$HOME/.cache}/opencode-wyvern"
|
|
209
221
|
printf '%s\t%s\n' "$id" "${dir:-~}" > "${XDG_CACHE_HOME:-$HOME/.cache}/opencode-wyvern/last.tsv"
|
|
210
222
|
if [ "$dir" = "~" ] || [ -z "$dir" ]; then
|
|
@@ -229,6 +241,12 @@ oc-recap() {
|
|
|
229
241
|
live="$(oc-sessions-today 2>/dev/null)"
|
|
230
242
|
if [ -z "$live" ]; then
|
|
231
243
|
cached="$(oc-cache-load)"
|
|
244
|
+
if [ "$last_exit" = "127" ]; then
|
|
245
|
+
echo -e "${RED} [!] Comando remoto non trovato (SSH exit 127).${NC}"
|
|
246
|
+
echo -e "${YELLOW} Probabile causa: opencode non e' installato sul server o non e' nel PATH della shell SSH.${NC}"
|
|
247
|
+
echo -e "${DARKGRAY:-} Risolvi con: oc-setup scegliendo Client + Server, oppure sul server: npm install -g opencode-ai${NC}"
|
|
248
|
+
return 127
|
|
249
|
+
fi
|
|
232
250
|
if [ -n "$cached" ]; then
|
|
233
251
|
m="$(stat -c %y "${XDG_CACHE_HOME:-$HOME/.cache}/opencode-wyvern/sessions.tsv" 2>/dev/null | cut -d'.' -f1)"
|
|
234
252
|
echo -e "${RED} [!] Connessione persa alle $err_time (SSH exit $last_exit).${NC}"
|
|
@@ -448,4 +466,4 @@ oc-help() {
|
|
|
448
466
|
echo ""
|
|
449
467
|
echo -e "${DARKGRAY:-}Nota: oc-ssh, oc-sessions, oc-resume richiedono SSH key configurata"
|
|
450
468
|
echo ""
|
|
451
|
-
}
|
|
469
|
+
}
|
|
@@ -26,13 +26,10 @@ function Sync-OcEnv {
|
|
|
26
26
|
Sync-OcEnv
|
|
27
27
|
|
|
28
28
|
function Get-OcPath {
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
else { $global:OC_OPENCODE = 'opencode' }
|
|
34
|
-
}
|
|
35
|
-
return $global:OC_OPENCODE
|
|
29
|
+
# Risolve opencode SUL SERVER al momento dell'esecuzione: funziona anche
|
|
30
|
+
# senza chiave SSH configurata (niente BatchMode) e senza opencode nel PATH
|
|
31
|
+
# del server (fallback sulle installazioni nvm ~/.nvm/versions/node/*/bin).
|
|
32
|
+
return '__oc_wyvern(){ OPENCODE_BIN="$(command -v opencode 2>/dev/null || ls -t $HOME/.nvm/versions/node/*/bin/opencode 2>/dev/null | head -n1)"; if [ -z "$OPENCODE_BIN" ]; then echo "[oc] ERRORE: opencode non trovato sul server. Esegui oc-setup scegliendo Client + Server, oppure installa sul server: npm install -g opencode-ai" >&2; return 127; fi; "$OPENCODE_BIN" "$@"; }; __oc_wyvern'
|
|
36
33
|
}
|
|
37
34
|
|
|
38
35
|
function oc-connect {
|
|
@@ -300,11 +297,21 @@ function oc-go {
|
|
|
300
297
|
param(
|
|
301
298
|
[Parameter(Mandatory)]
|
|
302
299
|
[string]$Id,
|
|
303
|
-
[string]$Dir = "
|
|
300
|
+
[string]$Dir = "",
|
|
304
301
|
[switch]$NoRecap
|
|
305
302
|
)
|
|
306
303
|
Sync-OcEnv
|
|
307
|
-
$
|
|
304
|
+
if ($Id -notmatch '^[A-Za-z0-9_-]+$') {
|
|
305
|
+
Write-Host "ID sessione non valido." -ForegroundColor Red
|
|
306
|
+
return
|
|
307
|
+
}
|
|
308
|
+
if ([string]::IsNullOrWhiteSpace($Dir)) {
|
|
309
|
+
$found = @(Get-OcCachedSessions | Where-Object { $_.Id -eq $Id } | Select-Object -First 1)
|
|
310
|
+
if (-not $found.Count) {
|
|
311
|
+
$found = @(Get-OcAllSessions | Where-Object { $_.Id -eq $Id } | Select-Object -First 1)
|
|
312
|
+
}
|
|
313
|
+
$Dir = if ($found.Count) { $found[0].Dir } else { "~" }
|
|
314
|
+
}
|
|
308
315
|
$oc = Get-OcPath
|
|
309
316
|
if ($Dir -eq '~' -or [string]::IsNullOrEmpty($Dir)) {
|
|
310
317
|
$remoteCmd = "cd ~ && $oc -s $Id"
|
|
@@ -334,6 +341,12 @@ function Show-OcRecap {
|
|
|
334
341
|
$sessions = @(Get-OcRecentSessions)
|
|
335
342
|
$fromCache = $false
|
|
336
343
|
if ($sessions.Count -eq 0) {
|
|
344
|
+
if ($LastExit -eq 127) {
|
|
345
|
+
Write-Host " [!] Comando remoto non trovato (SSH exit 127)." -ForegroundColor Red
|
|
346
|
+
Write-Host " Probabile causa: opencode non e' installato sul server o non e' nel PATH della shell SSH." -ForegroundColor Yellow
|
|
347
|
+
Write-Host " Risolvi con: oc-setup scegliendo Client + Server, oppure sul server: npm install -g opencode-ai" -ForegroundColor DarkGray
|
|
348
|
+
return
|
|
349
|
+
}
|
|
337
350
|
$status = Get-OcServerStatus
|
|
338
351
|
if ($status.Up) {
|
|
339
352
|
Write-Host " Server raggiungibile ma nessuna sessione nelle ultime 24 ore." -ForegroundColor Yellow
|