@@ -7,11 +7,13 @@ import (
77 "context"
88 "fmt"
99 "strings"
10+ "time"
1011
1112 "github.com/google/uuid"
1213 "github.com/wavetermdev/waveterm/pkg/aiusechat/uctypes"
1314 "github.com/wavetermdev/waveterm/pkg/blockcontroller"
1415 "github.com/wavetermdev/waveterm/pkg/waveobj"
16+ "github.com/wavetermdev/waveterm/pkg/wcore"
1517 "github.com/wavetermdev/waveterm/pkg/wstore"
1618)
1719
@@ -99,44 +101,42 @@ func MakeBlockShortDesc(block *waveobj.Block) string {
99101 }
100102}
101103
102- func AddToolsForTab (ctx context.Context , tabid string , widgetAccess bool , chatOpts * uctypes.WaveChatOpts ) error {
104+ func GenerateTabStateAndTools (ctx context.Context , tabid string , widgetAccess bool ) ( string , [] uctypes.ToolDefinition , error ) {
103105 if tabid == "" {
104- return nil
105- }
106- if ! widgetAccess {
107- chatOpts .SystemPrompt = append (chatOpts .SystemPrompt , "The user has chosen not to share widget context with you." )
108- return nil
109- }
110-
111- if _ , err := uuid .Parse (tabid ); err != nil {
112- return fmt .Errorf ("tabid must be a valid UUID" )
113- }
114-
115- tabObj , err := wstore .DBMustGet [* waveobj.Tab ](ctx , tabid )
116- if err != nil {
117- return fmt .Errorf ("error getting tab: %v" , err )
106+ return "" , nil , nil
118107 }
119-
120108 var blocks []* waveobj.Block
121- for _ , blockId := range tabObj .BlockIds {
122- block , err := wstore .DBGet [* waveobj.Block ](ctx , blockId )
123- if err != nil {
124- continue
109+ if widgetAccess {
110+ if _ , err := uuid .Parse (tabid ); err != nil {
111+ return "" , nil , fmt .Errorf ("tabid must be a valid UUID" )
125112 }
126- blocks = append (blocks , block )
127- }
128113
129- systemPrompt := generateTabSystemPrompt (blocks )
130- chatOpts .SystemPrompt = append (chatOpts .SystemPrompt , systemPrompt )
114+ tabObj , err := wstore .DBMustGet [* waveobj.Tab ](ctx , tabid )
115+ if err != nil {
116+ return "" , nil , fmt .Errorf ("error getting tab: %v" , err )
117+ }
131118
132- return nil
119+ for _ , blockId := range tabObj .BlockIds {
120+ block , err := wstore .DBGet [* waveobj.Block ](ctx , blockId )
121+ if err != nil {
122+ continue
123+ }
124+ blocks = append (blocks , block )
125+ }
126+ }
127+ tabState := GenerateCurrentTabStatePrompt (blocks , widgetAccess )
128+ var tools []uctypes.ToolDefinition
129+ for _ , block := range blocks {
130+ blockTools := generateToolsForBlock (block )
131+ tools = append (tools , blockTools ... )
132+ }
133+ return tabState , tools , nil
133134}
134135
135- func generateTabSystemPrompt (blocks []* waveobj.Block ) string {
136- if len ( blocks ) == 0 {
137- return "This tab is empty with no widgets currently open."
136+ func GenerateCurrentTabStatePrompt (blocks []* waveobj.Block , widgetAccess bool ) string {
137+ if ! widgetAccess {
138+ return `<current_tab_state>The user has chosen not to share widget context with you</current_tab_state>`
138139 }
139-
140140 var widgetDescriptions []string
141141 for _ , block := range blocks {
142142 desc := MakeBlockShortDesc (block )
@@ -148,21 +148,86 @@ func generateTabSystemPrompt(blocks []*waveobj.Block) string {
148148 widgetDescriptions = append (widgetDescriptions , fullDesc )
149149 }
150150
151- totalWidgets := len (widgetDescriptions )
152151 var prompt strings.Builder
153- if totalWidgets == 1 {
154- prompt .WriteString ("In this tab there is 1 widget open (the widgetid appears in parentheses before the description):\n " )
152+ prompt .WriteString ("<current_tab_state>\n " )
153+ if len (widgetDescriptions ) == 0 {
154+ prompt .WriteString ("No widgets open\n " )
155155 } else {
156- prompt .WriteString (fmt .Sprintf ("In this tab there are %d widgets open (the widgetid appears in parentheses before the description):\n " , totalWidgets ))
156+ for _ , desc := range widgetDescriptions {
157+ prompt .WriteString ("* " )
158+ prompt .WriteString (desc )
159+ prompt .WriteString ("\n " )
160+ }
157161 }
162+ prompt .WriteString ("</current_tab_state>" )
163+ return prompt .String ()
164+ }
158165
159- for _ , desc := range widgetDescriptions {
160- prompt .WriteString ("* " )
161- prompt .WriteString (desc )
162- prompt .WriteString ("\n " )
166+ func generateToolsForBlock (block * waveobj.Block ) []uctypes.ToolDefinition {
167+ if block .Meta == nil {
168+ return nil
163169 }
164170
165- return prompt .String ()
171+ viewType , ok := block .Meta ["view" ].(string )
172+ if ! ok {
173+ return nil
174+ }
175+
176+ var tools []uctypes.ToolDefinition
177+ switch viewType {
178+ case "web" :
179+ tools = append (tools , GetWebNavigateToolDefinition (block ))
180+ }
181+
182+ return tools
183+ }
184+
185+ func GetWebNavigateToolDefinition (block * waveobj.Block ) uctypes.ToolDefinition {
186+ blockIdPrefix := block .OID [:8 ]
187+ toolName := fmt .Sprintf ("web_navigate_%s" , blockIdPrefix )
188+
189+ return uctypes.ToolDefinition {
190+ Name : toolName ,
191+ DisplayName : fmt .Sprintf ("Navigate Web Block %s" , blockIdPrefix ),
192+ Description : fmt .Sprintf ("Navigate the web browser widget %s to a new URL" , blockIdPrefix ),
193+ InputSchema : map [string ]any {
194+ "type" : "object" ,
195+ "properties" : map [string ]any {
196+ "url" : map [string ]any {
197+ "type" : "string" ,
198+ "description" : "URL to navigate to" ,
199+ },
200+ },
201+ "required" : []string {"url" },
202+ },
203+ ToolAnyCallback : func (input any ) (any , error ) {
204+ inputMap , ok := input .(map [string ]any )
205+ if ! ok {
206+ return nil , fmt .Errorf ("invalid input format" )
207+ }
208+
209+ url , ok := inputMap ["url" ].(string )
210+ if ! ok {
211+ return nil , fmt .Errorf ("missing or invalid url parameter" )
212+ }
213+
214+ ctx , cancelFn := context .WithTimeout (context .Background (), 5 * time .Second )
215+ defer cancelFn ()
216+
217+ blockORef := waveobj .MakeORef (waveobj .OType_Block , block .OID )
218+ meta := map [string ]any {
219+ "url" : url ,
220+ }
221+
222+ err := wstore .UpdateObjectMeta (ctx , blockORef , meta , false )
223+ if err != nil {
224+ return nil , fmt .Errorf ("failed to update web block URL: %w" , err )
225+ }
226+
227+ wcore .SendWaveObjUpdate (blockORef )
228+ return true , nil
229+ },
230+ }
166231}
167232
168233func GetAdderToolDefinition () uctypes.ToolDefinition {
0 commit comments