Skip to content

Commit 6632365

Browse files
committed
3 tsunami tools, fix tsunami widget headers
1 parent 8a7a225 commit 6632365

2 files changed

Lines changed: 123 additions & 42 deletions

File tree

frontend/app/view/tsunami/tsunami.tsx

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ class TsunamiViewModel extends WebViewModel {
2020
shellProcFullStatus: jotai.PrimitiveAtom<BlockControllerRuntimeStatus>;
2121
shellProcStatusUnsubFn: () => void;
2222
isRestarting: jotai.PrimitiveAtom<boolean>;
23+
viewName: jotai.PrimitiveAtom<string>;
2324

2425
constructor(blockId: string, nodeModel: BlockNodeModel) {
2526
super(blockId, nodeModel);
@@ -162,6 +163,11 @@ const TsunamiView = memo((props: ViewComponentProps<TsunamiViewModel>) => {
162163
const meta = JSON.parse(jsonStr);
163164
if (meta.title || meta.shortdesc) {
164165
model.setAppMeta(meta);
166+
167+
if (meta.title) {
168+
const truncatedTitle = meta.title.length > 77 ? meta.title.substring(0, 77) + "..." : meta.title;
169+
globalStore.set(model.viewName, truncatedTitle);
170+
}
165171
}
166172
} catch (error) {
167173
console.error('Failed to parse TSUNAMI_META message:', error);

pkg/aiusechat/tools.go

Lines changed: 117 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -183,13 +183,16 @@ func generateToolsForBlock(block *waveobj.Block) []uctypes.ToolDefinition {
183183
// Check if tsunami widget is running
184184
status := blockcontroller.GetBlockControllerRuntimeStatus(block.OID)
185185
if status != nil && status.ShellProcStatus == blockcontroller.Status_Running && status.TsunamiPort > 0 {
186-
// Check if schemas are available
187186
blockORef := waveobj.MakeORef(waveobj.OType_Block, block.OID)
188187
rtInfo := wstore.GetRTInfo(blockORef)
189-
if rtInfo != nil && rtInfo.TsunamiSchemas != nil {
190-
if tool := GetTsunamiGetDataToolDefinition(block, rtInfo, status); tool != nil {
191-
tools = append(tools, *tool)
192-
}
188+
if tool := GetTsunamiGetDataToolDefinition(block, rtInfo, status); tool != nil {
189+
tools = append(tools, *tool)
190+
}
191+
if tool := GetTsunamiGetConfigToolDefinition(block, rtInfo, status); tool != nil {
192+
tools = append(tools, *tool)
193+
}
194+
if tool := GetTsunamiSetConfigToolDefinition(block, rtInfo, status); tool != nil {
195+
tools = append(tools, *tool)
193196
}
194197
}
195198
}
@@ -245,59 +248,131 @@ func GetWebNavigateToolDefinition(block *waveobj.Block) uctypes.ToolDefinition {
245248
}
246249
}
247250

251+
func makeTsunamiGetCallback(status *blockcontroller.BlockControllerRuntimeStatus, apiPath string) func(any) (any, error) {
252+
return func(input any) (any, error) {
253+
if status.TsunamiPort == 0 {
254+
return nil, fmt.Errorf("tsunami port not available")
255+
}
256+
257+
url := fmt.Sprintf("http://localhost:%d%s", status.TsunamiPort, apiPath)
258+
259+
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
260+
defer cancel()
261+
262+
req, err := http.NewRequestWithContext(ctx, "GET", url, nil)
263+
if err != nil {
264+
return nil, fmt.Errorf("failed to create request: %w", err)
265+
}
266+
267+
resp, err := http.DefaultClient.Do(req)
268+
if err != nil {
269+
return nil, fmt.Errorf("failed to make request to tsunami: %w", err)
270+
}
271+
defer resp.Body.Close()
272+
273+
if resp.StatusCode != http.StatusOK {
274+
return nil, fmt.Errorf("tsunami returned status %d", resp.StatusCode)
275+
}
276+
277+
var result any
278+
if err := json.NewDecoder(resp.Body).Decode(&result); err != nil {
279+
return nil, fmt.Errorf("failed to decode tsunami response: %w", err)
280+
}
281+
282+
return result, nil
283+
}
284+
}
285+
286+
func makeTsunamiPostCallback(status *blockcontroller.BlockControllerRuntimeStatus, apiPath string) func(any) (any, error) {
287+
return func(input any) (any, error) {
288+
if status.TsunamiPort == 0 {
289+
return nil, fmt.Errorf("tsunami port not available")
290+
}
291+
292+
url := fmt.Sprintf("http://localhost:%d%s", status.TsunamiPort, apiPath)
293+
294+
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
295+
defer cancel()
296+
297+
var reqBody []byte
298+
var err error
299+
if input != nil {
300+
reqBody, err = json.Marshal(input)
301+
if err != nil {
302+
return nil, fmt.Errorf("failed to marshal input: %w", err)
303+
}
304+
}
305+
306+
req, err := http.NewRequestWithContext(ctx, "POST", url, strings.NewReader(string(reqBody)))
307+
if err != nil {
308+
return nil, fmt.Errorf("failed to create request: %w", err)
309+
}
310+
req.Header.Set("Content-Type", "application/json")
311+
312+
resp, err := http.DefaultClient.Do(req)
313+
if err != nil {
314+
return nil, fmt.Errorf("failed to make request to tsunami: %w", err)
315+
}
316+
defer resp.Body.Close()
317+
318+
if resp.StatusCode != http.StatusOK {
319+
return nil, fmt.Errorf("tsunami returned status %d", resp.StatusCode)
320+
}
321+
322+
return true, nil
323+
}
324+
}
325+
248326
func GetTsunamiGetDataToolDefinition(block *waveobj.Block, rtInfo *waveobj.ObjRTInfo, status *blockcontroller.BlockControllerRuntimeStatus) *uctypes.ToolDefinition {
249327
blockIdPrefix := block.OID[:8]
250328
toolName := fmt.Sprintf("tsunami_getdata_%s", blockIdPrefix)
251329

330+
return &uctypes.ToolDefinition{
331+
Name: toolName,
332+
InputSchema: map[string]any{
333+
"type": "object",
334+
"properties": map[string]any{},
335+
},
336+
ToolAnyCallback: makeTsunamiGetCallback(status, "/api/data"),
337+
}
338+
}
339+
340+
func GetTsunamiGetConfigToolDefinition(block *waveobj.Block, rtInfo *waveobj.ObjRTInfo, status *blockcontroller.BlockControllerRuntimeStatus) *uctypes.ToolDefinition {
341+
blockIdPrefix := block.OID[:8]
342+
toolName := fmt.Sprintf("tsunami_getconfig_%s", blockIdPrefix)
343+
344+
return &uctypes.ToolDefinition{
345+
Name: toolName,
346+
InputSchema: map[string]any{
347+
"type": "object",
348+
"properties": map[string]any{},
349+
},
350+
ToolAnyCallback: makeTsunamiGetCallback(status, "/api/config"),
351+
}
352+
}
353+
354+
func GetTsunamiSetConfigToolDefinition(block *waveobj.Block, rtInfo *waveobj.ObjRTInfo, status *blockcontroller.BlockControllerRuntimeStatus) *uctypes.ToolDefinition {
355+
blockIdPrefix := block.OID[:8]
356+
toolName := fmt.Sprintf("tsunami_setconfig_%s", blockIdPrefix)
357+
252358
var inputSchema map[string]any
253359
if rtInfo != nil && rtInfo.TsunamiSchemas != nil {
254360
if schemasMap, ok := rtInfo.TsunamiSchemas.(map[string]any); ok {
255-
if dataSchema, exists := schemasMap["data"]; exists {
256-
inputSchema = dataSchema.(map[string]any)
361+
if configSchema, exists := schemasMap["config"]; exists {
362+
inputSchema = configSchema.(map[string]any)
257363
}
258364
}
259365
}
260366

261-
// Return nil if no data schema found
367+
// Return nil if no config schema found
262368
if inputSchema == nil {
263369
return nil
264370
}
265371

266372
return &uctypes.ToolDefinition{
267-
Name: toolName,
268-
InputSchema: inputSchema,
269-
ToolAnyCallback: func(input any) (any, error) {
270-
if status.TsunamiPort == 0 {
271-
return nil, fmt.Errorf("tsunami port not available")
272-
}
273-
274-
url := fmt.Sprintf("http://localhost:%d/api/data", status.TsunamiPort)
275-
276-
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
277-
defer cancel()
278-
279-
req, err := http.NewRequestWithContext(ctx, "GET", url, nil)
280-
if err != nil {
281-
return nil, fmt.Errorf("failed to create request: %w", err)
282-
}
283-
284-
resp, err := http.DefaultClient.Do(req)
285-
if err != nil {
286-
return nil, fmt.Errorf("failed to make request to tsunami: %w", err)
287-
}
288-
defer resp.Body.Close()
289-
290-
if resp.StatusCode != http.StatusOK {
291-
return nil, fmt.Errorf("tsunami returned status %d", resp.StatusCode)
292-
}
293-
294-
var result any
295-
if err := json.NewDecoder(resp.Body).Decode(&result); err != nil {
296-
return nil, fmt.Errorf("failed to decode tsunami response: %w", err)
297-
}
298-
299-
return result, nil
300-
},
373+
Name: toolName,
374+
InputSchema: inputSchema,
375+
ToolAnyCallback: makeTsunamiPostCallback(status, "/api/config"),
301376
}
302377
}
303378

0 commit comments

Comments
 (0)