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-09-03 05:21:35 +02:00
"github.com/wavetermdev/thenextwave/pkg/wconfig"
2024-07-18 00:24:43 +02:00
)
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"
2024-09-05 09:21:08 +02:00
Command_ControllerStop = "controllerstop"
Command_ControllerResync = "controllerresync"
2024-07-26 22:30:11 +02:00
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-09-04 06:08:51 +02:00
Command_RemoteFileJoiin = "remotefilejoin"
2024-09-04 07:15:02 +02:00
Command_ConnEnsure = "connensure"
Command_ConnReinstallWsh = "connreinstallwsh"
2024-09-04 08:04:19 +02:00
Command_ConnConnect = "connconnect"
2024-09-04 07:15:02 +02:00
Command_ConnDisconnect = "conndisconnect"
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
2024-09-05 09:21:08 +02:00
ControllerStopCommand ( ctx context . Context , blockId string ) error
ControllerResyncCommand ( ctx context . Context , data CommandControllerResyncData ) error
2024-07-26 22:30:11 +02:00
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-09-03 05:21:35 +02:00
SetConfigCommand ( ctx context . Context , data wconfig . MetaSettingsType ) error
2024-08-12 19:58:39 +02:00
2024-09-04 07:15:02 +02:00
// connection functions
2024-09-04 08:04:19 +02:00
ConnStatusCommand ( ctx context . Context ) ( [ ] ConnStatus , error )
2024-09-04 07:15:02 +02:00
ConnEnsureCommand ( ctx context . Context , connName string ) error
ConnReinstallWshCommand ( ctx context . Context , connName string ) error
2024-09-04 08:04:19 +02:00
ConnConnectCommand ( ctx context . Context , connName string ) error
2024-09-04 07:15:02 +02:00
ConnDisconnectCommand ( ctx context . Context , connName string ) error
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-09-04 06:08:51 +02:00
RemoteFileJoinCommand ( ctx context . Context , paths [ ] string ) ( * FileInfo , 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" `
}
2024-09-05 09:21:08 +02:00
type CommandControllerResyncData struct {
ForceRestart bool ` json:"forcerestart,omitempty" `
TabId string ` json:"tabid" wshcontext:"TabId" `
BlockId string ` json:"blockid" wshcontext:"BlockId" `
RtOpts * waveobj . RuntimeOpts ` json:"rtopts,omitempty" `
2024-07-18 00:24:43 +02:00
}
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 {
2024-09-03 01:48:10 +02:00
Path string ` json:"path" ` // cleaned path (may have "~")
Dir string ` json:"dir" ` // returns the directory part of the path (if this is a a directory, it will be equal to Path). "~" will be expanded, and separators will be normalized to "/"
2024-08-12 19:58:39 +02:00
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" `
2024-09-03 01:48:10 +02:00
ReadOnly bool ` json:"readonly,omitempty" ` // this is not set for fileinfo's returned from directory listings
2024-08-12 19:58:39 +02:00
}
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 {
2024-09-04 07:15:02 +02:00
Status string ` json:"status" `
Connection string ` json:"connection" `
Connected bool ` json:"connected" `
HasConnected bool ` json:"hasconnected" ` // true if it has *ever* connected successfully
Error string ` json:"error,omitempty" `
2024-08-24 03:12:40 +02:00
}