feat: HTTP + HTTPS proxy support (#139)

Co-authored-by: Hiroki Osame <hiroki.osame@gmail.com>
This commit is contained in:
Sam Büth
2023-03-27 08:51:51 +02:00
committed by GitHub
parent 6e02dc8f81
commit a0db0f3ece
7 changed files with 77 additions and 17 deletions

View File

@@ -35,8 +35,10 @@ export default async (
staged.files.map(file => ` ${file}`).join('\n')
}`);
const { env } = process;
const config = await getConfig({
OPENAI_KEY: process.env.OPENAI_KEY ?? process.env.OPENAI_API_KEY,
OPENAI_KEY: env.OPENAI_KEY || env.OPENAI_API_KEY,
proxy: env.https_proxy || env.HTTPS_PROXY || env.http_proxy || env.HTTP_PROXY,
generate: generate?.toString(),
});
@@ -49,6 +51,7 @@ export default async (
config.locale,
staged.diff,
config.generate,
config.proxy,
);
} finally {
s.stop('Changes analyzed');

View File

@@ -30,7 +30,10 @@ export default () => (async () => {
intro(bgCyan(black(' aicommits ')));
const config = await getConfig();
const { env } = process;
const config = await getConfig({
proxy: env.https_proxy || env.HTTPS_PROXY || env.http_proxy || env.HTTP_PROXY,
});
const s = spinner();
s.start('The AI is analyzing your changes');
@@ -41,6 +44,7 @@ export default () => (async () => {
config.locale,
staged!.diff,
config.generate,
config.proxy,
);
} finally {
s.stop('Changes analyzed');

View File

@@ -51,6 +51,15 @@ const configParsers = {
return parsed;
},
proxy(url?: string) {
if (!url || url.length === 0) {
return undefined;
}
parseAssert('proxy', /^https?:\/\//.test(url), 'Must be a valid URL');
return url;
},
} as const;
type ConfigKeys = keyof typeof configParsers;

View File

@@ -2,6 +2,7 @@ import https from 'https';
import type { ClientRequest, IncomingMessage } from 'http';
import type { CreateChatCompletionRequest, CreateChatCompletionResponse } from 'openai';
import { encoding_for_model as encodingForModel } from '@dqbd/tiktoken';
import createHttpsProxyAgent from 'https-proxy-agent';
import { KnownError } from './error.js';
const httpsPost = async (
@@ -9,6 +10,7 @@ const httpsPost = async (
path: string,
headers: Record<string, string>,
json: unknown,
proxy?: string,
) => new Promise<{
request: ClientRequest;
response: IncomingMessage;
@@ -27,6 +29,11 @@ const httpsPost = async (
'Content-Length': Buffer.byteLength(postContent),
},
timeout: 10_000, // 10s
agent: (
proxy
? createHttpsProxyAgent(proxy)
: undefined
),
},
(response) => {
const body: Buffer[] = [];
@@ -53,6 +60,7 @@ const httpsPost = async (
const createChatCompletion = async (
apiKey: string,
json: CreateChatCompletionRequest,
proxy?: string,
) => {
const { response, data } = await httpsPost(
'api.openai.com',
@@ -61,6 +69,7 @@ const createChatCompletion = async (
Authorization: `Bearer ${apiKey}`,
},
json,
proxy,
);
if (
@@ -97,6 +106,7 @@ export const generateCommitMessage = async (
locale: string,
diff: string,
completions: number,
proxy?: string,
) => {
const prompt = getPrompt(locale, diff);
@@ -109,20 +119,24 @@ export const generateCommitMessage = async (
}
try {
const completion = await createChatCompletion(apiKey, {
model,
messages: [{
role: 'user',
content: prompt,
}],
temperature: 0.7,
top_p: 1,
frequency_penalty: 0,
presence_penalty: 0,
max_tokens: 200,
stream: false,
n: completions,
});
const completion = await createChatCompletion(
apiKey,
{
model,
messages: [{
role: 'user',
content: prompt,
}],
temperature: 0.7,
top_p: 1,
frequency_penalty: 0,
presence_penalty: 0,
max_tokens: 200,
stream: false,
n: completions,
},
proxy,
);
return deduplicateMessages(
completion.choices