diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 4847dae..869743e 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -61,13 +61,13 @@ Once Prettier is installed, you can run it on a single file or multiple files us 1. For a single file: ```sh -prettier --write path/to/your/file.js +prettier --write path/to/your/file.ts ``` 2. For a multiple file: ```sh -prettier --write "src/**/*.js" +prettier --write "src/**/*.ts" ``` If you use Vscode, It is recommended to use [prettier-vscode][https://github.com/prettier/prettier-vscode] diff --git a/package-lock.json b/package-lock.json index 98f7fc7..69ffeea 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,6 +8,7 @@ "name": "@builder.io/ai-shell", "version": "1.0.6", "dependencies": { + "@azure/openai": "^1.0.0-beta.5", "@clack/core": "latest", "@clack/prompts": "latest", "@dqbd/tiktoken": "^1.0.2", @@ -40,6 +41,174 @@ "typescript": "^4.9.5" } }, + "node_modules/@azure-rest/core-client": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/@azure-rest/core-client/-/core-client-1.1.4.tgz", + "integrity": "sha512-RUIQOA8T0WcbNlddr8hjl2MuC5GVRqmMwPXqBVsgvdKesLy+eg3y/6nf3qe2fvcJMI1gF6VtgU5U4hRaR4w4ag==", + "dependencies": { + "@azure/abort-controller": "^1.1.0", + "@azure/core-auth": "^1.3.0", + "@azure/core-rest-pipeline": "^1.5.0", + "@azure/core-tracing": "^1.0.1", + "@azure/core-util": "^1.0.0", + "tslib": "^2.2.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@azure-rest/core-client/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@azure/abort-controller": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@azure/abort-controller/-/abort-controller-1.1.0.tgz", + "integrity": "sha512-TrRLIoSQVzfAJX9H1JeFjzAoDGcoK1IYX1UImfceTZpsyYfWr09Ss1aHW1y5TrrR3iq6RZLBwJ3E24uwPhwahw==", + "dependencies": { + "tslib": "^2.2.0" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/@azure/abort-controller/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@azure/core-auth": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@azure/core-auth/-/core-auth-1.5.0.tgz", + "integrity": "sha512-udzoBuYG1VBoHVohDTrvKjyzel34zt77Bhp7dQntVGGD0ehVq48owENbBG8fIgkHRNUBQH5k1r0hpoMu5L8+kw==", + "dependencies": { + "@azure/abort-controller": "^1.0.0", + "@azure/core-util": "^1.1.0", + "tslib": "^2.2.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@azure/core-auth/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@azure/core-lro": { + "version": "2.5.4", + "resolved": "https://registry.npmjs.org/@azure/core-lro/-/core-lro-2.5.4.tgz", + "integrity": "sha512-3GJiMVH7/10bulzOKGrrLeG/uCBH/9VtxqaMcB9lIqAeamI/xYQSHJL/KcsLDuH+yTjYpro/u6D/MuRe4dN70Q==", + "dependencies": { + "@azure/abort-controller": "^1.0.0", + "@azure/core-util": "^1.2.0", + "@azure/logger": "^1.0.0", + "tslib": "^2.2.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@azure/core-lro/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@azure/core-rest-pipeline": { + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/@azure/core-rest-pipeline/-/core-rest-pipeline-1.12.0.tgz", + "integrity": "sha512-+MnSB0vGZjszSzr5AW8z93/9fkDu2RLtWmAN8gskURq7EW2sSwqy8jZa0V26rjuBVkwhdA3Hw8z3VWoeBUOw+A==", + "dependencies": { + "@azure/abort-controller": "^1.0.0", + "@azure/core-auth": "^1.4.0", + "@azure/core-tracing": "^1.0.1", + "@azure/core-util": "^1.3.0", + "@azure/logger": "^1.0.0", + "form-data": "^4.0.0", + "http-proxy-agent": "^5.0.0", + "https-proxy-agent": "^5.0.0", + "tslib": "^2.2.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@azure/core-rest-pipeline/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@azure/core-tracing": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@azure/core-tracing/-/core-tracing-1.0.1.tgz", + "integrity": "sha512-I5CGMoLtX+pI17ZdiFJZgxMJApsK6jjfm85hpgp3oazCdq5Wxgh4wMr7ge/TTWW1B5WBuvIOI1fMU/FrOAMKrw==", + "dependencies": { + "tslib": "^2.2.0" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/@azure/core-tracing/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@azure/core-util": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@azure/core-util/-/core-util-1.4.0.tgz", + "integrity": "sha512-eGAyJpm3skVQoLiRqm/xPa+SXi/NPDdSHMxbRAz2lSprd+Zs+qrpQGQQ2VQ3Nttu+nSZR4XoYQC71LbEI7jsig==", + "dependencies": { + "@azure/abort-controller": "^1.0.0", + "tslib": "^2.2.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@azure/core-util/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@azure/logger": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@azure/logger/-/logger-1.0.4.tgz", + "integrity": "sha512-ustrPY8MryhloQj7OWGe+HrYx+aoiOxzbXTtgblbV3xwCqpzUK36phH3XNHQKj3EPonyFUuDTfR3qFhTEAuZEg==", + "dependencies": { + "tslib": "^2.2.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@azure/logger/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/@azure/openai": { + "version": "1.0.0-beta.5", + "resolved": "https://registry.npmjs.org/@azure/openai/-/openai-1.0.0-beta.5.tgz", + "integrity": "sha512-Qjb6eXun6OUGwbHMRYtmjojn8wZf5ATGQHFzxPc+/dWFeLdSj5ahs/yWRAgqff3oL6GmgQFhjCPhAnAbVv5Q3w==", + "dependencies": { + "@azure-rest/core-client": "^1.1.3", + "@azure/core-auth": "^1.4.0", + "@azure/core-lro": "^2.5.3", + "@azure/core-rest-pipeline": "^1.10.2", + "@azure/logger": "^1.0.3", + "tslib": "^2.4.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@azure/openai/node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, "node_modules/@babel/runtime": { "version": "7.21.5", "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.21.5.tgz", @@ -901,6 +1070,14 @@ } } }, + "node_modules/@tootallnate/once": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", + "integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==", + "engines": { + "node": ">= 10" + } + }, "node_modules/@types/dedent": { "version": "0.7.0", "resolved": "https://registry.npmjs.org/@types/dedent/-/dedent-0.7.0.tgz", @@ -1174,6 +1351,17 @@ "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, + "node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, "node_modules/ajv": { "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", @@ -1516,7 +1704,6 @@ "version": "4.3.4", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dev": true, "dependencies": { "ms": "2.1.2" }, @@ -2140,6 +2327,31 @@ "node": ">=8" } }, + "node_modules/http-proxy-agent": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz", + "integrity": "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==", + "dependencies": { + "@tootallnate/once": "2", + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "dependencies": { + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/human-signals": { "version": "4.3.1", "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-4.3.1.tgz", @@ -2522,8 +2734,7 @@ "node_modules/ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" }, "node_modules/natural-compare": { "version": "1.4.0", diff --git a/package.json b/package.json index 1b94e8a..3a3658e 100644 --- a/package.json +++ b/package.json @@ -4,6 +4,7 @@ "version": "1.0.6", "type": "module", "dependencies": { + "@azure/openai": "^1.0.0-beta.5", "@clack/core": "latest", "@clack/prompts": "latest", "@dqbd/tiktoken": "^1.0.2", diff --git a/src/commands/chat.ts b/src/commands/chat.ts index ff234d8..e871275 100644 --- a/src/commands/chat.ts +++ b/src/commands/chat.ts @@ -62,7 +62,9 @@ export default command( role: 'assistant', content: fullResponse, }); - console.log(''); + if (!fullResponse.endsWith('\n')) { + console.log(''); + } console.log(''); prompt(); }; diff --git a/src/helpers/completion.ts b/src/helpers/completion.ts index e726fee..170d034 100644 --- a/src/helpers/completion.ts +++ b/src/helpers/completion.ts @@ -8,6 +8,9 @@ import type { AxiosError } from 'axios'; import { streamToString } from './stream-to-string'; import './replace-all-polyfill'; import i18n from './i18n'; +import { getConfig } from './config'; + +import { OpenAIClient, AzureKeyCredential } from '@azure/openai'; const explainInSecondRequest = true; @@ -18,9 +21,9 @@ function getOpenAi(key: string, apiEndpoint: string) { return openAi; } -// Openai outputs markdown format for code blocks. It oftne uses +// Openai outputs markdown format for code blocks. It often uses // a github style like: "```bash" -const shellCodeStartRegex = /```[^\n]*/gi; +const shellCodeStartRegex = /```[^\n]*\n?/gi; export async function getScriptAndInfo({ prompt, @@ -66,8 +69,20 @@ export async function generateCompletion({ key: string; apiEndpoint: string; }) { - const openAi = getOpenAi(key, apiEndpoint); try { + if (apiEndpoint.endsWith('.openai.azure.com')) { + const { AZURE_OPENAI_DEPLOYMENT: deployment } = await getConfig(); + const messages = Array.isArray(prompt) + ? prompt + : [{ role: 'user', content: prompt }]; + const client = new OpenAIClient(apiEndpoint, new AzureKeyCredential(key)); + const deploymentId = deployment; + const events = client.listChatCompletions(deploymentId, messages, { + maxTokens: 1024, + }); + return events; + } + const openAi = getOpenAi(key, apiEndpoint); const completion = await openAi.createChatCompletion( { model: model || 'gpt-3.5-turbo', @@ -216,14 +231,12 @@ export const readData = } if (excluded) break; } - if (content && waitUntilNewline) { if (!content.includes('\n')) { continue; } waitUntilNewline = false; } - if (dataStart && content) { const contentWithoutExcluded = excluded ? content.replaceAll(excluded, '') diff --git a/src/helpers/config.ts b/src/helpers/config.ts index a536270..6001a6b 100644 --- a/src/helpers/config.ts +++ b/src/helpers/config.ts @@ -36,6 +36,13 @@ const configParsers = { return key; }, + AZURE_OPENAI_DEPLOYMENT(name?: string) { + if (!name || name.length === 0) { + return 'gpt-35-turbo'; + } + + return name; + }, MODEL(model?: string) { if (!model || model.length === 0) { return 'gpt-3.5-turbo'; @@ -140,6 +147,13 @@ export const showConfigUI = async () => { ? config.SILENT_MODE.toString() : i18n.t('(not set)'), }, + { + label: i18n.t('Azure OpenAI Deployment'), + value: 'AZURE_OPENAI_DEPLOYMENT', + hint: hasOwn(config, 'AZURE_OPENAI_DEPLOYMENT') + ? config.AZURE_OPENAI_DEPLOYMENT.toString() + : i18n.t('(not set)'), + }, { label: i18n.t('Model'), value: 'MODEL', @@ -179,6 +193,12 @@ export const showConfigUI = async () => { }); if (p.isCancel(apiEndpoint)) return; await setConfigs([['OPENAI_API_ENDPOINT', apiEndpoint]]); + } else if (choice === 'AZURE_OPENAI_DEPLOYMENT') { + const deploymentId = await p.text({ + message: i18n.t('Enter your Azure OpenAI API Deployment ID'), + }); + if (p.isCancel(deploymentId)) return; + await setConfigs([['AZURE_OPENAI_DEPLOYMENT', deploymentId]]); } else if (choice === 'SILENT_MODE') { const silentMode = await p.confirm({ message: i18n.t('Enable silent mode?'), diff --git a/src/helpers/i18n.ts b/src/helpers/i18n.ts index c62f0af..5f1b03e 100644 --- a/src/helpers/i18n.ts +++ b/src/helpers/i18n.ts @@ -85,7 +85,7 @@ i18next.init({ */ const t = (key: string): string => { if (!currentlang || currentlang === 'en') return key; - return i18next.t(key) as string; + return (i18next.t(key) || key) as string; }; const setLanguage = (lang: string) => { diff --git a/src/helpers/stream-to-iterable.ts b/src/helpers/stream-to-iterable.ts index f2bbbe4..4807c67 100644 --- a/src/helpers/stream-to-iterable.ts +++ b/src/helpers/stream-to-iterable.ts @@ -1,16 +1,54 @@ import { IncomingMessage } from 'http'; +import type { ChatCompletions } from '@azure/openai'; -export async function* streamToIterable(stream: IncomingMessage) { +export async function* streamToIterable( + stream: IncomingMessage | AsyncIterable +) { let previous = ''; - for await (const chunk of stream) { - const bufferChunk = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk); - previous += bufferChunk; - let eolIndex; - while ((eolIndex = previous.indexOf('\n')) >= 0) { - // line includes the EOL - const line = previous.slice(0, eolIndex + 1).trimEnd(); - if (line.startsWith('data: ')) yield line; - previous = previous.slice(eolIndex + 1); + if (!(stream instanceof IncomingMessage)) { + for await (const chunk of stream) { + const choice = chunk.choices[0]; + if (!choice) continue; + const delta = choice.delta?.content; + if (delta !== undefined) { + previous += delta; + } + if (previous.indexOf('\n') >= 0) { + previous = previous.replace(/^```([^\n]+)```$/gi, '```\n$1\n```'); + const lines = previous.split('\n'); + for (let i = 0; i < lines.length - 1; i++) { + let line = lines[i]; + const msg = { + choices: [{ delta: { content: `${line}\n` } }], + }; + yield `data: ${JSON.stringify(msg)}`; + } + previous = lines[lines.length - 1]; + } + } + + if (previous) { + previous = previous.replace(/^```([^\n]+)```$/gi, '```\n$1\n```'); + const lines = previous.split('\n'); + for (let i = 0; i < lines.length; i++) { + let line = lines[i]; + const msg = { + choices: [{ delta: { content: `${line}\n` } }], + }; + yield `data: ${JSON.stringify(msg)}`; + } + } + } else { + for await (const chunk of stream) { + const bufferChunk = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk); + previous += bufferChunk; + let eolIndex; + while ((eolIndex = previous.indexOf('\n')) >= 0) { + // line includes the EOL + const line = previous.slice(0, eolIndex + 1).trimEnd(); + if (line.startsWith('data: ')) yield line; + previous = previous.slice(eolIndex + 1); + } } } } diff --git a/src/locales/ar.json b/src/locales/ar.json index f7e4ba4..38579c3 100644 --- a/src/locales/ar.json +++ b/src/locales/ar.json @@ -54,5 +54,7 @@ "Missing required parameter": "معلمة مطلوبة مفقودة", "Please open a Bug report with the information above": "يرجى فتح تقرير خلل مع المعلومات أعلاه", "Prompt to run": "تشغيل التعليمات", - "You": "أنت" + "You": "أنت", + "Azure OpenAI Deployment": " نشر Azure OpenAI", + "Enter your Azure OpenAI API Deployment ID": "أدخل معرف نشر Azure OpenAI API الخاص بك" } diff --git a/src/locales/de.json b/src/locales/de.json index e740ddb..109513b 100644 --- a/src/locales/de.json +++ b/src/locales/de.json @@ -54,5 +54,7 @@ "Missing required parameter": "Fehlender erforderlicher Parameter", "Please open a Bug report with the information above": "Bitte öffnen Sie einen Fehlerbericht mit den oben genannten Informationen", "Prompt to run": "Aufforderung zum Ausführen", - "You": "Sie" + "You": "Sie", + "Azure OpenAI Deployment": "Azure OpenAI-Bereitstellung", + "Enter your Azure OpenAI API Deployment ID": "Geben Sie Ihre Azure OpenAI API-Bereitstellungs-ID ein" } diff --git a/src/locales/en.json b/src/locales/en.json index 0bd4278..f2ed3c5 100644 --- a/src/locales/en.json +++ b/src/locales/en.json @@ -54,5 +54,7 @@ "Missing required parameter": "Missing required parameter", "Please open a Bug report with the information above": "Please open a Bug report with the information above", "Prompt to run": "Prompt to run", - "You": "You" + "You": "You", + "Azure OpenAI Deployment": "Azure OpenAI Deployment", + "Enter your Azure OpenAI API Deployment ID": "Enter your Azure OpenAI API Deployment ID" } diff --git a/src/locales/es.json b/src/locales/es.json index 409761d..19cf73c 100644 --- a/src/locales/es.json +++ b/src/locales/es.json @@ -54,5 +54,7 @@ "Missing required parameter": "Falta el parámetro requerido", "Please open a Bug report with the information above": "Por favor abra un informe de error con la información anterior", "Prompt to run": "Indicio para ejecutar", - "You": "Tú" + "You": "Tú", + "Azure OpenAI Deployment": "Implementación de Azure OpenAI", + "Enter your Azure OpenAI API Deployment ID": "Ingrese su ID de implementación de la API de Azure OpenAI" } diff --git a/src/locales/fr.json b/src/locales/fr.json index 4c4c5ab..645c41a 100644 --- a/src/locales/fr.json +++ b/src/locales/fr.json @@ -54,5 +54,7 @@ "Missing required parameter": "Paramètre requis manquant", "Please open a Bug report with the information above": "Veuillez ouvrir un rapport de bogue avec les informations ci-dessus", "Prompt to run": "Invite pour exécuter", - "You": "Vous" + "You": "Vous", + "Azure OpenAI Deployment": "Déploiement Azure OpenAI", + "Enter your Azure OpenAI API Deployment ID": "Entrez votre ID de déploiement de l'API Azure OpenAI" } diff --git a/src/locales/id.json b/src/locales/id.json index b67ec05..d5e7990 100644 --- a/src/locales/id.json +++ b/src/locales/id.json @@ -54,5 +54,7 @@ "Missing required parameter": "Parameter yang diperlukan hilang", "Please open a Bug report with the information above": "Harap buka laporan Bug dengan informasi di atas", "Prompt to run": "Permintaan untuk dijalankan", - "You": "Anda" + "You": "Anda", + "Azure OpenAI Deployment": "Penerapan Azure OpenAI", + "Enter your Azure OpenAI API Deployment ID": "Masukkan ID Penerapan API Azure OpenAI anda" } diff --git a/src/locales/jp.json b/src/locales/jp.json index f9a3b7e..e05b08d 100644 --- a/src/locales/jp.json +++ b/src/locales/jp.json @@ -54,5 +54,7 @@ "Missing required parameter": "必要なパラメーターがありません", "Please open a Bug report with the information above": "上記の情報を含めてバグレポートを開いてください", "Prompt to run": "実行するプロンプト", - "You": "あなた" + "You": "あなた", + "Azure OpenAI Deployment": "Azure OpenAI のデプロイメント", + "Enter your Azure OpenAI API Deployment ID": "Azure OpenAI API デプロイメント ID を入力してください" } diff --git a/src/locales/ko.json b/src/locales/ko.json index e2dc138..78dec46 100644 --- a/src/locales/ko.json +++ b/src/locales/ko.json @@ -54,5 +54,7 @@ "Missing required parameter": "필수 매개변수가 누락되었습니다.", "Please open a Bug report with the information above": "위 정보를 포함하여 버그 보고서를 열어주세요.", "Prompt to run": "실행할 프롬프트", - "You": "당신" + "You": "당신", + "Azure OpenAI Deployment": "Azure OpenAI 배포", + "Enter your Azure OpenAI API Deployment ID": "Azure OpenAI API 배포 ID를 입력하세요." } diff --git a/src/locales/pt.json b/src/locales/pt.json index cd173e8..86cb6ef 100644 --- a/src/locales/pt.json +++ b/src/locales/pt.json @@ -54,5 +54,7 @@ "Missing required parameter": "Parâmetro obrigatório faltando", "Please open a Bug report with the information above": "Por favor, abra um relatório de bug com as informações acima", "Prompt to run": "Prompt para executar", - "You": "Você" + "You": "Você", + "Azure OpenAI Deployment": "Implantação OpenAI do Azure", + "Enter your Azure OpenAI API Deployment ID": "Insira seu ID de implantação da API Azure OpenAI" } diff --git a/src/locales/ru.json b/src/locales/ru.json index 4c46e31..957daf4 100644 --- a/src/locales/ru.json +++ b/src/locales/ru.json @@ -54,5 +54,7 @@ "Missing required parameter": "Отсутствует обязательный параметр", "Please open a Bug report with the information above": "Пожалуйста, откройте отчет об ошибке с указанной выше информацией", "Prompt to run": "Приглашение на запуск", - "You": "Вы" + "You": "Вы", + "Azure OpenAI Deployment": "Развертывание Azure OpenAI", + "Enter your Azure OpenAI API Deployment ID": "Введите идентификатор развертывания API Azure OpenAI" } diff --git a/src/locales/tr.json b/src/locales/tr.json index 8bcc179..d924572 100644 --- a/src/locales/tr.json +++ b/src/locales/tr.json @@ -54,5 +54,7 @@ "Missing required parameter": "Gerekli parametre eksik", "Please open a Bug report with the information above": "Lütfen yukarıdaki bilgilerle bir Hata raporu açın", "Prompt to run": "Çalıştırma istemi", - "You": "Siz" + "You": "Siz", + "Azure OpenAI Deployment": "Azure OpenAI Dağıtımı", + "Enter your Azure OpenAI API Deployment ID": "Azure OpenAI API Dağıtım Kimliğinizi girin" } diff --git a/src/locales/uk.json b/src/locales/uk.json index f49443b..5a1f4b6 100644 --- a/src/locales/uk.json +++ b/src/locales/uk.json @@ -54,5 +54,7 @@ "Missing required parameter": "Відсутній обов'язковий параметр", "Please open a Bug report with the information above": "Будь ласка, відкрийте звіт про помилку з інформацією вище", "Prompt to run": "Запит на запуск", - "You": "Ви" + "You": "Ви", + "Azure OpenAI Deployment": "Розгортання Azure OpenAI", + "Enter your Azure OpenAI API Deployment ID": "Введіть ідентифікатор розгортання Azure OpenAI API" } diff --git a/src/locales/vi.json b/src/locales/vi.json index 6a1e441..8618d66 100644 --- a/src/locales/vi.json +++ b/src/locales/vi.json @@ -54,5 +54,7 @@ "Missing required parameter": "Thiếu tham số bắt buộc", "Please open a Bug report with the information above": "Vui lòng mở một báo cáo lỗi với thông tin ở trên", "Prompt to run": "Lời nhắc để chạy", - "You": "Bạn" + "You": "Bạn", + "Azure OpenAI Deployment": "Triển khai Azure OpenAIt", + "Enter your Azure OpenAI API Deployment ID": "Nhập ID triển khai API Azure OpenAI của bạn" } diff --git a/src/locales/zh-Hans.json b/src/locales/zh-Hans.json index 4630718..1f7480f 100644 --- a/src/locales/zh-Hans.json +++ b/src/locales/zh-Hans.json @@ -54,5 +54,7 @@ "Missing required parameter": "缺少必需的参数", "Please open a Bug report with the information above": "请使用上面的信息打开 Bug 报告", "Prompt to run": "要运行的提示语", - "You": "您" + "You": "您", + "Azure OpenAI Deployment": "Azure OpenAI 部署", + "Enter your Azure OpenAI API Deployment ID": "输入您的 Azure OpenAI API 部署 ID" } diff --git a/src/locales/zh-Hant.json b/src/locales/zh-Hant.json index 25b04fe..e74ebb0 100644 --- a/src/locales/zh-Hant.json +++ b/src/locales/zh-Hant.json @@ -54,5 +54,7 @@ "Missing required parameter": "缺少必需的參數", "Please open a Bug report with the information above": "請使用上面的信息打開 Bug 報告", "Prompt to run": "要運行的提示語", - "You": "您" + "You": "您", + "Azure OpenAI Deployment": "Azure OpenAI 部署", + "Enter your Azure OpenAI API Deployment ID": "輸入您的 Azure OpenAI API 部署 ID" } diff --git a/src/prompt.ts b/src/prompt.ts index 6cc368d..f136de2 100644 --- a/src/prompt.ts +++ b/src/prompt.ts @@ -118,12 +118,12 @@ export async function prompt({ spin.stop(`${i18n.t('Your script')}:`); console.log(''); const script = await readScript(process.stdout.write.bind(process.stdout)); - console.log(''); + if (!script.endsWith('\n')) console.log(''); console.log(''); console.log(dim('•')); if (!skipCommandExplanation) { spin.start(i18n.t(`Getting explanation...`)); - const info = await readInfo(process.stdout.write.bind(process.stdout)); + let info = await readInfo(process.stdout.write.bind(process.stdout)); if (!info) { const { readExplanation } = await getExplanation({ script, @@ -132,11 +132,11 @@ export async function prompt({ }); spin.stop(`${i18n.t('Explanation')}:`); console.log(''); - await readExplanation(process.stdout.write.bind(process.stdout)); - console.log(''); - console.log(''); - console.log(dim('•')); + info = await readExplanation(process.stdout.write.bind(process.stdout)); } + if (!info.endsWith('\n')) console.log(''); + console.log(''); + console.log(dim('•')); } await runOrReviseFlow(script, key, model, apiEndpoint, silentMode); @@ -232,7 +232,7 @@ async function revisionFlow( console.log(''); const script = await readScript(process.stdout.write.bind(process.stdout)); - console.log(''); + if (!script.endsWith('\n')) console.log(''); console.log(''); console.log(dim('•')); @@ -248,8 +248,10 @@ async function revisionFlow( infoSpin.stop(`${i18n.t('Explanation')}:`); console.log(''); - await readExplanation(process.stdout.write.bind(process.stdout)); - console.log(''); + const result = await readExplanation( + process.stdout.write.bind(process.stdout) + ); + if (!result.endsWith('\n')) console.log(''); console.log(''); console.log(dim('•')); }