@vidiemme/copilot-proxy 0.1.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/LICENSE +21 -0
- package/README.md +57 -0
- package/dist/attribution.d.ts +34 -0
- package/dist/attribution.js +118 -0
- package/dist/attribution.js.map +1 -0
- package/dist/autostart.d.ts +10 -0
- package/dist/autostart.js +119 -0
- package/dist/autostart.js.map +1 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +393 -0
- package/dist/cli.js.map +1 -0
- package/dist/collector/forwarder.d.ts +44 -0
- package/dist/collector/forwarder.js +203 -0
- package/dist/collector/forwarder.js.map +1 -0
- package/dist/config.d.ts +44 -0
- package/dist/config.js +105 -0
- package/dist/config.js.map +1 -0
- package/dist/defaults.d.ts +33 -0
- package/dist/defaults.js +35 -0
- package/dist/defaults.js.map +1 -0
- package/dist/gitRepository.d.ts +21 -0
- package/dist/gitRepository.js +147 -0
- package/dist/gitRepository.js.map +1 -0
- package/dist/paths.d.ts +12 -0
- package/dist/paths.js +39 -0
- package/dist/paths.js.map +1 -0
- package/dist/projectDetector.d.ts +48 -0
- package/dist/projectDetector.js +130 -0
- package/dist/projectDetector.js.map +1 -0
- package/dist/proxy/handler.d.ts +5 -0
- package/dist/proxy/handler.js +149 -0
- package/dist/proxy/handler.js.map +1 -0
- package/dist/proxy/headers.d.ts +6 -0
- package/dist/proxy/headers.js +52 -0
- package/dist/proxy/headers.js.map +1 -0
- package/dist/proxy/inspectRequest.d.ts +18 -0
- package/dist/proxy/inspectRequest.js +41 -0
- package/dist/proxy/inspectRequest.js.map +1 -0
- package/dist/server.d.ts +7 -0
- package/dist/server.js +66 -0
- package/dist/server.js.map +1 -0
- package/dist/usage/collector.d.ts +25 -0
- package/dist/usage/collector.js +63 -0
- package/dist/usage/collector.js.map +1 -0
- package/dist/usage/parseAnthropic.d.ts +23 -0
- package/dist/usage/parseAnthropic.js +83 -0
- package/dist/usage/parseAnthropic.js.map +1 -0
- package/dist/usage/parseOpenAI.d.ts +24 -0
- package/dist/usage/parseOpenAI.js +72 -0
- package/dist/usage/parseOpenAI.js.map +1 -0
- package/dist/usage/sse.d.ts +17 -0
- package/dist/usage/sse.js +59 -0
- package/dist/usage/sse.js.map +1 -0
- package/dist/usage/types.d.ts +23 -0
- package/dist/usage/types.js +19 -0
- package/dist/usage/types.js.map +1 -0
- package/package.json +50 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"forwarder.js","sourceRoot":"","sources":["../../src/collector/forwarder.ts"],"names":[],"mappings":"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"}
|
package/dist/config.d.ts
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/** Sorgente dei valori di configurazione: `process.env` o una mappa equivalente. */
|
|
2
|
+
export type ConfigSource = Record<string, string | undefined>;
|
|
3
|
+
export interface AttributionMapping {
|
|
4
|
+
projectId?: string;
|
|
5
|
+
developerId?: string;
|
|
6
|
+
}
|
|
7
|
+
export interface ClientConfig {
|
|
8
|
+
port: number;
|
|
9
|
+
host: string;
|
|
10
|
+
logLevel: string;
|
|
11
|
+
upstreamBaseUrl: string;
|
|
12
|
+
upstreamAuthToken: string | undefined;
|
|
13
|
+
tlsKeyPath: string | undefined;
|
|
14
|
+
tlsCertPath: string | undefined;
|
|
15
|
+
/** Endpoint di raccolta, es. `https://copilot-collector.swarm.vidiemme.it/v1/usage`. */
|
|
16
|
+
collectorUrl: string;
|
|
17
|
+
collectorToken: string;
|
|
18
|
+
collectorTimeoutMs: number;
|
|
19
|
+
/** File su cui parcheggiare gli eventi quando il servizio non risponde. */
|
|
20
|
+
spoolPath: string;
|
|
21
|
+
projectHeader: string;
|
|
22
|
+
unassignedProject: string;
|
|
23
|
+
workspaceRoots: string[];
|
|
24
|
+
projectMarkers: string[];
|
|
25
|
+
projectStickyTtlMs: number;
|
|
26
|
+
attributionTokens: Record<string, AttributionMapping>;
|
|
27
|
+
developerIdSalt: string;
|
|
28
|
+
flushIntervalMs: number;
|
|
29
|
+
flushMaxBatch: number;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Costruisce la configurazione da una sorgente di chiavi.
|
|
33
|
+
*
|
|
34
|
+
* La sorgente e' iniettabile perche' il comando `start` sovrappone piu' livelli
|
|
35
|
+
* — file di configurazione utente, ambiente, opzioni della riga di comando —
|
|
36
|
+
* prima di arrivare qui.
|
|
37
|
+
*/
|
|
38
|
+
export declare function loadConfig(source?: ConfigSource): ClientConfig;
|
|
39
|
+
/**
|
|
40
|
+
* Pseudonimo stabile e non invertibile derivato da un segreto del client.
|
|
41
|
+
* Serve a distinguere i developer senza conservare credenziali.
|
|
42
|
+
*/
|
|
43
|
+
export declare function pseudonymize(secret: string, salt: string): string;
|
|
44
|
+
export declare function stableIdentity(token: string): string;
|
package/dist/config.js
ADDED
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import { createHash } from 'node:crypto';
|
|
2
|
+
import { DEFAULT_COLLECTOR_URL, DEFAULT_DEVELOPER_ID_SALT, defaultWorkspaceRoots } from './defaults.js';
|
|
3
|
+
import { defaultSpoolPath } from './paths.js';
|
|
4
|
+
function parseAttributionTokens(raw) {
|
|
5
|
+
try {
|
|
6
|
+
const parsed = JSON.parse(raw);
|
|
7
|
+
if (typeof parsed !== 'object' || parsed === null)
|
|
8
|
+
return {};
|
|
9
|
+
return parsed;
|
|
10
|
+
}
|
|
11
|
+
catch {
|
|
12
|
+
throw new Error("ATTRIBUTION_TOKENS non e' un JSON valido");
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Costruisce la configurazione da una sorgente di chiavi.
|
|
17
|
+
*
|
|
18
|
+
* La sorgente e' iniettabile perche' il comando `start` sovrappone piu' livelli
|
|
19
|
+
* — file di configurazione utente, ambiente, opzioni della riga di comando —
|
|
20
|
+
* prima di arrivare qui.
|
|
21
|
+
*/
|
|
22
|
+
export function loadConfig(source = process.env) {
|
|
23
|
+
const read = (name) => source[name]?.trim() || undefined;
|
|
24
|
+
const required = (name) => {
|
|
25
|
+
const value = read(name);
|
|
26
|
+
if (!value)
|
|
27
|
+
throw new Error(`Configurazione mancante: ${name}`);
|
|
28
|
+
return value;
|
|
29
|
+
};
|
|
30
|
+
const optional = (name, fallback) => read(name) ?? fallback;
|
|
31
|
+
const intOption = (name, fallback) => {
|
|
32
|
+
const parsed = Number.parseInt(optional(name, String(fallback)), 10);
|
|
33
|
+
return Number.isFinite(parsed) ? parsed : fallback;
|
|
34
|
+
};
|
|
35
|
+
const listOption = (name, fallback) => optional(name, fallback)
|
|
36
|
+
.split(',')
|
|
37
|
+
.map((item) => item.trim())
|
|
38
|
+
.filter((item) => item.length > 0);
|
|
39
|
+
const developerIdSalt = optional('DEVELOPER_ID_SALT', DEFAULT_DEVELOPER_ID_SALT);
|
|
40
|
+
if (developerIdSalt.length === 0 || developerIdSalt === 'change-me') {
|
|
41
|
+
throw new Error('DEVELOPER_ID_SALT deve essere impostato con un valore casuale: protegge lo pseudonimo del developer dal reverse lookup. Deve essere lo stesso su tutte le postazioni, altrimenti la stessa persona risulta come piu\' developer diversi');
|
|
42
|
+
}
|
|
43
|
+
const collectorUrl = optional('COLLECTOR_URL', DEFAULT_COLLECTOR_URL);
|
|
44
|
+
if (collectorUrl.startsWith('http://') &&
|
|
45
|
+
!/^https?:\/\/(localhost|127\.0\.0\.1)/.test(collectorUrl)) {
|
|
46
|
+
throw new Error('COLLECTOR_URL deve usare https: in chiaro il token di ingest sarebbe leggibile sulla rete');
|
|
47
|
+
}
|
|
48
|
+
return {
|
|
49
|
+
port: intOption('PORT', 8787),
|
|
50
|
+
host: optional('HOST', '127.0.0.1'),
|
|
51
|
+
logLevel: optional('LOG_LEVEL', 'info'),
|
|
52
|
+
upstreamBaseUrl: optional('UPSTREAM_BASE_URL', 'https://api.githubcopilot.com').replace(/\/+$/, ''),
|
|
53
|
+
upstreamAuthToken: read('UPSTREAM_AUTH_TOKEN'),
|
|
54
|
+
tlsKeyPath: read('TLS_KEY_PATH'),
|
|
55
|
+
tlsCertPath: read('TLS_CERT_PATH'),
|
|
56
|
+
collectorUrl,
|
|
57
|
+
collectorToken: required('COLLECTOR_TOKEN'),
|
|
58
|
+
collectorTimeoutMs: intOption('COLLECTOR_TIMEOUT_MS', 10_000),
|
|
59
|
+
spoolPath: optional('SPOOL_PATH', defaultSpoolPath()),
|
|
60
|
+
projectHeader: optional('PROJECT_HEADER', 'x-project-id').toLowerCase(),
|
|
61
|
+
unassignedProject: optional('UNASSIGNED_PROJECT', 'unassigned'),
|
|
62
|
+
workspaceRoots: listOption('WORKSPACE_ROOTS', defaultWorkspaceRoots()),
|
|
63
|
+
projectMarkers: listOption('PROJECT_MARKERS', '.git,.hg,.svn'),
|
|
64
|
+
projectStickyTtlMs: intOption('PROJECT_STICKY_TTL_MS', 30 * 60_000),
|
|
65
|
+
attributionTokens: parseAttributionTokens(optional('ATTRIBUTION_TOKENS', '{}')),
|
|
66
|
+
developerIdSalt,
|
|
67
|
+
flushIntervalMs: intOption('FLUSH_INTERVAL_MS', 5000),
|
|
68
|
+
flushMaxBatch: intOption('FLUSH_MAX_BATCH', 100),
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Pseudonimo stabile e non invertibile derivato da un segreto del client.
|
|
73
|
+
* Serve a distinguere i developer senza conservare credenziali.
|
|
74
|
+
*/
|
|
75
|
+
export function pseudonymize(secret, salt) {
|
|
76
|
+
return createHash('sha256').update(`${salt}:${secret}`).digest('hex').slice(0, 16);
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Estrae dalla credenziale la porzione che identifica la persona.
|
|
80
|
+
*
|
|
81
|
+
* Il token Copilot e' una lista di coppie `chiave=valore` separate da `;` e
|
|
82
|
+
* viene rinnovato di continuo: campi come `exp` cambiano a ogni rotazione. Fare
|
|
83
|
+
* l'hash del token intero produrrebbe un developer diverso ogni mezz'ora,
|
|
84
|
+
* frammentando qualsiasi analisi nel tempo. Si isolano quindi i soli campi
|
|
85
|
+
* stabili, con fallback al token completo per credenziali di altro formato.
|
|
86
|
+
*/
|
|
87
|
+
const STABLE_TOKEN_FIELDS = ['u', 'tid', 'oid', 'sid'];
|
|
88
|
+
export function stableIdentity(token) {
|
|
89
|
+
if (!token.includes('=') || !token.includes(';'))
|
|
90
|
+
return token;
|
|
91
|
+
const fields = new Map();
|
|
92
|
+
for (const pair of token.split(';')) {
|
|
93
|
+
const separator = pair.indexOf('=');
|
|
94
|
+
if (separator <= 0)
|
|
95
|
+
continue;
|
|
96
|
+
fields.set(pair.slice(0, separator).trim().toLowerCase(), pair.slice(separator + 1).trim());
|
|
97
|
+
}
|
|
98
|
+
for (const key of STABLE_TOKEN_FIELDS) {
|
|
99
|
+
const value = fields.get(key);
|
|
100
|
+
if (value)
|
|
101
|
+
return `${key}:${value}`;
|
|
102
|
+
}
|
|
103
|
+
return token;
|
|
104
|
+
}
|
|
105
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Valori aziendali committati nel pacchetto.
|
|
3
|
+
*
|
|
4
|
+
* Il proxy viene installato con `npx` da chi non conosce — ne' deve conoscere —
|
|
5
|
+
* l'infrastruttura di raccolta: se questi valori fossero da passare a mano, ogni
|
|
6
|
+
* postazione sarebbe un'occasione per sbagliarli. Stanno qui, non in un `.env`,
|
|
7
|
+
* perche' un file di ambiente sulla macchina del developer e' esattamente cio'
|
|
8
|
+
* che si vuole evitare. Restano sovrascrivibili da opzione o variabile
|
|
9
|
+
* d'ambiente per lo sviluppo del proxy stesso.
|
|
10
|
+
*/
|
|
11
|
+
/** Endpoint di ingest del servizio di raccolta. */
|
|
12
|
+
export declare const DEFAULT_COLLECTOR_URL = "https://copilot-collector.swarm.vidiemme.it/v1/usage";
|
|
13
|
+
/**
|
|
14
|
+
* Salt degli pseudonimi developer.
|
|
15
|
+
*
|
|
16
|
+
* Deve essere identico su tutte le postazioni: e' cio' che rende la stessa
|
|
17
|
+
* persona confrontabile fra macchine e nel tempo. Cambiarlo spezza la
|
|
18
|
+
* continuita' dello storico, perche' da quel momento la stessa persona compare
|
|
19
|
+
* con un id diverso.
|
|
20
|
+
*
|
|
21
|
+
* Sta nel sorgente e non fra i segreti: non protegge un accesso, rende solo non
|
|
22
|
+
* banale risalire dall'id alla credenziale da cui e' derivato. Chi ha il
|
|
23
|
+
* database conosce comunque le persone che ci lavorano.
|
|
24
|
+
*/
|
|
25
|
+
export declare const DEFAULT_DEVELOPER_ID_SALT = "44e342883d198dd2744dd9b485dce715f871e7c2c41dc8aa9ecb64b02b20a015";
|
|
26
|
+
/**
|
|
27
|
+
* Cartelle sotto cui cercare i repository.
|
|
28
|
+
*
|
|
29
|
+
* La home e' il default che funziona ovunque senza chiedere nulla: delimita i
|
|
30
|
+
* path che il proxy puo' risolvere, e nessuno tiene i propri repository fuori
|
|
31
|
+
* dalla propria home. Chi vuole restringere il campo passa `--workspace-roots`.
|
|
32
|
+
*/
|
|
33
|
+
export declare const defaultWorkspaceRoots: () => string;
|
package/dist/defaults.js
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { homedir } from 'node:os';
|
|
2
|
+
/**
|
|
3
|
+
* Valori aziendali committati nel pacchetto.
|
|
4
|
+
*
|
|
5
|
+
* Il proxy viene installato con `npx` da chi non conosce — ne' deve conoscere —
|
|
6
|
+
* l'infrastruttura di raccolta: se questi valori fossero da passare a mano, ogni
|
|
7
|
+
* postazione sarebbe un'occasione per sbagliarli. Stanno qui, non in un `.env`,
|
|
8
|
+
* perche' un file di ambiente sulla macchina del developer e' esattamente cio'
|
|
9
|
+
* che si vuole evitare. Restano sovrascrivibili da opzione o variabile
|
|
10
|
+
* d'ambiente per lo sviluppo del proxy stesso.
|
|
11
|
+
*/
|
|
12
|
+
/** Endpoint di ingest del servizio di raccolta. */
|
|
13
|
+
export const DEFAULT_COLLECTOR_URL = 'https://copilot-collector.swarm.vidiemme.it/v1/usage';
|
|
14
|
+
/**
|
|
15
|
+
* Salt degli pseudonimi developer.
|
|
16
|
+
*
|
|
17
|
+
* Deve essere identico su tutte le postazioni: e' cio' che rende la stessa
|
|
18
|
+
* persona confrontabile fra macchine e nel tempo. Cambiarlo spezza la
|
|
19
|
+
* continuita' dello storico, perche' da quel momento la stessa persona compare
|
|
20
|
+
* con un id diverso.
|
|
21
|
+
*
|
|
22
|
+
* Sta nel sorgente e non fra i segreti: non protegge un accesso, rende solo non
|
|
23
|
+
* banale risalire dall'id alla credenziale da cui e' derivato. Chi ha il
|
|
24
|
+
* database conosce comunque le persone che ci lavorano.
|
|
25
|
+
*/
|
|
26
|
+
export const DEFAULT_DEVELOPER_ID_SALT = '44e342883d198dd2744dd9b485dce715f871e7c2c41dc8aa9ecb64b02b20a015';
|
|
27
|
+
/**
|
|
28
|
+
* Cartelle sotto cui cercare i repository.
|
|
29
|
+
*
|
|
30
|
+
* La home e' il default che funziona ovunque senza chiedere nulla: delimita i
|
|
31
|
+
* path che il proxy puo' risolvere, e nessuno tiene i propri repository fuori
|
|
32
|
+
* dalla propria home. Chi vuole restringere il campo passa `--workspace-roots`.
|
|
33
|
+
*/
|
|
34
|
+
export const defaultWorkspaceRoots = () => homedir();
|
|
35
|
+
//# sourceMappingURL=defaults.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"defaults.js","sourceRoot":"","sources":["../src/defaults.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAElC;;;;;;;;;GASG;AAEH,mDAAmD;AACnD,MAAM,CAAC,MAAM,qBAAqB,GAAG,sDAAsD,CAAC;AAE5F;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,MAAM,yBAAyB,GACpC,kEAAkE,CAAC;AAErE;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,qBAAqB,GAAG,GAAW,EAAE,CAAC,OAAO,EAAE,CAAC"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { RepositoryIdentity } from '@vidiemme/copilot-usage-contract';
|
|
2
|
+
export type { RepositoryIdentity };
|
|
3
|
+
/**
|
|
4
|
+
* Scompone un URL di remote nei suoi segmenti, coprendo le forme in uso:
|
|
5
|
+
* `git@host:gruppo/repo.git`, `ssh://git@host:22/gruppo/repo`,
|
|
6
|
+
* `https://host/gruppo/sottogruppo/repo.git`, percorsi locali.
|
|
7
|
+
*/
|
|
8
|
+
export declare function parseRemoteUrl(raw: string): {
|
|
9
|
+
host: string | null;
|
|
10
|
+
segments: string[];
|
|
11
|
+
};
|
|
12
|
+
/**
|
|
13
|
+
* Ricava l'identita' del progetto dal remote Git invece che dal nome della
|
|
14
|
+
* cartella.
|
|
15
|
+
*
|
|
16
|
+
* Il nome della cartella lo sceglie chi clona ed e' quindi diverso da macchina
|
|
17
|
+
* a macchina; il percorso sul server Git no. Conservare anche i gruppi parent
|
|
18
|
+
* permette di aggregare in seguito per cliente, business unit o qualunque
|
|
19
|
+
* livello della gerarchia, senza dover riclassificare a mano.
|
|
20
|
+
*/
|
|
21
|
+
export declare function readRepositoryIdentity(projectRoot: string): RepositoryIdentity;
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
import { readFileSync, statSync } from 'node:fs';
|
|
2
|
+
import { basename, isAbsolute, join, resolve, sep } from 'node:path';
|
|
3
|
+
import { sanitizeIdentifier } from './attribution.js';
|
|
4
|
+
const REMOTE_HEADER = /^\s*\[\s*remote\s+"([^"]+)"\s*\]/;
|
|
5
|
+
const SECTION_HEADER = /^\s*\[/;
|
|
6
|
+
const URL_ENTRY = /^\s*url\s*=\s*(.+?)\s*$/;
|
|
7
|
+
const GITDIR_ENTRY = /^gitdir:\s*(.+)$/m;
|
|
8
|
+
const MAX_CONFIG_BYTES = 256 * 1024;
|
|
9
|
+
const MAX_PROJECT_ID_LENGTH = 160;
|
|
10
|
+
/**
|
|
11
|
+
* Individua la directory di metadati Git del progetto.
|
|
12
|
+
*
|
|
13
|
+
* In un worktree o in un submodule `.git` non e' una cartella ma un file che
|
|
14
|
+
* punta altrove; per i worktree il puntatore finisce dentro `worktrees/<nome>`,
|
|
15
|
+
* mentre la configurazione dei remote vive nella directory principale.
|
|
16
|
+
*/
|
|
17
|
+
function resolveGitDir(projectRoot) {
|
|
18
|
+
const gitPath = join(projectRoot, '.git');
|
|
19
|
+
let stats;
|
|
20
|
+
try {
|
|
21
|
+
stats = statSync(gitPath);
|
|
22
|
+
}
|
|
23
|
+
catch {
|
|
24
|
+
return undefined;
|
|
25
|
+
}
|
|
26
|
+
if (stats.isDirectory())
|
|
27
|
+
return gitPath;
|
|
28
|
+
let pointer;
|
|
29
|
+
try {
|
|
30
|
+
pointer = readFileSync(gitPath, 'utf-8');
|
|
31
|
+
}
|
|
32
|
+
catch {
|
|
33
|
+
return undefined;
|
|
34
|
+
}
|
|
35
|
+
const match = GITDIR_ENTRY.exec(pointer);
|
|
36
|
+
if (!match)
|
|
37
|
+
return undefined;
|
|
38
|
+
const target = match[1].trim();
|
|
39
|
+
const absolute = isAbsolute(target) ? target : resolve(projectRoot, target);
|
|
40
|
+
const worktrees = absolute.indexOf(`${sep}worktrees${sep}`);
|
|
41
|
+
return worktrees >= 0 ? absolute.slice(0, worktrees) : absolute;
|
|
42
|
+
}
|
|
43
|
+
/** Legge gli URL dei remote da un file di configurazione Git. */
|
|
44
|
+
function readRemotes(gitDir) {
|
|
45
|
+
const remotes = new Map();
|
|
46
|
+
let content;
|
|
47
|
+
try {
|
|
48
|
+
const configPath = join(gitDir, 'config');
|
|
49
|
+
if (statSync(configPath).size > MAX_CONFIG_BYTES)
|
|
50
|
+
return remotes;
|
|
51
|
+
content = readFileSync(configPath, 'utf-8');
|
|
52
|
+
}
|
|
53
|
+
catch {
|
|
54
|
+
return remotes;
|
|
55
|
+
}
|
|
56
|
+
let current;
|
|
57
|
+
for (const line of content.split('\n')) {
|
|
58
|
+
const header = REMOTE_HEADER.exec(line);
|
|
59
|
+
if (header) {
|
|
60
|
+
current = header[1];
|
|
61
|
+
continue;
|
|
62
|
+
}
|
|
63
|
+
if (SECTION_HEADER.test(line)) {
|
|
64
|
+
current = undefined;
|
|
65
|
+
continue;
|
|
66
|
+
}
|
|
67
|
+
if (!current)
|
|
68
|
+
continue;
|
|
69
|
+
const entry = URL_ENTRY.exec(line);
|
|
70
|
+
if (entry && !remotes.has(current))
|
|
71
|
+
remotes.set(current, entry[1]);
|
|
72
|
+
}
|
|
73
|
+
return remotes;
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Scompone un URL di remote nei suoi segmenti, coprendo le forme in uso:
|
|
77
|
+
* `git@host:gruppo/repo.git`, `ssh://git@host:22/gruppo/repo`,
|
|
78
|
+
* `https://host/gruppo/sottogruppo/repo.git`, percorsi locali.
|
|
79
|
+
*/
|
|
80
|
+
export function parseRemoteUrl(raw) {
|
|
81
|
+
const url = raw.trim().replace(/\/+$/, '').replace(/\.git$/i, '');
|
|
82
|
+
if (url.length === 0)
|
|
83
|
+
return { host: null, segments: [] };
|
|
84
|
+
if (url.startsWith('/') || url.startsWith('.') || url.startsWith('file:')) {
|
|
85
|
+
return { host: null, segments: [basename(url)] };
|
|
86
|
+
}
|
|
87
|
+
const scheme = /^[a-z][a-z0-9+.-]*:\/\/(.*)$/i.exec(url);
|
|
88
|
+
let host = null;
|
|
89
|
+
let path;
|
|
90
|
+
if (scheme) {
|
|
91
|
+
const rest = scheme[1];
|
|
92
|
+
const slash = rest.indexOf('/');
|
|
93
|
+
if (slash < 0)
|
|
94
|
+
return { host: null, segments: [] };
|
|
95
|
+
host = rest.slice(0, slash).replace(/^.*@/, '').replace(/:\d+$/, '') || null;
|
|
96
|
+
path = rest.slice(slash + 1);
|
|
97
|
+
}
|
|
98
|
+
else {
|
|
99
|
+
// Forma scp: [utente@]host:percorso
|
|
100
|
+
const scp = /^(?:[^@]+@)?([^:/]+):(.+)$/.exec(url);
|
|
101
|
+
if (!scp)
|
|
102
|
+
return { host: null, segments: [basename(url)] };
|
|
103
|
+
host = scp[1];
|
|
104
|
+
path = scp[2];
|
|
105
|
+
}
|
|
106
|
+
return { host, segments: path.split('/').filter((segment) => segment.length > 0) };
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Ricava l'identita' del progetto dal remote Git invece che dal nome della
|
|
110
|
+
* cartella.
|
|
111
|
+
*
|
|
112
|
+
* Il nome della cartella lo sceglie chi clona ed e' quindi diverso da macchina
|
|
113
|
+
* a macchina; il percorso sul server Git no. Conservare anche i gruppi parent
|
|
114
|
+
* permette di aggregare in seguito per cliente, business unit o qualunque
|
|
115
|
+
* livello della gerarchia, senza dover riclassificare a mano.
|
|
116
|
+
*/
|
|
117
|
+
export function readRepositoryIdentity(projectRoot) {
|
|
118
|
+
const fallbackName = sanitizeIdentifier(basename(projectRoot)) ?? 'unknown';
|
|
119
|
+
const fallback = {
|
|
120
|
+
projectId: fallbackName,
|
|
121
|
+
host: null,
|
|
122
|
+
groups: [],
|
|
123
|
+
name: fallbackName,
|
|
124
|
+
remoteUrl: null,
|
|
125
|
+
};
|
|
126
|
+
const gitDir = resolveGitDir(projectRoot);
|
|
127
|
+
if (!gitDir)
|
|
128
|
+
return fallback;
|
|
129
|
+
const remotes = readRemotes(gitDir);
|
|
130
|
+
const remoteUrl = remotes.get('origin') ?? remotes.get('upstream') ?? remotes.values().next().value;
|
|
131
|
+
if (!remoteUrl)
|
|
132
|
+
return fallback;
|
|
133
|
+
const { host, segments } = parseRemoteUrl(remoteUrl);
|
|
134
|
+
const clean = segments
|
|
135
|
+
.map((segment) => sanitizeIdentifier(segment))
|
|
136
|
+
.filter((segment) => segment !== undefined);
|
|
137
|
+
if (clean.length === 0)
|
|
138
|
+
return fallback;
|
|
139
|
+
return {
|
|
140
|
+
projectId: clean.join('/').slice(0, MAX_PROJECT_ID_LENGTH),
|
|
141
|
+
host,
|
|
142
|
+
groups: clean.slice(0, -1),
|
|
143
|
+
name: clean[clean.length - 1],
|
|
144
|
+
remoteUrl,
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
//# sourceMappingURL=gitRepository.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gitRepository.js","sourceRoot":"","sources":["../src/gitRepository.ts"],"names":[],"mappings":"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"}
|
package/dist/paths.d.ts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cartella dove il client tiene configurazione e stato.
|
|
3
|
+
*
|
|
4
|
+
* Sotto `npx` la working directory e' quella da cui il developer ha lanciato il
|
|
5
|
+
* comando, cioe' un posto qualsiasi: file di configurazione e spool devono
|
|
6
|
+
* stare in una posizione stabile, non relativa alla cwd.
|
|
7
|
+
*/
|
|
8
|
+
export declare function configDir(): string;
|
|
9
|
+
export declare function configFile(): string;
|
|
10
|
+
export declare function defaultSpoolPath(): string;
|
|
11
|
+
/** Percorso del `settings.json` utente di VS Code, per la piattaforma corrente. */
|
|
12
|
+
export declare function vscodeSettingsFile(): string;
|
package/dist/paths.js
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { homedir } from 'node:os';
|
|
2
|
+
import { join } from 'node:path';
|
|
3
|
+
/**
|
|
4
|
+
* Cartella dove il client tiene configurazione e stato.
|
|
5
|
+
*
|
|
6
|
+
* Sotto `npx` la working directory e' quella da cui il developer ha lanciato il
|
|
7
|
+
* comando, cioe' un posto qualsiasi: file di configurazione e spool devono
|
|
8
|
+
* stare in una posizione stabile, non relativa alla cwd.
|
|
9
|
+
*/
|
|
10
|
+
export function configDir() {
|
|
11
|
+
const override = process.env.COPILOT_PROXY_HOME?.trim();
|
|
12
|
+
if (override)
|
|
13
|
+
return override;
|
|
14
|
+
if (process.platform === 'win32') {
|
|
15
|
+
const appData = process.env.APPDATA?.trim();
|
|
16
|
+
if (appData)
|
|
17
|
+
return join(appData, 'copilot-proxy');
|
|
18
|
+
}
|
|
19
|
+
const xdg = process.env.XDG_CONFIG_HOME?.trim();
|
|
20
|
+
return join(xdg || join(homedir(), '.config'), 'copilot-proxy');
|
|
21
|
+
}
|
|
22
|
+
export function configFile() {
|
|
23
|
+
return join(configDir(), 'config.json');
|
|
24
|
+
}
|
|
25
|
+
export function defaultSpoolPath() {
|
|
26
|
+
return join(configDir(), 'spool.jsonl');
|
|
27
|
+
}
|
|
28
|
+
/** Percorso del `settings.json` utente di VS Code, per la piattaforma corrente. */
|
|
29
|
+
export function vscodeSettingsFile() {
|
|
30
|
+
if (process.platform === 'win32') {
|
|
31
|
+
const appData = process.env.APPDATA?.trim() ?? join(homedir(), 'AppData', 'Roaming');
|
|
32
|
+
return join(appData, 'Code', 'User', 'settings.json');
|
|
33
|
+
}
|
|
34
|
+
if (process.platform === 'darwin') {
|
|
35
|
+
return join(homedir(), 'Library', 'Application Support', 'Code', 'User', 'settings.json');
|
|
36
|
+
}
|
|
37
|
+
return join(homedir(), '.config', 'Code', 'User', 'settings.json');
|
|
38
|
+
}
|
|
39
|
+
//# sourceMappingURL=paths.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"paths.js","sourceRoot":"","sources":["../src/paths.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC;;;;;;GAMG;AACH,MAAM,UAAU,SAAS;IACvB,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,kBAAkB,EAAE,IAAI,EAAE,CAAC;IACxD,IAAI,QAAQ;QAAE,OAAO,QAAQ,CAAC;IAE9B,IAAI,OAAO,CAAC,QAAQ,KAAK,OAAO,EAAE,CAAC;QACjC,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC;QAC5C,IAAI,OAAO;YAAE,OAAO,IAAI,CAAC,OAAO,EAAE,eAAe,CAAC,CAAC;IACrD,CAAC;IAED,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,eAAe,EAAE,IAAI,EAAE,CAAC;IAChD,OAAO,IAAI,CAAC,GAAG,IAAI,IAAI,CAAC,OAAO,EAAE,EAAE,SAAS,CAAC,EAAE,eAAe,CAAC,CAAC;AAClE,CAAC;AAED,MAAM,UAAU,UAAU;IACxB,OAAO,IAAI,CAAC,SAAS,EAAE,EAAE,aAAa,CAAC,CAAC;AAC1C,CAAC;AAED,MAAM,UAAU,gBAAgB;IAC9B,OAAO,IAAI,CAAC,SAAS,EAAE,EAAE,aAAa,CAAC,CAAC;AAC1C,CAAC;AAED,mFAAmF;AACnF,MAAM,UAAU,kBAAkB;IAChC,IAAI,OAAO,CAAC,QAAQ,KAAK,OAAO,EAAE,CAAC;QACjC,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,OAAO,EAAE,IAAI,EAAE,IAAI,IAAI,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,SAAS,CAAC,CAAC;QACrF,OAAO,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,eAAe,CAAC,CAAC;IACxD,CAAC;IACD,IAAI,OAAO,CAAC,QAAQ,KAAK,QAAQ,EAAE,CAAC;QAClC,OAAO,IAAI,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,qBAAqB,EAAE,MAAM,EAAE,MAAM,EAAE,eAAe,CAAC,CAAC;IAC5F,CAAC;IACD,OAAO,IAAI,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,eAAe,CAAC,CAAC;AACrE,CAAC"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { type RepositoryIdentity } from './gitRepository.js';
|
|
2
|
+
export interface ProjectDetectorOptions {
|
|
3
|
+
/** Cartelle sotto cui vivono i progetti: delimitano cosa e' lecito risolvere. */
|
|
4
|
+
roots: string[];
|
|
5
|
+
/** File o cartelle che marcano la radice di un progetto (tipicamente `.git`). */
|
|
6
|
+
markers: string[];
|
|
7
|
+
/** Durata dell'ereditarieta' del progetto sulle richieste senza path. */
|
|
8
|
+
stickyTtlMs: number;
|
|
9
|
+
/** Limite di corpo ispezionato, per non pagare scansioni su payload enormi. */
|
|
10
|
+
maxScanBytes: number;
|
|
11
|
+
}
|
|
12
|
+
export interface DetectedProject {
|
|
13
|
+
repository: RepositoryIdentity;
|
|
14
|
+
/** `workspace` = dedotto dai path nella richiesta; `session` = ereditato. */
|
|
15
|
+
source: 'workspace' | 'session';
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Deduce il progetto di appartenenza di una richiesta dai path assoluti che
|
|
19
|
+
* questa cita.
|
|
20
|
+
*
|
|
21
|
+
* Le richieste di Copilot Chat trasportano il contesto di lavoro: file aperti,
|
|
22
|
+
* riferimenti espliciti, risultati degli strumenti dell'agente. Tutti nominano
|
|
23
|
+
* file reali sul disco. Risalendo da quei path fino al marker di progetto piu'
|
|
24
|
+
* vicino si ottiene l'attribuzione senza chiedere al developer di configurare
|
|
25
|
+
* nulla per ogni repository, e senza conservare il contenuto della richiesta:
|
|
26
|
+
* dei path si tiene solo l'identita' del repository.
|
|
27
|
+
*/
|
|
28
|
+
export declare class ProjectDetector {
|
|
29
|
+
private readonly roots;
|
|
30
|
+
private readonly markers;
|
|
31
|
+
private readonly stickyTtlMs;
|
|
32
|
+
private readonly maxScanBytes;
|
|
33
|
+
private readonly pattern;
|
|
34
|
+
/** Path candidato -> repository risolto (o `null` se fuori da ogni progetto). */
|
|
35
|
+
private readonly cache;
|
|
36
|
+
private readonly sticky;
|
|
37
|
+
constructor(options: ProjectDetectorOptions);
|
|
38
|
+
get enabled(): boolean;
|
|
39
|
+
/**
|
|
40
|
+
* @param sessionKey chiave della finestra/conversazione, usata per ereditare
|
|
41
|
+
* il progetto nelle richieste che non citano file (titoli, domande secche).
|
|
42
|
+
*/
|
|
43
|
+
detect(body: Buffer, sessionKey: string, now?: number): DetectedProject | undefined;
|
|
44
|
+
private fromBody;
|
|
45
|
+
/** Risale dal path fino al primo marker di progetto, senza uscire dal root. */
|
|
46
|
+
private projectFor;
|
|
47
|
+
private remember;
|
|
48
|
+
}
|