Skip to content

Commit

Permalink
feat: handle multiple instances via WebSocket satellites
Browse files Browse the repository at this point in the history
  • Loading branch information
ivangabriele committed Jul 20, 2023
1 parent 7dda375 commit 783e82f
Show file tree
Hide file tree
Showing 19 changed files with 503 additions and 198 deletions.
1 change: 1 addition & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{}
5 changes: 5 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
"@typescript-eslint/parser": "6.0.0",
"@vscode/test-electron": "2.3.3",
"@vscode/vsce": "2.19.0",
"cuid": "3.0.0",
"eslint": "8.45.0",
"eslint-config-airbnb": "19.0.4",
"eslint-config-airbnb-typescript": "17.1.0",
Expand Down Expand Up @@ -84,6 +85,10 @@
{
"command": "openai-forge.sendCurrentDocument",
"title": "OpenAI Forge: Send current document or stack"
},
{
"command": "openai-forge.startOrStopServer",
"title": "OpenAI Forge: Start/Stop OAIF Server/Satellite"
}
],
"configuration": {
Expand Down
2 changes: 1 addition & 1 deletion src/commands/addOrRemoveCurrentDocument.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { window } from 'vscode'

import { DocumentInfo } from '../libs/DocumentInfo'
import { stackManager } from '../libs/stackManager'
import { stackManager } from '../libs/StackManager'
import { getCurrentDocumentPath } from '../utils/getCurrentDocumentPath'

type AddOrRemoveCurrentDocumentArgs = {
Expand Down
19 changes: 9 additions & 10 deletions src/commands/evaluateAndSendCurrentDocumentOrStack.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,16 @@
import { ProgressLocation, window } from 'vscode'

import { DocumentInfo } from '../libs/DocumentInfo'
import { stackManager } from '../libs/stackManager'
import { WebSocketDataAction, type WebSocketData } from '../types'
import { server } from '../libs/Server'
import { stackManager } from '../libs/StackManager'
import { Communication } from '../types'
import { getChatGptPrompt } from '../utils/getChatGptPrompt'
import { getUserSetting } from '../utils/getUserSetting'
import { getUserWorkspaceEvaluators } from '../utils/getUserWorkspaceEvaluators'
import { getUserWorkspaceInfo } from '../utils/getUserWorkspaceInfo'
import { runEvaluator } from '../utils/runEvaluator'

import type { WebSocket } from 'ws'

export async function evaluateAndSendCurrentDocumentOrStack(webSocket: WebSocket) {
export async function evaluateAndSendCurrentDocumentOrStack() {
await window.withProgress(
{
location: ProgressLocation.Notification,
Expand All @@ -38,16 +37,16 @@ export async function evaluateAndSendCurrentDocumentOrStack(webSocket: WebSocket
progress.report({ message: 'OpenAI Forge: Sending source code & errors to ChatGPT...' })

const excludeProjectInfo = getUserSetting('prompt', 'excludeProjectInfo') || false
const message = await getChatGptPrompt(currentOrStackDocumentInfos, {
const messageMessage = await getChatGptPrompt(currentOrStackDocumentInfos, {
errorOutput,
workspaceInfo: !excludeProjectInfo ? workspaceInfo : undefined,
})
const webSocketData: WebSocketData = {
action: WebSocketDataAction.ASK,
message,
const message: Communication.Message = {
action: Communication.MessageAction.ASK,
message: messageMessage,
}

webSocket.send(JSON.stringify(webSocketData))
server.send(message)
},
)
}
19 changes: 9 additions & 10 deletions src/commands/sendCurrentDocumentOrStack.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
import { ProgressLocation, window } from 'vscode'

import { DocumentInfo } from '../libs/DocumentInfo'
import { stackManager } from '../libs/stackManager'
import { WebSocketDataAction, type WebSocketData } from '../types'
import { server } from '../libs/Server'
import { stackManager } from '../libs/StackManager'
import { Communication } from '../types'
import { getChatGptPrompt } from '../utils/getChatGptPrompt'
import { getUserSetting } from '../utils/getUserSetting'
import { getUserWorkspaceInfo } from '../utils/getUserWorkspaceInfo'

import type { WebSocket } from 'ws'

export async function sendCurrentDocument(webSocket: WebSocket) {
export async function sendCurrentDocument() {
await window.withProgress(
{
location: ProgressLocation.Notification,
Expand All @@ -33,16 +32,16 @@ export async function sendCurrentDocument(webSocket: WebSocket) {

progress.report({ message: 'OpenAI Forge: Sending source code & errors to ChatGPT...' })

const message = await getChatGptPrompt(currentOrStackDocumentInfos, {
const messageMessage = await getChatGptPrompt(currentOrStackDocumentInfos, {
userMessage,
workspaceInfo: currentWorkspaceInfo,
})
const webSocketData: WebSocketData = {
action: WebSocketDataAction.ASK,
message,
const message: Communication.Message = {
action: Communication.MessageAction.ASK,
message: messageMessage,
}

webSocket.send(JSON.stringify(webSocketData))
server.send(message)
},
)
}
9 changes: 9 additions & 0 deletions src/commands/startOrStopServer.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { server } from '../libs/Server'

export function startOrStopServer() {
if (server.isStarted) {
server.stop()
} else {
server.start()
}
}
50 changes: 4 additions & 46 deletions src/commands/welcome.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,9 @@
import { existsSync } from 'fs'
import { join } from 'path'
import { Position, Range, Uri, ViewColumn, WorkspaceEdit, window, workspace } from 'vscode'
import { window } from 'vscode'

import { DocumentationPath } from '../constants'
import { handleMessageItems } from '../helpers/handleMessageItems'
import { isEmpty } from '../helpers/isEmpty'
import { GlobalStateKey, getGlobalStateManager } from '../libs/GlobalStateManager'
import { MessageItemType, type MessageButton } from '../types'
import { getUserWorkspaceRootPath } from '../utils/getUserWorkspaceRootPath'
import { showDocumentation } from '../utils/showDocumentation'

const HIDE_MESSAGE_BUTTON: MessageButton = {
Expand All @@ -26,45 +22,7 @@ export async function welcome() {

await showDocumentation(DocumentationPath.WELCOME)

const workspaceSettingsPath = join(getUserWorkspaceRootPath(), '.vscode', 'settings.json')
if (!existsSync(workspaceSettingsPath)) {
await workspace.fs.writeFile(Uri.file(workspaceSettingsPath), Buffer.from('{}'))
}
const workspaceSettingsDocument = await workspace.openTextDocument(workspaceSettingsPath)
const workspaceSettingsText = workspaceSettingsDocument.getText()

if (!workspaceSettingsText.includes('openai-forge.customEvaluators')) {
const workspaceSettings = !isEmpty(workspaceSettingsText) ? JSON.parse(workspaceSettingsText) : {}
const suggestedWorkspaceSettings = JSON.stringify(
{
...workspaceSettings,
'openai-forge.customEvaluators': [
{
command: 'npm',
commandArgs: ['run', 'build'],
extensions: ['.js', '.jsx', '.ts', '.tsx'],
},
],
},
// eslint-disable-next-line no-null/no-null
null,
2,
)
const workspaceSettingsEdit = new WorkspaceEdit()
workspaceSettingsEdit.replace(
workspaceSettingsDocument.uri,
new Range(
new Position(0, 0),
workspaceSettingsDocument.lineAt(workspaceSettingsDocument.lineCount - 1).range.end,
),
suggestedWorkspaceSettings,
)

await window.showTextDocument(workspaceSettingsDocument, ViewColumn.Two)
await workspace.applyEdit(workspaceSettingsEdit)

window
.showInformationMessage("Once you've read the welcome page:", HIDE_MESSAGE_BUTTON.label)
.then(handleMessageItems([HIDE_MESSAGE_BUTTON]))
}
window
.showInformationMessage("Once you've read the welcome page:", HIDE_MESSAGE_BUTTON.label)
.then(handleMessageItems([HIDE_MESSAGE_BUTTON]))
}
28 changes: 16 additions & 12 deletions src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,14 @@ import { type ExtensionContext, workspace, commands, ExtensionMode } from 'vscod
import { addOrRemoveCurrentDocument } from './commands/addOrRemoveCurrentDocument'
import { evaluateAndSendCurrentDocumentOrStack } from './commands/evaluateAndSendCurrentDocumentOrStack'
import { sendCurrentDocument } from './commands/sendCurrentDocumentOrStack'
import { startOrStopServer } from './commands/startOrStopServer'
import { welcome } from './commands/welcome'
import { handleError } from './helpers/handleError'
import { getGlobalStateManager, initializeGlobalStateManager } from './libs/GlobalStateManager'
import { server } from './libs/server'
import { stackManager } from './libs/stackManager'
import { stateManager } from './libs/stateManager'
import { logger } from './libs/Logger'
import { server } from './libs/Server'
import { stackManager } from './libs/StackManager'
import { stateManager } from './libs/StateManager'

export async function activate(context: ExtensionContext) {
try {
Expand All @@ -24,6 +26,7 @@ export async function activate(context: ExtensionContext) {

await initializeGlobalStateManager(context)
if (context.extensionMode === ExtensionMode.Development) {
logger.isDevelopment = true
await getGlobalStateManager().clear()
}

Expand All @@ -36,17 +39,18 @@ export async function activate(context: ExtensionContext) {
)
const evaluateAndSendCurrentDocumentOrStackDisposable = commands.registerCommand(
'openai-forge.evaluateAndSendCurrentDocumentOrStack',
() => {
stateManager.clients.forEach(evaluateAndSendCurrentDocumentOrStack)
},
evaluateAndSendCurrentDocumentOrStack,
)
const sendCurrentDocumentDisposable = commands.registerCommand('openai-forge.sendCurrentDocument', () => {
stateManager.clients.forEach(sendCurrentDocument)
})
const sendCurrentDocumentDisposable = commands.registerCommand(
'openai-forge.sendCurrentDocument',
sendCurrentDocument,
)
const startOrStopServerDisposable = commands.registerCommand('openai-forge.startOrStopServer', startOrStopServer)

context.subscriptions.push(addOrRemoveCurrentDocumentDisposable)
context.subscriptions.push(evaluateAndSendCurrentDocumentOrStackDisposable)
context.subscriptions.push(sendCurrentDocumentDisposable)
context.subscriptions.push(startOrStopServerDisposable)

// -------------------------------------------------------------------------
// Status Bar Items
Expand All @@ -57,7 +61,7 @@ export async function activate(context: ExtensionContext) {
// -------------------------------------------------------------------------
// WebSocket Server

server.start(context)
server.start()

// -------------------------------------------------------------------------
// Welcome Documentation
Expand All @@ -71,6 +75,6 @@ export async function activate(context: ExtensionContext) {
}
}

export function deactivate() {
server.stop()
export async function deactivate() {
await server.stop()
}
9 changes: 9 additions & 0 deletions src/helpers/fromWebSocketMessage.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { type MessageEvent, type RawData } from 'ws'

import { type Communication } from '../types'

export function fromWebSocketMessage(rawDataOrMessageEvent: RawData | MessageEvent): Communication.Message {
const message: Communication.Message = JSON.parse(rawDataOrMessageEvent.toString())

return message
}
5 changes: 5 additions & 0 deletions src/helpers/toWebSocketMessage.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import type { Communication } from '../types'

export function toWebSocketMessage(message: Communication.Message): string {
return JSON.stringify(message)
}
5 changes: 5 additions & 0 deletions src/helpers/waitFor.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export async function waitFor(inMs: number): Promise<void> {
await new Promise(resolve => {
setTimeout(resolve, inMs)
})
}
13 changes: 13 additions & 0 deletions src/libs/Logger.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,25 @@ function parseLogArgs(dataOrLevel: any, maybeLevel: LogLevel | undefined): [LogL
}

class Logger {
#isDevelopment: boolean = false
#outputChannel: OutputChannel

constructor() {
this.#outputChannel = window.createOutputChannel('OpenAI Forge')
}

set isDevelopment(isDevelopment: boolean) {
this.#isDevelopment = isDevelopment
}

debug(...args: any[]): void {
if (!this.#isDevelopment) {
return
}

console.debug(...args)
}

log(message: string): void
log(message: string, level: LogLevel): void
log(message: string, data: any): void
Expand Down
Loading

0 comments on commit 783e82f

Please sign in to comment.