mirror of
https://github.com/wavetermdev/waveterm.git
synced 2025-02-01 23:21:59 +01:00
add line.linestate to DB. switch linetype to a dbmappable. update line sql queries. add state to /line:set command. bump migration (#2)
This commit is contained in:
parent
22fb034cc4
commit
5d89e0cfef
1
db/migrations/000021_linestate.down.sql
Normal file
1
db/migrations/000021_linestate.down.sql
Normal file
@ -0,0 +1 @@
|
||||
ALTER TABLE line DROP COLUMN linestate;
|
1
db/migrations/000021_linestate.up.sql
Normal file
1
db/migrations/000021_linestate.up.sql
Normal file
@ -0,0 +1 @@
|
||||
ALTER TABLE line ADD COLUMN linestate json NOT NULL DEFAULT '{}';
|
@ -68,7 +68,6 @@ CREATE TABLE history (
|
||||
remoteid varchar(36) NOT NULL,
|
||||
remotename varchar(50) NOT NULL,
|
||||
haderror boolean NOT NULL,
|
||||
cmdid varchar(36) NOT NULL,
|
||||
cmdstr text NOT NULL,
|
||||
ismetacmd boolean,
|
||||
incognito boolean
|
||||
@ -160,36 +159,13 @@ CREATE TABLE IF NOT EXISTS "line" (
|
||||
linetype varchar(10) NOT NULL,
|
||||
linelocal boolean NOT NULL,
|
||||
text text NOT NULL,
|
||||
cmdid varchar(36) NOT NULL,
|
||||
ephemeral boolean NOT NULL,
|
||||
contentheight int NOT NULL,
|
||||
star int NOT NULL,
|
||||
archived boolean NOT NULL,
|
||||
renderer varchar(50) NOT NULL,
|
||||
renderer varchar(50) NOT NULL, linestate json NOT NULL DEFAULT '{}',
|
||||
PRIMARY KEY (screenid, lineid)
|
||||
);
|
||||
CREATE TABLE IF NOT EXISTS "cmd" (
|
||||
screenid varchar(36) NOT NULL,
|
||||
cmdid varchar(36) NOT NULL,
|
||||
remoteownerid varchar(36) NOT NULL,
|
||||
remoteid varchar(36) NOT NULL,
|
||||
remotename varchar(50) NOT NULL,
|
||||
cmdstr text NOT NULL,
|
||||
rawcmdstr text NOT NULL,
|
||||
festate json NOT NULL,
|
||||
statebasehash varchar(36) NOT NULL,
|
||||
statediffhasharr json NOT NULL,
|
||||
termopts json NOT NULL,
|
||||
origtermopts json NOT NULL,
|
||||
status varchar(10) NOT NULL,
|
||||
startpk json NOT NULL,
|
||||
doneinfo json NOT NULL,
|
||||
runout json NOT NULL,
|
||||
rtnstate boolean NOT NULL,
|
||||
rtnbasehash varchar(36) NOT NULL,
|
||||
rtndiffhasharr json NOT NULL,
|
||||
PRIMARY KEY (screenid, cmdid)
|
||||
);
|
||||
CREATE TABLE screenupdate (
|
||||
updateid integer PRIMARY KEY,
|
||||
screenid varchar(36) NOT NULL,
|
||||
@ -204,3 +180,40 @@ CREATE TABLE webptypos (
|
||||
PRIMARY KEY (screenid, lineid)
|
||||
);
|
||||
CREATE INDEX idx_screenupdate_ids ON screenupdate (screenid, lineid);
|
||||
CREATE TABLE cmd_migration (
|
||||
screenid varchar(36) NOT NULL,
|
||||
lineid varchar(36) NOT NULL,
|
||||
cmdid varchar(36) NOT NULL,
|
||||
PRIMARY KEY (screenid, lineid)
|
||||
);
|
||||
CREATE TABLE IF NOT EXISTS "cmd" (
|
||||
screenid varchar(36) NOT NULL,
|
||||
lineid varchar(36) NOT NULL,
|
||||
remoteownerid varchar(36) NOT NULL,
|
||||
remoteid varchar(36) NOT NULL,
|
||||
remotename varchar(50) NOT NULL,
|
||||
cmdstr text NOT NULL,
|
||||
rawcmdstr text NOT NULL,
|
||||
festate json NOT NULL,
|
||||
statebasehash varchar(36) NOT NULL,
|
||||
statediffhasharr json NOT NULL,
|
||||
termopts json NOT NULL,
|
||||
origtermopts json NOT NULL,
|
||||
status varchar(10) NOT NULL,
|
||||
cmdpid int NOT NULL,
|
||||
remotepid int NOT NULL,
|
||||
donets bigint NOT NULL,
|
||||
exitcode int NOT NULL,
|
||||
durationms int NOT NULL,
|
||||
rtnstate boolean NOT NULL,
|
||||
rtnbasehash varchar(36) NOT NULL,
|
||||
rtndiffhasharr json NOT NULL,
|
||||
runout json NOT NULL,
|
||||
PRIMARY KEY (screenid, lineid)
|
||||
);
|
||||
CREATE TABLE cmd_migrate20 (
|
||||
screenid varchar(36) NOT NULL,
|
||||
lineid varchar(36) NOT NULL,
|
||||
cmdid varchar(36) NOT NULL,
|
||||
PRIMARY KEY (screenid, lineid)
|
||||
);
|
||||
|
@ -5,6 +5,7 @@ import (
|
||||
"context"
|
||||
"crypto/rand"
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/fs"
|
||||
"log"
|
||||
@ -23,6 +24,7 @@ import (
|
||||
"github.com/commandlinedev/apishell/pkg/packet"
|
||||
"github.com/commandlinedev/apishell/pkg/shexec"
|
||||
"github.com/commandlinedev/prompt-server/pkg/comp"
|
||||
"github.com/commandlinedev/prompt-server/pkg/dbutil"
|
||||
"github.com/commandlinedev/prompt-server/pkg/pcloud"
|
||||
"github.com/commandlinedev/prompt-server/pkg/remote"
|
||||
"github.com/commandlinedev/prompt-server/pkg/remote/openai"
|
||||
@ -63,6 +65,7 @@ const TsFormatStr = "2006-01-02 15:04:05"
|
||||
const (
|
||||
KwArgRenderer = "renderer"
|
||||
KwArgView = "view"
|
||||
KwArgState = "state"
|
||||
)
|
||||
|
||||
var ColorNames = []string{"black", "red", "green", "yellow", "blue", "magenta", "cyan", "white", "orange"}
|
||||
@ -2604,8 +2607,23 @@ func LineSetCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (ssto
|
||||
}
|
||||
varsUpdated = append(varsUpdated, KwArgView)
|
||||
}
|
||||
if stateJson, found := pk.Kwargs[KwArgState]; found {
|
||||
if len(stateJson) > sstore.MaxLineStateSize {
|
||||
return nil, fmt.Errorf("invalid state value (too large), size[%d], max[%d]", len(stateJson), sstore.MaxLineStateSize)
|
||||
}
|
||||
var stateMap map[string]any
|
||||
err = json.Unmarshal([]byte(stateJson), &stateMap)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("invalid state value, cannot parse json: %v", err)
|
||||
}
|
||||
err = sstore.UpdateLineState(ctx, ids.ScreenId, lineId, stateMap)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("cannot update linestate: %v", err)
|
||||
}
|
||||
varsUpdated = append(varsUpdated, KwArgState)
|
||||
}
|
||||
if len(varsUpdated) == 0 {
|
||||
return nil, fmt.Errorf("/line:set requires a value to set: %s", formatStrs([]string{KwArgView}, "or", false))
|
||||
return nil, fmt.Errorf("/line:set requires a value to set: %s", formatStrs([]string{KwArgView, KwArgState}, "or", false))
|
||||
}
|
||||
updatedLine, err := sstore.GetLineById(ctx, ids.ScreenId, lineId)
|
||||
if err != nil {
|
||||
@ -2836,7 +2854,7 @@ func LineStarCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (sst
|
||||
if starVal > 5 {
|
||||
return nil, fmt.Errorf("/line:star invalid star-value must be in the range of 0-5")
|
||||
}
|
||||
err = sstore.UpdateLineStar(ctx, lineId, starVal)
|
||||
err = sstore.UpdateLineStar(ctx, ids.ScreenId, lineId, starVal)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("/line:star error updating star value: %v", err)
|
||||
}
|
||||
@ -2991,6 +3009,11 @@ func LineShowCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (sst
|
||||
buf.WriteString(fmt.Sprintf(" %-15s %dms\n", "duration", cmd.DurationMs))
|
||||
}
|
||||
}
|
||||
stateStr := dbutil.QuickJson(line.LineState)
|
||||
if len(stateStr) > 80 {
|
||||
stateStr = stateStr[0:77] + "..."
|
||||
}
|
||||
buf.WriteString(fmt.Sprintf(" %-15s %s\n", "state", stateStr))
|
||||
update := &sstore.ModelUpdate{
|
||||
Info: &sstore.InfoMsgType{
|
||||
InfoTitle: fmt.Sprintf("line %d info", line.LineNum),
|
||||
|
@ -58,11 +58,11 @@ func GetMapGen[PT MapConverterPtr[T], T any](tx *txwrap.TxWrap, query string, ar
|
||||
}
|
||||
|
||||
func GetMappable[PT DBMappablePtr[T], T any](tx *txwrap.TxWrap, query string, args ...interface{}) PT {
|
||||
rtn := PT(new(T))
|
||||
m := tx.GetMap(query, args...)
|
||||
if len(m) == 0 {
|
||||
return nil
|
||||
}
|
||||
rtn := PT(new(T))
|
||||
FromDBMap(rtn, m)
|
||||
return rtn
|
||||
}
|
||||
|
@ -339,6 +339,9 @@ func makeWebShareUpdate(ctx context.Context, update *sstore.ScreenUpdateType) (*
|
||||
rtn.PtyData = &WebSharePtyData{PtyPos: realOffset, Data: data, Eof: true}
|
||||
}
|
||||
|
||||
case sstore.UpdateType_LineState:
|
||||
// TODO implement!
|
||||
|
||||
default:
|
||||
return nil, fmt.Errorf("unsupported update type (pcloud/makeWebScreenUpdate): %s\n", update.UpdateType)
|
||||
}
|
||||
|
@ -471,7 +471,7 @@ func GetScreenLinesById(ctx context.Context, screenId string) (*ScreenLinesType,
|
||||
return nil, nil
|
||||
}
|
||||
query = `SELECT * FROM line WHERE screenid = ? ORDER BY linenum`
|
||||
tx.Select(&screen.Lines, query, screen.ScreenId)
|
||||
screen.Lines = dbutil.SelectMappable[*LineType](tx, query, screen.ScreenId)
|
||||
query = `SELECT * FROM cmd WHERE screenid = ?`
|
||||
screen.Cmds = dbutil.SelectMapsGen[*CmdType](tx, query, screen.ScreenId)
|
||||
return screen, nil
|
||||
@ -761,16 +761,15 @@ func FindLineIdByArg(ctx context.Context, screenId string, lineArg string) (stri
|
||||
|
||||
func GetLineCmdByLineId(ctx context.Context, screenId string, lineId string) (*LineType, *CmdType, error) {
|
||||
return WithTxRtn3(ctx, func(tx *TxWrap) (*LineType, *CmdType, error) {
|
||||
var lineVal LineType
|
||||
query := `SELECT * FROM line WHERE screenid = ? AND lineid = ?`
|
||||
found := tx.Get(&lineVal, query, screenId, lineId)
|
||||
if !found {
|
||||
lineVal := dbutil.GetMappable[*LineType](tx, query, screenId, lineId)
|
||||
if lineVal == nil {
|
||||
return nil, nil, nil
|
||||
}
|
||||
var cmdRtn *CmdType
|
||||
query = `SELECT * FROM cmd WHERE screenid = ? AND lineid = ?`
|
||||
cmdRtn = dbutil.GetMapGen[*CmdType](tx, query, screenId, lineId)
|
||||
return &lineVal, cmdRtn, nil
|
||||
return lineVal, cmdRtn, nil
|
||||
})
|
||||
}
|
||||
|
||||
@ -795,9 +794,9 @@ func InsertLine(ctx context.Context, line *LineType, cmd *CmdType) error {
|
||||
query = `SELECT nextlinenum FROM screen WHERE screenid = ?`
|
||||
nextLineNum := tx.GetInt(query, line.ScreenId)
|
||||
line.LineNum = int64(nextLineNum)
|
||||
query = `INSERT INTO line ( screenid, userid, lineid, ts, linenum, linenumtemp, linelocal, linetype, text, renderer, ephemeral, contentheight, star, archived)
|
||||
VALUES (:screenid,:userid,:lineid,:ts,:linenum,:linenumtemp,:linelocal,:linetype,:text,:renderer,:ephemeral,:contentheight,:star,:archived)`
|
||||
tx.NamedExec(query, line)
|
||||
query = `INSERT INTO line ( screenid, userid, lineid, ts, linenum, linenumtemp, linelocal, linetype, linestate, text, renderer, ephemeral, contentheight, star, archived)
|
||||
VALUES (:screenid,:userid,:lineid,:ts,:linenum,:linenumtemp,:linelocal,:linetype,:linestate,:text,:renderer,:ephemeral,:contentheight,:star,:archived)`
|
||||
tx.NamedExec(query, dbutil.ToDBMap(line, false))
|
||||
query = `UPDATE screen SET nextlinenum = ? WHERE screenid = ?`
|
||||
tx.Exec(query, nextLineNum+1, line.ScreenId)
|
||||
if cmd != nil {
|
||||
@ -1889,10 +1888,10 @@ func GetFullState(ctx context.Context, ssPtr ShellStatePtr) (*packet.ShellState,
|
||||
return state, nil
|
||||
}
|
||||
|
||||
func UpdateLineStar(ctx context.Context, lineId string, starVal int) error {
|
||||
func UpdateLineStar(ctx context.Context, screenId string, lineId string, starVal int) error {
|
||||
txErr := WithTx(ctx, func(tx *TxWrap) error {
|
||||
query := `UPDATE line SET star = ? WHERE lineid = ?`
|
||||
tx.Exec(query, starVal, lineId)
|
||||
query := `UPDATE line SET star = ? WHERE screenid = ? AND lineid = ?`
|
||||
tx.Exec(query, starVal, screenId, lineId)
|
||||
return nil
|
||||
})
|
||||
if txErr != nil {
|
||||
@ -1903,8 +1902,8 @@ func UpdateLineStar(ctx context.Context, lineId string, starVal int) error {
|
||||
|
||||
func UpdateLineHeight(ctx context.Context, screenId string, lineId string, heightVal int) error {
|
||||
txErr := WithTx(ctx, func(tx *TxWrap) error {
|
||||
query := `UPDATE line SET contentheight = ? WHERE lineid = ?`
|
||||
tx.Exec(query, heightVal, lineId)
|
||||
query := `UPDATE line SET contentheight = ? WHERE screenid = ? AND lineid = ?`
|
||||
tx.Exec(query, heightVal, screenId, lineId)
|
||||
if isWebShare(tx, screenId) {
|
||||
insertScreenLineUpdate(tx, screenId, lineId, UpdateType_LineContentHeight)
|
||||
}
|
||||
@ -1918,8 +1917,8 @@ func UpdateLineHeight(ctx context.Context, screenId string, lineId string, heigh
|
||||
|
||||
func UpdateLineRenderer(ctx context.Context, screenId string, lineId string, renderer string) error {
|
||||
return WithTx(ctx, func(tx *TxWrap) error {
|
||||
query := `UPDATE line SET renderer = ? WHERE lineid = ?`
|
||||
tx.Exec(query, renderer, lineId)
|
||||
query := `UPDATE line SET renderer = ? WHERE screenid = ? AND lineid = ?`
|
||||
tx.Exec(query, renderer, screenId, lineId)
|
||||
if isWebShare(tx, screenId) {
|
||||
insertScreenLineUpdate(tx, screenId, lineId, UpdateType_LineRenderer)
|
||||
}
|
||||
@ -1927,28 +1926,34 @@ func UpdateLineRenderer(ctx context.Context, screenId string, lineId string, ren
|
||||
})
|
||||
}
|
||||
|
||||
// can return nil, nil if line is not found
|
||||
func GetLineById(ctx context.Context, screenId string, lineId string) (*LineType, error) {
|
||||
var rtn *LineType
|
||||
txErr := WithTx(ctx, func(tx *TxWrap) error {
|
||||
var line LineType
|
||||
query := `SELECT * FROM line WHERE screenid = ? AND lineid = ?`
|
||||
found := tx.Get(&line, query, screenId, lineId)
|
||||
if found {
|
||||
rtn = &line
|
||||
func UpdateLineState(ctx context.Context, screenId string, lineId string, lineState map[string]any) error {
|
||||
qjs := dbutil.QuickJson(lineState)
|
||||
if len(qjs) > MaxLineStateSize {
|
||||
return fmt.Errorf("linestate for line[%s:%s] exceeds maxsize, size[%d] max[%d]", screenId, lineId, len(qjs), MaxLineStateSize)
|
||||
}
|
||||
return WithTx(ctx, func(tx *TxWrap) error {
|
||||
query := `UPDATE line SET linestate = ? WHERE screenid = ? AND lineid = ?`
|
||||
tx.Exec(query, qjs, screenId, lineId)
|
||||
if isWebShare(tx, screenId) {
|
||||
insertScreenLineUpdate(tx, screenId, lineId, UpdateType_LineState)
|
||||
}
|
||||
return nil
|
||||
})
|
||||
if txErr != nil {
|
||||
return nil, txErr
|
||||
}
|
||||
return rtn, nil
|
||||
}
|
||||
|
||||
// can return nil, nil if line is not found
|
||||
func GetLineById(ctx context.Context, screenId string, lineId string) (*LineType, error) {
|
||||
return WithTxRtn(ctx, func(tx *TxWrap) (*LineType, error) {
|
||||
query := `SELECT * FROM line WHERE screenid = ? AND lineid = ?`
|
||||
line := dbutil.GetMappable[*LineType](tx, query, screenId, lineId)
|
||||
return line, nil
|
||||
})
|
||||
}
|
||||
|
||||
func SetLineArchivedById(ctx context.Context, screenId string, lineId string, archived bool) error {
|
||||
txErr := WithTx(ctx, func(tx *TxWrap) error {
|
||||
query := `UPDATE line SET archived = ? WHERE lineid = ?`
|
||||
tx.Exec(query, archived, lineId)
|
||||
query := `UPDATE line SET archived = ? WHERE screenid = ? AND lineid = ?`
|
||||
tx.Exec(query, archived, screenId, lineId)
|
||||
if isWebShare(tx, screenId) {
|
||||
if archived {
|
||||
insertScreenLineUpdate(tx, screenId, lineId, UpdateType_LineDel)
|
||||
@ -2395,10 +2400,9 @@ func GetLineCmdsFromHistoryItems(ctx context.Context, historyItems []*HistoryIte
|
||||
return nil, nil, nil
|
||||
}
|
||||
return WithTxRtn3(ctx, func(tx *TxWrap) ([]*LineType, []*CmdType, error) {
|
||||
var lineArr []*LineType
|
||||
lineIdsJsonArr := quickJsonArr(getLineIdsFromHistoryItems(historyItems))
|
||||
query := `SELECT * FROM line WHERE lineid IN (SELECT value FROM json_each(?))`
|
||||
tx.Select(&lineArr, query, lineIdsJsonArr)
|
||||
lineArr := dbutil.SelectMappable[*LineType](tx, query, lineIdsJsonArr)
|
||||
query = `SELECT * FROM cmd WHERE lineid IN (SELECT value FROM json_each(?))`
|
||||
cmdArr := dbutil.SelectMapsGen[*CmdType](tx, query, lineIdsJsonArr)
|
||||
return lineArr, cmdArr, nil
|
||||
|
@ -17,7 +17,7 @@ import (
|
||||
"github.com/golang-migrate/migrate/v4"
|
||||
)
|
||||
|
||||
const MaxMigration = 20
|
||||
const MaxMigration = 21
|
||||
const MigratePrimaryScreenVersion = 9
|
||||
const CmdScreenSpecialMigration = 13
|
||||
const CmdLineSpecialMigration = 20
|
||||
|
@ -34,6 +34,7 @@ const DBFileName = "prompt.db"
|
||||
const DBFileNameBackup = "backup.prompt.db"
|
||||
const MaxWebShareLineCount = 50
|
||||
const MaxWebShareScreenCount = 3
|
||||
const MaxLineStateSize = 4 * 1024 // 4k for now, can raise if needed
|
||||
|
||||
const DefaultSessionName = "default"
|
||||
const LocalRemoteAlias = "local"
|
||||
@ -113,6 +114,7 @@ const (
|
||||
UpdateType_LineDel = "line:del"
|
||||
UpdateType_LineRenderer = "line:renderer"
|
||||
UpdateType_LineContentHeight = "line:contentheight"
|
||||
UpdateType_LineState = "line:state"
|
||||
UpdateType_CmdStatus = "cmd:status"
|
||||
UpdateType_CmdTermOpts = "cmd:termopts"
|
||||
UpdateType_CmdExitCode = "cmd:exitcode"
|
||||
@ -707,23 +709,26 @@ type ScreenUpdateType struct {
|
||||
func (ScreenUpdateType) UseDBMap() {}
|
||||
|
||||
type LineType struct {
|
||||
ScreenId string `json:"screenid"`
|
||||
UserId string `json:"userid"`
|
||||
LineId string `json:"lineid"`
|
||||
Ts int64 `json:"ts"`
|
||||
LineNum int64 `json:"linenum"`
|
||||
LineNumTemp bool `json:"linenumtemp,omitempty"`
|
||||
LineLocal bool `json:"linelocal"`
|
||||
LineType string `json:"linetype"`
|
||||
Renderer string `json:"renderer,omitempty"`
|
||||
Text string `json:"text,omitempty"`
|
||||
Ephemeral bool `json:"ephemeral,omitempty"`
|
||||
ContentHeight int64 `json:"contentheight,omitempty"`
|
||||
Star bool `json:"star,omitempty"`
|
||||
Archived bool `json:"archived,omitempty"`
|
||||
Remove bool `json:"remove,omitempty"`
|
||||
ScreenId string `json:"screenid"`
|
||||
UserId string `json:"userid"`
|
||||
LineId string `json:"lineid"`
|
||||
Ts int64 `json:"ts"`
|
||||
LineNum int64 `json:"linenum"`
|
||||
LineNumTemp bool `json:"linenumtemp,omitempty"`
|
||||
LineLocal bool `json:"linelocal"`
|
||||
LineType string `json:"linetype"`
|
||||
LineState map[string]any `json:"linestate"`
|
||||
Renderer string `json:"renderer,omitempty"`
|
||||
Text string `json:"text,omitempty"`
|
||||
Ephemeral bool `json:"ephemeral,omitempty"`
|
||||
ContentHeight int64 `json:"contentheight,omitempty"`
|
||||
Star bool `json:"star,omitempty"`
|
||||
Archived bool `json:"archived,omitempty"`
|
||||
Remove bool `json:"remove,omitempty"`
|
||||
}
|
||||
|
||||
func (LineType) UseDBMap() {}
|
||||
|
||||
type OpenAIUsage struct {
|
||||
PromptTokens int `json:"prompt_tokens"`
|
||||
CompletionTokens int `json:"completion_tokens"`
|
||||
|
Loading…
Reference in New Issue
Block a user