@builder.io/ai-shell
Advanced tools
Comparing version 0.0.14 to 0.0.15
266
dist/cli.js
@@ -15,3 +15,5 @@ #!/usr/bin/env node | ||
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; } | ||
function _interopDefaultLegacy(e) { | ||
return e && typeof e === 'object' && 'default' in e ? e : { default: e }; | ||
} | ||
@@ -25,32 +27,39 @@ function _interopNamespace(e) { | ||
var d = Object.getOwnPropertyDescriptor(e, k); | ||
Object.defineProperty(n, k, d.get ? d : { | ||
enumerable: true, | ||
get: function () { return e[k]; } | ||
}); | ||
Object.defineProperty( | ||
n, | ||
k, | ||
d.get | ||
? d | ||
: { | ||
enumerable: true, | ||
get: function () { | ||
return e[k]; | ||
}, | ||
} | ||
); | ||
} | ||
}); | ||
} | ||
n["default"] = e; | ||
n['default'] = e; | ||
return Object.freeze(n); | ||
} | ||
var color__default = /*#__PURE__*/_interopDefaultLegacy(color); | ||
var fs__default = /*#__PURE__*/_interopDefaultLegacy(fs); | ||
var path__default = /*#__PURE__*/_interopDefaultLegacy(path); | ||
var os__default = /*#__PURE__*/_interopDefaultLegacy(os); | ||
var ini__default = /*#__PURE__*/_interopDefaultLegacy(ini); | ||
var p__namespace = /*#__PURE__*/_interopNamespace(p); | ||
var dedent__default = /*#__PURE__*/_interopDefaultLegacy(dedent); | ||
var color__default = /*#__PURE__*/ _interopDefaultLegacy(color); | ||
var fs__default = /*#__PURE__*/ _interopDefaultLegacy(fs); | ||
var path__default = /*#__PURE__*/ _interopDefaultLegacy(path); | ||
var os__default = /*#__PURE__*/ _interopDefaultLegacy(os); | ||
var ini__default = /*#__PURE__*/ _interopDefaultLegacy(ini); | ||
var p__namespace = /*#__PURE__*/ _interopNamespace(p); | ||
var dedent__default = /*#__PURE__*/ _interopDefaultLegacy(dedent); | ||
var version = "0.0.4"; | ||
var version = '0.0.4'; | ||
const commandName = "ai-shell"; | ||
const commandName = 'ai-shell'; | ||
class KnownError extends Error { | ||
} | ||
const indent = " ".repeat(4); | ||
class KnownError extends Error {} | ||
const indent = ' '.repeat(4); | ||
const handleCliError = (error) => { | ||
if (error instanceof Error && !(error instanceof KnownError)) { | ||
if (error.stack) { | ||
console.error(color.dim(error.stack.split("\n").slice(1).join("\n"))); | ||
console.error(color.dim(error.stack.split('\n').slice(1).join('\n'))); | ||
} | ||
@@ -63,5 +72,3 @@ console.error(` | ||
); | ||
console.error( | ||
`${indent}https://github.com/BuilderIO/ai-shell/issues/new` | ||
); | ||
console.error(`${indent}https://github.com/BuilderIO/ai-shell/issues/new`); | ||
} | ||
@@ -84,3 +91,3 @@ }; | ||
} | ||
parseAssert$1("OPENAI_KEY", key.startsWith("sk-"), 'Must start with "sk-"'); | ||
parseAssert$1('OPENAI_KEY', key.startsWith('sk-'), 'Must start with "sk-"'); | ||
return key; | ||
@@ -90,12 +97,16 @@ }, | ||
if (!model || model.length === 0) { | ||
return "gpt-3.5-turbo"; | ||
return 'gpt-3.5-turbo'; | ||
} | ||
return model; | ||
} | ||
}, | ||
}; | ||
const configPath = path__default["default"].join(os__default["default"].homedir(), ".ai-shell"); | ||
const fileExists = (filePath) => fs__default["default"].lstat(filePath).then( | ||
() => true, | ||
() => false | ||
const configPath = path__default['default'].join( | ||
os__default['default'].homedir(), | ||
'.ai-shell' | ||
); | ||
const fileExists = (filePath) => | ||
fs__default['default'].lstat(filePath).then( | ||
() => true, | ||
() => false | ||
); | ||
const readConfigFile = async () => { | ||
@@ -106,4 +117,7 @@ const configExists = await fileExists(configPath); | ||
} | ||
const configString = await fs__default["default"].readFile(configPath, "utf8"); | ||
return ini__default["default"].parse(configString); | ||
const configString = await fs__default['default'].readFile( | ||
configPath, | ||
'utf8' | ||
); | ||
return ini__default['default'].parse(configString); | ||
}; | ||
@@ -129,3 +143,7 @@ const getConfig = async (cliConfig) => { | ||
} | ||
await fs__default["default"].writeFile(configPath, ini__default["default"].stringify(config), "utf8"); | ||
await fs__default['default'].writeFile( | ||
configPath, | ||
ini__default['default'].stringify(config), | ||
'utf8' | ||
); | ||
}; | ||
@@ -135,4 +153,4 @@ | ||
{ | ||
name: "config", | ||
parameters: ["<mode>", "<key=value...>"] | ||
name: 'config', | ||
parameters: ['<mode>', '<key=value...>'], | ||
}, | ||
@@ -142,3 +160,3 @@ (argv) => { | ||
const { mode, keyValue: keyValues } = argv._; | ||
if (mode === "get") { | ||
if (mode === 'get') { | ||
const config = await getConfig(); | ||
@@ -152,6 +170,4 @@ for (const key of keyValues) { | ||
} | ||
if (mode === "set") { | ||
await setConfigs( | ||
keyValues.map((keyValue) => keyValue.split("=")) | ||
); | ||
if (mode === 'set') { | ||
await setConfigs(keyValues.map((keyValue) => keyValue.split('='))); | ||
return; | ||
@@ -161,3 +177,5 @@ } | ||
})().catch((error) => { | ||
console.error(`${color__default["default"].red("\u2716")} ${error.message}`); | ||
console.error( | ||
`${color__default['default'].red('\u2716')} ${error.message}` | ||
); | ||
handleCliError(error); | ||
@@ -170,10 +188,8 @@ process.exit(1); | ||
function getOpenAi(key) { | ||
const openAi = new openai.OpenAIApi(new openai.Configuration({ apiKey: key })); | ||
const openAi = new openai.OpenAIApi( | ||
new openai.Configuration({ apiKey: key }) | ||
); | ||
return openAi; | ||
} | ||
async function getScriptAndInfo({ | ||
prompt, | ||
key, | ||
model | ||
}) { | ||
async function getScriptAndInfo({ prompt, key, model }) { | ||
const fullPrompt = getFullPrompt(prompt); | ||
@@ -184,21 +200,16 @@ const { choices } = await generateCompletion({ | ||
key, | ||
model | ||
model, | ||
}); | ||
const message = choices[0].message.content; | ||
const script = message.split("```")[1].trim(); | ||
const info = message.split("```")[2].trim(); | ||
const script = message.split('```')[1].trim(); | ||
const info = message.split('```')[2].trim(); | ||
return { script, info }; | ||
} | ||
async function generateCompletion({ | ||
prompt, | ||
number = 1, | ||
key, | ||
model | ||
}) { | ||
async function generateCompletion({ prompt, number = 1, key, model }) { | ||
const openAi = getOpenAi(key); | ||
try { | ||
const completion = await openAi.createChatCompletion({ | ||
model: model || "gpt-3.5-turbo", | ||
messages: [{ role: "user", content: prompt }], | ||
n: Math.min(number, 10) | ||
model: model || 'gpt-3.5-turbo', | ||
messages: [{ role: 'user', content: prompt }], | ||
n: Math.min(number, 10), | ||
}); | ||
@@ -208,3 +219,3 @@ return completion.data; | ||
const errorAsAny = err; | ||
if (errorAsAny.code === "ENOTFOUND") { | ||
if (errorAsAny.code === 'ENOTFOUND') { | ||
throw new KnownError( | ||
@@ -217,7 +228,3 @@ `Error connecting to ${errorAsAny.hostname} (${errorAsAny.syscall}). Are you connected to the internet?` | ||
} | ||
async function getExplanation({ | ||
script, | ||
key, | ||
model | ||
}) { | ||
async function getExplanation({ script, key, model }) { | ||
const prompt = getExplanationPrompt(script); | ||
@@ -228,12 +235,7 @@ const result = await generateCompletion({ | ||
number: 1, | ||
model | ||
model, | ||
}); | ||
return result.choices[0].message.content.trim(); | ||
} | ||
async function getRevision({ | ||
prompt, | ||
code, | ||
key, | ||
model | ||
}) { | ||
async function getRevision({ prompt, code, key, model }) { | ||
const fullPrompt = getRevisionPrompt(prompt, code); | ||
@@ -244,10 +246,10 @@ const result = await generateCompletion({ | ||
number: 1, | ||
model | ||
model, | ||
}); | ||
const message = result.choices[0].message.content; | ||
const script = message.split("```")[1].trim(); | ||
const script = message.split('```')[1].trim(); | ||
return script; | ||
} | ||
function getExplanationPrompt(script) { | ||
return dedent__default["default"]` | ||
return dedent__default['default']` | ||
${explainBash} | ||
@@ -258,3 +260,3 @@ | ||
} | ||
const explainBash = dedent__default["default"]` | ||
const explainBash = dedent__default['default']` | ||
Then please describe the bash script in plain english, step by step, what exactly it does. | ||
@@ -264,7 +266,7 @@ Please describe succintly, use as few words as possible, do not be verbose. | ||
`; | ||
const generationDetails = dedent__default["default"]` | ||
const generationDetails = dedent__default['default']` | ||
Please only reply with the single line bash command surrounded by 3 backticks. It should be able to be directly run in a bash terminal. Do not include any other text. | ||
`; | ||
function getFullPrompt(prompt) { | ||
return dedent__default["default"]` | ||
return dedent__default['default']` | ||
I will give you a prompt to create a single line bash command that one can enter in a terminal and run, based on what is asked in the prompt. | ||
@@ -274,3 +276,3 @@ | ||
${"" } | ||
${''} | ||
@@ -281,3 +283,3 @@ The prompt is: ${prompt} | ||
function getRevisionPrompt(prompt, code) { | ||
return dedent__default["default"]` | ||
return dedent__default['default']` | ||
Please update the following bash script based on what is asked in the following prompt. | ||
@@ -298,6 +300,6 @@ | ||
const examples = [ | ||
"delete all log files", | ||
"list js files", | ||
"fetch me a random joke", | ||
"list all commits" | ||
'delete all log files', | ||
'list js files', | ||
'fetch me a random joke', | ||
'list all commits', | ||
]; | ||
@@ -307,18 +309,18 @@ async function getPrompt(prompt2) { | ||
{ | ||
prompt: () => p__namespace.text({ | ||
message: "What would you like me to to do?", | ||
placeholder: `e.g. ${sample(examples)}`, | ||
initialValue: prompt2, | ||
defaultValue: "Say hello", | ||
validate: (value) => { | ||
if (!value) | ||
return "Please enter a prompt."; | ||
} | ||
}) | ||
prompt: () => | ||
p__namespace.text({ | ||
message: 'What would you like me to to do?', | ||
placeholder: `e.g. ${sample(examples)}`, | ||
initialValue: prompt2, | ||
defaultValue: 'Say hello', | ||
validate: (value) => { | ||
if (!value) return 'Please enter a prompt.'; | ||
}, | ||
}), | ||
}, | ||
{ | ||
onCancel: () => { | ||
p__namespace.cancel("Goodbye!"); | ||
p__namespace.cancel('Goodbye!'); | ||
process.exit(0); | ||
} | ||
}, | ||
} | ||
@@ -331,16 +333,16 @@ ); | ||
{ | ||
prompt: () => p__namespace.text({ | ||
message: "What would you like me to to change in this script?", | ||
placeholder: "e.g. change the folder name", | ||
validate: (value) => { | ||
if (!value) | ||
return "Please enter a prompt."; | ||
} | ||
}) | ||
prompt: () => | ||
p__namespace.text({ | ||
message: 'What would you like me to to change in this script?', | ||
placeholder: 'e.g. change the folder name', | ||
validate: (value) => { | ||
if (!value) return 'Please enter a prompt.'; | ||
}, | ||
}), | ||
}, | ||
{ | ||
onCancel: () => { | ||
p__namespace.cancel("Goodbye!"); | ||
p__namespace.cancel('Goodbye!'); | ||
process.exit(0); | ||
} | ||
}, | ||
} | ||
@@ -350,6 +352,3 @@ ); | ||
} | ||
async function prompt({ | ||
defaultPrompt, | ||
usePrompt | ||
} = {}) { | ||
async function prompt({ defaultPrompt, usePrompt } = {}) { | ||
console.clear(); | ||
@@ -359,8 +358,12 @@ const { OPENAI_KEY: key } = await getConfig(); | ||
throw new KnownError( | ||
"Please set your OpenAI API key via `ai-shell config set OPENAI_KEY=<your token>`" | ||
'Please set your OpenAI API key via `ai-shell config set OPENAI_KEY=<your token>`' | ||
); | ||
} | ||
parseAssert("OPENAI_KEY", key.startsWith("sk-"), 'Must start with "sk-"'); | ||
p__namespace.intro(`${color__default["default"].bgCyan(color__default["default"].black(` ${commandName} `))}`); | ||
const thePrompt = usePrompt || await getPrompt(defaultPrompt); | ||
parseAssert('OPENAI_KEY', key.startsWith('sk-'), 'Must start with "sk-"'); | ||
p__namespace.intro( | ||
`${color__default['default'].bgCyan( | ||
color__default['default'].black(` ${commandName} `) | ||
)}` | ||
); | ||
const thePrompt = usePrompt || (await getPrompt(defaultPrompt)); | ||
const spin = p__namespace.spinner(); | ||
@@ -382,16 +385,16 @@ spin.start(`Loading...`); | ||
const answer = await p__namespace.select({ | ||
message: "Run this script?", | ||
message: 'Run this script?', | ||
options: [ | ||
{ label: "\u2705 Yes", value: "yes", hint: "Lets go!" }, | ||
{ label: '\u2705 Yes', value: 'yes', hint: 'Lets go!' }, | ||
{ | ||
label: "\u{1F4DD} Revise", | ||
value: "revise", | ||
hint: "Give feedback your prompt and get a new result" | ||
label: '\u{1F4DD} Revise', | ||
value: 'revise', | ||
hint: 'Give feedback your prompt and get a new result', | ||
}, | ||
{ label: "\u274C Cancel", value: "cancel", hint: "Exit the program" } | ||
] | ||
{ label: '\u274C Cancel', value: 'cancel', hint: 'Exit the program' }, | ||
], | ||
}); | ||
const confirmed = answer === "yes"; | ||
const cancel = answer === "cancel"; | ||
const revisePrompt = answer === "revise"; | ||
const confirmed = answer === 'yes'; | ||
const cancel = answer === 'cancel'; | ||
const revisePrompt = answer === 'revise'; | ||
if (revisePrompt) { | ||
@@ -401,7 +404,6 @@ await revisionFlow(script, key); | ||
p__namespace.outro(`Running: ${script}`); | ||
console.log(""); | ||
await execa.execaCommand(script, { stdio: "inherit" }).catch((err) => { | ||
}); | ||
console.log(''); | ||
await execa.execaCommand(script, { stdio: 'inherit' }).catch((err) => {}); | ||
} else if (cancel) { | ||
p__namespace.cancel("Goodbye!"); | ||
p__namespace.cancel('Goodbye!'); | ||
process.exit(0); | ||
@@ -417,3 +419,3 @@ } | ||
code: currentScript, | ||
key | ||
key, | ||
}); | ||
@@ -442,7 +444,7 @@ spin.stop(`Your new script:`); | ||
type: String, | ||
description: "Prompt to run", | ||
alias: "p" | ||
} | ||
description: 'Prompt to run', | ||
alias: 'p', | ||
}, | ||
}, | ||
commands: [config] | ||
commands: [config], | ||
}, | ||
@@ -449,0 +451,0 @@ (argv) => { |
{ | ||
"name": "@builder.io/ai-shell", | ||
"version": "0.0.14", | ||
"version": "0.0.15", | ||
"type": "module", | ||
@@ -30,2 +30,3 @@ "dependencies": { | ||
"lint:fix": "prettier --write .", | ||
"lint": "prettier --check .", | ||
"typecheck": "tsc", | ||
@@ -32,0 +33,0 @@ "build": "pkgroll", |
@@ -7,3 +7,2 @@ # AI Shell | ||
Inspired by [Github Copilot X CLI](https://githubnext.com/projects/copilot-cli/), but open source for everyone. | ||
@@ -81,3 +80,2 @@ | ||
## Credit | ||
@@ -91,2 +89,1 @@ | ||
If you want to help fix a bug or implement a feature in [Issues](https://github.com/BuilderIO/ai-shell/issues) (tip: look out for the `help wanted` label), checkout the [Contribution Guide](CONTRIBUTING.md) to learn how to setup the project. | ||
Sorry, the diff of this file is not supported yet
28964
866
87