2024-07-18 00:24:43 +02:00
|
|
|
// Copyright 2024, Command Line Inc.
|
|
|
|
// SPDX-License-Identifier: Apache-2.0
|
|
|
|
|
|
|
|
// types and methods for wsh rpc calls
|
|
|
|
package wshrpc
|
|
|
|
|
|
|
|
import (
|
2024-07-26 22:30:11 +02:00
|
|
|
"context"
|
2024-08-14 01:52:35 +02:00
|
|
|
"log"
|
2024-08-12 19:58:39 +02:00
|
|
|
"os"
|
2024-07-18 00:24:43 +02:00
|
|
|
"reflect"
|
|
|
|
|
|
|
|
"github.com/wavetermdev/thenextwave/pkg/ijson"
|
2024-08-20 23:56:48 +02:00
|
|
|
"github.com/wavetermdev/thenextwave/pkg/util/utilfn"
|
2024-07-18 00:24:43 +02:00
|
|
|
"github.com/wavetermdev/thenextwave/pkg/waveobj"
|
|
|
|
)
|
|
|
|
|
2024-08-17 03:45:45 +02:00
|
|
|
const LocalConnName = "local"
|
|
|
|
|
2024-07-18 00:24:43 +02:00
|
|
|
const (
|
2024-07-26 22:30:11 +02:00
|
|
|
RpcType_Call = "call" // single response (regular rpc)
|
|
|
|
RpcType_ResponseStream = "responsestream" // stream of responses (streaming rpc)
|
|
|
|
RpcType_StreamingRequest = "streamingrequest" // streaming request
|
|
|
|
RpcType_Complex = "complex" // streaming request/response
|
2024-07-18 00:24:43 +02:00
|
|
|
)
|
|
|
|
|
2024-07-26 22:30:11 +02:00
|
|
|
const (
|
2024-08-30 23:36:16 +02:00
|
|
|
Event_BlockClose = "blockclose"
|
|
|
|
Event_ConnChange = "connchange"
|
|
|
|
Event_SysInfo = "sysinfo"
|
|
|
|
Event_ControllerStatus = "controllerstatus"
|
2024-08-20 23:56:48 +02:00
|
|
|
)
|
|
|
|
|
|
|
|
const (
|
|
|
|
Command_Authenticate = "authenticate" // special
|
|
|
|
Command_Announce = "announce" // special (for routing)
|
2024-07-26 22:30:11 +02:00
|
|
|
Command_Message = "message"
|
|
|
|
Command_GetMeta = "getmeta"
|
|
|
|
Command_SetMeta = "setmeta"
|
|
|
|
Command_SetView = "setview"
|
|
|
|
Command_ControllerInput = "controllerinput"
|
|
|
|
Command_ControllerRestart = "controllerrestart"
|
|
|
|
Command_FileAppend = "fileappend"
|
|
|
|
Command_FileAppendIJson = "fileappendijson"
|
|
|
|
Command_ResolveIds = "resolveids"
|
|
|
|
Command_CreateBlock = "createblock"
|
|
|
|
Command_DeleteBlock = "deleteblock"
|
|
|
|
Command_FileWrite = "filewrite"
|
|
|
|
Command_FileRead = "fileread"
|
|
|
|
Command_EventPublish = "eventpublish"
|
|
|
|
Command_EventRecv = "eventrecv"
|
|
|
|
Command_EventSub = "eventsub"
|
|
|
|
Command_EventUnsub = "eventunsub"
|
|
|
|
Command_EventUnsubAll = "eventunsuball"
|
2024-08-30 20:33:04 +02:00
|
|
|
Command_EventReadHistory = "eventreadhistory"
|
2024-07-26 22:30:11 +02:00
|
|
|
Command_StreamTest = "streamtest"
|
|
|
|
Command_StreamWaveAi = "streamwaveai"
|
2024-07-31 23:13:36 +02:00
|
|
|
Command_StreamCpuData = "streamcpudata"
|
2024-08-12 19:58:39 +02:00
|
|
|
Command_Test = "test"
|
|
|
|
Command_RemoteStreamFile = "remotestreamfile"
|
|
|
|
Command_RemoteFileInfo = "remotefileinfo"
|
2024-08-14 03:36:11 +02:00
|
|
|
Command_RemoteWriteFile = "remotewritefile"
|
2024-08-19 20:02:40 +02:00
|
|
|
Command_RemoteFileDelete = "remotefiledelete"
|
2024-07-26 22:30:11 +02:00
|
|
|
)
|
2024-07-18 00:24:43 +02:00
|
|
|
|
2024-07-19 00:56:04 +02:00
|
|
|
type RespOrErrorUnion[T any] struct {
|
|
|
|
Response T
|
|
|
|
Error error
|
|
|
|
}
|
|
|
|
|
2024-07-26 22:30:11 +02:00
|
|
|
type WshRpcInterface interface {
|
2024-08-20 23:56:48 +02:00
|
|
|
AuthenticateCommand(ctx context.Context, data string) (CommandAuthenticateRtnData, error)
|
2024-08-17 01:49:49 +02:00
|
|
|
AnnounceCommand(ctx context.Context, data string) error // (special) announces a new route to the main router
|
2024-08-14 01:52:35 +02:00
|
|
|
|
2024-07-26 22:30:11 +02:00
|
|
|
MessageCommand(ctx context.Context, data CommandMessageData) error
|
2024-08-20 23:56:48 +02:00
|
|
|
GetMetaCommand(ctx context.Context, data CommandGetMetaData) (waveobj.MetaMapType, error)
|
2024-07-26 22:30:11 +02:00
|
|
|
SetMetaCommand(ctx context.Context, data CommandSetMetaData) error
|
|
|
|
SetViewCommand(ctx context.Context, data CommandBlockSetViewData) error
|
|
|
|
ControllerInputCommand(ctx context.Context, data CommandBlockInputData) error
|
|
|
|
ControllerRestartCommand(ctx context.Context, data CommandBlockRestartData) error
|
|
|
|
FileAppendCommand(ctx context.Context, data CommandFileData) error
|
|
|
|
FileAppendIJsonCommand(ctx context.Context, data CommandAppendIJsonData) error
|
|
|
|
ResolveIdsCommand(ctx context.Context, data CommandResolveIdsData) (CommandResolveIdsRtnData, error)
|
|
|
|
CreateBlockCommand(ctx context.Context, data CommandCreateBlockData) (waveobj.ORef, error)
|
|
|
|
DeleteBlockCommand(ctx context.Context, data CommandDeleteBlockData) error
|
|
|
|
FileWriteCommand(ctx context.Context, data CommandFileData) error
|
|
|
|
FileReadCommand(ctx context.Context, data CommandFileData) (string, error)
|
|
|
|
EventPublishCommand(ctx context.Context, data WaveEvent) error
|
|
|
|
EventSubCommand(ctx context.Context, data SubscriptionRequest) error
|
2024-08-24 03:12:40 +02:00
|
|
|
EventUnsubCommand(ctx context.Context, data string) error
|
2024-07-26 22:30:11 +02:00
|
|
|
EventUnsubAllCommand(ctx context.Context) error
|
2024-08-30 20:33:04 +02:00
|
|
|
EventReadHistoryCommand(ctx context.Context, data CommandEventReadHistoryData) ([]*WaveEvent, error)
|
2024-07-26 22:30:11 +02:00
|
|
|
StreamTestCommand(ctx context.Context) chan RespOrErrorUnion[int]
|
|
|
|
StreamWaveAiCommand(ctx context.Context, request OpenAiStreamRequest) chan RespOrErrorUnion[OpenAIPacketType]
|
2024-08-20 00:01:00 +02:00
|
|
|
StreamCpuDataCommand(ctx context.Context, request CpuDataRequest) chan RespOrErrorUnion[TimeSeriesData]
|
2024-08-12 19:58:39 +02:00
|
|
|
TestCommand(ctx context.Context, data string) error
|
2024-08-28 07:02:21 +02:00
|
|
|
SetConfigCommand(ctx context.Context, data waveobj.MetaMapType) error
|
2024-08-12 19:58:39 +02:00
|
|
|
|
2024-08-20 23:56:48 +02:00
|
|
|
// eventrecv is special, it's handled internally by WshRpc with EventListener
|
|
|
|
EventRecvCommand(ctx context.Context, data WaveEvent) error
|
|
|
|
|
2024-08-12 19:58:39 +02:00
|
|
|
// remotes
|
|
|
|
RemoteStreamFileCommand(ctx context.Context, data CommandRemoteStreamFileData) chan RespOrErrorUnion[CommandRemoteStreamFileRtnData]
|
|
|
|
RemoteFileInfoCommand(ctx context.Context, path string) (*FileInfo, error)
|
2024-08-19 20:02:40 +02:00
|
|
|
RemoteFileDeleteCommand(ctx context.Context, path string) error
|
2024-08-14 03:36:11 +02:00
|
|
|
RemoteWriteFileCommand(ctx context.Context, data CommandRemoteWriteFileData) error
|
2024-08-20 00:01:00 +02:00
|
|
|
RemoteStreamCpuDataCommand(ctx context.Context) chan RespOrErrorUnion[TimeSeriesData]
|
2024-07-26 22:30:11 +02:00
|
|
|
}
|
|
|
|
|
2024-07-18 00:24:43 +02:00
|
|
|
// for frontend
|
|
|
|
type WshServerCommandMeta struct {
|
|
|
|
CommandType string `json:"commandtype"`
|
|
|
|
}
|
|
|
|
|
2024-08-14 01:52:35 +02:00
|
|
|
type RpcOpts struct {
|
|
|
|
Timeout int `json:"timeout,omitempty"`
|
|
|
|
NoResponse bool `json:"noresponse,omitempty"`
|
|
|
|
Route string `json:"route,omitempty"`
|
2024-08-20 00:44:30 +02:00
|
|
|
|
|
|
|
StreamCancelFn func() `json:"-"` // this is an *output* parameter, set by the handler
|
2024-07-18 00:24:43 +02:00
|
|
|
}
|
|
|
|
|
2024-08-20 23:56:48 +02:00
|
|
|
const (
|
|
|
|
ClientType_ConnServer = "connserver"
|
|
|
|
ClientType_BlockController = "blockcontroller"
|
|
|
|
)
|
|
|
|
|
2024-07-26 22:30:11 +02:00
|
|
|
type RpcContext struct {
|
2024-08-20 23:56:48 +02:00
|
|
|
ClientType string `json:"ctype,omitempty"`
|
|
|
|
BlockId string `json:"blockid,omitempty"`
|
|
|
|
TabId string `json:"tabid,omitempty"`
|
|
|
|
Conn string `json:"conn,omitempty"`
|
2024-07-26 22:30:11 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
func HackRpcContextIntoData(dataPtr any, rpcContext RpcContext) {
|
2024-07-18 00:24:43 +02:00
|
|
|
dataVal := reflect.ValueOf(dataPtr).Elem()
|
2024-08-10 02:46:52 +02:00
|
|
|
if dataVal.Kind() != reflect.Struct {
|
|
|
|
return
|
|
|
|
}
|
2024-07-18 00:24:43 +02:00
|
|
|
dataType := dataVal.Type()
|
|
|
|
for i := 0; i < dataVal.NumField(); i++ {
|
|
|
|
field := dataVal.Field(i)
|
|
|
|
if !field.IsZero() {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
fieldType := dataType.Field(i)
|
|
|
|
tag := fieldType.Tag.Get("wshcontext")
|
|
|
|
if tag == "" {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
switch tag {
|
|
|
|
case "BlockId":
|
|
|
|
field.SetString(rpcContext.BlockId)
|
|
|
|
case "TabId":
|
|
|
|
field.SetString(rpcContext.TabId)
|
|
|
|
case "BlockORef":
|
|
|
|
if rpcContext.BlockId != "" {
|
2024-08-20 23:56:48 +02:00
|
|
|
field.Set(reflect.ValueOf(waveobj.MakeORef(waveobj.OType_Block, rpcContext.BlockId)))
|
2024-07-18 00:24:43 +02:00
|
|
|
}
|
2024-08-14 01:52:35 +02:00
|
|
|
default:
|
|
|
|
log.Printf("invalid wshcontext tag: %q in type(%T)", tag, dataPtr)
|
2024-07-18 00:24:43 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-08-20 23:56:48 +02:00
|
|
|
type CommandAuthenticateRtnData struct {
|
|
|
|
RouteId string `json:"routeid"`
|
|
|
|
}
|
|
|
|
|
2024-07-18 00:24:43 +02:00
|
|
|
type CommandMessageData struct {
|
|
|
|
ORef waveobj.ORef `json:"oref" wshcontext:"BlockORef"`
|
|
|
|
Message string `json:"message"`
|
|
|
|
}
|
|
|
|
|
|
|
|
type CommandGetMetaData struct {
|
|
|
|
ORef waveobj.ORef `json:"oref" wshcontext:"BlockORef"`
|
|
|
|
}
|
|
|
|
|
|
|
|
type CommandSetMetaData struct {
|
2024-08-20 23:56:48 +02:00
|
|
|
ORef waveobj.ORef `json:"oref" wshcontext:"BlockORef"`
|
|
|
|
Meta waveobj.MetaMapType `json:"meta"`
|
2024-07-18 00:24:43 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
type CommandResolveIdsData struct {
|
2024-08-14 01:52:35 +02:00
|
|
|
BlockId string `json:"blockid" wshcontext:"BlockId"`
|
|
|
|
Ids []string `json:"ids"`
|
2024-07-18 00:24:43 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
type CommandResolveIdsRtnData struct {
|
|
|
|
ResolvedIds map[string]waveobj.ORef `json:"resolvedids"`
|
|
|
|
}
|
|
|
|
|
|
|
|
type CommandCreateBlockData struct {
|
2024-08-21 05:14:14 +02:00
|
|
|
TabId string `json:"tabid" wshcontext:"TabId"`
|
|
|
|
BlockDef *waveobj.BlockDef `json:"blockdef"`
|
|
|
|
RtOpts *waveobj.RuntimeOpts `json:"rtopts,omitempty"`
|
|
|
|
Magnified bool `json:"magnified,omitempty"`
|
2024-07-18 00:24:43 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
type CommandBlockSetViewData struct {
|
|
|
|
BlockId string `json:"blockid" wshcontext:"BlockId"`
|
|
|
|
View string `json:"view"`
|
|
|
|
}
|
|
|
|
|
|
|
|
type CommandBlockRestartData struct {
|
|
|
|
BlockId string `json:"blockid" wshcontext:"BlockId"`
|
|
|
|
}
|
|
|
|
|
|
|
|
type CommandBlockInputData struct {
|
2024-08-20 23:56:48 +02:00
|
|
|
BlockId string `json:"blockid" wshcontext:"BlockId"`
|
|
|
|
InputData64 string `json:"inputdata64,omitempty"`
|
|
|
|
SigName string `json:"signame,omitempty"`
|
|
|
|
TermSize *waveobj.TermSize `json:"termsize,omitempty"`
|
2024-07-18 00:24:43 +02:00
|
|
|
}
|
|
|
|
|
2024-07-23 22:16:53 +02:00
|
|
|
type CommandFileData struct {
|
2024-07-18 00:24:43 +02:00
|
|
|
ZoneId string `json:"zoneid" wshcontext:"BlockId"`
|
|
|
|
FileName string `json:"filename"`
|
2024-07-23 22:16:53 +02:00
|
|
|
Data64 string `json:"data64,omitempty"`
|
2024-07-18 00:24:43 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
type CommandAppendIJsonData struct {
|
|
|
|
ZoneId string `json:"zoneid" wshcontext:"BlockId"`
|
|
|
|
FileName string `json:"filename"`
|
|
|
|
Data ijson.Command `json:"data"`
|
|
|
|
}
|
2024-07-19 03:13:59 +02:00
|
|
|
|
|
|
|
type CommandDeleteBlockData struct {
|
|
|
|
BlockId string `json:"blockid" wshcontext:"BlockId"`
|
|
|
|
}
|
2024-07-26 22:30:11 +02:00
|
|
|
|
|
|
|
type WaveEvent struct {
|
2024-08-30 20:33:04 +02:00
|
|
|
Event string `json:"event"`
|
|
|
|
Scopes []string `json:"scopes,omitempty"`
|
|
|
|
Sender string `json:"sender,omitempty"`
|
|
|
|
Persist int `json:"persist,omitempty"`
|
|
|
|
Data any `json:"data,omitempty"`
|
2024-07-26 22:30:11 +02:00
|
|
|
}
|
|
|
|
|
2024-08-20 23:56:48 +02:00
|
|
|
func (e WaveEvent) HasScope(scope string) bool {
|
|
|
|
return utilfn.ContainsStr(e.Scopes, scope)
|
|
|
|
}
|
|
|
|
|
2024-07-26 22:30:11 +02:00
|
|
|
type SubscriptionRequest struct {
|
|
|
|
Event string `json:"event"`
|
|
|
|
Scopes []string `json:"scopes,omitempty"`
|
|
|
|
AllScopes bool `json:"allscopes,omitempty"`
|
|
|
|
}
|
|
|
|
|
2024-08-30 20:33:04 +02:00
|
|
|
type CommandEventReadHistoryData struct {
|
|
|
|
Event string `json:"event"`
|
|
|
|
Scope string `json:"scope"`
|
|
|
|
MaxItems int `json:"maxitems"`
|
|
|
|
}
|
|
|
|
|
2024-07-26 22:30:11 +02:00
|
|
|
type OpenAiStreamRequest struct {
|
|
|
|
ClientId string `json:"clientid,omitempty"`
|
|
|
|
Opts *OpenAIOptsType `json:"opts"`
|
|
|
|
Prompt []OpenAIPromptMessageType `json:"prompt"`
|
|
|
|
}
|
|
|
|
|
|
|
|
type OpenAIPromptMessageType struct {
|
|
|
|
Role string `json:"role"`
|
|
|
|
Content string `json:"content"`
|
|
|
|
Name string `json:"name,omitempty"`
|
|
|
|
}
|
|
|
|
|
|
|
|
type OpenAIOptsType struct {
|
|
|
|
Model string `json:"model"`
|
|
|
|
APIToken string `json:"apitoken"`
|
|
|
|
BaseURL string `json:"baseurl,omitempty"`
|
|
|
|
MaxTokens int `json:"maxtokens,omitempty"`
|
|
|
|
MaxChoices int `json:"maxchoices,omitempty"`
|
|
|
|
Timeout int `json:"timeout,omitempty"`
|
|
|
|
}
|
|
|
|
|
|
|
|
type OpenAIPacketType struct {
|
|
|
|
Type string `json:"type"`
|
|
|
|
Model string `json:"model,omitempty"`
|
|
|
|
Created int64 `json:"created,omitempty"`
|
|
|
|
FinishReason string `json:"finish_reason,omitempty"`
|
|
|
|
Usage *OpenAIUsageType `json:"usage,omitempty"`
|
|
|
|
Index int `json:"index,omitempty"`
|
|
|
|
Text string `json:"text,omitempty"`
|
|
|
|
Error string `json:"error,omitempty"`
|
|
|
|
}
|
|
|
|
|
|
|
|
type OpenAIUsageType struct {
|
|
|
|
PromptTokens int `json:"prompt_tokens,omitempty"`
|
|
|
|
CompletionTokens int `json:"completion_tokens,omitempty"`
|
|
|
|
TotalTokens int `json:"total_tokens,omitempty"`
|
|
|
|
}
|
2024-07-31 23:13:36 +02:00
|
|
|
|
|
|
|
type CpuDataRequest struct {
|
2024-08-01 09:57:06 +02:00
|
|
|
Id string `json:"id"`
|
|
|
|
Count int `json:"count"`
|
2024-07-31 23:13:36 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
type CpuDataType struct {
|
|
|
|
Time int64 `json:"time"`
|
|
|
|
Value float64 `json:"value"`
|
|
|
|
}
|
2024-08-12 19:58:39 +02:00
|
|
|
|
|
|
|
type FileInfo struct {
|
|
|
|
Path string `json:"path"` // cleaned path
|
|
|
|
Name string `json:"name"`
|
|
|
|
NotFound bool `json:"notfound,omitempty"`
|
|
|
|
Size int64 `json:"size"`
|
|
|
|
Mode os.FileMode `json:"mode"`
|
|
|
|
ModeStr string `json:"modestr"`
|
|
|
|
ModTime int64 `json:"modtime"`
|
|
|
|
IsDir bool `json:"isdir,omitempty"`
|
|
|
|
MimeType string `json:"mimetype,omitempty"`
|
|
|
|
}
|
|
|
|
|
|
|
|
type CommandRemoteStreamFileData struct {
|
|
|
|
Path string `json:"path"`
|
|
|
|
ByteRange string `json:"byterange,omitempty"`
|
|
|
|
}
|
|
|
|
|
|
|
|
type CommandRemoteStreamFileRtnData struct {
|
2024-08-19 20:02:40 +02:00
|
|
|
FileInfo []*FileInfo `json:"fileinfo,omitempty"`
|
|
|
|
Data64 string `json:"data64,omitempty"`
|
2024-08-12 19:58:39 +02:00
|
|
|
}
|
2024-08-14 03:36:11 +02:00
|
|
|
|
|
|
|
type CommandRemoteWriteFileData struct {
|
|
|
|
Path string `json:"path"`
|
|
|
|
Data64 string `json:"data64"`
|
|
|
|
CreateMode os.FileMode `json:"createmode,omitempty"`
|
|
|
|
}
|
2024-08-20 00:01:00 +02:00
|
|
|
|
|
|
|
const (
|
|
|
|
TimeSeries_Cpu = "cpu"
|
|
|
|
)
|
|
|
|
|
|
|
|
type TimeSeriesData struct {
|
|
|
|
Ts int64 `json:"ts"`
|
|
|
|
Values map[string]float64 `json:"values"`
|
|
|
|
}
|
2024-08-24 03:12:40 +02:00
|
|
|
|
|
|
|
type ConnStatus struct {
|
|
|
|
Status string `json:"status"`
|
|
|
|
Connection string `json:"connection"`
|
|
|
|
Connected bool `json:"connected"`
|
|
|
|
Error string `json:"error,omitempty"`
|
|
|
|
}
|