From c59d08d90e4cb2485a86fada9ef414f035aeba51 Mon Sep 17 00:00:00 2001 From: Oqoqqo Halp Date: Sun, 16 Mar 2025 09:06:45 -0700 Subject: [PATCH 1/4] vibe compile --- cmd/wsh/cmd/wshcmd-ai.go | 57 +++++++++++++++++++++++++++++ frontend/app/store/wshclientapi.ts | 5 +++ frontend/app/view/waveai/waveai.tsx | 10 +++++ frontend/types/gotypes.d.ts | 16 ++++++++ pkg/wshrpc/wshclient/wshclient.go | 6 +++ pkg/wshrpc/wshrpctypes.go | 15 ++++++++ 6 files changed, 109 insertions(+) diff --git a/cmd/wsh/cmd/wshcmd-ai.go b/cmd/wsh/cmd/wshcmd-ai.go index 71f175089..bea6b0238 100644 --- a/cmd/wsh/cmd/wshcmd-ai.go +++ b/cmd/wsh/cmd/wshcmd-ai.go @@ -159,3 +159,60 @@ func aiRun(cmd *cobra.Command, args []string) (rtnErr error) { return nil } + +// AI Get Command implementation section +var aigetCmd = &cobra.Command{ + Use: "aiget [blockid]", + Short: "Get messages from an AI block", + Long: "Get messages from an AI block. Use --limit or -n to specify maximum number of messages to retrieve (default: 10)", + RunE: aigetRun, + PreRunE: preRunSetupRpcClient, + DisableFlagsInUseLine: true, +} + +var aigetLimit int + +func init() { + rootCmd.AddCommand(aigetCmd) + aigetCmd.Flags().IntVarP(&aigetLimit, "limit", "n", 10, "maximum number of messages to retrieve") +} + +func aigetRun(cmd *cobra.Command, args []string) (rtnErr error) { + defer func() { + sendActivity("aiget", rtnErr == nil) + }() + + // Default to "waveai" block + isDefaultBlock := blockArg == "" + if isDefaultBlock { + blockArg = "view@waveai" + } + + fullORef, err := resolveSimpleId(blockArg) + if err != nil { + return fmt.Errorf("resolving block: %w", err) + } + + // Create the route for this block + route := wshutil.MakeFeBlockRouteId(fullORef.OID) + + messageData := wshrpc.AiGetMessagesData{ + Limit: aigetLimit, + } + + var response wshrpc.AiGetMessagesResponse + response, err = wshclient.AiGetMessagesCommand(RpcClient, messageData, &wshrpc.RpcOpts{ + Route: route, + Timeout: 2000, + }) + if err != nil { + return fmt.Errorf("getting messages: %w", err) + } + + // Print messages + for _, msg := range response.Messages { + fmt.Printf("%s: %s\n", msg.Role, msg.Content) + } + + return nil +} diff --git a/frontend/app/store/wshclientapi.ts b/frontend/app/store/wshclientapi.ts index fba651911..1d4c35201 100644 --- a/frontend/app/store/wshclientapi.ts +++ b/frontend/app/store/wshclientapi.ts @@ -12,6 +12,11 @@ class RpcApiType { return client.wshRpcCall("activity", data, opts); } + // command "aigetmessages" [call] + AiGetMessagesCommand(client: WshClient, data: AiGetMessagesData, opts?: RpcOpts): Promise { + return client.wshRpcCall("aigetmessages", data, opts); + } + // command "aisendmessage" [call] AiSendMessageCommand(client: WshClient, data: AiMessageData, opts?: RpcOpts): Promise { return client.wshRpcCall("aisendmessage", data, opts); diff --git a/frontend/app/view/waveai/waveai.tsx b/frontend/app/view/waveai/waveai.tsx index 3ed852a78..a632bb7ce 100644 --- a/frontend/app/view/waveai/waveai.tsx +++ b/frontend/app/view/waveai/waveai.tsx @@ -59,6 +59,16 @@ class AiWshClient extends WshClient { } this.model.sendMessage(data.message); } + + handle_aigetmessages(rh: RpcResponseHelper, data: AiGetMessagesData) { + const messages = globalStore.get(this.model.messagesAtom); + const limit = data.limit || 10; + const limitedMessages = messages.slice(-limit).map((msg) => ({ + role: msg.user, + content: msg.text, + })); + rh.sendResponse({ data: limitedMessages }); + } } export class WaveAiModel implements ViewModel { diff --git a/frontend/types/gotypes.d.ts b/frontend/types/gotypes.d.ts index 2570f4b4d..04fb5c2c7 100644 --- a/frontend/types/gotypes.d.ts +++ b/frontend/types/gotypes.d.ts @@ -40,6 +40,22 @@ declare global { conn?: {[key: string]: number}; }; + // wshrpc.AiGetMessagesData + type AiGetMessagesData = { + limit?: number; + }; + + // wshrpc.AiGetMessagesResponse + type AiGetMessagesResponse = { + messages: AiMessage[]; + }; + + // wshrpc.AiMessage + type AiMessage = { + role: string; + content: string; + }; + // wshrpc.AiMessageData type AiMessageData = { message?: string; diff --git a/pkg/wshrpc/wshclient/wshclient.go b/pkg/wshrpc/wshclient/wshclient.go index 243065b9c..4f0ddae2c 100644 --- a/pkg/wshrpc/wshclient/wshclient.go +++ b/pkg/wshrpc/wshclient/wshclient.go @@ -22,6 +22,12 @@ func ActivityCommand(w *wshutil.WshRpc, data wshrpc.ActivityUpdate, opts *wshrpc return err } +// command "aigetmessages", wshserver.AiGetMessagesCommand +func AiGetMessagesCommand(w *wshutil.WshRpc, data wshrpc.AiGetMessagesData, opts *wshrpc.RpcOpts) (wshrpc.AiGetMessagesResponse, error) { + resp, err := sendRpcRequestCallHelper[wshrpc.AiGetMessagesResponse](w, "aigetmessages", data, opts) + return resp, err +} + // command "aisendmessage", wshserver.AiSendMessageCommand func AiSendMessageCommand(w *wshutil.WshRpc, data wshrpc.AiMessageData, opts *wshrpc.RpcOpts) error { _, err := sendRpcRequestCallHelper[any](w, "aisendmessage", data, opts) diff --git a/pkg/wshrpc/wshrpctypes.go b/pkg/wshrpc/wshrpctypes.go index 3d629533c..c5c74ff5d 100644 --- a/pkg/wshrpc/wshrpctypes.go +++ b/pkg/wshrpc/wshrpctypes.go @@ -137,6 +137,7 @@ const ( Command_VDomUrlRequest = "vdomurlrequest" Command_AiSendMessage = "aisendmessage" + Command_AiGetMessages = "aigetmessages" ) type RespOrErrorUnion[T any] struct { @@ -255,6 +256,7 @@ type WshRpcInterface interface { // ai AiSendMessageCommand(ctx context.Context, data AiMessageData) error + AiGetMessagesCommand(ctx context.Context, data AiGetMessagesData) (AiGetMessagesResponse, error) // proc VDomRenderCommand(ctx context.Context, data vdom.VDomFrontendUpdate) chan RespOrErrorUnion[*vdom.VDomBackendUpdate] @@ -681,6 +683,19 @@ type AiMessageData struct { Message string `json:"message,omitempty"` } +type AiMessage struct { + Role string `json:"role"` + Content string `json:"content"` +} + +type AiGetMessagesData struct { + Limit int `json:"limit,omitempty"` // If 0, defaults to 10 +} + +type AiGetMessagesResponse struct { + Messages []AiMessage `json:"messages"` +} + type CommandVarData struct { Key string `json:"key"` Val string `json:"val,omitempty"` From c1e9634d47f5890aab4017723bf848b79cae7493 Mon Sep 17 00:00:00 2001 From: Oqoqqo Halp Date: Sun, 16 Mar 2025 10:26:04 -0700 Subject: [PATCH 2/4] vibes working --- cmd/wsh/cmd/wshcmd-ai.go | 14 +++++++------- frontend/app/store/wshclientapi.ts | 2 +- frontend/types/gotypes.d.ts | 5 ----- pkg/wshrpc/wshclient/wshclient.go | 4 ++-- pkg/wshrpc/wshrpctypes.go | 6 +----- 5 files changed, 11 insertions(+), 20 deletions(-) diff --git a/cmd/wsh/cmd/wshcmd-ai.go b/cmd/wsh/cmd/wshcmd-ai.go index bea6b0238..e2c3377bc 100644 --- a/cmd/wsh/cmd/wshcmd-ai.go +++ b/cmd/wsh/cmd/wshcmd-ai.go @@ -14,6 +14,7 @@ import ( "github.com/wavetermdev/waveterm/pkg/wshrpc" "github.com/wavetermdev/waveterm/pkg/wshrpc/wshclient" "github.com/wavetermdev/waveterm/pkg/wshutil" + "encoding/json" ) var aiCmd = &cobra.Command{ @@ -200,19 +201,18 @@ func aigetRun(cmd *cobra.Command, args []string) (rtnErr error) { Limit: aigetLimit, } - var response wshrpc.AiGetMessagesResponse - response, err = wshclient.AiGetMessagesCommand(RpcClient, messageData, &wshrpc.RpcOpts{ + response, err := wshclient.AiGetMessagesCommand(RpcClient, messageData, &wshrpc.RpcOpts{ Route: route, Timeout: 2000, }) if err != nil { return fmt.Errorf("getting messages: %w", err) } - - // Print messages - for _, msg := range response.Messages { - fmt.Printf("%s: %s\n", msg.Role, msg.Content) + jsonBytes, err := json.Marshal(response) + if err != nil { + return fmt.Errorf("marshalling response: %w", err) } + fmt.Print(string(jsonBytes)) - return nil + return nil } diff --git a/frontend/app/store/wshclientapi.ts b/frontend/app/store/wshclientapi.ts index 1d4c35201..2a9e5bffa 100644 --- a/frontend/app/store/wshclientapi.ts +++ b/frontend/app/store/wshclientapi.ts @@ -13,7 +13,7 @@ class RpcApiType { } // command "aigetmessages" [call] - AiGetMessagesCommand(client: WshClient, data: AiGetMessagesData, opts?: RpcOpts): Promise { + AiGetMessagesCommand(client: WshClient, data: AiGetMessagesData, opts?: RpcOpts): Promise { return client.wshRpcCall("aigetmessages", data, opts); } diff --git a/frontend/types/gotypes.d.ts b/frontend/types/gotypes.d.ts index 04fb5c2c7..59ad4e3fb 100644 --- a/frontend/types/gotypes.d.ts +++ b/frontend/types/gotypes.d.ts @@ -45,11 +45,6 @@ declare global { limit?: number; }; - // wshrpc.AiGetMessagesResponse - type AiGetMessagesResponse = { - messages: AiMessage[]; - }; - // wshrpc.AiMessage type AiMessage = { role: string; diff --git a/pkg/wshrpc/wshclient/wshclient.go b/pkg/wshrpc/wshclient/wshclient.go index 4f0ddae2c..de9b44855 100644 --- a/pkg/wshrpc/wshclient/wshclient.go +++ b/pkg/wshrpc/wshclient/wshclient.go @@ -23,8 +23,8 @@ func ActivityCommand(w *wshutil.WshRpc, data wshrpc.ActivityUpdate, opts *wshrpc } // command "aigetmessages", wshserver.AiGetMessagesCommand -func AiGetMessagesCommand(w *wshutil.WshRpc, data wshrpc.AiGetMessagesData, opts *wshrpc.RpcOpts) (wshrpc.AiGetMessagesResponse, error) { - resp, err := sendRpcRequestCallHelper[wshrpc.AiGetMessagesResponse](w, "aigetmessages", data, opts) +func AiGetMessagesCommand(w *wshutil.WshRpc, data wshrpc.AiGetMessagesData, opts *wshrpc.RpcOpts) ([]wshrpc.AiMessage, error) { + resp, err := sendRpcRequestCallHelper[[]wshrpc.AiMessage](w, "aigetmessages", data, opts) return resp, err } diff --git a/pkg/wshrpc/wshrpctypes.go b/pkg/wshrpc/wshrpctypes.go index c5c74ff5d..569e3ad58 100644 --- a/pkg/wshrpc/wshrpctypes.go +++ b/pkg/wshrpc/wshrpctypes.go @@ -256,7 +256,7 @@ type WshRpcInterface interface { // ai AiSendMessageCommand(ctx context.Context, data AiMessageData) error - AiGetMessagesCommand(ctx context.Context, data AiGetMessagesData) (AiGetMessagesResponse, error) + AiGetMessagesCommand(ctx context.Context, data AiGetMessagesData) ([]AiMessage, error) // proc VDomRenderCommand(ctx context.Context, data vdom.VDomFrontendUpdate) chan RespOrErrorUnion[*vdom.VDomBackendUpdate] @@ -692,10 +692,6 @@ type AiGetMessagesData struct { Limit int `json:"limit,omitempty"` // If 0, defaults to 10 } -type AiGetMessagesResponse struct { - Messages []AiMessage `json:"messages"` -} - type CommandVarData struct { Key string `json:"key"` Val string `json:"val,omitempty"` From 42f140dcc934518b7bc0b51c72990d9fe104c8d8 Mon Sep 17 00:00:00 2001 From: Oqoqqo Halp Date: Sun, 16 Mar 2025 10:38:26 -0700 Subject: [PATCH 3/4] ident is weird --- cmd/wsh/cmd/wshcmd-ai.go | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/cmd/wsh/cmd/wshcmd-ai.go b/cmd/wsh/cmd/wshcmd-ai.go index e2c3377bc..8e092bfed 100644 --- a/cmd/wsh/cmd/wshcmd-ai.go +++ b/cmd/wsh/cmd/wshcmd-ai.go @@ -208,11 +208,11 @@ func aigetRun(cmd *cobra.Command, args []string) (rtnErr error) { if err != nil { return fmt.Errorf("getting messages: %w", err) } - jsonBytes, err := json.Marshal(response) - if err != nil { - return fmt.Errorf("marshalling response: %w", err) - } - fmt.Print(string(jsonBytes)) + jsonBytes, err := json.Marshal(response) + if err != nil { + return fmt.Errorf("marshalling response: %w", err) + } + fmt.Print(string(jsonBytes)) return nil } From 4c23d3b603260e93d2f3296d57baa9962eefcde8 Mon Sep 17 00:00:00 2001 From: Oqoqqo Halp Date: Sun, 16 Mar 2025 10:38:59 -0700 Subject: [PATCH 4/4] ident is weird --- cmd/wsh/cmd/wshcmd-ai.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/wsh/cmd/wshcmd-ai.go b/cmd/wsh/cmd/wshcmd-ai.go index 8e092bfed..2972e1eaa 100644 --- a/cmd/wsh/cmd/wshcmd-ai.go +++ b/cmd/wsh/cmd/wshcmd-ai.go @@ -214,5 +214,5 @@ func aigetRun(cmd *cobra.Command, args []string) (rtnErr error) { } fmt.Print(string(jsonBytes)) - return nil + return nil }