mirror of
https://github.com/google-gemini/gemini-cli.git
synced 2026-05-13 05:12:55 -07:00
This commit is contained in:
@@ -22,13 +22,82 @@ import WebSocket from 'ws';
|
|||||||
const ACTIVITY_ID_HEADER = 'x-activity-request-id';
|
const ACTIVITY_ID_HEADER = 'x-activity-request-id';
|
||||||
const MAX_BUFFER_SIZE = 100;
|
const MAX_BUFFER_SIZE = 100;
|
||||||
|
|
||||||
/** Type guard: Array.isArray doesn't narrow readonly arrays in TS 5.8 */
|
|
||||||
function isHeaderRecord(
|
function isHeaderRecord(
|
||||||
h: http.OutgoingHttpHeaders | readonly string[],
|
h: http.OutgoingHttpHeaders | readonly string[],
|
||||||
): h is http.OutgoingHttpHeaders {
|
): h is http.OutgoingHttpHeaders {
|
||||||
return !Array.isArray(h);
|
return !Array.isArray(h);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function isRequestOptions(value: unknown): value is http.RequestOptions {
|
||||||
|
return (
|
||||||
|
typeof value === 'object' &&
|
||||||
|
value !== null &&
|
||||||
|
!(value instanceof URL) &&
|
||||||
|
!Array.isArray(value)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function isIncomingMessageCallback(
|
||||||
|
value: unknown,
|
||||||
|
): value is (res: http.IncomingMessage) => void {
|
||||||
|
return typeof value === 'function';
|
||||||
|
}
|
||||||
|
|
||||||
|
type HttpRequestArgs =
|
||||||
|
| []
|
||||||
|
| [
|
||||||
|
url: string | URL | http.RequestOptions,
|
||||||
|
options?: http.RequestOptions | ((res: http.IncomingMessage) => void),
|
||||||
|
callback?: (res: http.IncomingMessage) => void,
|
||||||
|
];
|
||||||
|
|
||||||
|
function callHttpRequest(
|
||||||
|
originalFn: typeof http.request,
|
||||||
|
args: HttpRequestArgs,
|
||||||
|
): http.ClientRequest {
|
||||||
|
if (args.length === 0) {
|
||||||
|
return originalFn({});
|
||||||
|
}
|
||||||
|
if (args.length === 1) {
|
||||||
|
const first = args[0];
|
||||||
|
if (typeof first === 'string' || first instanceof URL) {
|
||||||
|
return originalFn(first);
|
||||||
|
}
|
||||||
|
if (isRequestOptions(first)) {
|
||||||
|
return originalFn(first);
|
||||||
|
}
|
||||||
|
return originalFn({});
|
||||||
|
}
|
||||||
|
if (args.length === 2) {
|
||||||
|
const first = args[0];
|
||||||
|
const second = args[1];
|
||||||
|
if (typeof first === 'string' || first instanceof URL) {
|
||||||
|
if (isIncomingMessageCallback(second)) {
|
||||||
|
return originalFn(first, second);
|
||||||
|
}
|
||||||
|
if (isRequestOptions(second)) {
|
||||||
|
return originalFn(first, second);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (isRequestOptions(first) && isIncomingMessageCallback(second)) {
|
||||||
|
return originalFn(first, second);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (args.length === 3) {
|
||||||
|
const first = args[0];
|
||||||
|
const second = args[1];
|
||||||
|
const third = args[2];
|
||||||
|
if (
|
||||||
|
(typeof first === 'string' || first instanceof URL) &&
|
||||||
|
isRequestOptions(second) &&
|
||||||
|
isIncomingMessageCallback(third)
|
||||||
|
) {
|
||||||
|
return originalFn(first, second, third);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return originalFn({});
|
||||||
|
}
|
||||||
|
|
||||||
export interface NetworkLog {
|
export interface NetworkLog {
|
||||||
id: string;
|
id: string;
|
||||||
timestamp: number;
|
timestamp: number;
|
||||||
@@ -364,7 +433,7 @@ export class ActivityLogger extends EventEmitter {
|
|||||||
|
|
||||||
const wrapRequest = (
|
const wrapRequest = (
|
||||||
originalFn: typeof http.request,
|
originalFn: typeof http.request,
|
||||||
args: unknown[],
|
args: HttpRequestArgs,
|
||||||
protocol: string,
|
protocol: string,
|
||||||
) => {
|
) => {
|
||||||
const firstArg = args[0];
|
const firstArg = args[0];
|
||||||
@@ -373,8 +442,10 @@ export class ActivityLogger extends EventEmitter {
|
|||||||
options = firstArg;
|
options = firstArg;
|
||||||
} else if (firstArg instanceof URL) {
|
} else if (firstArg instanceof URL) {
|
||||||
options = firstArg;
|
options = firstArg;
|
||||||
|
} else if (firstArg && typeof firstArg === 'object') {
|
||||||
|
options = isRequestOptions(firstArg) ? firstArg : {};
|
||||||
} else {
|
} else {
|
||||||
options = (firstArg ?? {}) as http.RequestOptions;
|
options = {};
|
||||||
}
|
}
|
||||||
|
|
||||||
let url = '';
|
let url = '';
|
||||||
@@ -393,9 +464,9 @@ export class ActivityLogger extends EventEmitter {
|
|||||||
`${protocol}//${options.hostname || options.host || 'localhost'}${options.path || '/'}`;
|
`${protocol}//${options.hostname || options.host || 'localhost'}${options.path || '/'}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (url.includes('127.0.0.1') || url.includes('localhost'))
|
if (url.includes('127.0.0.1') || url.includes('localhost')) {
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-type-assertion
|
return callHttpRequest(originalFn, args);
|
||||||
return originalFn.apply(http, args as any);
|
}
|
||||||
|
|
||||||
const rawHeaders =
|
const rawHeaders =
|
||||||
typeof options === 'object' &&
|
typeof options === 'object' &&
|
||||||
@@ -410,24 +481,23 @@ export class ActivityLogger extends EventEmitter {
|
|||||||
|
|
||||||
if (headers[ACTIVITY_ID_HEADER]) {
|
if (headers[ACTIVITY_ID_HEADER]) {
|
||||||
delete headers[ACTIVITY_ID_HEADER];
|
delete headers[ACTIVITY_ID_HEADER];
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-type-assertion
|
return callHttpRequest(originalFn, args);
|
||||||
return originalFn.apply(http, args as any);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const id = Math.random().toString(36).substring(7);
|
const id = Math.random().toString(36).substring(7);
|
||||||
this.requestStartTimes.set(id, Date.now());
|
this.requestStartTimes.set(id, Date.now());
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-type-assertion
|
const req = callHttpRequest(originalFn, args);
|
||||||
const req = originalFn.apply(http, args as any);
|
|
||||||
const requestChunks: Buffer[] = [];
|
const requestChunks: Buffer[] = [];
|
||||||
|
|
||||||
const oldWrite = req.write;
|
const oldWrite = req.write;
|
||||||
const oldEnd = req.end;
|
const oldEnd = req.end;
|
||||||
|
|
||||||
req.write = function (chunk: unknown, ...etc: unknown[]) {
|
req.write = function (chunk: string | Uint8Array, ...etc: unknown[]) {
|
||||||
if (chunk) {
|
if (chunk) {
|
||||||
const encoding =
|
const encoding =
|
||||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
|
typeof etc[0] === 'string' && Buffer.isEncoding(etc[0])
|
||||||
typeof etc[0] === 'string' ? (etc[0] as BufferEncoding) : undefined;
|
? etc[0]
|
||||||
|
: undefined;
|
||||||
requestChunks.push(
|
requestChunks.push(
|
||||||
Buffer.isBuffer(chunk)
|
Buffer.isBuffer(chunk)
|
||||||
? chunk
|
? chunk
|
||||||
@@ -438,19 +508,21 @@ export class ActivityLogger extends EventEmitter {
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-type-assertion
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-type-assertion, @typescript-eslint/no-unsafe-return
|
||||||
return oldWrite.apply(this, [chunk, ...etc] as any);
|
return (oldWrite as any).apply(this, [chunk, ...etc]);
|
||||||
};
|
};
|
||||||
|
|
||||||
req.end = function (
|
req.end = function (
|
||||||
this: http.ClientRequest,
|
this: http.ClientRequest,
|
||||||
chunk: unknown,
|
chunkOrCb?: string | Uint8Array | (() => void),
|
||||||
...etc: unknown[]
|
...etc: unknown[]
|
||||||
) {
|
) {
|
||||||
if (chunk && typeof chunk !== 'function') {
|
const chunk = typeof chunkOrCb === 'function' ? undefined : chunkOrCb;
|
||||||
|
if (chunk) {
|
||||||
const encoding =
|
const encoding =
|
||||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
|
typeof etc[0] === 'string' && Buffer.isEncoding(etc[0])
|
||||||
typeof etc[0] === 'string' ? (etc[0] as BufferEncoding) : undefined;
|
? etc[0]
|
||||||
|
: undefined;
|
||||||
requestChunks.push(
|
requestChunks.push(
|
||||||
Buffer.isBuffer(chunk)
|
Buffer.isBuffer(chunk)
|
||||||
? chunk
|
? chunk
|
||||||
@@ -473,7 +545,7 @@ export class ActivityLogger extends EventEmitter {
|
|||||||
pending: true,
|
pending: true,
|
||||||
});
|
});
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-type-assertion, @typescript-eslint/no-unsafe-return
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-type-assertion, @typescript-eslint/no-unsafe-return
|
||||||
return (oldEnd as any).apply(this, [chunk, ...etc]);
|
return (oldEnd as any).apply(this, [chunkOrCb, ...etc]);
|
||||||
};
|
};
|
||||||
|
|
||||||
req.on('response', (res: http.IncomingMessage) => {
|
req.on('response', (res: http.IncomingMessage) => {
|
||||||
@@ -545,12 +617,44 @@ export class ActivityLogger extends EventEmitter {
|
|||||||
return req;
|
return req;
|
||||||
};
|
};
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-type-assertion
|
Object.defineProperty(http, 'request', {
|
||||||
(http as any).request = (...args: unknown[]) =>
|
value: (
|
||||||
wrapRequest(originalRequest, args, 'http:');
|
url: string | URL | http.RequestOptions,
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-type-assertion
|
options?: http.RequestOptions | ((res: http.IncomingMessage) => void),
|
||||||
(https as any).request = (...args: unknown[]) =>
|
callback?: (res: http.IncomingMessage) => void,
|
||||||
wrapRequest(originalHttpsRequest as typeof http.request, args, 'https:');
|
): http.ClientRequest => {
|
||||||
|
const args: HttpRequestArgs =
|
||||||
|
callback !== undefined
|
||||||
|
? [url, options, callback]
|
||||||
|
: options !== undefined
|
||||||
|
? [url, options]
|
||||||
|
: [url];
|
||||||
|
return wrapRequest(originalRequest, args, 'http:');
|
||||||
|
},
|
||||||
|
writable: true,
|
||||||
|
configurable: true,
|
||||||
|
});
|
||||||
|
Object.defineProperty(https, 'request', {
|
||||||
|
value: (
|
||||||
|
url: string | URL | http.RequestOptions,
|
||||||
|
options?: http.RequestOptions | ((res: http.IncomingMessage) => void),
|
||||||
|
callback?: (res: http.IncomingMessage) => void,
|
||||||
|
): http.ClientRequest => {
|
||||||
|
const args: HttpRequestArgs =
|
||||||
|
callback !== undefined
|
||||||
|
? [url, options, callback]
|
||||||
|
: options !== undefined
|
||||||
|
? [url, options]
|
||||||
|
: [url];
|
||||||
|
return wrapRequest(
|
||||||
|
originalHttpsRequest as typeof http.request,
|
||||||
|
args,
|
||||||
|
'https:',
|
||||||
|
);
|
||||||
|
},
|
||||||
|
writable: true,
|
||||||
|
configurable: true,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
logConsole(payload: ConsoleLogPayload) {
|
logConsole(payload: ConsoleLogPayload) {
|
||||||
|
|||||||
Reference in New Issue
Block a user