@orbitpanel/cli 0.4.5 → 0.6.0
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/dist/lib/ai-stream.d.ts +34 -0
- package/dist/lib/ai-stream.js +131 -0
- package/dist/lib/ai-stream.js.map +1 -0
- package/dist/lib/risk.d.ts +38 -0
- package/dist/lib/risk.js +82 -0
- package/dist/lib/risk.js.map +1 -0
- package/dist/lib/runtime.d.ts +11 -0
- package/dist/lib/runtime.js +34 -0
- package/dist/lib/runtime.js.map +1 -0
- package/dist/lib/shell-commands.d.ts +19 -0
- package/dist/lib/shell-commands.js +407 -0
- package/dist/lib/shell-commands.js.map +1 -0
- package/dist/lib/shell-render.d.ts +25 -0
- package/dist/lib/shell-render.js +53 -0
- package/dist/lib/shell-render.js.map +1 -0
- package/dist/lib/shell.d.ts +2 -1
- package/dist/lib/shell.js +280 -604
- package/dist/lib/shell.js.map +1 -1
- package/dist/lib/stream-state.d.ts +28 -0
- package/dist/lib/stream-state.js +69 -0
- package/dist/lib/stream-state.js.map +1 -0
- package/dist/lib/ui.d.ts +13 -0
- package/dist/lib/ui.js +33 -0
- package/dist/lib/ui.js.map +1 -1
- package/dist/state/store.d.ts +29 -0
- package/dist/state/store.js +84 -0
- package/dist/state/store.js.map +1 -0
- package/dist/state/types.d.ts +43 -0
- package/dist/state/types.js +6 -0
- package/dist/state/types.js.map +1 -0
- package/oclif.manifest.json +49 -49
- package/package.json +1 -11
package/dist/lib/shell.js
CHANGED
|
@@ -1,656 +1,332 @@
|
|
|
1
|
-
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
1
|
/**
|
|
3
2
|
* Interactive REPL shell for @orbitpanel/cli.
|
|
4
|
-
*
|
|
3
|
+
* Thin orchestration layer — delegates to shell-commands.ts and shell-render.ts.
|
|
4
|
+
* Pure readline + chalk — no Ink/React dependency.
|
|
5
5
|
*/
|
|
6
|
-
import
|
|
7
|
-
import
|
|
8
|
-
import
|
|
9
|
-
import
|
|
10
|
-
import gradient from 'gradient-string';
|
|
11
|
-
import { loadConfig, DEFAULT_API_URL } from './config.js';
|
|
12
|
-
import { OrbitClient } from './client.js';
|
|
13
|
-
import { isAuthenticated, requestDeviceCode, pollDeviceCode, saveDeviceAuth, openBrowser } from './device-auth.js';
|
|
6
|
+
import chalk from 'chalk';
|
|
7
|
+
import ora from 'ora';
|
|
8
|
+
import { createInterface } from 'node:readline';
|
|
9
|
+
import { loadConfig } from './config.js';
|
|
14
10
|
import { loadSiteLink } from './site.js';
|
|
15
|
-
import { loadActiveSession
|
|
16
|
-
import { getGitBranch
|
|
17
|
-
import { buildReportPayload } from './report-builder.js';
|
|
11
|
+
import { loadActiveSession } from './session.js';
|
|
12
|
+
import { getGitBranch } from './git.js';
|
|
18
13
|
import { sendChat } from './ai-chat.js';
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
{ cmd: '/clear', alias: '', desc: 'pulisci schermo' },
|
|
36
|
-
{ cmd: '/help', alias: '/h', desc: 'lista comandi' },
|
|
37
|
-
{ cmd: '/exit', alias: '/q', desc: 'esci' },
|
|
38
|
-
];
|
|
39
|
-
/** Filter slash commands matching current input. */
|
|
40
|
-
function getCommandSuggestions(input) {
|
|
41
|
-
if (!input.startsWith('/'))
|
|
42
|
-
return [];
|
|
43
|
-
const query = input.toLowerCase();
|
|
44
|
-
if (query === '/')
|
|
45
|
-
return SLASH_COMMANDS;
|
|
46
|
-
return SLASH_COMMANDS.filter(c => c.cmd.startsWith(query) || (c.alias && c.alias.startsWith(query)));
|
|
14
|
+
import { OrbitStore } from '../state/store.js';
|
|
15
|
+
import { sendChatStream } from './ai-stream.js';
|
|
16
|
+
import { StreamStateMachine } from './stream-state.js';
|
|
17
|
+
import { outputBlock } from './ui.js';
|
|
18
|
+
import { B, BL, BB, YELLOW, DIM, WHITE, orbitGrad, sparkle, logoLines, SLASH_COMMANDS, sep, } from './shell-render.js';
|
|
19
|
+
import { statusLine } from './ui.js';
|
|
20
|
+
import { cmdStatus, cmdDoctor, cmdSessionStart, cmdSessionEnd, cmdSessionInfo, cmdNoteAdd, cmdReport, cmdList, cmdGet, cmdSites, cmdAuth, cmdLogin, cmdLink, } from './shell-commands.js';
|
|
21
|
+
// Default IO adapter — bridges store to real filesystem modules
|
|
22
|
+
const defaultStoreIO = {
|
|
23
|
+
loadConfig,
|
|
24
|
+
loadSiteLink: (cwd) => loadSiteLink(cwd),
|
|
25
|
+
loadActiveSession: (siteId) => loadActiveSession(siteId),
|
|
26
|
+
getGitBranch,
|
|
27
|
+
};
|
|
28
|
+
function sleep(ms) {
|
|
29
|
+
return new Promise(r => setTimeout(r, ms));
|
|
47
30
|
}
|
|
48
|
-
|
|
49
|
-
function
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
}) }));
|
|
31
|
+
// Tab-completion handler
|
|
32
|
+
function completer(line) {
|
|
33
|
+
if (!line.startsWith('/'))
|
|
34
|
+
return [[], line];
|
|
35
|
+
const hits = SLASH_COMMANDS
|
|
36
|
+
.filter(c => c.cmd.startsWith(line.toLowerCase()) || (c.alias && c.alias.startsWith(line.toLowerCase())))
|
|
37
|
+
.map(c => c.cmd);
|
|
38
|
+
return [hits.length ? hits : SLASH_COMMANDS.map(c => c.cmd), line];
|
|
57
39
|
}
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
'
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
const
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
const
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
40
|
+
export async function startShell(version) {
|
|
41
|
+
// Header with line-by-line animation
|
|
42
|
+
console.clear();
|
|
43
|
+
console.log('');
|
|
44
|
+
for (const line of logoLines) {
|
|
45
|
+
console.log(orbitGrad(line));
|
|
46
|
+
await sleep(50);
|
|
47
|
+
}
|
|
48
|
+
console.log('');
|
|
49
|
+
console.log(` ${chalk.bgRgb(37, 99, 235).white.bold(' CLI ')} ${chalk.bgHex('#1E293B').hex('#60A5FA')(` v${version} `)} ${DIM('·')} ${BL('Gestione Orbit Panel AI-powered')}`);
|
|
50
|
+
// Initialize centralized state
|
|
51
|
+
const cwd = process.cwd();
|
|
52
|
+
const store = new OrbitStore(defaultStoreIO);
|
|
53
|
+
await store.init(cwd);
|
|
54
|
+
const { config, tokenEntry, siteLink, session, gitBranch, runtime } = store.getState();
|
|
55
|
+
// Status bar (using centralized statusLine renderer)
|
|
56
|
+
const sessionMinutes = session
|
|
57
|
+
? Math.round((Date.now() - new Date(session.started_at).getTime()) / 60_000)
|
|
58
|
+
: undefined;
|
|
59
|
+
console.log('');
|
|
60
|
+
console.log(statusLine({
|
|
61
|
+
connected: !!tokenEntry,
|
|
62
|
+
siteUrl: siteLink?.final_url ?? (siteLink ? siteLink.orbit_site_id.slice(0, 16) : undefined),
|
|
63
|
+
sessionMinutes,
|
|
64
|
+
gitBranch: (session?.git_branch ?? gitBranch) ?? undefined,
|
|
65
|
+
runtimeMode: runtime,
|
|
66
|
+
}));
|
|
67
|
+
console.log('');
|
|
68
|
+
sep();
|
|
69
|
+
// Auto-prompt auth
|
|
70
|
+
if (!tokenEntry) {
|
|
71
|
+
console.log('');
|
|
72
|
+
console.log(` ${YELLOW('Non sei autenticato.')}`);
|
|
73
|
+
console.log('');
|
|
74
|
+
console.log(` ${BL('/auth')} accedi con il browser (consigliato)`);
|
|
75
|
+
console.log(` ${DIM('/login <t>')} inserisci un token MCP manualmente`);
|
|
76
|
+
console.log('');
|
|
77
|
+
}
|
|
78
|
+
else {
|
|
79
|
+
console.log(` ${DIM('Digita /help per la lista comandi, o scrivi in linguaggio naturale.')}`);
|
|
80
|
+
}
|
|
81
|
+
console.log('');
|
|
82
|
+
// REPL
|
|
83
|
+
const rl = createInterface({
|
|
84
|
+
input: process.stdin,
|
|
85
|
+
output: process.stdout,
|
|
86
|
+
prompt: ` ${B('orbit')} ${DIM('›')} `,
|
|
87
|
+
completer,
|
|
88
|
+
terminal: true,
|
|
89
|
+
});
|
|
90
|
+
rl.on('SIGINT', () => {
|
|
91
|
+
console.log(`\n\n ${DIM('Alla prossima!')}\n`);
|
|
92
|
+
rl.close();
|
|
93
|
+
});
|
|
94
|
+
process.on('SIGTSTP', () => {
|
|
95
|
+
console.log(`\n\n ${DIM('Alla prossima!')}\n`);
|
|
96
|
+
rl.close();
|
|
97
|
+
process.exit(0);
|
|
98
|
+
});
|
|
99
|
+
// Prompt function for risk confirmations (uses the active readline)
|
|
100
|
+
const promptConfirm = (message) => {
|
|
101
|
+
return new Promise((resolve) => {
|
|
102
|
+
rl.question(message, (answer) => {
|
|
103
|
+
const a = answer.trim().toLowerCase();
|
|
104
|
+
resolve(a === 's' || a === 'si' || a === 'y' || a === 'yes');
|
|
105
|
+
});
|
|
106
|
+
});
|
|
107
107
|
};
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
(async () => {
|
|
112
|
-
const
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
})();
|
|
117
|
-
}, []);
|
|
118
|
-
// Get current suggestions for arrow navigation
|
|
119
|
-
const suggestions = getCommandSuggestions(input);
|
|
120
|
-
const showSuggestions = input.startsWith('/') && suggestions.length > 0 && !loading;
|
|
121
|
-
useInput((ch, key) => {
|
|
122
|
-
if (key.ctrl && ch === 'c') {
|
|
123
|
-
addOutput({ text: '', dim: true }, { text: ' Alla prossima!', dim: true }, { text: '' });
|
|
124
|
-
setTimeout(() => exit(), 100);
|
|
125
|
-
return;
|
|
126
|
-
}
|
|
127
|
-
// Arrow navigation in suggestions
|
|
128
|
-
if (showSuggestions) {
|
|
129
|
-
if (key.downArrow) {
|
|
130
|
-
setSelectedIndex(prev => (prev + 1) % suggestions.length);
|
|
108
|
+
rl.prompt();
|
|
109
|
+
return new Promise((resolve) => {
|
|
110
|
+
rl.on('close', () => resolve());
|
|
111
|
+
rl.on('line', async (input) => {
|
|
112
|
+
const raw = input.trim();
|
|
113
|
+
const cmd = raw.toLowerCase();
|
|
114
|
+
if (!cmd) {
|
|
115
|
+
rl.prompt();
|
|
131
116
|
return;
|
|
132
117
|
}
|
|
133
|
-
|
|
134
|
-
|
|
118
|
+
// --- Command routing (thin dispatcher) ---
|
|
119
|
+
if (cmd === '/exit' || cmd === '/quit' || cmd === '/q') {
|
|
120
|
+
console.log(`\n ${DIM('Alla prossima!')}\n`);
|
|
121
|
+
rl.close();
|
|
135
122
|
return;
|
|
136
123
|
}
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
const needsArg = ['/note', '/get', '/login', '/link', '/auth'].indexOf(selected.cmd) === -1 ? false : ['/note', '/get', '/login', '/link'].includes(selected.cmd);
|
|
141
|
-
setInput(selected.cmd + (needsArg ? ' ' : ''));
|
|
142
|
-
setSelectedIndex(-1);
|
|
124
|
+
if (cmd === '/clear' || cmd === '/cls') {
|
|
125
|
+
console.clear();
|
|
126
|
+
rl.prompt();
|
|
143
127
|
return;
|
|
144
128
|
}
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
const needsArg = ['/note', '/get', '/login', '/link'].includes(selected.cmd);
|
|
149
|
-
if (needsArg) {
|
|
150
|
-
// Autocomplete but don't submit — needs argument
|
|
151
|
-
setInput(selected.cmd + ' ');
|
|
152
|
-
setSelectedIndex(-1);
|
|
153
|
-
return;
|
|
154
|
-
}
|
|
155
|
-
// Submit directly
|
|
156
|
-
setInput(selected.cmd);
|
|
157
|
-
setSelectedIndex(-1);
|
|
158
|
-
// Don't return — let TextInput handle the submit
|
|
159
|
-
}
|
|
160
|
-
}
|
|
161
|
-
// Reset selection when typing
|
|
162
|
-
if (!key.downArrow && !key.upArrow && !key.tab && !key.return) {
|
|
163
|
-
setSelectedIndex(-1);
|
|
164
|
-
}
|
|
165
|
-
});
|
|
166
|
-
const handleSubmit = async (value) => {
|
|
167
|
-
const raw = value.trim();
|
|
168
|
-
setInput('');
|
|
169
|
-
if (!raw)
|
|
170
|
-
return;
|
|
171
|
-
setHistory(prev => [...prev, raw]);
|
|
172
|
-
const cmd = raw.toLowerCase();
|
|
173
|
-
// Exit
|
|
174
|
-
if (cmd === '/exit' || cmd === '/quit' || cmd === '/q') {
|
|
175
|
-
addOutput({ text: '' }, { text: ' Alla prossima!', dim: true }, { text: '' });
|
|
176
|
-
setTimeout(() => exit(), 100);
|
|
177
|
-
return;
|
|
178
|
-
}
|
|
179
|
-
// Clear
|
|
180
|
-
if (cmd === '/clear' || cmd === '/cls') {
|
|
181
|
-
clearOutput();
|
|
182
|
-
return;
|
|
183
|
-
}
|
|
184
|
-
// Help / List
|
|
185
|
-
if (cmd === '/help' || cmd === '/h') {
|
|
186
|
-
const helpLines = [
|
|
187
|
-
{ text: '' },
|
|
188
|
-
{ text: ' ✦ Comandi disponibili', color: '#60A5FA', bold: true },
|
|
189
|
-
{ text: '' },
|
|
190
|
-
];
|
|
191
|
-
for (const c of SLASH_COMMANDS) {
|
|
192
|
-
const alias = c.alias ? ` ${c.alias}` : '';
|
|
193
|
-
helpLines.push({ text: ` ${c.cmd.padEnd(18)}${alias.padEnd(8)}${c.desc}` });
|
|
194
|
-
}
|
|
195
|
-
helpLines.push({ text: '' });
|
|
196
|
-
addOutput(...helpLines);
|
|
197
|
-
return;
|
|
198
|
-
}
|
|
199
|
-
// Status
|
|
200
|
-
if (cmd === '/status' || cmd === '/s') {
|
|
201
|
-
setLoading(true);
|
|
202
|
-
setLoadingText('Caricamento stato...');
|
|
203
|
-
try {
|
|
204
|
-
const config = await loadConfig();
|
|
205
|
-
const client = getClient(config);
|
|
206
|
-
const lines = [{ text: '' }, { text: ' ✦ Stato', color: '#2563EB', bold: true }, { text: '' }];
|
|
207
|
-
if (!client) {
|
|
208
|
-
lines.push({ text: ' ✗ Token non configurato', color: '#EF4444' });
|
|
209
|
-
lines.push({ text: ' Esegui: /login <token>', dim: true });
|
|
210
|
-
}
|
|
211
|
-
else {
|
|
212
|
-
const t = config.tokens[config.default_site];
|
|
213
|
-
const v = await client.validateToken();
|
|
214
|
-
lines.push({ text: ` ✓ Token ${t.token.slice(0, 15)}...`, color: v.valid ? '#22C55E' : '#EF4444' });
|
|
215
|
-
lines.push({ text: ` ✓ API ${v.valid ? 'raggiungibile' : v.error}`, color: v.valid ? '#22C55E' : '#EF4444' });
|
|
216
|
-
const siteLink = await loadSiteLink(process.cwd());
|
|
217
|
-
if (siteLink)
|
|
218
|
-
lines.push({ text: ` ✓ Sito ${siteLink.final_url ?? siteLink.orbit_site_id}`, color: '#60A5FA' });
|
|
219
|
-
const session = siteLink ? await loadActiveSession(siteLink.orbit_site_id) : null;
|
|
220
|
-
if (session) {
|
|
221
|
-
const elapsed = Math.round((Date.now() - new Date(session.started_at).getTime()) / 60_000);
|
|
222
|
-
lines.push({ text: ` ✓ Sessione attiva (${elapsed}min · ${session.notes.length} note)`, color: '#22C55E' });
|
|
223
|
-
}
|
|
224
|
-
if (v.valid) {
|
|
225
|
-
try {
|
|
226
|
-
const stats = await client.getStats();
|
|
227
|
-
const total = stats.total_interventions ?? 0;
|
|
228
|
-
lines.push({ text: '' });
|
|
229
|
-
lines.push({ text: ` ${total} interventi totali`, color: '#60A5FA' });
|
|
230
|
-
}
|
|
231
|
-
catch { }
|
|
232
|
-
}
|
|
233
|
-
}
|
|
234
|
-
lines.push({ text: '' });
|
|
235
|
-
addOutput(...lines);
|
|
236
|
-
}
|
|
237
|
-
finally {
|
|
238
|
-
setLoading(false);
|
|
239
|
-
}
|
|
240
|
-
return;
|
|
241
|
-
}
|
|
242
|
-
// Doctor
|
|
243
|
-
if (cmd === '/doctor' || cmd === '/doc') {
|
|
244
|
-
setLoading(true);
|
|
245
|
-
setLoadingText('Diagnostica...');
|
|
246
|
-
try {
|
|
247
|
-
const config = await loadConfig();
|
|
248
|
-
const lines = [{ text: '' }, { text: ' ✦ Diagnostica', color: '#2563EB', bold: true }, { text: '' }];
|
|
249
|
-
const t = config.default_site ? config.tokens[config.default_site] : undefined;
|
|
250
|
-
lines.push({ text: ` ${t ? '✓' : '!'} Token ${t ? t.token.slice(0, 15) + '...' : 'non configurato'}`, color: t ? '#22C55E' : '#EAB308' });
|
|
251
|
-
if (t) {
|
|
252
|
-
const c = new OrbitClient(t.token, config.api_url);
|
|
253
|
-
const start = Date.now();
|
|
254
|
-
const v = await c.validateToken();
|
|
255
|
-
lines.push({ text: ` ${v.valid ? '✓' : '✗'} API ${v.valid ? `raggiungibile (${Date.now() - start}ms)` : v.error}`, color: v.valid ? '#22C55E' : '#EF4444' });
|
|
256
|
-
}
|
|
257
|
-
const site = await loadSiteLink(process.cwd());
|
|
258
|
-
lines.push({ text: ` ${site ? '✓' : '!'} Sito ${site ? '.orbit.json presente' : 'non collegato'}`, color: site ? '#22C55E' : '#EAB308' });
|
|
259
|
-
const branch = await getGitBranch();
|
|
260
|
-
lines.push({ text: ` ${branch ? '✓' : '!'} Git ${branch ?? 'nessun repository'}`, color: branch ? '#22C55E' : '#EAB308' });
|
|
261
|
-
const allOk = !!(t && site && branch);
|
|
262
|
-
lines.push({ text: '' });
|
|
263
|
-
lines.push({ text: allOk ? ' ✓ Tutto ok — pronto per lavorare' : ' ! Attenzione — vedi sopra', color: allOk ? '#22C55E' : '#EAB308', bold: true });
|
|
264
|
-
lines.push({ text: '' });
|
|
265
|
-
addOutput(...lines);
|
|
266
|
-
}
|
|
267
|
-
finally {
|
|
268
|
-
setLoading(false);
|
|
269
|
-
}
|
|
270
|
-
return;
|
|
271
|
-
}
|
|
272
|
-
// Session start
|
|
273
|
-
if (cmd === '/session start' || cmd === '/ss') {
|
|
274
|
-
setLoading(true);
|
|
275
|
-
setLoadingText('Avvio sessione...');
|
|
276
|
-
try {
|
|
277
|
-
const siteLink = await loadSiteLink(process.cwd());
|
|
278
|
-
if (!siteLink) {
|
|
279
|
-
addOutput({ text: '' }, { text: ' ✗ Nessun sito collegato. Esegui: /link <site_id>', color: '#EF4444' }, { text: '' });
|
|
280
|
-
return;
|
|
281
|
-
}
|
|
282
|
-
const existing = await loadActiveSession(siteLink.orbit_site_id);
|
|
283
|
-
if (existing) {
|
|
284
|
-
addOutput({ text: '' }, { text: ` ! Sessione gia attiva (${existing.id}). Chiudi con: /session end`, color: '#EAB308' }, { text: '' });
|
|
285
|
-
return;
|
|
286
|
-
}
|
|
287
|
-
const branch = await getGitBranch();
|
|
288
|
-
const commit = await getGitCommitHead();
|
|
289
|
-
const s = await createSession(siteLink.orbit_site_id, { git_branch: branch ?? undefined, git_commit: commit ?? undefined });
|
|
290
|
-
addOutput({ text: '' }, { text: ' ✦ Sessione avviata', color: '#2563EB', bold: true }, { text: '' }, { text: ` ID ${s.id}`, color: '#60A5FA' }, ...(branch ? [{ text: ` Branch ${branch}` }] : []), ...(commit ? [{ text: ` Commit ${commit}`, color: '#60A5FA' }] : []), { text: ` Inizio ${new Date().toLocaleTimeString('it-IT', { hour: '2-digit', minute: '2-digit' })}` }, { text: '' });
|
|
291
|
-
}
|
|
292
|
-
finally {
|
|
293
|
-
setLoading(false);
|
|
294
|
-
}
|
|
295
|
-
return;
|
|
296
|
-
}
|
|
297
|
-
// Session end
|
|
298
|
-
if (cmd === '/session end' || cmd === '/se') {
|
|
299
|
-
setLoading(true);
|
|
300
|
-
setLoadingText('Chiusura sessione...');
|
|
301
|
-
try {
|
|
302
|
-
const siteLink = await loadSiteLink(process.cwd());
|
|
303
|
-
if (!siteLink) {
|
|
304
|
-
addOutput({ text: ' ✗ Nessun sito collegato', color: '#EF4444' });
|
|
305
|
-
return;
|
|
306
|
-
}
|
|
307
|
-
const session = await loadActiveSession(siteLink.orbit_site_id);
|
|
308
|
-
if (!session) {
|
|
309
|
-
addOutput({ text: ' Nessuna sessione attiva', dim: true });
|
|
310
|
-
return;
|
|
311
|
-
}
|
|
312
|
-
const commitEnd = await getGitCommitHead();
|
|
313
|
-
await endSession(session.id, { git_commit_end: commitEnd ?? undefined });
|
|
314
|
-
const elapsed = Math.round((Date.now() - new Date(session.started_at).getTime()) / 60_000);
|
|
315
|
-
addOutput({ text: '' }, { text: ` ✓ Sessione chiusa (${elapsed}min · ${session.notes.length} note)`, color: '#22C55E', bold: true }, { text: ' Invia il report con: /report', dim: true }, { text: '' });
|
|
316
|
-
}
|
|
317
|
-
finally {
|
|
318
|
-
setLoading(false);
|
|
319
|
-
}
|
|
320
|
-
return;
|
|
321
|
-
}
|
|
322
|
-
// Session info
|
|
323
|
-
if (cmd === '/session' || cmd === '/session info') {
|
|
324
|
-
const siteLink = await loadSiteLink(process.cwd());
|
|
325
|
-
if (!siteLink) {
|
|
326
|
-
addOutput({ text: ' Nessun sito collegato', dim: true });
|
|
129
|
+
if (cmd === '/help' || cmd === '/h') {
|
|
130
|
+
printHelp();
|
|
131
|
+
rl.prompt();
|
|
327
132
|
return;
|
|
328
133
|
}
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
134
|
+
if (cmd === '/status' || cmd === '/s') {
|
|
135
|
+
await cmdStatus();
|
|
136
|
+
rl.prompt();
|
|
332
137
|
return;
|
|
333
138
|
}
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
{ text: '' },
|
|
339
|
-
{ text: ` ID ${session.id}`, color: '#60A5FA' },
|
|
340
|
-
{ text: ` Durata ${elapsed} min` },
|
|
341
|
-
];
|
|
342
|
-
if (session.git_branch)
|
|
343
|
-
lines.push({ text: ` Branch ${session.git_branch}`, color: '#60A5FA' });
|
|
344
|
-
lines.push({ text: ` Note ${session.notes.length}` });
|
|
345
|
-
for (const n of session.notes.slice(-5)) {
|
|
346
|
-
lines.push({ text: ` · ${n.text}` });
|
|
139
|
+
if (cmd === '/doctor' || cmd === '/doc') {
|
|
140
|
+
await cmdDoctor();
|
|
141
|
+
rl.prompt();
|
|
142
|
+
return;
|
|
347
143
|
}
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
// Note
|
|
353
|
-
if (cmd.startsWith('/note ') || cmd.startsWith('/n ')) {
|
|
354
|
-
const text = raw.slice(raw.indexOf(' ') + 1);
|
|
355
|
-
const siteLink = await loadSiteLink(process.cwd());
|
|
356
|
-
if (!siteLink) {
|
|
357
|
-
addOutput({ text: ' ✗ Nessun sito collegato', color: '#EF4444' });
|
|
144
|
+
if (cmd === '/session start' || cmd === '/ss') {
|
|
145
|
+
await cmdSessionStart();
|
|
146
|
+
await store.refresh(cwd);
|
|
147
|
+
rl.prompt();
|
|
358
148
|
return;
|
|
359
149
|
}
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
150
|
+
if (cmd === '/session end' || cmd === '/se') {
|
|
151
|
+
await cmdSessionEnd();
|
|
152
|
+
await store.refresh(cwd);
|
|
153
|
+
rl.prompt();
|
|
363
154
|
return;
|
|
364
155
|
}
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
// Report
|
|
370
|
-
if (cmd === '/report' || cmd === '/r') {
|
|
371
|
-
setLoading(true);
|
|
372
|
-
setLoadingText('Invio report a Orbit...');
|
|
373
|
-
try {
|
|
374
|
-
const config = await loadConfig();
|
|
375
|
-
const client = getClient(config);
|
|
376
|
-
if (!client) {
|
|
377
|
-
addOutput({ text: ' ✗ Token non configurato', color: '#EF4444' });
|
|
378
|
-
return;
|
|
379
|
-
}
|
|
380
|
-
const siteLink = await loadSiteLink(process.cwd());
|
|
381
|
-
if (!siteLink) {
|
|
382
|
-
addOutput({ text: ' ✗ Nessun sito collegato', color: '#EF4444' });
|
|
383
|
-
return;
|
|
384
|
-
}
|
|
385
|
-
let session = await loadActiveSession(siteLink.orbit_site_id);
|
|
386
|
-
const commitEnd = await getGitCommitHead();
|
|
387
|
-
let filesChanged = 0;
|
|
388
|
-
if (session?.git_commit_start && commitEnd) {
|
|
389
|
-
const diff = await getGitDiffStat(session.git_commit_start, commitEnd);
|
|
390
|
-
filesChanged = diff.files_changed;
|
|
391
|
-
}
|
|
392
|
-
if (session && session.status === 'active') {
|
|
393
|
-
session = await endSession(session.id, { git_commit_end: commitEnd ?? undefined });
|
|
394
|
-
}
|
|
395
|
-
const payload = buildReportPayload({
|
|
396
|
-
session: session ?? { id: 'no-session', site_id: siteLink.orbit_site_id, started_at: new Date().toISOString(), notes: [], status: 'completed' },
|
|
397
|
-
git_commit_end: commitEnd ?? undefined, files_changed: filesChanged,
|
|
398
|
-
});
|
|
399
|
-
payload.site_id = siteLink.orbit_site_id;
|
|
400
|
-
const result = await client.createIntervention(payload);
|
|
401
|
-
addOutput({ text: '' }, { text: ` ✓ Report inviato ${String(result.id).slice(0, 8)}`, color: '#22C55E', bold: true }, { text: '' });
|
|
156
|
+
if (cmd === '/session' || cmd === '/session info') {
|
|
157
|
+
await cmdSessionInfo();
|
|
158
|
+
rl.prompt();
|
|
159
|
+
return;
|
|
402
160
|
}
|
|
403
|
-
|
|
404
|
-
|
|
161
|
+
if (cmd.startsWith('/note ') || cmd.startsWith('/n ')) {
|
|
162
|
+
await cmdNoteAdd(raw.slice(raw.indexOf(' ') + 1));
|
|
163
|
+
rl.prompt();
|
|
164
|
+
return;
|
|
405
165
|
}
|
|
406
|
-
|
|
407
|
-
|
|
166
|
+
if (cmd === '/report' || cmd === '/r') {
|
|
167
|
+
await cmdReport(promptConfirm);
|
|
168
|
+
await store.refresh(cwd);
|
|
169
|
+
rl.prompt();
|
|
170
|
+
return;
|
|
408
171
|
}
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
setLoading(true);
|
|
414
|
-
setLoadingText('Caricamento interventi...');
|
|
415
|
-
try {
|
|
416
|
-
const config = await loadConfig();
|
|
417
|
-
const client = getClient(config);
|
|
418
|
-
if (!client) {
|
|
419
|
-
addOutput({ text: ' ✗ Token non configurato', color: '#EF4444' });
|
|
420
|
-
return;
|
|
421
|
-
}
|
|
422
|
-
const siteLink = await loadSiteLink(process.cwd());
|
|
423
|
-
const filters = { limit: 10, sort: '-created_at' };
|
|
424
|
-
if (siteLink)
|
|
425
|
-
filters.site_id = siteLink.orbit_site_id;
|
|
426
|
-
const result = await client.listInterventions(filters);
|
|
427
|
-
const lines = [{ text: '' }, { text: ' ✦ Interventi', color: '#2563EB', bold: true }, { text: '' }];
|
|
428
|
-
if (result.items.length === 0) {
|
|
429
|
-
lines.push({ text: ' Nessun intervento trovato', dim: true });
|
|
430
|
-
}
|
|
431
|
-
else {
|
|
432
|
-
for (const item of result.items) {
|
|
433
|
-
const id = String(item.id ?? '').slice(0, 8);
|
|
434
|
-
const t = String(item.title ?? '').slice(0, 35).padEnd(35);
|
|
435
|
-
const s = item.status;
|
|
436
|
-
const sIcon = s === 'completed' ? '●' : s === 'in_progress' ? '●' : '●';
|
|
437
|
-
const sColor = s === 'completed' ? '#22C55E' : s === 'in_progress' ? '#EAB308' : '#60A5FA';
|
|
438
|
-
const sLabel = s === 'completed' ? 'completato' : s === 'in_progress' ? 'in corso' : s === 'verified' ? 'verificato' : 'pianificato';
|
|
439
|
-
const date = String(item.created_at ?? '').slice(5, 10);
|
|
440
|
-
const origin = item.origin === 'cli' ? 'CLI' : String(item.origin);
|
|
441
|
-
lines.push({ text: ` ${sIcon} ${id} ${t} ${sLabel.padEnd(12)} ${origin.padEnd(6)} ${date}`, color: sColor });
|
|
442
|
-
}
|
|
443
|
-
lines.push({ text: '' });
|
|
444
|
-
lines.push({ text: ` ${result.total} interventi`, dim: true });
|
|
445
|
-
}
|
|
446
|
-
lines.push({ text: '' });
|
|
447
|
-
addOutput(...lines);
|
|
172
|
+
if (cmd === '/list' || cmd === '/ls' || cmd === '/interventions') {
|
|
173
|
+
await cmdList();
|
|
174
|
+
rl.prompt();
|
|
175
|
+
return;
|
|
448
176
|
}
|
|
449
|
-
|
|
450
|
-
|
|
177
|
+
if (cmd.startsWith('/get ') || cmd.startsWith('/g ')) {
|
|
178
|
+
await cmdGet(raw.split(' ')[1]);
|
|
179
|
+
rl.prompt();
|
|
180
|
+
return;
|
|
451
181
|
}
|
|
452
|
-
|
|
453
|
-
|
|
182
|
+
if (cmd === '/sites' || cmd.startsWith('/sites ')) {
|
|
183
|
+
await cmdSites(cmd.split(' ')[1]);
|
|
184
|
+
await store.refresh(cwd);
|
|
185
|
+
rl.prompt();
|
|
186
|
+
return;
|
|
454
187
|
}
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
const id = raw.split(' ')[1];
|
|
460
|
-
if (!id) {
|
|
461
|
-
addOutput({ text: ' Uso: /get <intervention_id>', dim: true });
|
|
188
|
+
if (cmd === '/auth') {
|
|
189
|
+
await cmdAuth();
|
|
190
|
+
await store.refresh(cwd);
|
|
191
|
+
rl.prompt();
|
|
462
192
|
return;
|
|
463
193
|
}
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
if (!client) {
|
|
470
|
-
addOutput({ text: ' ✗ Token non configurato', color: '#EF4444' });
|
|
471
|
-
return;
|
|
472
|
-
}
|
|
473
|
-
const item = await client.getIntervention(id);
|
|
474
|
-
addOutput({ text: '' }, { text: ` ✦ ${String(item.title)}`, color: '#2563EB', bold: true }, { text: '' }, { text: ` ID ${String(item.id)}`, color: '#60A5FA' }, { text: ` Stato ${String(item.status)}` }, { text: ` Priorita ${String(item.priority)}` }, { text: ` Origin ${item.origin === 'cli' ? 'CLI' : String(item.origin)}`, color: item.origin === 'cli' ? '#2563EB' : undefined }, ...(item.type_tag ? [{ text: ` Tipo ${String(item.type_tag)}`, color: '#60A5FA' }] : []), { text: ` Creato ${String(item.created_at)}`, dim: true }, { text: '' });
|
|
194
|
+
if (cmd.startsWith('/login ')) {
|
|
195
|
+
await cmdLogin(raw.split(' ')[1]);
|
|
196
|
+
await store.refresh(cwd);
|
|
197
|
+
rl.prompt();
|
|
198
|
+
return;
|
|
475
199
|
}
|
|
476
|
-
|
|
477
|
-
|
|
200
|
+
if (cmd.startsWith('/link ')) {
|
|
201
|
+
await cmdLink(raw.split(' ')[1]);
|
|
202
|
+
await store.refresh(cwd);
|
|
203
|
+
rl.prompt();
|
|
204
|
+
return;
|
|
478
205
|
}
|
|
479
|
-
|
|
480
|
-
|
|
206
|
+
if (cmd.startsWith('/')) {
|
|
207
|
+
console.log(`\n ${DIM('Comando sconosciuto:')} ${WHITE(cmd)} ${DIM('— digita /help')}\n`);
|
|
208
|
+
rl.prompt();
|
|
209
|
+
return;
|
|
481
210
|
}
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
211
|
+
// Free text → AI chat (streaming with state machine + fallback)
|
|
212
|
+
await handleAIChat(raw, store);
|
|
213
|
+
rl.prompt();
|
|
214
|
+
});
|
|
215
|
+
});
|
|
216
|
+
}
|
|
217
|
+
// --- Help output ---
|
|
218
|
+
function printHelp() {
|
|
219
|
+
console.log('');
|
|
220
|
+
console.log(` ${sparkle} ${BB('Comandi disponibili')}`);
|
|
221
|
+
console.log('');
|
|
222
|
+
for (const c of SLASH_COMMANDS) {
|
|
223
|
+
const alias = c.alias ? DIM(` ${c.alias}`) : '';
|
|
224
|
+
console.log(` ${WHITE(c.cmd.padEnd(18))}${alias.padEnd(12)}${DIM(c.desc)}`);
|
|
225
|
+
}
|
|
226
|
+
console.log('');
|
|
227
|
+
console.log(` ${DIM('Oppure scrivi in linguaggio naturale per parlare con Orbit AI.')}`);
|
|
228
|
+
console.log('');
|
|
229
|
+
}
|
|
230
|
+
// --- AI Chat with streaming + state machine ---
|
|
231
|
+
async function handleAIChat(raw, store) {
|
|
232
|
+
const { config, siteLink } = store.getState();
|
|
233
|
+
console.log('');
|
|
234
|
+
console.log(` ${sparkle} ${BB('Orbit AI')}`);
|
|
235
|
+
const spinner = ora({ text: DIM('Recupero contesto...'), color: 'blue', indent: 2 }).start();
|
|
236
|
+
const sm = new StreamStateMachine();
|
|
237
|
+
try {
|
|
238
|
+
store.startRequest();
|
|
239
|
+
const result = await sendChatStream(raw, (event) => {
|
|
240
|
+
// State machine gates event processing
|
|
241
|
+
if (!sm.transition(event.type))
|
|
242
|
+
return;
|
|
243
|
+
switch (event.type) {
|
|
244
|
+
case 'status': {
|
|
245
|
+
const msg = (event.data.message ?? event.data.phase ?? '');
|
|
246
|
+
if (spinner.isSpinning)
|
|
247
|
+
spinner.text = DIM(msg);
|
|
248
|
+
break;
|
|
495
249
|
}
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
return;
|
|
250
|
+
case 'thinking': {
|
|
251
|
+
if (spinner.isSpinning)
|
|
252
|
+
spinner.text = DIM('Analisi in corso...');
|
|
253
|
+
break;
|
|
501
254
|
}
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
const site = sites[idx];
|
|
508
|
-
const siteId = String(site.id);
|
|
509
|
-
const domain = String(site.domain ?? site.home_url ?? siteId);
|
|
510
|
-
const { saveSiteLink } = await import('./site.js');
|
|
511
|
-
await saveSiteLink(process.cwd(), {
|
|
512
|
-
orbit_site_id: siteId,
|
|
513
|
-
platform: 'wordpress',
|
|
514
|
-
final_url: String(site.home_url ?? site.domain ?? ''),
|
|
515
|
-
});
|
|
516
|
-
addOutput({ text: '' }, { text: ` ✓ Sito selezionato: ${domain}`, color: '#22C55E', bold: true }, { text: ` ID: ${siteId}`, dim: true }, { text: '' });
|
|
517
|
-
}
|
|
518
|
-
else {
|
|
519
|
-
addOutput({ text: ` ✗ Numero non valido. Scegli tra 1 e ${sites.length}`, color: '#EF4444' });
|
|
255
|
+
case 'delta': {
|
|
256
|
+
if (spinner.isSpinning) {
|
|
257
|
+
spinner.stop();
|
|
258
|
+
console.log('');
|
|
259
|
+
process.stdout.write(' ');
|
|
520
260
|
}
|
|
521
|
-
|
|
261
|
+
const chunk = event.data.content;
|
|
262
|
+
process.stdout.write(chunk.replaceAll('\n', '\n '));
|
|
263
|
+
break;
|
|
522
264
|
}
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
{
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
addOutput(...lines);
|
|
546
|
-
}
|
|
547
|
-
catch (err) {
|
|
548
|
-
setLoading(false);
|
|
549
|
-
addOutput({ text: ` ✗ ${err instanceof Error ? err.message : String(err)}`, color: '#EF4444' });
|
|
550
|
-
}
|
|
551
|
-
return;
|
|
552
|
-
}
|
|
553
|
-
// Auth via browser (Device Code Flow)
|
|
554
|
-
if (cmd === '/auth') {
|
|
555
|
-
setLoading(true);
|
|
556
|
-
setLoadingText('Generazione codice...');
|
|
557
|
-
try {
|
|
558
|
-
const config = await loadConfig();
|
|
559
|
-
const apiUrl = config.api_url || DEFAULT_API_URL;
|
|
560
|
-
const deviceCode = await requestDeviceCode(apiUrl);
|
|
561
|
-
setLoading(false);
|
|
562
|
-
addOutput({ text: '' }, { text: ' ✦ Accesso con browser', color: '#2563EB', bold: true }, { text: '' }, { text: ` Apri questo URL nel browser:`, dim: false }, { text: ` ${deviceCode.verification_url}`, color: '#60A5FA' }, { text: '' }, { text: ` Codice: ${deviceCode.user_code}`, color: '#2563EB', bold: true }, { text: '' }, { text: ' In attesa di autorizzazione...', dim: true });
|
|
563
|
-
// Open browser automatically
|
|
564
|
-
await openBrowser(deviceCode.verification_url);
|
|
565
|
-
// Poll for authorization
|
|
566
|
-
setLoading(true);
|
|
567
|
-
setLoadingText('In attesa di autorizzazione dal browser...');
|
|
568
|
-
const result = await pollDeviceCode(apiUrl, deviceCode.device_code);
|
|
569
|
-
await saveDeviceAuth(result);
|
|
570
|
-
setLoading(false);
|
|
571
|
-
addOutput({ text: '' }, { text: ` ✓ Autenticato come ${result.user_email ?? 'utente'}`, color: '#22C55E', bold: true }, { text: ' Token salvato in ~/.orbit/config.json', dim: true }, { text: '' });
|
|
572
|
-
}
|
|
573
|
-
catch (err) {
|
|
574
|
-
setLoading(false);
|
|
575
|
-
addOutput({ text: ` ✗ Auth fallita: ${err instanceof Error ? err.message : String(err)}`, color: '#EF4444' });
|
|
576
|
-
}
|
|
577
|
-
return;
|
|
578
|
-
}
|
|
579
|
-
// Login with token
|
|
580
|
-
if (cmd.startsWith('/login ')) {
|
|
581
|
-
const token = raw.split(' ')[1];
|
|
582
|
-
if (!token?.startsWith('orbit_mcp_')) {
|
|
583
|
-
addOutput({ text: ' Uso: /login orbit_mcp_xxx', dim: true });
|
|
584
|
-
return;
|
|
265
|
+
case 'error': {
|
|
266
|
+
if (spinner.isSpinning)
|
|
267
|
+
spinner.stop();
|
|
268
|
+
console.log(`\n ${chalk.red('✗')} ${event.data.message}`);
|
|
269
|
+
break;
|
|
270
|
+
}
|
|
271
|
+
case 'done':
|
|
272
|
+
if (spinner.isSpinning)
|
|
273
|
+
spinner.stop();
|
|
274
|
+
break;
|
|
275
|
+
}
|
|
276
|
+
}, config, siteLink);
|
|
277
|
+
if (spinner.isSpinning)
|
|
278
|
+
spinner.stop();
|
|
279
|
+
store.endRequest();
|
|
280
|
+
const contentStarted = sm.current === 'generating' || sm.current === 'done';
|
|
281
|
+
// Fallback: stream failed before any content → try non-streaming
|
|
282
|
+
if (result.error && !contentStarted) {
|
|
283
|
+
const fallback = await sendChat(raw);
|
|
284
|
+
if (fallback.error) {
|
|
285
|
+
console.log('');
|
|
286
|
+
console.log(outputBlock('error', fallback.error));
|
|
585
287
|
}
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
const v = await client.validateToken();
|
|
591
|
-
if (v.valid) {
|
|
592
|
-
const { setToken } = await import('./config.js');
|
|
593
|
-
await setToken('default', { token, label: 'default', site_id: 'default', created_at: new Date().toISOString() });
|
|
594
|
-
addOutput({ text: '' }, { text: ' ✓ Autenticazione riuscita', color: '#22C55E', bold: true }, { text: '' });
|
|
288
|
+
else {
|
|
289
|
+
console.log('');
|
|
290
|
+
for (const line of (fallback.response ?? '').split('\n')) {
|
|
291
|
+
console.log(` ${line}`);
|
|
595
292
|
}
|
|
596
|
-
|
|
597
|
-
|
|
293
|
+
if (fallback.provider_used) {
|
|
294
|
+
console.log(`\n ${DIM(`(${fallback.provider_used})`)}`);
|
|
598
295
|
}
|
|
599
296
|
}
|
|
600
|
-
finally {
|
|
601
|
-
setLoading(false);
|
|
602
|
-
}
|
|
603
|
-
return;
|
|
604
|
-
}
|
|
605
|
-
// Link
|
|
606
|
-
if (cmd.startsWith('/link ')) {
|
|
607
|
-
const siteId = raw.split(' ')[1];
|
|
608
|
-
if (!siteId) {
|
|
609
|
-
addOutput({ text: ' Uso: /link <site_id>', dim: true });
|
|
610
|
-
return;
|
|
611
|
-
}
|
|
612
|
-
const { saveSiteLink, detectPlatform } = await import('./site.js');
|
|
613
|
-
const platform = await detectPlatform(process.cwd());
|
|
614
|
-
await saveSiteLink(process.cwd(), { orbit_site_id: siteId, platform });
|
|
615
|
-
addOutput({ text: '' }, { text: ` ✓ Sito collegato (${platform})`, color: '#22C55E', bold: true }, { text: '' });
|
|
616
|
-
return;
|
|
617
297
|
}
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
298
|
+
else {
|
|
299
|
+
if (contentStarted)
|
|
300
|
+
process.stdout.write('\n');
|
|
301
|
+
if (result.provider)
|
|
302
|
+
console.log(` ${DIM(`(${result.provider})`)}`);
|
|
303
|
+
if (result.error)
|
|
304
|
+
console.log(` ${chalk.red('✗')} ${result.error}`);
|
|
622
305
|
}
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
306
|
+
}
|
|
307
|
+
catch (err) {
|
|
308
|
+
if (spinner.isSpinning)
|
|
309
|
+
spinner.stop();
|
|
310
|
+
store.endRequest();
|
|
311
|
+
// Network-level failure → fallback to non-streaming
|
|
626
312
|
try {
|
|
627
|
-
const
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
313
|
+
const fallback = await sendChat(raw);
|
|
314
|
+
if (fallback.error) {
|
|
315
|
+
console.log('');
|
|
316
|
+
console.log(outputBlock('error', fallback.error));
|
|
631
317
|
}
|
|
632
318
|
else {
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
319
|
+
console.log('');
|
|
320
|
+
for (const line of (fallback.response ?? '').split('\n')) {
|
|
321
|
+
console.log(` ${line}`);
|
|
322
|
+
}
|
|
637
323
|
}
|
|
638
324
|
}
|
|
639
|
-
catch (
|
|
640
|
-
|
|
641
|
-
|
|
325
|
+
catch (e2) {
|
|
326
|
+
console.log('');
|
|
327
|
+
console.log(outputBlock('error', e2 instanceof Error ? e2.message : String(e2)));
|
|
642
328
|
}
|
|
643
|
-
}
|
|
644
|
-
|
|
645
|
-
}
|
|
646
|
-
function getClient(config) {
|
|
647
|
-
const t = config.default_site ? config.tokens[config.default_site] : undefined;
|
|
648
|
-
if (!t)
|
|
649
|
-
return null;
|
|
650
|
-
return new OrbitClient(t.token, config.api_url);
|
|
651
|
-
}
|
|
652
|
-
export async function startShell(version) {
|
|
653
|
-
const { waitUntilExit } = render(_jsx(Shell, { version: version }));
|
|
654
|
-
await waitUntilExit();
|
|
329
|
+
}
|
|
330
|
+
console.log('');
|
|
655
331
|
}
|
|
656
332
|
//# sourceMappingURL=shell.js.map
|