@vidiemme/copilot-proxy 0.1.1 → 0.3.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/README.md +18 -2
- package/dist/autostart.d.ts +4 -0
- package/dist/autostart.js +46 -3
- package/dist/autostart.js.map +1 -1
- package/dist/cli.js +240 -76
- package/dist/cli.js.map +1 -1
- package/dist/collector/forwarder.d.ts +16 -0
- package/dist/collector/forwarder.js +61 -5
- package/dist/collector/forwarder.js.map +1 -1
- package/dist/config.d.ts +3 -0
- package/dist/config.js +2 -0
- package/dist/config.js.map +1 -1
- package/dist/editors.d.ts +18 -0
- package/dist/editors.js +75 -0
- package/dist/editors.js.map +1 -0
- package/dist/paths.d.ts +0 -2
- package/dist/paths.js +0 -11
- package/dist/paths.js.map +1 -1
- package/dist/projectDetector.js +55 -11
- package/dist/projectDetector.js.map +1 -1
- package/dist/proxy/inspectRequest.js +3 -2
- package/dist/proxy/inspectRequest.js.map +1 -1
- package/dist/server.js +10 -3
- package/dist/server.js.map +1 -1
- package/dist/setupHelpers.d.ts +9 -0
- package/dist/setupHelpers.js +40 -0
- package/dist/setupHelpers.js.map +1 -0
- package/dist/usage/collector.js.map +1 -1
- package/dist/usage/parseOpenAI.d.ts +7 -5
- package/dist/usage/parseOpenAI.js +21 -10
- package/dist/usage/parseOpenAI.js.map +1 -1
- package/dist/usage/sse.js.map +1 -1
- package/dist/version.d.ts +2 -0
- package/dist/version.js +6 -0
- package/dist/version.js.map +1 -0
- package/package.json +4 -4
package/README.md
CHANGED
|
@@ -17,7 +17,9 @@ Il progetto viene riconosciuto dal repository git su cui si sta lavorando: nessu
|
|
|
17
17
|
profilo da cambiare quando si passa da un progetto all'altro.
|
|
18
18
|
|
|
19
19
|
Non vengono mai salvati prompt ne' risposte: solo contatori. L'identita' della
|
|
20
|
-
persona e' uno pseudonimo, cioe' un hash con salt non invertibile
|
|
20
|
+
persona e' uno pseudonimo, cioe' un hash con salt non invertibile; il setup
|
|
21
|
+
propone di affiancargli il nome di `git config`, per riconoscersi nella dashboard
|
|
22
|
+
(`--anonymous` per non farlo).
|
|
21
23
|
|
|
22
24
|
## Uso
|
|
23
25
|
|
|
@@ -27,17 +29,31 @@ npx @vidiemme/copilot-proxy@latest setup --vscode --autostart
|
|
|
27
29
|
|
|
28
30
|
# se qualcosa non torna
|
|
29
31
|
npx @vidiemme/copilot-proxy@latest doctor
|
|
32
|
+
|
|
33
|
+
# versione, eventi misurati e consegnati, spool in attesa
|
|
34
|
+
npx @vidiemme/copilot-proxy@latest status
|
|
30
35
|
```
|
|
31
36
|
|
|
37
|
+
Con l'avvio automatico, dopo un aggiornamento (`npm i -g @vidiemme/copilot-proxy@latest`)
|
|
38
|
+
serve `copilot-proxy restart`; per toglierlo, `copilot-proxy uninstall`.
|
|
39
|
+
|
|
32
40
|
Non c'e' nulla da configurare a mano: endpoint di raccolta, salt e cartelle dove
|
|
33
41
|
cercare i progetti sono gia' nel pacchetto. L'unica cosa da procurarsi e' il
|
|
34
42
|
token di raccolta, che il comando chiede in modo nascosto.
|
|
35
43
|
|
|
36
|
-
`--vscode` scrive le impostazioni utente di VS Code
|
|
44
|
+
`--vscode` scrive le impostazioni utente di VS Code e dei derivati installati
|
|
45
|
+
(Insiders, VSCodium, Cursor, Windsurf, Antigravity), `--autostart` registra il
|
|
37
46
|
proxy fra i servizi dell'utente: parte subito e a ogni accesso, senza che nessuno
|
|
38
47
|
debba ricordarsi di lanciarlo. Con entrambe, dopo questo comando non c'e' piu'
|
|
39
48
|
nulla da fare. Il comando stampa come disattivarlo.
|
|
40
49
|
|
|
50
|
+
Il setup chiede la porta locale (default 8787) e controlla che sia libera. Per
|
|
51
|
+
cambiarla dopo: `setup --force --port 9000 --vscode --autostart`, senza
|
|
52
|
+
reinserire il token.
|
|
53
|
+
|
|
54
|
+
JetBrains, Eclipse, Xcode e Visual Studio non si possono indirizzare al proxy:
|
|
55
|
+
il loro consumo non viene misurato.
|
|
56
|
+
|
|
41
57
|
Senza `--autostart` il proxy si avvia a mano:
|
|
42
58
|
|
|
43
59
|
```bash
|
package/dist/autostart.d.ts
CHANGED
|
@@ -8,3 +8,7 @@ export interface AutostartResult {
|
|
|
8
8
|
export declare function autostartFile(): string | undefined;
|
|
9
9
|
export declare function isAutostartInstalled(): boolean;
|
|
10
10
|
export declare function installAutostart(): AutostartResult;
|
|
11
|
+
/** Rimuove il servizio; `false` se non era installato. */
|
|
12
|
+
export declare function uninstallAutostart(): boolean;
|
|
13
|
+
/** Riavvia il servizio, ad esempio dopo un aggiornamento del pacchetto. */
|
|
14
|
+
export declare function restartAutostart(): void;
|
package/dist/autostart.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { execFileSync } from 'node:child_process';
|
|
2
|
-
import { existsSync, mkdirSync, writeFileSync } from 'node:fs';
|
|
2
|
+
import { existsSync, mkdirSync, rmSync, writeFileSync } from 'node:fs';
|
|
3
3
|
import { homedir } from 'node:os';
|
|
4
4
|
import { dirname, join } from 'node:path';
|
|
5
5
|
import { fileURLToPath } from 'node:url';
|
|
@@ -48,12 +48,55 @@ export function installAutostart() {
|
|
|
48
48
|
const result = process.platform === 'darwin' ? installLaunchd(file, entry) : installSystemd(file, entry);
|
|
49
49
|
// La cache di npx non e' una posizione stabile: `npm cache clean` la svuota e
|
|
50
50
|
// il servizio resterebbe a puntare nel vuoto.
|
|
51
|
+
const warnings = [];
|
|
51
52
|
if (entry.includes('/_npx/')) {
|
|
52
|
-
|
|
53
|
-
'Il servizio punta dentro la cache di npx, che puo\' essere ripulita. Per un avvio automatico stabile: npm i -g @vidiemme/copilot-proxy, poi rilancia il setup con --autostart';
|
|
53
|
+
warnings.push('Il servizio punta dentro la cache di npx, che puo\' essere ripulita. Per un avvio automatico stabile: npm i -g @vidiemme/copilot-proxy, poi rilancia il setup con --autostart');
|
|
54
54
|
}
|
|
55
|
+
if (VERSION_MANAGER_PATH.test(process.execPath)) {
|
|
56
|
+
warnings.push(`Il servizio usa ${process.execPath}, gestito da un version manager: se quella versione di Node viene disinstallata il proxy non riparte. Dopo un cambio di versione rilancia il setup con --autostart --force`);
|
|
57
|
+
}
|
|
58
|
+
if (warnings.length > 0)
|
|
59
|
+
result.warning = warnings.join('\n');
|
|
55
60
|
return result;
|
|
56
61
|
}
|
|
62
|
+
/** Node installato da nvm, fnm, asdf, mise, n o volta: il percorso cambia a ogni versione. */
|
|
63
|
+
const VERSION_MANAGER_PATH = /[\\/](\.nvm|\.?fnm|\.asdf|\.volta[\\/]tools|n[\\/]versions|mise[\\/]installs)[\\/]/;
|
|
64
|
+
function launchdTarget() {
|
|
65
|
+
return `gui/${process.getuid?.() ?? ''}/${LABEL}`;
|
|
66
|
+
}
|
|
67
|
+
/** Rimuove il servizio; `false` se non era installato. */
|
|
68
|
+
export function uninstallAutostart() {
|
|
69
|
+
const file = autostartFile();
|
|
70
|
+
if (file === undefined || !existsSync(file))
|
|
71
|
+
return false;
|
|
72
|
+
try {
|
|
73
|
+
if (process.platform === 'darwin') {
|
|
74
|
+
execFileSync('launchctl', ['bootout', launchdTarget()], { stdio: 'ignore' });
|
|
75
|
+
}
|
|
76
|
+
else {
|
|
77
|
+
execFileSync('systemctl', ['--user', 'disable', '--now', UNIT], { stdio: 'ignore' });
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
catch {
|
|
81
|
+
/* gia' fermo */
|
|
82
|
+
}
|
|
83
|
+
rmSync(file, { force: true });
|
|
84
|
+
if (process.platform === 'linux') {
|
|
85
|
+
execFileSync('systemctl', ['--user', 'daemon-reload'], { stdio: 'ignore' });
|
|
86
|
+
}
|
|
87
|
+
return true;
|
|
88
|
+
}
|
|
89
|
+
/** Riavvia il servizio, ad esempio dopo un aggiornamento del pacchetto. */
|
|
90
|
+
export function restartAutostart() {
|
|
91
|
+
if (!isAutostartInstalled())
|
|
92
|
+
throw new Error('avvio automatico non installato');
|
|
93
|
+
if (process.platform === 'darwin') {
|
|
94
|
+
execFileSync('launchctl', ['kickstart', '-k', launchdTarget()], { stdio: 'pipe' });
|
|
95
|
+
}
|
|
96
|
+
else {
|
|
97
|
+
execFileSync('systemctl', ['--user', 'restart', UNIT], { stdio: 'pipe' });
|
|
98
|
+
}
|
|
99
|
+
}
|
|
57
100
|
function installLaunchd(file, entry) {
|
|
58
101
|
const log = join(configDir(), 'proxy.log');
|
|
59
102
|
const env = environmentOverrides();
|
package/dist/autostart.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"autostart.js","sourceRoot":"","sources":["../src/autostart.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"autostart.js","sourceRoot":"","sources":["../src/autostart.ts"],"names":[],"mappings":"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"}
|
package/dist/cli.js
CHANGED
|
@@ -1,30 +1,44 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { mkdirSync, readFileSync, writeFileSync,
|
|
3
|
-
import {
|
|
2
|
+
import { mkdirSync, readFileSync, writeFileSync, statSync } from 'node:fs';
|
|
3
|
+
import { createInterface } from 'node:readline/promises';
|
|
4
4
|
import { parseArgs } from 'node:util';
|
|
5
|
-
import { installAutostart, isAutostartInstalled } from './autostart.js';
|
|
5
|
+
import { installAutostart, isAutostartInstalled, restartAutostart, uninstallAutostart } from './autostart.js';
|
|
6
6
|
import { loadConfig } from './config.js';
|
|
7
|
-
import {
|
|
7
|
+
import { applyEditorSettings, editorSnippet, installedEditors, knownEditors, pointsToProxy, readOverride, } from './editors.js';
|
|
8
|
+
import { configDir, configFile } from './paths.js';
|
|
8
9
|
import { buildApp } from './server.js';
|
|
9
|
-
|
|
10
|
-
|
|
10
|
+
import { gitIdentity, portStatus } from './setupHelpers.js';
|
|
11
|
+
import { CLIENT_VERSION } from './version.js';
|
|
12
|
+
const DEFAULT_PORT = 8787;
|
|
11
13
|
const USAGE = `
|
|
12
14
|
Proxy locale che misura il consumo di token di GitHub Copilot e lo attribuisce
|
|
13
15
|
al progetto su cui si sta lavorando.
|
|
14
16
|
|
|
15
|
-
npx @vidiemme/copilot-proxy setup
|
|
16
|
-
npx @vidiemme/copilot-proxy start
|
|
17
|
-
npx @vidiemme/copilot-proxy doctor
|
|
17
|
+
npx @vidiemme/copilot-proxy setup configura la postazione (una volta sola)
|
|
18
|
+
npx @vidiemme/copilot-proxy start avvia il proxy
|
|
19
|
+
npx @vidiemme/copilot-proxy doctor verifica che tutto sia a posto
|
|
20
|
+
npx @vidiemme/copilot-proxy status versione, traffico misurato, eventi in attesa
|
|
21
|
+
npx @vidiemme/copilot-proxy restart riavvia il servizio (dopo un aggiornamento)
|
|
22
|
+
npx @vidiemme/copilot-proxy uninstall rimuove l'avvio automatico
|
|
23
|
+
npx @vidiemme/copilot-proxy --version
|
|
18
24
|
|
|
19
25
|
Opzioni di setup:
|
|
20
|
-
--vscode scrive
|
|
26
|
+
--vscode scrive le impostazioni di VS Code e derivati (Insiders,
|
|
27
|
+
VSCodium, Cursor, Windsurf, Antigravity) installati
|
|
21
28
|
--autostart avvia il proxy a ogni accesso, senza doverlo lanciare
|
|
29
|
+
--port <n> porta locale del proxy (default 8787; chiesta se interattivo)
|
|
30
|
+
--name <nome> nome da mostrare nella dashboard (default: git user.name)
|
|
31
|
+
--email <email> email associata (default: git user.email)
|
|
32
|
+
--anonymous non inviare nome ed email: resta solo lo pseudonimo
|
|
22
33
|
--workspace-roots <a,b> cartelle sotto cui vivono i repository (default: la home)
|
|
23
|
-
--port <n> porta locale del proxy (default 8787)
|
|
24
34
|
--collector-url <url> endpoint di raccolta, se diverso da quello aziendale
|
|
25
35
|
--salt <valore> salt degli pseudonimi, se diverso da quello aziendale
|
|
26
36
|
--upstream <url> endpoint Copilot (default https://api.githubcopilot.com)
|
|
27
|
-
--force
|
|
37
|
+
--force rifa' il setup partendo dalla configurazione esistente
|
|
38
|
+
(token compreso: per cambiare porta basta --force --port)
|
|
39
|
+
|
|
40
|
+
JetBrains, Eclipse, Xcode, Android Studio e Visual Studio non hanno un modo per
|
|
41
|
+
indirizzare Copilot al proxy: il loro traffico non viene misurato.
|
|
28
42
|
|
|
29
43
|
L'unica cosa da procurarsi e' il token di raccolta, uguale per tutta l'azienda.
|
|
30
44
|
Non si passa come opzione: finirebbe nella cronologia della shell e nella lista
|
|
@@ -117,21 +131,49 @@ function promptSecret(question) {
|
|
|
117
131
|
stdin.on('data', onData);
|
|
118
132
|
});
|
|
119
133
|
}
|
|
134
|
+
async function promptLine(question) {
|
|
135
|
+
const rl = createInterface({ input: process.stdin, output: process.stdout });
|
|
136
|
+
try {
|
|
137
|
+
return (await rl.question(question)).trim();
|
|
138
|
+
}
|
|
139
|
+
finally {
|
|
140
|
+
rl.close();
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
function validPort(value) {
|
|
144
|
+
const port = Number(value);
|
|
145
|
+
return Number.isInteger(port) && port >= 1 && port <= 65535;
|
|
146
|
+
}
|
|
147
|
+
function setOrDelete(values, key, value) {
|
|
148
|
+
if (value)
|
|
149
|
+
values[key] = value;
|
|
150
|
+
else
|
|
151
|
+
delete values[key];
|
|
152
|
+
}
|
|
120
153
|
async function commandSetup(flags) {
|
|
121
154
|
const existing = readConfigFile();
|
|
122
|
-
|
|
123
|
-
|
|
155
|
+
const reconfigure = Object.keys(existing).length > 0;
|
|
156
|
+
if (reconfigure && flags.force !== true) {
|
|
157
|
+
console.error(`Esiste gia' ${configFile()}. Rilancia con --force per modificarlo.`);
|
|
124
158
|
return 1;
|
|
125
159
|
}
|
|
126
|
-
const
|
|
127
|
-
|
|
160
|
+
const interactive = process.stdin.isTTY === true;
|
|
161
|
+
// Con --force si parte dalla configurazione esistente: cambiare porta non deve costare il token.
|
|
162
|
+
const values = {};
|
|
163
|
+
for (const [key, value] of Object.entries(existing))
|
|
164
|
+
if (value !== undefined)
|
|
165
|
+
values[key] = value;
|
|
166
|
+
const token = process.env.COLLECTOR_TOKEN?.trim() ||
|
|
167
|
+
values.COLLECTOR_TOKEN ||
|
|
168
|
+
(await promptSecret('Token di raccolta: ')).trim();
|
|
169
|
+
if (token.length === 0) {
|
|
128
170
|
console.error('Token vuoto.');
|
|
129
171
|
return 1;
|
|
130
172
|
}
|
|
131
173
|
// Si scrive solo cio' che si discosta dai default del pacchetto: un file
|
|
132
174
|
// corto e' un file che si capisce, e i default restano aggiornabili con una
|
|
133
175
|
// nuova versione invece che postazione per postazione.
|
|
134
|
-
|
|
176
|
+
values.COLLECTOR_TOKEN = token;
|
|
135
177
|
const collectorUrl = flags['collector-url'];
|
|
136
178
|
if (collectorUrl)
|
|
137
179
|
values.COLLECTOR_URL = collectorUrl;
|
|
@@ -141,10 +183,35 @@ async function commandSetup(flags) {
|
|
|
141
183
|
const workspaceRoots = flags['workspace-roots'];
|
|
142
184
|
if (workspaceRoots)
|
|
143
185
|
values.WORKSPACE_ROOTS = workspaceRoots;
|
|
144
|
-
if (flags.port)
|
|
145
|
-
values.PORT = String(flags.port);
|
|
146
186
|
if (flags.upstream)
|
|
147
187
|
values.UPSTREAM_BASE_URL = String(flags.upstream);
|
|
188
|
+
let port = flags.port ? String(flags.port) : values.PORT;
|
|
189
|
+
if (!port && interactive) {
|
|
190
|
+
port = (await promptLine(`Porta locale del proxy [${DEFAULT_PORT}]: `)) || undefined;
|
|
191
|
+
}
|
|
192
|
+
if (port && !validPort(port)) {
|
|
193
|
+
console.error(`Porta non valida: ${port}. Serve un intero fra 1 e 65535.`);
|
|
194
|
+
return 1;
|
|
195
|
+
}
|
|
196
|
+
setOrDelete(values, 'PORT', port && Number(port) !== DEFAULT_PORT ? String(Number(port)) : undefined);
|
|
197
|
+
if (flags.anonymous === true) {
|
|
198
|
+
setOrDelete(values, 'DEVELOPER_NAME', undefined);
|
|
199
|
+
setOrDelete(values, 'DEVELOPER_EMAIL', undefined);
|
|
200
|
+
}
|
|
201
|
+
else {
|
|
202
|
+
const git = gitIdentity();
|
|
203
|
+
let name = flags.name ?? values.DEVELOPER_NAME ?? git.name;
|
|
204
|
+
const email = flags.email ?? values.DEVELOPER_EMAIL ?? git.email;
|
|
205
|
+
if (interactive && flags.name === undefined) {
|
|
206
|
+
const answer = await promptLine(`Nome da mostrare nella dashboard [${name ?? 'nessuno'}] ("-" per restare anonimo): `);
|
|
207
|
+
if (answer === '-')
|
|
208
|
+
name = undefined;
|
|
209
|
+
else if (answer)
|
|
210
|
+
name = answer;
|
|
211
|
+
}
|
|
212
|
+
setOrDelete(values, 'DEVELOPER_NAME', name?.slice(0, 100));
|
|
213
|
+
setOrDelete(values, 'DEVELOPER_EMAIL', name ? email?.slice(0, 200) : undefined);
|
|
214
|
+
}
|
|
148
215
|
// Meglio scoprire ora che la configurazione non regge, non al primo avvio.
|
|
149
216
|
let config;
|
|
150
217
|
try {
|
|
@@ -154,14 +221,22 @@ async function commandSetup(flags) {
|
|
|
154
221
|
console.error(`Configurazione non valida: ${error.message}`);
|
|
155
222
|
return 1;
|
|
156
223
|
}
|
|
224
|
+
if ((await portStatus(config.port, config.host)) === 'busy') {
|
|
225
|
+
console.error(`La porta ${config.port} e' occupata da un altro programma. Scegline un'altra con --port <n>.`);
|
|
226
|
+
return 1;
|
|
227
|
+
}
|
|
157
228
|
writeConfigFile(values);
|
|
158
229
|
console.log(`Scritto ${configFile()}`);
|
|
230
|
+
console.log(`Proxy su http://127.0.0.1:${config.port}`);
|
|
159
231
|
console.log(`Raccolta verso ${config.collectorUrl}`);
|
|
160
232
|
console.log(`Progetti cercati sotto ${config.workspaceRoots.join(', ')}`);
|
|
233
|
+
console.log(config.developerName
|
|
234
|
+
? `Nella dashboard comparirai come ${config.developerName}`
|
|
235
|
+
: 'Nella dashboard comparirai con uno pseudonimo');
|
|
161
236
|
if (flags.vscode === true)
|
|
162
|
-
|
|
237
|
+
applyEditors(config.port);
|
|
163
238
|
else
|
|
164
|
-
|
|
239
|
+
printEditorSettings(config.port);
|
|
165
240
|
if (flags.autostart === true) {
|
|
166
241
|
try {
|
|
167
242
|
const service = installAutostart();
|
|
@@ -180,37 +255,25 @@ async function commandSetup(flags) {
|
|
|
180
255
|
console.log('Per non doverlo fare ogni volta, rilancia il setup con --autostart');
|
|
181
256
|
return 0;
|
|
182
257
|
}
|
|
183
|
-
function
|
|
184
|
-
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
console.log('\nAggiungi alle impostazioni utente di VS Code (Preferences: Open User Settings (JSON)):\n' +
|
|
188
|
-
`${JSON.stringify(vsCodeSnippet(port), null, 2)}\n` +
|
|
189
|
-
'Oppure rilancia il setup con --vscode per farlo scrivere al comando.');
|
|
258
|
+
function printEditorSettings(port, editor) {
|
|
259
|
+
console.log(`\nAggiungi alle impostazioni utente di ${editor?.name ?? 'VS Code (e dei suoi derivati)'} (Preferences: Open User Settings (JSON)):\n` +
|
|
260
|
+
`${JSON.stringify(editorSnippet(port), null, 2)}\n` +
|
|
261
|
+
(editor ? '' : 'Oppure rilancia il setup con --vscode per farlo scrivere al comando.'));
|
|
190
262
|
}
|
|
191
|
-
function
|
|
192
|
-
const
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
const
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
}
|
|
202
|
-
catch (error) {
|
|
203
|
-
exists = error.code !== 'ENOENT';
|
|
204
|
-
if (exists) {
|
|
205
|
-
console.log(`\nNon riesco a modificare ${file} senza rischiare di rovinarlo (contiene commenti o non e' JSON valido).`);
|
|
206
|
-
printVsCodeSettings(port);
|
|
207
|
-
return;
|
|
263
|
+
function applyEditors(port) {
|
|
264
|
+
const found = installedEditors();
|
|
265
|
+
// Nessun editor ancora aperto: si prepara VS Code, che e' il caso piu' comune.
|
|
266
|
+
const targets = found.length > 0 ? found : knownEditors().slice(0, 1);
|
|
267
|
+
for (const editor of targets) {
|
|
268
|
+
const result = applyEditorSettings(editor, port);
|
|
269
|
+
if (result.status === 'unparsable') {
|
|
270
|
+
console.log(`\n${editor.name}: non riesco a modificare ${editor.settingsFile} senza rischiare di rovinarlo (contiene commenti o non e' JSON valido).`);
|
|
271
|
+
printEditorSettings(port, editor);
|
|
272
|
+
continue;
|
|
208
273
|
}
|
|
274
|
+
console.log(`${editor.name}: aggiornato ${editor.settingsFile}${result.backup ? ` (backup in ${result.backup})` : ''}`);
|
|
209
275
|
}
|
|
210
|
-
|
|
211
|
-
writeFileSync(file, `${JSON.stringify({ ...current, ...vsCodeSnippet(port) }, null, 2)}\n`);
|
|
212
|
-
console.log(`Aggiornato ${file}${exists ? ` (backup in ${file}.bak)` : ''}`);
|
|
213
|
-
console.log("Riavvia VS Code perche' le impostazioni abbiano effetto.");
|
|
276
|
+
console.log("Riavvia gli editor perche' le impostazioni abbiano effetto.");
|
|
214
277
|
}
|
|
215
278
|
async function commandStart(flags) {
|
|
216
279
|
const overrides = {};
|
|
@@ -246,7 +309,10 @@ async function commandStart(flags) {
|
|
|
246
309
|
async function commandDoctor() {
|
|
247
310
|
const results = [];
|
|
248
311
|
const check = (ok, message) => {
|
|
249
|
-
results.push([ok, message]);
|
|
312
|
+
results.push([ok ? 'ok' : 'fail', message]);
|
|
313
|
+
};
|
|
314
|
+
const warn = (message) => {
|
|
315
|
+
results.push(['warn', message]);
|
|
250
316
|
};
|
|
251
317
|
let config;
|
|
252
318
|
try {
|
|
@@ -291,46 +357,127 @@ async function commandDoctor() {
|
|
|
291
357
|
catch (error) {
|
|
292
358
|
check(false, `servizio di raccolta irraggiungibile: ${error.message}`);
|
|
293
359
|
}
|
|
294
|
-
//
|
|
295
|
-
//
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
const
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
: "VS Code non e' configurato per passare dal proxy");
|
|
360
|
+
// Basta un editor che punti al proxy; gli altri sono solo segnalati, perche'
|
|
361
|
+
// non tutti usano Copilot in ogni editor installato.
|
|
362
|
+
const editors = installedEditors();
|
|
363
|
+
const expected = `http://127.0.0.1:${config.port}`;
|
|
364
|
+
const configured = [];
|
|
365
|
+
const notConfigured = [];
|
|
366
|
+
for (const editor of editors) {
|
|
367
|
+
const value = readOverride(editor);
|
|
368
|
+
if (value && pointsToProxy(value, config.port))
|
|
369
|
+
configured.push(editor.name);
|
|
370
|
+
else
|
|
371
|
+
notConfigured.push(value ? `${editor.name} (punta a ${value}, atteso ${expected})` : editor.name);
|
|
307
372
|
}
|
|
308
|
-
|
|
309
|
-
check(
|
|
373
|
+
if (configured.length > 0) {
|
|
374
|
+
check(true, `passano dal proxy: ${configured.join(', ')}`);
|
|
375
|
+
if (notConfigured.length > 0)
|
|
376
|
+
warn(`non passano dal proxy: ${notConfigured.join(', ')}`);
|
|
377
|
+
}
|
|
378
|
+
else {
|
|
379
|
+
check(false, editors.length > 0
|
|
380
|
+
? `nessun editor passa dal proxy (${notConfigured.join(', ')}): rilancia "setup --vscode --force"`
|
|
381
|
+
: 'nessun editor della famiglia VS Code trovato su questa macchina');
|
|
310
382
|
}
|
|
311
383
|
const pending = spoolSize(config.spoolPath);
|
|
312
384
|
check(pending === 0, pending === 0 ? 'nessun evento in attesa di consegna' : `${pending} byte di eventi in attesa nello spool`);
|
|
313
385
|
// L'avvio automatico interessa solo se il proxy non sta gia' girando: chi
|
|
314
386
|
// preferisce lanciarlo a mano non deve vedere un errore.
|
|
315
|
-
|
|
387
|
+
const health = await readHealth(config.port);
|
|
388
|
+
const proxyUp = health !== undefined;
|
|
389
|
+
check(proxyUp, proxyUp
|
|
390
|
+
? `proxy ${health.version ?? ''} in ascolto${isAutostartInstalled() ? ', con avvio automatico' : ''}`
|
|
391
|
+
: `nessun proxy in ascolto sulla porta ${config.port}: attivalo per sempre con "setup --autostart --force", o una volta sola con "start"`);
|
|
392
|
+
if (health) {
|
|
393
|
+
if (health.version && health.version !== CLIENT_VERSION) {
|
|
394
|
+
warn(`il proxy in esecuzione e' la ${health.version}, questo comando la ${CLIENT_VERSION}: lancia "restart"`);
|
|
395
|
+
}
|
|
396
|
+
// L'impostazione di VS Code e' di debug: un aggiornamento dell'estensione
|
|
397
|
+
// puo' ignorarla senza avvisare, e lo si vede solo dall'assenza di traffico.
|
|
398
|
+
const silence = trafficSilence(health);
|
|
399
|
+
if (silence)
|
|
400
|
+
warn(silence);
|
|
401
|
+
}
|
|
402
|
+
report(results);
|
|
403
|
+
return results.every(([level]) => level !== 'fail') ? 0 : 1;
|
|
404
|
+
}
|
|
405
|
+
async function readHealth(port) {
|
|
316
406
|
try {
|
|
317
|
-
const
|
|
407
|
+
const response = await fetch(`http://127.0.0.1:${port}/_health`, {
|
|
318
408
|
signal: AbortSignal.timeout(2000),
|
|
319
409
|
});
|
|
320
|
-
|
|
410
|
+
return response.ok ? (await response.json()) : undefined;
|
|
321
411
|
}
|
|
322
412
|
catch {
|
|
323
|
-
|
|
413
|
+
return undefined;
|
|
324
414
|
}
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
415
|
+
}
|
|
416
|
+
const HOUR_MS = 60 * 60 * 1000;
|
|
417
|
+
function trafficSilence(health, now = Date.now()) {
|
|
418
|
+
const last = health.usage?.lastEventAt;
|
|
419
|
+
if (last) {
|
|
420
|
+
const hours = Math.floor((now - Date.parse(last)) / HOUR_MS);
|
|
421
|
+
return hours >= 24 ? `nessun traffico Copilot misurato nelle ultime ${hours} ore` : undefined;
|
|
422
|
+
}
|
|
423
|
+
const uptime = health.startedAt ? now - Date.parse(health.startedAt) : 0;
|
|
424
|
+
return uptime >= HOUR_MS
|
|
425
|
+
? "nessun traffico Copilot misurato dall'avvio del proxy: controlla che l'editor passi davvero di qui"
|
|
426
|
+
: undefined;
|
|
427
|
+
}
|
|
428
|
+
async function commandStatus() {
|
|
429
|
+
let config;
|
|
430
|
+
try {
|
|
431
|
+
config = loadConfig(mergedSource({}));
|
|
432
|
+
}
|
|
433
|
+
catch (error) {
|
|
434
|
+
console.error(error.message);
|
|
435
|
+
return 1;
|
|
436
|
+
}
|
|
437
|
+
const health = await readHealth(config.port);
|
|
438
|
+
console.log(`copilot-proxy ${CLIENT_VERSION}`);
|
|
439
|
+
console.log(`nome in dashboard: ${config.developerName ?? 'nessuno (pseudonimo)'}`);
|
|
440
|
+
console.log(`avvio automatico: ${isAutostartInstalled() ? 'attivo' : 'non installato'}`);
|
|
441
|
+
if (!health) {
|
|
442
|
+
console.log(`proxy: non in ascolto sulla porta ${config.port}`);
|
|
443
|
+
return 1;
|
|
444
|
+
}
|
|
445
|
+
const usage = health.usage;
|
|
446
|
+
console.log(`proxy: ${health.version ?? '?'} in ascolto dal ${health.startedAt ?? '?'}`);
|
|
447
|
+
if (usage) {
|
|
448
|
+
console.log(`eventi misurati: ${usage.recorded}, consegnati: ${usage.delivered}, scartati: ${usage.dropped}`);
|
|
449
|
+
console.log(`ultimo evento: ${usage.lastEventAt ?? 'nessuno'}`);
|
|
450
|
+
console.log(`ultima consegna: ${usage.lastDeliveryAt ?? 'nessuna'}`);
|
|
451
|
+
if (usage.lastError)
|
|
452
|
+
console.log(`ultimo errore del collector: ${usage.lastError}`);
|
|
453
|
+
}
|
|
454
|
+
console.log(`spool: ${health.spoolBytes ?? 0} byte in attesa`);
|
|
455
|
+
return 0;
|
|
456
|
+
}
|
|
457
|
+
function commandRestart() {
|
|
458
|
+
try {
|
|
459
|
+
restartAutostart();
|
|
460
|
+
}
|
|
461
|
+
catch (error) {
|
|
462
|
+
console.error(`Riavvio non riuscito: ${error.message}`);
|
|
463
|
+
return 1;
|
|
464
|
+
}
|
|
465
|
+
console.log('Proxy riavviato.');
|
|
466
|
+
return 0;
|
|
467
|
+
}
|
|
468
|
+
function commandUninstall() {
|
|
469
|
+
if (!uninstallAutostart()) {
|
|
470
|
+
console.log('Avvio automatico non installato: niente da rimuovere.');
|
|
471
|
+
return 0;
|
|
472
|
+
}
|
|
473
|
+
console.log(`Avvio automatico rimosso. Configurazione lasciata in ${configFile()}.`);
|
|
474
|
+
console.log("Ricordati di togliere le impostazioni del proxy da VS Code, altrimenti Copilot non raggiunge piu' l'upstream.");
|
|
475
|
+
return 0;
|
|
330
476
|
}
|
|
331
477
|
function report(results) {
|
|
332
|
-
|
|
333
|
-
|
|
478
|
+
const labels = { ok: 'OK ', warn: 'WARN', fail: 'FAIL' };
|
|
479
|
+
for (const [level, message] of results)
|
|
480
|
+
console.log(`${labels[level]} ${message}`);
|
|
334
481
|
}
|
|
335
482
|
function existsDir(path) {
|
|
336
483
|
try {
|
|
@@ -359,13 +506,21 @@ async function main() {
|
|
|
359
506
|
port: { type: 'string' },
|
|
360
507
|
upstream: { type: 'string' },
|
|
361
508
|
'log-level': { type: 'string' },
|
|
509
|
+
name: { type: 'string' },
|
|
510
|
+
email: { type: 'string' },
|
|
511
|
+
anonymous: { type: 'boolean' },
|
|
362
512
|
vscode: { type: 'boolean' },
|
|
363
513
|
autostart: { type: 'boolean' },
|
|
364
514
|
force: { type: 'boolean' },
|
|
365
515
|
help: { type: 'boolean', short: 'h' },
|
|
516
|
+
version: { type: 'boolean', short: 'v' },
|
|
366
517
|
},
|
|
367
518
|
});
|
|
368
519
|
const command = positionals[0] ?? 'start';
|
|
520
|
+
if (values.version === true || command === 'version') {
|
|
521
|
+
console.log(CLIENT_VERSION);
|
|
522
|
+
return;
|
|
523
|
+
}
|
|
369
524
|
if (values.help === true || command === 'help') {
|
|
370
525
|
console.log(USAGE);
|
|
371
526
|
return;
|
|
@@ -380,6 +535,15 @@ async function main() {
|
|
|
380
535
|
case 'doctor':
|
|
381
536
|
process.exitCode = await commandDoctor();
|
|
382
537
|
return;
|
|
538
|
+
case 'status':
|
|
539
|
+
process.exitCode = await commandStatus();
|
|
540
|
+
return;
|
|
541
|
+
case 'restart':
|
|
542
|
+
process.exitCode = commandRestart();
|
|
543
|
+
return;
|
|
544
|
+
case 'uninstall':
|
|
545
|
+
process.exitCode = commandUninstall();
|
|
546
|
+
return;
|
|
383
547
|
default:
|
|
384
548
|
console.error(`Comando sconosciuto: ${command}\n`);
|
|
385
549
|
console.log(USAGE);
|