mirror of
https://github.com/wavetermdev/waveterm.git
synced 2025-01-08 19:38:51 +01:00
ea3be8115a
* first draft at ui * first draft connecting openai to cmd info ui * added more updates and added prompt engineering * focus textarea on mount * fix aichat layout issue * added focus back to input after closing cmd info chat * added ability to clear chat history, closes on command enter, better initial greeting message, and small things like user can refocus the help textarea by pressing ctrl + space again * added a bunch of small upgrades * added context for chatgpt info command * added context to chatgpt cmd info command * added ability to use arrow keys to grab code markdown * added error handling as well as fixed the text area outline bug * slightly changed the ui for selecting * revamped ui and added correct scroll behavior * changed ui, fixed up code block selection, some other small changes * deep copied cmd info chat when we return * added error checking and removed logs * made deep copy code more clear * prettier with the right version * more prettier changes * removed extraneous comment
197 lines
5.9 KiB
Go
197 lines
5.9 KiB
Go
// Copyright 2023, Command Line Inc.
|
|
// SPDX-License-Identifier: Apache-2.0
|
|
|
|
// in-memory storage for waveterm server
|
|
package sstore
|
|
|
|
import (
|
|
"fmt"
|
|
"log"
|
|
"sync"
|
|
|
|
"github.com/wavetermdev/waveterm/waveshell/pkg/packet"
|
|
"github.com/wavetermdev/waveterm/wavesrv/pkg/utilfn"
|
|
)
|
|
|
|
// global lock for all memory operations
|
|
// memory ops are very fast, so this is not a bottleneck
|
|
var MemLock *sync.Mutex = &sync.Mutex{}
|
|
var ScreenMemStore map[string]*ScreenMemState = make(map[string]*ScreenMemState) // map of screenid -> ScreenMemState
|
|
|
|
const (
|
|
ScreenIndicator_None = ""
|
|
ScreenIndicator_Error = "error"
|
|
ScreenIndicator_Success = "success"
|
|
ScreenIndicator_Output = "output"
|
|
)
|
|
|
|
var screenIndicatorLevels map[string]int = map[string]int{
|
|
ScreenIndicator_None: 0,
|
|
ScreenIndicator_Output: 1,
|
|
ScreenIndicator_Success: 2,
|
|
ScreenIndicator_Error: 3,
|
|
}
|
|
|
|
func dumpScreenMemStore() {
|
|
MemLock.Lock()
|
|
defer MemLock.Unlock()
|
|
for k, v := range ScreenMemStore {
|
|
log.Printf(" ScreenMemStore[%s] = %+v\n", k, v)
|
|
}
|
|
}
|
|
|
|
// returns true if i1 > i2
|
|
func isIndicatorGreater(i1 string, i2 string) bool {
|
|
return screenIndicatorLevels[i1] > screenIndicatorLevels[i2]
|
|
}
|
|
|
|
type OpenAICmdInfoChatStore struct {
|
|
MessageCount int `json:"messagecount"`
|
|
Messages []*packet.OpenAICmdInfoChatMessage `json:"messages"`
|
|
}
|
|
|
|
type ScreenMemState struct {
|
|
NumRunningCommands int `json:"numrunningcommands,omitempty"`
|
|
IndicatorType string `json:"indicatortype,omitempty"`
|
|
CmdInputText utilfn.StrWithPos `json:"cmdinputtext,omitempty"`
|
|
CmdInputSeqNum int `json:"cmdinputseqnum,omitempty"`
|
|
AICmdInfoChat *OpenAICmdInfoChatStore `json:"aicmdinfochat,omitempty"`
|
|
}
|
|
|
|
func ScreenMemDeepCopyCmdInfoChatStore(store *OpenAICmdInfoChatStore) *OpenAICmdInfoChatStore {
|
|
rtnMessages := []*packet.OpenAICmdInfoChatMessage{}
|
|
for index := 0; index < len(store.Messages); index++ {
|
|
messageToCopy := *store.Messages[index]
|
|
if messageToCopy.AssistantResponse != nil {
|
|
assistantResponseCopy := *messageToCopy.AssistantResponse
|
|
messageToCopy.AssistantResponse = &assistantResponseCopy
|
|
}
|
|
rtnMessages = append(rtnMessages, &messageToCopy)
|
|
}
|
|
rtn := &OpenAICmdInfoChatStore{MessageCount: store.MessageCount, Messages: rtnMessages}
|
|
return rtn
|
|
}
|
|
|
|
func ScreenMemInitCmdInfoChat(screenId string) {
|
|
greetingMessagePk := &packet.OpenAICmdInfoChatMessage{
|
|
MessageID: 0,
|
|
IsAssistantResponse: true,
|
|
AssistantResponse: &packet.OpenAICmdInfoPacketOutputType{
|
|
Message: packet.OpenAICmdInfoChatGreetingMessage,
|
|
},
|
|
}
|
|
ScreenMemStore[screenId].AICmdInfoChat = &OpenAICmdInfoChatStore{MessageCount: 1, Messages: []*packet.OpenAICmdInfoChatMessage{greetingMessagePk}}
|
|
}
|
|
|
|
func ScreenMemClearCmdInfoChat(screenId string) {
|
|
MemLock.Lock()
|
|
defer MemLock.Unlock()
|
|
if ScreenMemStore[screenId] == nil {
|
|
ScreenMemStore[screenId] = &ScreenMemState{}
|
|
}
|
|
ScreenMemInitCmdInfoChat(screenId)
|
|
}
|
|
|
|
func ScreenMemAddCmdInfoChatMessage(screenId string, msg *packet.OpenAICmdInfoChatMessage) {
|
|
MemLock.Lock()
|
|
defer MemLock.Unlock()
|
|
if ScreenMemStore[screenId] == nil {
|
|
ScreenMemStore[screenId] = &ScreenMemState{}
|
|
}
|
|
if ScreenMemStore[screenId].AICmdInfoChat == nil {
|
|
log.Printf("AICmdInfoChat is null, creating")
|
|
ScreenMemInitCmdInfoChat(screenId)
|
|
}
|
|
|
|
CmdInfoChat := ScreenMemStore[screenId].AICmdInfoChat
|
|
CmdInfoChat.Messages = append(CmdInfoChat.Messages, msg)
|
|
CmdInfoChat.MessageCount++
|
|
}
|
|
|
|
func ScreenMemGetCmdInfoMessageCount(screenId string) int {
|
|
MemLock.Lock()
|
|
defer MemLock.Unlock()
|
|
if ScreenMemStore[screenId] == nil {
|
|
ScreenMemStore[screenId] = &ScreenMemState{}
|
|
}
|
|
if ScreenMemStore[screenId].AICmdInfoChat == nil {
|
|
ScreenMemInitCmdInfoChat(screenId)
|
|
}
|
|
return ScreenMemStore[screenId].AICmdInfoChat.MessageCount
|
|
}
|
|
|
|
func ScreenMemGetCmdInfoChat(screenId string) *OpenAICmdInfoChatStore {
|
|
MemLock.Lock()
|
|
defer MemLock.Unlock()
|
|
if ScreenMemStore[screenId] == nil {
|
|
ScreenMemStore[screenId] = &ScreenMemState{}
|
|
}
|
|
if ScreenMemStore[screenId].AICmdInfoChat == nil {
|
|
ScreenMemInitCmdInfoChat(screenId)
|
|
}
|
|
return ScreenMemDeepCopyCmdInfoChatStore(ScreenMemStore[screenId].AICmdInfoChat)
|
|
}
|
|
|
|
func ScreenMemUpdateCmdInfoChatMessage(screenId string, messageID int, msg *packet.OpenAICmdInfoChatMessage) error {
|
|
MemLock.Lock()
|
|
defer MemLock.Unlock()
|
|
if ScreenMemStore[screenId] == nil {
|
|
ScreenMemStore[screenId] = &ScreenMemState{}
|
|
}
|
|
if ScreenMemStore[screenId].AICmdInfoChat == nil {
|
|
ScreenMemInitCmdInfoChat(screenId)
|
|
}
|
|
CmdInfoChat := ScreenMemStore[screenId].AICmdInfoChat
|
|
if messageID >= 0 && messageID < len(CmdInfoChat.Messages) {
|
|
CmdInfoChat.Messages[messageID] = msg
|
|
} else {
|
|
return fmt.Errorf("ScreenMemUpdateCmdInfoChatMessage: error: Message Id out of range: %d", messageID)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func ScreenMemSetCmdInputText(screenId string, sp utilfn.StrWithPos, seqNum int) {
|
|
MemLock.Lock()
|
|
defer MemLock.Unlock()
|
|
if ScreenMemStore[screenId] == nil {
|
|
ScreenMemStore[screenId] = &ScreenMemState{}
|
|
}
|
|
if seqNum <= ScreenMemStore[screenId].CmdInputSeqNum {
|
|
return
|
|
}
|
|
ScreenMemStore[screenId].CmdInputText = sp
|
|
ScreenMemStore[screenId].CmdInputSeqNum = seqNum
|
|
}
|
|
|
|
func ScreenMemSetNumRunningCommands(screenId string, num int) {
|
|
MemLock.Lock()
|
|
defer MemLock.Unlock()
|
|
if ScreenMemStore[screenId] == nil {
|
|
ScreenMemStore[screenId] = &ScreenMemState{}
|
|
}
|
|
ScreenMemStore[screenId].NumRunningCommands = num
|
|
}
|
|
|
|
func ScreenMemCombineIndicator(screenId string, indicator string) {
|
|
MemLock.Lock()
|
|
defer MemLock.Unlock()
|
|
if ScreenMemStore[screenId] == nil {
|
|
ScreenMemStore[screenId] = &ScreenMemState{}
|
|
}
|
|
if isIndicatorGreater(indicator, ScreenMemStore[screenId].IndicatorType) {
|
|
ScreenMemStore[screenId].IndicatorType = indicator
|
|
}
|
|
}
|
|
|
|
// safe because we return a copy
|
|
func GetScreenMemState(screenId string) *ScreenMemState {
|
|
MemLock.Lock()
|
|
defer MemLock.Unlock()
|
|
ptr := ScreenMemStore[screenId]
|
|
if ptr == nil {
|
|
return nil
|
|
}
|
|
rtn := *ptr
|
|
return &rtn
|
|
}
|