Skip to content

Commit e5c3bd5

Browse files
committed
feat: add vscode extention
1 parent c3519ad commit e5c3bd5

File tree

20 files changed

+344
-20
lines changed

20 files changed

+344
-20
lines changed
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
.vscode/**
2+
.vscode-test/**
3+
out/**
4+
node_modules/**
5+
src/**
6+
.gitignore
7+
.yarnrc
8+
webpack.config.js
9+
vsc-extension-quickstart.md
10+
**/tsconfig.json
11+
**/.eslintrc.json
12+
**/*.map
13+
**/*.ts

packages/utils-ai-vscode/LICENSE

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2023 Estéban Soubiran <https://github.com/barbapapazes>
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

packages/utils-ai-vscode/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
# utils-ai-vscode

packages/utils-ai-vscode/package.json

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
{
2+
"publisher": "barbapapazes",
3+
"name": "utils-ai-vscode",
4+
"displayName": "Utils AI",
5+
"version": "0.1.1",
6+
"private": true,
7+
"description": "Write faster with AI",
8+
"license": "MIT",
9+
"repository": {
10+
"type": "git",
11+
"url": "https://github.com/barbapapazes/utils-ai",
12+
"directory": "packages/utils-ai-vscode"
13+
},
14+
"categories": [
15+
"Other"
16+
],
17+
"main": "./dist/index.js",
18+
"engines": {
19+
"vscode": "^1.83.0"
20+
},
21+
"activationEvents": [],
22+
"contributes": {
23+
"commands": [
24+
{
25+
"command": "utils-ai.addOpenAIKey",
26+
"title": "Utils AI: Add OpenAI API Key"
27+
},
28+
{
29+
"command": "utils-ai.removeOpenAIKey",
30+
"title": "Utils AI: Remove OpenAI API Key"
31+
},
32+
{
33+
"command": "utils-ai.correct",
34+
"title": "Utils AI: Correct current file",
35+
"icon": {
36+
"light": "./images/light.svg",
37+
"dark": "./images/dark.svg"
38+
}
39+
},
40+
{
41+
"command": "utils-ai.description",
42+
"title": "Utils AI: Generate description from current file"
43+
}
44+
],
45+
"menus": {
46+
"commandPalette": [
47+
{
48+
"command": "utils-ai.correct",
49+
"when": "editorLangId == 'markdown'"
50+
},
51+
{
52+
"command": "utils-ai.description",
53+
"when": "editorLangId == 'markdown'"
54+
}
55+
],
56+
"editor/title": [
57+
{
58+
"command": "utils-ai.correct",
59+
"group": "navigation",
60+
"when": "editorLangId == 'markdown'"
61+
}
62+
]
63+
}
64+
},
65+
"scripts": {
66+
"dev": "pnpm run build --watch src",
67+
"build": "tsup src/index.ts --external vscode",
68+
"vscode:prepublish": "pnpm run build",
69+
"publish": "vsce publish --no-dependencies"
70+
},
71+
"dependencies": {
72+
"utils-ai": "0.1.1"
73+
},
74+
"devDependencies": {
75+
"@types/node": "18.x",
76+
"@types/vscode": "^1.83.0",
77+
"@vscode/vsce": "^2.21.1",
78+
"tsup": "^7.2.0",
79+
"typescript": "^5.2.2"
80+
}
81+
}
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
import * as vscode from 'vscode'
2+
import type { Message } from 'utils-ai'
3+
import { fetchCompletion, getFirstSuggestion, getPrompt } from 'utils-ai'
4+
import { getOpenAIKey } from '../secrets'
5+
6+
export function correctCommand(context: vscode.ExtensionContext) {
7+
const secrets = context.secrets
8+
9+
return async () => {
10+
const editor = vscode.window.activeTextEditor
11+
12+
if (editor) {
13+
const key = await getOpenAIKey(secrets)
14+
15+
if (!key) {
16+
vscode.window.showErrorMessage('No key provided. Please provide a key using the "Add OpenAI Key" command.')
17+
return
18+
}
19+
20+
const prompt = getPrompt('spell-checker', 'en')
21+
const text = editor.document.getText()
22+
23+
const messages: Message[] = [
24+
{
25+
role: 'system',
26+
content: prompt.message,
27+
},
28+
{
29+
role: 'user',
30+
content: text,
31+
},
32+
]
33+
34+
try {
35+
// start a loading notification
36+
await vscode.window.withProgress({
37+
location: vscode.ProgressLocation.Notification,
38+
title: 'Utils AI: Correcting text',
39+
cancellable: false,
40+
}, async () => {
41+
// wait for the completion
42+
const response = await fetchCompletion(messages, { accessKey: key })
43+
44+
const correctedText = getFirstSuggestion(response)
45+
46+
// replace the text with the corrected text
47+
editor.edit((editBuilder) => {
48+
editBuilder.replace(new vscode.Range(0, 0, text.length, 0), correctedText)
49+
})
50+
})
51+
}
52+
catch (error: any) {
53+
vscode.window.showErrorMessage(error.message)
54+
}
55+
}
56+
}
57+
}
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
import * as vscode from 'vscode'
2+
import type { Message } from 'utils-ai'
3+
import { fetchCompletion, getFirstSuggestion, getPrompt } from 'utils-ai'
4+
import { getOpenAIKey } from '../secrets'
5+
6+
export function descriptionCommand(context: vscode.ExtensionContext) {
7+
const secrets = context.secrets
8+
9+
return async () => {
10+
const editor = vscode.window.activeTextEditor
11+
12+
if (editor) {
13+
const key = await getOpenAIKey(secrets)
14+
15+
if (!key) {
16+
vscode.window.showErrorMessage('No key provided. Please provide a key using the "Add OpenAI Key" command.')
17+
return
18+
}
19+
20+
const prompt = getPrompt('descriptor', 'en')
21+
const text = editor.document.getText()
22+
23+
const messages: Message[] = [
24+
{
25+
role: 'system',
26+
content: prompt.message,
27+
},
28+
{
29+
role: 'user',
30+
content: text,
31+
},
32+
]
33+
34+
try {
35+
// start a loading notification
36+
await vscode.window.withProgress({
37+
location: vscode.ProgressLocation.Notification,
38+
title: 'Utils AI: Generating description',
39+
cancellable: false,
40+
}, async () => {
41+
// wait for the completion
42+
const response = await fetchCompletion(messages, { accessKey: key })
43+
44+
// get the first suggestion
45+
const description = getFirstSuggestion(response)
46+
47+
const position = editor.selection.active
48+
// replace the text with the description
49+
editor.edit((editBuilder) => {
50+
editBuilder.replace(new vscode.Range(position, position), description)
51+
})
52+
})
53+
}
54+
catch (error: any) {
55+
vscode.window.showErrorMessage(error.message)
56+
}
57+
}
58+
}
59+
}

packages/utils-ai-vscode/src/index.ts

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
import * as vscode from 'vscode'
2+
import { addOpenAIKey, getOpenAIKey, removeOpenAIKey } from './secrets'
3+
import { descriptionCommand } from './commands/description'
4+
import { correctCommand } from './commands/correct'
5+
6+
export function activate(context: vscode.ExtensionContext) {
7+
const secrets = context.secrets
8+
9+
const addOpenAIKeyCommand = vscode.commands.registerCommand('utils-ai.addOpenAIKey', async () => {
10+
const key = await vscode.window.showInputBox({
11+
prompt: 'Enter your OpenAI API key',
12+
placeHolder: 'OpenAI API key',
13+
password: true,
14+
})
15+
16+
if (!key) {
17+
vscode.window.showErrorMessage('No key provided. Please try again.')
18+
return
19+
}
20+
21+
await addOpenAIKey(key, secrets)
22+
})
23+
24+
const removeOpenAIKeyCommand = vscode.commands.registerCommand('utils-ai.removeOpenAIKey', async () => {
25+
await removeOpenAIKey(secrets)
26+
})
27+
28+
const correctCommandDisposable = vscode.commands.registerCommand('utils-ai.correct', correctCommand(context))
29+
const descriptionCommandDisposable = vscode.commands.registerCommand('utils-ai.description', descriptionCommand(context))
30+
31+
context.subscriptions.push(addOpenAIKeyCommand, removeOpenAIKeyCommand, correctCommandDisposable, descriptionCommandDisposable)
32+
}
33+
34+
export async function deactivate(context: vscode.ExtensionContext) {
35+
const secrets = context.secrets
36+
37+
await removeOpenAIKey(secrets)
38+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import type * as vscode from 'vscode'
2+
3+
const OPEN_AI_SECRET_KEY = 'openai-key'
4+
5+
export async function addOpenAIKey(key: string, secrets: vscode.SecretStorage) {
6+
secrets.store(OPEN_AI_SECRET_KEY, key)
7+
}
8+
9+
export async function removeOpenAIKey(secrets: vscode.SecretStorage) {
10+
secrets.delete(OPEN_AI_SECRET_KEY)
11+
}
12+
13+
export async function getOpenAIKey(secrets: vscode.SecretStorage) {
14+
return secrets.get(OPEN_AI_SECRET_KEY)
15+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
{
2+
"compilerOptions": {
3+
"target": "ES2020",
4+
"lib": [
5+
"ES2020"
6+
],
7+
"rootDir": "src",
8+
"module": "commonjs",
9+
"strict": true,
10+
"sourceMap": true
11+
}
12+
}

packages/utils-ai/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
# utils-ai

0 commit comments

Comments
 (0)