@vidiemme/copilot-proxy 0.3.3 → 0.5.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 +46 -5
- package/dist/autostart.d.ts +18 -0
- package/dist/autostart.js +119 -6
- package/dist/autostart.js.map +1 -1
- package/dist/cli.js +146 -1
- package/dist/cli.js.map +1 -1
- package/dist/collector/forwarder.d.ts +4 -1
- package/dist/collector/forwarder.js +20 -15
- package/dist/collector/forwarder.js.map +1 -1
- package/dist/projectDetector.d.ts +2 -0
- package/dist/projectDetector.js +10 -2
- package/dist/projectDetector.js.map +1 -1
- package/dist/reload/copilotCli.d.ts +23 -0
- package/dist/reload/copilotCli.js +103 -0
- package/dist/reload/copilotCli.js.map +1 -0
- package/dist/reload/index.d.ts +69 -0
- package/dist/reload/index.js +249 -0
- package/dist/reload/index.js.map +1 -0
- package/dist/reload/reconstruct.d.ts +35 -0
- package/dist/reload/reconstruct.js +89 -0
- package/dist/reload/reconstruct.js.map +1 -0
- package/dist/reload/vscodeChat.d.ts +40 -0
- package/dist/reload/vscodeChat.js +203 -0
- package/dist/reload/vscodeChat.js.map +1 -0
- package/package.json +1 -1
|
@@ -24,6 +24,9 @@ export interface ForwarderStats {
|
|
|
24
24
|
}
|
|
25
25
|
/** Nome del client senza versione: `GitHubCopilotChat/0.72.0` -> `GitHubCopilotChat`. */
|
|
26
26
|
export declare function clientFamily(clientName: string | null | undefined): string;
|
|
27
|
+
/** Header di ogni invio al collector: credenziale e, se dichiarata, identita' del developer. */
|
|
28
|
+
export declare function collectorHeaders(config: ClientConfig): Record<string, string>;
|
|
29
|
+
export declare function chunk<T>(items: T[], size: number): T[][];
|
|
27
30
|
/**
|
|
28
31
|
* Inoltra gli eventi di consumo al servizio di raccolta.
|
|
29
32
|
*
|
|
@@ -44,7 +47,7 @@ export declare class UsageForwarder {
|
|
|
44
47
|
private readonly batchSize;
|
|
45
48
|
private readonly spoolPath;
|
|
46
49
|
private readonly sendingPath;
|
|
47
|
-
private readonly
|
|
50
|
+
private readonly headers;
|
|
48
51
|
constructor(config: ClientConfig, logger: Logger);
|
|
49
52
|
start(): void;
|
|
50
53
|
enqueue(event: UsageEventPayload): void;
|
|
@@ -15,7 +15,23 @@ export function clientFamily(clientName) {
|
|
|
15
15
|
const name = clientName?.trim().split(/[/\s]/, 1)[0];
|
|
16
16
|
return name || 'sconosciuto';
|
|
17
17
|
}
|
|
18
|
-
|
|
18
|
+
/** Header di ogni invio al collector: credenziale e, se dichiarata, identita' del developer. */
|
|
19
|
+
export function collectorHeaders(config) {
|
|
20
|
+
const headers = {
|
|
21
|
+
'content-type': 'application/json',
|
|
22
|
+
authorization: `Bearer ${config.collectorToken}`,
|
|
23
|
+
'user-agent': CLIENT_USER_AGENT,
|
|
24
|
+
};
|
|
25
|
+
// Gli header HTTP sono ASCII: nomi accentati viaggiano percent-encoded.
|
|
26
|
+
if (config.developerName) {
|
|
27
|
+
headers['x-developer-name'] = encodeURIComponent(config.developerName);
|
|
28
|
+
if (config.developerEmail) {
|
|
29
|
+
headers['x-developer-email'] = encodeURIComponent(config.developerEmail);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
return headers;
|
|
33
|
+
}
|
|
34
|
+
export function chunk(items, size) {
|
|
19
35
|
const chunks = [];
|
|
20
36
|
for (let index = 0; index < items.length; index += size) {
|
|
21
37
|
chunks.push(items.slice(index, index + size));
|
|
@@ -50,20 +66,14 @@ export class UsageForwarder {
|
|
|
50
66
|
batchSize;
|
|
51
67
|
spoolPath;
|
|
52
68
|
sendingPath;
|
|
53
|
-
|
|
69
|
+
headers;
|
|
54
70
|
constructor(config, logger) {
|
|
55
71
|
this.config = config;
|
|
56
72
|
this.logger = logger;
|
|
57
73
|
this.batchSize = Math.min(config.flushMaxBatch, MAX_EVENTS_PER_BATCH);
|
|
58
74
|
this.spoolPath = config.spoolPath;
|
|
59
75
|
this.sendingPath = `${config.spoolPath}.sending`;
|
|
60
|
-
|
|
61
|
-
if (config.developerName) {
|
|
62
|
-
this.identityHeaders['x-developer-name'] = encodeURIComponent(config.developerName);
|
|
63
|
-
if (config.developerEmail) {
|
|
64
|
-
this.identityHeaders['x-developer-email'] = encodeURIComponent(config.developerEmail);
|
|
65
|
-
}
|
|
66
|
-
}
|
|
76
|
+
this.headers = collectorHeaders(config);
|
|
67
77
|
}
|
|
68
78
|
start() {
|
|
69
79
|
if (this.timer)
|
|
@@ -137,12 +147,7 @@ export class UsageForwarder {
|
|
|
137
147
|
try {
|
|
138
148
|
response = await fetch(this.config.collectorUrl, {
|
|
139
149
|
method: 'POST',
|
|
140
|
-
headers:
|
|
141
|
-
'content-type': 'application/json',
|
|
142
|
-
authorization: `Bearer ${this.config.collectorToken}`,
|
|
143
|
-
'user-agent': CLIENT_USER_AGENT,
|
|
144
|
-
...this.identityHeaders,
|
|
145
|
-
},
|
|
150
|
+
headers: this.headers,
|
|
146
151
|
body: JSON.stringify({ events }),
|
|
147
152
|
signal: AbortSignal.timeout(this.config.collectorTimeoutMs),
|
|
148
153
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"forwarder.js","sourceRoot":"","sources":["../../src/collector/forwarder.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AACrF,OAAO,EAAE,oBAAoB,EAA0B,MAAM,kCAAkC,CAAC;AAEhG,OAAO,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAQlD,wFAAwF;AACxF,MAAM,gBAAgB,GAAG,MAAM,CAAC;AAChC,0EAA0E;AAC1E,MAAM,gBAAgB,GAAG,MAAM,CAAC;AAEhC;;;GAGG;AACH,MAAM,uBAAuB,GAAG,IAAI,GAAG,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC;AAoB9D,yFAAyF;AACzF,MAAM,UAAU,YAAY,CAAC,UAAqC;IAChE,MAAM,IAAI,GAAG,UAAU,EAAE,IAAI,EAAE,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACrD,OAAO,IAAI,IAAI,aAAa,CAAC;AAC/B,CAAC;AAED,
|
|
1
|
+
{"version":3,"file":"forwarder.js","sourceRoot":"","sources":["../../src/collector/forwarder.ts"],"names":[],"mappings":"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"}
|
|
@@ -41,6 +41,8 @@ export declare class ProjectDetector {
|
|
|
41
41
|
* il progetto nelle richieste che non citano file (titoli, domande secche).
|
|
42
42
|
*/
|
|
43
43
|
detect(body: Buffer, sessionKey: string, now?: number): DetectedProject | undefined;
|
|
44
|
+
/** Repository di un path locale, es. la cartella di lavoro di una sessione registrata. */
|
|
45
|
+
resolve(path: string, now?: number): RepositoryIdentity | undefined;
|
|
44
46
|
private fromBody;
|
|
45
47
|
/** Risale dal path fino al primo marker di progetto, senza uscire dal root. */
|
|
46
48
|
private projectFor;
|
package/dist/projectDetector.js
CHANGED
|
@@ -10,8 +10,12 @@ const IS_WINDOWS = sep === '\\';
|
|
|
10
10
|
const SEPARATOR = '[\\\\/]+';
|
|
11
11
|
/** Caratteri ammessi in un segmento di path, esclusi i separatori. */
|
|
12
12
|
const SEGMENT_CHAR = '[^\\s"\'`,;:*?<>|()\\[\\]{}\\\\/]';
|
|
13
|
-
/**
|
|
14
|
-
|
|
13
|
+
/**
|
|
14
|
+
* Un segmento puo' contenere spazi singoli: `My Project`. Dopo lo spazio non
|
|
15
|
+
* puo' esserci una lettera di unita': in `a.ts C:\b.ts` il secondo path non va
|
|
16
|
+
* inghiottito dal primo.
|
|
17
|
+
*/
|
|
18
|
+
const SEGMENT = `${SEGMENT_CHAR}+(?: (?![A-Za-z]:)${SEGMENT_CHAR}+)*`;
|
|
15
19
|
function escapeRegExp(value) {
|
|
16
20
|
return value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
17
21
|
}
|
|
@@ -107,6 +111,10 @@ export class ProjectDetector {
|
|
|
107
111
|
}
|
|
108
112
|
return undefined;
|
|
109
113
|
}
|
|
114
|
+
/** Repository di un path locale, es. la cartella di lavoro di una sessione registrata. */
|
|
115
|
+
resolve(path, now = Date.now()) {
|
|
116
|
+
return this.projectFor(normalizePath(path), now);
|
|
117
|
+
}
|
|
110
118
|
fromBody(body, now) {
|
|
111
119
|
if (!this.pattern || body.length === 0)
|
|
112
120
|
return undefined;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"projectDetector.js","sourceRoot":"","sources":["../src/projectDetector.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,EAAE,sBAAsB,EAA2B,MAAM,oBAAoB,CAAC;AAmBrF,MAAM,iBAAiB,GAAG,KAAK,CAAC;AAChC,MAAM,kBAAkB,GAAG,KAAK,CAAC;AACjC,2EAA2E;AAC3E,MAAM,YAAY,GAAG,EAAE,GAAG,MAAM,CAAC;AAEjC,MAAM,UAAU,GAAG,GAAG,KAAK,IAAI,CAAC;AAEhC,qFAAqF;AACrF,MAAM,SAAS,GAAG,UAAU,CAAC;AAC7B,sEAAsE;AACtE,MAAM,YAAY,GAAG,mCAAmC,CAAC;AACzD
|
|
1
|
+
{"version":3,"file":"projectDetector.js","sourceRoot":"","sources":["../src/projectDetector.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { TokenCounters } from '@vidiemme/copilot-usage-contract';
|
|
2
|
+
/** Una chiamata al modello registrata da Copilot CLI o da una sessione agentica in VS Code. */
|
|
3
|
+
export interface CliCall {
|
|
4
|
+
/** `serviceRequestId` di GitHub quando c'e': lo stesso che il proxy usa come chiave. */
|
|
5
|
+
requestId: string;
|
|
6
|
+
occurredAt: Date;
|
|
7
|
+
cwd: string;
|
|
8
|
+
sessionId: string;
|
|
9
|
+
model: string | null;
|
|
10
|
+
endpoint: string | null;
|
|
11
|
+
usage: TokenCounters;
|
|
12
|
+
durationMs: number | null;
|
|
13
|
+
}
|
|
14
|
+
export declare function defaultSessionStateDir(): string;
|
|
15
|
+
/**
|
|
16
|
+
* Normalizza un `session.usage_record`.
|
|
17
|
+
*
|
|
18
|
+
* Qui `inputTokens` e' il totale e comprende la cache; nel contratto invece le
|
|
19
|
+
* famiglie non si sovrappongono, quindi la parte servita dalla cache va tolta.
|
|
20
|
+
*/
|
|
21
|
+
export declare function parseUsageRecord(line: string, cwd: string, sessionId: string): CliCall | undefined;
|
|
22
|
+
/** Legge le chiamate registrate nelle sessioni di Copilot CLI. */
|
|
23
|
+
export declare function readCliCalls(stateDir?: string, modifiedSince?: Date): CliCall[];
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import { readdirSync, readFileSync, statSync } from 'node:fs';
|
|
2
|
+
import { homedir } from 'node:os';
|
|
3
|
+
import { join } from 'node:path';
|
|
4
|
+
function asObject(value) {
|
|
5
|
+
return typeof value === 'object' && value !== null && !Array.isArray(value) ? value : undefined;
|
|
6
|
+
}
|
|
7
|
+
function count(value) {
|
|
8
|
+
return typeof value === 'number' && Number.isFinite(value) ? Math.max(0, Math.floor(value)) : 0;
|
|
9
|
+
}
|
|
10
|
+
function text(value) {
|
|
11
|
+
return typeof value === 'string' && value.length > 0 ? value : null;
|
|
12
|
+
}
|
|
13
|
+
export function defaultSessionStateDir() {
|
|
14
|
+
return join(process.env.COPILOT_HOME?.trim() || join(homedir(), '.copilot'), 'session-state');
|
|
15
|
+
}
|
|
16
|
+
function sessionCwd(sessionDir) {
|
|
17
|
+
try {
|
|
18
|
+
const yaml = readFileSync(join(sessionDir, 'workspace.yaml'), 'utf-8');
|
|
19
|
+
return /^cwd:\s*(.+?)\s*$/m.exec(yaml)?.[1];
|
|
20
|
+
}
|
|
21
|
+
catch {
|
|
22
|
+
return undefined;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Normalizza un `session.usage_record`.
|
|
27
|
+
*
|
|
28
|
+
* Qui `inputTokens` e' il totale e comprende la cache; nel contratto invece le
|
|
29
|
+
* famiglie non si sovrappongono, quindi la parte servita dalla cache va tolta.
|
|
30
|
+
*/
|
|
31
|
+
export function parseUsageRecord(line, cwd, sessionId) {
|
|
32
|
+
let record;
|
|
33
|
+
try {
|
|
34
|
+
record = asObject(JSON.parse(line));
|
|
35
|
+
}
|
|
36
|
+
catch {
|
|
37
|
+
return undefined;
|
|
38
|
+
}
|
|
39
|
+
if (record?.type !== 'session.usage_record')
|
|
40
|
+
return undefined;
|
|
41
|
+
const usage = asObject(asObject(record.data)?.usage);
|
|
42
|
+
if (!usage)
|
|
43
|
+
return undefined;
|
|
44
|
+
const id = text(usage.serviceRequestId) ?? text(usage.apiCallId) ?? text(record.id);
|
|
45
|
+
const at = new Date(typeof record.timestamp === 'string' ? record.timestamp : NaN);
|
|
46
|
+
if (!id || Number.isNaN(at.getTime()))
|
|
47
|
+
return undefined;
|
|
48
|
+
const cached = count(usage.cacheReadTokens);
|
|
49
|
+
const written = count(usage.cacheWriteTokens);
|
|
50
|
+
return {
|
|
51
|
+
requestId: text(usage.serviceRequestId) ? id : `copilot-cli:${id}`,
|
|
52
|
+
occurredAt: at,
|
|
53
|
+
cwd,
|
|
54
|
+
sessionId,
|
|
55
|
+
model: text(usage.model),
|
|
56
|
+
endpoint: text(usage.apiEndpoint),
|
|
57
|
+
usage: {
|
|
58
|
+
inputTokens: Math.max(0, count(usage.inputTokens) - cached - written),
|
|
59
|
+
cachedInputTokens: cached,
|
|
60
|
+
cacheWriteTokens: written,
|
|
61
|
+
outputTokens: count(usage.outputTokens),
|
|
62
|
+
},
|
|
63
|
+
durationMs: typeof usage.duration === 'number' ? count(usage.duration) : null,
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
/** Legge le chiamate registrate nelle sessioni di Copilot CLI. */
|
|
67
|
+
export function readCliCalls(stateDir = defaultSessionStateDir(), modifiedSince) {
|
|
68
|
+
let sessions;
|
|
69
|
+
try {
|
|
70
|
+
sessions = readdirSync(stateDir);
|
|
71
|
+
}
|
|
72
|
+
catch {
|
|
73
|
+
return [];
|
|
74
|
+
}
|
|
75
|
+
const byId = new Map();
|
|
76
|
+
for (const sessionId of sessions) {
|
|
77
|
+
const sessionDir = join(stateDir, sessionId);
|
|
78
|
+
const eventsFile = join(sessionDir, 'events.jsonl');
|
|
79
|
+
let content;
|
|
80
|
+
try {
|
|
81
|
+
if (modifiedSince && statSync(eventsFile).mtime < modifiedSince)
|
|
82
|
+
continue;
|
|
83
|
+
content = readFileSync(eventsFile, 'utf-8');
|
|
84
|
+
}
|
|
85
|
+
catch {
|
|
86
|
+
continue;
|
|
87
|
+
}
|
|
88
|
+
const cwd = sessionCwd(sessionDir);
|
|
89
|
+
if (!cwd)
|
|
90
|
+
continue;
|
|
91
|
+
for (const line of content.split('\n')) {
|
|
92
|
+
// Filtro economico prima del parse: la gran parte delle righe sono messaggi.
|
|
93
|
+
if (!line.includes('"session.usage_record"'))
|
|
94
|
+
continue;
|
|
95
|
+
const call = parseUsageRecord(line, cwd, sessionId);
|
|
96
|
+
// Le sessioni biforcate ricopiano gli eventi della sessione d'origine.
|
|
97
|
+
if (call && !byId.has(call.requestId))
|
|
98
|
+
byId.set(call.requestId, call);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
return [...byId.values()];
|
|
102
|
+
}
|
|
103
|
+
//# sourceMappingURL=copilotCli.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"copilotCli.js","sourceRoot":"","sources":["../../src/reload/copilotCli.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { type UsageEventPayload } from '@vidiemme/copilot-usage-contract';
|
|
2
|
+
import { type ClientConfig } from '../config.js';
|
|
3
|
+
import { type CliCall } from './copilotCli.js';
|
|
4
|
+
import { type RateTier } from './reconstruct.js';
|
|
5
|
+
import { type ChatRequest } from './vscodeChat.js';
|
|
6
|
+
export type ReloadSource = 'copilot-cli' | 'vscode-chat';
|
|
7
|
+
export interface ReloadOptions {
|
|
8
|
+
roots: string[];
|
|
9
|
+
markers: string[];
|
|
10
|
+
from?: Date | undefined;
|
|
11
|
+
/** Esclusivo. */
|
|
12
|
+
to?: Date | undefined;
|
|
13
|
+
}
|
|
14
|
+
export interface RateBook {
|
|
15
|
+
creditUsd: number;
|
|
16
|
+
/** `null` = modello che il collector non sa prezzare. */
|
|
17
|
+
models: Map<string, {
|
|
18
|
+
tiers: RateTier[];
|
|
19
|
+
} | null>;
|
|
20
|
+
}
|
|
21
|
+
export interface ReloadPlan {
|
|
22
|
+
events: UsageEventPayload[];
|
|
23
|
+
/** Crediti addebitati per le chat incluse, per confronto con la dashboard. */
|
|
24
|
+
chatCredits: number;
|
|
25
|
+
/** Richieste di chat lette ma non caricabili, con il motivo. */
|
|
26
|
+
skippedChat: {
|
|
27
|
+
noBilling: number;
|
|
28
|
+
unpriced: Map<string, number>;
|
|
29
|
+
noRates: number;
|
|
30
|
+
};
|
|
31
|
+
sources: Record<ReloadSource, number>;
|
|
32
|
+
}
|
|
33
|
+
export interface ReloadInputs {
|
|
34
|
+
cliCalls: CliCall[];
|
|
35
|
+
chatRequests: ChatRequest[];
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Pseudonimo del developer per lo storico.
|
|
39
|
+
*
|
|
40
|
+
* Il proxy lo ricava dal token Copilot, che qui non c'e': si parte quindi
|
|
41
|
+
* dall'identita' dichiarata. E' un id diverso da quello del traffico dal vivo,
|
|
42
|
+
* ma il collector unisce i due sotto lo stesso nome visualizzato.
|
|
43
|
+
*/
|
|
44
|
+
export declare function developerIdFor(config: ClientConfig): string;
|
|
45
|
+
/** Prepara gli eventi da caricare, senza toccare la rete. */
|
|
46
|
+
export declare function buildReloadPlan(inputs: ReloadInputs, options: ReloadOptions, developerId: string, rates: RateBook | undefined): ReloadPlan;
|
|
47
|
+
/** Legge le sessioni salvate sulla macchina. */
|
|
48
|
+
export declare function readLocalSessions(options: ReloadOptions): ReloadInputs;
|
|
49
|
+
/** Tariffe dei modelli dal collector: le stesse con cui verranno prezzati gli eventi. */
|
|
50
|
+
export declare function fetchRates(config: ClientConfig, models: string[]): Promise<RateBook>;
|
|
51
|
+
export declare function chatModels(requests: ChatRequest[]): string[];
|
|
52
|
+
export interface SendResult {
|
|
53
|
+
accepted: number;
|
|
54
|
+
rejected: number;
|
|
55
|
+
/** Eventi non consegnati per errore di rete o del servizio: basta rilanciare. */
|
|
56
|
+
failed: number;
|
|
57
|
+
error?: string;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Invia gli eventi in batch, in ordine. Al primo errore si ferma: le chiavi
|
|
61
|
+
* sono deterministiche e il collector deduplica, quindi rilanciare riprende
|
|
62
|
+
* senza doppioni.
|
|
63
|
+
*/
|
|
64
|
+
export declare function sendEvents(config: ClientConfig, events: UsageEventPayload[], onProgress?: (sent: number) => void): Promise<SendResult>;
|
|
65
|
+
/**
|
|
66
|
+
* Primo avvio del proxy registrato nel suo log. Da li' in poi il traffico di
|
|
67
|
+
* questa postazione e' probabilmente gia' nel collector.
|
|
68
|
+
*/
|
|
69
|
+
export declare function proxyFirstStart(logFile?: string): Date | undefined;
|
|
@@ -0,0 +1,249 @@
|
|
|
1
|
+
import { readFileSync } from 'node:fs';
|
|
2
|
+
import { hostname, userInfo } from 'node:os';
|
|
3
|
+
import { join, resolve, sep } from 'node:path';
|
|
4
|
+
import { MAX_EVENTS_PER_BATCH, } from '@vidiemme/copilot-usage-contract';
|
|
5
|
+
import { chunk, collectorHeaders } from '../collector/forwarder.js';
|
|
6
|
+
import { pseudonymize } from '../config.js';
|
|
7
|
+
import { readRepositoryIdentity } from '../gitRepository.js';
|
|
8
|
+
import { configDir } from '../paths.js';
|
|
9
|
+
import { ProjectDetector } from '../projectDetector.js';
|
|
10
|
+
import { gitIdentity } from '../setupHelpers.js';
|
|
11
|
+
import { readCliCalls } from './copilotCli.js';
|
|
12
|
+
import { reconstructRounds } from './reconstruct.js';
|
|
13
|
+
import { readChatRequests } from './vscodeChat.js';
|
|
14
|
+
/** Clienti con cui si presentano gli eventi ricaricati: la famiglia e' quella del traffico dal vivo. */
|
|
15
|
+
const CLIENT_NAMES = {
|
|
16
|
+
'copilot-cli': 'copilot/reload',
|
|
17
|
+
'vscode-chat': 'GitHubCopilotChat/reload',
|
|
18
|
+
};
|
|
19
|
+
/**
|
|
20
|
+
* Pseudonimo del developer per lo storico.
|
|
21
|
+
*
|
|
22
|
+
* Il proxy lo ricava dal token Copilot, che qui non c'e': si parte quindi
|
|
23
|
+
* dall'identita' dichiarata. E' un id diverso da quello del traffico dal vivo,
|
|
24
|
+
* ma il collector unisce i due sotto lo stesso nome visualizzato.
|
|
25
|
+
*/
|
|
26
|
+
export function developerIdFor(config) {
|
|
27
|
+
const git = gitIdentity();
|
|
28
|
+
const identity = config.developerEmail ??
|
|
29
|
+
git.email ??
|
|
30
|
+
config.developerName ??
|
|
31
|
+
git.name ??
|
|
32
|
+
`${userInfo().username}@${hostname()}`;
|
|
33
|
+
return pseudonymize(`identity:${identity.toLowerCase()}`, config.developerIdSalt);
|
|
34
|
+
}
|
|
35
|
+
/** Su Windows i path non distinguono le maiuscole: VS Code salva `c:\...`, la home e' `C:\...`. */
|
|
36
|
+
function comparable(path) {
|
|
37
|
+
const absolute = resolve(path);
|
|
38
|
+
return sep === '\\' ? absolute.toLowerCase() : absolute;
|
|
39
|
+
}
|
|
40
|
+
function inside(path, roots) {
|
|
41
|
+
const target = comparable(path);
|
|
42
|
+
return roots.some((root) => {
|
|
43
|
+
const base = comparable(root);
|
|
44
|
+
return target === base || target.startsWith(base.endsWith(sep) ? base : `${base}${sep}`);
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
function inRange(at, options) {
|
|
48
|
+
return (!options.from || at >= options.from) && (!options.to || at < options.to);
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Collega una cartella di lavoro al suo repository.
|
|
52
|
+
*
|
|
53
|
+
* Una cartella sotto i root che non sta in nessun repository prende comunque
|
|
54
|
+
* un'identita' dal nome: e' lo stesso ripiego del proxy.
|
|
55
|
+
*/
|
|
56
|
+
function projectResolver(options) {
|
|
57
|
+
const detector = new ProjectDetector({
|
|
58
|
+
roots: options.roots,
|
|
59
|
+
markers: options.markers,
|
|
60
|
+
stickyTtlMs: 0,
|
|
61
|
+
maxScanBytes: 0,
|
|
62
|
+
});
|
|
63
|
+
return (folders) => {
|
|
64
|
+
const candidates = folders.filter((folder) => inside(folder, options.roots));
|
|
65
|
+
for (const folder of candidates) {
|
|
66
|
+
const repository = detector.resolve(folder);
|
|
67
|
+
if (repository)
|
|
68
|
+
return repository;
|
|
69
|
+
}
|
|
70
|
+
return candidates[0] ? readRepositoryIdentity(candidates[0]) : undefined;
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
/** Prepara gli eventi da caricare, senza toccare la rete. */
|
|
74
|
+
export function buildReloadPlan(inputs, options, developerId, rates) {
|
|
75
|
+
const projectOf = projectResolver(options);
|
|
76
|
+
const plan = {
|
|
77
|
+
events: [],
|
|
78
|
+
chatCredits: 0,
|
|
79
|
+
skippedChat: { noBilling: 0, unpriced: new Map(), noRates: 0 },
|
|
80
|
+
sources: { 'copilot-cli': 0, 'vscode-chat': 0 },
|
|
81
|
+
};
|
|
82
|
+
const base = (repository, source) => ({
|
|
83
|
+
developerId,
|
|
84
|
+
developerSource: 'identity',
|
|
85
|
+
projectId: repository.projectId,
|
|
86
|
+
projectSource: 'workspace',
|
|
87
|
+
repository,
|
|
88
|
+
clientName: CLIENT_NAMES[source],
|
|
89
|
+
streamed: false,
|
|
90
|
+
});
|
|
91
|
+
for (const call of inputs.cliCalls) {
|
|
92
|
+
if (!inRange(call.occurredAt, options))
|
|
93
|
+
continue;
|
|
94
|
+
const repository = projectOf([call.cwd]);
|
|
95
|
+
if (!repository)
|
|
96
|
+
continue;
|
|
97
|
+
plan.events.push({
|
|
98
|
+
...base(repository, 'copilot-cli'),
|
|
99
|
+
requestId: call.requestId,
|
|
100
|
+
occurredAt: call.occurredAt.toISOString(),
|
|
101
|
+
sessionId: call.sessionId,
|
|
102
|
+
endpoint: call.endpoint ?? '/reload/copilot-cli',
|
|
103
|
+
model: call.model,
|
|
104
|
+
usage: call.usage,
|
|
105
|
+
durationMs: call.durationMs,
|
|
106
|
+
});
|
|
107
|
+
plan.sources['copilot-cli'] += 1;
|
|
108
|
+
}
|
|
109
|
+
for (const request of inputs.chatRequests) {
|
|
110
|
+
if (!inRange(request.roundTimes[0], options))
|
|
111
|
+
continue;
|
|
112
|
+
const repository = projectOf(request.folders);
|
|
113
|
+
if (!repository)
|
|
114
|
+
continue;
|
|
115
|
+
if (request.credits === null || request.promptTokens === null || request.completionTokens === null) {
|
|
116
|
+
plan.skippedChat.noBilling += 1;
|
|
117
|
+
continue;
|
|
118
|
+
}
|
|
119
|
+
if (!rates) {
|
|
120
|
+
plan.skippedChat.noRates += 1;
|
|
121
|
+
continue;
|
|
122
|
+
}
|
|
123
|
+
const rate = request.model ? rates.models.get(request.model) : undefined;
|
|
124
|
+
const rounds = rate
|
|
125
|
+
? reconstructRounds({
|
|
126
|
+
rounds: request.roundTimes.length,
|
|
127
|
+
promptTokens: request.promptTokens,
|
|
128
|
+
completionTokens: request.completionTokens,
|
|
129
|
+
credits: request.credits,
|
|
130
|
+
}, rate.tiers, rates.creditUsd)
|
|
131
|
+
: undefined;
|
|
132
|
+
if (!rounds) {
|
|
133
|
+
const model = request.model ?? 'sconosciuto';
|
|
134
|
+
plan.skippedChat.unpriced.set(model, (plan.skippedChat.unpriced.get(model) ?? 0) + 1);
|
|
135
|
+
continue;
|
|
136
|
+
}
|
|
137
|
+
rounds.forEach((usage, index) => {
|
|
138
|
+
plan.events.push({
|
|
139
|
+
...base(repository, 'vscode-chat'),
|
|
140
|
+
// Deterministico: rilanciare il caricamento non duplica nulla.
|
|
141
|
+
requestId: `vscode-chat:${request.requestId}:${index}`,
|
|
142
|
+
occurredAt: request.roundTimes[index].toISOString(),
|
|
143
|
+
sessionId: request.sessionId,
|
|
144
|
+
endpoint: '/reload/vscode-chat',
|
|
145
|
+
model: request.model,
|
|
146
|
+
usage,
|
|
147
|
+
durationMs: null,
|
|
148
|
+
});
|
|
149
|
+
});
|
|
150
|
+
plan.chatCredits += request.credits;
|
|
151
|
+
plan.sources['vscode-chat'] += 1;
|
|
152
|
+
}
|
|
153
|
+
plan.events.sort((a, b) => a.occurredAt.localeCompare(b.occurredAt));
|
|
154
|
+
return plan;
|
|
155
|
+
}
|
|
156
|
+
/** Legge le sessioni salvate sulla macchina. */
|
|
157
|
+
export function readLocalSessions(options) {
|
|
158
|
+
return {
|
|
159
|
+
cliCalls: readCliCalls(undefined, options.from),
|
|
160
|
+
chatRequests: readChatRequests(undefined, options.from),
|
|
161
|
+
};
|
|
162
|
+
}
|
|
163
|
+
function ratesUrl(collectorUrl) {
|
|
164
|
+
return new URL('rates', collectorUrl.replace(/\/+$/, '')).toString();
|
|
165
|
+
}
|
|
166
|
+
/** Tariffe dei modelli dal collector: le stesse con cui verranno prezzati gli eventi. */
|
|
167
|
+
export async function fetchRates(config, models) {
|
|
168
|
+
const url = new URL(ratesUrl(config.collectorUrl));
|
|
169
|
+
for (const model of models)
|
|
170
|
+
url.searchParams.append('model', model);
|
|
171
|
+
const response = await fetch(url, {
|
|
172
|
+
headers: collectorHeaders(config),
|
|
173
|
+
signal: AbortSignal.timeout(config.collectorTimeoutMs),
|
|
174
|
+
});
|
|
175
|
+
if (response.status === 404) {
|
|
176
|
+
throw new Error("il collector non espone ancora /v1/rates: va aggiornato prima di caricare le chat di VS Code");
|
|
177
|
+
}
|
|
178
|
+
if (!response.ok)
|
|
179
|
+
throw new Error(`il collector risponde ${response.status} alla richiesta del listino`);
|
|
180
|
+
const body = (await response.json());
|
|
181
|
+
return { creditUsd: body.creditUsd, models: new Map(Object.entries(body.models)) };
|
|
182
|
+
}
|
|
183
|
+
export function chatModels(requests) {
|
|
184
|
+
return [...new Set(requests.map((request) => request.model).filter((model) => !!model))];
|
|
185
|
+
}
|
|
186
|
+
/**
|
|
187
|
+
* Invia gli eventi in batch, in ordine. Al primo errore si ferma: le chiavi
|
|
188
|
+
* sono deterministiche e il collector deduplica, quindi rilanciare riprende
|
|
189
|
+
* senza doppioni.
|
|
190
|
+
*/
|
|
191
|
+
export async function sendEvents(config, events, onProgress) {
|
|
192
|
+
const result = { accepted: 0, rejected: 0, failed: 0 };
|
|
193
|
+
const batches = chunk(events, MAX_EVENTS_PER_BATCH);
|
|
194
|
+
for (let index = 0; index < batches.length; index += 1) {
|
|
195
|
+
const batch = batches[index];
|
|
196
|
+
let response;
|
|
197
|
+
try {
|
|
198
|
+
response = await fetch(config.collectorUrl, {
|
|
199
|
+
method: 'POST',
|
|
200
|
+
headers: collectorHeaders(config),
|
|
201
|
+
body: JSON.stringify({ events: batch }),
|
|
202
|
+
signal: AbortSignal.timeout(config.collectorTimeoutMs),
|
|
203
|
+
});
|
|
204
|
+
}
|
|
205
|
+
catch (error) {
|
|
206
|
+
result.failed = batches.slice(index).flat().length;
|
|
207
|
+
result.error = `collector irraggiungibile: ${error.message}`;
|
|
208
|
+
return result;
|
|
209
|
+
}
|
|
210
|
+
if (!response.ok) {
|
|
211
|
+
result.failed = batches.slice(index).flat().length;
|
|
212
|
+
result.error = `il collector risponde ${response.status}`;
|
|
213
|
+
return result;
|
|
214
|
+
}
|
|
215
|
+
const body = (await response.json().catch(() => ({})));
|
|
216
|
+
const rejected = Array.isArray(body.rejected) ? body.rejected.length : 0;
|
|
217
|
+
result.rejected += rejected;
|
|
218
|
+
result.accepted += batch.length - rejected;
|
|
219
|
+
onProgress?.(result.accepted + result.rejected);
|
|
220
|
+
}
|
|
221
|
+
return result;
|
|
222
|
+
}
|
|
223
|
+
/**
|
|
224
|
+
* Primo avvio del proxy registrato nel suo log. Da li' in poi il traffico di
|
|
225
|
+
* questa postazione e' probabilmente gia' nel collector.
|
|
226
|
+
*/
|
|
227
|
+
export function proxyFirstStart(logFile = join(configDir(), 'proxy.log')) {
|
|
228
|
+
let content;
|
|
229
|
+
try {
|
|
230
|
+
content = readFileSync(logFile, 'utf-8');
|
|
231
|
+
}
|
|
232
|
+
catch {
|
|
233
|
+
return undefined;
|
|
234
|
+
}
|
|
235
|
+
for (const line of content.split('\n')) {
|
|
236
|
+
if (!line.includes('Server listening'))
|
|
237
|
+
continue;
|
|
238
|
+
try {
|
|
239
|
+
const time = JSON.parse(line).time;
|
|
240
|
+
if (typeof time === 'number')
|
|
241
|
+
return new Date(time);
|
|
242
|
+
}
|
|
243
|
+
catch {
|
|
244
|
+
// Riga non JSON: si passa alla prossima.
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
return undefined;
|
|
248
|
+
}
|
|
249
|
+
//# sourceMappingURL=index.js.map
|